Responsive editor improvements (#5449)

This commit is contained in:
d11n 2023-11-09 10:27:33 +01:00 committed by GitHub
parent c15f02ddbf
commit 2326894a2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 96 additions and 34 deletions

View File

@ -38,6 +38,10 @@
#crowdfund-body-description {
font-size: 16px;
}
.perk.card .card-img-top{
max-height: 210px;
object-fit: scale-down;
}
</style>
<vc:ui-extension-point location="crowdfund-head" model="@Model"></vc:ui-extension-point>
</head>

View File

@ -166,8 +166,10 @@
</div>
</div>
</div>
<div id="perks">
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), Model.PerksTemplate, "Perks", Model.TargetCurrency ?? Model.StoreDefaultCurrency)" />
<div id="perks" class="row">
<div class="col-xxl-constrain">
<partial name="TemplateEditor" model="@(nameof(Model.PerksTemplate), Model.PerksTemplate, "Perks", Model.TargetCurrency ?? Model.StoreDefaultCurrency)" />
</div>
</div>
<div class="row">
<div class="col-xl-8 col-xxl-constrain">
@ -329,10 +331,10 @@
</div>
</form>
<div class="d-flex gap-3 mt-3">
<div class="d-grid d-sm-flex flex-wrap gap-3 mt-3">
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
<form method="post" asp-controller="UIApps" asp-action="ToggleArchive" asp-route-appId="@Model.AppId">
<button type="submit" class="btn btn-outline-secondary" id="btn-archive-toggle">
<button type="submit" class="w-100 btn btn-outline-secondary" id="btn-archive-toggle">
@if (Model.Archived)
{
<span class="text-nowrap">Unarchive this app</span>

View File

@ -93,8 +93,10 @@
</div>
</div>
</div>
<div id="products">
<partial name="TemplateEditor" model="@(nameof(Model.Template), Model.Template, "Products", Model.Currency ?? Model.StoreDefaultCurrency)" />
<div id="products" class="row">
<div class="col-xxl-constrain">
<partial name="TemplateEditor" model="@(nameof(Model.Template), Model.Template, "Products", Model.Currency ?? Model.StoreDefaultCurrency)" />
</div>
</div>
<div class="row mt-5">
<div class="col-sm-10 col-md-9 col-xl-7 col-xxl-6">
@ -282,10 +284,10 @@
</div>
</form>
<div class="d-flex gap-3 mt-3">
<div class="d-grid d-sm-flex flex-wrap gap-3 mt-3">
<a class="btn btn-secondary" asp-action="ListInvoices" asp-controller="UIInvoice" asp-route-storeId="@Model.StoreId" asp-route-searchterm="@Model.SearchTerm">Invoices</a>
<form method="post" asp-controller="UIApps" asp-action="ToggleArchive" asp-route-appId="@Model.Id">
<button type="submit" class="btn btn-outline-secondary" id="btn-archive-toggle">
<button type="submit" class="w-100 btn btn-outline-secondary" id="btn-archive-toggle">
@if (Model.Archived)
{
<span class="text-nowrap">Unarchive this app</span>

View File

@ -76,7 +76,7 @@
</div>
<vc:ui-extension-point location="app-template-editor-item-detail" model="Model"></vc:ui-extension-point>
<div class="text-danger mb-3" v-for="error of errors">{{error}}</div>
<button class="btn btn-primary" type="button" id="ApplyItemChanges" v-on:click="apply">Apply</button>
<button class="btn btn-primary d-none d-xl-inline-block" type="button" id="ApplyItemChanges" v-on:click="apply">Apply</button>
</div>
<div v-if="!editingItem">Select an item to edit</div>
</div>
@ -84,27 +84,28 @@
<template id="items-editor">
<div>
<div class="items list-group list-group-horizontal flex-wrap" v-sortable="{ handle: '.drag', onUpdate (event) { $emit('sort-items', event) } }">
<div v-for="(item, index) of items" class="d-inline-flex align-items-start gap-2 list-group-item" style="flex: 0 1 375px" v-bind:key="item.id" :class="{ active: item === selectedItem }" v-on:click.stop="$emit('select-item', $event, index)">
<div class="items list-group list-group-flush" v-sortable="{ handle: '.drag', onUpdate (event) { $emit('sort-items', event) } }">
<div v-for="(item, index) of items" class="d-inline-flex align-items-center gap-3 list-group-item" :key="item.id" :class="{ active: item === selectedItem }" v-on:click.stop="$emit('select-item', $event, index)">
<button type="button" class="btn b-0 control drag" :disabled="items.length === 1">
<vc:icon symbol="drag" />
</button>
<div class="card template-item bg-transparent w-100 h-100">
<img class="card-img-top" :src="getImage(item)" :alt="item.title" :style="(item.image ? null : { opacity: 0.5 })">
<div class="card-body p-3 d-flex flex-column gap-2">
<div class="template-item d-flex align-items-start w-100 gap-3">
<div class="img">
<img :src="getImage(item)" :alt="item.title" :style="(item.image ? null : { opacity: 0.5 })">
</div>
<div class="d-flex flex-column gap-2">
<h5 class="card-title m-0" v-html="item.title"></h5>
<div class="d-flex gap-2 align-items-center">
<span class="fw-semibold badge text-bg-info" v-if="item.priceType === 'Topup' || item.price == 0">{{ item.priceType === 'Topup' ? 'Any amount' : 'Free' }}</span>
<span class="fw-semibold" v-else>{{ item.price }} @Model.currency{{ item.priceType === 'Minimum' ? ' minimum' : '' }}</span>
<span class="fw-semibold text-muted" v-else>{{ item.price }} @Model.currency{{ item.priceType === 'Minimum' ? ' minimum' : '' }}</span>
<span class="badge text-bg-warning" v-if="item.inventory">
{{ item.inventory > 0 ? `${item.inventory} left` : 'Sold out' }}
</span>
</div>
<p class="card-text" v-if="item.description">{{ item.description }}</p>
</div>
</div>
<button type="button" class="btn b-0 control remove" v-on:click="$emit('remove-item', $event, index)">
<vc:icon symbol="trash" />
<vc:icon symbol="remove" />
</button>
</div>
</div>
@ -138,7 +139,7 @@
<div class="tab-content">
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
<div class="row align-items-start">
<div class="col-lg-7 mb-4 mb-lg-0">
<div class="col-12 col-xl-7">
<items-editor :items="items"
:selected-item="selectedItem"
v-on:add-item="addItem"
@ -148,8 +149,20 @@
:class="{ 'pt-2': (!items || items.length === 0) }"
class="bg-tile pb-2 rounded" />
</div>
<div class="col-lg-5">
<item-editor :item="selectedItem" class="bg-tile p-4 rounded" />
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
<div class="offcanvas-header p-3">
<h5 class="offcanvas-title">Edit Item</h5>
<button type="button" class="btn-close" aria-label="Close" v-on:click="hideOffcanvas">
<vc:icon symbol="close" />
</button>
</div>
<div class="offcanvas-body p-3 p-xl-0">
<item-editor ref="itemEditor" :item="selectedItem" class="bg-tile w-100 p-xl-4 rounded" />
</div>
<div class="offcanvas-header p-3">
<button class="btn btn-primary" type="button" v-on:click="() => { $refs.itemEditor.apply(); hideOffcanvas() }">Apply and close</button>
<button class="btn btn-secondary" type="button" v-on:click="hideOffcanvas">Cancel</button>
</div>
</div>
</div>
</div>

View File

@ -64,7 +64,7 @@
<input :id="`field-option-text-${index}`" class="form-control" v-model="option.text" />
</div>
<button type="button" class="btn b-0 control remove" v-on:click="removeOption($event, index)">
<vc:icon symbol="trash" />
<vc:icon symbol="remove" />
</button>
</div>
</div>
@ -101,7 +101,7 @@
<input :id="`field-valuemap-mapped-${index}`" class="form-control" placeholder="Value to set" :value="v" v-on:change="updateValueMap(k, k, $event.target.value)" />
</div>
<button type="button" class="btn b-0 control remove" v-on:click="removeValueMap($event, k)">
<vc:icon symbol="trash" />
<vc:icon symbol="remove" />
</button>
</div>
</div>
@ -138,7 +138,7 @@
<component :is="getFieldComponent(field.type)" v-bind="field" :path="path.concat(field.name)" :selected-field="selectedField" v-on="$listeners" />
</div>
<button type="button" class="btn b-0 control remove" v-on:click="$emit('remove-field', $event, path, index)">
<vc:icon symbol="trash" />
<vc:icon symbol="remove" />
</button>
</div>
</div>
@ -247,7 +247,7 @@
<div class="tab-content">
<div class="tab-pane fade show active" id="EditorTabPane" role="tabpanel" aria-labelledby="EditorTabButton" tabindex="0">
<div class="row align-items-start">
<div class="col-lg-7 mb-4 mb-lg-0">
<div class="col-12 col-xl-7">
<fields-editor :path="[]"
:fields="fields"
:selected-field="selectedField"
@ -258,8 +258,16 @@
:class="{ 'pt-2': (!fields || fields.length === 0) }"
class="bg-tile pb-2 rounded" />
</div>
<div class="col-lg-5">
<field-editor :field="selectedField" class="bg-tile p-4 rounded" />
<div class="col-xl-5 offcanvas-xl offcanvas-end" tabindex="-1" ref="editorOffcanvas">
<div class="offcanvas-header p-3">
<h5 class="offcanvas-title">Edit Field</h5>
<button type="button" class="btn-close" aria-label="Close" v-on:click="hideOffcanvas">
<vc:icon symbol="close" />
</button>
</div>
<div class="offcanvas-body p-3 p-xl-0">
<field-editor :field="selectedField" class="bg-tile w-100 p-xl-4 rounded" />
</div>
</div>
</div>
</div>

View File

@ -152,7 +152,8 @@ document.addEventListener('DOMContentLoaded', () => {
data () {
return {
config,
selectedField: null
selectedField: null,
editorOffcanvas: null
}
},
computed: {
@ -192,10 +193,12 @@ document.addEventListener('DOMContentLoaded', () => {
const index = fields.length + 1
const length = fields.push({ type: 'text', name: `newField${index}`, label: `New field ${index}`, fields: [], options: [] })
this.selectedField = fields[length - 1]
this.showOffcanvas()
},
selectField(event, path, index) {
const fields = this.getFieldsForPath(path)
this.selectedField = fields[index]
this.showOffcanvas()
},
removeField(event, path, index) {
const fields = this.getFieldsForPath(path)
@ -217,12 +220,20 @@ document.addEventListener('DOMContentLoaded', () => {
fields = field.fields
}
return fields
},
showOffcanvas() {
if (window.getComputedStyle(this.$refs.editorOffcanvas).visibility === 'hidden')
this.editorOffcanvas.show();
},
hideOffcanvas() {
this.editorOffcanvas.hide();
}
},
mounted () {
if (!this.config.fields || this.config.fields.length === 0) {
this.addField(null,[])
}
this.editorOffcanvas = bootstrap.Offcanvas.getOrCreateInstance(this.$refs.editorOffcanvas);
}
})
})

View File

@ -229,7 +229,8 @@ document.addEventListener('DOMContentLoaded', () => {
data () {
return {
items,
selectedItem: null
selectedItem: null,
editorOffcanvas: null
}
},
computed: {
@ -263,9 +264,11 @@ document.addEventListener('DOMContentLoaded', () => {
disabled: false
})
this.selectedItem = this.items[length - 1]
this.showOffcanvas()
},
selectItem(event, index) {
this.selectedItem = this.items[index]
this.showOffcanvas()
},
removeItem(event, index) {
this.items.splice(index, 1)
@ -274,10 +277,18 @@ document.addEventListener('DOMContentLoaded', () => {
sortItems(event) {
const { newIndex, oldIndex } = event
this.items.splice(newIndex, 0, this.items.splice(oldIndex, 1)[0])
},
showOffcanvas() {
if (window.getComputedStyle(this.$refs.editorOffcanvas).visibility === 'hidden')
this.editorOffcanvas.show();
},
hideOffcanvas() {
this.editorOffcanvas.hide();
}
},
mounted() {
if (!this.items) this.items = []
this.editorOffcanvas = bootstrap.Offcanvas.getOrCreateInstance(this.$refs.editorOffcanvas);
}
})
})

View File

@ -1,9 +1,3 @@
.editor .card-img-top {
max-height: 210px;
object-fit: scale-down;
margin-bottom: auto;
}
.editor .nav-pills .nav-link {
background: none;
padding: 0;
@ -20,6 +14,7 @@
}
.editor .list-group-item {
--image-size: 3rem;
border: none;
margin: 0;
padding: var(--btcpay-space-m) var(--btcpay-space-m) var(--btcpay-space-m) var(--btcpay-space-s) !important;
@ -30,6 +25,18 @@
border: 0;
}
.editor .list-group-item .img img {
width: var(--image-size);
height: var(--image-size);
}
.editor .list-group-item .img img {
max-width: var(--image-size);
max-height: var(--image-size);
object-fit: scale-down;
border-radius: var(--btcpay-border-radius);
}
.editor fieldset .list-group-item {
padding: var(--btcpay-space-m) 0 var(--btcpay-space-m);
}
@ -52,6 +59,10 @@
color: var(--btcpay-danger);
}
.editor .control.remove .icon {
--btn-icon-size: 1.75rem;
}
.editor .field .form-group:last-child {
margin-bottom: 0;
}