@edgedev/create-edge-app 1.2.32 → 1.2.34
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/deploy.sh +77 -0
- package/edge/components/cms/block.vue +228 -18
- package/edge/components/cms/blockApi.vue +3 -3
- package/edge/components/cms/blockEditor.vue +374 -85
- package/edge/components/cms/blockPicker.vue +29 -3
- package/edge/components/cms/blockRender.vue +3 -3
- package/edge/components/cms/blocksManager.vue +755 -82
- package/edge/components/cms/codeEditor.vue +15 -6
- package/edge/components/cms/fontUpload.vue +318 -2
- package/edge/components/cms/htmlContent.vue +230 -89
- package/edge/components/cms/menu.vue +5 -4
- package/edge/components/cms/page.vue +750 -21
- package/edge/components/cms/site.vue +624 -84
- package/edge/components/cms/sitesManager.vue +5 -4
- 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/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/firebase.json +4 -0
- package/nuxt.config.ts +1 -1
- package/package.json +2 -2
- package/pages/app.vue +12 -12
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
const state = reactive({
|
|
4
6
|
mounted: false,
|
|
5
7
|
head: null,
|
|
6
8
|
})
|
|
9
|
+
|
|
10
|
+
useEdgeCmsDialogPositionFix()
|
|
11
|
+
|
|
7
12
|
definePageMeta({
|
|
8
13
|
middleware: 'auth',
|
|
9
14
|
})
|
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const state = reactive({
|
|
3
5
|
mounted: false,
|
|
6
|
+
head: null,
|
|
4
7
|
})
|
|
5
8
|
|
|
9
|
+
useEdgeCmsDialogPositionFix()
|
|
10
|
+
|
|
6
11
|
definePageMeta({
|
|
7
12
|
middleware: 'auth',
|
|
8
13
|
})
|
|
9
14
|
|
|
15
|
+
useHead(() => (state.head || {}))
|
|
16
|
+
|
|
10
17
|
onMounted(() => {
|
|
11
18
|
state.mounted = true
|
|
12
19
|
})
|
|
20
|
+
|
|
21
|
+
const setHead = (newHead) => {
|
|
22
|
+
state.head = newHead
|
|
23
|
+
}
|
|
13
24
|
</script>
|
|
14
25
|
|
|
15
26
|
<template>
|
|
16
27
|
<div
|
|
17
28
|
v-if="edgeGlobal.edgeState.organizationDocPath && state.mounted"
|
|
18
29
|
>
|
|
19
|
-
<edge-cms-blocks-manager />
|
|
30
|
+
<edge-cms-blocks-manager @head="setHead" />
|
|
20
31
|
</div>
|
|
21
32
|
</template>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
|
|
4
6
|
// const edgeGlobal = inject('edgeGlobal')
|
|
@@ -8,6 +10,8 @@ const state = reactive({
|
|
|
8
10
|
head: null,
|
|
9
11
|
})
|
|
10
12
|
|
|
13
|
+
useEdgeCmsDialogPositionFix()
|
|
14
|
+
|
|
11
15
|
const page = computed(() => {
|
|
12
16
|
if (route.params?.page) {
|
|
13
17
|
return route.params.page
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
|
|
4
6
|
// const edgeGlobal = inject('edgeGlobal')
|
|
@@ -7,6 +9,8 @@ const state = reactive({
|
|
|
7
9
|
mounted: false,
|
|
8
10
|
})
|
|
9
11
|
|
|
12
|
+
useEdgeCmsDialogPositionFix()
|
|
13
|
+
|
|
10
14
|
const page = computed(() => {
|
|
11
15
|
if (route.params?.page) {
|
|
12
16
|
return route.params.page
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
|
|
4
6
|
const state = reactive({
|
|
@@ -6,6 +8,8 @@ const state = reactive({
|
|
|
6
8
|
head: null,
|
|
7
9
|
})
|
|
8
10
|
|
|
11
|
+
useEdgeCmsDialogPositionFix()
|
|
12
|
+
|
|
9
13
|
const page = computed(() => {
|
|
10
14
|
if (route.params?.page) {
|
|
11
15
|
return route.params.page
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
|
|
4
6
|
// const edgeGlobal = inject('edgeGlobal')
|
|
@@ -7,6 +9,8 @@ const state = reactive({
|
|
|
7
9
|
mounted: false,
|
|
8
10
|
})
|
|
9
11
|
|
|
12
|
+
useEdgeCmsDialogPositionFix()
|
|
13
|
+
|
|
10
14
|
const page = computed(() => {
|
|
11
15
|
if (route.params?.page) {
|
|
12
16
|
return route.params.page
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
2
4
|
const route = useRoute()
|
|
3
5
|
const state = reactive({
|
|
4
6
|
mounted: false,
|
|
5
7
|
})
|
|
8
|
+
|
|
9
|
+
useEdgeCmsDialogPositionFix()
|
|
10
|
+
|
|
6
11
|
definePageMeta({
|
|
7
12
|
middleware: 'auth',
|
|
8
13
|
head: null,
|
|
@@ -1,18 +1,281 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { useEdgeCmsDialogPositionFix } from '~/edge/composables/useEdgeCmsDialogPositionFix'
|
|
3
|
+
|
|
4
|
+
const edgeFirebase = inject('edgeFirebase')
|
|
5
|
+
const { themes: themeNewDocSchema } = useCmsNewDocs()
|
|
2
6
|
const state = reactive({
|
|
3
7
|
filter: '',
|
|
8
|
+
importingJson: false,
|
|
9
|
+
importDocIdDialogOpen: false,
|
|
10
|
+
importDocIdValue: '',
|
|
11
|
+
importConflictDialogOpen: false,
|
|
12
|
+
importConflictDocId: '',
|
|
13
|
+
importErrorDialogOpen: false,
|
|
14
|
+
importErrorMessage: '',
|
|
4
15
|
})
|
|
16
|
+
const themeImportInputRef = ref(null)
|
|
17
|
+
const themeImportDocIdResolver = ref(null)
|
|
18
|
+
const themeImportConflictResolver = ref(null)
|
|
19
|
+
const INVALID_THEME_IMPORT_MESSAGE = 'Invalid file. Please import a valid theme file.'
|
|
20
|
+
|
|
21
|
+
useEdgeCmsDialogPositionFix()
|
|
22
|
+
|
|
23
|
+
useEdgeCmsDialogPositionFix()
|
|
5
24
|
|
|
6
25
|
definePageMeta({
|
|
7
26
|
middleware: 'auth',
|
|
8
27
|
})
|
|
28
|
+
|
|
29
|
+
const themesCollectionPath = computed(() => `${edgeGlobal.edgeState.organizationDocPath}/themes`)
|
|
30
|
+
const themesCollection = computed(() => edgeFirebase.data?.[themesCollectionPath.value] || {})
|
|
31
|
+
|
|
32
|
+
const readTextFile = file => new Promise((resolve, reject) => {
|
|
33
|
+
if (typeof FileReader === 'undefined') {
|
|
34
|
+
reject(new Error('File import is only available in the browser.'))
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
const reader = new FileReader()
|
|
38
|
+
reader.onload = () => resolve(String(reader.result || ''))
|
|
39
|
+
reader.onerror = () => reject(new Error('Could not read the selected file.'))
|
|
40
|
+
reader.readAsText(file)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const normalizeImportedDoc = (payload, fallbackDocId = '') => {
|
|
44
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload))
|
|
45
|
+
throw new Error(INVALID_THEME_IMPORT_MESSAGE)
|
|
46
|
+
|
|
47
|
+
if (payload.document && typeof payload.document === 'object' && !Array.isArray(payload.document)) {
|
|
48
|
+
const normalized = { ...payload.document }
|
|
49
|
+
if (!normalized.docId && payload.docId)
|
|
50
|
+
normalized.docId = payload.docId
|
|
51
|
+
if (!normalized.docId && fallbackDocId)
|
|
52
|
+
normalized.docId = fallbackDocId
|
|
53
|
+
return normalized
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const normalized = { ...payload }
|
|
57
|
+
if (!normalized.docId && fallbackDocId)
|
|
58
|
+
normalized.docId = fallbackDocId
|
|
59
|
+
return normalized
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const isPlainObject = value => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
63
|
+
|
|
64
|
+
const cloneSchemaValue = (value) => {
|
|
65
|
+
if (isPlainObject(value) || Array.isArray(value))
|
|
66
|
+
return edgeGlobal.dupObject(value)
|
|
67
|
+
return value
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const getDocDefaultsFromSchema = (schema = {}) => {
|
|
71
|
+
const defaults = {}
|
|
72
|
+
for (const [key, schemaEntry] of Object.entries(schema || {})) {
|
|
73
|
+
const hasValueProp = isPlainObject(schemaEntry) && Object.prototype.hasOwnProperty.call(schemaEntry, 'value')
|
|
74
|
+
const baseValue = hasValueProp ? schemaEntry.value : schemaEntry
|
|
75
|
+
defaults[key] = cloneSchemaValue(baseValue)
|
|
76
|
+
}
|
|
77
|
+
return defaults
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const getThemeDocDefaults = () => getDocDefaultsFromSchema(themeNewDocSchema.value || {})
|
|
81
|
+
|
|
82
|
+
const validateImportedThemeDoc = (doc) => {
|
|
83
|
+
if (!isPlainObject(doc))
|
|
84
|
+
throw new Error(INVALID_THEME_IMPORT_MESSAGE)
|
|
85
|
+
|
|
86
|
+
const requiredKeys = Object.keys(themeNewDocSchema.value || {})
|
|
87
|
+
const missing = requiredKeys.filter(key => !Object.prototype.hasOwnProperty.call(doc, key))
|
|
88
|
+
if (missing.length)
|
|
89
|
+
throw new Error(INVALID_THEME_IMPORT_MESSAGE)
|
|
90
|
+
|
|
91
|
+
return doc
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const makeUniqueDocId = (baseDocId, docsMap = {}) => {
|
|
95
|
+
const cleanBase = String(baseDocId || '').trim() || 'theme'
|
|
96
|
+
let nextDocId = `${cleanBase}-copy`
|
|
97
|
+
let suffix = 2
|
|
98
|
+
while (docsMap[nextDocId]) {
|
|
99
|
+
nextDocId = `${cleanBase}-copy-${suffix}`
|
|
100
|
+
suffix += 1
|
|
101
|
+
}
|
|
102
|
+
return nextDocId
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const requestThemeImportDocId = (initialValue = '') => {
|
|
106
|
+
state.importDocIdValue = String(initialValue || '')
|
|
107
|
+
state.importDocIdDialogOpen = true
|
|
108
|
+
return new Promise((resolve) => {
|
|
109
|
+
themeImportDocIdResolver.value = resolve
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const resolveThemeImportDocId = (value = '') => {
|
|
114
|
+
const resolver = themeImportDocIdResolver.value
|
|
115
|
+
themeImportDocIdResolver.value = null
|
|
116
|
+
state.importDocIdDialogOpen = false
|
|
117
|
+
if (resolver)
|
|
118
|
+
resolver(String(value || '').trim())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const requestThemeImportConflict = (docId) => {
|
|
122
|
+
state.importConflictDocId = String(docId || '')
|
|
123
|
+
state.importConflictDialogOpen = true
|
|
124
|
+
return new Promise((resolve) => {
|
|
125
|
+
themeImportConflictResolver.value = resolve
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const resolveThemeImportConflict = (action = 'cancel') => {
|
|
130
|
+
const resolver = themeImportConflictResolver.value
|
|
131
|
+
themeImportConflictResolver.value = null
|
|
132
|
+
state.importConflictDialogOpen = false
|
|
133
|
+
if (resolver)
|
|
134
|
+
resolver(action)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
watch(() => state.importDocIdDialogOpen, (open) => {
|
|
138
|
+
if (!open && themeImportDocIdResolver.value) {
|
|
139
|
+
const resolver = themeImportDocIdResolver.value
|
|
140
|
+
themeImportDocIdResolver.value = null
|
|
141
|
+
resolver('')
|
|
142
|
+
}
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
watch(() => state.importConflictDialogOpen, (open) => {
|
|
146
|
+
if (!open && themeImportConflictResolver.value) {
|
|
147
|
+
const resolver = themeImportConflictResolver.value
|
|
148
|
+
themeImportConflictResolver.value = null
|
|
149
|
+
resolver('cancel')
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const getImportDocId = async (incomingDoc, fallbackDocId = '') => {
|
|
154
|
+
let nextDocId = String(incomingDoc?.docId || '').trim()
|
|
155
|
+
if (!nextDocId)
|
|
156
|
+
nextDocId = await requestThemeImportDocId(fallbackDocId)
|
|
157
|
+
if (!nextDocId)
|
|
158
|
+
throw new Error('Import canceled. A docId is required.')
|
|
159
|
+
if (nextDocId.includes('/'))
|
|
160
|
+
throw new Error('docId cannot include "/".')
|
|
161
|
+
return nextDocId
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const openImportErrorDialog = (message) => {
|
|
165
|
+
state.importErrorMessage = String(message || 'Failed to import theme JSON.')
|
|
166
|
+
state.importErrorDialogOpen = true
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const triggerThemeImport = () => {
|
|
170
|
+
themeImportInputRef.value?.click()
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const importSingleThemeFile = async (file, existingThemes = {}) => {
|
|
174
|
+
const fileText = await readTextFile(file)
|
|
175
|
+
const parsed = JSON.parse(fileText)
|
|
176
|
+
const importedDoc = validateImportedThemeDoc(normalizeImportedDoc(parsed, ''))
|
|
177
|
+
const incomingDocId = await getImportDocId(importedDoc, '')
|
|
178
|
+
let targetDocId = incomingDocId
|
|
179
|
+
let importDecision = 'create'
|
|
180
|
+
|
|
181
|
+
if (existingThemes[targetDocId]) {
|
|
182
|
+
const decision = await requestThemeImportConflict(targetDocId)
|
|
183
|
+
if (decision === 'cancel')
|
|
184
|
+
return
|
|
185
|
+
if (decision === 'new') {
|
|
186
|
+
targetDocId = makeUniqueDocId(targetDocId, existingThemes)
|
|
187
|
+
if (typeof importedDoc.name === 'string' && importedDoc.name.trim() && !/\(Copy\)$/i.test(importedDoc.name.trim()))
|
|
188
|
+
importedDoc.name = `${importedDoc.name} (Copy)`
|
|
189
|
+
importDecision = 'new'
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
importDecision = 'overwrite'
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const payload = { ...getThemeDocDefaults(), ...importedDoc, docId: targetDocId }
|
|
197
|
+
await edgeFirebase.storeDoc(themesCollectionPath.value, payload, targetDocId)
|
|
198
|
+
existingThemes[targetDocId] = payload
|
|
199
|
+
|
|
200
|
+
if (importDecision === 'overwrite')
|
|
201
|
+
edgeFirebase?.toast?.success?.(`Overwrote theme "${targetDocId}".`)
|
|
202
|
+
else if (importDecision === 'new')
|
|
203
|
+
edgeFirebase?.toast?.success?.(`Imported theme as new "${targetDocId}".`)
|
|
204
|
+
else
|
|
205
|
+
edgeFirebase?.toast?.success?.(`Imported theme "${targetDocId}".`)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const handleThemeImport = async (event) => {
|
|
209
|
+
const input = event?.target
|
|
210
|
+
const files = Array.from(input?.files || [])
|
|
211
|
+
if (!files.length)
|
|
212
|
+
return
|
|
213
|
+
|
|
214
|
+
state.importingJson = true
|
|
215
|
+
const existingThemes = { ...(themesCollection.value || {}) }
|
|
216
|
+
try {
|
|
217
|
+
for (const file of files) {
|
|
218
|
+
try {
|
|
219
|
+
await importSingleThemeFile(file, existingThemes)
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.error('Failed to import theme JSON', error)
|
|
223
|
+
const message = error?.message || 'Failed to import theme JSON.'
|
|
224
|
+
if (/^Import canceled\./i.test(message))
|
|
225
|
+
continue
|
|
226
|
+
if (error instanceof SyntaxError || message === INVALID_THEME_IMPORT_MESSAGE)
|
|
227
|
+
openImportErrorDialog(INVALID_THEME_IMPORT_MESSAGE)
|
|
228
|
+
else
|
|
229
|
+
openImportErrorDialog(message)
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
state.importingJson = false
|
|
235
|
+
if (input)
|
|
236
|
+
input.value = ''
|
|
237
|
+
}
|
|
238
|
+
}
|
|
9
239
|
</script>
|
|
10
240
|
|
|
11
241
|
<template>
|
|
12
242
|
<div
|
|
13
243
|
v-if="edgeGlobal.edgeState.organizationDocPath"
|
|
14
244
|
>
|
|
15
|
-
<edge-dashboard
|
|
245
|
+
<edge-dashboard
|
|
246
|
+
:filter="state.filter"
|
|
247
|
+
collection="themes"
|
|
248
|
+
class="pt-0 flex-1"
|
|
249
|
+
header-class="bg-secondary py-2 border"
|
|
250
|
+
>
|
|
251
|
+
<template #header-end>
|
|
252
|
+
<div class="flex items-center gap-2">
|
|
253
|
+
<input
|
|
254
|
+
ref="themeImportInputRef"
|
|
255
|
+
type="file"
|
|
256
|
+
multiple
|
|
257
|
+
accept=".json,application/json"
|
|
258
|
+
class="hidden"
|
|
259
|
+
@change="handleThemeImport"
|
|
260
|
+
>
|
|
261
|
+
<edge-shad-button
|
|
262
|
+
type="button"
|
|
263
|
+
size="icon"
|
|
264
|
+
variant="outline"
|
|
265
|
+
class="h-9 w-9"
|
|
266
|
+
:disabled="state.importingJson"
|
|
267
|
+
title="Import Themes"
|
|
268
|
+
aria-label="Import Themes"
|
|
269
|
+
@click="triggerThemeImport"
|
|
270
|
+
>
|
|
271
|
+
<Loader2 v-if="state.importingJson" class="h-4 w-4 animate-spin" />
|
|
272
|
+
<Upload v-else class="h-4 w-4" />
|
|
273
|
+
</edge-shad-button>
|
|
274
|
+
<edge-shad-button class="uppercase bg-primary" to="/app/dashboard/themes/new">
|
|
275
|
+
Add Theme
|
|
276
|
+
</edge-shad-button>
|
|
277
|
+
</div>
|
|
278
|
+
</template>
|
|
16
279
|
<template #list="slotProps">
|
|
17
280
|
<template v-for="item in slotProps.filtered" :key="item.docId">
|
|
18
281
|
<edge-shad-button variant="text" class="cursor-pointer w-full flex justify-between items-center py-2 gap-3" :to="`/app/dashboard/themes/${item.docId}`">
|
|
@@ -40,5 +303,71 @@ definePageMeta({
|
|
|
40
303
|
</template>
|
|
41
304
|
</template>
|
|
42
305
|
</edge-dashboard>
|
|
306
|
+
<edge-shad-dialog v-model="state.importDocIdDialogOpen">
|
|
307
|
+
<DialogContent class="pt-8">
|
|
308
|
+
<DialogHeader>
|
|
309
|
+
<DialogTitle class="text-left">
|
|
310
|
+
Enter Theme Doc ID
|
|
311
|
+
</DialogTitle>
|
|
312
|
+
<DialogDescription>
|
|
313
|
+
This JSON file does not include a <code>docId</code>. Enter the doc ID you want to import into.
|
|
314
|
+
</DialogDescription>
|
|
315
|
+
</DialogHeader>
|
|
316
|
+
<edge-shad-input
|
|
317
|
+
v-model="state.importDocIdValue"
|
|
318
|
+
name="theme-import-doc-id"
|
|
319
|
+
label="Doc ID"
|
|
320
|
+
placeholder="example-theme-id"
|
|
321
|
+
/>
|
|
322
|
+
<DialogFooter class="pt-2 flex justify-between">
|
|
323
|
+
<edge-shad-button variant="outline" @click="resolveThemeImportDocId('')">
|
|
324
|
+
Cancel
|
|
325
|
+
</edge-shad-button>
|
|
326
|
+
<edge-shad-button @click="resolveThemeImportDocId(state.importDocIdValue)">
|
|
327
|
+
Continue
|
|
328
|
+
</edge-shad-button>
|
|
329
|
+
</DialogFooter>
|
|
330
|
+
</DialogContent>
|
|
331
|
+
</edge-shad-dialog>
|
|
332
|
+
<edge-shad-dialog v-model="state.importConflictDialogOpen">
|
|
333
|
+
<DialogContent class="pt-8">
|
|
334
|
+
<DialogHeader>
|
|
335
|
+
<DialogTitle class="text-left">
|
|
336
|
+
Theme Already Exists
|
|
337
|
+
</DialogTitle>
|
|
338
|
+
<DialogDescription>
|
|
339
|
+
<code>{{ state.importConflictDocId }}</code> already exists. Choose to overwrite it or import as a new theme.
|
|
340
|
+
</DialogDescription>
|
|
341
|
+
</DialogHeader>
|
|
342
|
+
<DialogFooter class="pt-2 flex justify-between">
|
|
343
|
+
<edge-shad-button variant="outline" @click="resolveThemeImportConflict('cancel')">
|
|
344
|
+
Cancel
|
|
345
|
+
</edge-shad-button>
|
|
346
|
+
<edge-shad-button variant="outline" @click="resolveThemeImportConflict('new')">
|
|
347
|
+
Add As New
|
|
348
|
+
</edge-shad-button>
|
|
349
|
+
<edge-shad-button @click="resolveThemeImportConflict('overwrite')">
|
|
350
|
+
Overwrite
|
|
351
|
+
</edge-shad-button>
|
|
352
|
+
</DialogFooter>
|
|
353
|
+
</DialogContent>
|
|
354
|
+
</edge-shad-dialog>
|
|
355
|
+
<edge-shad-dialog v-model="state.importErrorDialogOpen">
|
|
356
|
+
<DialogContent class="pt-8">
|
|
357
|
+
<DialogHeader>
|
|
358
|
+
<DialogTitle class="text-left">
|
|
359
|
+
Import Failed
|
|
360
|
+
</DialogTitle>
|
|
361
|
+
<DialogDescription class="text-left">
|
|
362
|
+
{{ state.importErrorMessage }}
|
|
363
|
+
</DialogDescription>
|
|
364
|
+
</DialogHeader>
|
|
365
|
+
<DialogFooter class="pt-2">
|
|
366
|
+
<edge-shad-button @click="state.importErrorDialogOpen = false">
|
|
367
|
+
Close
|
|
368
|
+
</edge-shad-button>
|
|
369
|
+
</DialogFooter>
|
|
370
|
+
</DialogContent>
|
|
371
|
+
</edge-shad-dialog>
|
|
43
372
|
</div>
|
|
44
373
|
</template>
|
package/firebase.json
CHANGED
package/nuxt.config.ts
CHANGED
|
@@ -24,7 +24,7 @@ export default defineNuxtConfig({
|
|
|
24
24
|
meta: [
|
|
25
25
|
{
|
|
26
26
|
'http-equiv': 'Content-Security-Policy',
|
|
27
|
-
'content': 'font-src \'self\' https://files.edgemarketingdesign.com https://use.typekit.net https://p.typekit.net data:;',
|
|
27
|
+
'content': 'font-src \'self\' https://files.edgemarketingdesign.com https://use.typekit.net https://p.typekit.net https://fonts.gstatic.com data:;',
|
|
28
28
|
},
|
|
29
29
|
],
|
|
30
30
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edgedev/create-edge-app",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.34",
|
|
4
4
|
"description": "Create Edge Starter App",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-edge-app": "./bin/cli.js"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@capacitor/push-notifications": "5.1.0",
|
|
23
23
|
"@chenfengyuan/vue-number-input": "2",
|
|
24
24
|
"@edgedev/firebase": "latest",
|
|
25
|
-
"@edgedev/template-engine": "
|
|
25
|
+
"@edgedev/template-engine": "latest",
|
|
26
26
|
"@guolao/vue-monaco-editor": "^1.5.5",
|
|
27
27
|
"@tiptap/extension-image": "^2.11.5",
|
|
28
28
|
"@tiptap/extension-text-style": "^2.11.5",
|
package/pages/app.vue
CHANGED
|
@@ -260,18 +260,18 @@ edgeGlobal.edgeState.userRoles = [
|
|
|
260
260
|
},
|
|
261
261
|
]
|
|
262
262
|
|
|
263
|
-
edgeGlobal.edgeState.menuItems = [
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
]
|
|
263
|
+
// edgeGlobal.edgeState.menuItems = [
|
|
264
|
+
// {
|
|
265
|
+
// title: 'Dashboard',
|
|
266
|
+
// to: '/app/dashboard/things',
|
|
267
|
+
// icon: 'LayoutDashboard',
|
|
268
|
+
// },
|
|
269
|
+
// {
|
|
270
|
+
// title: 'Sub Things',
|
|
271
|
+
// to: '/app/dashboard/subthings',
|
|
272
|
+
// icon: 'Package',
|
|
273
|
+
// },
|
|
274
|
+
// ]
|
|
275
275
|
</script>
|
|
276
276
|
|
|
277
277
|
<template>
|