@myissue/vue-website-page-builder 3.3.12 → 3.3.14

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.
@@ -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: string | null = null
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: string | null = null
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: BuilderResourceData) {
179
- // Must be an array
180
- if (!Array.isArray(components)) {
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
+ ) {
181
194
  return {
182
- error: true,
183
- reason: "'components' must be an array.",
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) {
202
+ return {
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
- // If empty array, that's acceptable
188
- if (components.length === 0) {
189
- return { error: false }
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
- const isObject = typeof first === 'object' && first !== null
196
- const hasHtmlCodeKey = 'html_code' in first
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 (!isObject || !hasHtmlCodeKey) {
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: "Each component must be an object and include an 'html_code' key.",
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
- return {
206
- message: 'Everything looks good. Components structure is valid.',
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,101 @@ 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
+ // Always clear DOM and store before mounting new resource
295
+ this.deleteAllComponentsFromDOM()
296
+
297
+ const localStorageData = this.loadStoredComponentsFromStorage()
298
+
299
+ this.pageBuilderStateStore.setIsLoadingGlobal(true)
300
+ await delay(200)
301
+ const config = this.pageBuilderStateStore.getPageBuilderConfig
302
+ const formType = config && config.updateOrCreate && config.updateOrCreate.formType
303
+
304
+ //
305
+ if (!config) return
306
+ //
307
+ if (
308
+ config &&
309
+ formType === 'update' &&
310
+ localStorageData &&
311
+ typeof localStorageData === 'string' &&
312
+ this.pendingMountData
313
+ ) {
314
+ this.pageBuilderStateStore.setHasLocalDraftForUpdate(true)
315
+ }
316
+ //
317
+ //
318
+ //
319
+ //
320
+ if (config && formType === 'update') {
321
+ if (this.pendingMountData) {
322
+ this.#completeBuilderInitialization(this.pendingMountData)
323
+ return
324
+ }
325
+
326
+ // Pending data for mount is null at this stage
327
+ if (typeof localStorageData === 'string') {
328
+ await this.#updateComponentsFromString(localStorageData)
329
+ this.#completeBuilderInitialization()
330
+ return
331
+ }
332
+
333
+ //
334
+ //
335
+ //
336
+ //
337
+ // Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
338
+ await nextTick()
339
+ // Attach event listeners to all editable elements in the Builder
340
+ await this.#addListenersToEditableElements()
341
+
342
+ this.pageBuilderStateStore.setIsRestoring(false)
343
+ this.pageBuilderStateStore.setIsLoadingGlobal(false)
344
+ }
345
+
346
+ if (config && formType === 'create') {
347
+ // Pending data for mount is null at this stage
348
+ if (typeof localStorageData === 'string') {
349
+ await this.#updateComponentsFromString(localStorageData)
350
+ this.#completeBuilderInitialization()
351
+ return
352
+ }
353
+
354
+ //
355
+ //
356
+ //
357
+ //
358
+ // Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
359
+ await nextTick()
360
+ // Attach event listeners to all editable elements in the Builder
361
+ await this.#addListenersToEditableElements()
362
+
363
+ this.pageBuilderStateStore.setIsRestoring(false)
364
+ this.pageBuilderStateStore.setIsLoadingGlobal(false)
365
+ }
366
+ }
228
367
  /**
229
368
  * - Entry point for initializing the Page Builder.
230
369
  * - Sets the builder as started in the state store.
@@ -237,62 +376,101 @@ export class PageBuilderService {
237
376
  */
238
377
  async startBuilder(
239
378
  config: PageBuilderConfig,
240
- components?: BuilderResourceData,
379
+ passedComponentsArray?: BuilderResourceData,
241
380
  ): 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
381
  // Reactive flag signals to the UI that the builder has been successfully initialized
252
382
  // Prevents builder actions to prevent errors caused by missing DOM .
253
383
  this.pageBuilderStateStore.setBuilderStarted(true)
384
+ const pagebuilder = document.querySelector('#pagebuilder')
385
+ let validation
254
386
 
255
- // Show a global loading indicator while initializing
256
- this.pageBuilderStateStore.setIsLoadingGlobal(true)
257
-
258
- // Wait briefly to ensure UI updates and async processes settle
387
+ try {
388
+ this.originalComponents = passedComponentsArray
389
+ this.pageBuilderStateStore.setPageBuilderConfig(config)
390
+ // Validate and normalize the config (ensure required fields are present)
391
+ this.#validateConfig(config)
259
392
 
260
- // Store the provided config in the builder's state store
261
- this.pageBuilderStateStore.setPageBuilderConfig(config)
393
+ validation = this.#validateUserProvidedComponents(passedComponentsArray)
262
394
 
263
- // Validate and normalize the config (ensure required fields are present)
264
- this.#validateConfig(config)
395
+ // Update the localStorage key name based on the config/resource
396
+ this.#updateLocalStorageItemName()
265
397
 
266
- // Update the localStorage key name based on the config/resource
267
- this.#updateLocalStorageItemName()
398
+ // Page Builder is not Present in the DOM but Components have been passed to the Builder
399
+ if (passedComponentsArray && !pagebuilder) {
400
+ this.#handlePageBuilderNotPresent(passedComponentsArray)
401
+ }
402
+ // Page Builder is Present in the DOM & Components have been passed to the Builder
403
+ if (pagebuilder) {
404
+ this.#completeBuilderInitialization(passedComponentsArray)
405
+ }
268
406
 
269
- const formType = config.updateOrCreate && config.updateOrCreate.formType
270
- if (formType === 'create') {
271
- await this.mountComponentsToDOM('')
407
+ // Return both the success message and validation info if present
408
+ return {
409
+ message: 'Page builder started successfully.',
410
+ ...(validation || {}),
411
+ }
412
+ } catch (err) {
413
+ console.error('Not able to start the Page Builder', err)
414
+ this.pageBuilderStateStore.setIsLoadingGlobal(false)
415
+ return {
416
+ error: true as const,
417
+ reason: 'Failed to start the Page Builder due to an unexpected error.',
418
+ }
272
419
  }
273
420
  }
274
421
 
275
- async #completeBuilderInitialization() {
276
- console.log('complete builder..')
277
- const pagebuilder = document.querySelector('#pagebuilder')
278
- if (!pagebuilder) return
422
+ async #completeBuilderInitialization(passedComponentsArray?: BuilderResourceData): Promise<void> {
423
+ this.pageBuilderStateStore.setIsLoadingGlobal(true)
424
+ const localStorageData = this.loadStoredComponentsFromStorage()
425
+
426
+ await this.delay(300)
279
427
 
280
428
  // Deselect any selected or hovered elements in the builder UI
281
429
  await this.clearHtmlSelection()
282
- this.pageBuilderStateStore.setIsLoadingGlobal(true)
283
- await this.delay(300)
284
430
 
285
- // Hide the global loading indicator and mark the builder as started
286
- this.pageBuilderStateStore.setIsLoadingGlobal(false)
431
+ if (passedComponentsArray) {
432
+ // Prefer components from local storage if available for this resource
433
+ if (!this.pendingMountData && localStorageData && typeof localStorageData === 'string') {
434
+ await this.#updateComponentsFromString(localStorageData)
435
+ } else {
436
+ // If no local storage is found, use the components array provided by the user
437
+ await this.#mountPassedComponentsToDOM(passedComponentsArray)
438
+ this.pendingMountData = null
439
+ }
440
+ }
287
441
 
288
- if (await this.hasLocalDraftForUpdate()) {
289
- this.pageBuilderStateStore.setHasLocalDraftForUpdate(true)
442
+ //
443
+ //
444
+ //
445
+ if (!passedComponentsArray) {
446
+ // Prefer components from local storage if available for this resource
447
+ if (localStorageData && typeof localStorageData === 'string') {
448
+ await this.#updateComponentsFromString(localStorageData)
449
+ } else {
450
+ // If no local storage is found, use the components array provided by the user
451
+ await this.#mountPassedComponentsToDOM([])
452
+ }
290
453
  }
454
+ //
455
+ //
456
+ //
457
+ //
458
+ //
459
+ //
460
+ //
461
+ //
462
+ //
463
+ //
464
+ //
465
+ //
466
+ //
291
467
 
292
468
  // Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
293
469
  await nextTick()
294
470
  // Attach event listeners to all editable elements in the Builder
295
471
  await this.#addListenersToEditableElements()
472
+ // Show a global loading indicator while initializing
473
+ this.pageBuilderStateStore.setIsLoadingGlobal(false)
296
474
 
297
475
  // Clean up any old localStorage items related to previous builder sessions
298
476
  this.deleteOldPageBuilderLocalStorage()
@@ -376,6 +554,8 @@ export class PageBuilderService {
376
554
  e.preventDefault()
377
555
  e.stopPropagation()
378
556
 
557
+ await this.handleAutoSave()
558
+
379
559
  const pagebuilder = document.querySelector('#pagebuilder')
380
560
 
381
561
  if (!pagebuilder) return
@@ -480,7 +660,7 @@ export class PageBuilderService {
480
660
  // Deselect any selected or hovered elements in the builder UI
481
661
  //
482
662
  this.#saveDomComponentsToLocalStorage()
483
- await this.delay(500)
663
+ await this.delay(300)
484
664
  } catch (err) {
485
665
  console.error('Error trying auto save.', err)
486
666
  } finally {
@@ -1113,21 +1293,25 @@ export class PageBuilderService {
1113
1293
  }
1114
1294
 
1115
1295
  #updateLocalStorageItemName(): void {
1116
- const updateOrCreate =
1296
+ const formtype =
1117
1297
  this.pageBuilderStateStore.getPageBuilderConfig &&
1118
1298
  this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1119
1299
  this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType
1120
1300
 
1121
- const resourceData = this.pageBuilderStateStore.getPageBuilderConfig?.resourceData
1301
+ const formname =
1302
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1303
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1304
+ this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formName
1122
1305
 
1123
- const resourceFormName =
1124
- this.pageBuilderStateStore.getPageBuilderConfig?.updateOrCreate?.formName
1306
+ const resourceData =
1307
+ this.pageBuilderStateStore.getPageBuilderConfig &&
1308
+ this.pageBuilderStateStore.getPageBuilderConfig.resourceData
1125
1309
 
1126
1310
  // Logic for create resource
1127
- if (updateOrCreate === 'create') {
1128
- if (resourceFormName && resourceFormName.length > 0) {
1311
+ if (formtype === 'create') {
1312
+ if (formname && formname.length > 0) {
1129
1313
  this.pageBuilderStateStore.setLocalStorageItemName(
1130
- `page-builder-create-resource-${this.sanitizeForLocalStorage(resourceFormName)}`,
1314
+ `page-builder-create-resource-${this.sanitizeForLocalStorage(formname)}`,
1131
1315
  )
1132
1316
  return
1133
1317
  }
@@ -1138,15 +1322,15 @@ export class PageBuilderService {
1138
1322
 
1139
1323
  // Logic for create
1140
1324
  // Logic for update and with resource form name
1141
- if (updateOrCreate === 'update') {
1142
- if (typeof resourceFormName === 'string' && resourceFormName.length > 0) {
1325
+ if (formtype === 'update') {
1326
+ if (typeof formname === 'string' && formname.length > 0) {
1143
1327
  //
1144
1328
  //
1145
1329
  if (resourceData && resourceData != null && !resourceData.title) {
1146
1330
  // Check if id is missing, null, undefined, or an empty string (after trimming)
1147
1331
  if (!resourceData.id || typeof resourceData.id === 'string') {
1148
1332
  this.pageBuilderStateStore.setLocalStorageItemName(
1149
- `page-builder-update-resource-${this.sanitizeForLocalStorage(resourceFormName)}`,
1333
+ `page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}`,
1150
1334
  )
1151
1335
  return
1152
1336
  }
@@ -1161,7 +1345,7 @@ export class PageBuilderService {
1161
1345
  ) {
1162
1346
  if (!resourceData.id || typeof resourceData.id === 'string') {
1163
1347
  this.pageBuilderStateStore.setLocalStorageItemName(
1164
- `page-builder-update-resource-${this.sanitizeForLocalStorage(resourceFormName)}-${this.sanitizeForLocalStorage(resourceData.title)}`,
1348
+ `page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(resourceData.title)}`,
1165
1349
  )
1166
1350
  return
1167
1351
  }
@@ -1173,7 +1357,7 @@ export class PageBuilderService {
1173
1357
  if (!resourceData.title && typeof resourceData.title !== 'string') {
1174
1358
  if (resourceData.id || typeof resourceData.id === 'number') {
1175
1359
  this.pageBuilderStateStore.setLocalStorageItemName(
1176
- `page-builder-update-resource-${this.sanitizeForLocalStorage(resourceFormName)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
1360
+ `page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
1177
1361
  )
1178
1362
  return
1179
1363
  }
@@ -1189,7 +1373,7 @@ export class PageBuilderService {
1189
1373
  ) {
1190
1374
  if (resourceData.id || typeof resourceData.id === 'number') {
1191
1375
  this.pageBuilderStateStore.setLocalStorageItemName(
1192
- `page-builder-update-resource-${this.sanitizeForLocalStorage(resourceFormName)}-${this.sanitizeForLocalStorage(resourceData.title)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
1376
+ `page-builder-update-resource-${this.sanitizeForLocalStorage(formname)}-${this.sanitizeForLocalStorage(resourceData.title)}-${this.sanitizeForLocalStorage(String(resourceData.id))}`,
1193
1377
  )
1194
1378
  return
1195
1379
  }
@@ -1197,11 +1381,8 @@ export class PageBuilderService {
1197
1381
  }
1198
1382
  }
1199
1383
 
1200
- // Logic for update without without resourceFormName
1201
- if (
1202
- !resourceFormName ||
1203
- (typeof resourceFormName === 'string' && resourceFormName.length === 0)
1204
- ) {
1384
+ // Logic for update without without formname
1385
+ if (!formname || (typeof formname === 'string' && formname.length === 0)) {
1205
1386
  //
1206
1387
  //
1207
1388
  if (resourceData && resourceData != null && !resourceData.title) {
@@ -1304,6 +1485,7 @@ export class PageBuilderService {
1304
1485
  * Saves the current DOM state (components) to localStorage.
1305
1486
  */
1306
1487
  #saveDomComponentsToLocalStorage() {
1488
+ this.#updateLocalStorageItemName()
1307
1489
  const pagebuilder = document.querySelector('#pagebuilder')
1308
1490
  if (!pagebuilder) return
1309
1491
 
@@ -1338,6 +1520,7 @@ export class PageBuilderService {
1338
1520
  }
1339
1521
 
1340
1522
  async removeCurrentComponentsFromLocalStorage() {
1523
+ this.#updateLocalStorageItemName()
1341
1524
  await nextTick()
1342
1525
 
1343
1526
  const key = this.getLocalStorageItemName.value
@@ -1348,12 +1531,10 @@ export class PageBuilderService {
1348
1531
 
1349
1532
  //
1350
1533
  deleteOldPageBuilderLocalStorage(): void {
1351
- if (
1352
- this.pageBuilderStateStore.getPageBuilderConfig &&
1353
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1354
- typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1355
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1356
- ) {
1534
+ const config = this.pageBuilderStateStore.getPageBuilderConfig
1535
+ const formType = config && config.updateOrCreate && config.updateOrCreate.formType
1536
+
1537
+ if (formType === 'update') {
1357
1538
  let oldCountLocalStorages = 0
1358
1539
  const deletedItemsLog: { Number: number; Key: string; SavedAt: string }[] = []
1359
1540
 
@@ -1401,38 +1582,6 @@ export class PageBuilderService {
1401
1582
  }
1402
1583
  }
1403
1584
 
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
1585
  // Call this when the user starts editing (e.g., on first change or when resuming a draft)
1437
1586
  startEditing() {
1438
1587
  this.hasStartedEditing = true
@@ -1440,40 +1589,49 @@ export class PageBuilderService {
1440
1589
 
1441
1590
  //
1442
1591
  async resumeEditingForUpdate() {
1443
- if (
1444
- this.pageBuilderStateStore.getPageBuilderConfig &&
1445
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1446
- typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1447
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1448
- ) {
1449
- const key = this.getLocalStorageItemName.value
1592
+ this.#updateLocalStorageItemName()
1593
+ const config = this.pageBuilderStateStore.getPageBuilderConfig
1594
+ const formType = config && config.updateOrCreate && config.updateOrCreate.formType
1595
+
1596
+ if (formType !== 'update') return
1597
+ //
1598
+ //
1599
+ //
1450
1600
 
1451
- if (typeof key === 'string') {
1452
- const updateDraftFromLocalStorage = localStorage.getItem(key)
1601
+ const key = this.getLocalStorageItemName.value
1453
1602
 
1454
- if (typeof updateDraftFromLocalStorage === 'string') {
1455
- this.pageBuilderStateStore.setIsLoadingResumeEditing(true)
1456
- await delay(500)
1457
- this.mountComponentsToDOM(updateDraftFromLocalStorage)
1458
- this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
1459
- }
1603
+ if (typeof key === 'string') {
1604
+ const updateDraftFromLocalStorage = localStorage.getItem(key)
1605
+
1606
+ if (typeof updateDraftFromLocalStorage === 'string') {
1607
+ this.pageBuilderStateStore.setIsLoadingResumeEditing(true)
1608
+ await delay(300)
1609
+ await this.#updateComponentsFromString(updateDraftFromLocalStorage)
1610
+ this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
1460
1611
  }
1461
1612
  }
1613
+
1614
+ // Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
1615
+ await nextTick()
1616
+ // Attach event listeners to all editable elements in the Builder
1617
+ await this.#addListenersToEditableElements()
1618
+ // set loading to false
1619
+ this.pageBuilderStateStore.setIsLoadingResumeEditing(false)
1462
1620
  }
1463
1621
 
1464
1622
  async restoreOriginalContent() {
1465
- if (
1466
- this.pageBuilderStateStore.getPageBuilderConfig &&
1467
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate &&
1468
- typeof this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'string' &&
1469
- this.pageBuilderStateStore.getPageBuilderConfig.updateOrCreate.formType === 'update'
1470
- ) {
1623
+ this.#updateLocalStorageItemName()
1624
+ const config = this.pageBuilderStateStore.getPageBuilderConfig
1625
+ const formType = config && config.updateOrCreate && config.updateOrCreate.formType
1626
+
1627
+ if (formType === 'update') {
1471
1628
  this.pageBuilderStateStore.setIsRestoring(true)
1472
1629
  await this.delay(300)
1473
1630
 
1474
1631
  // Restore the original content if available
1475
- if (this.originalComponents) {
1476
- this.mountComponentsToDOM(this.originalComponents)
1632
+ if (Array.isArray(this.originalComponents)) {
1633
+ await this.#mountPassedComponentsToDOM(this.originalComponents)
1634
+ this.removeCurrentComponentsFromLocalStorage()
1477
1635
  }
1478
1636
 
1479
1637
  // Wait for Vue to finish DOM updates before attaching event listeners. This ensure elements exist in the DOM.
@@ -1490,6 +1648,7 @@ export class PageBuilderService {
1490
1648
  }
1491
1649
 
1492
1650
  loadStoredComponentsFromStorage() {
1651
+ this.#updateLocalStorageItemName()
1493
1652
  if (!this.getLocalStorageItemName.value) return false
1494
1653
 
1495
1654
  if (
@@ -1784,19 +1943,22 @@ export class PageBuilderService {
1784
1943
  * @param data - JSON string (e.g., '[{"html_code":"...","id":"123","title":"..."}]')
1785
1944
  * OR HTML string (e.g., '<section data-componentid="123">...</section>')
1786
1945
  */
1787
- async #setComponentsFromData(htmlString: string): Promise<void> {
1946
+ async #updateComponentsFromString(htmlString: string): Promise<void> {
1788
1947
  // Auto-detect if input is JSON or HTML
1789
1948
  const trimmedData = htmlString.trim()
1790
1949
 
1791
1950
  if (trimmedData.startsWith('[') || trimmedData.startsWith('{')) {
1792
1951
  // Looks like JSON - parse as JSON
1793
1952
  await this.#parseJSONComponents(trimmedData)
1794
- } else if (trimmedData.startsWith('<')) {
1953
+ return
1954
+ }
1955
+ if (trimmedData.startsWith('<')) {
1795
1956
  // Looks like HTML - parse as HTML
1796
1957
  await this.#parseHTMLComponents(trimmedData)
1797
- } else {
1798
- await this.#parseJSONComponents(trimmedData)
1958
+ return
1799
1959
  }
1960
+
1961
+ await this.#parseJSONComponents(trimmedData)
1800
1962
  }
1801
1963
 
1802
1964
  // Private method to parse JSON components and save pageBuilderContentSavedAt to localStorage
@@ -1917,145 +2079,6 @@ export class PageBuilderService {
1917
2079
  }
1918
2080
  }
1919
2081
 
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
2082
  async toggleTipTapModal(status: boolean): Promise<void> {
2060
2083
  this.pageBuilderStateStore.setShowModalTipTap(status)
2061
2084