cinqcinqdev-seo 0.1.24 → 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import { ref, computed, watch, onMounted, definePageMeta, useRoute, useRuntimeConfig, useAsyncData, useHead, useSupabaseClient, useNuxtApp } from "#imports";
|
|
2
|
+
import { ref, computed, watch, onMounted, triggerRef, definePageMeta, useRoute, useRuntimeConfig, useAsyncData, useHead, useSupabaseClient, useNuxtApp } from "#imports";
|
|
3
3
|
import { useAdminSections } from "../../../composables/useAdminSections";
|
|
4
4
|
import { useAdminSettings, useAdminBasePath } from "#imports";
|
|
5
5
|
definePageMeta({ layout: false });
|
|
@@ -15,10 +15,11 @@ const adminSettings = useAdminSettings();
|
|
|
15
15
|
const basePath = useAdminBasePath();
|
|
16
16
|
onMounted(() => adminSettings.load());
|
|
17
17
|
const resolveSection = (type) => vueApp.component(`Sections${type}`) || vueApp.component(type) || null;
|
|
18
|
-
const { data:
|
|
18
|
+
const { data: _rawPage } = await useAsyncData(`admin-edit-${pageId}`, async () => {
|
|
19
19
|
const { data } = await supabase.from(table).select("*").eq("id", pageId).maybeSingle();
|
|
20
20
|
return data;
|
|
21
21
|
});
|
|
22
|
+
const page = ref(_rawPage.value);
|
|
22
23
|
useHead({ title: computed(() => page.value?.title ? `${page.value.title} \u2014 \xC9diteur` : "\xC9diteur \u2014 Admin") });
|
|
23
24
|
const isLeftSidebarOpen = ref(true);
|
|
24
25
|
const isRightSidebarOpen = ref(true);
|
|
@@ -111,12 +112,14 @@ const setI18nProp = (fieldName, lang, newValue) => {
|
|
|
111
112
|
}
|
|
112
113
|
obj[lang] = newValue;
|
|
113
114
|
props[fieldName] = obj;
|
|
115
|
+
triggerRef(page);
|
|
114
116
|
};
|
|
115
117
|
const getI18nVal = (val, lang) => {
|
|
116
118
|
if (!val) return "";
|
|
117
119
|
if (typeof val === "string") return lang === "fr" ? val : "";
|
|
118
120
|
return val[lang] || "";
|
|
119
121
|
};
|
|
122
|
+
const trigger = () => triggerRef(page);
|
|
120
123
|
const setI18nVal = (obj, key, lang, newValue) => {
|
|
121
124
|
const current = obj[key];
|
|
122
125
|
const i18nObj = { fr: "", ar: "", en: "" };
|
|
@@ -127,6 +130,7 @@ const setI18nVal = (obj, key, lang, newValue) => {
|
|
|
127
130
|
}
|
|
128
131
|
i18nObj[lang] = newValue;
|
|
129
132
|
obj[key] = i18nObj;
|
|
133
|
+
triggerRef(page);
|
|
130
134
|
};
|
|
131
135
|
const tagDepth = (tag) => {
|
|
132
136
|
const n = parseInt(tag.replace("h", ""));
|
|
@@ -638,7 +642,8 @@ const savePage = async () => {
|
|
|
638
642
|
<span class="absolute -top-1 right-0 text-[6px] font-black uppercase text-[#3d35ff]/40">{{ langLabel(editingLang) }}</span>
|
|
639
643
|
<input :value="getI18nProp(name, editingLang)" @input="setI18nProp(name, editingLang, $event.target.value)" :dir="editingLang === 'ar' ? 'rtl' : 'ltr'" class="w-full bg-gray-50 rounded-xl p-3 text-[10px] font-bold outline-none ring-1 ring-gray-100 focus:ring-[#3d35ff]" />
|
|
640
644
|
</div>
|
|
641
|
-
<input v-else
|
|
645
|
+
<input v-else :value="page.content[selectedBlockIndex].props[name]" @input="page.content[selectedBlockIndex].props[name] = $event.target.value;
|
|
646
|
+
trigger()" class="w-full bg-gray-50 rounded-xl p-3 text-[10px] font-bold outline-none ring-1 ring-gray-100 focus:ring-[#3d35ff]" />
|
|
642
647
|
</template>
|
|
643
648
|
|
|
644
649
|
<!-- Textarea i18n -->
|
|
@@ -647,18 +652,21 @@ const savePage = async () => {
|
|
|
647
652
|
<span class="absolute -top-1 right-0 text-[6px] font-black uppercase text-[#3d35ff]/40">{{ langLabel(editingLang) }}</span>
|
|
648
653
|
<textarea :value="getI18nProp(name, editingLang)" @input="setI18nProp(name, editingLang, $event.target.value)" :dir="editingLang === 'ar' ? 'rtl' : 'ltr'" rows="3" class="w-full bg-gray-50 rounded-xl p-3 text-[10px] outline-none ring-1 ring-gray-100 focus:ring-[#3d35ff]"></textarea>
|
|
649
654
|
</div>
|
|
650
|
-
<textarea v-else
|
|
655
|
+
<textarea v-else :value="page.content[selectedBlockIndex].props[name]" @input="page.content[selectedBlockIndex].props[name] = $event.target.value;
|
|
656
|
+
trigger()" rows="3" class="w-full bg-gray-50 rounded-xl p-3 text-[10px] outline-none ring-1 ring-gray-100"></textarea>
|
|
651
657
|
</template>
|
|
652
658
|
|
|
653
659
|
<!-- Select -->
|
|
654
|
-
<select v-else-if="field.type === 'select'"
|
|
660
|
+
<select v-else-if="field.type === 'select'" :value="page.content[selectedBlockIndex].props[name]" @change="page.content[selectedBlockIndex].props[name] = $event.target.value;
|
|
661
|
+
trigger()" class="w-full bg-gray-50 rounded-xl p-3 text-[10px] font-bold ring-1 ring-gray-100 outline-none">
|
|
655
662
|
<option v-for="opt in field.options" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
|
|
656
663
|
</select>
|
|
657
664
|
|
|
658
665
|
<!-- Cards -->
|
|
659
666
|
<div v-else-if="field.type === 'cards'" class="grid grid-cols-3 gap-2">
|
|
660
667
|
<button v-for="opt in field.options" :key="opt.value"
|
|
661
|
-
@click="page.content[selectedBlockIndex].props[name] = opt.value
|
|
668
|
+
@click="page.content[selectedBlockIndex].props[name] = opt.value;
|
|
669
|
+
trigger()"
|
|
662
670
|
:class="[
|
|
663
671
|
'p-2.5 rounded-xl border-2 text-center transition-all',
|
|
664
672
|
page.content[selectedBlockIndex].props[name] === opt.value ? 'border-[#3d35ff] bg-blue-50/50 text-[#3d35ff]' : 'border-gray-100 text-gray-400 hover:border-gray-200'
|
|
@@ -670,14 +678,17 @@ const savePage = async () => {
|
|
|
670
678
|
|
|
671
679
|
<!-- Color -->
|
|
672
680
|
<div v-else-if="field.type === 'color'" class="flex gap-2 bg-gray-50 p-2 rounded-xl ring-1 ring-gray-100">
|
|
673
|
-
<button v-for="c in ['#3d35ff', '#ffffff', '#000000', '#F9F9FB']" :key="c" @click="page.content[selectedBlockIndex].props[name] = c
|
|
674
|
-
|
|
681
|
+
<button v-for="c in ['#3d35ff', '#ffffff', '#000000', '#F9F9FB']" :key="c" @click="page.content[selectedBlockIndex].props[name] = c;
|
|
682
|
+
trigger()" class="w-5 h-5 rounded-full border border-black/5" :style="{ background: c }"></button>
|
|
683
|
+
<input :value="page.content[selectedBlockIndex].props[name]" @input="page.content[selectedBlockIndex].props[name] = $event.target.value;
|
|
684
|
+
trigger()" class="flex-1 bg-transparent text-[9px] font-mono outline-none" />
|
|
675
685
|
</div>
|
|
676
686
|
|
|
677
687
|
<!-- List -->
|
|
678
688
|
<div v-else-if="field.type === 'list'" class="space-y-4">
|
|
679
689
|
<div v-for="(item, idx) in page.content[selectedBlockIndex].props[name] || []" :key="idx" class="p-4 bg-gray-50 rounded-2xl relative border">
|
|
680
|
-
<button @click="page.content[selectedBlockIndex].props[name].splice(idx, 1)
|
|
690
|
+
<button @click="page.content[selectedBlockIndex].props[name].splice(idx, 1);
|
|
691
|
+
trigger()" class="absolute top-2 right-2 text-red-400 text-[8px]">✕</button>
|
|
681
692
|
<div v-for="(subField, subName) in field.itemFields" :key="subName" class="mb-2">
|
|
682
693
|
<label class="text-[7px] font-black uppercase opacity-30">{{ subField.label }}</label>
|
|
683
694
|
<div v-if="subField.type === 'image'" class="mt-1 space-y-1.5">
|
|
@@ -687,7 +698,8 @@ const savePage = async () => {
|
|
|
687
698
|
<button @click="openGallery(item, subName)" class="flex-1 text-[8px] font-black uppercase bg-white px-2 py-1.5 rounded-lg shadow-sm border">⊞ Galerie</button>
|
|
688
699
|
</div>
|
|
689
700
|
</div>
|
|
690
|
-
<select v-else-if="subField.type === 'select'"
|
|
701
|
+
<select v-else-if="subField.type === 'select'" :value="item[subName]" @change="item[subName] = $event.target.value;
|
|
702
|
+
trigger()" class="w-full bg-white rounded-lg p-2 text-[10px] font-bold outline-none shadow-sm border">
|
|
691
703
|
<option v-for="opt in subField.options" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
|
|
692
704
|
</select>
|
|
693
705
|
<template v-else-if="subField.i18n">
|
|
@@ -701,16 +713,20 @@ const savePage = async () => {
|
|
|
701
713
|
:dir="editingLang === 'ar' ? 'rtl' : 'ltr'"
|
|
702
714
|
:placeholder="langLabel(editingLang)"
|
|
703
715
|
class="flex-1 bg-white rounded-lg p-2 text-[10px] font-bold outline-none shadow-sm" />
|
|
704
|
-
<button @click="item[subName].splice(fi, 1)
|
|
716
|
+
<button @click="item[subName].splice(fi, 1);
|
|
717
|
+
trigger()" class="text-red-400 text-[8px] px-1 shrink-0">✕</button>
|
|
705
718
|
</div>
|
|
706
719
|
<button @click="if (!item[subName]) item[subName] = [];
|
|
707
|
-
item[subName].push({ fr: '', ar: '', en: '' })
|
|
720
|
+
item[subName].push({ fr: '', ar: '', en: '' });
|
|
721
|
+
trigger()" class="w-full py-1.5 border border-dashed rounded-lg text-[8px] font-black text-gray-400 hover:border-gray-400 transition">+ Fonctionnalité</button>
|
|
708
722
|
</div>
|
|
709
|
-
<input v-else
|
|
723
|
+
<input v-else :value="item[subName]" @input="item[subName] = $event.target.value;
|
|
724
|
+
trigger()" class="w-full bg-white rounded-lg p-2 text-[10px] font-bold outline-none shadow-sm" />
|
|
710
725
|
</div>
|
|
711
726
|
</div>
|
|
712
727
|
<button @click="if (!page.content[selectedBlockIndex].props[name]) page.content[selectedBlockIndex].props[name] = [];
|
|
713
|
-
page.content[selectedBlockIndex].props[name].push({})
|
|
728
|
+
page.content[selectedBlockIndex].props[name].push({});
|
|
729
|
+
trigger()" class="w-full py-2 border-2 border-dashed rounded-xl text-[8px] font-black text-gray-400">+ AJOUTER</button>
|
|
714
730
|
</div>
|
|
715
731
|
</div>
|
|
716
732
|
</div>
|