@griddo/ax 1.73.29 → 1.74.1
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/config/griddo-config/index.js +24 -3
- package/config/webpackSchemas.config.js +3 -5
- package/package.json +3 -2
- package/scripts/griddo-sync-schemas.js +4 -3
- package/src/__mocks__/axios/SitesList.ts +84 -0
- package/src/__mocks__/store/SitesList.ts +714 -0
- package/src/__tests__/components/Avatar/Avatar.test.tsx +119 -0
- package/src/__tests__/components/Avatar/__snapshots__/Avatar.test.tsx.snap +61 -0
- package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +10 -10
- package/src/__tests__/components/LanguageMenu/LanguageMenu.test.tsx +221 -0
- package/src/__tests__/components/Loading/Loading.test.tsx +23 -0
- package/src/__tests__/components/Login/Login.test.tsx +247 -0
- package/src/__tests__/components/Login/RecoveryModal/RecoveryModal.test.tsx +185 -0
- package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +6 -6
- package/src/__tests__/modules/Sites/Sites.test.tsx +259 -0
- package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +51 -0
- package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +896 -0
- package/src/api/sites.tsx +43 -4
- package/src/components/ActionMenu/index.tsx +1 -1
- package/src/components/Avatar/index.tsx +4 -4
- package/src/components/Browser/index.tsx +27 -20
- package/src/components/BrowserContent/index.tsx +6 -0
- package/src/components/Fields/AsyncSelect/style.tsx +6 -3
- package/src/components/Fields/CheckField/index.tsx +1 -0
- package/src/components/Fields/DateField/style.tsx +3 -1
- package/src/components/Fields/HeadingField/index.tsx +14 -5
- package/src/components/Fields/ImageField/index.tsx +3 -0
- package/src/components/Fields/ImageField/style.tsx +2 -2
- package/src/components/Fields/Select/style.tsx +2 -0
- package/src/components/Fields/SliderField/index.tsx +2 -1
- package/src/components/Fields/TextField/index.tsx +1 -0
- package/src/components/Icon/components/BulletList.js +16 -0
- package/src/components/Icon/components/Grid2.js +16 -0
- package/src/components/Icon/svgs/Bullet-list.svg +3 -0
- package/src/components/Icon/svgs/Grid-2.svg +3 -0
- package/src/components/IconAction/index.tsx +4 -2
- package/src/components/IconAction/style.tsx +8 -2
- package/src/components/LanguageMenu/index.tsx +13 -6
- package/src/components/Login/RecoveryModal/index.tsx +5 -4
- package/src/components/Login/index.tsx +13 -3
- package/src/components/Login/style.tsx +12 -25
- package/src/components/Pagination/style.tsx +1 -1
- package/src/components/SearchField/index.tsx +9 -1
- package/src/components/SideModal/style.tsx +8 -8
- package/src/components/TableFilters/LastAccessFilter/index.tsx +52 -0
- package/src/components/TableFilters/LastAccessFilter/style.tsx +31 -0
- package/src/components/TableFilters/LiveFilter/index.tsx +7 -5
- package/src/components/TableFilters/NameFilter/index.tsx +4 -3
- package/src/components/TableFilters/index.tsx +2 -0
- package/src/components/TableList/index.tsx +2 -1
- package/src/components/TableList/style.tsx +2 -2
- package/src/components/index.tsx +2 -0
- package/src/containers/App/actions.tsx +5 -0
- package/src/containers/App/interfaces.tsx +1 -1
- package/src/containers/App/reducer.tsx +1 -1
- package/src/containers/Navigation/Defaults/actions.tsx +3 -1
- package/src/containers/PageEditor/actions.tsx +6 -3
- package/src/containers/Sites/actions.tsx +76 -11
- package/src/containers/Sites/constants.tsx +2 -0
- package/src/containers/Sites/interfaces.tsx +12 -0
- package/src/containers/Sites/reducer.tsx +8 -0
- package/src/helpers/schemas.tsx +27 -1
- package/src/hooks/iframe.ts +56 -0
- package/src/hooks/index.tsx +3 -0
- package/src/modules/Content/index.tsx +4 -3
- package/src/modules/FramePreview/index.tsx +25 -39
- package/src/modules/GlobalEditor/Editor/index.tsx +2 -2
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +11 -7
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -3
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +1 -0
- package/src/modules/PageEditor/Editor/index.tsx +2 -2
- package/src/modules/PageEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/PageEditor/index.tsx +8 -7
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/index.tsx +12 -11
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +3 -17
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/style.tsx +2 -10
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/index.tsx +72 -0
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/style.tsx +32 -0
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/index.tsx +17 -27
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/style.tsx +14 -25
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +64 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/style.tsx +50 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +75 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/style.tsx +8 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +200 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/style.tsx +112 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/index.tsx +50 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/style.tsx +28 -0
- package/src/modules/Sites/SitesList/SiteModal/index.tsx +4 -3
- package/src/modules/Sites/SitesList/atoms.tsx +47 -0
- package/src/modules/Sites/SitesList/hooks.tsx +102 -0
- package/src/modules/Sites/SitesList/index.tsx +272 -19
- package/src/modules/Sites/SitesList/style.tsx +157 -4
- package/src/modules/Sites/SitesList/utils.tsx +33 -0
- package/src/modules/Sites/index.tsx +6 -11
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/types/index.tsx +25 -2
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SET_SITES,
|
|
3
|
+
SET_RECENT_SITES,
|
|
4
|
+
SET_SITES_TOTAL_ITEMS,
|
|
3
5
|
SET_SITES_BY_LANG,
|
|
4
6
|
SET_CURRENT_SITE_INFO,
|
|
5
7
|
SET_CURRENT_SITE_PAGES,
|
|
@@ -20,6 +22,8 @@ export interface ISitesState {
|
|
|
20
22
|
currentSiteName: string | null;
|
|
21
23
|
currentSitePages: IPage[];
|
|
22
24
|
sites: ISite[];
|
|
25
|
+
recentSites: ISite[];
|
|
26
|
+
sitesTotalItems: number;
|
|
23
27
|
sitesByLang: ISite[];
|
|
24
28
|
currentSiteInfo: any;
|
|
25
29
|
currentFilter: string | null;
|
|
@@ -34,10 +38,12 @@ export const initialState = {
|
|
|
34
38
|
currentSiteName: null,
|
|
35
39
|
currentSitePages: [],
|
|
36
40
|
sites: [],
|
|
41
|
+
recentSites: [],
|
|
37
42
|
sitesByLang: [],
|
|
38
43
|
currentSiteInfo: null,
|
|
39
44
|
currentFilter: "unique-pages",
|
|
40
45
|
totalItems: 0,
|
|
46
|
+
sitesTotalItems: 0,
|
|
41
47
|
currentSiteLanguages: [],
|
|
42
48
|
savedSiteInfo: null,
|
|
43
49
|
currentSiteErrorPages: [],
|
|
@@ -48,6 +54,8 @@ export function reducer(state = initialState, action: SitesActionsCreators): ISi
|
|
|
48
54
|
switch (action.type) {
|
|
49
55
|
case SET_FILTER:
|
|
50
56
|
case SET_SITES:
|
|
57
|
+
case SET_RECENT_SITES:
|
|
58
|
+
case SET_SITES_TOTAL_ITEMS:
|
|
51
59
|
case SET_SITES_BY_LANG:
|
|
52
60
|
case SET_CURRENT_SITE_INFO:
|
|
53
61
|
case SET_CURRENT_SITE_PAGES:
|
package/src/helpers/schemas.tsx
CHANGED
|
@@ -6,7 +6,33 @@ import { pageSchemas } from "@ax/schemas";
|
|
|
6
6
|
const allSchemas = { ...schemas.all, ...pageSchemas };
|
|
7
7
|
|
|
8
8
|
const getSchema = (name: string) => allSchemas[name];
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
const getDefaultSchema = (name: string) => {
|
|
11
|
+
const defaultSchema = allSchemas[name] ? allSchemas[name].default : {};
|
|
12
|
+
|
|
13
|
+
for (const key of Object.keys(defaultSchema)) {
|
|
14
|
+
if (
|
|
15
|
+
defaultSchema[key] &&
|
|
16
|
+
typeof defaultSchema[key] === "object" &&
|
|
17
|
+
Object.prototype.hasOwnProperty.call(defaultSchema[key], "schema")
|
|
18
|
+
) {
|
|
19
|
+
defaultSchema[key] = getDefaultSchema(defaultSchema[key].schema);
|
|
20
|
+
}
|
|
21
|
+
if (defaultSchema[key] instanceof Array) {
|
|
22
|
+
for (const i in defaultSchema[key]) {
|
|
23
|
+
if (
|
|
24
|
+
defaultSchema[key][i] &&
|
|
25
|
+
typeof defaultSchema[key][i] === "object" &&
|
|
26
|
+
Object.prototype.hasOwnProperty.call(defaultSchema[key][i], "schema")
|
|
27
|
+
) {
|
|
28
|
+
defaultSchema[key][i] = getDefaultSchema(defaultSchema[key][i].schema);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return defaultSchema;
|
|
35
|
+
};
|
|
10
36
|
|
|
11
37
|
const getSchemaThumbnails = (name: string, theme?: string) => {
|
|
12
38
|
if (!allSchemas[name]?.thumbnails) return null;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useCallback, useEffect } from "react";
|
|
2
|
+
|
|
3
|
+
const useOnMessageReceivedFromIframe = (actions?: {
|
|
4
|
+
setSelectedContentAction: any;
|
|
5
|
+
deleteModuleAction(editorID: number): void;
|
|
6
|
+
duplicateModuleAction(editorID: number): Promise<number>;
|
|
7
|
+
}): void => {
|
|
8
|
+
const onMessageReceivedFromIframe = useCallback(
|
|
9
|
+
async (ev: MessageEvent<{ type: string; message: string }>) => {
|
|
10
|
+
if (typeof ev.data !== "object") return;
|
|
11
|
+
if (!ev.data.type) return;
|
|
12
|
+
if (!ev.data.message) return;
|
|
13
|
+
if (ev.data.type === "module-click") {
|
|
14
|
+
actions?.setSelectedContentAction(ev.data.message);
|
|
15
|
+
}
|
|
16
|
+
if (ev.data.type === "module-delete") {
|
|
17
|
+
actions?.setSelectedContentAction(0);
|
|
18
|
+
actions?.deleteModuleAction(parseInt(ev.data.message));
|
|
19
|
+
}
|
|
20
|
+
if (ev.data.type === "module-duplicate") {
|
|
21
|
+
const duplicatedEditorID = await actions?.duplicateModuleAction(parseInt(ev.data.message));
|
|
22
|
+
actions?.setSelectedContentAction(duplicatedEditorID);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
[actions]
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
window.addEventListener("message", onMessageReceivedFromIframe);
|
|
30
|
+
return () => window.removeEventListener("message", onMessageReceivedFromIframe);
|
|
31
|
+
}, [onMessageReceivedFromIframe]);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const useOnMessageReceivedFromOutside = (setEditorContent: any, setSelectedContent: any): void => {
|
|
35
|
+
const onMessageReceivedFromOutside = useCallback(
|
|
36
|
+
(ev: MessageEvent<{ type: string; message: Record<string, unknown> }>) => {
|
|
37
|
+
if (typeof ev.data !== "object") return;
|
|
38
|
+
if (!ev.data.type) return;
|
|
39
|
+
if (!ev.data.message) return;
|
|
40
|
+
if (ev.data.type === "content-update") {
|
|
41
|
+
setEditorContent(ev.data.message);
|
|
42
|
+
}
|
|
43
|
+
if (ev.data.type === "selected-content") {
|
|
44
|
+
setSelectedContent(ev.data.message);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[setEditorContent, setSelectedContent]
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
window.addEventListener("message", onMessageReceivedFromOutside);
|
|
52
|
+
return () => window.removeEventListener("message", onMessageReceivedFromOutside);
|
|
53
|
+
}, [onMessageReceivedFromOutside]);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { useOnMessageReceivedFromIframe, useOnMessageReceivedFromOutside };
|
package/src/hooks/index.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { useDebounce, useEqualStructured, useIsDirty, usePrevious } from "./form
|
|
|
3
3
|
import { useHandleClickOutside, useModal, useToast } from "./modals";
|
|
4
4
|
import { useURLSearchParam } from "./location";
|
|
5
5
|
import { useCategoryColors } from "./content";
|
|
6
|
+
import { useOnMessageReceivedFromIframe, useOnMessageReceivedFromOutside } from "./iframe";
|
|
6
7
|
|
|
7
8
|
export {
|
|
8
9
|
useModal,
|
|
@@ -15,4 +16,6 @@ export {
|
|
|
15
16
|
useBulkSelection,
|
|
16
17
|
useURLSearchParam,
|
|
17
18
|
useCategoryColors,
|
|
19
|
+
useOnMessageReceivedFromIframe,
|
|
20
|
+
useOnMessageReceivedFromOutside,
|
|
18
21
|
};
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
ISite,
|
|
18
18
|
IUser,
|
|
19
19
|
IErrorItem,
|
|
20
|
+
IGetSitesParams,
|
|
20
21
|
} from "@ax/types";
|
|
21
22
|
import { MainWrapper, Modal, TableList, ErrorToast, Toast, EmptyState, Notification } from "@ax/components";
|
|
22
23
|
import { getFilteredStructuredData, isGlobalStructuredData, isStructuredDataFromPage } from "@ax/helpers";
|
|
@@ -255,8 +256,8 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
255
256
|
setColumnsState(initialColumns);
|
|
256
257
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
257
258
|
}, [filter]);
|
|
258
|
-
|
|
259
|
-
const fetchSitesByLang = async () => await getSitesByLang(
|
|
259
|
+
const params = { language: lang.id, recentSitesNumber: 7 };
|
|
260
|
+
const fetchSitesByLang = async () => await getSitesByLang(params);
|
|
260
261
|
|
|
261
262
|
useEffect(() => {
|
|
262
263
|
if (!locationState || locationState.isFromEditor !== true) {
|
|
@@ -819,7 +820,7 @@ interface IDispatchProps {
|
|
|
819
820
|
restorePage(id: number | number[]): Promise<boolean>;
|
|
820
821
|
getDataPack: (id: string) => Promise<void>;
|
|
821
822
|
resetCurrentSiteErrorPages: () => Promise<void>;
|
|
822
|
-
getSitesByLang(
|
|
823
|
+
getSitesByLang(params: IGetSitesParams): Promise<void>;
|
|
823
824
|
setContentFilters(contentFilters: Record<string, string> | null): void;
|
|
824
825
|
deleteAndRemoveFromSiteBulk(pageIds: number[], globalPageIds: number[]): Promise<boolean>;
|
|
825
826
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { getDefaultTheme } from "@ax/helpers";
|
|
@@ -6,7 +6,7 @@ import { Loading, BrowserContent } from "@ax/components";
|
|
|
6
6
|
import { ILanguage, IRootState, ISocialState } from "@ax/types";
|
|
7
7
|
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
8
8
|
import { findByEditorID } from "@ax/forms";
|
|
9
|
-
import { useURLSearchParam } from "@ax/hooks";
|
|
9
|
+
import { useOnMessageReceivedFromOutside, useURLSearchParam } from "@ax/hooks";
|
|
10
10
|
|
|
11
11
|
import * as S from "./style";
|
|
12
12
|
|
|
@@ -21,40 +21,14 @@ const FramePreview = (props: IProps) => {
|
|
|
21
21
|
globalLangs,
|
|
22
22
|
setSelectedContent,
|
|
23
23
|
setEditorContent,
|
|
24
|
+
deleteModule,
|
|
25
|
+
duplicateModule,
|
|
24
26
|
} = props;
|
|
25
27
|
|
|
26
28
|
const isPreview = useURLSearchParam("preview");
|
|
27
29
|
const isDisabled = useURLSearchParam("disabled");
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
(ev: MessageEvent<{ type: string; message: Record<string, unknown> }>) => {
|
|
31
|
-
if (typeof ev.data !== "object") return;
|
|
32
|
-
if (!ev.data.type) return;
|
|
33
|
-
if (ev.data.type !== "content-update") return;
|
|
34
|
-
if (!ev.data.message) return;
|
|
35
|
-
setEditorContent(ev.data.message);
|
|
36
|
-
},
|
|
37
|
-
[]
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
window.addEventListener("message", onMessageReceivedFromOutside);
|
|
42
|
-
return () => window.removeEventListener("message", onMessageReceivedFromOutside);
|
|
43
|
-
}, [onMessageReceivedFromOutside]);
|
|
44
|
-
|
|
45
|
-
const onMessageReceivedFromPanel = useCallback((ev: MessageEvent<{ type: string; message: string }>) => {
|
|
46
|
-
if (typeof ev.data !== "object") return;
|
|
47
|
-
if (!ev.data.type) return;
|
|
48
|
-
if (ev.data.type !== "selected-content") return;
|
|
49
|
-
if (!ev.data.message) return;
|
|
50
|
-
setSelectedContent(parseInt(ev.data.message));
|
|
51
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
-
}, []);
|
|
53
|
-
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
window.addEventListener("message", onMessageReceivedFromPanel);
|
|
56
|
-
return () => window.removeEventListener("message", onMessageReceivedFromPanel);
|
|
57
|
-
}, [onMessageReceivedFromPanel]);
|
|
31
|
+
useOnMessageReceivedFromOutside(setEditorContent, setSelectedContent);
|
|
58
32
|
|
|
59
33
|
const {
|
|
60
34
|
editorContent: { canonicalSite, language, pageLanguages },
|
|
@@ -77,14 +51,7 @@ const FramePreview = (props: IProps) => {
|
|
|
77
51
|
const isNavigationModule = ["header", "footer"].includes(selectedComponent.type);
|
|
78
52
|
|
|
79
53
|
if (isPreview === "false" && (isDisabled === "false" || isNavigationModule)) {
|
|
80
|
-
window.parent.postMessage(
|
|
81
|
-
{
|
|
82
|
-
type: "module-click",
|
|
83
|
-
message: editorID,
|
|
84
|
-
},
|
|
85
|
-
"*"
|
|
86
|
-
);
|
|
87
|
-
|
|
54
|
+
window.parent.postMessage({ type: "module-click", message: editorID }, "*");
|
|
88
55
|
setSelectedContent && setSelectedContent(editorID);
|
|
89
56
|
}
|
|
90
57
|
};
|
|
@@ -94,6 +61,20 @@ const FramePreview = (props: IProps) => {
|
|
|
94
61
|
const langs = currentSiteInfo ? siteLangs : globalLangs;
|
|
95
62
|
const siteID = currentSiteInfo ? currentSiteInfo.id : canonicalSite;
|
|
96
63
|
|
|
64
|
+
const deleteModuleSelected = (editorID: number) => {
|
|
65
|
+
window.parent.postMessage({ type: "module-delete", message: editorID }, "*");
|
|
66
|
+
setSelectedContent && setSelectedContent(0);
|
|
67
|
+
deleteModule(editorID);
|
|
68
|
+
};
|
|
69
|
+
const duplicateModuleSelected = (editorID: number) => {
|
|
70
|
+
window.parent.postMessage({ type: "module-duplicate", message: editorID }, "*");
|
|
71
|
+
duplicateModule(editorID);
|
|
72
|
+
};
|
|
73
|
+
const moduleActions = {
|
|
74
|
+
deleteModuleAction: deleteModuleSelected,
|
|
75
|
+
duplicateModuleAction: duplicateModuleSelected,
|
|
76
|
+
};
|
|
77
|
+
|
|
97
78
|
if (isLoading) return <Loading />;
|
|
98
79
|
|
|
99
80
|
return (
|
|
@@ -111,6 +92,7 @@ const FramePreview = (props: IProps) => {
|
|
|
111
92
|
footer={currentSiteInfo && footer}
|
|
112
93
|
languageID={language}
|
|
113
94
|
pageLanguages={pageLanguages}
|
|
95
|
+
moduleActions={moduleActions}
|
|
114
96
|
renderer={isPreview === "true" ? "preview" : "editor"}
|
|
115
97
|
/>
|
|
116
98
|
</S.Wrapper>
|
|
@@ -127,6 +109,8 @@ interface IProps {
|
|
|
127
109
|
isLoading: boolean;
|
|
128
110
|
setSelectedContent(editorID: number): void;
|
|
129
111
|
setEditorContent(editorContent: Record<string, unknown>): void;
|
|
112
|
+
deleteModule(editorID: number): void;
|
|
113
|
+
duplicateModule(editorID: number): void;
|
|
130
114
|
}
|
|
131
115
|
|
|
132
116
|
const mapStateToProps = (state: IRootState) => ({
|
|
@@ -142,6 +126,8 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
142
126
|
const mapDispatchToProps = {
|
|
143
127
|
setSelectedContent: pageEditorActions.setSelectedContent,
|
|
144
128
|
setEditorContent: pageEditorActions.setEditorContent,
|
|
129
|
+
deleteModule: pageEditorActions.deleteModule,
|
|
130
|
+
duplicateModule: pageEditorActions.duplicateModule,
|
|
145
131
|
};
|
|
146
132
|
|
|
147
133
|
export default connect(mapStateToProps, mapDispatchToProps)(FramePreview);
|
|
@@ -86,8 +86,8 @@ interface IEditorStateProps {
|
|
|
86
86
|
interface IPageBrowserDispatchProps {
|
|
87
87
|
setSelectedContent(editorID: number): void;
|
|
88
88
|
setSelectedTab(tab: string): void;
|
|
89
|
-
deleteModule(editorID: number, key
|
|
90
|
-
duplicateModule(editorID: number, key
|
|
89
|
+
deleteModule(editorID: number, key?: string): void;
|
|
90
|
+
duplicateModule(editorID: number, key?: string): Promise<number>;
|
|
91
91
|
addComponent: (componentType: any, key: string) => void;
|
|
92
92
|
addModule: (moduleType: string, selectedID: number, key: string) => void;
|
|
93
93
|
moveElement(moduleID: number, selectedContent: any, newIndex: number, key: string): void;
|
|
@@ -18,18 +18,25 @@ const PageBrowser = (props: IProps) => {
|
|
|
18
18
|
isReadOnly,
|
|
19
19
|
isPreview,
|
|
20
20
|
browserRef,
|
|
21
|
+
deleteModule,
|
|
22
|
+
duplicateModule,
|
|
21
23
|
} = props;
|
|
22
24
|
|
|
23
25
|
const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
|
|
24
26
|
const pathWithoutSlash = path ? (path.endsWith("/") ? path.slice(0, -1) : path) : "";
|
|
25
27
|
const url = `${pathWithoutSlash}${slugWithSlash}`;
|
|
26
28
|
|
|
29
|
+
const actions = {
|
|
30
|
+
deleteModuleAction: deleteModule,
|
|
31
|
+
duplicateModuleAction: duplicateModule,
|
|
32
|
+
setSelectedContentAction: setSelectedContent,
|
|
33
|
+
};
|
|
34
|
+
|
|
27
35
|
return (
|
|
28
36
|
<Browser
|
|
29
37
|
isPage={true}
|
|
30
38
|
content={props.content.editorContent}
|
|
31
39
|
socials={socials}
|
|
32
|
-
setSelectedContent={setSelectedContent}
|
|
33
40
|
url={url}
|
|
34
41
|
theme={theme}
|
|
35
42
|
cloudinaryName={cloudinaryName}
|
|
@@ -39,11 +46,12 @@ const PageBrowser = (props: IProps) => {
|
|
|
39
46
|
isPreview={isPreview}
|
|
40
47
|
showIframe={true}
|
|
41
48
|
browserRef={browserRef}
|
|
49
|
+
actions={actions}
|
|
42
50
|
/>
|
|
43
51
|
);
|
|
44
52
|
};
|
|
45
53
|
|
|
46
|
-
interface
|
|
54
|
+
interface IPageBrowserStateProps {
|
|
47
55
|
// TODO: Define content Type
|
|
48
56
|
content: any;
|
|
49
57
|
socials: ISocialState;
|
|
@@ -60,11 +68,13 @@ interface IPageBrowserDispatchProps {
|
|
|
60
68
|
isReadOnly: boolean;
|
|
61
69
|
isPreview?: boolean;
|
|
62
70
|
browserRef?: any;
|
|
71
|
+
deleteModule(editorID: number): void;
|
|
72
|
+
duplicateModule(editorID: number): Promise<number>;
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
type IProps =
|
|
75
|
+
type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
|
|
66
76
|
|
|
67
|
-
const mapStateToProps = (state: IRootState):
|
|
77
|
+
const mapStateToProps = (state: IRootState): IPageBrowserStateProps => ({
|
|
68
78
|
content: { ...state.pageEditor.editorContent },
|
|
69
79
|
socials: state.social,
|
|
70
80
|
cloudinaryName: state.app.globalSettings.cloudinaryName,
|
|
@@ -76,6 +86,8 @@ const mapStateToProps = (state: IRootState): IEditorStateProps => ({
|
|
|
76
86
|
|
|
77
87
|
const mapDispatchToProps = {
|
|
78
88
|
setSelectedContent: pageEditorActions.setSelectedContent,
|
|
89
|
+
deleteModule: pageEditorActions.deleteModule,
|
|
90
|
+
duplicateModule: pageEditorActions.duplicateModule,
|
|
79
91
|
};
|
|
80
92
|
|
|
81
93
|
export default connect(mapStateToProps, mapDispatchToProps)(PageBrowser);
|
|
@@ -10,10 +10,10 @@ const DefaultsBrowser = (props: IProps) => {
|
|
|
10
10
|
socials,
|
|
11
11
|
cloudinaryName,
|
|
12
12
|
content,
|
|
13
|
-
setSelectedContent,
|
|
14
13
|
currentSiteInfo: { theme, id: siteID },
|
|
15
14
|
siteLangs,
|
|
16
15
|
browserRef,
|
|
16
|
+
actions,
|
|
17
17
|
} = props;
|
|
18
18
|
|
|
19
19
|
const updatedContent = { ...content };
|
|
@@ -24,17 +24,22 @@ const DefaultsBrowser = (props: IProps) => {
|
|
|
24
24
|
isPage={false}
|
|
25
25
|
socials={socials}
|
|
26
26
|
content={updatedContent}
|
|
27
|
-
setSelectedContent={setSelectedContent}
|
|
28
27
|
url={content.slug}
|
|
29
28
|
theme={theme}
|
|
30
29
|
cloudinaryName={cloudinaryName}
|
|
31
30
|
siteLangs={siteLangs}
|
|
32
31
|
siteID={siteID}
|
|
32
|
+
actions={actions}
|
|
33
33
|
/>
|
|
34
34
|
);
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
interface
|
|
37
|
+
interface IDefaultsBrowserProps {
|
|
38
|
+
actions: any;
|
|
39
|
+
browserRef?: any;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
interface IDefaultsBrowserStateProps {
|
|
38
43
|
// TODO: Define content Type
|
|
39
44
|
content: any;
|
|
40
45
|
currentSiteInfo: any;
|
|
@@ -43,14 +48,13 @@ interface IEditorStateProps {
|
|
|
43
48
|
siteLangs: ILanguage[];
|
|
44
49
|
}
|
|
45
50
|
|
|
46
|
-
interface
|
|
51
|
+
interface IDefaultsBrowserDispatchProps {
|
|
47
52
|
setSelectedContent(editorID: number): void;
|
|
48
|
-
browserRef?: any;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
type IProps =
|
|
55
|
+
type IProps = IDefaultsBrowserProps & IDefaultsBrowserStateProps & IDefaultsBrowserDispatchProps;
|
|
52
56
|
|
|
53
|
-
const mapStateToProps = (state: IRootState):
|
|
57
|
+
const mapStateToProps = (state: IRootState): IDefaultsBrowserStateProps => ({
|
|
54
58
|
content: { ...state.navigation.editorContent },
|
|
55
59
|
currentSiteInfo: state.sites.currentSiteInfo,
|
|
56
60
|
socials: state.social,
|
|
@@ -33,11 +33,12 @@ const Editor = (props: IProps) => {
|
|
|
33
33
|
replaceModuleAction: replaceModule,
|
|
34
34
|
duplicateModuleAction: duplicateModule,
|
|
35
35
|
replaceElementsInCollectionAction: replaceElementsInCollection,
|
|
36
|
+
setSelectedContentAction: setSelectedContent,
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
return (
|
|
39
40
|
<ResizePanel
|
|
40
|
-
leftPanel={<DefaultsBrowser browserRef={browserRef} />}
|
|
41
|
+
leftPanel={<DefaultsBrowser browserRef={browserRef} actions={actions} />}
|
|
41
42
|
rightPanel={
|
|
42
43
|
<ConfigPanel
|
|
43
44
|
schema={schema}
|
|
@@ -72,8 +73,8 @@ interface IEditorStateProps {
|
|
|
72
73
|
interface IPageBrowserDispatchProps {
|
|
73
74
|
setSelectedContent(editorID: number): void;
|
|
74
75
|
setSelectedTab(tab: string): void;
|
|
75
|
-
deleteModule(editorID: number, key
|
|
76
|
-
duplicateModule(editorID: number, key
|
|
76
|
+
deleteModule(editorID: number, key?: string): void;
|
|
77
|
+
duplicateModule(editorID: number, key?: string): Promise<number>;
|
|
77
78
|
addComponent: (componentType: any, key: string) => void;
|
|
78
79
|
replaceModule(module: any, parent: any, objKey: string): void;
|
|
79
80
|
replaceElementsInCollection(newValue: string, reference: string): void;
|
|
@@ -114,8 +114,8 @@ interface IEditorStateProps {
|
|
|
114
114
|
interface IPageBrowserDispatchProps {
|
|
115
115
|
setSelectedContent(editorID: number): void;
|
|
116
116
|
setSelectedTab(tab: string): void;
|
|
117
|
-
deleteModule(editorID: number, key
|
|
118
|
-
duplicateModule(editorID: number, key
|
|
117
|
+
deleteModule(editorID: number, key?: string): void;
|
|
118
|
+
duplicateModule(editorID: number, key?: string): Promise<number>;
|
|
119
119
|
addComponent: (componentType: any, key: string) => void;
|
|
120
120
|
addModule: (moduleType: string, selectedID: number, key: string) => void;
|
|
121
121
|
moveElement(moduleID: number, selectedContent: any, newIndex: number, key: string): void;
|
|
@@ -21,6 +21,8 @@ const PageBrowser = (props: IProps) => {
|
|
|
21
21
|
isReadOnly,
|
|
22
22
|
isPreview,
|
|
23
23
|
browserRef,
|
|
24
|
+
deleteModule,
|
|
25
|
+
duplicateModule,
|
|
24
26
|
} = props;
|
|
25
27
|
|
|
26
28
|
const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
|
|
@@ -28,6 +30,12 @@ const PageBrowser = (props: IProps) => {
|
|
|
28
30
|
const url = `${pathWithoutSlash}${slugWithSlash}`;
|
|
29
31
|
const disabled = isTemplateActivated === false || isReadOnly;
|
|
30
32
|
|
|
33
|
+
const actions = {
|
|
34
|
+
deleteModuleAction: deleteModule,
|
|
35
|
+
duplicateModuleAction: duplicateModule,
|
|
36
|
+
setSelectedContentAction: setSelectedContent,
|
|
37
|
+
};
|
|
38
|
+
|
|
31
39
|
return (
|
|
32
40
|
<Browser
|
|
33
41
|
isPage={true}
|
|
@@ -35,7 +43,6 @@ const PageBrowser = (props: IProps) => {
|
|
|
35
43
|
header={header}
|
|
36
44
|
footer={footer}
|
|
37
45
|
socials={socials}
|
|
38
|
-
setSelectedContent={setSelectedContent}
|
|
39
46
|
url={url}
|
|
40
47
|
theme={theme}
|
|
41
48
|
cloudinaryName={cloudinaryName}
|
|
@@ -45,11 +52,12 @@ const PageBrowser = (props: IProps) => {
|
|
|
45
52
|
isPreview={isPreview}
|
|
46
53
|
showIframe={true}
|
|
47
54
|
browserRef={browserRef}
|
|
55
|
+
actions={actions}
|
|
48
56
|
/>
|
|
49
57
|
);
|
|
50
58
|
};
|
|
51
59
|
|
|
52
|
-
interface
|
|
60
|
+
interface IPageBrowserStateProps {
|
|
53
61
|
// TODO: Define content Type
|
|
54
62
|
content: any;
|
|
55
63
|
currentSiteInfo: any;
|
|
@@ -66,11 +74,13 @@ interface IPageBrowserDispatchProps {
|
|
|
66
74
|
isReadOnly: boolean;
|
|
67
75
|
isPreview?: boolean;
|
|
68
76
|
browserRef?: any;
|
|
77
|
+
deleteModule(editorID: number): void;
|
|
78
|
+
duplicateModule(editorID: number): Promise<number>;
|
|
69
79
|
}
|
|
70
80
|
|
|
71
|
-
type IProps =
|
|
81
|
+
type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
|
|
72
82
|
|
|
73
|
-
const mapStateToProps = (state: IRootState):
|
|
83
|
+
const mapStateToProps = (state: IRootState): IPageBrowserStateProps => ({
|
|
74
84
|
content: { ...state.pageEditor.editorContent },
|
|
75
85
|
currentSiteInfo: state.sites.currentSiteInfo,
|
|
76
86
|
socials: state.social,
|
|
@@ -82,6 +92,8 @@ const mapStateToProps = (state: IRootState): IEditorStateProps => ({
|
|
|
82
92
|
|
|
83
93
|
const mapDispatchToProps = {
|
|
84
94
|
setSelectedContent: pageEditorActions.setSelectedContent,
|
|
95
|
+
deleteModule: pageEditorActions.deleteModule,
|
|
96
|
+
duplicateModule: pageEditorActions.duplicateModule,
|
|
85
97
|
};
|
|
86
98
|
|
|
87
99
|
export default connect(mapStateToProps, mapDispatchToProps)(PageBrowser);
|
|
@@ -141,13 +141,14 @@ const PageEditor = (props: IProps) => {
|
|
|
141
141
|
status: pageStatus.UPLOAD_PENDING,
|
|
142
142
|
};
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
144
|
+
const handleSavePage = async () => {
|
|
145
|
+
const isSaved = await savePage(false, publishPage);
|
|
146
|
+
if (isSaved) {
|
|
147
|
+
resetDirty();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
pageID ? updatePageStatus([pageID], pageStatus.UPLOAD_PENDING) : await handleSavePage();
|
|
151
152
|
} else {
|
|
152
153
|
setNotification({ text: errorNotificationText, type: "error" });
|
|
153
154
|
}
|
|
@@ -19,8 +19,9 @@ const Field = (props: IField): JSX.Element => {
|
|
|
19
19
|
theme,
|
|
20
20
|
} = props;
|
|
21
21
|
const { isOpen, toggleModal } = useModal();
|
|
22
|
-
const options = defaults.filter(
|
|
23
|
-
component
|
|
22
|
+
const options = defaults.filter(
|
|
23
|
+
(component: any) =>
|
|
24
|
+
component.type === type && content[component.type]?.id !== component.id && !component.setAsDefault
|
|
24
25
|
);
|
|
25
26
|
const optionsType = `${type}s`;
|
|
26
27
|
|
|
@@ -43,9 +44,9 @@ const Field = (props: IField): JSX.Element => {
|
|
|
43
44
|
...(!!dataPackConfigFormData.templates && dataPackConfigFormData.templates[template]),
|
|
44
45
|
...(type === "header" && { defaultHeader: option.id }),
|
|
45
46
|
...(type === "footer" && { defaultFooter: option.id }),
|
|
46
|
-
}
|
|
47
|
+
},
|
|
47
48
|
},
|
|
48
|
-
}
|
|
49
|
+
};
|
|
49
50
|
updateDataPackFormValue(configFormData);
|
|
50
51
|
updateEditorContent(pageEditorID, type, option.id);
|
|
51
52
|
toggleModal();
|
|
@@ -53,18 +54,18 @@ const Field = (props: IField): JSX.Element => {
|
|
|
53
54
|
|
|
54
55
|
const isDefaultNavigation = () => {
|
|
55
56
|
const defaultType = type === "header" ? "defaultHeader" : "defaultFooter";
|
|
56
|
-
const templateNavigation = dataPackConfigFormData.templates && dataPackConfigFormData.templates[template]
|
|
57
|
+
const templateNavigation = dataPackConfigFormData.templates && dataPackConfigFormData.templates[template];
|
|
57
58
|
const templateDefaultNavigation = templateNavigation && templateNavigation[defaultType];
|
|
58
59
|
if (!templateDefaultNavigation) return true;
|
|
59
60
|
const siteDefaultNavigation = defaults.find((navigation: any) => navigation.id === templateDefaultNavigation);
|
|
60
61
|
return !!siteDefaultNavigation?.isDefault;
|
|
61
|
-
}
|
|
62
|
+
};
|
|
62
63
|
|
|
63
64
|
const setDefault = {
|
|
64
65
|
title: `Put the default ${type}`,
|
|
65
66
|
action: () => handleReplace({ id: null }),
|
|
66
67
|
checked: isDefaultNavigation(),
|
|
67
|
-
}
|
|
68
|
+
};
|
|
68
69
|
|
|
69
70
|
const hasOptions: boolean | undefined = options?.length > 0 || !isDefaultNavigation();
|
|
70
71
|
|
|
@@ -90,18 +91,18 @@ const Field = (props: IField): JSX.Element => {
|
|
|
90
91
|
/>
|
|
91
92
|
)}
|
|
92
93
|
</>
|
|
93
|
-
)
|
|
94
|
-
}
|
|
94
|
+
);
|
|
95
|
+
};
|
|
95
96
|
|
|
96
97
|
interface IField {
|
|
97
98
|
type: string;
|
|
98
99
|
template: string;
|
|
99
100
|
defaults: any;
|
|
100
|
-
content: any
|
|
101
|
+
content: any;
|
|
101
102
|
dataPackConfigFormData: any;
|
|
102
103
|
theme: string;
|
|
103
104
|
updateEditorContent: (selectedEditorID: number, key: string, value: any) => void;
|
|
104
105
|
updateDataPackFormValue: (value: any) => void;
|
|
105
106
|
}
|
|
106
107
|
|
|
107
|
-
export { Field }
|
|
108
|
+
export { Field };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
|
|
4
4
|
import { IRootState } from "@ax/types";
|
|
@@ -12,15 +12,7 @@ import Editor from "./Editor";
|
|
|
12
12
|
import * as S from "./style";
|
|
13
13
|
|
|
14
14
|
const TemplateEditor = (props: IProps) => {
|
|
15
|
-
const {
|
|
16
|
-
isLoading,
|
|
17
|
-
isSaving,
|
|
18
|
-
editorContent,
|
|
19
|
-
setHistoryPush,
|
|
20
|
-
template,
|
|
21
|
-
updateDataPack,
|
|
22
|
-
dataPackSelected,
|
|
23
|
-
} = props;
|
|
15
|
+
const { isLoading, isSaving, editorContent, setHistoryPush, template, updateDataPack, dataPackSelected } = props;
|
|
24
16
|
|
|
25
17
|
const { isDirty, setIsDirty } = useIsDirty(editorContent);
|
|
26
18
|
|
|
@@ -46,13 +38,7 @@ const TemplateEditor = (props: IProps) => {
|
|
|
46
38
|
) : (
|
|
47
39
|
<>
|
|
48
40
|
<RouteLeavingGuard when={isDirty} action={goBack} text={leavingGuardText} />
|
|
49
|
-
<MainWrapper
|
|
50
|
-
title={template}
|
|
51
|
-
backLink={true}
|
|
52
|
-
rightButton={rightButtonProps}
|
|
53
|
-
fixedAppBar={true}
|
|
54
|
-
fullWidth={true}
|
|
55
|
-
>
|
|
41
|
+
<MainWrapper title={template} backLink={true} rightButton={rightButtonProps} fixedAppBar={true} fullWidth={true}>
|
|
56
42
|
<ErrorToast size="l" />
|
|
57
43
|
<S.Content>
|
|
58
44
|
<Editor />
|