|
|
@@ -11,6 +11,58 @@
|
|
|
<!-- Left Panel -->
|
|
|
<div class="flex flex-1 flex-col gap-2 max-xl:flex-auto">
|
|
|
<div class="box-shadow rounded bg-white p-4 dark:bg-gray-900">
|
|
|
+ <!-- Column Labels Config -->
|
|
|
+ <div class="mb-4 grid gap-2 border-b border-slate-200 pb-4 dark:border-gray-800">
|
|
|
+ <div class="flex items-center justify-between gap-x-2.5">
|
|
|
+ <p class="text-base font-semibold text-gray-800 dark:text-white">
|
|
|
+ @lang('admin::app.settings.themes.edit.column-labels')
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <!-- Add Column Button -->
|
|
|
+ <div
|
|
|
+ class="secondary-button"
|
|
|
+ @click="addColumn"
|
|
|
+ >
|
|
|
+ @lang('admin::app.settings.themes.edit.add-column')
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <input
|
|
|
+ type="hidden"
|
|
|
+ v-for="columnKey in columnKeys"
|
|
|
+ :key="'hidden-column-label-' + columnKey"
|
|
|
+ :name="'{{ $currentLocale->code }}[options][column_labels][' + columnKey + ']'"
|
|
|
+ :value="columnLabels[columnKey] ?? ''"
|
|
|
+ />
|
|
|
+
|
|
|
+ <div
|
|
|
+ class="grid gap-1"
|
|
|
+ v-for="(columnKey, index) in columnKeys"
|
|
|
+ :key="'column-label-' + columnKey"
|
|
|
+ >
|
|
|
+ <div class="flex items-center justify-between gap-x-2.5">
|
|
|
+ <label class="text-xs font-medium text-gray-500 dark:text-gray-300">
|
|
|
+ @lang('admin::app.settings.themes.edit.column') @{{ index + 1 }}
|
|
|
+ </label>
|
|
|
+
|
|
|
+ <p
|
|
|
+ class="cursor-pointer text-red-600 transition-all hover:underline"
|
|
|
+ v-if="columnKeys.length > 1"
|
|
|
+ @click="removeColumn(columnKey)"
|
|
|
+ >
|
|
|
+ @lang('admin::app.settings.themes.edit.delete')
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ class="w-full rounded-lg border border-gray-300 bg-white px-3 py-2 text-sm text-gray-800 transition-all focus:border-gray-400 focus:ring-0 dark:border-gray-800 dark:bg-gray-900 dark:text-white"
|
|
|
+ v-model="columnLabels[columnKey]"
|
|
|
+ :placeholder="'@lang('admin::app.settings.themes.edit.column') ' + (index + 1)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- Add Links-->
|
|
|
<div class="mb-2.5 flex items-center justify-between gap-x-2.5">
|
|
|
<div class="flex flex-col gap-1">
|
|
|
@@ -190,9 +242,13 @@
|
|
|
:placeholder="trans('admin::app.settings.themes.edit.column')"
|
|
|
::disabled="isUpdating"
|
|
|
>
|
|
|
- <option value="column_1">1</option>
|
|
|
- <option value="column_2">2</option>
|
|
|
- <option value="column_3">3</option>
|
|
|
+ <option
|
|
|
+ v-for="(columnKey, index) in columnKeys"
|
|
|
+ :key="'option-' + columnKey"
|
|
|
+ :value="columnKey"
|
|
|
+ >
|
|
|
+ @{{ columnLabels[columnKey] || (index + 1) }}
|
|
|
+ </option>
|
|
|
</x-admin::form.control-group.control>
|
|
|
|
|
|
<x-admin::form.control-group.error control-name="column" />
|
|
|
@@ -272,8 +328,35 @@
|
|
|
props: ['errors'],
|
|
|
|
|
|
data() {
|
|
|
+ const options = @json($theme->translate($currentLocale->code)['options'] ?? null) ?? {};
|
|
|
+
|
|
|
+ const links = { ...options };
|
|
|
+
|
|
|
+ delete links.column_labels;
|
|
|
+
|
|
|
+ const columnLabels = options.column_labels ?? {};
|
|
|
+
|
|
|
+ // Ensure every link group has a column label entry.
|
|
|
+ Object.keys(links).forEach((key) => {
|
|
|
+ links[key] = (links[key] ?? []).map((item) => ({
|
|
|
+ ...item,
|
|
|
+ column: key,
|
|
|
+ }));
|
|
|
+
|
|
|
+ if (columnLabels[key] === undefined) {
|
|
|
+ columnLabels[key] = '';
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // At least one column by default.
|
|
|
+ if (Object.keys(columnLabels).length === 0) {
|
|
|
+ columnLabels.column_1 = '';
|
|
|
+ }
|
|
|
+
|
|
|
return {
|
|
|
- footerLinks: @json($theme->translate($currentLocale->code)['options'] ?? null),
|
|
|
+ footerLinks: links,
|
|
|
+
|
|
|
+ columnLabels,
|
|
|
|
|
|
isUpdating: false,
|
|
|
};
|
|
|
@@ -283,28 +366,48 @@
|
|
|
isFooterLinksEmpty() {
|
|
|
return Object.values(this.footerLinks).every(column => column.length === 0);
|
|
|
},
|
|
|
- },
|
|
|
|
|
|
- created() {
|
|
|
- if (this.footerLinks === null) {
|
|
|
- this.footerLinks = {};
|
|
|
- }
|
|
|
+ columnKeys() {
|
|
|
+ const keys = new Set([
|
|
|
+ ...Object.keys(this.columnLabels),
|
|
|
+ ...Object.keys(this.footerLinks),
|
|
|
+ ]);
|
|
|
|
|
|
- for (let i = 1; i <= 3; i++) {
|
|
|
- if (!this.footerLinks.hasOwnProperty(`column_${i}`)) {
|
|
|
- this.footerLinks[`column_${i}`] = [];
|
|
|
- }
|
|
|
- }
|
|
|
+ return [...keys].sort((a, b) => {
|
|
|
+ const numA = parseInt((a.match(/column_(\d+)/) ?? [])[1] ?? 0, 10);
|
|
|
+ const numB = parseInt((b.match(/column_(\d+)/) ?? [])[1] ?? 0, 10);
|
|
|
|
|
|
- Object.keys(this.footerLinks).forEach(key => {
|
|
|
- this.footerLinks[key] = this.footerLinks[key].map(item => ({
|
|
|
- ...item,
|
|
|
- column: key
|
|
|
- }));
|
|
|
- });
|
|
|
+ return numA - numB;
|
|
|
+ });
|
|
|
+ },
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
+ addColumn() {
|
|
|
+ let index = 1;
|
|
|
+
|
|
|
+ while (
|
|
|
+ this.columnLabels.hasOwnProperty(`column_${index}`)
|
|
|
+ || this.footerLinks.hasOwnProperty(`column_${index}`)
|
|
|
+ ) {
|
|
|
+ index++;
|
|
|
+ }
|
|
|
+
|
|
|
+ const key = `column_${index}`;
|
|
|
+
|
|
|
+ this.columnLabels[key] = '';
|
|
|
+ this.footerLinks[key] = [];
|
|
|
+ },
|
|
|
+
|
|
|
+ removeColumn(columnKey) {
|
|
|
+ this.$emitter.emit('open-confirm-modal', {
|
|
|
+ agree: () => {
|
|
|
+ delete this.columnLabels[columnKey];
|
|
|
+ delete this.footerLinks[columnKey];
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
updateOrCreate(params) {
|
|
|
if (params.key != null) {
|
|
|
Object.keys(this.footerLinks).forEach(key => {
|