mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-18 13:26:47 +01:00
Editor: Use offcanvas for all breakpoints (#6441)
Avoids scrolling the editor out of the viewport. Closes #6436. Done for the POS/Crowdfund editor, as well as the Forms one.
This commit is contained in:
parent
341bea48f8
commit
a8d1f55544
@ -1240,15 +1240,17 @@ namespace BTCPayServer.Tests
|
|||||||
s.Driver.FindElement(By.Id("Title")).SendKeys("Tea shop");
|
s.Driver.FindElement(By.Id("Title")).SendKeys("Tea shop");
|
||||||
s.Driver.FindElement(By.CssSelector("label[for='DefaultView_Cart']")).Click();
|
s.Driver.FindElement(By.CssSelector("label[for='DefaultView_Cart']")).Click();
|
||||||
s.Driver.FindElement(By.CssSelector(".template-item:nth-of-type(1)")).Click();
|
s.Driver.FindElement(By.CssSelector(".template-item:nth-of-type(1)")).Click();
|
||||||
|
s.Driver.WaitUntilAvailable(By.Id("BuyButtonText"));
|
||||||
s.Driver.FindElement(By.Id("BuyButtonText")).SendKeys("Take my money");
|
s.Driver.FindElement(By.Id("BuyButtonText")).SendKeys("Take my money");
|
||||||
s.Driver.FindElement(By.Id("EditorCategories-ts-control")).SendKeys("Drinks");
|
s.Driver.FindElement(By.Id("EditorCategories-ts-control")).SendKeys("Drinks");
|
||||||
|
s.Driver.FindElement(By.CssSelector(".offcanvas-header button")).Click();
|
||||||
|
s.Driver.WaitUntilAvailable(By.Id("CodeTabButton"));
|
||||||
s.Driver.ScrollTo(By.Id("CodeTabButton"));
|
s.Driver.ScrollTo(By.Id("CodeTabButton"));
|
||||||
s.Driver.FindElement(By.Id("CodeTabButton")).Click();
|
s.Driver.FindElement(By.Id("CodeTabButton")).Click();
|
||||||
var template = s.Driver.FindElement(By.Id("TemplateConfig")).GetAttribute("value");
|
var template = s.Driver.FindElement(By.Id("TemplateConfig")).GetAttribute("value");
|
||||||
Assert.Contains("\"buyButtonText\": \"Take my money\"", template);
|
Assert.Contains("\"buyButtonText\": \"Take my money\"", template);
|
||||||
Assert.Matches("\"categories\": \\[\r?\n\\s*\"Drinks\"\\s*\\]", template);
|
Assert.Matches("\"categories\": \\[\r?\n\\s*\"Drinks\"\\s*\\]", template);
|
||||||
|
|
||||||
|
|
||||||
s.ClickPagePrimary();
|
s.ClickPagePrimary();
|
||||||
Assert.Contains("App updated", s.FindAlertMessage().Text);
|
Assert.Contains("App updated", s.FindAlertMessage().Text);
|
||||||
|
|
||||||
@ -1453,12 +1455,15 @@ namespace BTCPayServer.Tests
|
|||||||
s.GoToUrl(editUrl);
|
s.GoToUrl(editUrl);
|
||||||
s.Driver.ScrollTo(By.Id("btAddItem"));
|
s.Driver.ScrollTo(By.Id("btAddItem"));
|
||||||
s.Driver.FindElement(By.Id("btAddItem")).Click();
|
s.Driver.FindElement(By.Id("btAddItem")).Click();
|
||||||
|
s.Driver.WaitUntilAvailable(By.Id("EditorTitle"));
|
||||||
s.Driver.FindElement(By.Id("EditorTitle")).SendKeys("Perk 1");
|
s.Driver.FindElement(By.Id("EditorTitle")).SendKeys("Perk 1");
|
||||||
s.Driver.FindElement(By.Id("EditorAmount")).SendKeys("20");
|
s.Driver.FindElement(By.Id("EditorAmount")).SendKeys("20");
|
||||||
// Test autogenerated ID
|
// Test autogenerated ID
|
||||||
Assert.Equal("perk-1", s.Driver.FindElement(By.Id("EditorId")).GetAttribute("value"));
|
Assert.Equal("perk-1", s.Driver.FindElement(By.Id("EditorId")).GetAttribute("value"));
|
||||||
s.Driver.FindElement(By.Id("EditorId")).Clear();
|
s.Driver.FindElement(By.Id("EditorId")).Clear();
|
||||||
s.Driver.FindElement(By.Id("EditorId")).SendKeys("Perk-1");
|
s.Driver.FindElement(By.Id("EditorId")).SendKeys("Perk-1");
|
||||||
|
s.Driver.FindElement(By.CssSelector(".offcanvas-header button")).Click();
|
||||||
|
s.Driver.WaitUntilAvailable(By.Id("CodeTabButton"));
|
||||||
s.Driver.ScrollTo(By.Id("CodeTabButton"));
|
s.Driver.ScrollTo(By.Id("CodeTabButton"));
|
||||||
s.Driver.FindElement(By.Id("CodeTabButton")).Click();
|
s.Driver.FindElement(By.Id("CodeTabButton")).Click();
|
||||||
var template = s.Driver.FindElement(By.Id("TemplateConfig")).GetAttribute("value");
|
var template = s.Driver.FindElement(By.Id("TemplateConfig")).GetAttribute("value");
|
||||||
|
@ -54,70 +54,66 @@
|
|||||||
{
|
{
|
||||||
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
|
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
|
||||||
}
|
}
|
||||||
<div class="row">
|
<div class="row" style="max-width:540px;">
|
||||||
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
|
<div class="col-sm-6">
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="AppName" class="form-label" data-required></label>
|
|
||||||
<input asp-for="AppName" class="form-control" required />
|
|
||||||
<span asp-validation-for="AppName" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="Title" class="form-label" data-required></label>
|
|
||||||
<input asp-for="Title" class="form-control" required />
|
|
||||||
<span asp-validation-for="Title" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Tagline" class="form-label"></label>
|
<label asp-for="AppName" class="form-label" data-required></label>
|
||||||
<input asp-for="Tagline" class="form-control" />
|
<input asp-for="AppName" class="form-control" required />
|
||||||
<span asp-validation-for="Tagline" class="text-danger"></span>
|
<span asp-validation-for="AppName" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="d-flex align-items-center justify-content-between gap-2">
|
<label asp-for="Title" class="form-label" data-required></label>
|
||||||
<label asp-for="MainImageFile" class="form-label"></label>
|
<input asp-for="Title" class="form-control" required />
|
||||||
|
<span asp-validation-for="Title" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="Tagline" class="form-label"></label>
|
||||||
|
<input asp-for="Tagline" class="form-control" />
|
||||||
|
<span asp-validation-for="Tagline" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="d-flex align-items-center justify-content-between gap-2">
|
||||||
|
<label asp-for="MainImageFile" class="form-label"></label>
|
||||||
|
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||||
|
{
|
||||||
|
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
||||||
|
<vc:icon symbol="cross" /> <span text-translate="true">Remove</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
@if (canUpload)
|
||||||
|
{
|
||||||
|
<div class="d-flex align-items-center gap-3">
|
||||||
|
<input asp-for="MainImageFile" type="file" class="form-control flex-grow">
|
||||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
||||||
{
|
{
|
||||||
<button type="submit" class="btn btn-link p-0 text-danger" name="RemoveLogoFile" value="true">
|
<img src="@Model.MainImageUrl" alt="Logo" style="height:2.1rem;max-width:10.5rem;" />
|
||||||
<vc:icon symbol="cross" /> <span text-translate="true">Remove</span>
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@if (canUpload)
|
<span asp-validation-for="MainImageFile" class="text-danger"></span>
|
||||||
{
|
}
|
||||||
<div class="d-flex align-items-center gap-3">
|
else
|
||||||
<input asp-for="MainImageFile" type="file" class="form-control flex-grow">
|
{
|
||||||
@if (!string.IsNullOrEmpty(Model.MainImageUrl))
|
<input asp-for="MainImageFile" type="file" class="form-control" disabled>
|
||||||
{
|
<div class="form-text">@ViewLocalizer["In order to upload, a {0} must be configured.", Html.ActionLink(StringLocalizer["file storage"], "Files", "UIServer")]</div>
|
||||||
<img src="@Model.MainImageUrl" alt="Logo" style="height:2.1rem;max-width:10.5rem;" />
|
}
|
||||||
}
|
</div>
|
||||||
</div>
|
<div class="form-group">
|
||||||
<span asp-validation-for="MainImageFile" class="text-danger"></span>
|
<div class="d-flex align-items-center">
|
||||||
}
|
<input asp-for="Enabled" type="checkbox" class="btcpay-toggle me-3"/>
|
||||||
else
|
<div>
|
||||||
{
|
<label asp-for="Enabled" class="form-check-label"></label>
|
||||||
<input asp-for="MainImageFile" type="file" class="form-control" disabled>
|
<span asp-validation-for="Enabled" class="text-danger"></span>
|
||||||
<div class="form-text">@ViewLocalizer["In order to upload, a {0} must be configured.", Html.ActionLink(StringLocalizer["file storage"], "Files", "UIServer")]</div>
|
<div class="text-muted" text-translate="true">The crowdfund will be visible to anyone.</div>
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="d-flex align-items-center">
|
|
||||||
<input asp-for="Enabled" type="checkbox" class="btcpay-toggle me-3"/>
|
|
||||||
<div>
|
|
||||||
<label asp-for="Enabled" class="form-check-label"></label>
|
|
||||||
<span asp-validation-for="Enabled" class="text-danger"></span>
|
|
||||||
<div class="text-muted" text-translate="true">The crowdfund will be visible to anyone.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-xl-10 col-xxl-constrain">
|
<div class="col-xxl-constrain">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="Description" class="form-label" data-required></label>
|
<label asp-for="Description" class="form-label" data-required></label>
|
||||||
<textarea asp-for="Description" rows="20" cols="40" class="form-control richtext"></textarea>
|
<textarea asp-for="Description" rows="20" cols="40" class="form-control richtext"></textarea>
|
||||||
|
@ -58,47 +58,43 @@
|
|||||||
{
|
{
|
||||||
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
|
<div asp-validation-summary="All" class="@(ViewContext.ModelState.ErrorCount.Equals(1) ? "no-marker" : "")"></div>
|
||||||
}
|
}
|
||||||
<div class="row">
|
<div class="row" style="max-width:540px;">
|
||||||
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
|
<div class="col-sm-6">
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="AppName" class="form-label" data-required></label>
|
|
||||||
<input asp-for="AppName" class="form-control" required />
|
|
||||||
<span asp-validation-for="AppName" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="form-group">
|
|
||||||
<label asp-for="Title" class="form-label" data-required></label>
|
|
||||||
<input asp-for="Title" class="form-control" required />
|
|
||||||
<span asp-validation-for="Title" class="text-danger"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label asp-for="DefaultView" class="form-label" data-required text-translate="true">Choose Point of Sale Style</label>
|
<label asp-for="AppName" class="form-label" data-required></label>
|
||||||
<div class="btcpay-list-select">
|
<input asp-for="AppName" class="form-control" required />
|
||||||
@foreach (var type in Enum.GetValues<PosViewType>())
|
<span asp-validation-for="AppName" class="text-danger"></span>
|
||||||
{
|
|
||||||
<input type="radio" asp-for="DefaultView" value="@type" id="DefaultView_@type">
|
|
||||||
<label for="DefaultView_@type" class="btcpay-list-select-item">
|
|
||||||
<vc:icon symbol="pos-@type.ToString().ToLowerInvariant()" />
|
|
||||||
@typeof(PosViewType).DisplayName(type.ToString())
|
|
||||||
</label>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-0">
|
</div>
|
||||||
<label asp-for="Currency" class="form-label"></label>
|
<div class="col-sm-6">
|
||||||
<input asp-for="Currency" class="form-control w-auto" currency-selection />
|
<div class="form-group">
|
||||||
<div class="form-text">@StringLocalizer["Uses the store's default currency ({0}) if empty.", Model.StoreDefaultCurrency]</div>
|
<label asp-for="Title" class="form-label" data-required></label>
|
||||||
<span asp-validation-for="Currency" class="text-danger"></span>
|
<input asp-for="Title" class="form-control" required />
|
||||||
|
<span asp-validation-for="Title" class="text-danger"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label asp-for="DefaultView" class="form-label" data-required text-translate="true">Choose Point of Sale Style</label>
|
||||||
|
<div class="btcpay-list-select">
|
||||||
|
@foreach (var type in Enum.GetValues<PosViewType>())
|
||||||
|
{
|
||||||
|
<input type="radio" asp-for="DefaultView" value="@type" id="DefaultView_@type">
|
||||||
|
<label for="DefaultView_@type" class="btcpay-list-select-item">
|
||||||
|
<vc:icon symbol="pos-@type.ToString().ToLowerInvariant()" />
|
||||||
|
@typeof(PosViewType).DisplayName(type.ToString())
|
||||||
|
</label>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<label asp-for="Currency" class="form-label"></label>
|
||||||
|
<input asp-for="Currency" class="form-control w-auto" currency-selection />
|
||||||
|
<div class="form-text">@StringLocalizer["Uses the store's default currency ({0}) if empty.", Model.StoreDefaultCurrency]</div>
|
||||||
|
<span asp-validation-for="Currency" class="text-danger"></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="description" class="row mt-4">
|
<div id="description" class="row mt-4">
|
||||||
<div class="col-xl-10 col-xxl-constrain">
|
<div class="col-xxl-constrain">
|
||||||
<div class="form-group mb-0">
|
<div class="form-group mb-0">
|
||||||
<label asp-for="Description" class="form-label"></label>
|
<label asp-for="Description" class="form-label"></label>
|
||||||
<textarea asp-for="Description" rows="10" cols="40" class="form-control richtext"></textarea>
|
<textarea asp-for="Description" rows="10" cols="40" class="form-control richtext"></textarea>
|
||||||
|
@ -139,7 +139,7 @@
|
|||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
|
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
|
||||||
<div class="row align-items-start">
|
<div class="row align-items-start">
|
||||||
<div class="col-12 col-xl-7">
|
<div class="col-12">
|
||||||
<items-editor :items="items"
|
<items-editor :items="items"
|
||||||
:selected-item="selectedItem"
|
:selected-item="selectedItem"
|
||||||
v-on:add-item="addItem"
|
v-on:add-item="addItem"
|
||||||
@ -149,13 +149,13 @@
|
|||||||
:class="{ 'pt-2': (!items || items.length === 0) }"
|
:class="{ 'pt-2': (!items || items.length === 0) }"
|
||||||
class="bg-tile pb-2 rounded" />
|
class="bg-tile pb-2 rounded" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
<div class="offcanvas offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
||||||
<div class="offcanvas-header justify-content-between p-3">
|
<div class="offcanvas-header justify-content-between p-3">
|
||||||
<h5 class="offcanvas-title" text-translate="true">Edit Item</h5>
|
<h5 class="offcanvas-title" text-translate="true">Edit Item</h5>
|
||||||
<button type="button" class="btn btn-sm rounded-pill" :class="{ 'btn-primary': itemChanged, 'btn-outline-secondary': !itemChanged }" v-on:click="hideOffcanvas" v-text="itemChanged ? 'Apply' : 'Close'"></button>
|
<button type="button" class="btn btn-sm rounded-pill" :class="{ 'btn-primary': itemChanged, 'btn-outline-secondary': !itemChanged }" v-on:click="hideOffcanvas" v-text="itemChanged ? 'Apply' : 'Close'"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="offcanvas-body p-3 p-xl-0">
|
<div class="offcanvas-body p-3">
|
||||||
<item-editor ref="itemEditor" :item="selectedItem" class="bg-tile w-100 p-xl-4 rounded" />
|
<item-editor ref="itemEditor" :item="selectedItem" class="bg-tile w-100 rounded" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -236,7 +236,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="FormEditor" class="editor">
|
<div id="FormEditor" class="editor col-xxl-constrain">
|
||||||
<div class="d-flex flex-wrap align-items-end justify-content-between gap-3 mb-3">
|
<div class="d-flex flex-wrap align-items-end justify-content-between gap-3 mb-3">
|
||||||
<ul class="nav nav-pills gap-4" role="tablist">
|
<ul class="nav nav-pills gap-4" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
@ -255,7 +255,7 @@
|
|||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
|
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
|
||||||
<div class="row align-items-start">
|
<div class="row align-items-start">
|
||||||
<div class="col-12 col-xl-7">
|
<div class="col-12">
|
||||||
<fields-editor :path="[]"
|
<fields-editor :path="[]"
|
||||||
:fields="fields"
|
:fields="fields"
|
||||||
:selected-field="selectedField"
|
:selected-field="selectedField"
|
||||||
@ -266,15 +266,15 @@
|
|||||||
:class="{ 'pt-2': (!fields || fields.length === 0) }"
|
:class="{ 'pt-2': (!fields || fields.length === 0) }"
|
||||||
class="bg-tile pb-2 rounded" />
|
class="bg-tile pb-2 rounded" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
<div class="offcanvas offcanvas-end" tabindex="-1" ref="editorOffcanvas">
|
||||||
<div class="offcanvas-header justify-content-between p-3">
|
<div class="offcanvas-header justify-content-between p-3">
|
||||||
<h5 class="offcanvas-title" text-translate="true">Edit Field</h5>
|
<h5 class="offcanvas-title" text-translate="true">Edit Field</h5>
|
||||||
<button type="button" class="btn-close" aria-label="@StringLocalizer["Close"]" v-on:click="hideOffcanvas">
|
<button type="button" class="btn-close" aria-label="@StringLocalizer["Close"]" v-on:click="hideOffcanvas">
|
||||||
<vc:icon symbol="close" />
|
<vc:icon symbol="close" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="offcanvas-body p-3 p-xl-0">
|
<div class="offcanvas-body p-3">
|
||||||
<field-editor :field="selectedField" class="bg-tile w-100 p-xl-4 rounded" />
|
<field-editor :field="selectedField" class="bg-tile w-100 rounded" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user