@myissue/vue-website-page-builder 3.3.96 → 3.3.97
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/dist/style.css +1 -1
- package/dist/vue-website-page-builder.js +6238 -6168
- package/dist/vue-website-page-builder.umd.cjs +55 -55
- package/package.json +1 -1
- package/src/Components/PageBuilder/EditorMenu/Editables/ComponentTopMenu.vue +18 -3
- package/src/Components/PageBuilder/UndoRedo/UndoRedo.vue +50 -9
- package/src/PageBuilder/PageBuilder.vue +15 -15
- package/src/css/style.css +28 -0
- package/src/services/PageBuilderService.ts +76 -12
- package/src/stores/page-builder-state.ts +12 -0
- package/src/tests/DefaultComponents/DefaultBuilderComponents.vue +1 -1
- package/src/tests/pageBuilderService.test.ts +110 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import DynamicModalBuilder from '../../../Modals/DynamicModalBuilder.vue'
|
|
3
|
-
import { ref } from 'vue'
|
|
3
|
+
import { ref, computed } from 'vue'
|
|
4
4
|
import { getPageBuilder } from '../../../../composables/builderInstance'
|
|
5
5
|
import { useTranslations } from '../../../../composables/useTranslations'
|
|
6
6
|
|
|
@@ -22,6 +22,9 @@ const firstModalButtonFunctionDynamicModalBuilder = ref(null)
|
|
|
22
22
|
const secondModalButtonFunctionDynamicModalBuilder = ref(null)
|
|
23
23
|
const thirdModalButtonFunctionDynamicModalBuilder = ref(null)
|
|
24
24
|
|
|
25
|
+
const canMoveUp = computed(() => pageBuilderService.canMoveUp())
|
|
26
|
+
const canMoveDown = computed(() => pageBuilderService.canMoveDown())
|
|
27
|
+
|
|
25
28
|
// remove component
|
|
26
29
|
const handleDelete = function () {
|
|
27
30
|
showModalDeleteComponent.value = true
|
|
@@ -78,14 +81,26 @@ const handleDelete = function () {
|
|
|
78
81
|
<button
|
|
79
82
|
type="button"
|
|
80
83
|
@click="pageBuilderService.reorderComponent(-1)"
|
|
81
|
-
|
|
84
|
+
:disabled="!canMoveUp"
|
|
85
|
+
class="pbx-h-10 pbx-w-10 pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square pbx-text-black"
|
|
86
|
+
:class="[
|
|
87
|
+
canMoveUp
|
|
88
|
+
? 'hover:pbx-bg-myPrimaryLinkColor hover:pbx-text-white focus-visible:pbx-ring-0'
|
|
89
|
+
: 'pbx-cursor-not-allowed pbx-bg-opacity-20 hover:pbx-bg-gray-200',
|
|
90
|
+
]"
|
|
82
91
|
>
|
|
83
92
|
<span class="material-symbols-outlined"> move_up </span>
|
|
84
93
|
</button>
|
|
85
94
|
<button
|
|
86
95
|
type="button"
|
|
87
96
|
@click="pageBuilderService.reorderComponent(1)"
|
|
88
|
-
|
|
97
|
+
:disabled="!canMoveDown"
|
|
98
|
+
class="pbx-h-10 pbx-w-10 pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square pbx-text-black"
|
|
99
|
+
:class="[
|
|
100
|
+
canMoveDown
|
|
101
|
+
? 'hover:pbx-bg-myPrimaryLinkColor hover:pbx-text-white focus-visible:pbx-ring-0'
|
|
102
|
+
: 'pbx-cursor-not-allowed pbx-bg-opacity-20 hover:pbx-bg-gray-200',
|
|
103
|
+
]"
|
|
89
104
|
>
|
|
90
105
|
<span class="material-symbols-outlined"> move_down </span>
|
|
91
106
|
</button>
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
<script setup>
|
|
2
|
-
import { computed } from 'vue'
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref } from 'vue'
|
|
3
3
|
import { sharedPageBuilderStore } from '../../../stores/shared-store'
|
|
4
4
|
import GlobalLoader from '../../../Components/Loaders/GlobalLoader.vue'
|
|
5
5
|
import { getPageBuilder } from '../../../composables/builderInstance'
|
|
6
6
|
|
|
7
7
|
const pageBuilderService = getPageBuilder()
|
|
8
8
|
|
|
9
|
+
const emit = defineEmits(['toolbar-hide-request'])
|
|
10
|
+
|
|
9
11
|
// Use shared store instance
|
|
10
12
|
const pageBuilderStateStore = sharedPageBuilderStore
|
|
11
13
|
|
|
@@ -13,30 +15,69 @@ const getIsLoadingGlobal = computed(() => {
|
|
|
13
15
|
return pageBuilderStateStore.getIsLoadingGlobal
|
|
14
16
|
})
|
|
15
17
|
|
|
18
|
+
const historyIndex = computed(() => pageBuilderStateStore.getHistoryIndex)
|
|
19
|
+
const historyLength = computed(() => pageBuilderStateStore.getHistoryLength)
|
|
20
|
+
|
|
21
|
+
const canUndo = computed(() => historyIndex.value > 0)
|
|
22
|
+
const canRedo = computed(() => historyIndex.value < historyLength.value - 1)
|
|
23
|
+
|
|
16
24
|
const handleUndo = async function () {
|
|
17
|
-
|
|
25
|
+
if (canUndo.value) {
|
|
26
|
+
// Emit event to hide toolbar
|
|
27
|
+
emit('toolbar-hide-request')
|
|
28
|
+
await pageBuilderService.undo()
|
|
29
|
+
await pageBuilderService.clearHtmlSelection()
|
|
30
|
+
}
|
|
18
31
|
}
|
|
32
|
+
|
|
19
33
|
const handleRedo = async function () {
|
|
20
|
-
|
|
34
|
+
if (canRedo.value) {
|
|
35
|
+
// Emit event to hide toolbar
|
|
36
|
+
emit('toolbar-hide-request')
|
|
37
|
+
await pageBuilderService.redo()
|
|
38
|
+
await pageBuilderService.clearHtmlSelection()
|
|
39
|
+
}
|
|
21
40
|
}
|
|
22
41
|
</script>
|
|
23
42
|
|
|
24
43
|
<template>
|
|
25
44
|
<GlobalLoader v-if="getIsLoadingGlobal"></GlobalLoader>
|
|
26
|
-
<div
|
|
45
|
+
<div
|
|
46
|
+
@click="
|
|
47
|
+
async () => {
|
|
48
|
+
await pageBuilderService.clearHtmlSelection()
|
|
49
|
+
}
|
|
50
|
+
"
|
|
51
|
+
class="pbx-flex-1 pbx-flex pbx-justify-center pbx-items-center pbx-py-2 pbx-w-full gap-1"
|
|
52
|
+
>
|
|
27
53
|
<!-- Undo Start -->
|
|
28
|
-
<button @click="handleUndo" type="button">
|
|
54
|
+
<button @click="handleUndo" type="button" :disabled="!canUndo">
|
|
29
55
|
<div
|
|
30
|
-
class="pbx-h-10 pbx-w-10 pbx-
|
|
56
|
+
class="pbx-h-10 pbx-w-10 pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square pbx-text-black hover:pbx-text-white"
|
|
57
|
+
:class="[
|
|
58
|
+
canUndo
|
|
59
|
+
? 'pbx-cursor-pointer hover:pbx-bg-myPrimaryLinkColor focus-visible:pbx-ring-0'
|
|
60
|
+
: 'pbx-cursor-not-allowed pbx-bg-opacity-20 hover:pbx-bg-gray-200',
|
|
61
|
+
]"
|
|
31
62
|
>
|
|
32
63
|
<span class="material-symbols-outlined"> undo </span>
|
|
33
64
|
</div>
|
|
34
65
|
</button>
|
|
35
66
|
<!-- Undo End -->
|
|
67
|
+
<div
|
|
68
|
+
class="pbx-text-xs pbx-text-gray-600 pbx-mx-2 pbx-py-3 pbx-px-2 pbx-border-solid pbx-border pbx-border-gray-200 pbx-rounded-full"
|
|
69
|
+
>
|
|
70
|
+
{{ historyIndex + 1 }}/{{ historyLength }}
|
|
71
|
+
</div>
|
|
36
72
|
<!-- Redo Start -->
|
|
37
|
-
<button @click="handleRedo" type="button">
|
|
73
|
+
<button @click="handleRedo" type="button" :disabled="!canRedo">
|
|
38
74
|
<div
|
|
39
|
-
class="pbx-h-10 pbx-w-10 pbx-
|
|
75
|
+
class="pbx-h-10 pbx-w-10 pbx-rounded-full pbx-flex pbx-items-center pbx-border-none pbx-justify-center pbx-bg-gray-50 pbx-aspect-square pbx-text-black hover:pbx-text-white"
|
|
76
|
+
:class="[
|
|
77
|
+
canRedo
|
|
78
|
+
? 'pbx-cursor-pointer hover:pbx-bg-myPrimaryLinkColor focus-visible:pbx-ring-0'
|
|
79
|
+
: 'pbx-cursor-not-allowed pbx-bg-opacity-20 hover:pbx-bg-gray-200',
|
|
80
|
+
]"
|
|
40
81
|
>
|
|
41
82
|
<span class="material-symbols-outlined"> redo </span>
|
|
42
83
|
</div>
|
|
@@ -320,12 +320,18 @@ const ensureBuilderInitialized = function () {
|
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
323
|
+
const pbxBuilderWrapper = ref(null)
|
|
324
|
+
|
|
325
|
+
const hideToolbar = function () {
|
|
326
|
+
const toolbar = document.querySelector('#pbxEditToolbar')
|
|
327
|
+
if (toolbar) {
|
|
328
|
+
toolbar.classList.remove('is-visible')
|
|
329
|
+
toolbar.removeAttribute('style')
|
|
330
|
+
}
|
|
331
|
+
}
|
|
326
332
|
|
|
327
333
|
function updatePanelPosition() {
|
|
328
|
-
const container =
|
|
334
|
+
const container = pbxBuilderWrapper.value
|
|
329
335
|
const editToolbarElement = container && container.querySelector('#pbxEditToolbar')
|
|
330
336
|
|
|
331
337
|
if (!container || !editToolbarElement) return
|
|
@@ -356,11 +362,9 @@ function updatePanelPosition() {
|
|
|
356
362
|
editToolbarElement.style.left = `${left}px`
|
|
357
363
|
editToolbarElement.style.top = `${top}px`
|
|
358
364
|
editToolbarElement.classList.add('is-visible')
|
|
359
|
-
|
|
360
|
-
lastToolbarLeft = left
|
|
361
|
-
lastToolbarTop = top
|
|
362
365
|
} else {
|
|
363
366
|
editToolbarElement.classList.remove('is-visible')
|
|
367
|
+
editToolbarElement.removeAttribute('style') // Ensure all styles are removed
|
|
364
368
|
}
|
|
365
369
|
}
|
|
366
370
|
|
|
@@ -389,7 +393,7 @@ onMounted(async () => {
|
|
|
389
393
|
updatePanelPosition()
|
|
390
394
|
|
|
391
395
|
// Set up MutationObserver and event listeners
|
|
392
|
-
const container =
|
|
396
|
+
const container = pbxBuilderWrapper.value
|
|
393
397
|
if (!container) return
|
|
394
398
|
|
|
395
399
|
const observer = new MutationObserver(updatePanelPosition)
|
|
@@ -528,7 +532,7 @@ onMounted(async () => {
|
|
|
528
532
|
</template>
|
|
529
533
|
<!-- Logo # end -->
|
|
530
534
|
|
|
531
|
-
<UndoRedo></UndoRedo>
|
|
535
|
+
<UndoRedo @toolbar-hide-request="hideToolbar"></UndoRedo>
|
|
532
536
|
|
|
533
537
|
<div
|
|
534
538
|
@click.self="
|
|
@@ -858,18 +862,14 @@ onMounted(async () => {
|
|
|
858
862
|
<!-- Left Menu End -->
|
|
859
863
|
|
|
860
864
|
<main
|
|
861
|
-
ref="
|
|
865
|
+
ref="pbxBuilderWrapper"
|
|
862
866
|
id="page-builder-wrapper"
|
|
863
|
-
class="pbx-transition-all pbx-duration-300 pbx-font-sans pbx-p-1 pbx-flex pbx-flex-col pbx-grow pbx-rounded-tr-2xl pbx-rounded-tl-2xl pbx-border-solid pbx-border pbx-border-gray-200 pbx-items-stretch pbx-text-black pbx-h-[100vh] pbx-overflow-y-
|
|
867
|
+
class="pbx-transition-all pbx-duration-300 pbx-font-sans pbx-p-1 pbx-flex pbx-flex-col pbx-grow pbx-rounded-tr-2xl pbx-rounded-tl-2xl pbx-border-solid pbx-border pbx-border-gray-200 pbx-items-stretch pbx-text-black pbx-h-[100vh] pbx-overflow-y-scroll pbx-relative pbx-pt-14"
|
|
864
868
|
:class="[getMenuRight ? 'pbx-w-full' : 'pbx-w-full']"
|
|
865
869
|
>
|
|
866
870
|
<div
|
|
867
871
|
id="pbxEditToolbar"
|
|
868
872
|
class="pbx-z-30 lg:pbx-mx-20 pbx-flex pbx-gap-2 pbx-justify-center pbx-items-center pbx-rounded pbx-px-4 pbx-bg-red-200 pbx-h-0"
|
|
869
|
-
style="
|
|
870
|
-
box-shadow: 0 0 0 10px oklch(86.9% 0.005 56.366);
|
|
871
|
-
background: oklch(86.9% 0.005 56.366);
|
|
872
|
-
"
|
|
873
873
|
>
|
|
874
874
|
<template v-if="getElement">
|
|
875
875
|
<EditGetElement></EditGetElement>
|
package/src/css/style.css
CHANGED
|
@@ -395,6 +395,8 @@
|
|
|
395
395
|
padding-right: 1rem;
|
|
396
396
|
padding-left: 1rem;
|
|
397
397
|
height: 2.2rem;
|
|
398
|
+
box-shadow: 0 0 0 10px oklch(86.9% 0.005 56.366);
|
|
399
|
+
background: oklch(86.9% 0.005 56.366);
|
|
398
400
|
}
|
|
399
401
|
|
|
400
402
|
/* CSS for content inside page builder # start */
|
|
@@ -476,3 +478,29 @@
|
|
|
476
478
|
list-style: disc !important;
|
|
477
479
|
padding: 0rem;
|
|
478
480
|
}
|
|
481
|
+
|
|
482
|
+
.pbx-reorder-highlight {
|
|
483
|
+
animation: pbx-reorder-flash 0.4s ease-in-out;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
@keyframes pbx-reorder-flash {
|
|
487
|
+
0% {
|
|
488
|
+
box-shadow: 0 0 0 0px rgba(66, 153, 225, 0.7);
|
|
489
|
+
transform: scale(1);
|
|
490
|
+
opacity: 1;
|
|
491
|
+
}
|
|
492
|
+
50% {
|
|
493
|
+
box-shadow: 0 0 0 10px rgba(66, 153, 225, 0);
|
|
494
|
+
transform: scale(0.2); /* Even more shrink */
|
|
495
|
+
opacity: 0.8;
|
|
496
|
+
}
|
|
497
|
+
100% {
|
|
498
|
+
box-shadow: 0 0 0 0px rgba(66, 153, 225, 0);
|
|
499
|
+
transform: scale(1);
|
|
500
|
+
opacity: 1;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.pbx-sibling-highlight {
|
|
505
|
+
border: 2px dashed #4299e1; /* Blue dashed border */
|
|
506
|
+
}
|
|
@@ -984,7 +984,6 @@ export class PageBuilderService {
|
|
|
984
984
|
await this.handleAutoSave()
|
|
985
985
|
}
|
|
986
986
|
|
|
987
|
-
private historyIndex: number = -1
|
|
988
987
|
private getHistoryBaseKey(): string | null {
|
|
989
988
|
return this.getLocalStorageItemName.value
|
|
990
989
|
}
|
|
@@ -993,7 +992,8 @@ export class PageBuilderService {
|
|
|
993
992
|
const baseKey = this.getHistoryBaseKey()
|
|
994
993
|
if (baseKey) {
|
|
995
994
|
const history = LocalStorageManager.getHistory(baseKey)
|
|
996
|
-
this.
|
|
995
|
+
this.pageBuilderStateStore.setHistoryIndex(history.length - 1)
|
|
996
|
+
this.pageBuilderStateStore.setHistoryLength(history.length)
|
|
997
997
|
}
|
|
998
998
|
}
|
|
999
999
|
|
|
@@ -1458,9 +1458,9 @@ export class PageBuilderService {
|
|
|
1458
1458
|
if (!baseKey) return
|
|
1459
1459
|
|
|
1460
1460
|
const history = LocalStorageManager.getHistory(baseKey)
|
|
1461
|
-
if (history.length > 1 && this.
|
|
1462
|
-
this.
|
|
1463
|
-
const data = history[this.
|
|
1461
|
+
if (history.length > 1 && this.pageBuilderStateStore.getHistoryIndex > 0) {
|
|
1462
|
+
this.pageBuilderStateStore.setHistoryIndex(this.pageBuilderStateStore.getHistoryIndex - 1)
|
|
1463
|
+
const data = history[this.pageBuilderStateStore.getHistoryIndex]
|
|
1464
1464
|
const htmlString = this.renderComponentsToHtml(data.components)
|
|
1465
1465
|
await this.mountComponentsToDOM(htmlString)
|
|
1466
1466
|
}
|
|
@@ -1474,9 +1474,9 @@ export class PageBuilderService {
|
|
|
1474
1474
|
if (!baseKey) return
|
|
1475
1475
|
|
|
1476
1476
|
const history = LocalStorageManager.getHistory(baseKey)
|
|
1477
|
-
if (history.length > 0 && this.
|
|
1478
|
-
this.
|
|
1479
|
-
const data = history[this.
|
|
1477
|
+
if (history.length > 0 && this.pageBuilderStateStore.getHistoryIndex < history.length - 1) {
|
|
1478
|
+
this.pageBuilderStateStore.setHistoryIndex(this.pageBuilderStateStore.getHistoryIndex + 1)
|
|
1479
|
+
const data = history[this.pageBuilderStateStore.getHistoryIndex]
|
|
1480
1480
|
const htmlString = this.renderComponentsToHtml(data.components)
|
|
1481
1481
|
await this.mountComponentsToDOM(htmlString)
|
|
1482
1482
|
}
|
|
@@ -1632,7 +1632,7 @@ export class PageBuilderService {
|
|
|
1632
1632
|
* Reorders the currently selected component up or down in the component list.
|
|
1633
1633
|
* @param {number} direction - The direction to move the component (-1 for up, 1 for down).
|
|
1634
1634
|
*/
|
|
1635
|
-
public reorderComponent(direction: number): void {
|
|
1635
|
+
public async reorderComponent(direction: number): Promise<void> {
|
|
1636
1636
|
if (!this.getComponents.value || !this.getComponent.value) return
|
|
1637
1637
|
|
|
1638
1638
|
if (this.getComponents.value.length <= 1) return
|
|
@@ -1660,6 +1660,69 @@ export class PageBuilderService {
|
|
|
1660
1660
|
// Move the component to the new position in the array.
|
|
1661
1661
|
this.getComponents.value.splice(currentIndex, 1)
|
|
1662
1662
|
this.getComponents.value.splice(newIndex, 0, componentToMove)
|
|
1663
|
+
|
|
1664
|
+
// Wait for the DOM to update after reordering
|
|
1665
|
+
await nextTick()
|
|
1666
|
+
|
|
1667
|
+
// Scroll to the moved component
|
|
1668
|
+
const pageBuilderWrapper = document.querySelector('#page-builder-wrapper')
|
|
1669
|
+
const movedComponentElement = pageBuilderWrapper?.querySelector(
|
|
1670
|
+
`section[data-componentid="${componentToMove.id}"]`,
|
|
1671
|
+
)
|
|
1672
|
+
|
|
1673
|
+
if (movedComponentElement) {
|
|
1674
|
+
// Apply highlight to the moved element
|
|
1675
|
+
movedComponentElement.classList.add('pbx-reorder-highlight')
|
|
1676
|
+
|
|
1677
|
+
// Highlight its new neighbors (if they exist)
|
|
1678
|
+
const prevSibling = movedComponentElement.previousElementSibling as HTMLElement
|
|
1679
|
+
const nextSibling = movedComponentElement.nextElementSibling as HTMLElement
|
|
1680
|
+
|
|
1681
|
+
if (prevSibling && prevSibling.tagName === 'SECTION') {
|
|
1682
|
+
prevSibling.classList.add('pbx-sibling-highlight')
|
|
1683
|
+
}
|
|
1684
|
+
if (nextSibling && nextSibling.tagName === 'SECTION') {
|
|
1685
|
+
nextSibling.classList.add('pbx-sibling-highlight')
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
// Scroll to the moved component
|
|
1689
|
+
movedComponentElement.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
|
1690
|
+
|
|
1691
|
+
// Remove highlights after a delay
|
|
1692
|
+
setTimeout(() => {
|
|
1693
|
+
movedComponentElement.classList.remove('pbx-reorder-highlight')
|
|
1694
|
+
if (prevSibling && prevSibling.tagName === 'SECTION') {
|
|
1695
|
+
prevSibling.classList.remove('pbx-sibling-highlight')
|
|
1696
|
+
}
|
|
1697
|
+
if (nextSibling && nextSibling.tagName === 'SECTION') {
|
|
1698
|
+
nextSibling.classList.remove('pbx-sibling-highlight')
|
|
1699
|
+
}
|
|
1700
|
+
}, 1000) // Adjust delay as needed
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* Checks if the currently selected component can be moved up.
|
|
1706
|
+
* @returns {boolean} True if the component can be moved up, false otherwise.
|
|
1707
|
+
*/
|
|
1708
|
+
public canMoveUp(): boolean {
|
|
1709
|
+
if (!this.getComponents.value || !this.getComponent.value) return false
|
|
1710
|
+
const currentIndex = this.getComponents.value.findIndex(
|
|
1711
|
+
(component) => component.id === this.getComponent.value?.id,
|
|
1712
|
+
)
|
|
1713
|
+
return currentIndex > 0
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
/**
|
|
1717
|
+
* Checks if the currently selected component can be moved down.
|
|
1718
|
+
* @returns {boolean} True if the component can be moved down, false otherwise.
|
|
1719
|
+
*/
|
|
1720
|
+
public canMoveDown(): boolean {
|
|
1721
|
+
if (!this.getComponents.value || !this.getComponent.value) return false
|
|
1722
|
+
const currentIndex = this.getComponents.value.findIndex(
|
|
1723
|
+
(component) => component.id === this.getComponent.value?.id,
|
|
1724
|
+
)
|
|
1725
|
+
return currentIndex < this.getComponents.value.length - 1
|
|
1663
1726
|
}
|
|
1664
1727
|
|
|
1665
1728
|
/**
|
|
@@ -1890,15 +1953,16 @@ export class PageBuilderService {
|
|
|
1890
1953
|
}
|
|
1891
1954
|
}
|
|
1892
1955
|
|
|
1893
|
-
if (this.
|
|
1894
|
-
history = history.slice(0, this.
|
|
1956
|
+
if (this.pageBuilderStateStore.getHistoryIndex < history.length - 1) {
|
|
1957
|
+
history = history.slice(0, this.pageBuilderStateStore.getHistoryIndex + 1)
|
|
1895
1958
|
}
|
|
1896
1959
|
history.push(dataToSave)
|
|
1897
1960
|
if (history.length > 10) {
|
|
1898
1961
|
history = history.slice(history.length - 10)
|
|
1899
1962
|
}
|
|
1900
1963
|
localStorage.setItem(baseKey + '-history', JSON.stringify(history))
|
|
1901
|
-
this.
|
|
1964
|
+
this.pageBuilderStateStore.setHistoryIndex(history.length - 1)
|
|
1965
|
+
this.pageBuilderStateStore.setHistoryLength(history.length)
|
|
1902
1966
|
}
|
|
1903
1967
|
}
|
|
1904
1968
|
/**
|
|
@@ -65,6 +65,8 @@ interface PageBuilderState {
|
|
|
65
65
|
isResumeEditing: boolean
|
|
66
66
|
isRestoring: boolean
|
|
67
67
|
currentLanguage: string | null
|
|
68
|
+
historyIndex: number
|
|
69
|
+
historyLength: number
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
@@ -125,6 +127,8 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
125
127
|
isResumeEditing: false,
|
|
126
128
|
isRestoring: false,
|
|
127
129
|
currentLanguage: null,
|
|
130
|
+
historyIndex: -1,
|
|
131
|
+
historyLength: 0,
|
|
128
132
|
}),
|
|
129
133
|
getters: {
|
|
130
134
|
// Core Page Builder Getters
|
|
@@ -273,6 +277,8 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
273
277
|
getIsLoadingResumeEditing: (state: PageBuilderState): boolean => state.isResumeEditing,
|
|
274
278
|
getIsRestoring: (state: PageBuilderState): boolean => state.isRestoring,
|
|
275
279
|
getCurrentLanguage: (state: PageBuilderState): string | null => state.currentLanguage,
|
|
280
|
+
getHistoryIndex: (state: PageBuilderState): number => state.historyIndex,
|
|
281
|
+
getHistoryLength: (state: PageBuilderState): number => state.historyLength,
|
|
276
282
|
},
|
|
277
283
|
actions: {
|
|
278
284
|
setComponentArrayAddMethod(payload: string | null): void {
|
|
@@ -473,5 +479,11 @@ export const usePageBuilderStateStore = defineStore('pageBuilderState', {
|
|
|
473
479
|
setCurrentLanguage(payload: string): void {
|
|
474
480
|
this.currentLanguage = payload
|
|
475
481
|
},
|
|
482
|
+
setHistoryIndex(payload: number): void {
|
|
483
|
+
this.historyIndex = payload
|
|
484
|
+
},
|
|
485
|
+
setHistoryLength(payload: number): void {
|
|
486
|
+
this.historyLength = payload
|
|
487
|
+
},
|
|
476
488
|
},
|
|
477
489
|
})
|
|
@@ -147,7 +147,7 @@ const getSvgPreview = (title: string) => {
|
|
|
147
147
|
v-for="category in categories"
|
|
148
148
|
:key="category"
|
|
149
149
|
@click="selectedCategory = category"
|
|
150
|
-
class="pbx-mySecondaryButton pbx-
|
|
150
|
+
class="pbx-mySecondaryButton pbx-text-xs pbx-px-4"
|
|
151
151
|
:class="{ active: selectedCategory === category }"
|
|
152
152
|
>
|
|
153
153
|
{{ translate(category) }}
|
|
@@ -5,20 +5,119 @@ import { usePageBuilderStateStore } from '../stores/page-builder-state'
|
|
|
5
5
|
import componentsArray from './componentsArray.test.json'
|
|
6
6
|
|
|
7
7
|
// Mock store (replace with your actual store or a better mock if needed)
|
|
8
|
-
const mockStore
|
|
8
|
+
const mockStore = {
|
|
9
|
+
// Mock getters
|
|
10
|
+
getApplyImageToSelection: { src: '' },
|
|
11
|
+
getLocalStorageItemName: 'test-key',
|
|
12
|
+
getHyberlinkEnable: false,
|
|
13
|
+
getComponents: [],
|
|
14
|
+
getComponent: null,
|
|
15
|
+
getElement: null,
|
|
16
|
+
getComponentArrayAddMethod: null,
|
|
17
|
+
getShowModalTipTap: false,
|
|
18
|
+
getMenuRight: false,
|
|
19
|
+
getBorderStyle: null,
|
|
20
|
+
getBorderWidth: null,
|
|
21
|
+
getBorderColor: null,
|
|
22
|
+
getBorderRadiusGlobal: null,
|
|
23
|
+
getBorderRadiusTopLeft: null,
|
|
24
|
+
getBorderRadiusTopRight: null,
|
|
25
|
+
getBorderRadiusBottomleft: null,
|
|
26
|
+
getBorderRadiusBottomRight: null,
|
|
27
|
+
getElementContainsHyperlink: null,
|
|
28
|
+
getHyperlinkAbility: null,
|
|
29
|
+
getHyperlinkInput: null,
|
|
30
|
+
getHyperlinkMessage: null,
|
|
31
|
+
getHyperlinkError: null,
|
|
32
|
+
getOpenHyperlinkInNewTab: null,
|
|
33
|
+
getOpacity: null,
|
|
34
|
+
getBackgroundOpacity: null,
|
|
35
|
+
getTextAreaVueModel: null,
|
|
36
|
+
getCurrentClasses: [],
|
|
37
|
+
getCurrentStyles: {},
|
|
38
|
+
getFontVerticalPadding: null,
|
|
39
|
+
getFontHorizontalPadding: null,
|
|
40
|
+
getFontVerticalMargin: null,
|
|
41
|
+
getFontHorizontalMargin: null,
|
|
42
|
+
getFontStyle: null,
|
|
43
|
+
getFontFamily: null,
|
|
44
|
+
getFontWeight: null,
|
|
45
|
+
getFontBase: null,
|
|
46
|
+
getFontDesktop: null,
|
|
47
|
+
getFontTablet: null,
|
|
48
|
+
getFontMobile: null,
|
|
49
|
+
getBackgroundColor: null,
|
|
50
|
+
getTextColor: null,
|
|
51
|
+
getBasePrimaryImage: null,
|
|
52
|
+
getPageBuilderConfig: null,
|
|
53
|
+
getCurrentPreviewImage: null,
|
|
54
|
+
getBuilderStarted: false,
|
|
55
|
+
getIsLoadingGlobal: false,
|
|
56
|
+
getIsSaving: false,
|
|
57
|
+
getHasLocalDraftForUpdate: false,
|
|
58
|
+
getIsLoadingResumeEditing: false,
|
|
59
|
+
getIsRestoring: false,
|
|
60
|
+
getCurrentLanguage: null,
|
|
61
|
+
getHistoryIndex: 0,
|
|
62
|
+
getHistoryLength: 0,
|
|
63
|
+
|
|
64
|
+
// Mock actions
|
|
9
65
|
setBuilderStarted: vi.fn(),
|
|
10
66
|
setPageBuilderConfig: vi.fn(),
|
|
11
|
-
|
|
67
|
+
setHistoryIndex: vi.fn(),
|
|
68
|
+
setHistoryLength: vi.fn(),
|
|
69
|
+
setLocalStorageItemName: vi.fn(),
|
|
70
|
+
setShowModalTipTap: vi.fn(),
|
|
71
|
+
setMenuRight: vi.fn(),
|
|
72
|
+
setBorderStyle: vi.fn(),
|
|
73
|
+
setBorderWidth: vi.fn(),
|
|
74
|
+
setBorderColor: vi.fn(),
|
|
75
|
+
setBorderRadiusGlobal: vi.fn(),
|
|
76
|
+
setBorderRadiusTopLeft: vi.fn(),
|
|
77
|
+
setBorderRadiusTopRight: vi.fn(),
|
|
78
|
+
setBorderRadiusBottomleft: vi.fn(),
|
|
79
|
+
setBorderRadiusBottomRight: vi.fn(),
|
|
80
|
+
setElementContainsHyperlink: vi.fn(),
|
|
81
|
+
setHyperlinkAbility: vi.fn(),
|
|
82
|
+
setHyperlinkInput: vi.fn(),
|
|
83
|
+
setHyperlinkMessage: vi.fn(),
|
|
84
|
+
setHyperlinkError: vi.fn(),
|
|
85
|
+
setHyberlinkEnable: vi.fn(),
|
|
86
|
+
setOpenHyperlinkInNewTab: vi.fn(),
|
|
87
|
+
setOpacity: vi.fn(),
|
|
88
|
+
setBackgroundOpacity: vi.fn(),
|
|
89
|
+
setTextAreaVueModel: vi.fn(),
|
|
90
|
+
setClass: vi.fn(),
|
|
91
|
+
removeClass: vi.fn(),
|
|
92
|
+
setCurrentClasses: vi.fn(),
|
|
93
|
+
setCurrentStyles: vi.fn(),
|
|
94
|
+
setFontVerticalPadding: vi.fn(),
|
|
95
|
+
setFontHorizontalPadding: vi.fn(),
|
|
96
|
+
setFontVerticalMargin: vi.fn(),
|
|
97
|
+
setFontHorizontalMargin: vi.fn(),
|
|
98
|
+
setFontStyle: vi.fn(),
|
|
99
|
+
setFontFamily: vi.fn(),
|
|
100
|
+
setFontWeight: vi.fn(),
|
|
101
|
+
setFontBase: vi.fn(),
|
|
102
|
+
setFontDesktop: vi.fn(),
|
|
103
|
+
setFontTablet: vi.fn(),
|
|
104
|
+
setFontMobile: vi.fn(),
|
|
105
|
+
setBackgroundColor: vi.fn(),
|
|
106
|
+
setTextColor: vi.fn(),
|
|
107
|
+
setElement: vi.fn(),
|
|
108
|
+
setComponent: vi.fn(),
|
|
12
109
|
setComponents: vi.fn(),
|
|
110
|
+
setPushComponents: vi.fn(),
|
|
111
|
+
setBasePrimaryImage: vi.fn(),
|
|
112
|
+
setCurrentLayoutPreview: vi.fn(),
|
|
113
|
+
setApplyImageToSelection: vi.fn(),
|
|
114
|
+
setCurrentPreviewImage: vi.fn(),
|
|
13
115
|
setIsLoadingGlobal: vi.fn(),
|
|
14
|
-
|
|
15
|
-
setIsLoadingResumeEditing: vi.fn(),
|
|
116
|
+
setIsSaving: vi.fn(),
|
|
16
117
|
setHasLocalDraftForUpdate: vi.fn(),
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
setLocalStorageItemName: vi.fn(),
|
|
21
|
-
// ...add more as needed for your test
|
|
118
|
+
setIsLoadingResumeEditing: vi.fn(),
|
|
119
|
+
setIsRestoring: vi.fn(),
|
|
120
|
+
setCurrentLanguage: vi.fn(),
|
|
22
121
|
} as unknown as ReturnType<typeof usePageBuilderStateStore>
|
|
23
122
|
|
|
24
123
|
const configPageBuilder = {
|
|
@@ -60,7 +159,7 @@ describe('PageBuilderService', () => {
|
|
|
60
159
|
|
|
61
160
|
it('should handle missing components array gracefully', async () => {
|
|
62
161
|
const result = await service.startBuilder(configPageBuilder)
|
|
63
|
-
expect(result).toHaveProperty('
|
|
64
|
-
|
|
162
|
+
expect(result).toHaveProperty('validation.error', true)
|
|
163
|
+
expect(result).toHaveProperty('validation.reason', 'Components data must be an array.')
|
|
65
164
|
})
|
|
66
165
|
})
|