@designcrowd/library.brand-page 6.1.6 → 6.1.7
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-COw1kYDh.js → CreatedOnBrandCrowd-de-de-Dh3Paq4X.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-en-us-JRm1p0it.js → CreatedOnBrandCrowd-en-us-DLWYV4xe.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-es-es-D-G9uI6b.js → CreatedOnBrandCrowd-es-es-CcjzRbm_.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-fr-DQCScohj.js → CreatedOnBrandCrowd-fr-ca-UuUNeB_L.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-fr-ca-DQCScohj.js → CreatedOnBrandCrowd-fr-fr-UuUNeB_L.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-pt-4RazAfO7.js → CreatedOnBrandCrowd-pt-br-ZVYZ5AnV.js} +1 -1
- package/lib/src/{CreatedOnBrandCrowd-pt-br-4RazAfO7.js → CreatedOnBrandCrowd-pt-pt-ZVYZ5AnV.js} +1 -1
- package/lib/src/{CreatedOnDcom-de-de-DqvLTbhq.js → CreatedOnDcom-de-de-BPVyqOPL.js} +1 -1
- package/lib/src/{CreatedOnDcom-en-us-DG1X0ero.js → CreatedOnDcom-en-us-BUSRV01e.js} +1 -1
- package/lib/src/{CreatedOnDcom-es-es-BxHAIikP.js → CreatedOnDcom-es-es-BuABJnvQ.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-ca-BGXoViAC.js → CreatedOnDcom-fr-ca-sjHceLRY.js} +1 -1
- package/lib/src/{CreatedOnDcom-fr-fr-CsvmeK2T.js → CreatedOnDcom-fr-fr-D_qGXL3E.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-br-DvWm7MjO.js → CreatedOnDcom-pt-br-D3Sb_YEi.js} +1 -1
- package/lib/src/{CreatedOnDcom-pt-pt-Bhz2YEVP.js → CreatedOnDcom-pt-pt-BI47Hv58.js} +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.d.ts +0 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.js +1 -4
- package/lib/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.js +9 -6
- package/lib/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.js +7 -9
- package/lib/src/brand-page-maker/constants/sidebar-constant.d.ts +1 -0
- package/lib/src/brand-page-maker/constants/sidebar-constant.js +10 -1
- package/lib/src/css/library.brand-page-brandCrowd.min.css +27 -27
- package/lib/src/css/library.brand-page-brandPage.min.css +27 -27
- package/lib/src/css/library.brand-page-designCom.min.css +27 -27
- package/lib/src/css/library.brand-page-preview.min.css +27 -27
- package/lib/src/index.mjs +1 -1
- package/lib/src/{lib-Bg2K2ze6.js → lib-BBX3eBci.js} +13006 -13027
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.d.ts +10 -177
- package/lib/src/shared/content-settings/components/content-settings/ContentSettings.mixin.js +8 -15
- package/lib/src/shared/content-settings/components/content-settings/ReplaceImageSettingsForContent.mixin.d.ts +1 -1
- package/lib/src/shared/content-settings/store/content-settings-store.d.ts +0 -1
- package/lib/src/shared/content-settings/store/content-settings-store.js +0 -1
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.d.ts +1 -12
- package/lib/src/shared/page-settings/components/page-settings/PageSettings.mixin.js +9 -24
- package/lib/src/shared/side-bar/components/SideBar.mixin.d.ts +1 -1
- package/lib/src/shared/side-bar/components/SideBar.mixin.js +6 -6
- package/lib/src/shared/side-bar/store/side-bar-store.js +15 -2
- package/package.json +1 -1
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.mixin.ts +1 -4
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.stories.ts +9 -10
- package/src/brand-page-maker/components/brand-page-maker/BrandPageMaker.vue +2 -0
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.mixin.ts +8 -12
- package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.pages-tab.test.ts +78 -0
- package/src/brand-page-maker/constants/sidebar-constant.ts +10 -1
- package/src/brand-page-maker/stores/brandpage-maker/brandpage-maker-store.test.ts +9 -4
- package/src/shared/content-settings/components/content-settings/ContentSettings.mixin.ts +7 -19
- package/src/shared/content-settings/components/content-settings/ContentSettings.pages-tab.test.ts +20 -0
- package/src/shared/content-settings/components/content-settings/ContentSettings.vue +1 -8
- package/src/shared/content-settings/store/content-settings-store.ts +0 -1
- package/src/shared/page-settings/components/page-settings/PageSettings.image-replace.test.ts +100 -0
- package/src/shared/page-settings/components/page-settings/PageSettings.mixin.ts +14 -31
- package/src/shared/page-settings/components/page-settings/PageSettings.vue +11 -7
- package/src/shared/side-bar/components/SideBar.landing-tab.test.ts +67 -0
- package/src/shared/side-bar/components/SideBar.mixin.ts +6 -6
- package/src/shared/side-bar/store/side-bar-store.test.ts +124 -0
- package/src/shared/side-bar/store/side-bar-store.ts +17 -2
package/src/brand-page-maker/components/brandpage-maker-page/BrandPageMakerPage.pages-tab.test.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, test, expect, vi } from 'vitest';
|
|
2
|
+
import BrandPageMakerPageMixin from './BrandPageMakerPage.mixin';
|
|
3
|
+
import { SIDE_BAR_TAB_NAMES } from '@brand-page-maker/constants';
|
|
4
|
+
import { PAGE_SECTIONS } from '@shared/page-settings/models';
|
|
5
|
+
|
|
6
|
+
// Clicking the header/footer of the live preview jumps straight to the Pages tab
|
|
7
|
+
// and its matching section (BP-5855) — it must NOT push the old Content "pages"
|
|
8
|
+
// sub-mode, which no longer exists. Driving the handlers keeps the test light.
|
|
9
|
+
const { onPageHeaderContainerClick, onPageFooterContainerClick } = (
|
|
10
|
+
BrandPageMakerPageMixin as any
|
|
11
|
+
).methods;
|
|
12
|
+
|
|
13
|
+
const createContext = () => ({
|
|
14
|
+
isInteractivePreviewEnabled: true,
|
|
15
|
+
sideBarStore: { setSelectedTabName: vi.fn() },
|
|
16
|
+
contentSettingsStore: {
|
|
17
|
+
_setSelectedItemId: vi.fn(),
|
|
18
|
+
pushMode: vi.fn(),
|
|
19
|
+
resetMode: vi.fn(),
|
|
20
|
+
},
|
|
21
|
+
pageSettingsStore: { setSelectedSectionName: vi.fn() },
|
|
22
|
+
isHeaderSelected: false,
|
|
23
|
+
isFooterSelected: false,
|
|
24
|
+
isContentSelected: false,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('BrandPageMakerPage — preview deep links open the Pages tab', () => {
|
|
28
|
+
test('header click opens the Pages tab at the header section', () => {
|
|
29
|
+
const context = createContext();
|
|
30
|
+
|
|
31
|
+
onPageHeaderContainerClick.call(context);
|
|
32
|
+
|
|
33
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
34
|
+
tabName: SIDE_BAR_TAB_NAMES.PAGE_SETTINGS,
|
|
35
|
+
});
|
|
36
|
+
expect(
|
|
37
|
+
context.pageSettingsStore.setSelectedSectionName,
|
|
38
|
+
).toHaveBeenCalledWith({ sectionName: PAGE_SECTIONS.header });
|
|
39
|
+
expect(context.contentSettingsStore.pushMode).not.toHaveBeenCalled();
|
|
40
|
+
expect(context.isHeaderSelected).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('footer click opens the Pages tab at the footer section', () => {
|
|
44
|
+
const context = createContext();
|
|
45
|
+
|
|
46
|
+
onPageFooterContainerClick.call(context);
|
|
47
|
+
|
|
48
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
49
|
+
tabName: SIDE_BAR_TAB_NAMES.PAGE_SETTINGS,
|
|
50
|
+
});
|
|
51
|
+
expect(
|
|
52
|
+
context.pageSettingsStore.setSelectedSectionName,
|
|
53
|
+
).toHaveBeenCalledWith({ sectionName: PAGE_SECTIONS.footer });
|
|
54
|
+
expect(context.contentSettingsStore.pushMode).not.toHaveBeenCalled();
|
|
55
|
+
expect(context.isFooterSelected).toBe(true);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// BP-5855 regression: setSelectedTabName only resets a leftover mode on an
|
|
59
|
+
// actual tab change, so clicking the header/footer while ALREADY on the
|
|
60
|
+
// Pages tab (e.g. mid image-replace from a footer icon) needs its own
|
|
61
|
+
// explicit reset here, or the panel stays stuck on the picker instead of
|
|
62
|
+
// scrolling to the section.
|
|
63
|
+
test('header click clears a leftover mode explicitly, not just via the tab switch', () => {
|
|
64
|
+
const context = createContext();
|
|
65
|
+
|
|
66
|
+
onPageHeaderContainerClick.call(context);
|
|
67
|
+
|
|
68
|
+
expect(context.contentSettingsStore.resetMode).toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('footer click clears a leftover mode explicitly, not just via the tab switch', () => {
|
|
72
|
+
const context = createContext();
|
|
73
|
+
|
|
74
|
+
onPageFooterContainerClick.call(context);
|
|
75
|
+
|
|
76
|
+
expect(context.contentSettingsStore.resetMode).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { SideBarTab } from '@shared/side-bar/models';
|
|
2
|
-
import { constantsTr } from '@src/composables/useTranslate';
|
|
2
|
+
import { constantsTr, pageSettingsTr } from '@src/composables/useTranslate';
|
|
3
3
|
|
|
4
4
|
export const SIDE_BAR_TAB_NAMES = {
|
|
5
5
|
PREVIEW: 'Preview',
|
|
6
6
|
TEMPLATE_SETTINGS: 'TemplatesSettings',
|
|
7
|
+
PAGE_SETTINGS: 'PageSettings',
|
|
7
8
|
CONTENT_SETTINGS: 'ContentSettings',
|
|
8
9
|
BACKGROUND_SETTINGS: 'BackgroundSettings',
|
|
9
10
|
ADMIN_BACKGROUND_SETTINGS: 'AdminBackgroundSettings',
|
|
@@ -31,6 +32,14 @@ export const DEFAULT_SIDE_BAR_TABS = (): SideBarTab[] => [
|
|
|
31
32
|
isDisabledForAdmin: false,
|
|
32
33
|
isVisible: true,
|
|
33
34
|
},
|
|
35
|
+
{
|
|
36
|
+
name: SIDE_BAR_TAB_NAMES.PAGE_SETTINGS,
|
|
37
|
+
displayName: pageSettingsTr(`pages`),
|
|
38
|
+
iconName: 'page-blank',
|
|
39
|
+
accessibleDisplayName: 'Pages',
|
|
40
|
+
isDisabledForAdmin: false,
|
|
41
|
+
isVisible: true,
|
|
42
|
+
},
|
|
34
43
|
{
|
|
35
44
|
name: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
|
|
36
45
|
displayName: constantsTr(`contentDisplayName`),
|
|
@@ -839,17 +839,22 @@ describe('brand page maker store module', () => {
|
|
|
839
839
|
|
|
840
840
|
await makerStore.initialise(INITIALISE_PAYLOAD);
|
|
841
841
|
|
|
842
|
-
// Simulate the user opening a content item's focused settings.
|
|
842
|
+
// Simulate the user opening a content item's focused settings. Tab first,
|
|
843
|
+
// then mode — focusing an item is only possible once already on the
|
|
844
|
+
// Content tab (setSelectedTabName resets a leftover mode on an actual tab
|
|
845
|
+
// change, so pushing the mode before landing on the tab would be
|
|
846
|
+
// backwards from how this happens for real, and would immediately wipe
|
|
847
|
+
// it here too).
|
|
843
848
|
const orphanItemId = 'orphan-content-id-not-in-snapshot';
|
|
844
849
|
|
|
850
|
+
sideBarStore.setSelectedTabName({
|
|
851
|
+
tabName: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
|
|
852
|
+
});
|
|
845
853
|
contentSettingsStore.pushMode({
|
|
846
854
|
mode: CONTENT_SETTINGS_MODES.focusedContentItem,
|
|
847
855
|
selectedItemId: orphanItemId,
|
|
848
856
|
});
|
|
849
857
|
contentSettingsStore.selectedItemId = orphanItemId;
|
|
850
|
-
sideBarStore.setSelectedTabName({
|
|
851
|
-
tabName: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
|
|
852
|
-
});
|
|
853
858
|
|
|
854
859
|
// Pre-condition: panel is showing the focused content item.
|
|
855
860
|
expect(contentSettingsStore.mode).toBe(
|
|
@@ -4,14 +4,12 @@ import type { Content } from '@brand-page';
|
|
|
4
4
|
import type { ItemCategory } from '@brand-page-maker/models';
|
|
5
5
|
import { ITEM_CATEGORIES, ITEM_CATEGORY_NAMES } from '@brand-page-maker/models';
|
|
6
6
|
import { UI_EVENT_SOURCES } from '../../../models';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from '../../../page-settings/store';
|
|
7
|
+
import { useUiPageSettingsStore } from '../../../page-settings/store';
|
|
8
|
+
import { useUiSideBarStore } from '../../../side-bar/store';
|
|
9
|
+
import { SIDE_BAR_TAB_NAMES } from '@brand-page-maker/constants';
|
|
11
10
|
import { useUiContentSettingsStore } from '../../store';
|
|
12
11
|
import { CONTENT_SETTINGS_MODES } from '../../store';
|
|
13
12
|
import {
|
|
14
|
-
useBrandPageMakerStore,
|
|
15
13
|
useBrandPageMakerUserStore,
|
|
16
14
|
useBrandPageContainerStore,
|
|
17
15
|
} from '@brand-page-maker/stores';
|
|
@@ -39,11 +37,11 @@ interface CategoryTab {
|
|
|
39
37
|
export default defineComponent({
|
|
40
38
|
emits: ['capture-preview-snapshot'],
|
|
41
39
|
setup() {
|
|
42
|
-
const brandPageMakerStore = useBrandPageMakerStore();
|
|
43
40
|
const contentSettingsStore = useUiContentSettingsStore();
|
|
44
41
|
const pageSettingsStore = useUiPageSettingsStore();
|
|
45
42
|
const pageNavigationStore = usePageNavigationStore();
|
|
46
43
|
const styleSettingsStore = useUiStyleSettingsStore();
|
|
44
|
+
const sideBarStore = useUiSideBarStore();
|
|
47
45
|
const userStore = useBrandPageMakerUserStore();
|
|
48
46
|
const containerStore = useBrandPageContainerStore();
|
|
49
47
|
const eventTracker = useEventTracker();
|
|
@@ -52,10 +50,8 @@ export default defineComponent({
|
|
|
52
50
|
|
|
53
51
|
return {
|
|
54
52
|
mode: computed(() => contentSettingsStore.mode),
|
|
55
|
-
pages: computed(() => pageSettingsStore.pages),
|
|
56
53
|
activePageId: computed(() => pageNavigationStore.activePageId),
|
|
57
54
|
activeCategoryTab: computed(() => contentSettingsStore.activeCategoryTab),
|
|
58
|
-
isBrandSite: computed(() => brandPageMakerStore.isBrandSite),
|
|
59
55
|
contentSettingsSelectedItemId: computed(
|
|
60
56
|
() => contentSettingsStore.selectedItemId,
|
|
61
57
|
),
|
|
@@ -63,10 +59,10 @@ export default defineComponent({
|
|
|
63
59
|
canUseRichTextEditor: computed(
|
|
64
60
|
() => userStore.features.canUseRichTextEditor,
|
|
65
61
|
),
|
|
66
|
-
brandPageMakerStore,
|
|
67
62
|
contentSettingsStore,
|
|
68
63
|
pageNavigationStore,
|
|
69
64
|
pageSettingsStore,
|
|
65
|
+
sideBarStore,
|
|
70
66
|
styleSettingsStore,
|
|
71
67
|
eventTracker,
|
|
72
68
|
historyStore,
|
|
@@ -81,7 +77,6 @@ export default defineComponent({
|
|
|
81
77
|
label: ITEM_CATEGORY_NAMES()[c].displayName,
|
|
82
78
|
})),
|
|
83
79
|
] as CategoryTab[],
|
|
84
|
-
isAddPageModalVisible: false,
|
|
85
80
|
};
|
|
86
81
|
},
|
|
87
82
|
mounted() {
|
|
@@ -99,9 +94,6 @@ export default defineComponent({
|
|
|
99
94
|
showPageControls(): boolean {
|
|
100
95
|
return true;
|
|
101
96
|
},
|
|
102
|
-
isManagePagesButtonVisible(): boolean {
|
|
103
|
-
return this.isBrandSite || this.pageSettingsStore.pages.length > 1;
|
|
104
|
-
},
|
|
105
97
|
visibleCategoryTabs(): CategoryTab[] {
|
|
106
98
|
return this.categoryTabs.filter(
|
|
107
99
|
(t) =>
|
|
@@ -223,12 +215,8 @@ export default defineComponent({
|
|
|
223
215
|
);
|
|
224
216
|
},
|
|
225
217
|
onManagePageButtonClick(): void {
|
|
226
|
-
this.
|
|
227
|
-
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
this.pageSettingsStore.setSelectedSectionName({
|
|
231
|
-
sectionName: PAGE_SETTINGS_SECTIONS.pages,
|
|
218
|
+
this.sideBarStore.setSelectedTabName({
|
|
219
|
+
tabName: SIDE_BAR_TAB_NAMES.PAGE_SETTINGS,
|
|
232
220
|
});
|
|
233
221
|
},
|
|
234
222
|
onAddPageButtonClick(): void {
|
package/src/shared/content-settings/components/content-settings/ContentSettings.pages-tab.test.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, test, expect, vi } from 'vitest';
|
|
2
|
+
import ContentSettingsMixin from './ContentSettings.mixin';
|
|
3
|
+
import { SIDE_BAR_TAB_NAMES } from '@brand-page-maker/constants';
|
|
4
|
+
|
|
5
|
+
// The Content tab's "Manage Pages" dropdown item and gear icon both redirect to
|
|
6
|
+
// the dedicated Pages tab (BP-5855) — they no longer open a nested sub-mode.
|
|
7
|
+
// Driving the handler keeps the test light.
|
|
8
|
+
const { onManagePageButtonClick } = (ContentSettingsMixin as any).methods;
|
|
9
|
+
|
|
10
|
+
describe('ContentSettings — Manage Pages redirects to the Pages tab', () => {
|
|
11
|
+
test('onManagePageButtonClick switches to the Pages tab', () => {
|
|
12
|
+
const context = { sideBarStore: { setSelectedTabName: vi.fn() } };
|
|
13
|
+
|
|
14
|
+
onManagePageButtonClick.call(context);
|
|
15
|
+
|
|
16
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
17
|
+
tabName: SIDE_BAR_TAB_NAMES.PAGE_SETTINGS,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -37,7 +37,6 @@
|
|
|
37
37
|
@on-click.stop="onAddNewPageSelected()"
|
|
38
38
|
/>
|
|
39
39
|
<Button
|
|
40
|
-
v-if="isManagePagesButtonVisible"
|
|
41
40
|
data-test-tag="manage-pages"
|
|
42
41
|
icon="settings"
|
|
43
42
|
icon-size="md"
|
|
@@ -134,10 +133,6 @@
|
|
|
134
133
|
/>
|
|
135
134
|
<!-- End of Image mode -->
|
|
136
135
|
|
|
137
|
-
<!-- Start of Page mode -->
|
|
138
|
-
<PageSettings v-if="mode === CONTENT_SETTINGS_MODES.pages" />
|
|
139
|
-
<!-- End of Page mode -->
|
|
140
|
-
|
|
141
136
|
<!-- Start of Single Content Item Settings -->
|
|
142
137
|
<FocusedContentItemSettings
|
|
143
138
|
v-if="mode === CONTENT_SETTINGS_MODES.focusedContentItem"
|
|
@@ -145,7 +140,7 @@
|
|
|
145
140
|
/>
|
|
146
141
|
<!-- End of Single Content Item Settings -->
|
|
147
142
|
|
|
148
|
-
<NewPageModal
|
|
143
|
+
<NewPageModal />
|
|
149
144
|
</div>
|
|
150
145
|
</template>
|
|
151
146
|
<script>
|
|
@@ -158,7 +153,6 @@ import ReplaceImageSettingsForContent from './ReplaceImageSettingsForContent.vue
|
|
|
158
153
|
import ContentSettingsButton from './ContentSettingsButton.vue';
|
|
159
154
|
import ContentSettingsLockedButton from './ContentSettingsLockedButton.vue';
|
|
160
155
|
import NewPageModal from '../../../page-settings/components/new-page-modal/NewPageModal.vue';
|
|
161
|
-
import PageSettings from '../../../page-settings/components/page-settings/PageSettings.vue';
|
|
162
156
|
import FocusedContentItemSettings from '../focused-content-item-settings/FocusedContentItemSettings.vue';
|
|
163
157
|
import { CONTENT_SETTINGS_MODES } from '../../store';
|
|
164
158
|
import { contentSettingsTr } from '@src/composables/useTranslate';
|
|
@@ -175,7 +169,6 @@ export default {
|
|
|
175
169
|
ReorderableList,
|
|
176
170
|
ReplaceImageSettingsForContent,
|
|
177
171
|
NewPageModal,
|
|
178
|
-
PageSettings,
|
|
179
172
|
PageSelectorDropDown,
|
|
180
173
|
},
|
|
181
174
|
mixins: [ContentSettingsMixin],
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { describe, test, expect, beforeEach } from 'vitest';
|
|
2
|
+
import { createPinia, setActivePinia } from 'pinia';
|
|
3
|
+
import { shallowMount } from '@vue/test-utils';
|
|
4
|
+
import PageSettings from './PageSettings.vue';
|
|
5
|
+
import ReplaceImageSettingsForContent from '../../../content-settings/components/content-settings/ReplaceImageSettingsForContent.vue';
|
|
6
|
+
import { useUiContentSettingsStore } from '../../../content-settings/store';
|
|
7
|
+
import { UI_EVENT_SOURCES } from '../../../models';
|
|
8
|
+
|
|
9
|
+
// Regression coverage for BP-5855: a header/footer image-replace intent (e.g. a social
|
|
10
|
+
// link icon) used to push the shared content-settings image-picker mode while
|
|
11
|
+
// PageSettings was still nested inside ContentSettings — pushing that mode swapped the
|
|
12
|
+
// panel in place. Now that PageSettings renders as its own sidebar tab
|
|
13
|
+
// (`<component :is="selectedTabName">` in BrandPageMaker.vue), the picker never mounted
|
|
14
|
+
// and the mode leaked into the next Content-tab visit. PageSettings must render the
|
|
15
|
+
// picker itself when the intent came from page settings, and hide the pages body while
|
|
16
|
+
// it's open.
|
|
17
|
+
describe('PageSettings — header/footer image-replace intent', () => {
|
|
18
|
+
let contentSettingsStore: ReturnType<typeof useUiContentSettingsStore>;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
setActivePinia(createPinia());
|
|
22
|
+
contentSettingsStore = useUiContentSettingsStore();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const mountPageSettings = () => shallowMount(PageSettings);
|
|
26
|
+
|
|
27
|
+
const pagesBodyIsVisible = (
|
|
28
|
+
wrapper: ReturnType<typeof mountPageSettings>,
|
|
29
|
+
): boolean =>
|
|
30
|
+
(
|
|
31
|
+
wrapper.find('[data-component="page-settings"] > div')
|
|
32
|
+
.element as HTMLElement
|
|
33
|
+
).style.display !== 'none';
|
|
34
|
+
|
|
35
|
+
test('by default: no picker, pages body visible', () => {
|
|
36
|
+
const wrapper = mountPageSettings();
|
|
37
|
+
|
|
38
|
+
expect(wrapper.findComponent(ReplaceImageSettingsForContent).exists()).toBe(
|
|
39
|
+
false,
|
|
40
|
+
);
|
|
41
|
+
expect(pagesBodyIsVisible(wrapper)).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('a page-settings image-replace intent opens the picker and hides the pages body', async () => {
|
|
45
|
+
const wrapper = mountPageSettings();
|
|
46
|
+
|
|
47
|
+
contentSettingsStore.setSelectedItemAndFieldName({
|
|
48
|
+
id: 'footer',
|
|
49
|
+
name: 'socialLinks',
|
|
50
|
+
index: 0,
|
|
51
|
+
eventSource: UI_EVENT_SOURCES.pageSettings,
|
|
52
|
+
});
|
|
53
|
+
contentSettingsStore.pushMode({ mode: 'images' });
|
|
54
|
+
await wrapper.vm.$nextTick();
|
|
55
|
+
|
|
56
|
+
expect(wrapper.findComponent(ReplaceImageSettingsForContent).exists()).toBe(
|
|
57
|
+
true,
|
|
58
|
+
);
|
|
59
|
+
expect(pagesBodyIsVisible(wrapper)).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('does not open the picker for a content-settings-sourced image intent', async () => {
|
|
63
|
+
const wrapper = mountPageSettings();
|
|
64
|
+
|
|
65
|
+
contentSettingsStore.setSelectedItemAndFieldName({
|
|
66
|
+
id: 'some-content-item',
|
|
67
|
+
name: 'image',
|
|
68
|
+
index: 0,
|
|
69
|
+
eventSource: UI_EVENT_SOURCES.contentSettings,
|
|
70
|
+
});
|
|
71
|
+
contentSettingsStore.pushMode({ mode: 'images' });
|
|
72
|
+
await wrapper.vm.$nextTick();
|
|
73
|
+
|
|
74
|
+
expect(wrapper.findComponent(ReplaceImageSettingsForContent).exists()).toBe(
|
|
75
|
+
false,
|
|
76
|
+
);
|
|
77
|
+
expect(pagesBodyIsVisible(wrapper)).toBe(true);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('popping the mode after picking an image restores the pages body', async () => {
|
|
81
|
+
const wrapper = mountPageSettings();
|
|
82
|
+
|
|
83
|
+
contentSettingsStore.setSelectedItemAndFieldName({
|
|
84
|
+
id: 'footer',
|
|
85
|
+
name: 'socialLinks',
|
|
86
|
+
index: 0,
|
|
87
|
+
eventSource: UI_EVENT_SOURCES.pageSettings,
|
|
88
|
+
});
|
|
89
|
+
contentSettingsStore.pushMode({ mode: 'images' });
|
|
90
|
+
await wrapper.vm.$nextTick();
|
|
91
|
+
|
|
92
|
+
contentSettingsStore.popMode();
|
|
93
|
+
await wrapper.vm.$nextTick();
|
|
94
|
+
|
|
95
|
+
expect(wrapper.findComponent(ReplaceImageSettingsForContent).exists()).toBe(
|
|
96
|
+
false,
|
|
97
|
+
);
|
|
98
|
+
expect(pagesBodyIsVisible(wrapper)).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -16,7 +16,11 @@ import {
|
|
|
16
16
|
PAGE_SECTION_STYLE_OPTIONS,
|
|
17
17
|
type PageSectionStyleOption,
|
|
18
18
|
} from '@brand-page-maker/models/page-section-style.model';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
CONTENT_SETTINGS_MODES,
|
|
21
|
+
useUiContentSettingsStore,
|
|
22
|
+
} from '../../../content-settings/store';
|
|
23
|
+
import { UI_EVENT_SOURCES } from '../../../models';
|
|
20
24
|
import {
|
|
21
25
|
PAGE_SETTINGS_SECTIONS,
|
|
22
26
|
type PageSettingsSection,
|
|
@@ -47,13 +51,6 @@ export interface PageField {
|
|
|
47
51
|
page: ContentPage;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
const PAGE_SETTINGS_PAGES = {
|
|
51
|
-
page: 'page',
|
|
52
|
-
logo: 'logo',
|
|
53
|
-
} as const;
|
|
54
|
-
|
|
55
|
-
type PageSettingsPage = keyof typeof PAGE_SETTINGS_PAGES;
|
|
56
|
-
|
|
57
54
|
const isRouteNestedInOrders = (
|
|
58
55
|
orders: NavOrder[],
|
|
59
56
|
routeId: string,
|
|
@@ -274,8 +271,6 @@ export default defineComponent({
|
|
|
274
271
|
isDeleteModalVisible: false,
|
|
275
272
|
deleteModalPageId: undefined as string | undefined,
|
|
276
273
|
deleteModalPageTitle: undefined as string | undefined,
|
|
277
|
-
currentPageNo: PAGE_SETTINGS_PAGES.page as PageSettingsPage,
|
|
278
|
-
PAGE_SETTINGS_PAGES,
|
|
279
274
|
PAGE_SETTINGS_SECTIONS,
|
|
280
275
|
ALIGN_LEFT_ALIGNED,
|
|
281
276
|
ALIGN_CENTERED,
|
|
@@ -334,6 +329,15 @@ export default defineComponent({
|
|
|
334
329
|
showFooterSettings(): boolean {
|
|
335
330
|
return this.isBrandSite;
|
|
336
331
|
},
|
|
332
|
+
// Header/footer image-replace intents (e.g. a social link icon) route through the
|
|
333
|
+
// shared content-settings image picker rather than duplicating it here.
|
|
334
|
+
isReplacingPageSettingsImage(): boolean {
|
|
335
|
+
return (
|
|
336
|
+
this.contentSettingsStore.mode === CONTENT_SETTINGS_MODES.images &&
|
|
337
|
+
this.contentSettingsStore.selectedItemEventSource ===
|
|
338
|
+
UI_EVENT_SOURCES.pageSettings
|
|
339
|
+
);
|
|
340
|
+
},
|
|
337
341
|
hideText() {
|
|
338
342
|
return this.isDesignCom
|
|
339
343
|
? styleSettingsTr(`hideDesignLogo`)
|
|
@@ -474,33 +478,12 @@ export default defineComponent({
|
|
|
474
478
|
onCancelDeletePage() {
|
|
475
479
|
this.isDeleteModalVisible = false;
|
|
476
480
|
},
|
|
477
|
-
onLogoVariationSelected(value: string) {
|
|
478
|
-
if (!this.selectedSectionName) {
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
const sectionName = this.selectedSectionName;
|
|
483
|
-
|
|
484
|
-
this.pageSettingsStore.setPageSettingsSectionValue({
|
|
485
|
-
sectionName,
|
|
486
|
-
propName: 'logoImageUrl',
|
|
487
|
-
value,
|
|
488
|
-
viewport: this.viewport,
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
this.currentPageNo = PAGE_SETTINGS_PAGES.page;
|
|
492
|
-
|
|
493
|
-
this.pageSettingsStore.setSelectedSectionName({ sectionName });
|
|
494
|
-
},
|
|
495
481
|
onPageTitleInput(pageId: string, title: string) {
|
|
496
482
|
this.pageSettingsStore.setPageTitle({
|
|
497
483
|
pageId,
|
|
498
484
|
pageTitle: title,
|
|
499
485
|
});
|
|
500
486
|
},
|
|
501
|
-
onBackButtonClick() {
|
|
502
|
-
this.contentSettingsStore.popMode();
|
|
503
|
-
},
|
|
504
487
|
scrollToPageSettingsSection(sectionName: PageSettingsSection) {
|
|
505
488
|
this.$nextTick(() => {
|
|
506
489
|
const $sideBarContent = document.querySelector(
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div data-component="page-settings">
|
|
3
|
+
<!-- Header/footer image-replace intent (e.g. a social link icon) — shares the
|
|
4
|
+
content-settings image picker instead of duplicating it. -->
|
|
5
|
+
<ReplaceImageSettingsForContent v-if="isReplacingPageSettingsImage" />
|
|
3
6
|
<!-- start page settings -->
|
|
4
|
-
<div v-show="
|
|
5
|
-
<SideBarSettingsHeader
|
|
6
|
-
:title="pageSettingsTr('managePages')"
|
|
7
|
-
:show-back-button="true"
|
|
8
|
-
@on-back="onBackButtonClick"
|
|
9
|
-
/>
|
|
7
|
+
<div v-show="!isReplacingPageSettingsImage">
|
|
8
|
+
<SideBarSettingsHeader :title="pageSettingsTr('managePages')" />
|
|
10
9
|
<p class="tw-font-sans tw-text-sm tw-text-grayscale-600 tw-mb-3">
|
|
11
10
|
{{ pageSettingsTr('addPagesDescription') }}
|
|
12
11
|
</p>
|
|
@@ -19,7 +18,6 @@
|
|
|
19
18
|
<SideBarSectionTitle :title="pageSettingsTr('addPages')" />
|
|
20
19
|
<!-- Nested draggable section for visible pages -->
|
|
21
20
|
<NestedDraggable
|
|
22
|
-
v-if="!parentRouteId"
|
|
23
21
|
:orders="pageNavigationStore.orders"
|
|
24
22
|
:is-dragging-page="isDraggingPage"
|
|
25
23
|
:is-design-com="isDesignCom"
|
|
@@ -105,6 +103,8 @@
|
|
|
105
103
|
@cancel="onCancelDeletePage"
|
|
106
104
|
@confirm="onConfirmDeletePage"
|
|
107
105
|
/>
|
|
106
|
+
|
|
107
|
+
<NewPageModal />
|
|
108
108
|
</div>
|
|
109
109
|
<!-- end page settings -->
|
|
110
110
|
</div>
|
|
@@ -115,7 +115,9 @@ import SideBarSettingsHeader from '../../../common/SideBarSettingsHeader.vue';
|
|
|
115
115
|
import PageSettingsMixin from './PageSettings.mixin.ts';
|
|
116
116
|
import SideBarSectionTitle from '../../../common/SideBarSectionTitle.vue';
|
|
117
117
|
import DeletePageModal from '../delete-page-modal/DeletePageModal.vue';
|
|
118
|
+
import NewPageModal from '../new-page-modal/NewPageModal.vue';
|
|
118
119
|
import PageSettingsSectionStyles from '../page-settings-section-styles/PageSettingsSectionStyles.vue';
|
|
120
|
+
import ReplaceImageSettingsForContent from '../../../content-settings/components/content-settings/ReplaceImageSettingsForContent.vue';
|
|
119
121
|
import NestedDraggable from './NestedDraggable.vue';
|
|
120
122
|
import { useBrandPageContainerStore } from '@brand-page-maker/stores';
|
|
121
123
|
import { pageSettingsTr, styleSettingsTr } from '@src/composables/useTranslate';
|
|
@@ -129,7 +131,9 @@ export default {
|
|
|
129
131
|
SideBarSectionTitle,
|
|
130
132
|
NestedDraggable,
|
|
131
133
|
DeletePageModal,
|
|
134
|
+
NewPageModal,
|
|
132
135
|
PageSettingsSectionStyles,
|
|
136
|
+
ReplaceImageSettingsForContent,
|
|
133
137
|
},
|
|
134
138
|
mixins: [PageSettingsMixin],
|
|
135
139
|
setup(_props, _context) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, test, expect, vi } from 'vitest';
|
|
2
|
+
import SideBarMixin from './SideBar.mixin';
|
|
3
|
+
import { SIDE_BAR_TAB_NAMES } from '@src/brand-page-maker/constants/sidebar-constant';
|
|
4
|
+
|
|
5
|
+
// The desktop landing tab is chosen by NAME, not list position — inserting the
|
|
6
|
+
// Pages tab between Templates and Content must not change where an editor opens
|
|
7
|
+
// (BP-5855). Driving update() directly keeps the guard cheap.
|
|
8
|
+
const update = (SideBarMixin as any).methods.update;
|
|
9
|
+
|
|
10
|
+
const createContext = (
|
|
11
|
+
overrides: {
|
|
12
|
+
isMobileScreenSize?: boolean;
|
|
13
|
+
isPublished?: boolean;
|
|
14
|
+
isUserDraft?: boolean;
|
|
15
|
+
mobileTabName?: string;
|
|
16
|
+
} = {},
|
|
17
|
+
) => ({
|
|
18
|
+
isMobileScreenSize: overrides.isMobileScreenSize ?? false,
|
|
19
|
+
mobileTabName: overrides.mobileTabName ?? SIDE_BAR_TAB_NAMES.PREVIEW,
|
|
20
|
+
brandPageContainerStore: {
|
|
21
|
+
isPublished: overrides.isPublished ?? false,
|
|
22
|
+
isUserDraft: overrides.isUserDraft ?? false,
|
|
23
|
+
},
|
|
24
|
+
sideBarStore: { setSelectedTabName: vi.fn() },
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('SideBar.update — default landing tab', () => {
|
|
28
|
+
test('a published site opens on Content', () => {
|
|
29
|
+
const context = createContext({ isPublished: true });
|
|
30
|
+
|
|
31
|
+
update.call(context);
|
|
32
|
+
|
|
33
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
34
|
+
tabName: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('an existing user draft opens on Content', () => {
|
|
39
|
+
const context = createContext({ isUserDraft: true });
|
|
40
|
+
|
|
41
|
+
update.call(context);
|
|
42
|
+
|
|
43
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
44
|
+
tabName: SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('a brand-new site opens on Templates', () => {
|
|
49
|
+
const context = createContext();
|
|
50
|
+
|
|
51
|
+
update.call(context);
|
|
52
|
+
|
|
53
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
54
|
+
tabName: SIDE_BAR_TAB_NAMES.TEMPLATE_SETTINGS,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('mobile opens on the preview tab', () => {
|
|
59
|
+
const context = createContext({ isMobileScreenSize: true });
|
|
60
|
+
|
|
61
|
+
update.call(context);
|
|
62
|
+
|
|
63
|
+
expect(context.sideBarStore.setSelectedTabName).toHaveBeenCalledWith({
|
|
64
|
+
tabName: SIDE_BAR_TAB_NAMES.PREVIEW,
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -73,15 +73,15 @@ export default defineComponent({
|
|
|
73
73
|
methods: {
|
|
74
74
|
update() {
|
|
75
75
|
if (this.isMobileScreenSize === false) {
|
|
76
|
-
|
|
76
|
+
// Land on Content for returning editors, Templates for new sites.
|
|
77
|
+
// Select by name, not list position — the tab order is not fixed.
|
|
78
|
+
const tabName =
|
|
77
79
|
this.brandPageContainerStore.isPublished ||
|
|
78
80
|
this.brandPageContainerStore.isUserDraft
|
|
79
|
-
?
|
|
80
|
-
:
|
|
81
|
+
? SIDE_BAR_TAB_NAMES.CONTENT_SETTINGS
|
|
82
|
+
: SIDE_BAR_TAB_NAMES.TEMPLATE_SETTINGS;
|
|
81
83
|
|
|
82
|
-
this.sideBarStore.setSelectedTabName({
|
|
83
|
-
tabName: this.tabs.filter((x) => !x.isMobileOnly)[index].name,
|
|
84
|
-
});
|
|
84
|
+
this.sideBarStore.setSelectedTabName({ tabName });
|
|
85
85
|
} else {
|
|
86
86
|
this.sideBarStore.setSelectedTabName({ tabName: this.mobileTabName });
|
|
87
87
|
}
|