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

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.78",
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
@@ -50,6 +50,8 @@ class PageBuilderClass {
50
50
  constructor(pageBuilderStateStore: ReturnType<typeof usePageBuilderStateStore>) {
51
51
  this.nextTick = nextTick()
52
52
 
53
+ this.hasStartedEditing = false
54
+
53
55
  this.containsPagebuilder = document.querySelector('#contains-pagebuilder')
54
56
 
55
57
  this.pageBuilderStateStore = pageBuilderStateStore
@@ -275,6 +277,7 @@ class PageBuilderClass {
275
277
  }
276
278
 
277
279
  handleAutoSave = async () => {
280
+ this.startEditing()
278
281
  const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
279
282
 
280
283
  // Check if config is set
@@ -312,6 +315,7 @@ class PageBuilderClass {
312
315
  }
313
316
 
314
317
  handleManualSave = async () => {
318
+ this.startEditing()
315
319
  const passedConfig = this.pageBuilderStateStore.getConfigPageBuilder
316
320
 
317
321
  // Check if config is set
@@ -1215,6 +1219,66 @@ class PageBuilderClass {
1215
1219
  }
1216
1220
  }
1217
1221
 
1222
+ async hasLocalDraftForUpdate(): boolean {
1223
+ if (this.hasStartedEditing) return false
1224
+
1225
+ if (
1226
+ this.pageBuilderStateStore.getConfigPageBuilder &&
1227
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1228
+ typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1229
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1230
+ ) {
1231
+ const key = this.getLocalStorageItemName.value
1232
+ if (typeof key === 'string') {
1233
+ const draft = localStorage.getItem(key)
1234
+ if (draft) {
1235
+ try {
1236
+ await this.delay(1000)
1237
+ const draftParsed = JSON.parse(draft)
1238
+ const dbComponents = this.getComponents.value
1239
+ return JSON.stringify(draftParsed.components) !== JSON.stringify(dbComponents)
1240
+ } catch (e) {
1241
+ return false
1242
+ }
1243
+ }
1244
+ }
1245
+ }
1246
+ return false
1247
+ }
1248
+
1249
+ // Call this when the user starts editing (e.g., on first change or when resuming a draft)
1250
+ startEditing() {
1251
+ this.hasStartedEditing = true
1252
+ }
1253
+
1254
+ async resumeEditingForUpdate() {
1255
+ if (
1256
+ this.pageBuilderStateStore.getConfigPageBuilder &&
1257
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate &&
1258
+ typeof this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'string' &&
1259
+ this.pageBuilderStateStore.getConfigPageBuilder.updateOrCreate.formType === 'update'
1260
+ ) {
1261
+ const key = this.getLocalStorageItemName.value
1262
+ if (typeof key === 'string') {
1263
+ const savedCurrentDesign = localStorage.getItem(key)
1264
+ if (savedCurrentDesign) {
1265
+ try {
1266
+ const parsed = JSON.parse(savedCurrentDesign)
1267
+ if (parsed && Array.isArray(parsed.components)) {
1268
+ this.pageBuilderStateStore.setComponents(parsed.components)
1269
+ localStorage.removeItem(key)
1270
+ await nextTick()
1271
+ await this.setEventListenersForElements()
1272
+ await this.handleAutoSave()
1273
+ }
1274
+ } catch (e) {
1275
+ console.error('Failed to parse local draft:', e)
1276
+ }
1277
+ }
1278
+ }
1279
+ }
1280
+ }
1281
+
1218
1282
  getStorageItemNameForResource(): string | null {
1219
1283
  return this.getLocalStorageItemName.value
1220
1284
  }
@@ -1223,6 +1287,7 @@ class PageBuilderClass {
1223
1287
 
1224
1288
  if (
1225
1289
  this.getLocalStorageItemName.value &&
1290
+ typeof this.getLocalStorageItemName.value === 'string' &&
1226
1291
  localStorage.getItem(this.getLocalStorageItemName.value)
1227
1292
  ) {
1228
1293
  const savedCurrentDesign = localStorage.getItem(this.getLocalStorageItemName.value)