mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
upd tt
This commit is contained in:
@@ -11,6 +11,7 @@ using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Controllers;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Models;
|
||||
using BTCPayServer.Services.Apps;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -68,7 +69,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
[HttpGet("plugins/TicketTailor/{appId}")]
|
||||
public async Task<IActionResult> View(string appId)
|
||||
{
|
||||
var app = await _appService.GetApp(appId, TicketTailorApp.AppType);
|
||||
var app = await _appService.GetApp(appId, TicketTailorApp.AppType, true);
|
||||
if (app is null)
|
||||
return NotFound();
|
||||
try
|
||||
@@ -83,7 +84,11 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
return View(new TicketTailorViewModel() {Event = evt, Settings = config});
|
||||
return View(new TicketTailorViewModel()
|
||||
{
|
||||
Event = evt, Settings = config,
|
||||
StoreBranding = new StoreBrandingViewModel(app.StoreData.GetStoreBlob())
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -380,6 +385,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
vm.ApiKey = tt.ApiKey;
|
||||
vm.EventId = tt.EventId;
|
||||
vm.ShowDescription = tt.ShowDescription;
|
||||
vm.SendEmail = tt.SendEmail;
|
||||
vm.BypassAvailabilityCheck = tt.BypassAvailabilityCheck;
|
||||
vm.CustomCSS = tt.CustomCSS;
|
||||
vm.RequireFullName = tt.RequireFullName;
|
||||
@@ -483,7 +489,8 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
SpecificTickets = vm.SpecificTickets,
|
||||
BypassAvailabilityCheck = vm.BypassAvailabilityCheck,
|
||||
RequireFullName = vm.RequireFullName,
|
||||
AllowDiscountCodes = vm.AllowDiscountCodes
|
||||
AllowDiscountCodes = vm.AllowDiscountCodes,
|
||||
SendEmail = vm.SendEmail
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -238,6 +238,10 @@ public class TicketTailorService : EventHostedServiceBase
|
||||
}
|
||||
await _invoiceRepository.UpdateInvoiceMetadata(invoice.Id, invoice.StoreId, invoice.Metadata.ToJObject());
|
||||
await _invoiceRepository.AddInvoiceLogs(invoice.Id, invLogs);
|
||||
|
||||
if (settings.SendEmail)
|
||||
{
|
||||
|
||||
var uri = new Uri(btcpayUrl);
|
||||
var url =
|
||||
_linkGenerator.GetUriByAction("Receipt",
|
||||
@@ -257,6 +261,8 @@ public class TicketTailorService : EventHostedServiceBase
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -13,5 +13,6 @@ namespace BTCPayServer.Plugins.TicketTailor
|
||||
public bool BypassAvailabilityCheck { get; set; }
|
||||
public bool RequireFullName { get; set; }
|
||||
public bool AllowDiscountCodes { get; set; }
|
||||
public bool SendEmail { get; set; } = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Models;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace BTCPayServer.Plugins.TicketTailor;
|
||||
@@ -12,6 +13,7 @@ public class UpdateTicketTailorSettingsViewModel
|
||||
public SelectList Events { get; set; }
|
||||
public string EventId { get; set; }
|
||||
public bool ShowDescription { get; set; }
|
||||
public bool SendEmail { get; set; }
|
||||
public string CustomCSS { get; set; }
|
||||
public TicketTailorClient.TicketType[] TicketTypes { get; set; }
|
||||
|
||||
@@ -41,6 +43,7 @@ public class TicketTailorViewModel
|
||||
public PurchaseRequestItem[] Items { get; set; }
|
||||
public string AccessCode { get; set; }
|
||||
public string DiscountCode { get; set; }
|
||||
public StoreBrandingViewModel StoreBranding { get; set; }
|
||||
|
||||
public class PurchaseRequestItem
|
||||
{
|
||||
|
||||
@@ -89,6 +89,11 @@
|
||||
<label asp-for="AllowDiscountCodes" class="form-check-label">Allow discount codes (due to the nature of Ticket Tailor's API, redemption limit is not applied.</label>
|
||||
<span asp-validation-for="AllowDiscountCodes" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input asp-for="SendEmail" type="checkbox" class="form-check-input"/>
|
||||
<label asp-for="SendEmail" class="form-check-label">Send an email when an invoice settles and the ticket is issued. </label>
|
||||
<span asp-validation-for="SendEmail" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="CustomCSS" class="form-label">Additional Custom CSS</label>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
@model BTCPayServer.Plugins.TicketTailor.TicketTailorViewModel
|
||||
@{
|
||||
var appId = Context.GetRouteValue("appId");
|
||||
Layout = "_LayoutSimple";
|
||||
ViewData["StoreBranding"] = Model.StoreBranding;
|
||||
Layout = null;
|
||||
var available = Model.Settings.BypassAvailabilityCheck || (Model.Event.Unavailable != "true" && Model.Event.TicketsAvailable == "true");
|
||||
Model.Settings.SpecificTickets ??= new List<SpecificTicket>();
|
||||
Context.Request.Query.TryGetValue("accessCode", out var accessCode);
|
||||
@@ -13,85 +14,36 @@
|
||||
Model.DiscountCode = discount;
|
||||
}
|
||||
}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<partial name="LayoutHead"/>
|
||||
|
||||
|
||||
<style>
|
||||
hr:last-child{
|
||||
display: none;
|
||||
}
|
||||
footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(Model.Settings.CustomCSS))
|
||||
{
|
||||
@Safe.Raw(Model.Settings.CustomCSS)
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", ()=>{
|
||||
const form = document.querySelector("form");
|
||||
const btn = document.querySelector("button[type='submit']");
|
||||
const inputs = document.querySelectorAll("input");
|
||||
const discountCode = document.querySelector("#DiscountCode");
|
||||
inputs.forEach(value => value.addEventListener("input", (evt)=>{
|
||||
|
||||
|
||||
let total = 0;
|
||||
let totalQty = 0;
|
||||
document.querySelectorAll("[data-price]").forEach(value1 => {
|
||||
if (!!value1.value){
|
||||
const qty = parseInt(value1.value);
|
||||
if (qty > 0){
|
||||
|
||||
const price = parseFloat(value1.dataset.price).toPrecision(12);
|
||||
total += price * qty;
|
||||
totalQty += qty;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (totalQty > 0){
|
||||
btn.removeAttribute("disabled");
|
||||
}
|
||||
else{
|
||||
btn.setAttribute("disabled", "disabled");
|
||||
}
|
||||
btn.textContent = `Purchase for ${total.toFixed(2)} @Model.Event.Currency.ToUpperInvariant()`
|
||||
|
||||
if (discountCode && discountCode.value && totalQty > 0){
|
||||
const data = new FormData(form);
|
||||
const xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && this.status == 200) {
|
||||
const response = JSON.parse(this.responseText);
|
||||
if (response.discountedAmount){
|
||||
btn.innerHTML = `Purchase for ${response.total.toFixed(2)} @Model.Event.Currency.ToUpperInvariant()<br/><span class="">${response.discountedAmount.toFixed(2)} @Model.Event.Currency.ToUpperInvariant() discount</span>`
|
||||
} else{
|
||||
btn.textContent = `Purchase for ${response.total.toFixed(2)} @Model.Event.Currency.ToUpperInvariant()`
|
||||
}
|
||||
}
|
||||
}
|
||||
xhttp.open("POST", "@Url.Action("Purchase", new {appId, preview = true})", true);
|
||||
xhttp.send(data);
|
||||
}
|
||||
}))
|
||||
form.addEventListener("submit", ()=>{
|
||||
btn.setAttribute("disabled", "disabled");
|
||||
inputs.forEach(value => value.setAttribute("readonly", "readonly"));
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<div class="container d-flex h-100">
|
||||
<div class="justify-content-center mx-auto px-2 py-3 w-100 m-auto">
|
||||
</head>
|
||||
<body class="min-vh-100">
|
||||
<div id="TicketTailor" class="public-page-wrap">
|
||||
<partial name="_StoreHeader" model="(Model.Event.Title, Model.StoreBranding)"/>
|
||||
<main>
|
||||
<partial name="_StatusMessage"/>
|
||||
|
||||
<h1 class="text-center ">@Model.Event.Title</h1>
|
||||
<h2 class="text-muted mb-4 text-center ">@Model.Event.Start.Formatted - @Model.Event.EventEnd.Formatted</h2>
|
||||
<div class="text-muted mb-4 text-center lead ">@Model.Event.Start.Formatted - @Model.Event.EventEnd.Formatted</div>
|
||||
@if (Model.Settings.ShowDescription && !string.IsNullOrEmpty(Model.Event.Description))
|
||||
{
|
||||
<div class="row" id="ticket-tailor-description text-center ">
|
||||
<div class="overflow-hidden col-12 ">@Safe.Raw(Model.Event.Description)</div>
|
||||
</div>
|
||||
<div class="ticket-tailor-description lead">@Safe.Raw(Model.Event.Description)</div>
|
||||
}
|
||||
|
||||
|
||||
<form method="post" asp-controller="TicketTailor" asp-action="Purchase" asp-antiforgery="false" asp-route-appId="@appId">
|
||||
<input type="hidden" asp-for="AccessCode" value="@accessCode"/>
|
||||
<div class="row g-2 justify-content-center mb-4" id="ticket-form-container">
|
||||
@@ -122,7 +74,6 @@ document.addEventListener("DOMContentLoaded", ()=>{
|
||||
<div class="bg-tile w-100 p-4 mb-2">
|
||||
|
||||
|
||||
|
||||
@if (!string.IsNullOrEmpty(groupedTickets.Key))
|
||||
{
|
||||
var group = Model.Event.TicketGroups.First(ticketGroup => ticketGroup.Id == groupedTickets.Key);
|
||||
@@ -140,25 +91,31 @@ document.addEventListener("DOMContentLoaded", ()=>{
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matched.Price is not null)
|
||||
{
|
||||
item.Price = matched.Price.Value;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(matched.Name))
|
||||
{
|
||||
item.Name = matched.Name;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(matched.Description))
|
||||
{
|
||||
item.Description = matched.Description;
|
||||
}
|
||||
|
||||
availableToShow = true;
|
||||
specific = true;
|
||||
}
|
||||
|
||||
if (!availableToShow)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
||||
<input type="hidden" asp-for="Items[index].TicketTypeId" value="@item.Id"/>
|
||||
@@ -200,7 +157,6 @@ document.addEventListener("DOMContentLoaded", ()=>{
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -221,14 +177,18 @@ document.addEventListener("DOMContentLoaded", ()=>{
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</main>
|
||||
|
||||
<div class="row text-center">
|
||||
<div class="col-12" id="fiat-page-link">
|
||||
<footer class="store-footer">
|
||||
<p >
|
||||
<a href="@Model.Event.Url">Back to fiat ticket page</a>
|
||||
</p>
|
||||
<a class="store-powered-by" href="https://btcpayserver.org" target="_blank" rel="noreferrer noopener">
|
||||
Powered by <partial name="_StoreFooterLogo"/>
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="powered__by__btcpayserver col-12">
|
||||
Powered by <a target="_blank" href="https://github.com/btcpayserver/btcpayserver" rel="noreferrer noopener">BTCPay Server</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<partial name="LayoutFoot"/>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user