@myissue/vue-website-page-builder 3.2.77 → 3.2.79

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myissue/vue-website-page-builder",
3
- "version": "v3.2.77",
3
+ "version": "v3.2.79",
4
4
  "description": "Vue 3 page builder component with drag & drop functionality.",
5
5
  "type": "module",
6
6
  "main": "./dist/vue-website-page-builder.umd.cjs",
@@ -17,6 +17,11 @@ defineProps({
17
17
  default: false,
18
18
  required: false,
19
19
  },
20
+ isLoading: {
21
+ type: Boolean,
22
+ default: false,
23
+ required: false,
24
+ },
20
25
  disabledWhichButton: {
21
26
  type: String,
22
27
  default: '',
@@ -97,7 +102,7 @@ const thirdButtonBuilder = function () {
97
102
  </div>
98
103
  </div>
99
104
 
100
- <template v-if="simpleModal !== true">
105
+ <template v-if="simpleModal !== true && !isLoading">
101
106
  <div class="py-4 flex sm:justify-end justify-center border-t border-gray-200 mt-4">
102
107
  <slot name="footer" />
103
108
  <div
@@ -362,6 +367,18 @@ const thirdButtonBuilder = function () {
362
367
  </div>
363
368
  </div>
364
369
  </template>
370
+ <template v-if="isLoading">
371
+ <div class="flex items-center my-2 py-4 px-2 justify-end">
372
+ <div
373
+ class="inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-current border-r-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite]"
374
+ >
375
+ <span
376
+ class="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]"
377
+ >Loading...</span
378
+ >
379
+ </div>
380
+ </div>
381
+ </template>
365
382
  </ModalBuilder>
366
383
  </template>
367
384
 
@@ -71,7 +71,7 @@ const configPageBuilder = {
71
71
  image: '/jane_doe.jpg',
72
72
  },
73
73
  updateOrCreate: {
74
- formType: 'create' as 'create',
74
+ formType: 'update' as 'update',
75
75
  formName: 'news',
76
76
  },
77
77
  pageBuilderLogo: {
@@ -12,12 +12,13 @@ import { updateOrCreateIsFalsy } from '../helpers/passedPageBuilderConfig'
12
12
  import ToolbarOption from '../Components/PageBuilder/ToolbarOption/ToolbarOption.vue'
13
13
  import { delay } from '../composables/delay'
14
14
  import { useDebounce } from '../composables/useDebounce.ts'
15
+ import DynamicModalBuilder from '../Components/Modals/DynamicModalBuilder.vue'
15
16
 
16
17
  /**
17
18
  * Props for PageBuilder component
18
19
  * @typedef {Object} Props
19
20
  * @property {Object|null} CustomMediaLibraryComponent - Custom media component
20
- * @property {Object|null} CustomBuilderComponents - Custom search component
21
+ * @property {Object|null} CustomBuilderComponents - Custom component
21
22
  * @property {Object} configPageBuilder - Configuration object containing:
22
23
  */
23
24
  const props = defineProps({
@@ -192,6 +193,47 @@ watch(
192
193
  },
193
194
  { immediate: true },
194
195
  )
196
+ const gridColumnModalResumeEditing = ref(Number(1))
197
+ const typeModal = ref('')
198
+ const showModalResumeEditing = ref(false)
199
+ const titleModalResumeEditing = ref('')
200
+ const descriptionModalResumeEditing = ref('')
201
+ const firstButtonResumeEditing = ref('')
202
+ const secondButtonResumeEditing = ref(null)
203
+ const thirdButtonResumeEditing = ref(null)
204
+ const firstModalButtonResumeEditingFunction = ref(null)
205
+ const secondModalButtonResumeEditingFunction = ref(null)
206
+ const thirdModalButtonResumeEditingFunction = ref(null)
207
+
208
+ const isLoadingResumeEditing = ref(null)
209
+
210
+ const handlerRumeEditingForUpdate = async function () {
211
+ await pageBuilderClass.clearHtmlSelection()
212
+
213
+ typeModal.value = 'default'
214
+ titleModalResumeEditing.value = 'Continue Your Work?'
215
+ descriptionModalResumeEditing.value =
216
+ 'We noticed you have some changes that weren’t saved last time. Would you like to pick up where you left off, or use the version that’s currently saved?'
217
+ firstButtonResumeEditing.value = 'Use Saved Version'
218
+ secondButtonResumeEditing.value = null
219
+ thirdButtonResumeEditing.value = 'Continue Where I Left Off'
220
+ showModalResumeEditing.value = true
221
+
222
+ firstModalButtonResumeEditingFunction.value = function () {
223
+ showModalResumeEditing.value = false
224
+ }
225
+
226
+ secondModalButtonResumeEditingFunction.value = function () {}
227
+ thirdModalButtonResumeEditingFunction.value = async function () {
228
+ isLoadingResumeEditing.value = true
229
+ await delay(1000)
230
+ await pageBuilderClass.resumeEditingForUpdate()
231
+ isLoadingResumeEditing.value = false
232
+ showModalResumeEditing.value = false
233
+ }
234
+
235
+ // end modal
236
+ }
195
237
 
196
238
  onMounted(async () => {
197
239
  const config = getConfigPageBuilder.value
@@ -204,6 +246,10 @@ onMounted(async () => {
204
246
  await pageBuilderClass.clearHtmlSelection()
205
247
 
206
248
  await pageBuilderClass.setEventListenersForElements()
249
+
250
+ if (await pageBuilderClass.hasLocalDraftForUpdate()) {
251
+ handlerRumeEditingForUpdate()
252
+ }
207
253
  })
208
254
  </script>
209
255
 
@@ -266,6 +312,24 @@ onMounted(async () => {
266
312
  <Preview></Preview>
267
313
  </ModalBuilder>
268
314
 
315
+ <DynamicModalBuilder
316
+ :showDynamicModalBuilder="showModalResumeEditing"
317
+ :isLoading="isLoadingResumeEditing"
318
+ :type="typeModal"
319
+ :gridColumnAmount="gridColumnModalResumeEditing"
320
+ :title="titleModalResumeEditing"
321
+ :description="descriptionModalResumeEditing"
322
+ :firstButtonText="firstButtonResumeEditing"
323
+ :secondButtonText="secondButtonResumeEditing"
324
+ :thirdButtonText="thirdButtonResumeEditing"
325
+ @firstModalButtonFunctionDynamicModalBuilder="firstModalButtonResumeEditingFunction"
326
+ @secondModalButtonFunctionDynamicModalBuilder="secondModalButtonResumeEditingFunction"
327
+ @thirdModalButtonFunctionDynamicModalBuilder="thirdModalButtonResumeEditingFunction"
328
+ >
329
+ <header></header>
330
+ <main></main>
331
+ </DynamicModalBuilder>
332
+
269
333
  <div>
270
334
  <div class="relative h-full flex pb-2 gap-2">
271
335
  <div
@@ -306,7 +370,7 @@ onMounted(async () => {
306
370
  class="flex myPrimaryGap items-center pt-4 pb-2 pl-2 h-24 w-full min-w-36"
307
371
  >
308
372
  <button
309
- class="myPrimaryButton h-6 flex gap-2"
373
+ class="mySecondaryButton h-6 flex gap-2"
310
374
  @click.stop="
311
375
  async () => {
312
376
  await pageBuilderClass.clearHtmlSelection()
@@ -335,6 +399,8 @@ onMounted(async () => {
335
399
  </div>
336
400
  <div>Save</div>
337
401
  </button>
402
+
403
+ <!-- Continue editing # end -->
338
404
  </div>
339
405
 
340
406
  <div
@@ -46,10 +46,13 @@ class PageBuilderClass {
46
46
  private NoneListernesTags: string[]
47
47
  private delay: (ms?: number) => Promise<void>
48
48
  private observer?: MutationObserverType
49
+ private hasStartedEditing: boolean = false
49
50
 
50
51
  constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>) {
51
52
  this.nextTick = nextTick()
52
53
 
54
+ this.hasStartedEditing = false
55
+
53
56
  this.containsPagebuilder = document.querySelector('#contains-pagebuilder')
54
57
 
55
58
  this.pageBuilderStateStore = pageBuilderStateStore
@@ -275,6 +278,7 @@ class PageBuilderClass {
275
278
  }
276
279
 
277
280
  handleAutoSave = async () => {
281
+ this.startEditing()
278
282
  const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
279
283
 
280
284
  // Check if config is set
@@ -312,6 +316,7 @@ class PageBuilderClass {
312
316
  }
313
317
 
314
318
  handleManualSave = async () => {
319
+ this.startEditing()
315
320
  const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
316
321
 
317
322
  // Check if config is set
@@ -1215,6 +1220,66 @@ class PageBuilderClass {
1215
1220
  }
1216
1221
  }
1217
1222
 
1223
+ async hasLocalDraftForUpdate(): Promise<boolean> {
1224
+ if (this.hasStartedEditing) return false
1225
+
1226
+ if (
1227
+ this.pageBuilderStateStore.getConfigPageBuilder &&
1228
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1229
+ typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1230
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1231
+ ) {
1232
+ const key = this.getLocalStorageItemName.value
1233
+ if (typeof key === 'string') {
1234
+ const draft = localStorage.getItem(key)
1235
+ if (draft) {
1236
+ try {
1237
+ await this.delay(1000)
1238
+ const draftParsed = JSON.parse(draft)
1239
+ const dbComponents = this.getComponents.value
1240
+ return JSON.stringify(draftParsed.components) !== JSON.stringify(dbComponents)
1241
+ } catch (e) {
1242
+ return false
1243
+ }
1244
+ }
1245
+ }
1246
+ }
1247
+ return false
1248
+ }
1249
+
1250
+ // Call this when the user starts editing (e.g., on first change or when resuming a draft)
1251
+ startEditing() {
1252
+ this.hasStartedEditing = true
1253
+ }
1254
+
1255
+ async resumeEditingForUpdate() {
1256
+ if (
1257
+ this.pageBuilderStateStore.getConfigPageBuilder &&
1258
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1259
+ typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1260
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1261
+ ) {
1262
+ const key = this.getLocalStorageItemName.value
1263
+ if (typeof key === 'string') {
1264
+ const savedCurrentDesign = localStorage.getItem(key)
1265
+ if (savedCurrentDesign) {
1266
+ try {
1267
+ const parsed = JSON.parse(savedCurrentDesign)
1268
+ if (parsed && Array.isArray(parsed.components)) {
1269
+ this.pageBuilderStateStore.setComponents(parsed.components)
1270
+ localStorage.removeItem(key)
1271
+ await nextTick()
1272
+ await this.setEventListenersForElements()
1273
+ await this.handleAutoSave()
1274
+ }
1275
+ } catch (e) {
1276
+ console.error('Failed to parse local draft:', e)
1277
+ }
1278
+ }
1279
+ }
1280
+ }
1281
+ }
1282
+
1218
1283
  getStorageItemNameForResource(): string | null {
1219
1284
  return this.getLocalStorageItemName.value
1220
1285
  }
@@ -1223,6 +1288,7 @@ class PageBuilderClass {
1223
1288
 
1224
1289
  if (
1225
1290
  this.getLocalStorageItemName.value &&
1291
+ typeof this.getLocalStorageItemName.value === 'string' &&
1226
1292
  localStorage.getItem(this.getLocalStorageItemName.value)
1227
1293
  ) {
1228
1294
  const savedCurrentDesign = localStorage.getItem(this.getLocalStorageItemName.value)