@griddo/ax 1.66.13 → 1.67.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/package.json +2 -2
- package/src/__tests__/components/Fields/ConditionalField/ConditionalField.test.tsx +95 -0
- package/src/api/pages.tsx +15 -3
- package/src/api/redirects.tsx +4 -2
- package/src/api/sites.tsx +12 -4
- package/src/components/Browser/index.tsx +9 -22
- package/src/components/Browser/style.tsx +1 -6
- package/src/components/ErrorCenter/index.tsx +8 -5
- package/src/components/ErrorCenter/style.tsx +21 -8
- package/src/components/Fields/ComponentArray/MixableComponentArray/AddItemButton/index.tsx +3 -3
- package/src/components/Fields/ComponentArray/MixableComponentArray/index.tsx +60 -25
- package/src/components/Fields/ComponentContainer/index.tsx +21 -7
- package/src/components/Fields/ConditionalField/index.tsx +1 -1
- package/src/components/Fields/LinkField/index.tsx +111 -0
- package/src/components/Fields/ReferenceField/ItemList/index.tsx +4 -0
- package/src/components/Fields/ReferenceField/ManualPanel/index.tsx +12 -2
- package/src/components/Fields/ReferenceField/index.tsx +24 -12
- package/src/components/Fields/ReferenceField/style.tsx +12 -1
- package/src/components/Fields/UrlField/index.tsx +13 -1
- package/src/components/Fields/VisualUniqueSelection/utils.tsx +1 -6
- package/src/components/Fields/index.tsx +2 -0
- package/src/components/FieldsBehavior/index.tsx +14 -1
- package/src/components/Icon/components/Copy.js +14 -0
- package/src/components/Icon/components/Copy2.js +14 -0
- package/src/components/Icon/components/Duplicate.js +3 -5
- package/src/components/Icon/components/Page.js +12 -0
- package/src/components/Icon/svgs/Copy.svg +3 -0
- package/src/components/Icon/svgs/Copy2.svg +3 -0
- package/src/components/Icon/svgs/Duplicate.svg +1 -1
- package/src/components/Icon/svgs/page.svg +3 -0
- package/src/components/MainWrapper/AppBar/index.tsx +21 -10
- package/src/components/MainWrapper/AppBar/style.tsx +11 -3
- package/src/components/MainWrapper/index.tsx +2 -0
- package/src/components/Notification/index.tsx +1 -3
- package/src/components/SearchField/index.tsx +37 -4
- package/src/components/SearchField/style.tsx +23 -10
- package/src/components/index.tsx +2 -0
- package/src/containers/Navigation/Defaults/actions.tsx +2 -0
- package/src/containers/PageEditor/actions.tsx +101 -19
- package/src/containers/PageEditor/utils.tsx +2 -1
- package/src/containers/Sites/actions.tsx +53 -24
- package/src/containers/Sites/constants.tsx +2 -0
- package/src/containers/Sites/interfaces.tsx +12 -5
- package/src/containers/Sites/reducer.tsx +8 -0
- package/src/containers/StructuredData/actions.tsx +5 -8
- package/src/forms/errors.tsx +1 -0
- package/src/forms/index.tsx +13 -1
- package/src/forms/validators.tsx +181 -13
- package/src/helpers/dataPacks.tsx +8 -1
- package/src/helpers/index.tsx +4 -1
- package/src/helpers/objects.tsx +10 -2
- package/src/modules/Categories/CategoriesList/CategoryItem/index.tsx +3 -1
- package/src/modules/Categories/CategoriesList/CategoryPanel/index.tsx +15 -9
- package/src/modules/Categories/CategoriesList/index.tsx +2 -1
- package/src/modules/Content/PageItem/index.tsx +52 -2
- package/src/modules/Content/atoms.tsx +41 -3
- package/src/modules/Content/index.tsx +44 -2
- package/src/modules/Content/style.tsx +8 -1
- package/src/modules/FramePreview/index.tsx +85 -0
- package/src/modules/FramePreview/style.tsx +18 -0
- package/src/modules/GlobalEditor/Editor/index.tsx +3 -1
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +3 -0
- package/src/modules/GlobalEditor/index.tsx +22 -6
- package/src/modules/PageEditor/Editor/index.tsx +5 -1
- package/src/modules/PageEditor/PageBrowser/index.tsx +4 -5
- package/src/modules/PageEditor/index.tsx +40 -12
- package/src/modules/Redirects/index.tsx +40 -10
- package/src/modules/Settings/Globals/index.tsx +1 -1
- package/src/modules/Sites/index.tsx +2 -2
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +1 -1
- package/src/modules/StructuredData/StructuredDataList/index.tsx +19 -2
- package/src/modules/Users/Profile/index.tsx +3 -3
- package/src/routes/multisite.tsx +12 -4
- package/src/routes/site.tsx +1 -1
- package/src/types/index.tsx +13 -4
- package/tsconfig.paths.json +2 -1
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
IGetSitePagesParams,
|
|
16
16
|
IColumn,
|
|
17
17
|
ISite,
|
|
18
|
+
IUser,
|
|
18
19
|
} from "@ax/types";
|
|
19
20
|
import { MainWrapper, Modal, TableList, ErrorToast, Toast, EmptyState, Notification } from "@ax/components";
|
|
20
21
|
import { getFilteredStructuredData, isGlobalStructuredData, isStructuredDataFromPage } from "@ax/helpers";
|
|
@@ -86,6 +87,11 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
86
87
|
restorePage,
|
|
87
88
|
getDataPack,
|
|
88
89
|
dataPacks,
|
|
90
|
+
resetCurrentSiteErrorPages,
|
|
91
|
+
currentSiteErrorPages,
|
|
92
|
+
getSitesByLang,
|
|
93
|
+
sitesByLang,
|
|
94
|
+
user,
|
|
89
95
|
} = props;
|
|
90
96
|
|
|
91
97
|
const itemsPerPage = 50;
|
|
@@ -109,7 +115,9 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
109
115
|
const dataIds = currentDataContent && currentDataContent.map((data: any) => data.id);
|
|
110
116
|
const contentIds = isStructuredData ? dataIds : pagesIds;
|
|
111
117
|
const currentSitePagesTemplatesIds = currentSitePages && currentSitePages.map((page: any) => page.templateId);
|
|
112
|
-
|
|
118
|
+
const currentSitesByLang = sitesByLang?.filter(
|
|
119
|
+
(site) => user?.sites?.includes("all") || user.sites.includes(site.id)
|
|
120
|
+
);
|
|
113
121
|
const categoryColumns =
|
|
114
122
|
currentStructuredData && currentStructuredData.schema
|
|
115
123
|
? currentStructuredData.schema.fields.filter((field: any) => field.showList)
|
|
@@ -171,6 +179,11 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
171
179
|
} = useToast();
|
|
172
180
|
|
|
173
181
|
const { categoryColors, addCategoryColors } = useCategoryColors();
|
|
182
|
+
const {
|
|
183
|
+
isVisible: isVisibleCopiedToast,
|
|
184
|
+
toggleToast: toggleCopiedToast,
|
|
185
|
+
setIsVisible: setIsVisibleCopiedToast,
|
|
186
|
+
} = useToast();
|
|
174
187
|
|
|
175
188
|
const getParams = useCallback(() => {
|
|
176
189
|
const siteID = currentSiteInfo ? currentSiteInfo.id : null;
|
|
@@ -231,11 +244,15 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
231
244
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
232
245
|
}, [filter]);
|
|
233
246
|
|
|
247
|
+
const fetchSitesByLang = async () => await getSitesByLang(lang.id);
|
|
248
|
+
|
|
234
249
|
useEffect(() => {
|
|
235
250
|
if (!locationState || locationState.isFromEditor !== true) {
|
|
236
251
|
setFilter("unique-pages");
|
|
237
252
|
}
|
|
238
253
|
resetPageEditor();
|
|
254
|
+
resetCurrentSiteErrorPages();
|
|
255
|
+
fetchSitesByLang();
|
|
239
256
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
240
257
|
}, []);
|
|
241
258
|
|
|
@@ -533,6 +550,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
533
550
|
deleteBulk: deleteCurrentPageBulk,
|
|
534
551
|
getDataPack: getDataPack,
|
|
535
552
|
setTemplateInstanceError,
|
|
553
|
+
toggleCopiedToast,
|
|
536
554
|
};
|
|
537
555
|
|
|
538
556
|
return (
|
|
@@ -540,6 +558,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
540
558
|
item={item}
|
|
541
559
|
key={pageItem.id}
|
|
542
560
|
functions={pageItemFunctions}
|
|
561
|
+
sites={currentSitesByLang}
|
|
543
562
|
activatedTemplates={activatedTemplates}
|
|
544
563
|
toggleToast={toggleRemovedToast}
|
|
545
564
|
setRemovedPage={setRemovedPage}
|
|
@@ -650,8 +669,18 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
650
669
|
message: "Page deleted.",
|
|
651
670
|
};
|
|
652
671
|
|
|
672
|
+
const copiedToastProps = {
|
|
673
|
+
setIsVisible: setIsVisibleCopiedToast,
|
|
674
|
+
message: "1 Page copied to another Site",
|
|
675
|
+
};
|
|
676
|
+
|
|
653
677
|
const addNewAction = filter === "unique-pages" || isGlobalPages ? toggleNewModal : addNewData;
|
|
654
678
|
|
|
679
|
+
const errorPagesText =
|
|
680
|
+
currentSiteErrorPages.length > 1
|
|
681
|
+
? "These pages contains some errors, so you can not publish them yet. Please, review the errors on the pages."
|
|
682
|
+
: "This page contains some errors, so you can not publish it yet. Please, review the errors on the page.";
|
|
683
|
+
|
|
655
684
|
return (
|
|
656
685
|
<MainWrapper
|
|
657
686
|
title={title}
|
|
@@ -671,6 +700,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
671
700
|
text={`There can be only one ${templateInstanceError.templateName} page and you already have it.`}
|
|
672
701
|
/>
|
|
673
702
|
)}
|
|
703
|
+
{!!currentSiteErrorPages.length && <Notification type="error" text={errorPagesText} />}
|
|
674
704
|
<TableList
|
|
675
705
|
tableHeader={Header}
|
|
676
706
|
pagination={pagination}
|
|
@@ -720,6 +750,7 @@ const Content = (props: IProps): JSX.Element => {
|
|
|
720
750
|
{isVisible && <Toast {...toastProps} />}
|
|
721
751
|
{isVisibleRemovedToast && <Toast {...removedToastProps} />}
|
|
722
752
|
{isVisibleDeletedToast && <Toast {...deletedToastProps} />}
|
|
753
|
+
{isVisibleCopiedToast && <Toast {...copiedToastProps} />}
|
|
723
754
|
</MainWrapper>
|
|
724
755
|
);
|
|
725
756
|
};
|
|
@@ -741,6 +772,9 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
741
772
|
activatedTemplates: state.dataPacks.templates,
|
|
742
773
|
isLoading: state.app.isLoading,
|
|
743
774
|
dataPacks: state.dataPacks.activated,
|
|
775
|
+
currentSiteErrorPages: state.sites.currentSiteErrorPages,
|
|
776
|
+
sitesByLang: state.sites.sitesByLang,
|
|
777
|
+
user: state.users.currentUser,
|
|
744
778
|
});
|
|
745
779
|
|
|
746
780
|
interface IDispatchProps {
|
|
@@ -760,7 +794,7 @@ interface IDispatchProps {
|
|
|
760
794
|
getStructuredDataContents(params: any, siteID: number): Promise<void>;
|
|
761
795
|
resetForm(): void;
|
|
762
796
|
deleteBulk(ids: any): Promise<boolean>;
|
|
763
|
-
duplicatePage(pageID: number, data
|
|
797
|
+
duplicatePage(pageID: number, data?: any, siteID?: number): Promise<boolean>;
|
|
764
798
|
deleteDataContent(dataID: number[]): Promise<boolean>;
|
|
765
799
|
restoreDataContent(catID: number | number[]): void;
|
|
766
800
|
setFilter(value: string): void;
|
|
@@ -770,6 +804,8 @@ interface IDispatchProps {
|
|
|
770
804
|
importPageFromGlobal(pageID: number | number[]): Promise<boolean>;
|
|
771
805
|
restorePage(id: number | number[]): Promise<boolean>;
|
|
772
806
|
getDataPack: (id: string) => Promise<void>;
|
|
807
|
+
resetCurrentSiteErrorPages: () => Promise<void>;
|
|
808
|
+
getSitesByLang(language: number): Promise<void>;
|
|
773
809
|
}
|
|
774
810
|
|
|
775
811
|
const mapDispatchToProps = {
|
|
@@ -798,6 +834,8 @@ const mapDispatchToProps = {
|
|
|
798
834
|
importPageFromGlobal: sitesActions.importPageFromGlobal,
|
|
799
835
|
restorePage: pageEditorActions.restorePage,
|
|
800
836
|
getDataPack: dataPacksActions.getSiteDataPack,
|
|
837
|
+
resetCurrentSiteErrorPages: sitesActions.resetCurrentSiteErrorPages,
|
|
838
|
+
getSitesByLang: sitesActions.getSitesByLang,
|
|
801
839
|
};
|
|
802
840
|
|
|
803
841
|
interface IPagesProps {
|
|
@@ -819,6 +857,10 @@ interface IPagesProps {
|
|
|
819
857
|
activatedTemplates: any[];
|
|
820
858
|
isLoading: boolean;
|
|
821
859
|
dataPacks: IDataPack[];
|
|
860
|
+
currentSiteErrorPages: number[];
|
|
861
|
+
sites: ISite[];
|
|
862
|
+
sitesByLang: ISite[];
|
|
863
|
+
user: IUser;
|
|
822
864
|
}
|
|
823
865
|
|
|
824
866
|
type IProps = IPagesProps & IDispatchProps;
|
|
@@ -35,4 +35,11 @@ const ModalContent = styled.div`
|
|
|
35
35
|
}
|
|
36
36
|
`;
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
const SelectWrapper = styled.div`
|
|
39
|
+
& .react-select__control,
|
|
40
|
+
.react-select__menu {
|
|
41
|
+
min-width: 100%;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
export { ContentListWrapper, TableWrapper, PaginationWrapper, EmptyWrapper, ModalContent, SelectWrapper };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { connect } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import * as components from "components";
|
|
5
|
+
import { SiteProvider } from "components";
|
|
6
|
+
import { Preview } from "@griddo/core";
|
|
7
|
+
import { getDefaultTheme } from "@ax/helpers";
|
|
8
|
+
import { Loading } from "@ax/components";
|
|
9
|
+
import { ILanguage, IRootState, ISocialState } from "@ax/types";
|
|
10
|
+
|
|
11
|
+
import * as S from "./style";
|
|
12
|
+
|
|
13
|
+
const FramePreview = (props: IProps) => {
|
|
14
|
+
const { content, socials, selectedEditorID, cloudinaryName, isLoading, currentSiteInfo, siteLangs, globalLangs } =
|
|
15
|
+
props;
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
editorContent: { canonicalSite, language, pageLanguages },
|
|
19
|
+
header,
|
|
20
|
+
footer,
|
|
21
|
+
} = content;
|
|
22
|
+
|
|
23
|
+
document.body.classList.add("preview");
|
|
24
|
+
|
|
25
|
+
const API_URL = process.env.REACT_APP_API_ENDPOINT;
|
|
26
|
+
const PUBLIC_API_URL = process.env.REACT_APP_PUBLIC_API_ENDPOINT;
|
|
27
|
+
|
|
28
|
+
const globalTheme = getDefaultTheme();
|
|
29
|
+
const theme = currentSiteInfo ? currentSiteInfo.theme : globalTheme;
|
|
30
|
+
const langs = currentSiteInfo ? siteLangs : globalLangs;
|
|
31
|
+
const siteID = currentSiteInfo ? currentSiteInfo.id : canonicalSite;
|
|
32
|
+
|
|
33
|
+
if (isLoading) return <Loading />;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<SiteProvider
|
|
37
|
+
cloudinaryCloudName={cloudinaryName}
|
|
38
|
+
theme={theme}
|
|
39
|
+
socials={socials}
|
|
40
|
+
siteLangs={langs}
|
|
41
|
+
selectEditorID={selectedEditorID}
|
|
42
|
+
renderer="editor"
|
|
43
|
+
apiUrl={API_URL}
|
|
44
|
+
publicApiUrl={PUBLIC_API_URL}
|
|
45
|
+
siteId={siteID}
|
|
46
|
+
>
|
|
47
|
+
<S.Wrapper ref={(ref: any) => ((window as any).browserRef = ref)}>
|
|
48
|
+
<Preview
|
|
49
|
+
isPage={true}
|
|
50
|
+
apiUrl={API_URL}
|
|
51
|
+
library={components}
|
|
52
|
+
content={content.editorContent}
|
|
53
|
+
header={currentSiteInfo && header}
|
|
54
|
+
footer={currentSiteInfo && footer}
|
|
55
|
+
languageId={language}
|
|
56
|
+
pageLanguages={pageLanguages}
|
|
57
|
+
/>
|
|
58
|
+
</S.Wrapper>
|
|
59
|
+
</SiteProvider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
interface IProps {
|
|
64
|
+
content: any;
|
|
65
|
+
selectedEditorID: number;
|
|
66
|
+
socials: ISocialState;
|
|
67
|
+
cloudinaryName: string | null;
|
|
68
|
+
currentSiteInfo: any;
|
|
69
|
+
siteLangs: ILanguage[];
|
|
70
|
+
globalLangs: ILanguage[];
|
|
71
|
+
isLoading: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const mapStateToProps = (state: IRootState) => ({
|
|
75
|
+
content: { ...state.pageEditor.editorContent },
|
|
76
|
+
selectedEditorID: state.pageEditor.selectedEditorID as number,
|
|
77
|
+
socials: state.social,
|
|
78
|
+
cloudinaryName: state.app.globalSettings.cloudinaryName,
|
|
79
|
+
currentSiteInfo: state.sites.currentSiteInfo,
|
|
80
|
+
siteLangs: state.sites.currentSiteLanguages,
|
|
81
|
+
globalLangs: state.app.globalLangs,
|
|
82
|
+
isLoading: state.app.isLoading,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
export default connect(mapStateToProps)(FramePreview);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div`
|
|
4
|
+
overflow: auto;
|
|
5
|
+
scroll-behavior: smooth;
|
|
6
|
+
height: 100%;
|
|
7
|
+
position: relative;
|
|
8
|
+
|
|
9
|
+
.headroom {
|
|
10
|
+
position: relative !important;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
body.preview:not(&) {
|
|
14
|
+
min-width: 0 !important;
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
export { Wrapper };
|
|
@@ -29,6 +29,7 @@ const Editor = (props: IProps) => {
|
|
|
29
29
|
copyModule,
|
|
30
30
|
pasteModule,
|
|
31
31
|
theme,
|
|
32
|
+
browserRef,
|
|
32
33
|
setNotification,
|
|
33
34
|
} = props;
|
|
34
35
|
|
|
@@ -47,7 +48,7 @@ const Editor = (props: IProps) => {
|
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
50
|
<ResizePanel
|
|
50
|
-
leftPanel={<PageBrowser isReadOnly={isReadOnly} theme={theme} />}
|
|
51
|
+
leftPanel={<PageBrowser isReadOnly={isReadOnly} theme={theme} browserRef={browserRef} />}
|
|
51
52
|
rightPanel={
|
|
52
53
|
<ConfigPanel
|
|
53
54
|
schema={schema}
|
|
@@ -99,6 +100,7 @@ interface IPageBrowserDispatchProps {
|
|
|
99
100
|
isEditable: boolean;
|
|
100
101
|
isReadOnly: boolean;
|
|
101
102
|
theme: string;
|
|
103
|
+
browserRef: any;
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -18,6 +18,7 @@ const PageBrowser = (props: IProps) => {
|
|
|
18
18
|
theme,
|
|
19
19
|
isReadOnly,
|
|
20
20
|
isPreview,
|
|
21
|
+
browserRef,
|
|
21
22
|
} = props;
|
|
22
23
|
|
|
23
24
|
const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
|
|
@@ -38,6 +39,7 @@ const PageBrowser = (props: IProps) => {
|
|
|
38
39
|
disabled={isReadOnly}
|
|
39
40
|
siteID={canonicalSite}
|
|
40
41
|
isPreview={isPreview}
|
|
42
|
+
browserRef={browserRef}
|
|
41
43
|
/>
|
|
42
44
|
);
|
|
43
45
|
};
|
|
@@ -60,6 +62,7 @@ interface IPageBrowserDispatchProps {
|
|
|
60
62
|
theme: string;
|
|
61
63
|
isReadOnly: boolean;
|
|
62
64
|
isPreview?: boolean;
|
|
65
|
+
browserRef?: any;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useState, useRef } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
import { RouteComponentProps } from "react-router-dom";
|
|
4
4
|
|
|
@@ -42,6 +42,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
42
42
|
savedSiteInfo,
|
|
43
43
|
userEditing,
|
|
44
44
|
isNewTranslation,
|
|
45
|
+
currentSiteErrorPages,
|
|
45
46
|
} = props;
|
|
46
47
|
|
|
47
48
|
const { isOpen, toggleModal } = useModal();
|
|
@@ -50,6 +51,8 @@ const GlobalEditor = (props: IProps) => {
|
|
|
50
51
|
const [selectedTab, setSelectedTab] = useState("edit");
|
|
51
52
|
const [notification, setNotification] = useState<INotification | null>(null);
|
|
52
53
|
const { isDirty, setIsDirty, resetDirty } = useIsDirty(editorContent.editorContent, isNewTranslation);
|
|
54
|
+
const [errorPagesChecked, setErrorPagesChecked] = useState(false);
|
|
55
|
+
const browserRef = useRef<HTMLDivElement>(null);
|
|
53
56
|
|
|
54
57
|
const isPublished = props.pageStatus === pageStatus.PUBLISHED || props.pageStatus === pageStatus.UPLOAD_PENDING;
|
|
55
58
|
const isDraft = props.pageStatus === pageStatus.MODIFIED;
|
|
@@ -98,6 +101,16 @@ const GlobalEditor = (props: IProps) => {
|
|
|
98
101
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
99
102
|
}, [userEditing]);
|
|
100
103
|
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (!errorPagesChecked && !isLoading && editorContent.editorContent) {
|
|
106
|
+
const pageId = editorContent.editorContent.id;
|
|
107
|
+
const hasErrors = currentSiteErrorPages.some((errorPageId) => pageId === errorPageId);
|
|
108
|
+
hasErrors && reviewPage();
|
|
109
|
+
setErrorPagesChecked(true);
|
|
110
|
+
}
|
|
111
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
112
|
+
}, [editorContent]);
|
|
113
|
+
|
|
101
114
|
const setRoute = (path: string) => props.setHistoryPush(path, true);
|
|
102
115
|
|
|
103
116
|
const removePage = async () => {
|
|
@@ -114,7 +127,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
114
127
|
const publishPage = async () => {
|
|
115
128
|
const { updatePageStatus, savePage, pageID, validatePage } = props;
|
|
116
129
|
|
|
117
|
-
const validated = await validatePage(true);
|
|
130
|
+
const validated = await validatePage(true, browserRef);
|
|
118
131
|
|
|
119
132
|
if (validated) {
|
|
120
133
|
const publishPage = {
|
|
@@ -134,7 +147,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
134
147
|
const publishChanges = async () => {
|
|
135
148
|
const { savePage, validatePage } = props;
|
|
136
149
|
|
|
137
|
-
const validated = await validatePage(true);
|
|
150
|
+
const validated = await validatePage(true, browserRef);
|
|
138
151
|
|
|
139
152
|
if (validated) {
|
|
140
153
|
const publishPage = {
|
|
@@ -163,13 +176,13 @@ const GlobalEditor = (props: IProps) => {
|
|
|
163
176
|
|
|
164
177
|
const reviewPage = () => {
|
|
165
178
|
const { validatePage } = props;
|
|
166
|
-
validatePage();
|
|
179
|
+
validatePage(undefined, browserRef);
|
|
167
180
|
};
|
|
168
181
|
|
|
169
182
|
const handlePublishDraft = async () => {
|
|
170
183
|
const { savePage, validatePage } = props;
|
|
171
184
|
|
|
172
|
-
const validated = await validatePage(true);
|
|
185
|
+
const validated = await validatePage(true, browserRef);
|
|
173
186
|
|
|
174
187
|
if (validated) {
|
|
175
188
|
const isSaved = await savePage(false, null, true);
|
|
@@ -462,6 +475,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
462
475
|
isEditable={isEditable}
|
|
463
476
|
isReadOnly={isReadOnly}
|
|
464
477
|
theme={theme}
|
|
478
|
+
browserRef={browserRef}
|
|
465
479
|
setNotification={setNotification}
|
|
466
480
|
/>
|
|
467
481
|
</S.Content>
|
|
@@ -524,6 +538,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
|
|
|
524
538
|
userEditing: state.pageEditor.userEditing,
|
|
525
539
|
currentUserID: state.users.currentUser.id,
|
|
526
540
|
isNewTranslation: state.pageEditor.isNewTranslation,
|
|
541
|
+
currentSiteErrorPages: state.sites.currentSiteErrorPages,
|
|
527
542
|
});
|
|
528
543
|
|
|
529
544
|
interface IPageEditorStateProps {
|
|
@@ -543,6 +558,7 @@ interface IPageEditorStateProps {
|
|
|
543
558
|
userEditing: IUserEditing | null;
|
|
544
559
|
currentUserID: number | null;
|
|
545
560
|
isNewTranslation: boolean;
|
|
561
|
+
currentSiteErrorPages: number[];
|
|
546
562
|
}
|
|
547
563
|
|
|
548
564
|
const mapDispatchToProps = {
|
|
@@ -567,7 +583,7 @@ interface IPageEditorDispatchProps {
|
|
|
567
583
|
getPage(pageID?: number, global?: boolean): Promise<void>;
|
|
568
584
|
savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
|
|
569
585
|
deletePage(params?: ISavePageParams): Promise<boolean>;
|
|
570
|
-
validatePage(publish?: boolean): Promise<boolean>;
|
|
586
|
+
validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
|
|
571
587
|
updatePageStatus(id: number[], status: string): Promise<boolean>;
|
|
572
588
|
setHistoryPush(path: string, isEditor: boolean): void;
|
|
573
589
|
setLanguage?(lang: { locale: string; id: number | null }): void;
|
|
@@ -35,6 +35,7 @@ const Editor = (props: IProps) => {
|
|
|
35
35
|
isReadOnly,
|
|
36
36
|
userEditing,
|
|
37
37
|
site,
|
|
38
|
+
browserRef,
|
|
38
39
|
lastElementAddedId,
|
|
39
40
|
copyModule,
|
|
40
41
|
pasteModule,
|
|
@@ -58,7 +59,9 @@ const Editor = (props: IProps) => {
|
|
|
58
59
|
|
|
59
60
|
return (
|
|
60
61
|
<ResizePanel
|
|
61
|
-
leftPanel={
|
|
62
|
+
leftPanel={
|
|
63
|
+
<PageBrowser isTemplateActivated={isTemplateActivated} isReadOnly={isReadOnly} browserRef={browserRef} />
|
|
64
|
+
}
|
|
62
65
|
rightPanel={
|
|
63
66
|
<ConfigPanel
|
|
64
67
|
schema={schema}
|
|
@@ -119,6 +122,7 @@ interface IPageBrowserDispatchProps {
|
|
|
119
122
|
isEditable: boolean;
|
|
120
123
|
pageTitle: string;
|
|
121
124
|
isReadOnly: boolean;
|
|
125
|
+
browserRef: any;
|
|
122
126
|
}
|
|
123
127
|
|
|
124
128
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -3,7 +3,7 @@ import { connect } from "react-redux";
|
|
|
3
3
|
import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
4
4
|
|
|
5
5
|
import { Browser } from "@ax/components";
|
|
6
|
-
import {
|
|
6
|
+
import { ILanguage, IRootState, ISocialState } from "@ax/types";
|
|
7
7
|
|
|
8
8
|
const PageBrowser = (props: IProps) => {
|
|
9
9
|
const {
|
|
@@ -21,6 +21,7 @@ const PageBrowser = (props: IProps) => {
|
|
|
21
21
|
isTemplateActivated,
|
|
22
22
|
isReadOnly,
|
|
23
23
|
isPreview,
|
|
24
|
+
browserRef,
|
|
24
25
|
} = props;
|
|
25
26
|
|
|
26
27
|
const slugWithSlash = slug ? (slug.startsWith("/") ? slug : `/${slug}`) : "";
|
|
@@ -44,6 +45,7 @@ const PageBrowser = (props: IProps) => {
|
|
|
44
45
|
disabled={disabled}
|
|
45
46
|
siteID={siteID}
|
|
46
47
|
isPreview={isPreview}
|
|
48
|
+
browserRef={browserRef}
|
|
47
49
|
/>
|
|
48
50
|
);
|
|
49
51
|
};
|
|
@@ -56,8 +58,6 @@ interface IEditorStateProps {
|
|
|
56
58
|
socials: ISocialState;
|
|
57
59
|
cloudinaryName: string | null;
|
|
58
60
|
siteLangs: ILanguage[];
|
|
59
|
-
schema: ISchema | Record<string, unknown>;
|
|
60
|
-
breadcrumb: IBreadcrumbItem[];
|
|
61
61
|
selectedParent: any;
|
|
62
62
|
activatedModules: string[];
|
|
63
63
|
}
|
|
@@ -67,6 +67,7 @@ interface IPageBrowserDispatchProps {
|
|
|
67
67
|
isTemplateActivated: boolean;
|
|
68
68
|
isReadOnly: boolean;
|
|
69
69
|
isPreview?: boolean;
|
|
70
|
+
browserRef?: any;
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -78,8 +79,6 @@ const mapStateToProps = (state: IRootState): IEditorStateProps => ({
|
|
|
78
79
|
socials: state.social,
|
|
79
80
|
cloudinaryName: state.app.globalSettings.cloudinaryName,
|
|
80
81
|
siteLangs: state.sites.currentSiteLanguages,
|
|
81
|
-
schema: state.pageEditor.schema,
|
|
82
|
-
breadcrumb: state.pageEditor.breadcrumb,
|
|
83
82
|
selectedParent: state.pageEditor.selectedParent,
|
|
84
83
|
activatedModules: state.dataPacks.modules,
|
|
85
84
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useState, useRef } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
3
|
import { RouteComponentProps } from "react-router-dom";
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ import { navigationActions } from "@ax/containers/Navigation";
|
|
|
10
10
|
import { pageStatus } from "@ax/containers/PageEditor/interfaces";
|
|
11
11
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
12
12
|
import { useIsDirty, useModal } from "@ax/hooks";
|
|
13
|
-
import { isModuleDisabled } from "@ax/helpers";
|
|
13
|
+
import { isModuleDisabled, getDeactivatedModules } from "@ax/helpers";
|
|
14
14
|
import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
|
|
15
15
|
import { DeleteModal } from "./atoms";
|
|
16
16
|
import Editor from "./Editor";
|
|
@@ -44,6 +44,7 @@ const PageEditor = (props: IProps) => {
|
|
|
44
44
|
pageEditor: { editorContent, schema },
|
|
45
45
|
userEditing,
|
|
46
46
|
isNewTranslation,
|
|
47
|
+
currentSiteErrorPages,
|
|
47
48
|
} = props;
|
|
48
49
|
|
|
49
50
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
@@ -54,6 +55,8 @@ const PageEditor = (props: IProps) => {
|
|
|
54
55
|
const { isOpen, toggleModal } = useModal();
|
|
55
56
|
const { isOpen: isUnpublishOpen, toggleModal: toggleUnpublishModal } = useModal();
|
|
56
57
|
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
58
|
+
const [errorPagesChecked, setErrorPagesChecked] = useState(false);
|
|
59
|
+
const browserRef = useRef<HTMLDivElement>(null);
|
|
57
60
|
|
|
58
61
|
const isGlobal = editorContent.editorContent && editorContent.editorContent.origin === "GLOBAL";
|
|
59
62
|
const isEditable = editorContent.editorContent && editorContent.editorContent.editable;
|
|
@@ -101,6 +104,16 @@ const PageEditor = (props: IProps) => {
|
|
|
101
104
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
102
105
|
}, [lang]);
|
|
103
106
|
|
|
107
|
+
useEffect(() => {
|
|
108
|
+
if (!errorPagesChecked && !isLoading && editorContent.editorContent) {
|
|
109
|
+
const pageId = editorContent.editorContent.id;
|
|
110
|
+
const hasErrors = currentSiteErrorPages.some((errorPageId) => pageId === errorPageId);
|
|
111
|
+
hasErrors && reviewPage();
|
|
112
|
+
setErrorPagesChecked(true);
|
|
113
|
+
}
|
|
114
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
115
|
+
}, [editorContent]);
|
|
116
|
+
|
|
104
117
|
const setRoute = (path: string) => props.setHistoryPush(path, true);
|
|
105
118
|
|
|
106
119
|
const removePage = async () => {
|
|
@@ -118,7 +131,7 @@ const PageEditor = (props: IProps) => {
|
|
|
118
131
|
const publishPage = async () => {
|
|
119
132
|
const { updatePageStatus, savePage, pageID, validatePage } = props;
|
|
120
133
|
|
|
121
|
-
const validated = await validatePage(true);
|
|
134
|
+
const validated = await validatePage(true, browserRef);
|
|
122
135
|
|
|
123
136
|
if (validated) {
|
|
124
137
|
const publishPage = {
|
|
@@ -138,7 +151,7 @@ const PageEditor = (props: IProps) => {
|
|
|
138
151
|
const publishChanges = async () => {
|
|
139
152
|
const { savePage, validatePage } = props;
|
|
140
153
|
|
|
141
|
-
const validated = await validatePage(true);
|
|
154
|
+
const validated = await validatePage(true, browserRef);
|
|
142
155
|
|
|
143
156
|
if (validated) {
|
|
144
157
|
const publishPage = {
|
|
@@ -167,13 +180,13 @@ const PageEditor = (props: IProps) => {
|
|
|
167
180
|
|
|
168
181
|
const reviewPage = () => {
|
|
169
182
|
const { validatePage } = props;
|
|
170
|
-
validatePage();
|
|
183
|
+
validatePage(false, browserRef);
|
|
171
184
|
};
|
|
172
185
|
|
|
173
186
|
const handlePublishDraft = async () => {
|
|
174
187
|
const { savePage, validatePage } = props;
|
|
175
188
|
|
|
176
|
-
const validated = await validatePage(true);
|
|
189
|
+
const validated = await validatePage(true, browserRef);
|
|
177
190
|
|
|
178
191
|
if (validated) {
|
|
179
192
|
const isSaved = await savePage(false, null, true);
|
|
@@ -295,10 +308,12 @@ const PageEditor = (props: IProps) => {
|
|
|
295
308
|
|
|
296
309
|
const goToPages = (path: string) => setRoute(path);
|
|
297
310
|
|
|
298
|
-
const goToError = (editorID: number, tab: string, template: boolean) => {
|
|
311
|
+
const goToError = (editorID: number | null, tab: string, template: boolean) => {
|
|
299
312
|
const realEditorID = template ? 0 : editorID;
|
|
300
|
-
|
|
301
|
-
|
|
313
|
+
if (realEditorID !== null) {
|
|
314
|
+
setSelectedContent(realEditorID);
|
|
315
|
+
setTab(tab);
|
|
316
|
+
}
|
|
302
317
|
};
|
|
303
318
|
|
|
304
319
|
const modalText = (
|
|
@@ -309,9 +324,18 @@ const PageEditor = (props: IProps) => {
|
|
|
309
324
|
|
|
310
325
|
let isTemplateActivated = true;
|
|
311
326
|
let hasDeactivatedModules = false;
|
|
327
|
+
let deactivatedModules: string[] = [];
|
|
312
328
|
if (editorContent.editorContent && editorContent.editorContent.template) {
|
|
313
329
|
const editorTemplate = editorContent.editorContent.template;
|
|
314
|
-
|
|
330
|
+
const mainContentModules = editorTemplate?.mainContent?.modules;
|
|
331
|
+
|
|
332
|
+
if (mainContentModules) {
|
|
333
|
+
deactivatedModules = getDeactivatedModules(activatedModules, mainContentModules);
|
|
334
|
+
hasDeactivatedModules = deactivatedModules.length > 0;
|
|
335
|
+
} else {
|
|
336
|
+
hasDeactivatedModules = isModuleDisabled(selectedComponent, schema.schemaType, activatedModules);
|
|
337
|
+
}
|
|
338
|
+
|
|
315
339
|
isTemplateActivated = activatedTemplates.find((temp: any) => temp.id === editorTemplate.templateType)
|
|
316
340
|
? true
|
|
317
341
|
: false;
|
|
@@ -395,7 +419,8 @@ const PageEditor = (props: IProps) => {
|
|
|
395
419
|
if (!isTemplateActivated) {
|
|
396
420
|
getSiteDataPackbyTemplate(editorTemplate.templateType);
|
|
397
421
|
} else if (hasDeactivatedModules) {
|
|
398
|
-
|
|
422
|
+
const currentModule = deactivatedModules.length === 1 ? deactivatedModules[0] : selectedComponent;
|
|
423
|
+
getSiteDataPackbyModule(currentModule);
|
|
399
424
|
}
|
|
400
425
|
setHistoryPush("/sites/settings/content-types", false);
|
|
401
426
|
}
|
|
@@ -506,6 +531,7 @@ const PageEditor = (props: IProps) => {
|
|
|
506
531
|
isEditable={isEditable}
|
|
507
532
|
pageTitle={pageName}
|
|
508
533
|
isReadOnly={isReadOnly}
|
|
534
|
+
browserRef={browserRef}
|
|
509
535
|
setNotification={setNotification}
|
|
510
536
|
/>
|
|
511
537
|
</S.Content>
|
|
@@ -576,6 +602,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
|
|
|
576
602
|
userEditing: state.pageEditor.userEditing,
|
|
577
603
|
currentUserID: state.users.currentUser.id,
|
|
578
604
|
isNewTranslation: state.pageEditor.isNewTranslation,
|
|
605
|
+
currentSiteErrorPages: state.sites.currentSiteErrorPages,
|
|
579
606
|
});
|
|
580
607
|
|
|
581
608
|
interface IPageEditorStateProps {
|
|
@@ -596,6 +623,7 @@ interface IPageEditorStateProps {
|
|
|
596
623
|
userEditing: IUserEditing | null;
|
|
597
624
|
currentUserID: number | null;
|
|
598
625
|
isNewTranslation: boolean;
|
|
626
|
+
currentSiteErrorPages: number[];
|
|
599
627
|
}
|
|
600
628
|
|
|
601
629
|
const mapDispatchToProps = {
|
|
@@ -622,7 +650,7 @@ interface IPageEditorDispatchProps {
|
|
|
622
650
|
getPage(pageID?: number): Promise<void>;
|
|
623
651
|
savePage(createDraft: boolean, publishPage?: any, publishDraft?: boolean): Promise<boolean>;
|
|
624
652
|
deletePage(params?: ISavePageParams): Promise<boolean>;
|
|
625
|
-
validatePage(publish?: boolean): Promise<boolean>;
|
|
653
|
+
validatePage(publish?: boolean, browserRef?: any): Promise<boolean>;
|
|
626
654
|
updatePageStatus(id: number[], status: string): Promise<boolean>;
|
|
627
655
|
setHistoryPush(path: string, isEditor: boolean): void;
|
|
628
656
|
setLanguage?(lang: { locale: string; id: number | null }): void;
|