mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Moved transpaerency to the new status page, and separated each section into a tab.
This commit is contained in:
parent
d425b42694
commit
b967bc07d6
@ -8,7 +8,7 @@ using System.Net;
|
||||
using System.Net.Mail;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Teknik.Areas.Transparency.Models;
|
||||
using Teknik.Areas.Status.Models;
|
||||
using Teknik.Areas.Upload.Models;
|
||||
using Teknik.Areas.Users.Models;
|
||||
using Teknik.Areas.Users.Utility;
|
||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Teknik.Areas.Status.Models;
|
||||
using Teknik.Areas.Status.ViewModels;
|
||||
using Teknik.Attributes;
|
||||
using Teknik.Controllers;
|
||||
@ -24,12 +25,13 @@ namespace Teknik.Areas.Status.Controllers
|
||||
[AllowAnonymous]
|
||||
public ActionResult Index()
|
||||
{
|
||||
ViewBag.Title = "Status Information - " + Config.Title;
|
||||
ViewBag.Title = "System Status - " + Config.Title;
|
||||
ViewBag.Description = "Current status information for the server and resources.";
|
||||
|
||||
StatusViewModel model = new StatusViewModel();
|
||||
|
||||
// Load initial status info
|
||||
#region Statistics
|
||||
Upload.Models.Upload upload = db.Uploads.OrderByDescending(u => u.UploadId).FirstOrDefault();
|
||||
model.UploadCount = (upload != null) ? upload.UploadId : 0;
|
||||
model.UploadSize = (upload != null) ? db.Uploads.Sum(u => (long)u.ContentLength) : 0;
|
||||
@ -45,6 +47,116 @@ namespace Teknik.Areas.Status.Controllers
|
||||
|
||||
Vault.Models.Vault vault = db.Vaults.OrderByDescending(v => v.VaultId).FirstOrDefault();
|
||||
model.VaultCount = (url != null) ? vault.VaultId : 0;
|
||||
#endregion
|
||||
|
||||
// Get Transaction Inforomation
|
||||
#region Transactions
|
||||
DateTime curTime = DateTime.Now;
|
||||
|
||||
var billSums = db.Transactions.OfType<Bill>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year}).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList();
|
||||
foreach (var sum in billSums)
|
||||
{
|
||||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency);
|
||||
decimal realValue = sum.total * exchangeRate;
|
||||
model.Transactions.TotalBills += realValue;
|
||||
model.Transactions.TotalNet += realValue;
|
||||
if (curTime.Month == sum.month && curTime.Year == sum.year)
|
||||
{
|
||||
model.Transactions.CurrentMonthBills += Math.Abs(realValue);
|
||||
}
|
||||
}
|
||||
|
||||
var oneSums = db.Transactions.OfType<OneTime>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year }).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList();
|
||||
foreach (var sum in oneSums)
|
||||
{
|
||||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency);
|
||||
decimal realValue = sum.total * exchangeRate;
|
||||
model.Transactions.TotalOneTimes += realValue;
|
||||
model.Transactions.TotalNet += realValue;
|
||||
if (curTime.Month == sum.month && curTime.Year == sum.year)
|
||||
{
|
||||
model.Transactions.CurrentMonthBills += Math.Abs(realValue);
|
||||
}
|
||||
}
|
||||
|
||||
var donationSums = db.Transactions.OfType<Donation>().GroupBy(b => new { b.Currency, b.DateSent.Month, b.DateSent.Year }).Select(b => new { month = b.Key.Month, year = b.Key.Year, currency = b.Key.Currency, total = b.Sum(c => c.Amount) }).ToList();
|
||||
foreach (var sum in donationSums)
|
||||
{
|
||||
decimal exchangeRate = CurrencyHelper.GetExchangeRate(sum.currency);
|
||||
decimal realValue = sum.total * exchangeRate;
|
||||
model.Transactions.TotalDonations += realValue;
|
||||
model.Transactions.TotalNet += realValue;
|
||||
if (curTime.Month == sum.month && curTime.Year == sum.year)
|
||||
{
|
||||
model.Transactions.CurrentMonthIncome += Math.Abs(realValue);
|
||||
}
|
||||
}
|
||||
|
||||
List<Bill> bills = db.Transactions.OfType<Bill>().OrderByDescending(b => b.DateSent).ToList();
|
||||
if (bills != null)
|
||||
{
|
||||
foreach (Bill bill in bills)
|
||||
{
|
||||
BillViewModel billModel = new BillViewModel();
|
||||
billModel.Amount = bill.Amount;
|
||||
billModel.Currency = bill.Currency;
|
||||
billModel.Reason = bill.Reason;
|
||||
billModel.DateSent = bill.DateSent;
|
||||
billModel.Recipient = bill.Recipient;
|
||||
model.Transactions.Bills.Add(billModel);
|
||||
}
|
||||
}
|
||||
|
||||
List<OneTime> oneTimes = db.Transactions.OfType<OneTime>().OrderByDescending(b => b.DateSent).ToList();
|
||||
if (oneTimes != null)
|
||||
{
|
||||
foreach (OneTime oneTime in oneTimes)
|
||||
{
|
||||
OneTimeViewModel oneTimeModel = new OneTimeViewModel();
|
||||
oneTimeModel.Amount = oneTime.Amount;
|
||||
oneTimeModel.Currency = oneTime.Currency;
|
||||
oneTimeModel.Reason = oneTime.Reason;
|
||||
oneTimeModel.DateSent = oneTime.DateSent;
|
||||
oneTimeModel.Recipient = oneTime.Recipient;
|
||||
model.Transactions.OneTimes.Add(oneTimeModel);
|
||||
}
|
||||
}
|
||||
|
||||
List<Donation> donations = db.Transactions.OfType<Donation>().OrderByDescending(b => b.DateSent).ToList();
|
||||
if (donations != null)
|
||||
{
|
||||
foreach (Donation donation in donations)
|
||||
{
|
||||
DonationViewModel donationModel = new DonationViewModel();
|
||||
donationModel.Amount = donation.Amount;
|
||||
donationModel.Currency = donation.Currency;
|
||||
donationModel.Reason = donation.Reason;
|
||||
donationModel.DateSent = donation.DateSent;
|
||||
donationModel.Sender = donation.Sender;
|
||||
model.Transactions.Donations.Add(donationModel);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
// Takedown information
|
||||
#region Takedowns
|
||||
List<Takedown> takedowns = db.Takedowns.OrderByDescending(b => b.DateRequested).ToList();
|
||||
if (takedowns != null)
|
||||
{
|
||||
foreach (Takedown takedown in takedowns)
|
||||
{
|
||||
TakedownViewModel takedownModel = new TakedownViewModel();
|
||||
takedownModel.Requester = takedown.Requester;
|
||||
takedownModel.RequesterContact = takedown.RequesterContact;
|
||||
takedownModel.Reason = takedown.Reason;
|
||||
takedownModel.ActionTaken = takedown.ActionTaken;
|
||||
takedownModel.DateRequested = takedown.DateRequested;
|
||||
takedownModel.DateActionTaken = takedown.DateActionTaken;
|
||||
|
||||
model.Takedowns.Add(takedownModel);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Models
|
||||
namespace Teknik.Areas.Status.Models
|
||||
{
|
||||
public class Bill : Transaction
|
||||
{
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Models
|
||||
namespace Teknik.Areas.Status.Models
|
||||
{
|
||||
public class Donation : Transaction
|
||||
{
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Models
|
||||
namespace Teknik.Areas.Status.Models
|
||||
{
|
||||
public class OneTime : Transaction
|
||||
{
|
@ -4,7 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Models
|
||||
namespace Teknik.Areas.Status.Models
|
||||
{
|
||||
public class Takedown
|
||||
{
|
@ -3,16 +3,17 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Models
|
||||
namespace Teknik.Areas.Status.Models
|
||||
{
|
||||
public class Transaction
|
||||
{
|
||||
public int TransactionId { get; set; }
|
||||
|
||||
public double Amount { get; set; }
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
public string Currency { get; set; }
|
||||
public CurrencyType Currency { get; set; }
|
||||
|
||||
public string Reason { get; set; }
|
||||
|
@ -3,6 +3,11 @@ var memUsageChart;
|
||||
var networkUsageChart;
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#bills-section').collapse('hide');
|
||||
$('#oneTime-section').collapse('hide');
|
||||
$('#donations-section').collapse('hide');
|
||||
$('#takedowns-section').collapse('hide');
|
||||
|
||||
/* ----------------------------------------
|
||||
CPU Usage
|
||||
-----------------------------------------*/
|
||||
@ -22,11 +27,13 @@ $(document).ready(function () {
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Percentage %'
|
||||
text: 'Percentage'
|
||||
},
|
||||
max: 100,
|
||||
min: 0,
|
||||
format: '{value}',
|
||||
labels: {
|
||||
format: '{value}%'
|
||||
},
|
||||
plotLines: [{
|
||||
value: 0,
|
||||
width: 1,
|
||||
@ -38,6 +45,9 @@ $(document).ready(function () {
|
||||
crosshairs: true,
|
||||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y:.2f}%</b><br/>'
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Total',
|
||||
@ -98,6 +108,9 @@ $(document).ready(function () {
|
||||
return '<span style="color:' + this.color + '">\u25CF</span> ' + this.series.name + ': <b>' + yVal + '</b><br/>';
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Total',
|
||||
@ -156,6 +169,9 @@ $(document).ready(function () {
|
||||
return '<span style="color:' + this.color + '">\u25CF</span> ' + this.series.name + ': <b>' + yVal + '</b><br/>';
|
||||
}
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'Sent',
|
||||
@ -173,7 +189,9 @@ $(document).ready(function () {
|
||||
-----------------------------------------*/
|
||||
visitChart = new Highcharts.chart({
|
||||
chart: {
|
||||
renderTo: 'visitor-chart'
|
||||
renderTo: 'visitor-chart',
|
||||
type: 'line',
|
||||
marginRight: 10
|
||||
},
|
||||
title: {
|
||||
text: 'Daily Visitors'
|
||||
@ -199,6 +217,9 @@ $(document).ready(function () {
|
||||
headerFormat: '<span style="font-size: 10px">{point.key:%B %e, %Y}</span><br/>',
|
||||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>'
|
||||
},
|
||||
credits: {
|
||||
enabled: false
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'All Visitors',
|
||||
@ -260,8 +281,9 @@ $(document).ready(function () {
|
||||
url: getVisitorDataURL,
|
||||
success: function (response) {
|
||||
if (response.result) {
|
||||
visitChart.series[0].setData(response.result.totalVisitors);
|
||||
visitChart.series[1].setData(response.result.uniqueVisitors);
|
||||
visitChart.series[0].setData(response.result.totalVisitors, false);
|
||||
visitChart.series[1].setData(response.result.uniqueVisitors, false);
|
||||
visitChart.redraw();
|
||||
}
|
||||
else {
|
||||
var err = response;
|
||||
@ -274,4 +296,9 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Resize the chart when viewing the tab (initial width is wrong due to chart being hidden)
|
||||
$('a[href="#site-stats"]').on('shown.bs.tab', function (e) {
|
||||
visitChart.setSize($('#visitor-chart').width(), $('#visitor-chart').height());
|
||||
})
|
||||
});
|
13
Teknik/Areas/Status/ViewModels/BillViewModel.cs
Normal file
13
Teknik/Areas/Status/ViewModels/BillViewModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class BillViewModel : TransactionViewModel
|
||||
{
|
||||
public string Recipient { get; set; }
|
||||
}
|
||||
}
|
13
Teknik/Areas/Status/ViewModels/DonationViewModel.cs
Normal file
13
Teknik/Areas/Status/ViewModels/DonationViewModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class DonationViewModel : TransactionViewModel
|
||||
{
|
||||
public string Sender { get; set; }
|
||||
}
|
||||
}
|
13
Teknik/Areas/Status/ViewModels/OneTimeViewModel.cs
Normal file
13
Teknik/Areas/Status/ViewModels/OneTimeViewModel.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class OneTimeViewModel : TransactionViewModel
|
||||
{
|
||||
public string Recipient { get; set; }
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.Areas.Status.Models;
|
||||
using Teknik.Models;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
@ -21,6 +22,10 @@ namespace Teknik.Areas.Status.ViewModels
|
||||
|
||||
public int VaultCount { get; set; }
|
||||
|
||||
public TransactionsViewModel Transactions { get; set; }
|
||||
|
||||
public List<TakedownViewModel> Takedowns { get; set; }
|
||||
|
||||
public StatusViewModel()
|
||||
{
|
||||
UploadCount = 0;
|
||||
@ -29,6 +34,8 @@ namespace Teknik.Areas.Status.ViewModels
|
||||
UserCount = 0;
|
||||
ShortenedUrlCount = 0;
|
||||
VaultCount = 0;
|
||||
Transactions = new TransactionsViewModel();
|
||||
Takedowns = new List<TakedownViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
25
Teknik/Areas/Status/ViewModels/TakedownViewModel.cs
Normal file
25
Teknik/Areas/Status/ViewModels/TakedownViewModel.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class TakedownViewModel : ViewModelBase
|
||||
{
|
||||
public string Requester { get; set; }
|
||||
|
||||
public string RequesterContact { get; set; }
|
||||
|
||||
public string Reason { get; set; }
|
||||
|
||||
public string ActionTaken { get; set; }
|
||||
|
||||
public DateTime DateRequested { get; set; }
|
||||
|
||||
public DateTime DateActionTaken { get; set; }
|
||||
|
||||
public virtual ICollection<Upload.Models.Upload> Attachments { get; set; }
|
||||
}
|
||||
}
|
21
Teknik/Areas/Status/ViewModels/TransactionViewModel.cs
Normal file
21
Teknik/Areas/Status/ViewModels/TransactionViewModel.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.Areas.Status.Models;
|
||||
using Teknik.Utilities;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class TransactionViewModel : ViewModelBase
|
||||
{
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
public CurrencyType Currency { get; set; }
|
||||
|
||||
public string Reason { get; set; }
|
||||
|
||||
public DateTime DateSent { get; set; }
|
||||
}
|
||||
}
|
40
Teknik/Areas/Status/ViewModels/TransactionsViewModel.cs
Normal file
40
Teknik/Areas/Status/ViewModels/TransactionsViewModel.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Status.ViewModels
|
||||
{
|
||||
public class TransactionsViewModel : ViewModelBase
|
||||
{
|
||||
public decimal CurrentMonthBills { get; set; }
|
||||
|
||||
public decimal CurrentMonthIncome { get; set; }
|
||||
|
||||
public decimal TotalBills { get; set; }
|
||||
|
||||
public decimal TotalOneTimes { get; set; }
|
||||
|
||||
public decimal TotalDonations { get; set; }
|
||||
|
||||
public decimal TotalNet { get; set; }
|
||||
|
||||
public List<BillViewModel> Bills { get; set; }
|
||||
|
||||
public List<OneTimeViewModel> OneTimes { get; set; }
|
||||
|
||||
public List<DonationViewModel> Donations { get; set; }
|
||||
|
||||
public TransactionsViewModel()
|
||||
{
|
||||
TotalBills = 0;
|
||||
TotalOneTimes = 0;
|
||||
TotalDonations = 0;
|
||||
TotalNet = 0;
|
||||
Bills = new List<BillViewModel>();
|
||||
OneTimes = new List<OneTimeViewModel>();
|
||||
Donations = new List<DonationViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
35
Teknik/Areas/Status/Views/Status/Bills.cshtml
Normal file
35
Teknik/Areas/Status/Views/Status/Bills.cshtml
Normal file
@ -0,0 +1,35 @@
|
||||
@model List<Teknik.Areas.Status.ViewModels.BillViewModel>
|
||||
|
||||
@using Teknik.Areas.Status.ViewModels
|
||||
|
||||
@if (Model != null && Model.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3>Bills</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#bills-section">View Bills</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="bills-section" class="collapse in">
|
||||
<table class="table table-condensed table-bordered table-hover">
|
||||
<tr>
|
||||
<th><strong>Date</strong></th>
|
||||
<th><strong>Amount</strong></th>
|
||||
<th><strong>Description</strong></th>
|
||||
</tr>
|
||||
@foreach (BillViewModel bill in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@bill.DateSent.ToString("MMMM dd, yyyy")</td>
|
||||
<td>@bill.Amount <var>@bill.Currency.ToString()</var></td>
|
||||
<td>@bill.Reason</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
37
Teknik/Areas/Status/Views/Status/Donations.cshtml
Normal file
37
Teknik/Areas/Status/Views/Status/Donations.cshtml
Normal file
@ -0,0 +1,37 @@
|
||||
@model List<Teknik.Areas.Status.ViewModels.DonationViewModel>
|
||||
|
||||
@using Teknik.Areas.Status.ViewModels
|
||||
|
||||
@if (Model != null && Model.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3>Donations</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#donations-section">View Donations</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="donations-section" class="collapse in">
|
||||
<table class="table table-condensed table-bordered table-hover">
|
||||
<tr>
|
||||
<th><strong>Date</strong></th>
|
||||
<th><strong>Amount</strong></th>
|
||||
<th><strong>Donor</strong></th>
|
||||
<th><strong>Reason for Donation</strong></th>
|
||||
</tr>
|
||||
@foreach (DonationViewModel donation in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@donation.DateSent.ToString("MMMM dd, yyyy")</td>
|
||||
<td>@donation.Amount <var>@donation.Currency.ToString()</var></td>
|
||||
<td>@donation.Sender</td>
|
||||
<td>@donation.Reason</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
@model Teknik.Areas.Status.ViewModels.StatusViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
@using Newtonsoft.Json
|
||||
@using Teknik.Areas.Status.Models
|
||||
|
||||
@Scripts.Render("~/bundles/signalr")
|
||||
@Scripts.Render("~/signalr/hubs")
|
||||
@ -20,9 +20,16 @@
|
||||
<div class="container">
|
||||
@if (Model.Config.StatusConfig.Enabled)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<h2 class="text-center"><b>Realtime Usage</b></h2>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#realtime-stats" role="tab" data-toggle="tab">Realtime Server Usage</a></li>
|
||||
<li role="presentation"><a href="#site-stats" role="tab" data-toggle="tab">Site Statistics</a></li>
|
||||
<li role="presentation"><a href="#transactions" role="tab" data-toggle="tab">Transactions</a></li>
|
||||
<li role="presentation"><a href="#takedowns" role="tab" data-toggle="tab">Takedowns</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="realtime-stats">
|
||||
<h2 class="text-center"><b>Realtime Server Usage</b></h2>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
@ -40,11 +47,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<br />
|
||||
<h2 class="text-center"><b>Statistics</b></h2>
|
||||
<div role="tabpanel" class="tab-pane" id="site-stats">
|
||||
<h2 class="text-center"><b>Site Statistics</b></h2>
|
||||
<hr>
|
||||
@if (Model.Config.PiwikConfig.Enabled)
|
||||
{
|
||||
@ -53,7 +57,6 @@
|
||||
<div id="visitor-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-center">
|
||||
@ -80,6 +83,13 @@
|
||||
<p>Number of Users: @Model.UserCount</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="transactions">
|
||||
@Html.Partial("~/Areas/Status/Views/Status/Transactions.cshtml", Model.Transactions)
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="takedowns">
|
||||
@Html.Partial("~/Areas/Status/Views/Status/Takedowns.cshtml", Model.Takedowns)
|
||||
</div>
|
||||
</div>
|
||||
}
|
35
Teknik/Areas/Status/Views/Status/OneTimes.cshtml
Normal file
35
Teknik/Areas/Status/Views/Status/OneTimes.cshtml
Normal file
@ -0,0 +1,35 @@
|
||||
@model List<Teknik.Areas.Status.ViewModels.OneTimeViewModel>
|
||||
|
||||
@using Teknik.Areas.Status.ViewModels
|
||||
|
||||
@if (Model != null && Model.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3>One Time Payments</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#oneTime-section">View Payments</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="oneTime-section" class="collapse in">
|
||||
<table class="table table-condensed table-bordered table-hover">
|
||||
<tr>
|
||||
<th><strong>Date</strong></th>
|
||||
<th><strong>Amount</strong></th>
|
||||
<th><strong>Reason for Payment</strong></th>
|
||||
</tr>
|
||||
@foreach (OneTimeViewModel oneTime in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@oneTime.DateSent.ToString("MMMM dd, yyyy")</td>
|
||||
<td>@oneTime.Amount <var>@oneTime.Currency.ToString()</var></td>
|
||||
<td>@oneTime.Reason</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
37
Teknik/Areas/Status/Views/Status/Takedowns.cshtml
Normal file
37
Teknik/Areas/Status/Views/Status/Takedowns.cshtml
Normal file
@ -0,0 +1,37 @@
|
||||
@model List<Teknik.Areas.Status.ViewModels.TakedownViewModel>
|
||||
|
||||
@using Teknik.Areas.Status.ViewModels
|
||||
|
||||
@if (Model != null && Model.Any())
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2 class="text-center"><b>Takedowns</b></h2>
|
||||
<hr>
|
||||
@if (Model != null && Model.Any())
|
||||
{
|
||||
<table class="table table-hover table-bordered table-condensed">
|
||||
<tr>
|
||||
<th><strong>Requester</strong></th>
|
||||
<th><strong>Contact</strong></th>
|
||||
<th><strong>Date Requested</strong></th>
|
||||
<th><strong>Date Of Action</strong></th>
|
||||
<th><strong>Reason</strong></th>
|
||||
<th><strong>Action Taken</strong></th>
|
||||
</tr>
|
||||
@foreach (TakedownViewModel takedown in Model)
|
||||
{
|
||||
<tr>
|
||||
<td>@takedown.Requester</td>
|
||||
<td>@takedown.RequesterContact</td>
|
||||
<td>@takedown.DateRequested.ToString("MMMM dd, yyyy")</td>
|
||||
<td>@takedown.DateActionTaken.ToString("MMMM dd, yyyy")</td>
|
||||
<td>@takedown.Reason</td>
|
||||
<td>@takedown.ActionTaken</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
60
Teknik/Areas/Status/Views/Status/Transactions.cshtml
Normal file
60
Teknik/Areas/Status/Views/Status/Transactions.cshtml
Normal file
@ -0,0 +1,60 @@
|
||||
@model Teknik.Areas.Status.ViewModels.TransactionsViewModel
|
||||
|
||||
@using Teknik.Areas.Status.ViewModels
|
||||
|
||||
@{
|
||||
decimal totalBills = Model.CurrentMonthBills;
|
||||
decimal totalIncome = Model.CurrentMonthIncome;
|
||||
int incomePercentage = 100;
|
||||
if (totalIncome != 0 && totalBills != 0)
|
||||
{
|
||||
incomePercentage = (int)Math.Max((Math.Floor(totalBills / totalIncome) * 100), 100);
|
||||
}
|
||||
|
||||
string processStyle = "progress-bar progress-bar-success";
|
||||
if (incomePercentage < 100)
|
||||
{
|
||||
processStyle += " progress-bar-striped";
|
||||
}
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h2 class="text-center"><b>Transactions</b></h2>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<h3 class="text-center">Monthly Donation Target</h3>
|
||||
<div class="progress">
|
||||
<div class="@processStyle" role="progressbar" style="width: @incomePercentage%"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 text-center">$@totalIncome Donated / $@totalBills Bills</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="text-center">Transaction Totals</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Donations</h4>
|
||||
<p>$@Math.Round(Model.TotalDonations, 2)</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Bills</h4>
|
||||
<p>$@Math.Round(Model.TotalBills, 2)</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>One-Time Payments</h4>
|
||||
<p>$@Math.Round(Model.TotalOneTimes, 2)</p>
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Net Profit</h4>
|
||||
<p>$@Math.Round(Model.TotalNet, 2)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@Html.Partial("~/Areas/Status/Views/Status/Bills.cshtml", Model.Bills)
|
||||
@Html.Partial("~/Areas/Status/Views/Status/OneTimes.cshtml", Model.OneTimes)
|
||||
@Html.Partial("~/Areas/Status/Views/Status/Donations.cshtml", Model.Donations)
|
@ -1,130 +0,0 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Teknik.Areas.Transparency.Models;
|
||||
using Teknik.Areas.Transparency.ViewModels;
|
||||
using Teknik.Attributes;
|
||||
using Teknik.Controllers;
|
||||
using Teknik.Filters;
|
||||
using Teknik.Models;
|
||||
using Teknik.Piwik;
|
||||
|
||||
namespace Teknik.Areas.Transparency.Controllers
|
||||
{
|
||||
[TeknikAuthorize]
|
||||
public class TransparencyController : DefaultController
|
||||
{
|
||||
private TeknikEntities db = new TeknikEntities();
|
||||
|
||||
[TrackPageView]
|
||||
[AllowAnonymous]
|
||||
public ActionResult Index()
|
||||
{
|
||||
ViewBag.Title = "Transparency - " + Config.Title;
|
||||
ViewBag.Description = "Teknik transparency and statistics.";
|
||||
TransparencyViewModel model = new TransparencyViewModel();
|
||||
|
||||
if (Config.TransparencyConfig.Enabled)
|
||||
{
|
||||
model.TotalNet = new Dictionary<string, double>();
|
||||
|
||||
var billSums = db.Transactions.OfType<Bill>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList();
|
||||
model.TotalBills = new Dictionary<string, double>();
|
||||
foreach (var sum in billSums)
|
||||
{
|
||||
model.TotalBills.Add(sum.currency, sum.total);
|
||||
if (model.TotalNet.ContainsKey(sum.currency))
|
||||
{
|
||||
model.TotalNet[sum.currency] += sum.total;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.TotalNet.Add(sum.currency, sum.total);
|
||||
}
|
||||
}
|
||||
|
||||
var oneSums = db.Transactions.OfType<OneTime>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList();
|
||||
model.TotalOneTimes = new Dictionary<string, double>();
|
||||
foreach (var sum in oneSums)
|
||||
{
|
||||
model.TotalOneTimes.Add(sum.currency, sum.total);
|
||||
if (model.TotalNet.ContainsKey(sum.currency))
|
||||
{
|
||||
model.TotalNet[sum.currency] += sum.total;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.TotalNet.Add(sum.currency, sum.total);
|
||||
}
|
||||
}
|
||||
|
||||
var donationSums = db.Transactions.OfType<Donation>().GroupBy(b => b.Currency).Select(b => new { currency = b.Key, total = b.Sum(c => c.Amount) }).ToList();
|
||||
model.TotalDonations = new Dictionary<string, double>();
|
||||
foreach (var sum in donationSums)
|
||||
{
|
||||
model.TotalDonations.Add(sum.currency, sum.total);
|
||||
if (model.TotalNet.ContainsKey(sum.currency))
|
||||
{
|
||||
model.TotalNet[sum.currency] += sum.total;
|
||||
}
|
||||
else
|
||||
{
|
||||
model.TotalNet.Add(sum.currency, sum.total);
|
||||
}
|
||||
}
|
||||
|
||||
List<Bill> bills = db.Transactions.OfType<Bill>().OrderByDescending(b => b.DateSent).ToList();
|
||||
model.Bills = (bills != null) ? bills : new List<Bill>();
|
||||
|
||||
List<OneTime> oneTimes = db.Transactions.OfType<OneTime>().OrderByDescending(b => b.DateSent).ToList();
|
||||
model.OneTimes = (oneTimes != null) ? oneTimes : new List<OneTime>();
|
||||
|
||||
List<Donation> donations = db.Transactions.OfType<Donation>().OrderByDescending(b => b.DateSent).ToList();
|
||||
model.Donations = (donations != null) ? donations : new List<Donation>();
|
||||
|
||||
|
||||
List<Takedown> takedowns = db.Takedowns.OrderByDescending(b => b.DateRequested).ToList();
|
||||
model.Takedowns = (takedowns != null) ? takedowns : new List<Takedown>();
|
||||
|
||||
// Grab canary file
|
||||
if (System.IO.File.Exists(Config.TransparencyConfig.CanaryPath))
|
||||
{
|
||||
model.Canary = System.IO.File.ReadAllText(Config.TransparencyConfig.CanaryPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Canary = string.Empty;
|
||||
}
|
||||
}
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public ActionResult GetVisitorData()
|
||||
{
|
||||
// Get the data from the Piwik
|
||||
if (!string.IsNullOrEmpty(Config.PiwikConfig.API))
|
||||
{
|
||||
List<VisitorData> dataList = Reporting.GetVisitSummaryByDays(Config, 31);
|
||||
|
||||
List<object> uniqueData = new List<object>();
|
||||
List<object> totalData = new List<object>();
|
||||
|
||||
foreach (VisitorData data in dataList.OrderBy(d => d.Date))
|
||||
{
|
||||
object uniqueDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.UniqueVisitors };
|
||||
uniqueData.Add(uniqueDay);
|
||||
object totalDay = new { x = Convert.ToInt64((data.Date.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds), y = data.Visits };
|
||||
totalData.Add(totalDay);
|
||||
}
|
||||
|
||||
return Json(new { result = new { uniqueVisitors = uniqueData.ToArray(), totalVisitors = totalData.ToArray() } }, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
return Json(new { error = new { message = "Piwik not configured" } }, JsonRequestBehavior.AllowGet);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
var visitChart;
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#bills-section').collapse('hide');
|
||||
$('#oneTime-section').collapse('hide');
|
||||
$('#donations-section').collapse('hide');
|
||||
$('#takedowns-section').collapse('hide');
|
||||
|
||||
visitChart = new Highcharts.chart({
|
||||
chart: {
|
||||
renderTo: 'visitor-chart'
|
||||
},
|
||||
title: {
|
||||
text: 'Daily Visitors'
|
||||
},
|
||||
xAxis: {
|
||||
type: 'datetime',
|
||||
dateTimeLabelFormats: { // don't display the dummy year
|
||||
month: '%e. %b',
|
||||
year: '%b'
|
||||
},
|
||||
title: {
|
||||
text: 'Date'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Visitors'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
shared: true,
|
||||
crosshairs: true,
|
||||
headerFormat: '<span style="font-size: 10px">{point.key:%B %e, %Y}</span><br/>',
|
||||
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.y}</b><br/>'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'All Visitors',
|
||||
data: []
|
||||
},
|
||||
{
|
||||
name: 'Unique Visitors',
|
||||
data: []
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
if (statsEnabled) {
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: getVisitorDataURL,
|
||||
success: function (response) {
|
||||
if (response.result) {
|
||||
visitChart.series[0].setData(response.result.totalVisitors);
|
||||
visitChart.series[1].setData(response.result.uniqueVisitors);
|
||||
}
|
||||
else {
|
||||
var err = response;
|
||||
if (response.error) {
|
||||
err = response.error.message;
|
||||
}
|
||||
$("#top_msg").css('display', 'inline', 'important');
|
||||
$("#top_msg").html('<div class="alert alert-danger alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>' + err + '</div>');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
@ -1,45 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Optimization;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.Utilities;
|
||||
|
||||
namespace Teknik.Areas.Transparency
|
||||
{
|
||||
public class TransparencyAreaRegistration : AreaRegistration
|
||||
{
|
||||
public override string AreaName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Transparency";
|
||||
}
|
||||
}
|
||||
|
||||
public override void RegisterArea(AreaRegistrationContext context)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
context.MapSubdomainRoute(
|
||||
"Transparency.Index",
|
||||
new List<string>() { "transparency" }, // Subdomains
|
||||
new List<string>() { config.Host }, // domains
|
||||
"",
|
||||
new { controller = "Transparency", action = "Index" },
|
||||
new[] { typeof(Controllers.TransparencyController).Namespace }
|
||||
);
|
||||
context.MapSubdomainRoute(
|
||||
"Transparency.Action",
|
||||
new List<string>() { "transparency" }, // Subdomains
|
||||
new List<string>() { config.Host }, // domains
|
||||
"Action/{controller}/{action}",
|
||||
new { controller = "Transparency", action = "Index" },
|
||||
new[] { typeof(Controllers.TransparencyController).Namespace }
|
||||
);
|
||||
|
||||
// Register Script Bundle
|
||||
BundleTable.Bundles.Add(new CdnScriptBundle("~/bundles/transparency", config.CdnHost).Include(
|
||||
"~/Scripts/Highcharts/highcharts.js",
|
||||
"~/Areas/Transparency/Scripts/Transparency.js"));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Teknik.Areas.Transparency.Models;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Transparency.ViewModels
|
||||
{
|
||||
public class TransparencyViewModel : ViewModelBase
|
||||
{
|
||||
public string Canary { get; set; }
|
||||
|
||||
public Dictionary<string, double> TotalBills { get; set; }
|
||||
|
||||
public Dictionary<string, double> TotalOneTimes { get; set; }
|
||||
|
||||
public Dictionary<string, double> TotalDonations { get; set; }
|
||||
|
||||
public Dictionary<string, double> TotalNet { get; set; }
|
||||
|
||||
public List<Bill> Bills { get; set; }
|
||||
|
||||
public List<OneTime> OneTimes { get; set; }
|
||||
|
||||
public List<Donation> Donations { get; set; }
|
||||
|
||||
public List<Takedown> Takedowns { get; set; }
|
||||
}
|
||||
}
|
@ -1,255 +0,0 @@
|
||||
@model Teknik.Areas.Transparency.ViewModels.TransparencyViewModel
|
||||
|
||||
@using Teknik.Utilities
|
||||
@using Teknik.Areas.Transparency.Models
|
||||
|
||||
@Scripts.Render("~/bundles/transparency")
|
||||
|
||||
<script type="text/javascript">
|
||||
var statsEnabled = @(Model.Config.PiwikConfig.Enabled.ToString().ToLower());
|
||||
var getVisitorDataURL = '@Url.SubRouteUrl("transparency", "Transparency.Action", new { action = "GetVisitorData" })';
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
@if (Model.Config.TransparencyConfig.Enabled)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-offset-1">
|
||||
<h2 class="text-center"><b>Behind the Scenes</b></h2>
|
||||
<hr>
|
||||
<p>
|
||||
Here you can view all of Teknik's financial information, takedown requests and the actions we took.
|
||||
</p>
|
||||
<p>
|
||||
If you would like to request additional information about Teknik, please feel free to contact us through our <a href="@Url.SubRouteUrl("contact", "Contact.Index")" target="_blank">Contact Form</a> or by emailing us at <a href="mailto:@Model.Config.SupportEmail">@Model.Config.SupportEmail</a>.
|
||||
</p>
|
||||
<br />
|
||||
<h2 class="text-center"><b>Transactions</b></h2>
|
||||
<hr>
|
||||
<h3 class="text-center">Total Amounts</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Donations</h4>
|
||||
@foreach (var val in Model.TotalDonations)
|
||||
{
|
||||
<p>@Math.Round(val.Value, 2) @val.Key</p>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Bills</h4>
|
||||
@foreach (var val in Model.TotalBills)
|
||||
{
|
||||
<p>@Math.Round(val.Value, 2) @val.Key</p>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>One-Time Payments</h4>
|
||||
@foreach (var val in Model.TotalOneTimes)
|
||||
{
|
||||
<p>@Math.Round(val.Value, 2) @val.Key</p>
|
||||
}
|
||||
</div>
|
||||
<div class="col-sm-3 text-center">
|
||||
<h4>Net Profit</h4>
|
||||
@foreach (var val in Model.TotalNet)
|
||||
{
|
||||
<p>@Math.Round(val.Value, 2) @val.Key</p>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if (Model.Bills != null && Model.Bills.Any())
|
||||
{
|
||||
<h3>Bills</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#bills-section">View Bills</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="bills-section" class="collapse in">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<h4><strong>Date</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Amount</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
<h4><strong>Description</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (Bill bill in Model.Bills)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
@bill.DateSent.ToString("MMMM dd, yyyy")
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@bill.Amount <var>@bill.Currency</var>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
@bill.Reason
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (Model.OneTimes != null && Model.OneTimes.Any())
|
||||
{
|
||||
<h3>One Time Payments</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#oneTime-section">View Payments</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="oneTime-section" class="collapse in">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<h4><strong>Date</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Amount</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
<h4><strong>Reason for Payment</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (OneTime oneTime in Model.OneTimes)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
@oneTime.DateSent.ToString("MMMM dd, yyyy")
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@oneTime.Amount <var>@oneTime.Currency</var>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
@oneTime.Reason
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (Model.Donations != null && Model.Donations.Any())
|
||||
{
|
||||
<h3>Donations</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#donations-section">View Donations</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="donations-section" class="collapse in">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<h4><strong>Date</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Amount</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Donor</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<h4><strong>Reason for Donation</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (Donation donation in Model.Donations)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
@donation.DateSent.ToString("MMMM dd, yyyy")
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@donation.Amount <var>@donation.Currency</var>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@donation.Sender
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
@donation.Reason
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<br />
|
||||
<h2 class="text-center"><b>Takedowns</b></h2>
|
||||
<hr>
|
||||
@if (Model.Takedowns != null && Model.Takedowns.Any())
|
||||
{
|
||||
<h3>Takedowns</h3>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#takedowns-section">View Takedowns</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div id="takedowns-section" class="collapse in">
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Requester</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Contact</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Reason</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Action Taken</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Date Requested</strong></h4>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<h4><strong>Date Of Action</strong></h4>
|
||||
</div>
|
||||
</div>
|
||||
@foreach (Takedown takedown in Model.Takedowns)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
@takedown.Requester
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@takedown.RequesterContact
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@takedown.Reason
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@takedown.ActionTaken
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@takedown.DateRequested.ToString("MMMM dd, yyyy")
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
@takedown.DateActionTaken.ToString("MMMM dd, yyyy")
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
@if (!string.IsNullOrEmpty(Model.Canary))
|
||||
{
|
||||
<pre>@Model.Canary</pre>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2 text-center">
|
||||
<h3>Transparency Information has been disabled</h3>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
@ -1,3 +0,0 @@
|
||||
@{
|
||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="System.Web.Mvc" />
|
||||
<add namespace="System.Web.Mvc.Ajax" />
|
||||
<add namespace="System.Web.Mvc.Html" />
|
||||
<add namespace="System.Web.Routing" />
|
||||
<add namespace="System.Web.Optimization" />
|
||||
<add namespace="Teknik" />
|
||||
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<appSettings>
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
</appSettings>
|
||||
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
@ -8,7 +8,7 @@ using Teknik.Migrations;
|
||||
using Teknik.Areas.Upload.Models;
|
||||
using Teknik.Areas.Paste.Models;
|
||||
using Teknik.Areas.Podcast.Models;
|
||||
using Teknik.Areas.Transparency.Models;
|
||||
using Teknik.Areas.Status.Models;
|
||||
using Teknik.Areas.Shortener.Models;
|
||||
using Teknik.Attributes;
|
||||
using System.Data.Entity.ModelConfiguration.Conventions;
|
||||
|
Binary file not shown.
@ -103,6 +103,10 @@
|
||||
<HintPath>..\packages\MySql.Data.6.9.9\lib\net45\MySql.Data.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="NBitcoin, Version=3.0.2.4, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NBitcoin.3.0.2.4\lib\net45\NBitcoin.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="nClam, Version=2.0.6.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\nClam.2.0.6.0\lib\net40-Client\nClam.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
@ -259,8 +263,19 @@
|
||||
<Compile Include="Areas\Privacy\PrivacyAreaRegistration.cs" />
|
||||
<Compile Include="Areas\Privacy\ViewModels\PrivacyViewModel.cs" />
|
||||
<Compile Include="Areas\Status\Controllers\StatusController.cs" />
|
||||
<Compile Include="Areas\Status\Models\Bill.cs" />
|
||||
<Compile Include="Areas\Status\Models\Donation.cs" />
|
||||
<Compile Include="Areas\Status\Models\OneTime.cs" />
|
||||
<Compile Include="Areas\Status\Models\Takedown.cs" />
|
||||
<Compile Include="Areas\Status\Models\Transaction.cs" />
|
||||
<Compile Include="Areas\Status\StatusAreaRegistration.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\OneTimeViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\DonationViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\StatusViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\TakedownViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\TransactionsViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\BillViewModel.cs" />
|
||||
<Compile Include="Areas\Status\ViewModels\TransactionViewModel.cs" />
|
||||
<Compile Include="Areas\User\Controllers\UserController.cs" />
|
||||
<Compile Include="Areas\User\Models\BlogSettings.cs" />
|
||||
<Compile Include="Areas\User\Models\ResetPasswordVerification.cs" />
|
||||
@ -302,14 +317,6 @@
|
||||
<Compile Include="Areas\TOS\Controllers\TOSController.cs" />
|
||||
<Compile Include="Areas\TOS\TOSAreaRegistration.cs" />
|
||||
<Compile Include="Areas\TOS\ViewModels\TOSViewModel.cs" />
|
||||
<Compile Include="Areas\Transparency\Controllers\TransparencyController.cs" />
|
||||
<Compile Include="Areas\Transparency\Models\Bill.cs" />
|
||||
<Compile Include="Areas\Transparency\Models\Donation.cs" />
|
||||
<Compile Include="Areas\Transparency\Models\OneTime.cs" />
|
||||
<Compile Include="Areas\Transparency\Models\Takedown.cs" />
|
||||
<Compile Include="Areas\Transparency\Models\Transaction.cs" />
|
||||
<Compile Include="Areas\Transparency\TransparencyAreaRegistration.cs" />
|
||||
<Compile Include="Areas\Transparency\ViewModels\TransparencyViewModel.cs" />
|
||||
<Compile Include="Areas\Upload\Controllers\UploadController.cs" />
|
||||
<Compile Include="Areas\Upload\Models\FileModel.cs" />
|
||||
<Compile Include="Areas\Upload\Models\Upload.cs" />
|
||||
@ -371,7 +378,6 @@
|
||||
<Content Include="Areas\Podcast\Content\Podcast.css" />
|
||||
<Content Include="Areas\Podcast\Scripts\Podcast.js" />
|
||||
<Content Include="Areas\Status\Scripts\Status.js" />
|
||||
<Content Include="Areas\Transparency\Scripts\Transparency.js" />
|
||||
<Content Include="Areas\Upload\Content\Upload.css" />
|
||||
<Content Include="Areas\User\Scripts\CheckAuthCode.js" />
|
||||
<Content Include="Areas\User\Scripts\Profile.js" />
|
||||
@ -564,9 +570,7 @@
|
||||
<Content Include="Areas\Podcast\Views\Podcast\ViewPodcast.cshtml" />
|
||||
<Content Include="App_Data\Config.json" />
|
||||
<Content Include="Areas\User\Views\User\Settings.cshtml" />
|
||||
<Content Include="Areas\Transparency\Views\web.config" />
|
||||
<Content Include="Areas\Vault\Views\_ViewStart.cshtml" />
|
||||
<Content Include="Areas\Transparency\Views\Transparency\Index.cshtml" />
|
||||
<Content Include="Areas\Help\Views\Help\RSS.cshtml" />
|
||||
<Content Include="Areas\Stream\Views\web.config" />
|
||||
<Content Include="Areas\Stream\Views\_ViewStart.cshtml" />
|
||||
@ -612,14 +616,18 @@
|
||||
<Content Include="Fonts\fontawesome-webfont.eot" />
|
||||
<Content Include="Areas\User\Views\User\AuthToken.cshtml" />
|
||||
<Content Include="Areas\Error\Views\Error\Http401.cshtml" />
|
||||
<Content Include="Areas\Transparency\Views\_ViewStart.cshtml" />
|
||||
<Content Include="Areas\Vault\Views\Vault\ModifyVault.cshtml" />
|
||||
<Content Include="Areas\Vault\Views\Vault\ModifyVaultItem.cshtml" />
|
||||
<Content Include="Areas\Vault\Views\Vault\PasteItem.cshtml" />
|
||||
<Content Include="Areas\Vault\Views\Vault\UploadItem.cshtml" />
|
||||
<Content Include="Areas\Status\Views\web.config" />
|
||||
<Content Include="Areas\Status\Views\_ViewStart.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Shared\Index.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\Index.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\Transactions.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\Bills.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\OneTimes.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\Donations.cshtml" />
|
||||
<Content Include="Areas\Status\Views\Status\Takedowns.cshtml" />
|
||||
<None Include="Properties\PublishProfiles\Teknik Dev.pubxml" />
|
||||
<None Include="Properties\PublishProfiles\Teknik Production.pubxml" />
|
||||
<None Include="Scripts\jquery-2.1.4.intellisense.js" />
|
||||
@ -718,12 +726,10 @@
|
||||
<Folder Include="Areas\Privacy\Models\" />
|
||||
<Folder Include="Areas\Privacy\Views\Shared\" />
|
||||
<Folder Include="Areas\Shortener\Views\Shared\" />
|
||||
<Folder Include="Areas\Status\Models\" />
|
||||
<Folder Include="Areas\Status\Views\Status\" />
|
||||
<Folder Include="Areas\Status\Views\Shared\" />
|
||||
<Folder Include="Areas\Stream\Views\Shared\" />
|
||||
<Folder Include="Areas\TOS\Models\" />
|
||||
<Folder Include="Areas\TOS\Views\Shared\" />
|
||||
<Folder Include="Areas\Transparency\Views\Shared\" />
|
||||
<Folder Include="Areas\Upload\Views\Shared\" />
|
||||
<Folder Include="Areas\User\Repositories\" />
|
||||
<Folder Include="Areas\User\Views\Shared\" />
|
||||
|
@ -51,7 +51,7 @@
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col-sm-5 col-sm-offset-1 text-left text-muted">
|
||||
© Teknik 2013-2017 | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("transparency", "Transparency.Index")">Transparency</a>
|
||||
© Teknik 2013-2017 | <a href="@Url.SubRouteUrl("privacy", "Privacy.Index")">Privacy</a> | <a href="@Url.SubRouteUrl("tos", "TOS.Index")">TOS</a> | <a href="@Url.SubRouteUrl("status", "Status.Index")">Status</a>
|
||||
</div>
|
||||
<div class="col-sm-5 text-right text-muted">
|
||||
<div id="pagetime" style="display:none;">
|
||||
|
@ -32,6 +32,7 @@
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net46" userInstalled="true" />
|
||||
<package id="Modernizr" version="2.8.3" targetFramework="net452" userInstalled="true" />
|
||||
<package id="MySql.Data" version="6.9.9" targetFramework="net452" />
|
||||
<package id="NBitcoin" version="3.0.2.4" targetFramework="net462" />
|
||||
<package id="nClam" version="2.0.6.0" targetFramework="net462" />
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" userInstalled="true" />
|
||||
<package id="Owin" version="1.0" targetFramework="net462" />
|
||||
|
@ -40,7 +40,6 @@ namespace Teknik.Configuration
|
||||
private StreamConfig _StreamConfig;
|
||||
private ShortenerConfig _ShortenerConfig;
|
||||
private VaultConfig _VaultConfig;
|
||||
private TransparencyConfig _TransparencyConfig;
|
||||
private StatusConfig _StatusConfig;
|
||||
private DatabaseConfig _DatabaseConfig;
|
||||
private LoggingConfig _LoggingConfig;
|
||||
@ -98,9 +97,6 @@ namespace Teknik.Configuration
|
||||
// Vault Configuration
|
||||
public VaultConfig VaultConfig { get { return _VaultConfig; } set { _VaultConfig = value; } }
|
||||
|
||||
// Transparency Configuration
|
||||
public TransparencyConfig TransparencyConfig { get { return _TransparencyConfig; } set { _TransparencyConfig = value; } }
|
||||
|
||||
// Status Configuration
|
||||
public StatusConfig StatusConfig { get { return _StatusConfig; } set { _StatusConfig = value; } }
|
||||
|
||||
@ -150,7 +146,6 @@ namespace Teknik.Configuration
|
||||
StreamConfig = new StreamConfig();
|
||||
ShortenerConfig = new ShortenerConfig();
|
||||
VaultConfig = new VaultConfig();
|
||||
TransparencyConfig = new TransparencyConfig();
|
||||
StatusConfig = new StatusConfig();
|
||||
DatabaseConfig = new DatabaseConfig();
|
||||
LoggingConfig = new LoggingConfig();
|
||||
|
@ -63,7 +63,6 @@
|
||||
<Compile Include="VaultConfig.cs" />
|
||||
<Compile Include="ShortenerConfig.cs" />
|
||||
<Compile Include="StreamConfig.cs" />
|
||||
<Compile Include="TransparencyConfig.cs" />
|
||||
<Compile Include="UploadConfig.cs" />
|
||||
<Compile Include="UserConfig.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Configuration
|
||||
{
|
||||
public class TransparencyConfig
|
||||
{
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
public string CanaryPath { get; set; }
|
||||
|
||||
public TransparencyConfig()
|
||||
{
|
||||
Enabled = false;
|
||||
CanaryPath = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
78
Utilities/Utilities/CurrencyHelper.cs
Normal file
78
Utilities/Utilities/CurrencyHelper.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Teknik.Utilities
|
||||
{
|
||||
public static class CurrencyHelper
|
||||
{
|
||||
private static decimal m_CurrentBTCPrice = 0;
|
||||
private static DateTime m_LastBTCQuery = DateTime.MinValue;
|
||||
private static TimeSpan m_MaxBTCQueryTime = new TimeSpan(1, 0, 0); // Max query of every hour
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exchange rate for a given currency relative to USD
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <returns></returns>
|
||||
public static decimal GetExchangeRate(CurrencyType target)
|
||||
{
|
||||
decimal exchangeRate = 1;
|
||||
switch (target)
|
||||
{
|
||||
case CurrencyType.USD:
|
||||
exchangeRate = 1;
|
||||
break;
|
||||
case CurrencyType.BTC:
|
||||
// get BTC usd price
|
||||
exchangeRate = GetBTCPrice();
|
||||
break;
|
||||
}
|
||||
|
||||
return exchangeRate;
|
||||
}
|
||||
|
||||
public static decimal GetBTCPrice()
|
||||
{
|
||||
DateTime curTime = DateTime.Now;
|
||||
if (curTime - m_LastBTCQuery > m_MaxBTCQueryTime)
|
||||
{
|
||||
m_LastBTCQuery = curTime;
|
||||
string url = "http://api.bitcoincharts.com/v1/weighted_prices.json";
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
try
|
||||
{
|
||||
WebResponse response = request.GetResponse();
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
{
|
||||
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
|
||||
string jsonResult = reader.ReadToEnd();
|
||||
JObject result = JsonConvert.DeserializeObject<JObject>(jsonResult);
|
||||
if (result["USD"] != null)
|
||||
{
|
||||
string priceStr = result["USD"]["24h"].ToString();
|
||||
decimal.TryParse(priceStr, out m_CurrentBTCPrice);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebException ex)
|
||||
{
|
||||
WebResponse errorResponse = ex.Response;
|
||||
using (Stream responseStream = errorResponse.GetResponseStream())
|
||||
{
|
||||
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
|
||||
String errorText = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m_CurrentBTCPrice;
|
||||
}
|
||||
}
|
||||
}
|
13
Utilities/Utilities/CurrencyType.cs
Normal file
13
Utilities/Utilities/CurrencyType.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Teknik.Utilities
|
||||
{
|
||||
public enum CurrencyType
|
||||
{
|
||||
USD,
|
||||
BTC
|
||||
}
|
||||
}
|
@ -105,6 +105,8 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CurrencyHelper.cs" />
|
||||
<Compile Include="CurrencyType.cs" />
|
||||
<Compile Include="FileGenerateResult.cs" />
|
||||
<Compile Include="HttpWebResponseResult.cs" />
|
||||
<Compile Include="BundleExtensions.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user