mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Updates Crowdfund & POS Modal (#3806)
* ui+cf: updates perks modal * Toggle editor with Bootstrap * Add currency info to app items Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
parent
cade6c6c38
commit
c531b26821
7 changed files with 107 additions and 88 deletions
|
@ -25,7 +25,7 @@ namespace BTCPayServer.Controllers
|
|||
|
||||
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Cookie)]
|
||||
[HttpGet("{appId}/settings/crowdfund")]
|
||||
public IActionResult UpdateCrowdfund(string appId)
|
||||
public async Task<IActionResult> UpdateCrowdfund(string appId)
|
||||
{
|
||||
var app = GetCurrentApp();
|
||||
if (app == null)
|
||||
|
@ -37,6 +37,7 @@ namespace BTCPayServer.Controllers
|
|||
Title = settings.Title,
|
||||
StoreId = app.StoreDataId,
|
||||
StoreName = app.StoreData?.StoreName,
|
||||
StoreDefaultCurrency = await GetStoreDefaultCurrentIfEmpty(app.StoreDataId, settings.TargetCurrency),
|
||||
AppName = app.Name,
|
||||
Enabled = settings.Enabled,
|
||||
EnforceTargetAmount = settings.EnforceTargetAmount,
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace BTCPayServer.Controllers
|
|||
public partial class UIAppsController
|
||||
{
|
||||
[HttpGet("{appId}/settings/pos")]
|
||||
public IActionResult UpdatePointOfSale(string appId)
|
||||
public async Task<IActionResult> UpdatePointOfSale(string appId)
|
||||
{
|
||||
var app = GetCurrentApp();
|
||||
if (app == null)
|
||||
|
@ -25,11 +25,13 @@ namespace BTCPayServer.Controllers
|
|||
var settings = app.GetSettings<PointOfSaleSettings>();
|
||||
settings.DefaultView = settings.EnableShoppingCart ? PosViewType.Cart : settings.DefaultView;
|
||||
settings.EnableShoppingCart = false;
|
||||
|
||||
var vm = new UpdatePointOfSaleViewModel
|
||||
{
|
||||
Id = appId,
|
||||
StoreId = app.StoreDataId,
|
||||
StoreName = app.StoreData?.StoreName,
|
||||
StoreDefaultCurrency = await GetStoreDefaultCurrentIfEmpty(app.StoreDataId, settings.Currency),
|
||||
AppName = app.Name,
|
||||
Title = settings.Title,
|
||||
DefaultView = settings.DefaultView,
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace BTCPayServer.Models.AppViewModels
|
|||
{
|
||||
public string StoreId { get; set; }
|
||||
public string StoreName { get; set; }
|
||||
public string StoreDefaultCurrency { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace BTCPayServer.Models.AppViewModels
|
|||
{
|
||||
public string StoreId { get; set; }
|
||||
public string StoreName { get; set; }
|
||||
public string StoreDefaultCurrency { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@model (string templateId, string title)
|
||||
@model (string templateId, string title, string currency)
|
||||
|
||||
<div id="template-editor-app" v-cloak>
|
||||
<div class="form-group mb-0">
|
||||
<h3 class="mt-5 mb-4">@Model.title </h3>
|
||||
<h3 class="mt-5 mb-4">@Model.title</h3>
|
||||
@if (ViewContext.ViewData.ModelState.TryGetValue(Model.templateId, out var errors))
|
||||
{
|
||||
foreach (var error in errors.Errors)
|
||||
|
@ -37,7 +37,7 @@
|
|||
<button type="button" class="btn btn-primary" v-on:click="editItem(-1)" id="btn-add">
|
||||
<i class="fa fa-plus fa-fw"></i> Add
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" v-on:click="toggleTemplateElement()" id="ToggleRawEditor">
|
||||
<button type="button" class="btn btn-secondary" id="ToggleRawEditor" data-bs-toggle="collapse" data-bs-target="#RawEditor" aria-expanded="false" aria-controls="RawEditor">
|
||||
Toggle raw editor
|
||||
</button>
|
||||
</div>
|
||||
|
@ -46,7 +46,7 @@
|
|||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" v-if="editingItem">{{editingItem.index>=0? "Edit" : "Create"}} item</h5>
|
||||
<h5 class="modal-title" v-if="editingItem">{{editingItem.index>=0? "Edit" : "Add"}} Item</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" ref="close">
|
||||
<vc:icon symbol="close"/>
|
||||
</button>
|
||||
|
@ -54,60 +54,69 @@
|
|||
<div class="modal-body" v-if="editingItem">
|
||||
<div class="mb-3">
|
||||
<span class="text-danger row m-2" v-for="error of errors">{{error}}</span>
|
||||
<div class="form-group">
|
||||
<label class="form-label" data-required>Title</label>
|
||||
<input type="text" required pattern="[^\*#]+" class="form-control mb-2" v-model="editingItem.title" autofocus ref="txtTitle" />
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-6">
|
||||
<label class="form-label" data-required>Title</label>
|
||||
<input type="text" required pattern="[^\*#]+" class="form-control mb-2" v-model="editingItem.title" autofocus ref="txtTitle"/>
|
||||
</div>
|
||||
<div class="col-sm-3 px-0">
|
||||
<label class="form-label">Price</label>
|
||||
<select class="form-select" v-model="editingItem.custom">
|
||||
<option v-for="option in customPriceOptions" :value="option.value">{{option.text}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3" v-show="editingItem.custom !== 'topup'">
|
||||
|
||||
<label class="form-label"> </label>
|
||||
<input class="form-control mb-2"
|
||||
inputmode="decimal"
|
||||
pattern="\d*"
|
||||
step="any"
|
||||
min="0"
|
||||
type="number"
|
||||
required
|
||||
v-model="editingItem.price" ref="txtPrice"/>
|
||||
<div class="col-sm-6" v-show="editingItem.custom !== 'topup'">
|
||||
<label class="form-label"> </label>
|
||||
<div class="input-group mb-2">
|
||||
<input class="form-control"
|
||||
inputmode="decimal"
|
||||
pattern="\d*"
|
||||
step="any"
|
||||
min="0"
|
||||
type="number"
|
||||
required
|
||||
v-model="editingItem.price"
|
||||
ref="txtPrice"
|
||||
aria-describedby="currency-addon"/>
|
||||
<span class="input-group-text" id="currency-addon">@Model.currency</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Image</label>
|
||||
<input type="text" class="form-control mb-2" pattern="[^\*#]+" v-model="editingItem.image" ref="txtImage"/>
|
||||
<label class="form-label">Image Url</label>
|
||||
<input type="text" class="form-control mb-2" pattern="[^\*#]+" v-model="editingItem.image" ref="txtImage" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea rows="3" cols="40" class="form-control mb-2" v-model="editingItem.description" ref="txtDescription"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Inventory (leave blank to not use inventory feature)</label>
|
||||
<input type="number" inputmode="numeric" min="0" step="1" class="form-control mb-2" v-model="editingItem.inventory" ref="txtInventory"/>
|
||||
<label class="form-label">Inventory</label>
|
||||
<input type="number" inputmode="numeric" min="0" step="1" class="form-control mb-2" v-model="editingItem.inventory" ref="txtInventory" />
|
||||
<p class="form-text text-muted">
|
||||
Leave blank to not use this feature.
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Id (leave blank to generate from title)</label>
|
||||
<input type="text" required pattern="[^\*#]+" class="form-control mb-2" v-model="editingItem.id" ref="txtId"/>
|
||||
<label class="form-label">ID</label>
|
||||
<input type="text" required pattern="[^\*#]+" class="form-control mb-2" v-model="editingItem.id" ref="txtId" />
|
||||
<p class="form-text text-muted">
|
||||
Leave blank to generate ID from title.
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Buy Button Text</label>
|
||||
<input type="text" id="BuyButtonText" class="form-control mb-2" v-model="editingItem.buyButtonText" ref="txtBuyButtonText"/>
|
||||
<input type="text" id="BuyButtonText" class="form-control mb-2" v-model="editingItem.buyButtonText" ref="txtBuyButtonText" />
|
||||
</div>
|
||||
<div class="form-group d-flex align-items-center">
|
||||
<input type="checkbox" id="Disabled" class="btcpay-toggle me-2" v-model="editingItem.disabled"/>
|
||||
<input type="checkbox" id="Disabled" class="btcpay-toggle me-3" v-model="editingItem.disabled" />
|
||||
<label class="form-label mb-0">Disabled</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" v-on:click="clearEditingItem()">Close</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click="saveEditingItem()" id="SaveItemChanges">Save Changes</button>
|
||||
<button type="button" class="btn btn-primary" v-on:click="saveEditingItem()" id="SaveItemChanges">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -139,12 +148,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||
this.loadYml();
|
||||
this.getInputElement().on("input change", this.loadYml.bind(this));
|
||||
this.getModalElement().on("hide.bs.modal", this.clearEditingItem.bind(this));
|
||||
this.toggleTemplateElement();
|
||||
},
|
||||
methods: {
|
||||
toggleTemplateElement: function(){
|
||||
this.getInputElement().parent().toggle();
|
||||
},
|
||||
getImage: function(item){
|
||||
var image = this.unEscapeKey(item.image) || "~/img/img-placeholder.svg";
|
||||
var url = image.startsWith("~") ? image.replace('~', window.location.pathname.substring(0, image.indexOf('/apps'))) : image;
|
||||
|
|
|
@ -85,70 +85,74 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="TargetCurrency" class="form-label"></label>
|
||||
<input asp-for="TargetCurrency" class="form-control" placeholder="Use store's default settings" />
|
||||
<input asp-for="TargetCurrency" class="form-control" currency-selection style="max-width:10ch;" />
|
||||
<small class="d-inline-block form-text text-muted">Uses the store's default currency (@Model.StoreDefaultCurrency) if empty.</small>
|
||||
<span asp-validation-for="TargetCurrency" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label asp-for="StartDate" class="form-label"></label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<input type="datetime-local" asp-for="StartDate"
|
||||
value="@(Model.StartDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No start date has been set" />
|
||||
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="StartDate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label asp-for="EndDate" class="form-label"></label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<input type="datetime-local" asp-for="EndDate"
|
||||
value="@(Model.EndDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No end date has been set" />
|
||||
<button class="btn btn-secondary input-group-clear input-group-text" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="EndDate" class="text-danger"></span>
|
||||
<div class="row g-3">
|
||||
<div class="col col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label asp-for="StartDate" class="form-label"></label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<input type="datetime-local" asp-for="StartDate"
|
||||
value="@(Model.StartDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No start date has been set" />
|
||||
<button class="btn btn-secondary input-group-clear" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="StartDate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0" id="ResetRow" hidden="@(Model.StartDate == null)">
|
||||
<label asp-for="ResetEvery" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control" min="0">
|
||||
<select class="form-select" asp-for="ResetEvery">
|
||||
@foreach (var opt in Model.ResetEveryValues)
|
||||
{
|
||||
<option value="@opt">@opt</option>
|
||||
}
|
||||
</select>
|
||||
<div class="col col-12 col-sm-6">
|
||||
<div class="form-group">
|
||||
<label asp-for="EndDate" class="form-label"></label>
|
||||
<div class="input-group flex-nowrap">
|
||||
<input type="datetime-local" asp-for="EndDate"
|
||||
value="@(Model.EndDate?.ToString("u", CultureInfo.InvariantCulture))"
|
||||
class="form-control flatdtpicker"
|
||||
placeholder="No end date has been set" />
|
||||
<button class="btn btn-secondary input-group-clear input-group-text" type="button" title="Clear">
|
||||
<span class="fa fa-times"></span>
|
||||
</button>
|
||||
</div>
|
||||
<span asp-validation-for="EndDate" class="text-danger"></span>
|
||||
</div>
|
||||
<span asp-validation-for="ResetEveryAmount" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0" id="ResetRow" hidden="@(Model.StartDate == null)">
|
||||
<label asp-for="ResetEvery" class="form-label"></label>
|
||||
<div class="input-group">
|
||||
<input type="number" inputmode="numeric" asp-for="ResetEveryAmount" placeholder="Amount" class="form-control" min="0">
|
||||
<select class="form-select" asp-for="ResetEvery">
|
||||
@foreach (var opt in Model.ResetEveryValues)
|
||||
{
|
||||
<option value="@opt">@opt</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<span asp-validation-for="ResetEveryAmount" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xxl-constrain">
|
||||
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), "Perks")" />
|
||||
<div class="col-xl-10 col-xxl-constrain">
|
||||
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), "Perks", Model.TargetCurrency ?? Model.StoreDefaultCurrency)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row collapse" id="RawEditor">
|
||||
<div class="col-xl-10 col-xxl-constrain">
|
||||
<div class="form-group pt-3">
|
||||
<label asp-for="PerksTemplate" class="form-label"></label>
|
||||
<textarea asp-for="PerksTemplate" rows="10" cols="40" class="form-control"></textarea>
|
||||
<span asp-validation-for="PerksTemplate" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-xxl-constrain">
|
||||
<div class="form-group">
|
||||
<label asp-for="PerksTemplate" class="form-label"></label>
|
||||
<textarea asp-for="PerksTemplate" rows="10" cols="40" class="js-product-template form-control"></textarea>
|
||||
<span asp-validation-for="PerksTemplate" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<h3 class="mt-5 mb-4">Contributions</h3>
|
||||
<div class="form-check mb-3">
|
||||
<input asp-for="SortPerksByPopularity" type="checkbox" class="form-check-input" />
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Currency" class="form-label"></label>
|
||||
<input asp-for="Currency" currency-selection class="form-control" placeholder="Use store's default settings" />
|
||||
<input asp-for="Currency" class="form-control" currency-selection style="max-width:10ch;" />
|
||||
<small class="d-inline-block form-text text-muted">Uses the store's default currency (@Model.StoreDefaultCurrency) if empty.</small>
|
||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -50,10 +51,14 @@
|
|||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xxl-constrain">
|
||||
<partial name="TemplateEditor" model="@(nameof(Model.Template), "Products")" />
|
||||
<div class="form-group mb-0">
|
||||
<partial name="TemplateEditor" model="@(nameof(Model.Template), "Products", Model.Currency ?? Model.StoreDefaultCurrency)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row collapse" id="RawEditor">
|
||||
<div class="col-xxl-constrain">
|
||||
<div class="form-group pt-3">
|
||||
<label asp-for="Template" class="form-label"></label>
|
||||
<textarea asp-for="Template" rows="10" cols="40" class="js-product-template form-control"></textarea>
|
||||
<textarea asp-for="Template" rows="10" cols="40" class="form-control"></textarea>
|
||||
<span asp-validation-for="Template" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue