@edgedev/create-edge-app 1.2.33 → 1.2.35
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/README.md +1 -0
- package/agents.md +95 -2
- package/deploy.sh +136 -0
- package/edge/components/cms/block.vue +977 -305
- package/edge/components/cms/blockApi.vue +3 -3
- package/edge/components/cms/blockEditor.vue +688 -86
- package/edge/components/cms/blockPicker.vue +31 -5
- package/edge/components/cms/blockRender.vue +3 -3
- package/edge/components/cms/blocksManager.vue +790 -82
- package/edge/components/cms/codeEditor.vue +15 -6
- package/edge/components/cms/fontUpload.vue +318 -2
- package/edge/components/cms/htmlContent.vue +825 -93
- package/edge/components/cms/init_blocks/contact_us.html +55 -47
- package/edge/components/cms/init_blocks/newsletter.html +56 -96
- package/edge/components/cms/menu.vue +96 -34
- package/edge/components/cms/page.vue +902 -58
- package/edge/components/cms/posts.vue +13 -4
- package/edge/components/cms/site.vue +638 -87
- package/edge/components/cms/siteSettingsForm.vue +19 -9
- package/edge/components/cms/sitesManager.vue +5 -4
- package/edge/components/cms/themeDefaultMenu.vue +20 -2
- package/edge/components/cms/themeEditor.vue +196 -162
- package/edge/components/editor.vue +5 -1
- package/edge/composables/global.ts +37 -5
- package/edge/composables/siteSettingsTemplate.js +2 -0
- package/edge/composables/useCmsNewDocs.js +100 -0
- package/edge/composables/useEdgeCmsDialogPositionFix.js +19 -0
- package/edge/routes/cms/dashboard/blocks/[block].vue +5 -0
- package/edge/routes/cms/dashboard/blocks/index.vue +12 -1
- package/edge/routes/cms/dashboard/media/index.vue +5 -0
- package/edge/routes/cms/dashboard/sites/[site]/[[page]].vue +4 -0
- package/edge/routes/cms/dashboard/sites/[site].vue +4 -0
- package/edge/routes/cms/dashboard/sites/index.vue +4 -0
- package/edge/routes/cms/dashboard/templates/[page].vue +4 -0
- package/edge/routes/cms/dashboard/templates/index.vue +4 -0
- package/edge/routes/cms/dashboard/themes/[theme].vue +5 -0
- package/edge/routes/cms/dashboard/themes/index.vue +330 -1
- package/edge-pull.sh +16 -2
- package/edge-push.sh +9 -1
- package/edge-remote.sh +20 -0
- package/edge-status.sh +9 -5
- package/edge-update-all.sh +127 -0
- package/firebase.json +4 -0
- package/nuxt.config.ts +1 -1
- package/package.json +2 -2
|
@@ -480,13 +480,17 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
480
480
|
</div>
|
|
481
481
|
<div class="space-y-2 text-sm">
|
|
482
482
|
<div class="grid grid-cols-[70px_1fr] gap-3">
|
|
483
|
-
<div class="text-muted-foreground">
|
|
483
|
+
<div class="text-muted-foreground">
|
|
484
|
+
CNAME
|
|
485
|
+
</div>
|
|
484
486
|
<div class="font-mono">
|
|
485
487
|
{{ entry?.dnsRecords?.www?.name || 'www' }} → {{ entry?.dnsRecords?.www?.value || pagesDomain }}
|
|
486
488
|
</div>
|
|
487
489
|
</div>
|
|
488
490
|
<div class="grid grid-cols-[70px_1fr] gap-3">
|
|
489
|
-
<div class="text-muted-foreground">
|
|
491
|
+
<div class="text-muted-foreground">
|
|
492
|
+
CNAME
|
|
493
|
+
</div>
|
|
490
494
|
<div class="font-mono">
|
|
491
495
|
{{ entry?.dnsRecords?.apex?.name || '@' }} → {{ entry?.dnsRecords?.apex?.value || pagesDomain }}
|
|
492
496
|
</div>
|
|
@@ -532,7 +536,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
532
536
|
item-value="value"
|
|
533
537
|
@update:model-value="value => (props.settings.theme = value || '')"
|
|
534
538
|
/>
|
|
535
|
-
<edge-shad-select
|
|
539
|
+
<!-- <edge-shad-select
|
|
536
540
|
:model-value="props.settings.menuPosition || ''"
|
|
537
541
|
name="menuPosition"
|
|
538
542
|
label="Menu Position"
|
|
@@ -542,7 +546,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
542
546
|
item-title="label"
|
|
543
547
|
item-value="value"
|
|
544
548
|
@update:model-value="value => (props.settings.menuPosition = value || '')"
|
|
545
|
-
/>
|
|
549
|
+
/> -->
|
|
546
550
|
</TabsContent>
|
|
547
551
|
<TabsContent value="branding" class="pt-4 space-y-4">
|
|
548
552
|
<div v-if="props.enableMediaPicker && props.siteId" class="space-y-2">
|
|
@@ -562,7 +566,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
562
566
|
<img
|
|
563
567
|
:src="props.settings.logo"
|
|
564
568
|
alt="Logo preview"
|
|
565
|
-
|
|
569
|
+
class="max-h-16 max-w-[220px] h-auto w-auto rounded-md border border-border object-contain" :class="[previewBackgroundClass(props.settings.logo)]"
|
|
566
570
|
>
|
|
567
571
|
<edge-shad-button
|
|
568
572
|
type="button"
|
|
@@ -612,7 +616,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
612
616
|
<img
|
|
613
617
|
:src="props.settings.logoLight"
|
|
614
618
|
alt="Light logo preview"
|
|
615
|
-
|
|
619
|
+
class="max-h-16 max-w-[220px] h-auto w-auto rounded-md border border-border object-contain" :class="[previewBackgroundClass(props.settings.logoLight)]"
|
|
616
620
|
>
|
|
617
621
|
<edge-shad-button
|
|
618
622
|
type="button"
|
|
@@ -666,7 +670,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
666
670
|
<img
|
|
667
671
|
:src="props.settings.brandLogoDark"
|
|
668
672
|
alt="Brand dark logo preview"
|
|
669
|
-
|
|
673
|
+
class="max-h-16 max-w-[220px] h-auto w-auto rounded-md border border-border object-contain" :class="[previewBackgroundClass(props.settings.brandLogoDark)]"
|
|
670
674
|
>
|
|
671
675
|
<edge-shad-button
|
|
672
676
|
type="button"
|
|
@@ -716,7 +720,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
716
720
|
<img
|
|
717
721
|
:src="props.settings.brandLogoLight"
|
|
718
722
|
alt="Brand light logo preview"
|
|
719
|
-
|
|
723
|
+
class="max-h-16 max-w-[220px] h-auto w-auto rounded-md border border-border object-contain" :class="[previewBackgroundClass(props.settings.brandLogoLight)]"
|
|
720
724
|
>
|
|
721
725
|
<edge-shad-button
|
|
722
726
|
type="button"
|
|
@@ -767,7 +771,7 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
767
771
|
<img
|
|
768
772
|
:src="props.settings.favicon"
|
|
769
773
|
alt="Favicon preview"
|
|
770
|
-
|
|
774
|
+
class="max-h-12 max-w-12 h-auto w-auto rounded-md border border-border object-contain" :class="[previewBackgroundClass(props.settings.favicon)]"
|
|
771
775
|
>
|
|
772
776
|
<edge-shad-button
|
|
773
777
|
type="button"
|
|
@@ -856,6 +860,12 @@ watch(() => props.settings?.forwardApex, (value) => {
|
|
|
856
860
|
name="trackingAdroll"
|
|
857
861
|
placeholder="ADROLL-ID"
|
|
858
862
|
/>
|
|
863
|
+
<edge-shad-input
|
|
864
|
+
v-model="props.settings.sureFeedURL"
|
|
865
|
+
label="Sure Feedback"
|
|
866
|
+
name="sureFeedURL"
|
|
867
|
+
placeholder=""
|
|
868
|
+
/>
|
|
859
869
|
</div>
|
|
860
870
|
</TabsContent>
|
|
861
871
|
<TabsContent value="social" class="pt-4">
|
|
@@ -7,6 +7,7 @@ const isAiBusy = status => status === 'queued' || status === 'running'
|
|
|
7
7
|
const state = reactive({
|
|
8
8
|
filter: '',
|
|
9
9
|
})
|
|
10
|
+
const cmsMultiOrg = useState('cmsMultiOrg', () => false)
|
|
10
11
|
|
|
11
12
|
const isAdmin = computed(() => {
|
|
12
13
|
return edgeGlobal.isAdminGlobal(edgeFirebase).value
|
|
@@ -25,21 +26,21 @@ const canAddSite = computed(() => {
|
|
|
25
26
|
})
|
|
26
27
|
|
|
27
28
|
const queryField = computed(() => {
|
|
28
|
-
if (!isAdmin.value) {
|
|
29
|
+
if (!isAdmin.value && !cmsMultiOrg.value) {
|
|
29
30
|
return 'users'
|
|
30
31
|
}
|
|
31
32
|
return ''
|
|
32
33
|
})
|
|
33
34
|
|
|
34
35
|
const queryValue = computed(() => {
|
|
35
|
-
if (!isAdmin.value) {
|
|
36
|
+
if (!isAdmin.value && !cmsMultiOrg.value) {
|
|
36
37
|
return [edgeFirebase?.user?.uid]
|
|
37
38
|
}
|
|
38
39
|
return ''
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
const queryOperator = computed(() => {
|
|
42
|
-
if (!isAdmin.value) {
|
|
43
|
+
if (!isAdmin.value && !cmsMultiOrg.value) {
|
|
43
44
|
return 'array-contains-any'
|
|
44
45
|
}
|
|
45
46
|
return ''
|
|
@@ -100,7 +101,7 @@ const queryOperator = computed(() => {
|
|
|
100
101
|
<Separator class="dark:bg-slate-600" />
|
|
101
102
|
</template>
|
|
102
103
|
<div
|
|
103
|
-
v-if="slotProps.filtered.length === 0 && !isAdmin && disableAddSiteForNonAdmin"
|
|
104
|
+
v-if="slotProps.filtered.length === 0 && !isAdmin && disableAddSiteForNonAdmin && !cmsMultiOrg"
|
|
104
105
|
class="px-4 py-6 text-sm text-muted-foreground"
|
|
105
106
|
>
|
|
106
107
|
No sites are assigned to your account. Contact an organization admin to add a site for you.
|
|
@@ -118,6 +118,17 @@ const getFolderName = (entry) => {
|
|
|
118
118
|
return ''
|
|
119
119
|
return Object.keys(entry.item || {})[0] || ''
|
|
120
120
|
}
|
|
121
|
+
const getFolderTitle = (entry) => {
|
|
122
|
+
if (!isFolder(entry))
|
|
123
|
+
return ''
|
|
124
|
+
const title = String(entry?.menuTitle || entry?.folderTitle || '').trim()
|
|
125
|
+
if (title)
|
|
126
|
+
return title
|
|
127
|
+
const folderName = getFolderName(entry)
|
|
128
|
+
if (!folderName)
|
|
129
|
+
return ''
|
|
130
|
+
return folderName.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
|
|
131
|
+
}
|
|
121
132
|
|
|
122
133
|
const getFolderList = (menuName, folderName) => {
|
|
123
134
|
const targetMenu = modelValue.value[menuName] || []
|
|
@@ -228,6 +239,7 @@ const submitFolderDialog = () => {
|
|
|
228
239
|
return
|
|
229
240
|
const slug = uniqueFolderSlug(value, state.folderDialog.menu)
|
|
230
241
|
modelValue.value[state.folderDialog.menu].push({
|
|
242
|
+
menuTitle: value,
|
|
231
243
|
item: { [slug]: [] },
|
|
232
244
|
})
|
|
233
245
|
state.folderDialog.open = false
|
|
@@ -262,13 +274,16 @@ const openRenameDialogForPage = (menuName, index, folderName = null) => {
|
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
const openRenameDialogForFolder = (menuName, folderName, index) => {
|
|
277
|
+
const folderList = modelValue.value[menuName] || []
|
|
278
|
+
const target = folderList[index]
|
|
279
|
+
const currentTitle = String(target?.menuTitle || target?.folderTitle || '').trim()
|
|
265
280
|
state.renameDialog = {
|
|
266
281
|
open: true,
|
|
267
282
|
type: 'folder',
|
|
268
283
|
menu: menuName,
|
|
269
284
|
folder: folderName,
|
|
270
285
|
index,
|
|
271
|
-
value: folderName,
|
|
286
|
+
value: currentTitle || folderName,
|
|
272
287
|
}
|
|
273
288
|
}
|
|
274
289
|
|
|
@@ -347,6 +362,9 @@ const submitRenameDialog = () => {
|
|
|
347
362
|
return
|
|
348
363
|
const currentName = getFolderName(target)
|
|
349
364
|
const slug = uniqueFolderSlug(value || currentName, state.renameDialog.menu, currentName)
|
|
365
|
+
target.menuTitle = value || target.menuTitle || target.folderTitle || currentName
|
|
366
|
+
if (Object.prototype.hasOwnProperty.call(target, 'folderTitle'))
|
|
367
|
+
delete target.folderTitle
|
|
350
368
|
if (slug !== currentName) {
|
|
351
369
|
target.item[slug] = target.item[currentName]
|
|
352
370
|
delete target.item[currentName]
|
|
@@ -438,7 +456,7 @@ const hasEntries = computed(() => {
|
|
|
438
456
|
<div>
|
|
439
457
|
<div class="text-sm font-semibold flex items-center gap-1">
|
|
440
458
|
<Folder class="w-4 h-4" />
|
|
441
|
-
{{
|
|
459
|
+
{{ getFolderTitle(element) }}
|
|
442
460
|
</div>
|
|
443
461
|
<div class="text-[11px] text-muted-foreground">
|
|
444
462
|
Folder
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { toTypedSchema } from '@vee-validate/zod'
|
|
3
|
-
import { FolderCog } from 'lucide-vue-next'
|
|
3
|
+
import { Download, FolderCog } from 'lucide-vue-next'
|
|
4
4
|
import * as z from 'zod'
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
themeId: {
|
|
@@ -11,98 +11,21 @@ const props = defineProps({
|
|
|
11
11
|
|
|
12
12
|
const emit = defineEmits(['head'])
|
|
13
13
|
const edgeFirebase = inject('edgeFirebase')
|
|
14
|
+
const { themes: themeNewDocSchema } = useCmsNewDocs()
|
|
14
15
|
const { createDefaults: createSiteSettingsDefaults } = useSiteSettingsTemplate()
|
|
15
16
|
const state = reactive({
|
|
16
17
|
filter: '',
|
|
17
18
|
workingDoc: {},
|
|
18
19
|
newDocs: {
|
|
19
|
-
themes:
|
|
20
|
-
name: { value: '' },
|
|
21
|
-
headJSON: {
|
|
22
|
-
value: `{
|
|
23
|
-
"link": [
|
|
24
|
-
{
|
|
25
|
-
"rel": "preconnect",
|
|
26
|
-
"href": "https://fonts.googleapis.com"
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"rel": "preconnect",
|
|
30
|
-
"href": "https://fonts.gstatic.com",
|
|
31
|
-
"crossorigin": ""
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"rel": "stylesheet",
|
|
35
|
-
"href": "https://fonts.googleapis.com/css2?family=Overpass:wght@400;700&family=Kode+Mono:wght@400;700&display=swap"
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
}`,
|
|
39
|
-
},
|
|
40
|
-
theme: {
|
|
41
|
-
value: `{
|
|
42
|
-
"extend": {
|
|
43
|
-
"colors": {
|
|
44
|
-
"brand": "#3B82F6",
|
|
45
|
-
"accent": "#F59E0B",
|
|
46
|
-
"surface": "#FAFAFA",
|
|
47
|
-
"subtle": "#F3F4F6",
|
|
48
|
-
"text": "#1F2937",
|
|
49
|
-
"muted": "#9CA3AF",
|
|
50
|
-
"success": "#22C55E",
|
|
51
|
-
"danger": "#EF4444",
|
|
52
|
-
"border": "#E5E7EB",
|
|
53
|
-
"ring": "#93C5FD",
|
|
54
|
-
"link": "#3B82F6",
|
|
55
|
-
"linkHover": "#1D4ED8",
|
|
56
|
-
"navBg": "#000000",
|
|
57
|
-
"navText": "#FFFFFF",
|
|
58
|
-
"navMuted": "#6B7280",
|
|
59
|
-
"navBorder": "",
|
|
60
|
-
"navActive": "#3B82F6",
|
|
61
|
-
"navHoverBg": "",
|
|
62
|
-
"navActiveBg": "",
|
|
63
|
-
"sideNavBg": "#FFFFFF",
|
|
64
|
-
"sideNavText": "#000000",
|
|
65
|
-
"sideNavActive": "#AFBD23"
|
|
66
|
-
},
|
|
67
|
-
"fontFamily": {
|
|
68
|
-
"sans": ["Overpass", "sans-serif"],
|
|
69
|
-
"serif": ["Kode Mono", "monospace"],
|
|
70
|
-
"mono": ["Overpass", "sans-serif"],
|
|
71
|
-
"brand": ["Kode Mono", "monospace"]
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
"apply": {},
|
|
75
|
-
"slots": {},
|
|
76
|
-
"variants": {
|
|
77
|
-
"light": {
|
|
78
|
-
"apply": {}
|
|
79
|
-
},
|
|
80
|
-
"dark": {
|
|
81
|
-
"apply": {},
|
|
82
|
-
"slots": {}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}`,
|
|
86
|
-
},
|
|
87
|
-
extraCSS: {
|
|
88
|
-
value: '',
|
|
89
|
-
},
|
|
90
|
-
version: 1,
|
|
91
|
-
defaultPages: { value: [] },
|
|
92
|
-
defaultMenus: {
|
|
93
|
-
value: {
|
|
94
|
-
'Site Root': [],
|
|
95
|
-
'Not In Menu': [],
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
defaultSiteSettings: { value: createSiteSettingsDefaults() },
|
|
99
|
-
},
|
|
20
|
+
themes: themeNewDocSchema.value,
|
|
100
21
|
},
|
|
101
22
|
mounted: false,
|
|
102
23
|
loading: false,
|
|
103
24
|
defaultSettingsOpen: false,
|
|
104
25
|
})
|
|
105
26
|
|
|
27
|
+
const editorViewportHeight = 'calc(100vh - 420px)'
|
|
28
|
+
|
|
106
29
|
const blockSchema = toTypedSchema(z.object({
|
|
107
30
|
name: z.string({
|
|
108
31
|
required_error: 'Name is required',
|
|
@@ -126,6 +49,16 @@ const parseJsonSafe = (value, fallback) => {
|
|
|
126
49
|
}
|
|
127
50
|
|
|
128
51
|
const headObject = computed(() => lastValidHead.value)
|
|
52
|
+
const previewTheme = computed(() => {
|
|
53
|
+
const isObjectTheme = !!lastValidTheme.value
|
|
54
|
+
&& typeof lastValidTheme.value === 'object'
|
|
55
|
+
&& !Array.isArray(lastValidTheme.value)
|
|
56
|
+
const baseTheme = isObjectTheme ? lastValidTheme.value : {}
|
|
57
|
+
return {
|
|
58
|
+
...baseTheme,
|
|
59
|
+
extraCSS: typeof state.workingDoc?.extraCSS === 'string' ? state.workingDoc.extraCSS : '',
|
|
60
|
+
}
|
|
61
|
+
})
|
|
129
62
|
|
|
130
63
|
watch(headObject, (newHeadElements) => {
|
|
131
64
|
emit('head', newHeadElements)
|
|
@@ -325,6 +258,62 @@ const templatePageOptions = computed(() => {
|
|
|
325
258
|
.sort((a, b) => a.label.localeCompare(b.label))
|
|
326
259
|
})
|
|
327
260
|
|
|
261
|
+
const themesCollectionPath = computed(() => `${edgeGlobal.edgeState.organizationDocPath}/themes`)
|
|
262
|
+
const themesCollection = computed(() => edgeFirebase.data?.[themesCollectionPath.value] || {})
|
|
263
|
+
|
|
264
|
+
const downloadJsonFile = (payload, filename) => {
|
|
265
|
+
if (typeof window === 'undefined')
|
|
266
|
+
return
|
|
267
|
+
const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' })
|
|
268
|
+
const objectUrl = URL.createObjectURL(blob)
|
|
269
|
+
const anchor = document.createElement('a')
|
|
270
|
+
anchor.href = objectUrl
|
|
271
|
+
anchor.download = filename
|
|
272
|
+
document.body.appendChild(anchor)
|
|
273
|
+
anchor.click()
|
|
274
|
+
anchor.remove()
|
|
275
|
+
URL.revokeObjectURL(objectUrl)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const isPlainObject = value => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
279
|
+
|
|
280
|
+
const cloneSchemaValue = (value) => {
|
|
281
|
+
if (isPlainObject(value) || Array.isArray(value))
|
|
282
|
+
return edgeGlobal.dupObject(value)
|
|
283
|
+
return value
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const getDocDefaultsFromSchema = (schema = {}) => {
|
|
287
|
+
const defaults = {}
|
|
288
|
+
for (const [key, schemaEntry] of Object.entries(schema || {})) {
|
|
289
|
+
const hasValueProp = isPlainObject(schemaEntry) && Object.prototype.hasOwnProperty.call(schemaEntry, 'value')
|
|
290
|
+
const baseValue = hasValueProp ? schemaEntry.value : schemaEntry
|
|
291
|
+
defaults[key] = cloneSchemaValue(baseValue)
|
|
292
|
+
}
|
|
293
|
+
return defaults
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const getThemeDocDefaults = () => getDocDefaultsFromSchema(themeNewDocSchema.value || {})
|
|
297
|
+
|
|
298
|
+
const notifySuccess = (message) => {
|
|
299
|
+
edgeFirebase?.toast?.success?.(message)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const notifyError = (message) => {
|
|
303
|
+
edgeFirebase?.toast?.error?.(message)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const exportCurrentTheme = () => {
|
|
307
|
+
const doc = themesCollection.value?.[props.themeId]
|
|
308
|
+
if (!doc || !doc.docId) {
|
|
309
|
+
notifyError('Save this theme before exporting.')
|
|
310
|
+
return
|
|
311
|
+
}
|
|
312
|
+
const exportPayload = { ...getThemeDocDefaults(), ...doc }
|
|
313
|
+
downloadJsonFile(exportPayload, `theme-${doc.docId}.json`)
|
|
314
|
+
notifySuccess(`Exported theme "${doc.docId}".`)
|
|
315
|
+
}
|
|
316
|
+
|
|
328
317
|
watch (sites, async (newSites) => {
|
|
329
318
|
state.loading = true
|
|
330
319
|
const selectedSite = String(edgeGlobal.edgeState.blockEditorSite || '').trim()
|
|
@@ -380,7 +369,9 @@ onBeforeMount(async () => {
|
|
|
380
369
|
:doc-id="props.themeId"
|
|
381
370
|
:schema="blockSchema"
|
|
382
371
|
:new-doc-schema="state.newDocs.themes"
|
|
383
|
-
class="
|
|
372
|
+
header-class="py-2 bg-secondary text-foreground rounded-none sticky top-0 border"
|
|
373
|
+
class="w-full mx-auto flex-1 bg-transparent flex flex-col border-none shadow-none pt-0 px-0"
|
|
374
|
+
card-content-class="px-0"
|
|
384
375
|
:show-footer="false"
|
|
385
376
|
:no-close-after-save="true"
|
|
386
377
|
:working-doc-overrides="state.workingDoc"
|
|
@@ -391,99 +382,142 @@ onBeforeMount(async () => {
|
|
|
391
382
|
{{ slotProps.title }}
|
|
392
383
|
</template>
|
|
393
384
|
<template #header-center>
|
|
394
|
-
<div class="w-full flex gap-
|
|
385
|
+
<div class="w-full flex gap-2 px-4 items-center">
|
|
395
386
|
<div class="w-full">
|
|
396
387
|
<edge-shad-select
|
|
397
388
|
v-if="!state.loading"
|
|
398
389
|
v-model="edgeGlobal.edgeState.blockEditorSite"
|
|
399
|
-
label="Preview Site"
|
|
400
390
|
name="site"
|
|
401
391
|
:items="sites.map(s => ({ title: s.name, name: s.docId }))"
|
|
402
392
|
placeholder="Select Site"
|
|
403
393
|
class="w-full"
|
|
404
394
|
/>
|
|
405
395
|
</div>
|
|
396
|
+
<div class="flex items-center gap-2">
|
|
397
|
+
<edge-shad-button
|
|
398
|
+
type="button"
|
|
399
|
+
size="icon"
|
|
400
|
+
variant="outline"
|
|
401
|
+
class="h-9 w-9"
|
|
402
|
+
:disabled="props.themeId === 'new' || !themesCollection?.[props.themeId]"
|
|
403
|
+
title="Export Theme"
|
|
404
|
+
aria-label="Export Theme"
|
|
405
|
+
@click="exportCurrentTheme"
|
|
406
|
+
>
|
|
407
|
+
<Download class="h-4 w-4" />
|
|
408
|
+
</edge-shad-button>
|
|
409
|
+
</div>
|
|
406
410
|
</div>
|
|
407
411
|
</template>
|
|
408
412
|
<template #main="slotProps">
|
|
409
|
-
<div class="pt-4
|
|
410
|
-
<
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
>
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
<
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
language="json"
|
|
465
|
-
name="headJSON"
|
|
466
|
-
height="400px"
|
|
467
|
-
class="mb-4 w-full"
|
|
468
|
-
/>
|
|
469
|
-
<edge-cms-code-editor
|
|
470
|
-
v-model="slotProps.workingDoc.extraCSS"
|
|
471
|
-
title="Extra CSS"
|
|
472
|
-
language="css"
|
|
473
|
-
name="extraCSS"
|
|
474
|
-
height="300px"
|
|
475
|
-
class="mb-4 w-full"
|
|
476
|
-
/>
|
|
477
|
-
</div>
|
|
478
|
-
<div class="w-1/2">
|
|
479
|
-
<div class="w-full mx-auto bg-white drop-shadow-[4px_4px_6px_rgba(0,0,0,0.5)] shadow-lg shadow-black/30">
|
|
480
|
-
<edge-cms-block-picker
|
|
481
|
-
:site-id="edgeGlobal.edgeState.blockEditorSite"
|
|
482
|
-
class="!h-[calc(100vh-220px)] overflow-y-auto"
|
|
483
|
-
list-only
|
|
484
|
-
:theme="lastValidTheme"
|
|
413
|
+
<div class="pt-4 space-y-4">
|
|
414
|
+
<edge-shad-input
|
|
415
|
+
v-model="slotProps.workingDoc.name"
|
|
416
|
+
label="Theme Name"
|
|
417
|
+
name="name"
|
|
418
|
+
/>
|
|
419
|
+
<div class="flex flex-col gap-4 xl:flex-row">
|
|
420
|
+
<div class="w-full xl:w-1/2">
|
|
421
|
+
<Tabs class="w-full" default-value="theme-json">
|
|
422
|
+
<TabsList class="w-full mt-3 bg-secondary rounded-sm grid grid-cols-2 xl:grid-cols-5">
|
|
423
|
+
<TabsTrigger value="theme-json" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
|
|
424
|
+
Theme JSON
|
|
425
|
+
</TabsTrigger>
|
|
426
|
+
<TabsTrigger value="head-json" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
|
|
427
|
+
Head JSON
|
|
428
|
+
</TabsTrigger>
|
|
429
|
+
<TabsTrigger value="custom-fonts" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
|
|
430
|
+
Custom Fonts
|
|
431
|
+
</TabsTrigger>
|
|
432
|
+
<TabsTrigger value="extra-css" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
|
|
433
|
+
Extra CSS
|
|
434
|
+
</TabsTrigger>
|
|
435
|
+
<TabsTrigger value="default-templates" class="w-full text-black data-[state=active]:bg-black data-[state=active]:text-white">
|
|
436
|
+
Default Templates
|
|
437
|
+
</TabsTrigger>
|
|
438
|
+
</TabsList>
|
|
439
|
+
|
|
440
|
+
<TabsContent value="theme-json" class="mt-4">
|
|
441
|
+
<edge-cms-code-editor
|
|
442
|
+
v-model="slotProps.workingDoc.theme"
|
|
443
|
+
title="Theme JSON"
|
|
444
|
+
language="json"
|
|
445
|
+
name="content"
|
|
446
|
+
:height="editorViewportHeight"
|
|
447
|
+
class="w-full"
|
|
448
|
+
/>
|
|
449
|
+
</TabsContent>
|
|
450
|
+
|
|
451
|
+
<TabsContent value="head-json" class="mt-4">
|
|
452
|
+
<edge-cms-code-editor
|
|
453
|
+
v-model="slotProps.workingDoc.headJSON"
|
|
454
|
+
title="Head JSON"
|
|
455
|
+
language="json"
|
|
456
|
+
name="headJSON"
|
|
457
|
+
:height="editorViewportHeight"
|
|
458
|
+
class="w-full"
|
|
459
|
+
/>
|
|
460
|
+
</TabsContent>
|
|
461
|
+
|
|
462
|
+
<TabsContent value="custom-fonts" class="mt-4">
|
|
463
|
+
<edge-cms-font-upload
|
|
464
|
+
v-if="slotProps.workingDoc"
|
|
465
|
+
v-model:head-json="slotProps.workingDoc.headJSON"
|
|
466
|
+
:theme-id="props.themeId"
|
|
467
|
+
class="w-full"
|
|
485
468
|
/>
|
|
486
|
-
</
|
|
469
|
+
</TabsContent>
|
|
470
|
+
|
|
471
|
+
<TabsContent value="extra-css" class="mt-4">
|
|
472
|
+
<edge-cms-code-editor
|
|
473
|
+
v-model="slotProps.workingDoc.extraCSS"
|
|
474
|
+
title="Extra CSS"
|
|
475
|
+
language="css"
|
|
476
|
+
name="extraCSS"
|
|
477
|
+
:height="editorViewportHeight"
|
|
478
|
+
class="w-full"
|
|
479
|
+
/>
|
|
480
|
+
</TabsContent>
|
|
481
|
+
|
|
482
|
+
<TabsContent value="default-templates" class="mt-4">
|
|
483
|
+
<Card class="h-full">
|
|
484
|
+
<CardHeader class="pb-2">
|
|
485
|
+
<div class="flex items-center justify-between gap-2">
|
|
486
|
+
<CardTitle class="text-base">
|
|
487
|
+
Default Templates
|
|
488
|
+
</CardTitle>
|
|
489
|
+
<edge-shad-button
|
|
490
|
+
size="icon"
|
|
491
|
+
type="text"
|
|
492
|
+
@click="state.defaultSettingsOpen = true"
|
|
493
|
+
>
|
|
494
|
+
<FolderCog class="h-4 w-4" />
|
|
495
|
+
</edge-shad-button>
|
|
496
|
+
</div>
|
|
497
|
+
<CardDescription class="text-xs">
|
|
498
|
+
Choose which template pages are created for new sites and organize them into Site Menu or Not In Menu.
|
|
499
|
+
</CardDescription>
|
|
500
|
+
</CardHeader>
|
|
501
|
+
<CardContent>
|
|
502
|
+
<edge-cms-theme-default-menu
|
|
503
|
+
v-if="slotProps.workingDoc"
|
|
504
|
+
v-model="slotProps.workingDoc.defaultMenus"
|
|
505
|
+
:template-options="templatePageOptions"
|
|
506
|
+
:template-pages="templatePages"
|
|
507
|
+
/>
|
|
508
|
+
</CardContent>
|
|
509
|
+
</Card>
|
|
510
|
+
</TabsContent>
|
|
511
|
+
</Tabs>
|
|
512
|
+
</div>
|
|
513
|
+
<div class="w-full xl:w-1/2">
|
|
514
|
+
<div class="w-full mx-auto bg-white drop-shadow-[4px_4px_6px_rgba(0,0,0,0.5)] shadow-lg shadow-black/30">
|
|
515
|
+
<edge-cms-block-picker
|
|
516
|
+
:site-id="edgeGlobal.edgeState.blockEditorSite"
|
|
517
|
+
class="!h-[calc(100vh-220px)] overflow-y-auto"
|
|
518
|
+
list-only
|
|
519
|
+
:theme="previewTheme"
|
|
520
|
+
/>
|
|
487
521
|
</div>
|
|
488
522
|
</div>
|
|
489
523
|
</div>
|
|
@@ -27,6 +27,10 @@ const props = defineProps({
|
|
|
27
27
|
type: Boolean,
|
|
28
28
|
default: true,
|
|
29
29
|
},
|
|
30
|
+
headerClass: {
|
|
31
|
+
type: String,
|
|
32
|
+
default: 'py-4 bg-secondary text-foreground rounded-none sticky top-0',
|
|
33
|
+
},
|
|
30
34
|
class: {
|
|
31
35
|
type: String,
|
|
32
36
|
default: '',
|
|
@@ -583,7 +587,7 @@ const onError = async () => {
|
|
|
583
587
|
@error="onError"
|
|
584
588
|
>
|
|
585
589
|
<slot name="header" :on-submit="triggerSubmit" :on-cancel="onCancel" :submitting="state.submitting" :unsaved-changes="unsavedChanges" :title="title" :working-doc="state.workingDoc" :errors="state.errors">
|
|
586
|
-
<edge-menu v-if="props.showHeader" class="
|
|
590
|
+
<edge-menu v-if="props.showHeader" :class="props.headerClass">
|
|
587
591
|
<template #start>
|
|
588
592
|
<slot name="header-start" :unsaved-changes="unsavedChanges" :title="title" :errors="state.errors" :working-doc="state.workingDoc">
|
|
589
593
|
<FilePenLine class="mr-2" />
|