@designcrowd/library.brand-page 6.2.1 → 6.2.2
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-CtvPtYF6.js → CreatedOnBrandCrowd-de-de-7P2gNr-R.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-eGF-EjAX.js → CreatedOnBrandCrowd-en-us-Dl7BymW6.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-CSemsOtT.js → CreatedOnBrandCrowd-es-es-CO4FvWVw.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-DzylX-AT.js → CreatedOnBrandCrowd-fr-ca-DHNqakQu.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-DzylX-AT.js → CreatedOnBrandCrowd-fr-fr-DHNqakQu.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-QMUxXQsE.js → CreatedOnBrandCrowd-pt-br-CGUC-ZbP.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-QMUxXQsE.js → CreatedOnBrandCrowd-pt-pt-CGUC-ZbP.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-M7OoJt-1.js → CreatedOnDcom-de-de-Dvds-Vmy.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-D7hMM0AI.js → CreatedOnDcom-en-us-fd3C-8Tp.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-CLw-BLp2.js → CreatedOnDcom-es-es-DTXZW35-.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BRu_kmeu.js → CreatedOnDcom-fr-ca-DRCYOKPs.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-IMnEv_yM.js → CreatedOnDcom-fr-fr-DpIB8x2x.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-Bt6v1p27.js → CreatedOnDcom-pt-br-Esnxy8wX.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-BVsFJIJg.js → CreatedOnDcom-pt-pt-CaiVHFXR.js} +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +7 -1
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.d.ts +6 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.d.ts +3 -0
- package/lib/src/brand-page-maker/composables/useEventTracker.js +10 -0
- package/lib/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.js +2 -4
- package/lib/src/{bundled-translations-KY0aSmMp.js → bundled-translations-BYUfWBT3.js} +9 -9
- package/lib/src/{bundled-translations.de-DE-BIFi4bYj.js → bundled-translations.de-DE-MmzUu1tt.js} +13 -13
- package/lib/src/{bundled-translations.es-ES-CHlKuPLO.js → bundled-translations.es-ES-D-tG33XL.js} +1 -1
- package/lib/src/{bundled-translations.fr-CA-DR1fvm8e.js → bundled-translations.fr-CA-CNc1H1h3.js} +1 -1
- package/lib/src/{bundled-translations.fr-FR-DnpWVIQg.js → bundled-translations.fr-FR-DX0-yepT.js} +1 -1
- package/lib/src/{bundled-translations.pt-BR-p8szTOiT.js → bundled-translations.pt-BR-ih1-LRgy.js} +9 -9
- package/lib/src/{bundled-translations.pt-PT-DEk39NhW.js → bundled-translations.pt-PT-Dq2CmD1p.js} +1 -1
- 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/composables/useTranslate.d.ts +1 -1
- package/lib/src/composables/useTranslate.js +1 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +4 -4
- package/lib/src/css/library.brand-page-brandPage.min.css +4 -4
- package/lib/src/css/library.brand-page-designCom.min.css +4 -4
- package/lib/src/css/library.brand-page-preview.min.css +4 -4
- package/lib/src/index.mjs +2 -2
- package/lib/src/{lib-B38VVCSw.js → lib-V7aqfuiB.js} +18106 -17965
- package/lib/src/metadata-builder/builders/item-id-utils.d.ts +2 -0
- package/lib/src/metadata-builder/builders/item-id-utils.js +8 -2
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +8 -1
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +6 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItem.mixin.d.ts +1 -0
- package/lib/src/shared/content-settings/components/content-settings-item/ContentSettingsItemField.mixin.d.ts +5 -0
- package/lib/src/shared/content-settings/components/payment-config-field/PaymentConfigField.mixin.d.ts +5 -0
- package/lib/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.d.ts +9 -1
- package/lib/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.js +31 -9
- package/lib/src/shared/logo-settings/components/EditLogoSettings.mixin.d.ts +1 -0
- package/lib/src/shared/logo-settings/components/LogoSettings.mixin.d.ts +5 -0
- package/lib/src/shared/page-navigation/store/page-navigation-store.d.ts +2 -1
- package/lib/src/shared/page-navigation/store/page-navigation-store.js +22 -9
- package/lib/src/shared/page-settings/components/new-page-modal/NewPageModal.mixin.d.ts +7 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +10 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.js +12 -35
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +6 -0
- package/lib/src/shared/page-settings/duplicate-page.util.d.ts +4 -0
- package/lib/src/shared/page-settings/duplicate-page.util.js +82 -0
- package/lib/src/shared/page-settings/models.d.ts +1 -0
- package/lib/src/shared/page-settings/store/page-settings-store.d.ts +5 -0
- package/lib/src/shared/page-settings/store/page-settings-store.js +90 -7
- package/lib/src/shared/page-settings/utils.d.ts +3 -0
- package/lib/src/shared/page-settings/utils.js +6 -0
- package/lib/src/shared/publish-brand-page-with-state/PublishBrandPageModalWithState.mixin.d.ts +1 -0
- package/lib/src/shared/side-bar/components/SideBarTabButton.mixin.d.ts +1 -0
- package/lib/src/shared/style-settings/components/StyleSettings.mixin.d.ts +1 -0
- package/lib/src/shared/template-settings/components/TemplatesSettings.mixin.d.ts +1 -0
- package/lib/src/tracker.mjs +1 -1
- package/lib/src/{useEventTracker-C5Ql5p7u.js → useEventTracker-DwPTmzpa.js} +13 -3
- package/package.json +1 -1
- package/src/brand-page-maker/composables/useEventTracker.ts +13 -0
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.ts +2 -4
- 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/composables/useTranslate.ts +2 -1
- package/src/metadata-builder/builders/item-id-utils.ts +9 -2
- package/src/shared/ecommerce-settings/components/product-config-field/ProductConfigOption.vue +0 -2
- package/src/shared/ecommerce-settings/util/refreshDuplicatedMetadata.ts +32 -10
- package/src/shared/page-navigation/store/page-navigation-store.ts +41 -13
- package/src/shared/page-settings/components/page-settings/NestedDraggable.vue +3 -0
- package/src/shared/page-settings/components/page-settings/PageElement.vue +2 -0
- package/src/shared/page-settings/components/page-settings/PageSettingMenu.test.ts +105 -0
- package/src/shared/page-settings/components/page-settings/PageSettingMenu.vue +16 -0
- package/src/shared/page-settings/components/page-settings/PageSettings.duplicate.test.ts +108 -0
- package/src/shared/page-settings/components/page-settings/PageSettings.mixin.ts +22 -50
- package/src/shared/page-settings/components/page-settings/PageSettings.vue +1 -0
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.de-DE.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.es-ES.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.fr-CA.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.fr-FR.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.pt-BR.json +3 -1
- package/src/shared/page-settings/components/page-settings/i18n/page-settings.pt-PT.json +3 -1
- package/src/shared/page-settings/duplicate-page.util.test.ts +382 -0
- package/src/shared/page-settings/duplicate-page.util.ts +124 -0
- package/src/shared/page-settings/models.ts +1 -0
- package/src/shared/page-settings/store/page-settings-store.test.ts +512 -1
- package/src/shared/page-settings/store/page-settings-store.ts +145 -11
- package/src/shared/page-settings/utils.ts +10 -0
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
:delete-page-selected="onDeletePageSelected"
|
|
29
29
|
:change-page-visibility="onChangePageVisibility"
|
|
30
30
|
:on-add-sub-page-selected="onAddSubPageSelected"
|
|
31
|
+
:on-duplicate-page-selected="onDuplicatePageSelected"
|
|
31
32
|
:total-pages="totalPages"
|
|
32
33
|
:visible-page-count="visiblePageCount"
|
|
33
34
|
/>
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
:on-delete-page-selected="onDeletePageSelected"
|
|
42
43
|
:on-change-page-visibility="onChangePageVisibility"
|
|
43
44
|
:on-add-sub-page-selected="onAddSubPageSelected"
|
|
45
|
+
:on-duplicate-page-selected="onDuplicatePageSelected"
|
|
44
46
|
:move="handleMove"
|
|
45
47
|
@drag-start="handleStart"
|
|
46
48
|
@drag-end="handleEnd"
|
|
@@ -92,6 +94,7 @@ interface Props {
|
|
|
92
94
|
onDeletePageSelected: (pageId: string) => void;
|
|
93
95
|
onChangePageVisibility: (pageId: string) => void;
|
|
94
96
|
onAddSubPageSelected: (pageId: string) => void;
|
|
97
|
+
onDuplicatePageSelected: (pageId: string) => void;
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
const props = defineProps<Props>();
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
:on-delete-page-selected="deletePageSelected"
|
|
46
46
|
:on-change-page-visibility="changePageVisibility"
|
|
47
47
|
:on-add-sub-page-selected="onAddSubPageSelected"
|
|
48
|
+
:on-duplicate-page-selected="onDuplicatePageSelected"
|
|
48
49
|
:is-root-page="isRootPage"
|
|
49
50
|
:total-pages="totalPages"
|
|
50
51
|
:visible-page-count="visiblePageCount"
|
|
@@ -80,6 +81,7 @@ interface Props {
|
|
|
80
81
|
deletePageSelected: (pageId: string) => void;
|
|
81
82
|
changePageVisibility: (pageId: string) => void;
|
|
82
83
|
onAddSubPageSelected: (pageId: string) => void;
|
|
84
|
+
onDuplicatePageSelected: (pageId: string) => void;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
defineProps<Props>();
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { describe, test, expect, beforeAll, vi } from 'vitest';
|
|
2
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
3
|
+
import { mount } from '@vue/test-utils';
|
|
4
|
+
|
|
5
|
+
import { setLocaleAsync } from '@src/composables/useTranslate';
|
|
6
|
+
import PageSettingMenu from './PageSettingMenu.vue';
|
|
7
|
+
|
|
8
|
+
// Menu order is a product requirement, so it is asserted rather than just
|
|
9
|
+
// membership.
|
|
10
|
+
const ITEM_TAGS = [
|
|
11
|
+
'add-subpage',
|
|
12
|
+
'duplicate-page',
|
|
13
|
+
'toggle-page-visibility',
|
|
14
|
+
'delete-page',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const mountMenu = (overrides = {}) =>
|
|
18
|
+
mount(PageSettingMenu, {
|
|
19
|
+
props: {
|
|
20
|
+
index: 1,
|
|
21
|
+
pageId: 'page-1',
|
|
22
|
+
isHidden: false,
|
|
23
|
+
isDesignCom: false,
|
|
24
|
+
isRootPage: true,
|
|
25
|
+
hasSubPages: false,
|
|
26
|
+
totalPages: 3,
|
|
27
|
+
visiblePageCount: 3,
|
|
28
|
+
onDeletePageSelected: vi.fn(),
|
|
29
|
+
onChangePageVisibility: vi.fn(),
|
|
30
|
+
onAddSubPageSelected: vi.fn(),
|
|
31
|
+
onDuplicatePageSelected: vi.fn(),
|
|
32
|
+
...overrides,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const openMenu = async (wrapper: ReturnType<typeof mountMenu>) => {
|
|
37
|
+
await wrapper.find('[data-test-tag="page-menu-trigger"]').trigger('click');
|
|
38
|
+
|
|
39
|
+
return wrapper;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const renderedTags = (wrapper: ReturnType<typeof mountMenu>) =>
|
|
43
|
+
wrapper
|
|
44
|
+
.findAll('li')
|
|
45
|
+
.map((li) => li.attributes('data-test-tag'))
|
|
46
|
+
.filter((tag): tag is string => Boolean(tag));
|
|
47
|
+
|
|
48
|
+
describe('PageSettingMenu', () => {
|
|
49
|
+
beforeAll(async () => {
|
|
50
|
+
setActivePinia(createPinia());
|
|
51
|
+
|
|
52
|
+
await setLocaleAsync('en-US');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('a root page shows every action in order', async () => {
|
|
56
|
+
const wrapper = await openMenu(mountMenu());
|
|
57
|
+
|
|
58
|
+
expect(renderedTags(wrapper)).toEqual(ITEM_TAGS);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('a sub-page shows duplicate but not add-subpage', async () => {
|
|
62
|
+
const wrapper = await openMenu(mountMenu({ isRootPage: false }));
|
|
63
|
+
|
|
64
|
+
expect(renderedTags(wrapper)).toEqual([
|
|
65
|
+
'duplicate-page',
|
|
66
|
+
'toggle-page-visibility',
|
|
67
|
+
'delete-page',
|
|
68
|
+
]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('the home page can be duplicated but not hidden or deleted', async () => {
|
|
72
|
+
const wrapper = await openMenu(mountMenu({ index: 0 }));
|
|
73
|
+
|
|
74
|
+
expect(renderedTags(wrapper)).toEqual(['add-subpage', 'duplicate-page']);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('a parent page can be duplicated even though it cannot be deleted', async () => {
|
|
78
|
+
const wrapper = await openMenu(mountMenu({ hasSubPages: true }));
|
|
79
|
+
|
|
80
|
+
expect(renderedTags(wrapper)).toContain('duplicate-page');
|
|
81
|
+
expect(renderedTags(wrapper)).not.toContain('delete-page');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('clicking duplicate calls back with the page id and closes the menu', async () => {
|
|
85
|
+
const onDuplicatePageSelected = vi.fn();
|
|
86
|
+
|
|
87
|
+
const wrapper = await openMenu(mountMenu({ onDuplicatePageSelected }));
|
|
88
|
+
|
|
89
|
+
await wrapper.find('[data-test-tag="duplicate-page"]').trigger('click');
|
|
90
|
+
|
|
91
|
+
expect(onDuplicatePageSelected).toHaveBeenCalledTimes(1);
|
|
92
|
+
expect(onDuplicatePageSelected).toHaveBeenCalledWith('page-1');
|
|
93
|
+
expect(wrapper.find('[data-test-tag="duplicate-page"]').exists()).toBe(
|
|
94
|
+
false,
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('the duplicate row is labelled from the translation bundle', async () => {
|
|
99
|
+
const wrapper = await openMenu(mountMenu());
|
|
100
|
+
|
|
101
|
+
expect(wrapper.find('[data-test-tag="duplicate-page"]').text()).toEqual(
|
|
102
|
+
'Duplicate page',
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -29,6 +29,16 @@
|
|
|
29
29
|
pageSettingsTr('addSubPage')
|
|
30
30
|
}}</span>
|
|
31
31
|
</li>
|
|
32
|
+
<li
|
|
33
|
+
data-test-tag="duplicate-page"
|
|
34
|
+
class="tw-cursor-pointer tw-flex tw-gap-2 tw-items-center tw-px-5 hover:tw-bg-grayscale-400 tw-mt-3"
|
|
35
|
+
@click="onDuplicateClick"
|
|
36
|
+
>
|
|
37
|
+
<Icon name="duplicate" :class="{ 'tw-pt-1': !isDesignCom }" />
|
|
38
|
+
<span class="tw-whitespace-nowrap">{{
|
|
39
|
+
pageSettingsTr('duplicatePage')
|
|
40
|
+
}}</span>
|
|
41
|
+
</li>
|
|
32
42
|
<li
|
|
33
43
|
v-if="props.index !== 0"
|
|
34
44
|
data-test-tag="toggle-page-visibility"
|
|
@@ -74,6 +84,7 @@ interface Props {
|
|
|
74
84
|
onDeletePageSelected: (pageId: string) => void;
|
|
75
85
|
onChangePageVisibility: (pageId: string) => void;
|
|
76
86
|
onAddSubPageSelected: (pageId: string) => void;
|
|
87
|
+
onDuplicatePageSelected: (pageId: string) => void;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
90
|
const props = defineProps<Props>();
|
|
@@ -100,6 +111,11 @@ const onAddSubPageClick = () => {
|
|
|
100
111
|
closeMenu();
|
|
101
112
|
};
|
|
102
113
|
|
|
114
|
+
const onDuplicateClick = () => {
|
|
115
|
+
props.onDuplicatePageSelected(props.pageId);
|
|
116
|
+
closeMenu();
|
|
117
|
+
};
|
|
118
|
+
|
|
103
119
|
const onChangePageVisibility = () => {
|
|
104
120
|
props.onChangePageVisibility(props.pageId);
|
|
105
121
|
closeMenu();
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { describe, test, expect, beforeAll, vi } from 'vitest';
|
|
2
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
3
|
+
import { shallowMount } from '@vue/test-utils';
|
|
4
|
+
|
|
5
|
+
import { setLocaleAsync } from '@src/composables/useTranslate';
|
|
6
|
+
import {
|
|
7
|
+
INITIALISE_PAYLOAD,
|
|
8
|
+
USER_FEATURES,
|
|
9
|
+
} from '@brand-page-maker/components/brand-page-maker/__fixtures__';
|
|
10
|
+
import {
|
|
11
|
+
UNLIMITED_MAX_NUM_OF_PAGES,
|
|
12
|
+
useBrandPageMakerStore,
|
|
13
|
+
useBrandPageMakerUserStore,
|
|
14
|
+
} from '@brand-page-maker/stores';
|
|
15
|
+
import { FabricRenderClient } from '../../../../clients/fabric-render-client';
|
|
16
|
+
import { useUiPageSettingsStore } from '../../store';
|
|
17
|
+
import { usePageNavigationStore } from '../../../page-navigation/store/page-navigation-store';
|
|
18
|
+
import PageSettings from './PageSettings.vue';
|
|
19
|
+
|
|
20
|
+
vi.mock('../../../../clients/brand-page-client', () => ({
|
|
21
|
+
default: {
|
|
22
|
+
getWebsiteContextualUpgradeTestBucketAsync: vi
|
|
23
|
+
.fn()
|
|
24
|
+
.mockResolvedValue(undefined),
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
// The analytics contract lives in the mixin, not the store: the store returns
|
|
29
|
+
// the copy, the mixin decides what gets tracked. Nothing else covers it.
|
|
30
|
+
describe('PageSettings - duplicate page handler', () => {
|
|
31
|
+
const setupAsync = async () => {
|
|
32
|
+
const makerStore = useBrandPageMakerStore();
|
|
33
|
+
const userStore = useBrandPageMakerUserStore();
|
|
34
|
+
|
|
35
|
+
userStore.setUserState({
|
|
36
|
+
features: { ...USER_FEATURES, maxNumOfPages: UNLIMITED_MAX_NUM_OF_PAGES },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await makerStore.initialise(INITIALISE_PAYLOAD);
|
|
40
|
+
|
|
41
|
+
const wrapper = shallowMount(PageSettings);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
wrapper,
|
|
45
|
+
pageSettingsStore: useUiPageSettingsStore(),
|
|
46
|
+
pageNavigationStore: usePageNavigationStore(),
|
|
47
|
+
spy: vi.spyOn(
|
|
48
|
+
wrapper.vm.eventTracker,
|
|
49
|
+
'sendWebsiteManageDuplicatePageEvent',
|
|
50
|
+
),
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
beforeAll(async () => {
|
|
55
|
+
FabricRenderClient.setInstance({ baseUrl: 'http://localhost:3000' });
|
|
56
|
+
setActivePinia(createPinia());
|
|
57
|
+
|
|
58
|
+
await setLocaleAsync('en-US');
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test('tracks the source page title, not the copy', async () => {
|
|
62
|
+
const { wrapper, pageSettingsStore, spy } = await setupAsync();
|
|
63
|
+
|
|
64
|
+
const source = pageSettingsStore.addNewPage({ title: 'About' });
|
|
65
|
+
|
|
66
|
+
await wrapper.vm.onDuplicatePageSelected(source.id);
|
|
67
|
+
|
|
68
|
+
expect(spy).toHaveBeenCalledWith('About', false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('flags a duplicated sub-page', async () => {
|
|
72
|
+
const { wrapper, pageSettingsStore, spy } = await setupAsync();
|
|
73
|
+
|
|
74
|
+
const parent = pageSettingsStore.addNewPage({ title: 'Portfolio' });
|
|
75
|
+
const child = pageSettingsStore.addNewPage({
|
|
76
|
+
title: 'Portfolio 1',
|
|
77
|
+
newPageParentId: parent.id,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await wrapper.vm.onDuplicatePageSelected(child.id);
|
|
81
|
+
|
|
82
|
+
expect(spy).toHaveBeenCalledWith('Portfolio 1', true);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('tracks nothing when the page limit blocked the duplicate', async () => {
|
|
86
|
+
const { wrapper, pageSettingsStore, spy } = await setupAsync();
|
|
87
|
+
const userStore = useBrandPageMakerUserStore();
|
|
88
|
+
|
|
89
|
+
userStore.setUserState({
|
|
90
|
+
features: {
|
|
91
|
+
...USER_FEATURES,
|
|
92
|
+
maxNumOfPages: pageSettingsStore.pages.length,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
await wrapper.vm.onDuplicatePageSelected(pageSettingsStore.pages[0].id);
|
|
97
|
+
|
|
98
|
+
expect(spy).not.toHaveBeenCalled();
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('tracks nothing for an unknown page id', async () => {
|
|
102
|
+
const { wrapper, spy } = await setupAsync();
|
|
103
|
+
|
|
104
|
+
await wrapper.vm.onDuplicatePageSelected('does-not-exist');
|
|
105
|
+
|
|
106
|
+
expect(spy).not.toHaveBeenCalled();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
@@ -124,55 +124,6 @@ export default defineComponent({
|
|
|
124
124
|
|
|
125
125
|
const isDraggingPage = ref(false);
|
|
126
126
|
|
|
127
|
-
const syncPagesWithOrders = (): void => {
|
|
128
|
-
const pageIdOrder: string[] = [];
|
|
129
|
-
|
|
130
|
-
const collectPageIds = (orders: NavOrder[]): void => {
|
|
131
|
-
for (const order of orders) {
|
|
132
|
-
const route = pageNavigationStore.routes.find(
|
|
133
|
-
(r) => r.id === order.routeId,
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
if (route?.pageId) {
|
|
137
|
-
pageIdOrder.push(route.pageId);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (order.subRoutes && order.subRoutes.length > 0) {
|
|
141
|
-
collectPageIds(order.subRoutes);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
collectPageIds(pageNavigationStore.orders);
|
|
147
|
-
|
|
148
|
-
if (!pageIdOrder.length) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const pageMap = new Map<string, ContentPage>();
|
|
153
|
-
|
|
154
|
-
for (const page of pageSettingsStore.pages) {
|
|
155
|
-
pageMap.set(page.id, page);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const orderedPages: ContentPage[] = [];
|
|
159
|
-
|
|
160
|
-
for (const pageId of pageIdOrder) {
|
|
161
|
-
const page = pageMap.get(pageId);
|
|
162
|
-
|
|
163
|
-
if (page) {
|
|
164
|
-
orderedPages.push(page);
|
|
165
|
-
pageMap.delete(pageId);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
for (const remainingPage of pageMap.values()) {
|
|
170
|
-
orderedPages.push(remainingPage);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
pageSettingsStore.setPages({ pages: orderedPages });
|
|
174
|
-
};
|
|
175
|
-
|
|
176
127
|
const onDraggingStart = (): void => {
|
|
177
128
|
isDraggingPage.value = true;
|
|
178
129
|
};
|
|
@@ -200,7 +151,7 @@ export default defineComponent({
|
|
|
200
151
|
}
|
|
201
152
|
}
|
|
202
153
|
|
|
203
|
-
syncPagesWithOrders();
|
|
154
|
+
pageSettingsStore.syncPagesWithOrders();
|
|
204
155
|
|
|
205
156
|
// Recalc the moved route's slug to ensure uniqueness at its new depth
|
|
206
157
|
if (routeId) {
|
|
@@ -371,6 +322,27 @@ export default defineComponent({
|
|
|
371
322
|
isNewPageModalVisible: true,
|
|
372
323
|
});
|
|
373
324
|
},
|
|
325
|
+
async onDuplicatePageSelected(pageId: string) {
|
|
326
|
+
const sourcePage = this.pageSettingsStore.pages.find(
|
|
327
|
+
(p) => p.id === pageId,
|
|
328
|
+
);
|
|
329
|
+
const isSubPage = Boolean(
|
|
330
|
+
this.pageNavigationStore.getParentRouteIdForPage(pageId),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const newPage = await this.pageSettingsStore.duplicatePage({ pageId });
|
|
334
|
+
|
|
335
|
+
// Nothing was created - paywalled, or the page is gone. The upsell is
|
|
336
|
+
// already tracked through the bridge's cta_location.
|
|
337
|
+
if (!newPage || !sourcePage) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
this.eventTracker.sendWebsiteManageDuplicatePageEvent(
|
|
342
|
+
sourcePage.title,
|
|
343
|
+
isSubPage,
|
|
344
|
+
);
|
|
345
|
+
},
|
|
374
346
|
onChangePageVisibility(pageId: string) {
|
|
375
347
|
const page = this.pageSettingsStore.pages.find((p) => p.id === pageId);
|
|
376
348
|
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
:on-delete-page-selected="onDeletePageSelected"
|
|
39
39
|
:on-change-page-visibility="onChangePageVisibility"
|
|
40
40
|
:on-add-sub-page-selected="onAddSubPageSelected"
|
|
41
|
+
:on-duplicate-page-selected="onDuplicatePageSelected"
|
|
41
42
|
@drag-start="onDraggingStart"
|
|
42
43
|
@drag-end="onDraggingEnd"
|
|
43
44
|
/>
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Seite anzeigen",
|
|
20
20
|
"hidePage": "Seite ausblenden",
|
|
21
21
|
"delete": "Seite löschen",
|
|
22
|
-
"addSubPage": "Unterseite hinzufügen"
|
|
22
|
+
"addSubPage": "Unterseite hinzufügen",
|
|
23
|
+
"duplicatePage": "Seite duplizieren",
|
|
24
|
+
"duplicatePageTitle": "{{title}} Kopieren"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Mostrar página",
|
|
20
20
|
"hidePage": "Ocultar página",
|
|
21
21
|
"delete": "Eliminar página",
|
|
22
|
-
"addSubPage": "Añadir subpágina"
|
|
22
|
+
"addSubPage": "Añadir subpágina",
|
|
23
|
+
"duplicatePage": "Duplicar página",
|
|
24
|
+
"duplicatePageTitle": "{{title}} copia"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Afficher la page",
|
|
20
20
|
"hidePage": "Masquez la page",
|
|
21
21
|
"delete": "Supprimer la page",
|
|
22
|
-
"addSubPage": "Ajouter une sous-page"
|
|
22
|
+
"addSubPage": "Ajouter une sous-page",
|
|
23
|
+
"duplicatePage": "Dupliquer la page",
|
|
24
|
+
"duplicatePageTitle": "{{title}} Copie"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Afficher la page",
|
|
20
20
|
"hidePage": "Masquez la page",
|
|
21
21
|
"delete": "Supprimer la page",
|
|
22
|
-
"addSubPage": "Ajouter une sous-page"
|
|
22
|
+
"addSubPage": "Ajouter une sous-page",
|
|
23
|
+
"duplicatePage": "Dupliquer la page",
|
|
24
|
+
"duplicatePageTitle": "Copie de {{title}}"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Mostrar página",
|
|
20
20
|
"hidePage": "Ocultar página",
|
|
21
21
|
"delete": "Eliminar página",
|
|
22
|
-
"addSubPage": "Adicionar subpágina"
|
|
22
|
+
"addSubPage": "Adicionar subpágina",
|
|
23
|
+
"duplicatePage": "Duplicar página",
|
|
24
|
+
"duplicatePageTitle": "{{title}} Copiar"
|
|
23
25
|
}
|
|
24
26
|
}
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"showPage": "Mostrar página",
|
|
20
20
|
"hidePage": "Ocultar página",
|
|
21
21
|
"delete": "Eliminar página",
|
|
22
|
-
"addSubPage": "Adicionar subpágina"
|
|
22
|
+
"addSubPage": "Adicionar subpágina",
|
|
23
|
+
"duplicatePage": "Duplicar página",
|
|
24
|
+
"duplicatePageTitle": "{{title}} Cópia"
|
|
23
25
|
}
|
|
24
26
|
}
|