mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 22:14:26 +01:00
add minimal crowdfund system and UI
This commit is contained in:
@@ -22,6 +22,9 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public string MainImageUrl { get; set; }
|
||||
public string NotificationUrl { get; set; }
|
||||
public string Tagline { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +44,12 @@ namespace BTCPayServer.Controllers
|
||||
StartDate = settings.StartDate,
|
||||
TargetCurrency = settings.TargetCurrency,
|
||||
Description = settings.Description,
|
||||
MainImageUrl = settings.MainImageUrl,
|
||||
EndDate = settings.EndDate,
|
||||
TargetAmount = settings.TargetAmount,
|
||||
CustomCSSLink = settings.CustomCSSLink
|
||||
CustomCSSLink = settings.CustomCSSLink,
|
||||
NotificationUrl = settings.NotificationUrl,
|
||||
Tagline = settings.Tagline
|
||||
};
|
||||
return View(vm);
|
||||
}
|
||||
@@ -62,12 +68,15 @@ namespace BTCPayServer.Controllers
|
||||
Title = vm.Title,
|
||||
Enabled = vm.Enabled,
|
||||
EnforceTargetAmount = vm.EnforceTargetAmount,
|
||||
StartDate = vm.StartDate,
|
||||
StartDate = vm.StartDate?.ToUniversalTime(),
|
||||
TargetCurrency = vm.TargetCurrency,
|
||||
Description = vm.Description,
|
||||
EndDate = vm.EndDate,
|
||||
EndDate = vm.EndDate?.ToUniversalTime(),
|
||||
TargetAmount = vm.TargetAmount,
|
||||
CustomCSSLink = vm.CustomCSSLink
|
||||
CustomCSSLink = vm.CustomCSSLink,
|
||||
MainImageUrl = vm.MainImageUrl,
|
||||
NotificationUrl = vm.NotificationUrl,
|
||||
Tagline = vm.Tagline
|
||||
});
|
||||
await UpdateAppSettings(app);
|
||||
StatusMessage = "App updated";
|
||||
|
||||
@@ -86,37 +86,46 @@ namespace BTCPayServer.Controllers
|
||||
[HttpGet]
|
||||
[Route("/apps/{appId}/crowdfund")]
|
||||
[XFrameOptionsAttribute(null)]
|
||||
public async Task<IActionResult> ViewCrowdfund(string appId)
|
||||
public async Task<IActionResult> ViewCrowdfund(string appId, string statusMessage)
|
||||
|
||||
{
|
||||
var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund);
|
||||
var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund, true);
|
||||
if (app == null)
|
||||
return NotFound();
|
||||
var settings = app.GetSettings<CrowdfundSettings>();
|
||||
var currency = _AppsHelper.GetCurrencyData(settings.TargetCurrency, false);
|
||||
|
||||
return View(CrowdfundHelper.GetInfo(app, _invoiceRepository, _rateFetcher, _btcPayNetworkProvider ));
|
||||
return View(await CrowdfundHelper.GetInfo(app, _invoiceRepository, _rateFetcher, _btcPayNetworkProvider, statusMessage ));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Route("/apps/{appId}/crowdfund/contribute")]
|
||||
[Route("/apps/{appId}/crowdfund")]
|
||||
[XFrameOptionsAttribute(null)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
[EnableCors(CorsPolicies.All)]
|
||||
public async Task<IActionResult> ContributeToCrowdfund(string appId,[FromBody]ContributeToCrowdfund request, [FromQuery]bool redirectToCheckout)
|
||||
public async Task<IActionResult> ContributeToCrowdfund(string appId, ContributeToCrowdfund request)
|
||||
{
|
||||
var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund);
|
||||
var app = await _AppsHelper.GetApp(appId, AppType.Crowdfund, true);
|
||||
if (app == null)
|
||||
return NotFound();
|
||||
var settings = app.GetSettings<CrowdfundSettings>();
|
||||
var currency = _AppsHelper.GetCurrencyData(settings.TargetCurrency, false);
|
||||
var store = await _AppsHelper.GetStore(app);
|
||||
|
||||
store.AdditionalClaims.Add(new Claim(Policies.CanCreateInvoice.Key, store.Id));
|
||||
var invoice = await _InvoiceController.CreateInvoiceCore(new Invoice()
|
||||
{
|
||||
|
||||
OrderId = appId,
|
||||
Currency = settings.TargetCurrency,
|
||||
BuyerEmail = request.Email,
|
||||
Price = request.Amount,
|
||||
NotificationURL = settings.NotificationUrl,
|
||||
FullNotifications = true,
|
||||
ExtendedNotifications = true,
|
||||
}, store, HttpContext.Request.GetAbsoluteRoot());
|
||||
if (redirectToCheckout)
|
||||
if (request.RedirectToCheckout)
|
||||
{
|
||||
return RedirectToAction(nameof(InvoiceController.Checkout), "Invoice", new { invoiceId = invoice.Data.Id });
|
||||
return RedirectToAction(nameof(InvoiceController.Checkout), "Invoice",
|
||||
new {invoiceId = invoice.Data.Id});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -208,9 +217,10 @@ namespace BTCPayServer.Controllers
|
||||
var finalTasks = new List<Task>();
|
||||
foreach (var rateTask in ratesTask)
|
||||
{
|
||||
finalTasks.Add(rateTask.Value.ContinueWith(task =>
|
||||
finalTasks.Add(Task.Run(async () =>
|
||||
{
|
||||
var rate = task.Result.BidAsk?.Bid;
|
||||
var tResult = await rateTask.Value;
|
||||
var rate = tResult.BidAsk?.Bid;
|
||||
if (rate == null) return;
|
||||
var currencyGroup = groupingByCurrency.Single(entities => entities.Key == rateTask.Key.Left);
|
||||
result += currencyGroup.Sum(entity => entity.ProductInformation.Price / rate.Value);
|
||||
@@ -224,7 +234,7 @@ namespace BTCPayServer.Controllers
|
||||
}
|
||||
|
||||
public static async Task<ViewCrowdfundViewModel> GetInfo(AppData appData, InvoiceRepository invoiceRepository,
|
||||
RateFetcher rateFetcher, BTCPayNetworkProvider btcPayNetworkProvider)
|
||||
RateFetcher rateFetcher, BTCPayNetworkProvider btcPayNetworkProvider, string statusMessage= null)
|
||||
{
|
||||
var settings = appData.GetSettings<CrowdfundSettings>();
|
||||
var invoices = await GetPaidInvoicesForApp(appData, invoiceRepository);
|
||||
@@ -235,13 +245,15 @@ namespace BTCPayServer.Controllers
|
||||
var paidInvoices = invoices.Length;
|
||||
var active = (settings.StartDate == null || DateTime.UtcNow >= settings.StartDate) &&
|
||||
(settings.EndDate == null || DateTime.UtcNow <= settings.EndDate) &&
|
||||
(!settings.EnforceTargetAmount || settings.TargetAmount > currentAmount)
|
||||
(!settings.EnforceTargetAmount || settings.TargetAmount > currentAmount);
|
||||
|
||||
return new ViewCrowdfundViewModel()
|
||||
{
|
||||
Title = settings.Title,
|
||||
Tagline = settings.Tagline,
|
||||
Description = settings.Description,
|
||||
CustomCSSLink = settings.CustomCSSLink,
|
||||
MainImageUrl = settings.MainImageUrl,
|
||||
StoreId = appData.StoreDataId,
|
||||
AppId = appData.Id,
|
||||
StartDate = settings.StartDate,
|
||||
@@ -249,11 +261,16 @@ namespace BTCPayServer.Controllers
|
||||
TargetAmount = settings.TargetAmount,
|
||||
TargetCurrency = settings.TargetCurrency,
|
||||
EnforceTargetAmount = settings.EnforceTargetAmount,
|
||||
StatusMessage = statusMessage,
|
||||
Info = new ViewCrowdfundViewModel.CrowdfundInfo()
|
||||
{
|
||||
TotalContributors = paidInvoices,
|
||||
CurrentAmount = currentAmount,
|
||||
Active = active
|
||||
Active = active,
|
||||
DaysLeft = settings.EndDate.HasValue? (settings.EndDate - DateTime.UtcNow).Value.Days: (int?) null,
|
||||
DaysLeftToStart = settings.StartDate.HasValue? (settings.StartDate - DateTime.UtcNow).Value.Days: (int?) null,
|
||||
ShowProgress =active && settings.TargetAmount.HasValue,
|
||||
ProgressPercentage = currentAmount/ settings.TargetAmount * 100
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -281,14 +298,19 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
}
|
||||
|
||||
public async Task<AppData> GetApp(string appId, AppType appType)
|
||||
public async Task<AppData> GetApp(string appId, AppType appType, bool includeStore = false)
|
||||
{
|
||||
using (var ctx = _ContextFactory.CreateContext())
|
||||
{
|
||||
return await ctx.Apps
|
||||
var query = ctx.Apps
|
||||
.Where(us => us.Id == appId &&
|
||||
us.AppType == appType.ToString())
|
||||
.FirstOrDefaultAsync();
|
||||
us.AppType == appType.ToString());
|
||||
|
||||
if (includeStore)
|
||||
{
|
||||
query = query.Include(data => data.StoreData);
|
||||
}
|
||||
return await query.FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ using Microsoft.Extensions.Options;
|
||||
using Microsoft.AspNetCore.Mvc.Cors.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using System.Net;
|
||||
using BTCPayServer.Hubs;
|
||||
using Meziantou.AspNetCore.BundleTagHelpers;
|
||||
using BTCPayServer.Security;
|
||||
|
||||
@@ -78,7 +79,7 @@ namespace BTCPayServer.Hosting
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
services.AddSignalR();
|
||||
services.AddBTCPayServer();
|
||||
services.AddMvc(o =>
|
||||
{
|
||||
@@ -198,6 +199,10 @@ namespace BTCPayServer.Hosting
|
||||
AppPath = options.GetRootUri(),
|
||||
Authorization = new[] { new NeedRole(Roles.ServerAdmin) }
|
||||
});
|
||||
app.UseSignalR(route =>
|
||||
{
|
||||
route.MapHub<CrowdfundHub>("/apps/crowdfund/hub");
|
||||
});
|
||||
app.UseWebSockets();
|
||||
app.UseStatusCodePages();
|
||||
app.UseMvc(routes =>
|
||||
|
||||
10
BTCPayServer/Hubs/CrowdfundHub.cs
Normal file
10
BTCPayServer/Hubs/CrowdfundHub.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
||||
namespace BTCPayServer.Hubs
|
||||
{
|
||||
public class CrowdfundHub: Hub
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,9 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
|
||||
[Required]
|
||||
public string Description { get; set; }
|
||||
public string MainImageUrl { get; set; }
|
||||
|
||||
public string NotificationUrl { get; set; }
|
||||
|
||||
[Required]
|
||||
public bool Enabled { get; set; }
|
||||
@@ -33,5 +36,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
[MaxLength(500)]
|
||||
[Display(Name = "Custom bootstrap CSS file")]
|
||||
public string CustomCSSLink { get; set; }
|
||||
|
||||
public string Tagline { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public string AppId { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string MainImageUrl { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
@@ -19,6 +20,7 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
|
||||
public CrowdfundInfo Info { get; set; }
|
||||
public string Tagline { get; set; }
|
||||
|
||||
|
||||
public class CrowdfundInfo
|
||||
@@ -26,14 +28,21 @@ namespace BTCPayServer.Models.AppViewModels
|
||||
public int TotalContributors { get; set; }
|
||||
public decimal CurrentAmount { get; set; }
|
||||
public bool Active { get; set; }
|
||||
public bool ShowProgress { get; set; }
|
||||
public decimal? ProgressPercentage { get; set; }
|
||||
public int? DaysLeft{ get; set; }
|
||||
public int? DaysLeftToStart{ get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ContributeToCrowdfund
|
||||
{
|
||||
public ViewCrowdfundViewModel ViewCrowdfundViewModel { get; set; }
|
||||
[Required] public decimal Amount { get; set; }
|
||||
public string Email { get; set; }
|
||||
public bool RedirectToCheckout { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
<input asp-for="Title" class="form-control" />
|
||||
<span asp-validation-for="Title" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Tagline" class="control-label"></label>*
|
||||
<input asp-for="Tagline" class="form-control" />
|
||||
<span asp-validation-for="Tagline" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Description" class="control-label"></label>*
|
||||
<textarea asp-for="Description" rows="20" cols="40" class="form-control"></textarea>
|
||||
@@ -36,13 +41,26 @@
|
||||
<input asp-for="CustomCSSLink" class="form-control" />
|
||||
<span asp-validation-for="CustomCSSLink" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="MainImageUrl" class="control-label"></label>
|
||||
<input asp-for="MainImageUrl" class="form-control" />
|
||||
<span asp-validation-for="MainImageUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="NotificationUrl" class="control-label"></label>
|
||||
<input asp-for="NotificationUrl" class="form-control" />
|
||||
<span asp-validation-for="NotificationUrl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Enabled"></label>
|
||||
<input asp-for="Enabled" type="checkbox" class="form-check"/>
|
||||
<span asp-validation-for="Enabled" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="EnforceTargetAmount"></label>
|
||||
<input asp-for="EnforceTargetAmount" type="checkbox" class="form-check"/>
|
||||
|
||||
<span asp-validation-for="EnforceTargetAmount" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
23
BTCPayServer/Views/AppsPublic/ContributeForm.cshtml
Normal file
23
BTCPayServer/Views/AppsPublic/ContributeForm.cshtml
Normal file
@@ -0,0 +1,23 @@
|
||||
@model BTCPayServer.Models.AppViewModels.ContributeToCrowdfund
|
||||
|
||||
|
||||
<form method="post">
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Email"></label>
|
||||
<input asp-for="Email" type="email" class="form-control"/>
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Amount"></label>
|
||||
<div class="input-group mb-3">
|
||||
<input asp-for="Amount" type="number" step="any" class="form-control"/>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">@Model.ViewCrowdfundViewModel.TargetCurrency.ToUpperInvariant()</span>
|
||||
</div>
|
||||
</div>
|
||||
<span asp-validation-for="Amount" class="text-danger"></span>
|
||||
</div>
|
||||
<input type="hidden" asp-for="RedirectToCheckout"/>
|
||||
<button type="submit" class="btn btn-primary">Contribute</button>
|
||||
</form>
|
||||
@@ -1,8 +0,0 @@
|
||||
@model BTCPayServer.Models.AppViewModels.ContributeToCrowdfund
|
||||
|
||||
|
||||
<form method="post" action="contribute">
|
||||
<input asp-for="Email" type="email"/>
|
||||
<input asp-for="Amount" type="number" step="any" />
|
||||
<button type="submit">Contribute</button>
|
||||
</form>
|
||||
@@ -1,19 +0,0 @@
|
||||
@model BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel
|
||||
<div class="container d-flex h-100">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
<partial name="_StatusMessage" for="@Model.StatusMessage"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<header>
|
||||
<h1>@Model.Title</h1>
|
||||
</header>
|
||||
<main>
|
||||
@Model.Description
|
||||
<partial name="ContributeForm"/>
|
||||
</main>
|
||||
<footer></footer>
|
||||
<pre> @Html.Raw(Model)</pre>
|
||||
</div>
|
||||
101
BTCPayServer/Views/AppsPublic/MinimalCrowdfund.cshtml
Normal file
101
BTCPayServer/Views/AppsPublic/MinimalCrowdfund.cshtml
Normal file
@@ -0,0 +1,101 @@
|
||||
@using BTCPayServer.Models.AppViewModels
|
||||
@model BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel
|
||||
<div class="container h-100">
|
||||
|
||||
|
||||
<div class="row align-items-center h-100">
|
||||
|
||||
<div class="mx-auto card col-lg-8 col-sm-12 col-md-9 p-0">
|
||||
<partial name="_StatusMessage" for="@Model.StatusMessage"/>
|
||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||
{
|
||||
<img class="card-img-top" src="@Model.MainImageUrl" alt="Card image cap">
|
||||
}
|
||||
@if (Model.Info.ShowProgress)
|
||||
{
|
||||
<div class="progress rounded-0 striped" style="min-height: 30px">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="@Model.Info.ProgressPercentage" aria-valuemin="0" aria-valuemax="100">
|
||||
@if (Model.Info.ProgressPercentage.Value > 0)
|
||||
{
|
||||
@(Model.Info.ProgressPercentage + "%")
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="card-body">
|
||||
<div class="card-title row">
|
||||
<div class="col-9">
|
||||
|
||||
<h1 >
|
||||
@Model.Title
|
||||
@if (!string.IsNullOrEmpty(Model.Tagline))
|
||||
{
|
||||
<h2 class="text-muted">@Model.Tagline</h2>
|
||||
}
|
||||
|
||||
@if (Model.Info.DaysLeftToStart.HasValue && Model.Info.DaysLeftToStart > 0)
|
||||
{
|
||||
<small>
|
||||
@($"{Model.Info.DaysLeftToStart} day{(Model.Info.DaysLeftToStart.Value > 1 ? "s" : "")} left to start")
|
||||
|
||||
</small>
|
||||
}
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
<ul class="list-group list-group-flush col-3">
|
||||
<li class="list-group-item">@(Model.EndDate.HasValue? $"Ends {Model.EndDate.Value:dddd, dd MMMM yyyy HH:mm}" : "No specific end date")</li>
|
||||
<li class="list-group-item">@(Model.TargetAmount.HasValue? $"{Model.TargetAmount:G29} {Model.TargetCurrency.ToUpperInvariant()} Goal" :
|
||||
"No specific target goal")</li>
|
||||
<li class="list-group-item">@(Model.EnforceTargetAmount? $"Hardcap Goal" : "Softcap Goal")</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@if (Model.Info.Active)
|
||||
{
|
||||
<div class="card-deck mb-4 ">
|
||||
<div class="card shadow">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-center">@Model.Info.TotalContributors</h5>
|
||||
<h6 class="card-text text-center"> Contributors</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card shadow">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-center">@Model.Info.CurrentAmount @Model.TargetCurrency.ToUpperInvariant()</h5>
|
||||
<h6 class="card-text text-center"> Raised</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.Info.DaysLeft.HasValue && Model.Info.DaysLeft > 0)
|
||||
{
|
||||
<div class="card shadow">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title text-center">@Model.Info.DaysLeft</h5>
|
||||
<h6 class="card-text text-center">Day@(Model.Info.DaysLeft.Value > 1 ? "s" : "") left</h6>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="card-text"> @Html.Raw(Model.Description)</div>
|
||||
@if (Model.Info.Active)
|
||||
{
|
||||
<hr/>
|
||||
<h3>Contribute</h3>
|
||||
<partial name="ContributeForm" model="@(new ContributeToCrowdfund()
|
||||
{
|
||||
RedirectToCheckout = true,
|
||||
ViewCrowdfundViewModel = Model
|
||||
})"/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,7 +1,5 @@
|
||||
@addTagHelper *, Meziantou.AspNetCore.BundleTagHelpers
|
||||
@inject BTCPayServer.HostedServices.CssThemeManager themeManager
|
||||
|
||||
@using System.Security.AccessControl
|
||||
@model BTCPayServer.Models.AppViewModels.ViewCrowdfundViewModel
|
||||
@{
|
||||
ViewData["Title"] = Model.Title;
|
||||
@@ -15,7 +13,7 @@
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="@this.Context.Request.GetAbsoluteUri(themeManager.BootstrapUri)" rel="stylesheet"/>
|
||||
<link href="@Context.Request.GetAbsoluteUri(themeManager.BootstrapUri)" rel="stylesheet"/>
|
||||
@if (Model.CustomCSSLink != null)
|
||||
{
|
||||
<link href="@Model.CustomCSSLink" rel="stylesheet"/>
|
||||
@@ -23,7 +21,7 @@
|
||||
<link href="~/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet"/>
|
||||
<bundle name="wwwroot/bundles/crowdfund-bundle.min.js"></bundle>
|
||||
<script>
|
||||
var srvModel = @Html.Raw(Model);
|
||||
var srvModel = @Json.Serialize(Model);
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user