@designcrowd/library.brand-page 5.18.4 → 5.18.5
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/lib/src/{CreatedOnBrandCrowd-de-de-DQLtpdLe.js → CreatedOnBrandCrowd-de-de-ciKpCAd9.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-CvEhlADd.js → CreatedOnBrandCrowd-en-us-CZbTS1AZ.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-pYQeTTC0.js → CreatedOnBrandCrowd-es-es-C8MExng5.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-CcE-iCEq.js → CreatedOnBrandCrowd-fr-ca-CO0L9NK2.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-CcE-iCEq.js → CreatedOnBrandCrowd-fr-fr-CO0L9NK2.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-OyhWWWyO.js → CreatedOnBrandCrowd-pt-br-zVDvBF2H.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-OyhWWWyO.js → CreatedOnBrandCrowd-pt-pt-zVDvBF2H.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-DH98FFLS.js → CreatedOnDcom-de-de-WrUSQdjf.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-DK67NN1r.js → CreatedOnDcom-en-us-BqC9YtkL.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-9-QU4BU6.js → CreatedOnDcom-es-es-BzH32Oya.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-U9J9H9VB.js → CreatedOnDcom-fr-ca-D7TYfCW0.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-DqdzB1DJ.js → CreatedOnDcom-fr-fr-DVlyfBtb.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-c4UiWtkB.js → CreatedOnDcom-pt-br-CSRB91ey.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-Do2qJsYp.js → CreatedOnDcom-pt-pt-9KMj5gpc.js} +1 -1
- package/lib/src/brand-page/models/navigation-styles.model.d.ts +7 -0
- package/lib/src/brand-page/models/navigation-styles.model.js +25 -2
- package/lib/src/brand-page/utils/migration/migration-16.d.ts +2 -0
- package/lib/src/brand-page/utils/migration/migration-16.js +47 -0
- package/lib/src/brand-page/utils/migration.util.js +7 -0
- package/lib/src/brand-page-maker/components/action-bar/ActionBar.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +8 -0
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMakerTemplateSettings.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -0
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +87 -2
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +5 -0
- package/lib/src/brand-page-maker/components/brandpage-settings/ReplaceImageSettingsForBrandPageSettings.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.d.ts +3 -0
- package/lib/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.js +11 -0
- package/lib/src/brand-page-maker/components/seo-settings/SeoPageSettings.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/seo-settings/UrlSettings.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/social-share/SocialShare.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/components/template-preview/TemplatePreview.mixin.d.ts +7 -2
- package/lib/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.js +9 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +20 -1
- package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +20 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.js +17 -0
- package/lib/src/brand-page-maker/composables/useUndoRedoFlag.d.ts +17 -0
- package/lib/src/brand-page-maker/composables/useUndoRedoFlag.js +25 -0
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.d.ts +41 -2
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +308 -14
- package/lib/src/brand-page-maker/stores/history/history-store.d.ts +83 -0
- package/lib/src/brand-page-maker/stores/history/history-store.js +495 -0
- package/lib/src/brand-page-maker/stores/logo-store/logo-store.d.ts +1 -0
- package/lib/src/brand-page-maker/stores/user/user-store.js +1 -0
- package/lib/src/bundled-translations-D1q3rSEz.js +175 -0
- package/lib/src/bundled-translations.de-DE-BxqLLwbh.js +175 -0
- package/lib/src/bundled-translations.es-ES-uh249NlJ.js +175 -0
- package/lib/src/bundled-translations.fr-CA-BEQmv2fX.js +175 -0
- package/lib/src/bundled-translations.fr-FR-BnNuCojH.js +175 -0
- package/lib/src/bundled-translations.pt-BR-CJUOxVlq.js +175 -0
- package/lib/src/bundled-translations.pt-PT-Ds9cMEqK.js +175 -0
- package/lib/src/bundles/bundled-translations.de-DE.json +3 -1
- package/lib/src/bundles/bundled-translations.es-ES.json +3 -1
- package/lib/src/bundles/bundled-translations.fr-CA.json +3 -1
- package/lib/src/bundles/bundled-translations.fr-FR.json +3 -1
- package/lib/src/bundles/bundled-translations.json +3 -1
- package/lib/src/bundles/bundled-translations.pt-BR.json +3 -1
- package/lib/src/bundles/bundled-translations.pt-PT.json +3 -1
- package/lib/src/constants/ui.d.ts +1 -0
- package/lib/src/css/library.brand-page-brandCrowd.min.css +77 -82
- package/lib/src/css/library.brand-page-brandPage.min.css +77 -83
- package/lib/src/css/library.brand-page-designCom.min.css +77 -82
- package/lib/src/css/library.brand-page-preview.min.css +77 -82
- package/lib/src/index.mjs +62 -60
- package/lib/src/{lib-BI3J4Mbk.js → lib-BXbo_N88.js} +35072 -34447
- package/lib/src/metadata-builder/builders/reorder-pages-builder.d.ts +13 -0
- package/lib/src/metadata-builder/builders/reorder-pages-builder.js +49 -0
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +87 -2
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +5 -0
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.stories.js +1 -0
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +23 -2
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +16 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +7 -2
- package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.d.ts +3 -0
- package/lib/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.js +19 -2
- package/lib/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.js +18 -8
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +64 -0
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.js +6 -0
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +19 -0
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.js +11 -0
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +10 -2
- package/lib/src/shared/logo-settings/store/editable-logo-store.d.ts +5 -1
- package/lib/src/shared/logo-settings/store/editable-logo-store.js +31 -0
- package/lib/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.js +10 -8
- package/lib/src/shared/navigation-style-settings/store/index.js +1 -12
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +24 -2
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +10 -2
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +23 -2
- package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +16 -0
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +23 -2
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +16 -0
- package/package.json +1 -1
- package/src/brand-page/components/button/Button.vue +2 -10
- package/src/brand-page/components/contact-form/ContactForm.vue +2 -2
- package/src/brand-page/components/navigation/navigation-side-menu/NavigationSideMenu.vue +4 -1
- package/src/brand-page/models/navigation-styles.model.ts +39 -1
- package/src/brand-page/utils/__snapshots__/migration.util.test.ts.snap +3 -3
- package/src/brand-page/utils/migration/migration-16.test.ts +319 -0
- package/src/brand-page/utils/migration/migration-16.ts +75 -0
- package/src/brand-page/utils/migration.util.ts +8 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +9 -0
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +2 -3
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -0
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +5 -0
- package/src/brand-page-maker/components/color-palette/BpColorPalette.vue +9 -7
- package/src/brand-page-maker/components/cookie-collection/CookieSettings.vue +18 -17
- package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.mixin.ts +13 -0
- package/src/brand-page-maker/components/quick-link-bar/QuickLinkBar.vue +26 -3
- package/src/brand-page-maker/components/quick-link-bar/RedoButton.vue +66 -0
- package/src/brand-page-maker/components/quick-link-bar/UndoButton.vue +66 -0
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.de-DE.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.es-ES.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.fr-CA.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.fr-FR.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.json +3 -1
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.pt-BR.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/i18n/quick-link-bar.pt-PT.json +6 -4
- package/src/brand-page-maker/components/quick-link-bar/undo-redo-buttons.test.ts +116 -0
- package/src/brand-page-maker/components/save-contact/SaveContact.vue +12 -19
- package/src/brand-page-maker/composables/ai-chat/useAiWebsiteBuilderChat.ts +10 -0
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +24 -1
- package/src/brand-page-maker/composables/useEventTracker.ts +29 -0
- package/src/brand-page-maker/composables/useUndoRedoFlag.ts +30 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +377 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +371 -18
- package/src/brand-page-maker/stores/history/history-store.test.ts +1120 -0
- package/src/brand-page-maker/stores/history/history-store.ts +660 -0
- package/src/brand-page-maker/stores/logo-store/logo-store.ts +5 -0
- package/src/brand-page-maker/stores/user/user-store.ts +1 -0
- package/src/bundles/bundled-translations.de-DE.json +3 -1
- package/src/bundles/bundled-translations.es-ES.json +3 -1
- package/src/bundles/bundled-translations.fr-CA.json +3 -1
- package/src/bundles/bundled-translations.fr-FR.json +3 -1
- package/src/bundles/bundled-translations.json +3 -1
- package/src/bundles/bundled-translations.pt-BR.json +3 -1
- package/src/bundles/bundled-translations.pt-PT.json +3 -1
- package/src/constants/ui.ts +1 -0
- package/src/metadata-builder/builders/reorder-pages-builder.ts +80 -0
- package/src/shared/content-settings/components/color-field/ColorField.vue +10 -5
- package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +5 -0
- package/src/shared/content-settings/components/content-settings/ContentSettings.stories.ts +1 -0
- package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.mixin.ts +19 -2
- package/src/shared/content-settings/components/draggable-item-list/DraggableItemList.vue +1 -1
- package/src/shared/content-settings/components/form-fields-field/FormFieldsField.mixin.ts +26 -10
- package/src/shared/content-settings/components/logo-selection-field/LogoSelection.vue +63 -48
- package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +4 -0
- package/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.ts +7 -0
- package/src/shared/content-settings/components/text-field/TextField.vue +1 -0
- package/src/shared/content-settings/components/text-image-field/TextImageField.vue +33 -4
- package/src/shared/logo-settings/components/EditLogoSettings.mixin.ts +11 -0
- package/src/shared/logo-settings/store/editable-logo-store.ts +42 -1
- package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.mixin.ts +17 -11
- package/src/shared/navigation-style-settings/components/navigation-style-settings/NavigationStyleSettings.vue +4 -1
- package/src/shared/navigation-style-settings/store/index.ts +1 -21
- package/lib/src/bundled-translations-B5Fkt3qd.js +0 -175
- package/lib/src/bundled-translations.de-DE-DpdVePM9.js +0 -175
- package/lib/src/bundled-translations.es-ES-BsIcrzZF.js +0 -175
- package/lib/src/bundled-translations.fr-CA-G1XCp2Qh.js +0 -175
- package/lib/src/bundled-translations.fr-FR-BdwLXOnB.js +0 -175
- package/lib/src/bundled-translations.pt-BR-Bvn5ePe7.js +0 -175
- package/lib/src/bundled-translations.pt-PT-CDtkb2k1.js +0 -175
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
+
v-if="shouldShowBar"
|
|
3
4
|
data-component="quick-link-bar"
|
|
4
5
|
class="c-quick-links tw-w-full tw-flex-none tw-bg-white md:tw-h-12 tw-border-b tw-border-grayscale-500 tw-px-2 lg:tw-px-4 tw-box-border tw-flex tw-items-center tw-text-grayscale-800 tw-fixed lg:tw-static"
|
|
5
6
|
>
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
<!-- Left slot: Undo/Redo buttons. Always rendered for layout balance
|
|
8
|
+
(flex-1 reserves equal space on left and right) so the center
|
|
9
|
+
cluster stays geometrically centered in the bar regardless of
|
|
10
|
+
whether the buttons are visible. -->
|
|
11
|
+
<div class="tw-flex tw-flex-1 tw-justify-start tw-gap-1">
|
|
12
|
+
<template v-if="undoRedoEnabled">
|
|
13
|
+
<UndoButton />
|
|
14
|
+
<RedoButton />
|
|
15
|
+
</template>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<!-- Center cluster: URL label, link, copy button -->
|
|
19
|
+
<div
|
|
20
|
+
v-if="isPublished"
|
|
21
|
+
class="tw-flex tw-items-center tw-gap-2 tw-justify-center"
|
|
8
22
|
>
|
|
9
23
|
<strong class="tw-font-semibold tw-hidden xl:tw-inline-block">
|
|
10
24
|
{{ quickLinkBarTr('myWebPageLabel') }}
|
|
@@ -27,7 +41,12 @@
|
|
|
27
41
|
}"
|
|
28
42
|
@on-click.stop="onCopyClick"
|
|
29
43
|
/>
|
|
30
|
-
</
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<!-- Right spacer: balances the left slot so the center cluster is
|
|
47
|
+
geometrically centered. -->
|
|
48
|
+
<div class="tw-flex-1" />
|
|
49
|
+
|
|
31
50
|
<textarea ref="textarea" :value="brandPageUrl" class="tw-sr-only" />
|
|
32
51
|
</div>
|
|
33
52
|
</template>
|
|
@@ -35,10 +54,14 @@
|
|
|
35
54
|
import QuickLinkBarMixin from './QuickLinkBar.mixin.ts';
|
|
36
55
|
import { Button } from '@designcrowd/fe-shared-lib';
|
|
37
56
|
import { quickLinkBarTr } from '@src/composables/useTranslate';
|
|
57
|
+
import UndoButton from './UndoButton.vue';
|
|
58
|
+
import RedoButton from './RedoButton.vue';
|
|
38
59
|
|
|
39
60
|
export default {
|
|
40
61
|
components: {
|
|
41
62
|
Button,
|
|
63
|
+
UndoButton,
|
|
64
|
+
RedoButton,
|
|
42
65
|
},
|
|
43
66
|
mixins: [QuickLinkBarMixin],
|
|
44
67
|
setup(props, context) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Tooltip
|
|
3
|
+
direction="top"
|
|
4
|
+
alignment="center"
|
|
5
|
+
:should-show-icon="false"
|
|
6
|
+
class="c-redo-button-tooltip"
|
|
7
|
+
>
|
|
8
|
+
<template #open>
|
|
9
|
+
<Icon
|
|
10
|
+
data-component="redo-button"
|
|
11
|
+
data-test-redo-button
|
|
12
|
+
name="redo"
|
|
13
|
+
size="md"
|
|
14
|
+
:aria-label="quickLinkBarTr('redoLabel')"
|
|
15
|
+
role="button"
|
|
16
|
+
tabindex="0"
|
|
17
|
+
:class="[
|
|
18
|
+
'tw-p-2 tw-rounded tw-transition-colors',
|
|
19
|
+
isDisabled
|
|
20
|
+
? 'tw-text-grayscale-500 tw-cursor-not-allowed tw-opacity-50'
|
|
21
|
+
: 'tw-text-grayscale-800 tw-cursor-pointer hover:tw-bg-grayscale-300',
|
|
22
|
+
]"
|
|
23
|
+
@click.stop="onClick"
|
|
24
|
+
@keydown.enter.stop="onClick"
|
|
25
|
+
@keydown.space.stop.prevent="onClick"
|
|
26
|
+
/>
|
|
27
|
+
</template>
|
|
28
|
+
<template #content>
|
|
29
|
+
<span class="tw-whitespace-nowrap tw-text-sm">
|
|
30
|
+
{{ quickLinkBarTr('redoLabel') }}
|
|
31
|
+
</span>
|
|
32
|
+
</template>
|
|
33
|
+
</Tooltip>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { computed } from 'vue';
|
|
38
|
+
import { Icon, Tooltip } from '@designcrowd/fe-shared-lib';
|
|
39
|
+
import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
|
|
40
|
+
import { useAiWebsiteBuilderThreadStore } from '@brand-page-maker/stores/ai-thread/ai-website-builder-thread-store';
|
|
41
|
+
import { useBrandPageContainerStore } from '@brand-page-maker/stores/brandpage-container';
|
|
42
|
+
import { quickLinkBarTr } from '@src/composables/useTranslate';
|
|
43
|
+
|
|
44
|
+
const historyStore = useHistoryStore();
|
|
45
|
+
const aiThreadStore = useAiWebsiteBuilderThreadStore();
|
|
46
|
+
const containerStore = useBrandPageContainerStore();
|
|
47
|
+
|
|
48
|
+
const isDisabled = computed(
|
|
49
|
+
() =>
|
|
50
|
+
!historyStore.canRedo ||
|
|
51
|
+
aiThreadStore.isProcessing ||
|
|
52
|
+
containerStore.isSaving,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const onClick = () => {
|
|
56
|
+
if (isDisabled.value) return;
|
|
57
|
+
historyStore.redo();
|
|
58
|
+
};
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<style scoped>
|
|
62
|
+
.c-redo-button-tooltip :deep(.shared-tooltip__body) {
|
|
63
|
+
width: auto;
|
|
64
|
+
padding: 4px 8px;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Tooltip
|
|
3
|
+
direction="top"
|
|
4
|
+
alignment="center"
|
|
5
|
+
:should-show-icon="false"
|
|
6
|
+
class="c-undo-button-tooltip"
|
|
7
|
+
>
|
|
8
|
+
<template #open>
|
|
9
|
+
<Icon
|
|
10
|
+
data-component="undo-button"
|
|
11
|
+
data-test-undo-button
|
|
12
|
+
name="undo"
|
|
13
|
+
size="md"
|
|
14
|
+
:aria-label="quickLinkBarTr('undoLabel')"
|
|
15
|
+
role="button"
|
|
16
|
+
tabindex="0"
|
|
17
|
+
:class="[
|
|
18
|
+
'tw-p-2 tw-rounded tw-transition-colors',
|
|
19
|
+
isDisabled
|
|
20
|
+
? 'tw-text-grayscale-500 tw-cursor-not-allowed tw-opacity-50'
|
|
21
|
+
: 'tw-text-grayscale-800 tw-cursor-pointer hover:tw-bg-grayscale-300',
|
|
22
|
+
]"
|
|
23
|
+
@click.stop="onClick"
|
|
24
|
+
@keydown.enter.stop="onClick"
|
|
25
|
+
@keydown.space.stop.prevent="onClick"
|
|
26
|
+
/>
|
|
27
|
+
</template>
|
|
28
|
+
<template #content>
|
|
29
|
+
<span class="tw-whitespace-nowrap tw-text-sm">
|
|
30
|
+
{{ quickLinkBarTr('undoLabel') }}
|
|
31
|
+
</span>
|
|
32
|
+
</template>
|
|
33
|
+
</Tooltip>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { computed } from 'vue';
|
|
38
|
+
import { Icon, Tooltip } from '@designcrowd/fe-shared-lib';
|
|
39
|
+
import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
|
|
40
|
+
import { useAiWebsiteBuilderThreadStore } from '@brand-page-maker/stores/ai-thread/ai-website-builder-thread-store';
|
|
41
|
+
import { useBrandPageContainerStore } from '@brand-page-maker/stores/brandpage-container';
|
|
42
|
+
import { quickLinkBarTr } from '@src/composables/useTranslate';
|
|
43
|
+
|
|
44
|
+
const historyStore = useHistoryStore();
|
|
45
|
+
const aiThreadStore = useAiWebsiteBuilderThreadStore();
|
|
46
|
+
const containerStore = useBrandPageContainerStore();
|
|
47
|
+
|
|
48
|
+
const isDisabled = computed(
|
|
49
|
+
() =>
|
|
50
|
+
!historyStore.canUndo ||
|
|
51
|
+
aiThreadStore.isProcessing ||
|
|
52
|
+
containerStore.isSaving,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const onClick = () => {
|
|
56
|
+
if (isDisabled.value) return;
|
|
57
|
+
historyStore.undo();
|
|
58
|
+
};
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<style scoped>
|
|
62
|
+
.c-undo-button-tooltip :deep(.shared-tooltip__body) {
|
|
63
|
+
width: auto;
|
|
64
|
+
padding: 4px 8px;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "Meine Webseite:",
|
|
4
|
+
"copyButton": "Kopieren",
|
|
5
|
+
"copiedButton": "Kopiert!",
|
|
6
|
+
"undoLabel": "Rückgängig machen",
|
|
7
|
+
"redoLabel": "Wiederholen"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "Mi página web:",
|
|
4
|
+
"copyButton": "Copiar",
|
|
5
|
+
"copiedButton": "¡Copiado!",
|
|
6
|
+
"undoLabel": "Deshacer",
|
|
7
|
+
"redoLabel": "Rehacer"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "Ma page Web :",
|
|
4
|
+
"copyButton": "Copier",
|
|
5
|
+
"copiedButton": "Copié !",
|
|
6
|
+
"undoLabel": "Annuler",
|
|
7
|
+
"redoLabel": "Rétablir"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "Ma page Web :",
|
|
4
|
+
"copyButton": "Copier",
|
|
5
|
+
"copiedButton": "Copié !",
|
|
6
|
+
"undoLabel": "Annuler",
|
|
7
|
+
"redoLabel": "Rétablir"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "Minha página web:",
|
|
4
|
+
"copyButton": "Copiar",
|
|
5
|
+
"copiedButton": "Copiado!",
|
|
6
|
+
"undoLabel": "Desfazer",
|
|
7
|
+
"redoLabel": "Refazer"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"quickLinkBar"
|
|
3
|
-
"myWebPageLabel"
|
|
4
|
-
"copyButton"
|
|
5
|
-
"copiedButton"
|
|
2
|
+
"quickLinkBar": {
|
|
3
|
+
"myWebPageLabel": "A minha página Web:",
|
|
4
|
+
"copyButton": "Copiar",
|
|
5
|
+
"copiedButton": "Copiado!",
|
|
6
|
+
"undoLabel": "Desfazer",
|
|
7
|
+
"redoLabel": "Refazer"
|
|
6
8
|
}
|
|
7
9
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
4
|
+
import UndoButton from './UndoButton.vue';
|
|
5
|
+
import RedoButton from './RedoButton.vue';
|
|
6
|
+
|
|
7
|
+
// These tests cover the click-dispatch contract for the undo/redo buttons:
|
|
8
|
+
// - Click → historyStore.undo()/redo() ONLY when enabled.
|
|
9
|
+
// - Disabled when any of three guards is true: canUndo/canRedo,
|
|
10
|
+
// aiThread.isProcessing, container.isSaving.
|
|
11
|
+
//
|
|
12
|
+
// Markup, class names, and i18n strings are intentionally not asserted —
|
|
13
|
+
// they're covered by e2e tests and the data-component / data-test-*
|
|
14
|
+
// conventions.
|
|
15
|
+
|
|
16
|
+
vi.mock('@src/composables/useTranslate', () => ({
|
|
17
|
+
quickLinkBarTr: (key: string) => key,
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
// Minimal stubs for fe-shared-lib so wrapper.find('[data-test-…]') can
|
|
21
|
+
// match the icon element regardless of how the real components render.
|
|
22
|
+
vi.mock('@designcrowd/fe-shared-lib', () => ({
|
|
23
|
+
Icon: {
|
|
24
|
+
name: 'Icon',
|
|
25
|
+
inheritAttrs: true,
|
|
26
|
+
template: '<span v-bind="$attrs" @click="$emit(\'click\', $event)" />',
|
|
27
|
+
},
|
|
28
|
+
Tooltip: {
|
|
29
|
+
name: 'Tooltip',
|
|
30
|
+
template: '<div><slot name="open" /><slot name="content" /></div>',
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
const historyStoreMock = {
|
|
35
|
+
canUndo: true,
|
|
36
|
+
canRedo: true,
|
|
37
|
+
undo: vi.fn(),
|
|
38
|
+
redo: vi.fn(),
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
vi.mock('@brand-page-maker/stores/history/history-store', () => ({
|
|
42
|
+
useHistoryStore: vi.fn(() => historyStoreMock),
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
const aiStoreMock = { isProcessing: false };
|
|
46
|
+
|
|
47
|
+
vi.mock(
|
|
48
|
+
'@brand-page-maker/stores/ai-thread/ai-website-builder-thread-store',
|
|
49
|
+
() => ({
|
|
50
|
+
useAiWebsiteBuilderThreadStore: vi.fn(() => aiStoreMock),
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const containerStoreMock = { isSaving: false };
|
|
55
|
+
|
|
56
|
+
vi.mock('@brand-page-maker/stores/brandpage-container', () => ({
|
|
57
|
+
useBrandPageContainerStore: vi.fn(() => containerStoreMock),
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
setActivePinia(createPinia());
|
|
62
|
+
historyStoreMock.canUndo = true;
|
|
63
|
+
historyStoreMock.canRedo = true;
|
|
64
|
+
historyStoreMock.undo = vi.fn();
|
|
65
|
+
historyStoreMock.redo = vi.fn();
|
|
66
|
+
aiStoreMock.isProcessing = false;
|
|
67
|
+
containerStoreMock.isSaving = false;
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('UndoButton', () => {
|
|
71
|
+
it('dispatches historyStore.undo() when enabled', async () => {
|
|
72
|
+
const wrapper = mount(UndoButton);
|
|
73
|
+
|
|
74
|
+
await wrapper.find('[data-test-undo-button]').trigger('click');
|
|
75
|
+
|
|
76
|
+
expect(historyStoreMock.undo).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it.each([
|
|
80
|
+
['canUndo is false', () => (historyStoreMock.canUndo = false)],
|
|
81
|
+
['AI is processing', () => (aiStoreMock.isProcessing = true)],
|
|
82
|
+
['save is in flight', () => (containerStoreMock.isSaving = true)],
|
|
83
|
+
])('does not dispatch when %s', async (_label, applyGuard) => {
|
|
84
|
+
applyGuard();
|
|
85
|
+
|
|
86
|
+
const wrapper = mount(UndoButton);
|
|
87
|
+
|
|
88
|
+
await wrapper.find('[data-test-undo-button]').trigger('click');
|
|
89
|
+
|
|
90
|
+
expect(historyStoreMock.undo).not.toHaveBeenCalled();
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('RedoButton', () => {
|
|
95
|
+
it('dispatches historyStore.redo() when enabled', async () => {
|
|
96
|
+
const wrapper = mount(RedoButton);
|
|
97
|
+
|
|
98
|
+
await wrapper.find('[data-test-redo-button]').trigger('click');
|
|
99
|
+
|
|
100
|
+
expect(historyStoreMock.redo).toHaveBeenCalled();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it.each([
|
|
104
|
+
['canRedo is false', () => (historyStoreMock.canRedo = false)],
|
|
105
|
+
['AI is processing', () => (aiStoreMock.isProcessing = true)],
|
|
106
|
+
['save is in flight', () => (containerStoreMock.isSaving = true)],
|
|
107
|
+
])('does not dispatch when %s', async (_label, applyGuard) => {
|
|
108
|
+
applyGuard();
|
|
109
|
+
|
|
110
|
+
const wrapper = mount(RedoButton);
|
|
111
|
+
|
|
112
|
+
await wrapper.find('[data-test-redo-button]').trigger('click');
|
|
113
|
+
|
|
114
|
+
expect(historyStoreMock.redo).not.toHaveBeenCalled();
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
<Toggle
|
|
21
21
|
id="save-contact-enabled"
|
|
22
|
-
:model-value="
|
|
22
|
+
:model-value="isSavingEnabled"
|
|
23
23
|
color="primary"
|
|
24
24
|
@update:model-value="onSavingEnabled()"
|
|
25
25
|
/>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
</div>
|
|
28
28
|
<div class="tw-flex-none tw-mt-4">
|
|
29
29
|
<div
|
|
30
|
-
v-if="!isAdmin && !isPrePurchase &&
|
|
30
|
+
v-if="!isAdmin && !isPrePurchase && isSavingEnabled"
|
|
31
31
|
class="tw-flex tw-items-center tw-justify-between tw-cursor-pointer tw-gap-1"
|
|
32
32
|
@click="onHideBranding"
|
|
33
33
|
>
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
</div>
|
|
63
63
|
<Toggle
|
|
64
64
|
id="show-preview-cookie-banner"
|
|
65
|
-
:model-value="
|
|
65
|
+
:model-value="hideBranding"
|
|
66
66
|
color="primary"
|
|
67
67
|
@update:model-value="onHideBranding()"
|
|
68
68
|
/>
|
|
@@ -78,7 +78,7 @@ import {
|
|
|
78
78
|
useBrandPageContainerStore,
|
|
79
79
|
} from '@brand-page-maker/stores';
|
|
80
80
|
import { saveContactSettingsTr } from '@src/composables/useTranslate';
|
|
81
|
-
import { computed
|
|
81
|
+
import { computed } from 'vue';
|
|
82
82
|
import {
|
|
83
83
|
EVENTS,
|
|
84
84
|
useEventTracker,
|
|
@@ -107,11 +107,6 @@ const showBrandCrowdLogo = computed(
|
|
|
107
107
|
() => brandPageMakerStore.showBrandCrowdLogo,
|
|
108
108
|
);
|
|
109
109
|
|
|
110
|
-
const data = reactive({
|
|
111
|
-
isToggled: isSavingEnabled.value,
|
|
112
|
-
hideBranding: hideBranding.value,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
110
|
const siteName = computed((): string => {
|
|
116
111
|
return props.isDesignCom ? 'Design.com' : 'BrandCrowd';
|
|
117
112
|
});
|
|
@@ -127,30 +122,28 @@ const hideBrandingTooltip = computed((): string => {
|
|
|
127
122
|
});
|
|
128
123
|
|
|
129
124
|
const onSavingEnabled = () => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
});
|
|
125
|
+
const next = !isSavingEnabled.value;
|
|
126
|
+
|
|
127
|
+
brandPageMakerStore.setSavingEnabled({ isSavingEnabled: next });
|
|
134
128
|
eventTracker.sendWebsiteEvent({
|
|
135
129
|
eventName: EVENTS.WEBSITE_MAKER_DIGITAL_BUSINESS_CARDS_SAVE_CONTACT_TOGGLE,
|
|
136
130
|
eventProps: {
|
|
137
131
|
cta_location: UPGRADE_CTA_LOCATIONS.SAVE_CONTACT_SETTINGS,
|
|
138
|
-
toggle_value:
|
|
132
|
+
toggle_value: next ? 'enabled' : 'disabled',
|
|
139
133
|
},
|
|
140
134
|
});
|
|
141
135
|
};
|
|
142
136
|
|
|
143
137
|
const onHideBranding = async () => {
|
|
144
138
|
if (!showBrandCrowdLogo.value) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
});
|
|
139
|
+
const next = !hideBranding.value;
|
|
140
|
+
|
|
141
|
+
brandPageMakerStore.setHideBranding({ hideBranding: next });
|
|
149
142
|
eventTracker.sendWebsiteEvent({
|
|
150
143
|
eventName: EVENTS.WEBSITE_MAKER_DIGITAL_BUSINESS_CARDS_HIDE_POPUP,
|
|
151
144
|
eventProps: {
|
|
152
145
|
cta_location: UPGRADE_CTA_LOCATIONS.SAVE_CONTACT_SETTINGS,
|
|
153
|
-
toggle_value:
|
|
146
|
+
toggle_value: next ? 'enabled' : 'disabled',
|
|
154
147
|
},
|
|
155
148
|
});
|
|
156
149
|
} else {
|
|
@@ -29,6 +29,8 @@ import {
|
|
|
29
29
|
useUiStore,
|
|
30
30
|
} from '../../stores';
|
|
31
31
|
import { useBrandPageMakerStore } from '../../stores';
|
|
32
|
+
import { useHistoryStore } from '../../stores/history/history-store';
|
|
33
|
+
import { useUndoRedoFlag } from '../useUndoRedoFlag';
|
|
32
34
|
import { useBrandPageMakerUserStore } from '../../stores/user/user-store';
|
|
33
35
|
import { useAiMetadataBuilder } from './useAiMetadataBuilder';
|
|
34
36
|
import {
|
|
@@ -55,6 +57,8 @@ export function useAiWebsiteBuilderChat(): UseAiChatResult {
|
|
|
55
57
|
const aiThreadStore = useAiWebsiteBuilderThreadStore();
|
|
56
58
|
const snapshotStore = useSnapshotStore();
|
|
57
59
|
const brandPageMakerStore = useBrandPageMakerStore();
|
|
60
|
+
const historyStore = useHistoryStore();
|
|
61
|
+
const undoRedoEnabled = useUndoRedoFlag();
|
|
58
62
|
const containerStore = useBrandPageContainerStore();
|
|
59
63
|
const userStore = useBrandPageMakerUserStore();
|
|
60
64
|
const uiStore = useUiStore();
|
|
@@ -441,6 +445,12 @@ export function useAiWebsiteBuilderChat(): UseAiChatResult {
|
|
|
441
445
|
|
|
442
446
|
await nextTick();
|
|
443
447
|
|
|
448
|
+
// One history entry per AI prompt (US-E1). `captureAiChangeset` cancels
|
|
449
|
+
// the auto-watcher's pending flush so the apply doesn't double-capture.
|
|
450
|
+
if (undoRedoEnabled.value) {
|
|
451
|
+
historyStore.captureAiChangeset();
|
|
452
|
+
}
|
|
453
|
+
|
|
444
454
|
// Re-capture snapshot so subsequent messages reflect the updated page
|
|
445
455
|
await snapshotStore.refreshSnapshotAsync();
|
|
446
456
|
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
backgroundColorConvertor,
|
|
48
48
|
} from '@brand-page-maker/convertors';
|
|
49
49
|
import { useUiContentSettingsStore } from '@shared/content-settings/store';
|
|
50
|
+
import { useHistoryStore } from '@brand-page-maker/stores/history/history-store';
|
|
50
51
|
import { AllSelection } from 'prosemirror-state';
|
|
51
52
|
import { MaxLength } from './extensions/MaxLength';
|
|
52
53
|
import { AutoLink } from './extensions/AutoLink';
|
|
@@ -208,6 +209,12 @@ export const useRichTextEditor = (
|
|
|
208
209
|
isHyperlinkPopupOpen: Ref<boolean>,
|
|
209
210
|
selectedLinkTypeValue: Ref<HyperlinkType>,
|
|
210
211
|
): UseRichTextEditorReturn => {
|
|
212
|
+
const historyStore = useHistoryStore();
|
|
213
|
+
|
|
214
|
+
// TipTap rehydrates and writes back canonical HTML on mount — fold
|
|
215
|
+
// that into the current head instead of pushing a phantom entry.
|
|
216
|
+
historyStore.mergeNextMutation();
|
|
217
|
+
|
|
211
218
|
const editor = new Editor({
|
|
212
219
|
content: model.value ?? '',
|
|
213
220
|
editable: !props.readOnly,
|
|
@@ -456,7 +463,16 @@ export const useRichTextEditor = (
|
|
|
456
463
|
watch(
|
|
457
464
|
() => model.value,
|
|
458
465
|
(newValue) => {
|
|
459
|
-
|
|
466
|
+
// Re-seed the editor when the model has been mutated from outside
|
|
467
|
+
// (history undo/redo, template switch, reorder). `!editor.isFocused`
|
|
468
|
+
// distinguishes "external mutation" from "user is typing in me" — the
|
|
469
|
+
// latter would wipe the user's cursor if we called setContent.
|
|
470
|
+
// `updateRichTextEditor.value` is retained as an explicit override for
|
|
471
|
+
// callers (reorder) that need to force a re-seed while focused.
|
|
472
|
+
const isExternalMutation =
|
|
473
|
+
updateRichTextEditor.value || !editor.isFocused;
|
|
474
|
+
|
|
475
|
+
if (isExternalMutation && editor.getHTML() !== newValue) {
|
|
460
476
|
editor.commands.setContent(newValue, false);
|
|
461
477
|
updateRichTextEditor.value = false;
|
|
462
478
|
//text style type is not switching when reordering
|
|
@@ -487,6 +503,13 @@ export const useRichTextEditor = (
|
|
|
487
503
|
});
|
|
488
504
|
|
|
489
505
|
editor.on('selectionUpdate', () => {
|
|
506
|
+
// Skip while a history snapshot is being applied — `setContent` fires
|
|
507
|
+
// selectionUpdate before the editor has fully rehydrated, which causes
|
|
508
|
+
// toolbar buttons (alignment, letter-spacing) to flash through bogus
|
|
509
|
+
// active states before settling. The editor emits a final selectionUpdate
|
|
510
|
+
// after apply completes, which lands the correct values (BP-5506).
|
|
511
|
+
if (historyStore.isApplyingSnapshot) return;
|
|
512
|
+
|
|
490
513
|
const textStyleAttributes = editor.getAttributes('textStyle');
|
|
491
514
|
const highlightAttributes = editor.getAttributes('highlight');
|
|
492
515
|
const focusedAlignment = editor.getAttributes(
|
|
@@ -70,6 +70,10 @@ export const EVENTS = {
|
|
|
70
70
|
'website_maker_digital_business_cards_hide_popup',
|
|
71
71
|
WEBSITE_MAKER_GETTY_VIDEO: 'website_maker_getty_video',
|
|
72
72
|
WEBSITE_MAKER_SHIPPING_TOGGLE: 'website_maker_shipping_toggle',
|
|
73
|
+
WEBSITE_MAKER_UNDO: 'website_maker_undo',
|
|
74
|
+
WEBSITE_MAKER_REDO: 'website_maker_redo',
|
|
75
|
+
WEBSITE_MAKER_HISTORY_CAPPED: 'website_maker_history_capped',
|
|
76
|
+
WEBSITE_MAKER_HISTORY_OVERSIZED: 'website_maker_history_oversized',
|
|
73
77
|
};
|
|
74
78
|
|
|
75
79
|
export const SELECT_LOCATIONS = {
|
|
@@ -420,6 +424,31 @@ const useEventTracker = () => {
|
|
|
420
424
|
is_enabled: isEnabled,
|
|
421
425
|
});
|
|
422
426
|
},
|
|
427
|
+
// Undo / Redo (BP-5506)
|
|
428
|
+
sendUndoEvent: (props: {
|
|
429
|
+
entries_count: number;
|
|
430
|
+
actor: string | undefined;
|
|
431
|
+
}) => {
|
|
432
|
+
_publishEvent(EVENTS.WEBSITE_MAKER_UNDO, props);
|
|
433
|
+
},
|
|
434
|
+
sendRedoEvent: (props: {
|
|
435
|
+
entries_count: number;
|
|
436
|
+
actor: string | undefined;
|
|
437
|
+
}) => {
|
|
438
|
+
_publishEvent(EVENTS.WEBSITE_MAKER_REDO, props);
|
|
439
|
+
},
|
|
440
|
+
sendHistoryCappedEvent: (props: {
|
|
441
|
+
entries_count: number;
|
|
442
|
+
size_bytes: number;
|
|
443
|
+
}) => {
|
|
444
|
+
_publishEvent(EVENTS.WEBSITE_MAKER_HISTORY_CAPPED, props);
|
|
445
|
+
},
|
|
446
|
+
sendHistoryOversizedEvent: (props: {
|
|
447
|
+
attempted_bytes: number;
|
|
448
|
+
source: string;
|
|
449
|
+
}) => {
|
|
450
|
+
_publishEvent(EVENTS.WEBSITE_MAKER_HISTORY_OVERSIZED, props);
|
|
451
|
+
},
|
|
423
452
|
};
|
|
424
453
|
};
|
|
425
454
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { computed, type ComputedRef } from 'vue';
|
|
2
|
+
import { useBrandPageMakerUserStore } from '@brand-page-maker/stores/user';
|
|
3
|
+
import { useBrandPageMakerStore } from '@brand-page-maker/stores/brandpage-maker/brandpage-maker-store';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns whether undo/redo is active for the current maker session. All
|
|
7
|
+
* three conditions must hold:
|
|
8
|
+
*
|
|
9
|
+
* 1. `userStore.features.canUseUndoRedo` is true. The flag is populated by
|
|
10
|
+
* the consumer (BrandCrowd.Net / web-renderer) via the
|
|
11
|
+
* `WebsiteDesignUserFeatures.CanUseUndoRedo` boolean on the ViewModel —
|
|
12
|
+
* same precedent as RichTextEditor / GettyVideos / AITextGenerator.
|
|
13
|
+
* 2. The maker is a brand-site (Website Maker). V1 scope is brand-site
|
|
14
|
+
* only; brand-page (single-page profile) and brand-contact (vCard) are
|
|
15
|
+
* out of scope.
|
|
16
|
+
* 3. The session is NOT in admin-maker mode (`userStore.isAdmin`). The
|
|
17
|
+
* admin maker uses the same components but a different editing flow
|
|
18
|
+
* (template authoring) where undo/redo is out of scope.
|
|
19
|
+
*/
|
|
20
|
+
export function useUndoRedoFlag(): ComputedRef<boolean> {
|
|
21
|
+
const userStore = useBrandPageMakerUserStore();
|
|
22
|
+
const brandPageMakerStore = useBrandPageMakerStore();
|
|
23
|
+
|
|
24
|
+
return computed(
|
|
25
|
+
() =>
|
|
26
|
+
userStore.features.canUseUndoRedo &&
|
|
27
|
+
brandPageMakerStore.isBrandSite &&
|
|
28
|
+
!userStore.isAdmin,
|
|
29
|
+
);
|
|
30
|
+
}
|