@myissue/vue-website-page-builder 3.3.12 → 3.3.13
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 +14 -26
- package/dist/vue-website-page-builder.css +1 -1
- package/dist/vue-website-page-builder.js +4715 -4730
- package/dist/vue-website-page-builder.umd.cjs +37 -37
- package/package.json +1 -1
- package/src/Components/Loaders/GlobalLoader.vue +1 -1
- package/src/Components/Modals/ModalBuilder.vue +2 -2
- package/src/DemoComponents/HomeSection.vue +6 -3
- package/src/DemoComponents/html.json +46 -48
- package/src/PageBuilder/PageBuilder.vue +29 -26
- package/src/composables/PageBuilderService.ts +285 -273
- package/src/stores/page-builder-state.ts +1 -1
- package/src/tailwind-safelist.html +1 -1
- package/src/types/index.ts +2 -4
|
@@ -39,9 +39,9 @@ export class PageBuilderService {
|
|
|
39
39
|
private delay: (ms?: number) => Promise<void>
|
|
40
40
|
private hasStartedEditing: boolean = false
|
|
41
41
|
// Hold data from Database or Backend for updated post
|
|
42
|
-
private originalComponents:
|
|
42
|
+
private originalComponents: BuilderResourceData | undefined = undefined
|
|
43
43
|
// Holds data to be mounted when #pagebuilder is not yet present in the DOM
|
|
44
|
-
private pendingMountData:
|
|
44
|
+
private pendingMountData: BuilderResourceData | null = null
|
|
45
45
|
|
|
46
46
|
constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>) {
|
|
47
47
|
this.hasStartedEditing = false
|
|
@@ -175,36 +175,80 @@ export class PageBuilderService {
|
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
#validateUserProvidedComponents(components:
|
|
179
|
-
|
|
180
|
-
|
|
178
|
+
#validateUserProvidedComponents(components: unknown) {
|
|
179
|
+
const formType =
|
|
180
|
+
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
181
|
+
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
|
|
182
|
+
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType
|
|
183
|
+
|
|
184
|
+
if (Array.isArray(components) && components.length === 0) {
|
|
185
|
+
return { error: false as const, message: 'No components provided (empty array).' }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (
|
|
189
|
+
Array.isArray(components) &&
|
|
190
|
+
components.length >= 1 &&
|
|
191
|
+
formType === 'create' &&
|
|
192
|
+
components
|
|
193
|
+
) {
|
|
194
|
+
return {
|
|
195
|
+
error: true as const,
|
|
196
|
+
warning:
|
|
197
|
+
'You cannot set formType to create in your configuration while also passing a components data array to the Page Builder. Please set formType to update.',
|
|
198
|
+
status: 'validation_failed',
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (formType === 'create' && components) {
|
|
181
202
|
return {
|
|
182
|
-
error: true,
|
|
183
|
-
|
|
203
|
+
error: true as const,
|
|
204
|
+
warning:
|
|
205
|
+
'You cannot set formType to create in your configuration while also passing a components data array to the Page Builder. Please set formType to update.',
|
|
206
|
+
status: 'validation_failed',
|
|
184
207
|
}
|
|
185
208
|
}
|
|
186
209
|
|
|
187
|
-
//
|
|
188
|
-
if (components
|
|
189
|
-
return {
|
|
210
|
+
// Must be an array
|
|
211
|
+
if (!Array.isArray(components)) {
|
|
212
|
+
return {
|
|
213
|
+
error: true as const,
|
|
214
|
+
reason: 'Components data must be an array.',
|
|
215
|
+
}
|
|
190
216
|
}
|
|
191
217
|
|
|
192
218
|
// Check that the first item looks like a component
|
|
193
219
|
const first = components[0]
|
|
194
220
|
|
|
195
|
-
|
|
196
|
-
|
|
221
|
+
// Check that the first item is not an empty object
|
|
222
|
+
if (isEmptyObject(first)) {
|
|
223
|
+
console.error(
|
|
224
|
+
'The first object in the array is empty. Each component must be a non-empty object and include an html_code key.',
|
|
225
|
+
)
|
|
226
|
+
return {
|
|
227
|
+
error: true as const,
|
|
228
|
+
reason:
|
|
229
|
+
"The first object in the array is empty. Each component must be a non-empty object and include an 'html_code' key.",
|
|
230
|
+
}
|
|
231
|
+
}
|
|
197
232
|
|
|
198
|
-
if (
|
|
233
|
+
if (first && 'html_code' in first && typeof first.html_code !== 'string') {
|
|
234
|
+
console.error("The 'html_code' property in the first object must be a string.")
|
|
199
235
|
return {
|
|
200
|
-
error: true,
|
|
201
|
-
reason: "
|
|
236
|
+
error: true as const,
|
|
237
|
+
reason: "The 'html_code' property in the first object must be a string.",
|
|
202
238
|
}
|
|
203
239
|
}
|
|
204
240
|
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
// Check that the first item has an 'html_code' key
|
|
242
|
+
if (!first || !('html_code' in first)) {
|
|
243
|
+
console.error("The first object in the array must include an 'html_code' key.")
|
|
244
|
+
return {
|
|
245
|
+
error: true as const,
|
|
246
|
+
reason: "The first object in the array must include an 'html_code' key.",
|
|
247
|
+
}
|
|
207
248
|
}
|
|
249
|
+
|
|
250
|
+
// No errors found
|
|
251
|
+
return { error: false as const }
|
|
208
252
|
}
|
|
209
253
|
|
|
210
254
|
#validateConfig(config: PageBuilderConfig): void {
|
|
@@ -225,6 +269,96 @@ export class PageBuilderService {
|
|
|
225
269
|
}
|
|
226
270
|
}
|
|
227
271
|
|
|
272
|
+
#handlePageBuilderNotPresent(passedDataComponents: BuilderResourceData) {
|
|
273
|
+
this.pendingMountData = passedDataComponents
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async #mountPassedComponentsToDOM(components?: BuilderResourceData): Promise<void> {
|
|
277
|
+
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
278
|
+
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
279
|
+
const localStorageData = this.loadStoredComponentsFromStorage()
|
|
280
|
+
|
|
281
|
+
let dataToPass: string
|
|
282
|
+
if (typeof components === 'string') {
|
|
283
|
+
dataToPass = components
|
|
284
|
+
} else if (components !== undefined) {
|
|
285
|
+
dataToPass = JSON.stringify(components)
|
|
286
|
+
} else {
|
|
287
|
+
dataToPass = ''
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
await this.#updateComponentsFromString(dataToPass)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async tryMountPendingComponents() {
|
|
294
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(true)
|
|
295
|
+
await delay(200)
|
|
296
|
+
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
297
|
+
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
298
|
+
const localStorageData = this.loadStoredComponentsFromStorage()
|
|
299
|
+
//
|
|
300
|
+
if (!config) return
|
|
301
|
+
//
|
|
302
|
+
if (
|
|
303
|
+
config &&
|
|
304
|
+
formType === 'update' &&
|
|
305
|
+
localStorageData &&
|
|
306
|
+
typeof localStorageData === 'string' &&
|
|
307
|
+
this.pendingMountData
|
|
308
|
+
) {
|
|
309
|
+
this.pageBuilderStateStore.setHasLocalDraftForUpdate(true)
|
|
310
|
+
}
|
|
311
|
+
//
|
|
312
|
+
//
|
|
313
|
+
//
|
|
314
|
+
//
|
|
315
|
+
if (config && formType === 'update') {
|
|
316
|
+
if (this.pendingMountData) {
|
|
317
|
+
this.#completeBuilderInitialization(this.pendingMountData)
|
|
318
|
+
return
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Pending data for mount is null at this stage
|
|
322
|
+
if (typeof localStorageData === 'string') {
|
|
323
|
+
await this.#updateComponentsFromString(localStorageData)
|
|
324
|
+
this.#completeBuilderInitialization()
|
|
325
|
+
return
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
//
|
|
329
|
+
//
|
|
330
|
+
//
|
|
331
|
+
//
|
|
332
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
333
|
+
await nextTick()
|
|
334
|
+
// Attach event listeners to all editable elements in the Builder
|
|
335
|
+
await this.#addListenersToEditableElements()
|
|
336
|
+
|
|
337
|
+
this.pageBuilderStateStore.setIsRestoring(false)
|
|
338
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (config && formType === 'create') {
|
|
342
|
+
// Pending data for mount is null at this stage
|
|
343
|
+
if (typeof localStorageData === 'string') {
|
|
344
|
+
await this.#updateComponentsFromString(localStorageData)
|
|
345
|
+
this.#completeBuilderInitialization()
|
|
346
|
+
return
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
//
|
|
350
|
+
//
|
|
351
|
+
//
|
|
352
|
+
//
|
|
353
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
354
|
+
await nextTick()
|
|
355
|
+
// Attach event listeners to all editable elements in the Builder
|
|
356
|
+
await this.#addListenersToEditableElements()
|
|
357
|
+
|
|
358
|
+
this.pageBuilderStateStore.setIsRestoring(false)
|
|
359
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
360
|
+
}
|
|
361
|
+
}
|
|
228
362
|
/**
|
|
229
363
|
* - Entry point for initializing the Page Builder.
|
|
230
364
|
* - Sets the builder as started in the state store.
|
|
@@ -237,62 +371,101 @@ export class PageBuilderService {
|
|
|
237
371
|
*/
|
|
238
372
|
async startBuilder(
|
|
239
373
|
config: PageBuilderConfig,
|
|
240
|
-
|
|
374
|
+
passedComponentsArray?: BuilderResourceData,
|
|
241
375
|
): Promise<StartBuilderResult> {
|
|
242
|
-
console.log('start builder ran..', components)
|
|
243
|
-
if (components) {
|
|
244
|
-
this.#validateUserProvidedComponents(components)
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
message: 'Page builder started successfully with valid components.',
|
|
249
|
-
}
|
|
250
|
-
|
|
251
376
|
// Reactive flag signals to the UI that the builder has been successfully initialized
|
|
252
377
|
// Prevents builder actions to prevent errors caused by missing DOM .
|
|
253
378
|
this.pageBuilderStateStore.setBuilderStarted(true)
|
|
379
|
+
const pagebuilder = document.querySelector('#pagebuilder')
|
|
380
|
+
let validation
|
|
254
381
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
382
|
+
try {
|
|
383
|
+
this.originalComponents = passedComponentsArray
|
|
384
|
+
this.pageBuilderStateStore.setPageBuilderConfig(config)
|
|
385
|
+
// Validate and normalize the config (ensure required fields are present)
|
|
386
|
+
this.#validateConfig(config)
|
|
259
387
|
|
|
260
|
-
|
|
261
|
-
this.pageBuilderStateStore.setPageBuilderConfig(config)
|
|
388
|
+
validation = this.#validateUserProvidedComponents(passedComponentsArray)
|
|
262
389
|
|
|
263
|
-
|
|
264
|
-
|
|
390
|
+
// Update the localStorage key name based on the config/resource
|
|
391
|
+
this.#updateLocalStorageItemName()
|
|
265
392
|
|
|
266
|
-
|
|
267
|
-
|
|
393
|
+
// Page Builder is not Present in the DOM but Components have been passed to the Builder
|
|
394
|
+
if (passedComponentsArray && !pagebuilder) {
|
|
395
|
+
this.#handlePageBuilderNotPresent(passedComponentsArray)
|
|
396
|
+
}
|
|
397
|
+
// Page Builder is Present in the DOM & Components have been passed to the Builder
|
|
398
|
+
if (pagebuilder) {
|
|
399
|
+
this.#completeBuilderInitialization(passedComponentsArray)
|
|
400
|
+
}
|
|
268
401
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
402
|
+
// Return both the success message and validation info if present
|
|
403
|
+
return {
|
|
404
|
+
message: 'Page builder started successfully.',
|
|
405
|
+
...(validation || {}),
|
|
406
|
+
}
|
|
407
|
+
} catch (err) {
|
|
408
|
+
console.error('Not able to start the Page Builder', err)
|
|
409
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
410
|
+
return {
|
|
411
|
+
error: true as const,
|
|
412
|
+
reason: 'Failed to start the Page Builder due to an unexpected error.',
|
|
413
|
+
}
|
|
272
414
|
}
|
|
273
415
|
}
|
|
274
416
|
|
|
275
|
-
async #completeBuilderInitialization() {
|
|
276
|
-
|
|
277
|
-
const
|
|
278
|
-
|
|
417
|
+
async #completeBuilderInitialization(passedComponentsArray?: BuilderResourceData): Promise<void> {
|
|
418
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(true)
|
|
419
|
+
const localStorageData = this.loadStoredComponentsFromStorage()
|
|
420
|
+
|
|
421
|
+
await this.delay(300)
|
|
279
422
|
|
|
280
423
|
// Deselect any selected or hovered elements in the builder UI
|
|
281
424
|
await this.clearHtmlSelection()
|
|
282
|
-
this.pageBuilderStateStore.setIsLoadingGlobal(true)
|
|
283
|
-
await this.delay(300)
|
|
284
425
|
|
|
285
|
-
|
|
286
|
-
|
|
426
|
+
if (passedComponentsArray) {
|
|
427
|
+
// Prefer components from local storage if available for this resource
|
|
428
|
+
if (!this.pendingMountData && localStorageData && typeof localStorageData === 'string') {
|
|
429
|
+
await this.#updateComponentsFromString(localStorageData)
|
|
430
|
+
} else {
|
|
431
|
+
// If no local storage is found, use the components array provided by the user
|
|
432
|
+
await this.#mountPassedComponentsToDOM(passedComponentsArray)
|
|
433
|
+
this.pendingMountData = null
|
|
434
|
+
}
|
|
435
|
+
}
|
|
287
436
|
|
|
288
|
-
|
|
289
|
-
|
|
437
|
+
//
|
|
438
|
+
//
|
|
439
|
+
//
|
|
440
|
+
if (!passedComponentsArray) {
|
|
441
|
+
// Prefer components from local storage if available for this resource
|
|
442
|
+
if (localStorageData && typeof localStorageData === 'string') {
|
|
443
|
+
await this.#updateComponentsFromString(localStorageData)
|
|
444
|
+
} else {
|
|
445
|
+
// If no local storage is found, use the components array provided by the user
|
|
446
|
+
await this.#mountPassedComponentsToDOM([])
|
|
447
|
+
}
|
|
290
448
|
}
|
|
449
|
+
//
|
|
450
|
+
//
|
|
451
|
+
//
|
|
452
|
+
//
|
|
453
|
+
//
|
|
454
|
+
//
|
|
455
|
+
//
|
|
456
|
+
//
|
|
457
|
+
//
|
|
458
|
+
//
|
|
459
|
+
//
|
|
460
|
+
//
|
|
461
|
+
//
|
|
291
462
|
|
|
292
463
|
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
293
464
|
await nextTick()
|
|
294
465
|
// Attach event listeners to all editable elements in the Builder
|
|
295
466
|
await this.#addListenersToEditableElements()
|
|
467
|
+
// Show a global loading indicator while initializing
|
|
468
|
+
this.pageBuilderStateStore.setIsLoadingGlobal(false)
|
|
296
469
|
|
|
297
470
|
// Clean up any old localStorage items related to previous builder sessions
|
|
298
471
|
this.deleteOldPageBuilderLocalStorage()
|
|
@@ -480,7 +653,7 @@ export class PageBuilderService {
|
|
|
480
653
|
// Deselect any selected or hovered elements in the builder UI
|
|
481
654
|
//
|
|
482
655
|
this.#saveDomComponentsToLocalStorage()
|
|
483
|
-
await this.delay(
|
|
656
|
+
await this.delay(300)
|
|
484
657
|
} catch (err) {
|
|
485
658
|
console.error('Error trying auto save.', err)
|
|
486
659
|
} finally {
|
|
@@ -1113,21 +1286,25 @@ export class PageBuilderService {
|
|
|
1113
1286
|
}
|
|
1114
1287
|
|
|
1115
1288
|
#updateLocalStorageItemName(): void {
|
|
1116
|
-
const
|
|
1289
|
+
const formtype =
|
|
1117
1290
|
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
1118
1291
|
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
|
|
1119
1292
|
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType
|
|
1120
1293
|
|
|
1121
|
-
const
|
|
1294
|
+
const formname =
|
|
1295
|
+
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
1296
|
+
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
|
|
1297
|
+
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formName
|
|
1122
1298
|
|
|
1123
|
-
const
|
|
1124
|
-
this.pageBuilderStateStore.getPageBuilderConfig
|
|
1299
|
+
const resourceData =
|
|
1300
|
+
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
1301
|
+
this.pageBuilderStateStore.getPageBuilderConfig.resourceData
|
|
1125
1302
|
|
|
1126
1303
|
// Logic for create resource
|
|
1127
|
-
if (
|
|
1128
|
-
if (
|
|
1304
|
+
if (formtype === 'create') {
|
|
1305
|
+
if (formname && formname.length > 0) {
|
|
1129
1306
|
this.pageBuilderStateStore.setLocalStorageItemName(
|
|
1130
|
-
`page-builder-create-resource-${this.sanitizeForLocalStorage(
|
|
1307
|
+
`page-builder-create-resource-${this.sanitizeForLocalStorage(formname)}`,
|
|
1131
1308
|
)
|
|
1132
1309
|
return
|
|
1133
1310
|
}
|
|
@@ -1138,15 +1315,15 @@ export class PageBuilderService {
|
|
|
1138
1315
|
|
|
1139
1316
|
// Logic for create
|
|
1140
1317
|
// Logic for update and with resource form name
|
|
1141
|
-
if (
|
|
1142
|
-
if (typeof
|
|
1318
|
+
if (formtype === 'update') {
|
|
1319
|
+
if (typeof formname === 'string' && formname.length > 0) {
|
|
1143
1320
|
//
|
|
1144
1321
|
//
|
|
1145
1322
|
if (resourceData && resourceData != null && !resourceData.title) {
|
|
1146
1323
|
// Check if id is missing, null, undefined, or an empty string (after trimming)
|
|
1147
1324
|
if (!resourceData.id || typeof resourceData.id === 'string') {
|
|
1148
1325
|
this.pageBuilderStateStore.setLocalStorageItemName(
|
|
1149
|
-
`page-builder-update-resource-${this.sanitizeForLocalStorage(
|
|
1326
|
+
`page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}`,
|
|
1150
1327
|
)
|
|
1151
1328
|
return
|
|
1152
1329
|
}
|
|
@@ -1161,7 +1338,7 @@ export class PageBuilderService {
|
|
|
1161
1338
|
) {
|
|
1162
1339
|
if (!resourceData.id || typeof resourceData.id === 'string') {
|
|
1163
1340
|
this.pageBuilderStateStore.setLocalStorageItemName(
|
|
1164
|
-
`page-builder-update-resource-${this.sanitizeForLocalStorage(
|
|
1341
|
+
`page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(resourceData.title)}`,
|
|
1165
1342
|
)
|
|
1166
1343
|
return
|
|
1167
1344
|
}
|
|
@@ -1173,7 +1350,7 @@ export class PageBuilderService {
|
|
|
1173
1350
|
if (!resourceData.title && typeof resourceData.title !== 'string') {
|
|
1174
1351
|
if (resourceData.id || typeof resourceData.id === 'number') {
|
|
1175
1352
|
this.pageBuilderStateStore.setLocalStorageItemName(
|
|
1176
|
-
`page-builder-update-resource-${this.sanitizeForLocalStorage(
|
|
1353
|
+
`page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
|
|
1177
1354
|
)
|
|
1178
1355
|
return
|
|
1179
1356
|
}
|
|
@@ -1189,7 +1366,7 @@ export class PageBuilderService {
|
|
|
1189
1366
|
) {
|
|
1190
1367
|
if (resourceData.id || typeof resourceData.id === 'number') {
|
|
1191
1368
|
this.pageBuilderStateStore.setLocalStorageItemName(
|
|
1192
|
-
`page-builder-update-resource-${this.sanitizeForLocalStorage(
|
|
1369
|
+
`page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(resourceData.title)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
|
|
1193
1370
|
)
|
|
1194
1371
|
return
|
|
1195
1372
|
}
|
|
@@ -1197,11 +1374,8 @@ export class PageBuilderService {
|
|
|
1197
1374
|
}
|
|
1198
1375
|
}
|
|
1199
1376
|
|
|
1200
|
-
// Logic for update without without
|
|
1201
|
-
if (
|
|
1202
|
-
!resourceFormName ||
|
|
1203
|
-
(typeof resourceFormName === 'string' && resourceFormName.length === 0)
|
|
1204
|
-
) {
|
|
1377
|
+
// Logic for update without without formname
|
|
1378
|
+
if (!formname || (typeof formname === 'string' && formname.length === 0)) {
|
|
1205
1379
|
//
|
|
1206
1380
|
//
|
|
1207
1381
|
if (resourceData && resourceData != null && !resourceData.title) {
|
|
@@ -1348,12 +1522,10 @@ export class PageBuilderService {
|
|
|
1348
1522
|
|
|
1349
1523
|
//
|
|
1350
1524
|
deleteOldPageBuilderLocalStorage(): void {
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
|
|
1356
|
-
) {
|
|
1525
|
+
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
1526
|
+
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
1527
|
+
|
|
1528
|
+
if (formType === 'update') {
|
|
1357
1529
|
let oldCountLocalStorages = 0
|
|
1358
1530
|
const deletedItemsLog: { Number: number; Key: string; SavedAt: string }[] = []
|
|
1359
1531
|
|
|
@@ -1401,38 +1573,6 @@ export class PageBuilderService {
|
|
|
1401
1573
|
}
|
|
1402
1574
|
}
|
|
1403
1575
|
|
|
1404
|
-
async hasLocalDraftForUpdate(): Promise<boolean> {
|
|
1405
|
-
const pagebuilder = document.querySelector('#pagebuilder')
|
|
1406
|
-
if (!pagebuilder) {
|
|
1407
|
-
return true
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
if (this.hasStartedEditing) return false
|
|
1411
|
-
|
|
1412
|
-
if (
|
|
1413
|
-
this.pageBuilderStateStore.getPageBuilderConfig &&
|
|
1414
|
-
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
|
|
1415
|
-
typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
|
|
1416
|
-
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
|
|
1417
|
-
) {
|
|
1418
|
-
const key = this.getLocalStorageItemName.value
|
|
1419
|
-
if (typeof key === 'string') {
|
|
1420
|
-
const draft = localStorage.getItem(key)
|
|
1421
|
-
if (draft) {
|
|
1422
|
-
try {
|
|
1423
|
-
await this.delay(500)
|
|
1424
|
-
this.pageBuilderStateStore.setHasLocalDraftForUpdate(false)
|
|
1425
|
-
return true
|
|
1426
|
-
} catch (err) {
|
|
1427
|
-
console.error('Unable to mount components to DOM.', err)
|
|
1428
|
-
return false
|
|
1429
|
-
}
|
|
1430
|
-
}
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
return false
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
1576
|
// Call this when the user starts editing (e.g., on first change or when resuming a draft)
|
|
1437
1577
|
startEditing() {
|
|
1438
1578
|
this.hasStartedEditing = true
|
|
@@ -1440,40 +1580,48 @@ export class PageBuilderService {
|
|
|
1440
1580
|
|
|
1441
1581
|
//
|
|
1442
1582
|
async resumeEditingForUpdate() {
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1583
|
+
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
1584
|
+
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
1585
|
+
|
|
1586
|
+
if (formType !== 'update') return
|
|
1587
|
+
//
|
|
1588
|
+
//
|
|
1589
|
+
//
|
|
1450
1590
|
|
|
1451
|
-
|
|
1452
|
-
const updateDraftFromLocalStorage = localStorage.getItem(key)
|
|
1591
|
+
const key = this.getLocalStorageItemName.value
|
|
1453
1592
|
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1593
|
+
if (typeof key === 'string') {
|
|
1594
|
+
const updateDraftFromLocalStorage = localStorage.getItem(key)
|
|
1595
|
+
|
|
1596
|
+
if (typeof updateDraftFromLocalStorage === 'string') {
|
|
1597
|
+
this.pageBuilderStateStore.setIsLoadingResumeEditing(true)
|
|
1598
|
+
localStorage.removeItem(key)
|
|
1599
|
+
await delay(300)
|
|
1600
|
+
await this.#updateComponentsFromString(updateDraftFromLocalStorage)
|
|
1601
|
+
this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
|
|
1460
1602
|
}
|
|
1461
1603
|
}
|
|
1604
|
+
|
|
1605
|
+
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
1606
|
+
await nextTick()
|
|
1607
|
+
// Attach event listeners to all editable elements in the Builder
|
|
1608
|
+
await this.#addListenersToEditableElements()
|
|
1609
|
+
// set loading to false
|
|
1610
|
+
this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
|
|
1462
1611
|
}
|
|
1463
1612
|
|
|
1464
1613
|
async restoreOriginalContent() {
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
|
|
1470
|
-
) {
|
|
1614
|
+
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
1615
|
+
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
1616
|
+
|
|
1617
|
+
if (formType === 'update') {
|
|
1471
1618
|
this.pageBuilderStateStore.setIsRestoring(true)
|
|
1472
1619
|
await this.delay(300)
|
|
1473
1620
|
|
|
1474
1621
|
// Restore the original content if available
|
|
1475
|
-
if (this.originalComponents) {
|
|
1476
|
-
this
|
|
1622
|
+
if (Array.isArray(this.originalComponents)) {
|
|
1623
|
+
await this.#mountPassedComponentsToDOM(this.originalComponents)
|
|
1624
|
+
this.removeCurrentComponentsFromLocalStorage()
|
|
1477
1625
|
}
|
|
1478
1626
|
|
|
1479
1627
|
// Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
|
|
@@ -1784,19 +1932,22 @@ export class PageBuilderService {
|
|
|
1784
1932
|
* @param data - JSON string (e.g., '[{"html_code":"...","id":"123","title":"..."}]')
|
|
1785
1933
|
* OR HTML string (e.g., '<section data-componentid="123">...</section>')
|
|
1786
1934
|
*/
|
|
1787
|
-
async #
|
|
1935
|
+
async #updateComponentsFromString(htmlString: string): Promise<void> {
|
|
1788
1936
|
// Auto-detect if input is JSON or HTML
|
|
1789
1937
|
const trimmedData = htmlString.trim()
|
|
1790
1938
|
|
|
1791
1939
|
if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
|
|
1792
1940
|
// Looks like JSON - parse as JSON
|
|
1793
1941
|
await this.#parseJSONComponents(trimmedData)
|
|
1794
|
-
|
|
1942
|
+
return
|
|
1943
|
+
}
|
|
1944
|
+
if (trimmedData.startsWith('<')) {
|
|
1795
1945
|
// Looks like HTML - parse as HTML
|
|
1796
1946
|
await this.#parseHTMLComponents(trimmedData)
|
|
1797
|
-
|
|
1798
|
-
await this.#parseJSONComponents(trimmedData)
|
|
1947
|
+
return
|
|
1799
1948
|
}
|
|
1949
|
+
|
|
1950
|
+
await this.#parseJSONComponents(trimmedData)
|
|
1800
1951
|
}
|
|
1801
1952
|
|
|
1802
1953
|
// Private method to parse JSON components and save pageBuilderContentSavedAt to localStorage
|
|
@@ -1917,145 +2068,6 @@ export class PageBuilderService {
|
|
|
1917
2068
|
}
|
|
1918
2069
|
}
|
|
1919
2070
|
|
|
1920
|
-
async mountComponentsToDOM(passedData: string): Promise<void> {
|
|
1921
|
-
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
1922
|
-
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
1923
|
-
|
|
1924
|
-
if (formType) {
|
|
1925
|
-
const pagebuilder = document.querySelector('#pagebuilder')
|
|
1926
|
-
const localStorageData = this.loadStoredComponentsFromStorage()
|
|
1927
|
-
|
|
1928
|
-
if (!pagebuilder) {
|
|
1929
|
-
await this.#handlePageBuilderNotPresent(passedData, formType)
|
|
1930
|
-
return
|
|
1931
|
-
}
|
|
1932
|
-
|
|
1933
|
-
this.#handleOriginalComponentsForUpdate(passedData, formType)
|
|
1934
|
-
|
|
1935
|
-
if (this.#isCreateFormType(formType)) {
|
|
1936
|
-
await this.#handleCreateFormType(passedData, localStorageData)
|
|
1937
|
-
return
|
|
1938
|
-
}
|
|
1939
|
-
|
|
1940
|
-
if (this.#isUpdateFormType(formType)) {
|
|
1941
|
-
await this.#handleUpdateFormType(passedData, localStorageData)
|
|
1942
|
-
return
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
}
|
|
1946
|
-
|
|
1947
|
-
// --- Private helpers ---
|
|
1948
|
-
|
|
1949
|
-
async #handlePageBuilderNotPresent(passedData: string, formType: string) {
|
|
1950
|
-
if (formType === 'create') {
|
|
1951
|
-
console.log('mountComponentsToDOM ran: m0')
|
|
1952
|
-
this.pendingMountData = ''
|
|
1953
|
-
return
|
|
1954
|
-
}
|
|
1955
|
-
console.log('mountComponentsToDOM ran: m1:')
|
|
1956
|
-
this.pendingMountData = passedData
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
#handleOriginalComponentsForUpdate(passedData: string, formType: string) {
|
|
1960
|
-
if (formType === 'update' && passedData && !this.originalComponents) {
|
|
1961
|
-
console.log('mountComponentsToDOM ran: m3')
|
|
1962
|
-
this.originalComponents = passedData
|
|
1963
|
-
}
|
|
1964
|
-
}
|
|
1965
|
-
|
|
1966
|
-
async #handleUpdateFormType(passedData: string, localStorageData: string | false) {
|
|
1967
|
-
if (passedData) {
|
|
1968
|
-
console.log('mountComponentsToDOM ran: m4')
|
|
1969
|
-
await this.#setComponentsFromData(passedData)
|
|
1970
|
-
return
|
|
1971
|
-
}
|
|
1972
|
-
if (localStorageData) {
|
|
1973
|
-
console.log('mountComponentsToDOM ran: m5')
|
|
1974
|
-
await this.#setComponentsFromData(localStorageData)
|
|
1975
|
-
return
|
|
1976
|
-
}
|
|
1977
|
-
// If nothing, clear components
|
|
1978
|
-
console.log('mountComponentsToDOM ran: m6')
|
|
1979
|
-
this.deleteAllComponentsFromDOM()
|
|
1980
|
-
}
|
|
1981
|
-
|
|
1982
|
-
async #handleCreateFormType(passedData: string, localStorageData: string | false) {
|
|
1983
|
-
if (localStorageData) {
|
|
1984
|
-
console.log('mountComponentsToDOM ran: m7')
|
|
1985
|
-
await this.#setComponentsFromData(localStorageData)
|
|
1986
|
-
return
|
|
1987
|
-
}
|
|
1988
|
-
if (passedData) {
|
|
1989
|
-
console.log('mountComponentsToDOM ran: m8')
|
|
1990
|
-
await this.#setComponentsFromData(passedData)
|
|
1991
|
-
return
|
|
1992
|
-
}
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
#isCreateFormType(formType: string): boolean {
|
|
1996
|
-
return formType === 'create'
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
#isUpdateFormType(formType: string): boolean {
|
|
2000
|
-
return formType === 'update'
|
|
2001
|
-
}
|
|
2002
|
-
|
|
2003
|
-
async ensureBuilderInitializedForCreate() {
|
|
2004
|
-
const pagebuilder = document.querySelector('#pagebuilder')
|
|
2005
|
-
if (!pagebuilder) return
|
|
2006
|
-
|
|
2007
|
-
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
2008
|
-
console.log('den er:', config)
|
|
2009
|
-
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
2010
|
-
|
|
2011
|
-
if (formType === 'create') {
|
|
2012
|
-
this.#completeBuilderInitialization()
|
|
2013
|
-
await nextTick()
|
|
2014
|
-
|
|
2015
|
-
if (
|
|
2016
|
-
formType === 'create' &&
|
|
2017
|
-
(!this.getComponents.value ||
|
|
2018
|
-
(Array.isArray(this.getComponents.value) && this.getComponents.value.length === 0))
|
|
2019
|
-
) {
|
|
2020
|
-
console.log('ensureBuilderInitializedForCreate e1')
|
|
2021
|
-
await this.mountComponentsToDOM('')
|
|
2022
|
-
this.pendingMountData = null
|
|
2023
|
-
return
|
|
2024
|
-
}
|
|
2025
|
-
|
|
2026
|
-
console.log('ensureBuilderInitializedForCreate e2:')
|
|
2027
|
-
await this.mountComponentsToDOM('')
|
|
2028
|
-
await nextTick()
|
|
2029
|
-
// Attach event listeners to all editable elements in the Builder
|
|
2030
|
-
await this.#addListenersToEditableElements()
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
|
-
async ensureBuilderInitializedForUpdate() {
|
|
2035
|
-
const pagebuilder = document.querySelector('#pagebuilder')
|
|
2036
|
-
if (!pagebuilder) return
|
|
2037
|
-
|
|
2038
|
-
const config = this.pageBuilderStateStore.getPageBuilderConfig
|
|
2039
|
-
const formType = config && config.updateOrCreate && config.updateOrCreate.formType
|
|
2040
|
-
|
|
2041
|
-
if (formType === 'update') {
|
|
2042
|
-
this.#completeBuilderInitialization()
|
|
2043
|
-
|
|
2044
|
-
// Only for update/draft/demo: mount if pendingMountData is a non-empty string
|
|
2045
|
-
if (this.pendingMountData && typeof this.pendingMountData === 'string') {
|
|
2046
|
-
console.log('ensureBuilderInitializedForUpdate t1:')
|
|
2047
|
-
await this.mountComponentsToDOM(this.pendingMountData)
|
|
2048
|
-
this.pendingMountData = null
|
|
2049
|
-
return
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
console.log('ensureBuilderInitializedForUpdate t2:')
|
|
2053
|
-
await nextTick()
|
|
2054
|
-
// Always try to load latest from localStorage or fallback
|
|
2055
|
-
await this.mountComponentsToDOM('')
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
|
|
2059
2071
|
async toggleTipTapModal(status: boolean): Promise<void> {
|
|
2060
2072
|
this.pageBuilderStateStore.setShowModalTipTap(status)
|
|
2061
2073
|
|