@griddo/ax 11.15.9 → 11.16.0-rc.0
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/RestrictionsModal/CurrentAccessList/CurrentAccessList.test.tsx +173 -0
- package/src/__tests__/components/RestrictionsModal/OptionsStep/OptionsStep.test.tsx +160 -0
- package/src/__tests__/components/RestrictionsModal/RestrictionsModal.test.tsx +134 -0
- package/src/__tests__/components/RestrictionsModal/RolesList/RolesList.test.tsx +234 -0
- package/src/__tests__/components/RestrictionsModal/UsersList/UsersList.test.tsx +288 -0
- package/src/__tests__/hooks/users.test.tsx +382 -0
- package/src/api/pages.tsx +24 -1
- package/src/api/sites.tsx +14 -14
- package/src/api/structuredData.tsx +17 -7
- package/src/components/Browser/index.tsx +12 -0
- package/src/components/Browser/style.tsx +5 -1
- package/src/components/ConfigPanel/Form/index.tsx +11 -10
- package/src/components/ContentItem/index.tsx +31 -0
- package/src/components/ContentItem/style.tsx +43 -0
- package/src/components/Fields/ImageField/index.tsx +2 -1
- package/src/components/Fields/RadioField/index.tsx +3 -3
- package/src/components/Fields/RadioField/style.tsx +1 -1
- package/src/components/FloatingNote/index.tsx +12 -1
- package/src/components/FloatingNote/style.tsx +2 -1
- package/src/components/Modal/style.tsx +11 -0
- package/src/components/PageFinder/SelectionListItem/index.tsx +27 -17
- package/src/components/PageFinder/index.tsx +65 -28
- package/src/components/PageFinder/style.tsx +0 -1
- package/src/components/RestrictionsModal/CurrentAccessList/index.tsx +74 -0
- package/src/components/RestrictionsModal/CurrentAccessList/style.tsx +155 -0
- package/src/components/RestrictionsModal/OptionsStep/index.tsx +55 -0
- package/src/components/RestrictionsModal/OptionsStep/style.tsx +29 -0
- package/src/components/RestrictionsModal/RolesList/RoleItem/index.tsx +54 -0
- package/src/components/RestrictionsModal/RolesList/RoleItem/style.tsx +34 -0
- package/src/components/RestrictionsModal/RolesList/index.tsx +107 -0
- package/src/components/RestrictionsModal/RolesList/style.tsx +76 -0
- package/src/components/RestrictionsModal/UsersList/UserItem/index.tsx +78 -0
- package/src/components/RestrictionsModal/UsersList/UserItem/style.tsx +73 -0
- package/src/components/RestrictionsModal/UsersList/index.tsx +151 -0
- package/src/components/RestrictionsModal/UsersList/style.tsx +55 -0
- package/src/components/RestrictionsModal/index.tsx +181 -0
- package/src/components/RestrictionsModal/style.tsx +31 -0
- package/src/components/RestrictionsModal/utils.tsx +24 -0
- package/src/components/ScheduleModal/index.tsx +32 -8
- package/src/components/SelectionComponent/index.tsx +65 -0
- package/src/components/SelectionComponent/style.tsx +69 -0
- package/src/components/TableFilters/RoleFilter/index.tsx +3 -3
- package/src/components/TableList/TableItem/style.tsx +7 -13
- package/src/components/Tabs/index.tsx +2 -1
- package/src/components/UserRolesAndSites/index.tsx +2 -2
- package/src/components/index.tsx +6 -0
- package/src/containers/PageEditor/actions.tsx +43 -0
- package/src/containers/PageEditor/constants.tsx +1 -0
- package/src/containers/PageEditor/interfaces.tsx +26 -19
- package/src/containers/PageEditor/reducer.tsx +32 -19
- package/src/containers/Users/reducer.tsx +1 -0
- package/src/helpers/forms.tsx +3 -1
- package/src/hooks/index.tsx +2 -1
- package/src/hooks/users.tsx +154 -14
- package/src/modules/ActivityLog/LogFilters/UserFilter/index.tsx +11 -12
- package/src/modules/Content/PageItem/index.tsx +17 -10
- package/src/modules/Content/index.tsx +1 -3
- package/src/modules/GlobalEditor/Editor/index.tsx +6 -0
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +6 -0
- package/src/modules/GlobalEditor/Preview/index.tsx +4 -2
- package/src/modules/GlobalEditor/index.tsx +72 -45
- package/src/modules/Navigation/Menus/List/Table/ConfigPanel/Form/index.tsx +3 -5
- package/src/modules/Navigation/Menus/List/Table/ConfigPanel/index.tsx +4 -4
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/ConnectedField/index.tsx +2 -3
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +3 -4
- package/src/modules/Navigation/Menus/List/Table/SidePanel/index.tsx +5 -6
- package/src/modules/PageEditor/Editor/index.tsx +6 -0
- package/src/modules/PageEditor/PageBrowser/index.tsx +6 -0
- package/src/modules/PageEditor/Preview/index.tsx +9 -2
- package/src/modules/PageEditor/atoms.tsx +110 -3
- package/src/modules/PageEditor/index.tsx +76 -95
- package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +1 -3
- package/src/modules/Sites/SitesList/GridView/GridSiteItem/style.tsx +19 -2
- package/src/modules/Sites/SitesList/WelcomeModal/FinalStep/index.tsx +2 -2
- package/src/modules/Sites/SitesList/WelcomeModal/utils.ts +2 -2
- package/src/modules/StructuredData/Form/ConnectedField/index.tsx +2 -2
- package/src/modules/StructuredData/Form/index.tsx +120 -75
- package/src/modules/StructuredData/Form/style.tsx +7 -1
- package/src/modules/StructuredData/StructuredDataList/GlobalPageItem/index.tsx +15 -8
- package/src/modules/StructuredData/StructuredDataList/StructuredDataItem/index.tsx +15 -9
- package/src/modules/StructuredData/{StructuredDataList/StructuredDataItem/utils.tsx → utils.tsx} +16 -2
- package/src/modules/Users/Profile/atoms.tsx +62 -4
- package/src/modules/Users/Profile/index.tsx +83 -4
- package/src/modules/Users/Profile/style.tsx +60 -0
- package/src/modules/Users/UserCreate/SiteItem/RolesModal/RoleItem/index.tsx +3 -5
- package/src/modules/Users/UserCreate/SiteItem/index.tsx +2 -2
- package/src/modules/Users/UserCreate/atoms.tsx +69 -0
- package/src/modules/Users/UserCreate/index.tsx +149 -70
- package/src/modules/Users/UserCreate/style.tsx +24 -1
- package/src/modules/Users/UserForm/index.tsx +260 -146
- package/src/modules/Users/UserForm/style.tsx +13 -1
- package/src/modules/Users/UserList/UserItem/index.tsx +3 -3
- package/src/types/index.tsx +19 -6
- package/src/types/logs.tsx +1 -1
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
Notification,
|
|
16
16
|
OcassionalToast,
|
|
17
17
|
RestoreModal,
|
|
18
|
+
RestrictionsModal,
|
|
18
19
|
ScheduleModal,
|
|
19
20
|
} from "@ax/components";
|
|
20
21
|
import { appActions } from "@ax/containers/App";
|
|
@@ -25,7 +26,7 @@ import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
|
25
26
|
import { usersActions } from "@ax/containers/Users";
|
|
26
27
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
27
28
|
import { dateToString, getDefaultTheme } from "@ax/helpers";
|
|
28
|
-
import { useIsDirty, useModals,
|
|
29
|
+
import { useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
29
30
|
import type {
|
|
30
31
|
HeadingFilter,
|
|
31
32
|
IErrorItem,
|
|
@@ -36,6 +37,7 @@ import type {
|
|
|
36
37
|
ISavePageParams,
|
|
37
38
|
ISite,
|
|
38
39
|
IUserEditing,
|
|
40
|
+
PageAccessGrantsSummary,
|
|
39
41
|
} from "@ax/types";
|
|
40
42
|
|
|
41
43
|
import { DeleteModal } from "./atoms";
|
|
@@ -73,14 +75,23 @@ const GlobalEditor = (props: IProps) => {
|
|
|
73
75
|
restorePage,
|
|
74
76
|
updateEditorContent,
|
|
75
77
|
schemaVersion,
|
|
78
|
+
updatePageAccessGrants,
|
|
79
|
+
accessGrants,
|
|
76
80
|
} = props;
|
|
77
81
|
|
|
78
|
-
const isAllowedTo =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
const isAllowedTo = usePermissionsForPage(
|
|
83
|
+
"global",
|
|
84
|
+
pageID,
|
|
85
|
+
{
|
|
86
|
+
publishPages: "global.globalData.publishUnpublishAllGlobalData",
|
|
87
|
+
createPages: "global.globalData.createAllGlobalData",
|
|
88
|
+
deletePages: "global.globalData.deleteAllGlobalData",
|
|
89
|
+
editContentPages: "global.globalData.editAllGlobalData",
|
|
90
|
+
setPagePermissions: "global.globalData.setPermissionPerPage",
|
|
91
|
+
},
|
|
92
|
+
accessGrants,
|
|
93
|
+
pageLanguages,
|
|
94
|
+
);
|
|
84
95
|
|
|
85
96
|
const defaultTab = isAllowedTo.editContentPages ? "edit" : "view";
|
|
86
97
|
|
|
@@ -108,6 +119,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
108
119
|
"headingsPreview",
|
|
109
120
|
"keywordsPreview",
|
|
110
121
|
"dirtyNavigate",
|
|
122
|
+
"userAccess",
|
|
111
123
|
"delete",
|
|
112
124
|
]);
|
|
113
125
|
|
|
@@ -158,6 +170,10 @@ const GlobalEditor = (props: IProps) => {
|
|
|
158
170
|
return () => clearInterval(interval);
|
|
159
171
|
}, []);
|
|
160
172
|
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
setSelectedTab(defaultTab);
|
|
175
|
+
}, [defaultTab]);
|
|
176
|
+
|
|
161
177
|
// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
|
|
162
178
|
useEffect(() => {
|
|
163
179
|
resetDirty();
|
|
@@ -347,6 +363,14 @@ const GlobalEditor = (props: IProps) => {
|
|
|
347
363
|
|
|
348
364
|
const menuOptions = [];
|
|
349
365
|
|
|
366
|
+
if (isAllowedTo.setPagePermissions) {
|
|
367
|
+
menuOptions.push({
|
|
368
|
+
label: "Page user access",
|
|
369
|
+
icon: "users",
|
|
370
|
+
action: () => toggleModal("userAccess"),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
350
374
|
if (isAllowedTo.publishPages && !isScheduled && !isPublished && props.pageStatus !== pageStatus.OFFLINE_PENDING) {
|
|
351
375
|
menuOptions.push({
|
|
352
376
|
label: "Schedule",
|
|
@@ -409,6 +433,7 @@ const GlobalEditor = (props: IProps) => {
|
|
|
409
433
|
};
|
|
410
434
|
|
|
411
435
|
const isEditable = editorContent?.editable;
|
|
436
|
+
const isRestricted = !!(accessGrants.users.length || accessGrants.roles.length);
|
|
412
437
|
|
|
413
438
|
const handleSavePage = async (setToast?: (msg: string) => void) => {
|
|
414
439
|
const { savePage } = props;
|
|
@@ -542,26 +567,6 @@ const GlobalEditor = (props: IProps) => {
|
|
|
542
567
|
|
|
543
568
|
const mainUnpublishAction = { title: "Ok", onClick: () => toggleModal("unpublish") };
|
|
544
569
|
|
|
545
|
-
const mainScheduleModalAction = {
|
|
546
|
-
title: "Schedule",
|
|
547
|
-
onClick: handleSchedulePublication,
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
const secondaryScheduleModalAction = {
|
|
551
|
-
title: "Cancel",
|
|
552
|
-
onClick: () => toggleModal("schedule"),
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
const mainCancelScheduleModalAction = {
|
|
556
|
-
title: "Cancel Schedule",
|
|
557
|
-
onClick: handleCancelSchedulePublication,
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
const secondaryCancelScheduleModalAction = {
|
|
561
|
-
title: "Back",
|
|
562
|
-
onClick: () => toggleModal("cancelSchedule"),
|
|
563
|
-
};
|
|
564
|
-
|
|
565
570
|
const tabIcons = isAllowedTo.editContentPages
|
|
566
571
|
? [
|
|
567
572
|
{ name: "edit", text: "Edit mode" },
|
|
@@ -646,6 +651,13 @@ const GlobalEditor = (props: IProps) => {
|
|
|
646
651
|
setTab(defaultContentTab);
|
|
647
652
|
};
|
|
648
653
|
|
|
654
|
+
const handleUpdateAccessGrants = async (accessGrants: PageAccessGrantsSummary) => {
|
|
655
|
+
const isUpdated = await updatePageAccessGrants({ siteID: "global", pageID, accessGrants });
|
|
656
|
+
if (isUpdated) {
|
|
657
|
+
toggleModal("userAccess");
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
649
661
|
return isLoading ? (
|
|
650
662
|
<Loading />
|
|
651
663
|
) : (
|
|
@@ -725,12 +737,14 @@ const GlobalEditor = (props: IProps) => {
|
|
|
725
737
|
toggleKeywordsPreview={handleToggleKeywordsEditor}
|
|
726
738
|
isKeywordsPreviewOpen={isOpen("keywordsPreview")}
|
|
727
739
|
keywordsFilter={keywordsFilter}
|
|
740
|
+
isRestrictedPage={isRestricted}
|
|
741
|
+
onRestrictionsClick={isAllowedTo.setPagePermissions ? () => toggleModal("userAccess") : undefined}
|
|
728
742
|
/>
|
|
729
743
|
</S.Content>
|
|
730
744
|
</>
|
|
731
745
|
) : (
|
|
732
746
|
<>
|
|
733
|
-
<Preview theme={theme} />
|
|
747
|
+
<Preview theme={theme} isRestrictedPage={isRestricted} />
|
|
734
748
|
{toastMsg?.length && <OcassionalToast icon="warning" message={toastMsg} />}
|
|
735
749
|
</>
|
|
736
750
|
)}
|
|
@@ -777,16 +791,14 @@ const GlobalEditor = (props: IProps) => {
|
|
|
777
791
|
<ScheduleModal
|
|
778
792
|
isOpen={isOpen("schedule")}
|
|
779
793
|
toggleModal={() => toggleModal("schedule")}
|
|
780
|
-
|
|
781
|
-
secondaryModalAction={secondaryScheduleModalAction}
|
|
794
|
+
onSchedule={handleSchedulePublication}
|
|
782
795
|
scheduleDate={scheduleDate}
|
|
783
796
|
setScheduleDate={setScheduleDate}
|
|
784
797
|
/>
|
|
785
798
|
<CancelScheduleModal
|
|
786
799
|
isOpen={isOpen("cancelSchedule")}
|
|
787
800
|
toggleModal={() => toggleModal("cancelSchedule")}
|
|
788
|
-
|
|
789
|
-
secondaryModalAction={secondaryCancelScheduleModalAction}
|
|
801
|
+
onCancelSchedule={handleCancelSchedulePublication}
|
|
790
802
|
/>
|
|
791
803
|
<RestoreModal
|
|
792
804
|
isOpen={isOpen("restore")}
|
|
@@ -814,20 +826,27 @@ const GlobalEditor = (props: IProps) => {
|
|
|
814
826
|
addKeywords={handleAddKeywords}
|
|
815
827
|
deleteKeyword={handledeleteKeyword}
|
|
816
828
|
/>
|
|
829
|
+
<RestrictionsModal
|
|
830
|
+
isOpen={isOpen("userAccess")}
|
|
831
|
+
toggleModal={() => toggleModal("userAccess")}
|
|
832
|
+
currentAccessGrants={accessGrants}
|
|
833
|
+
onUpdateAccessGrants={handleUpdateAccessGrants}
|
|
834
|
+
isSaving={isSaving}
|
|
835
|
+
/>
|
|
836
|
+
<Modal
|
|
837
|
+
isOpen={isOpen("dirtyNavigate")}
|
|
838
|
+
hide={handleCancelDirtyNavigation}
|
|
839
|
+
size="S"
|
|
840
|
+
title="Unsaved changes"
|
|
841
|
+
mainAction={{ title: "Yes, discard changes", onClick: handleConfirmDirtyNavigation }}
|
|
842
|
+
secondaryAction={{ title: "Cancel", onClick: handleCancelDirtyNavigation }}
|
|
843
|
+
>
|
|
844
|
+
<S.ModalContent>
|
|
845
|
+
Some content <strong>is not saved</strong> on this page. If you exit without saving it, it will be lost. Do
|
|
846
|
+
you want to discard your changes?
|
|
847
|
+
</S.ModalContent>
|
|
848
|
+
</Modal>
|
|
817
849
|
</MainWrapper>
|
|
818
|
-
<Modal
|
|
819
|
-
isOpen={isOpen("dirtyNavigate")}
|
|
820
|
-
hide={handleCancelDirtyNavigation}
|
|
821
|
-
size="S"
|
|
822
|
-
title="Unsaved changes"
|
|
823
|
-
mainAction={{ title: "Yes, discard changes", onClick: handleConfirmDirtyNavigation }}
|
|
824
|
-
secondaryAction={{ title: "Cancel", onClick: handleCancelDirtyNavigation }}
|
|
825
|
-
>
|
|
826
|
-
<S.ModalContent>
|
|
827
|
-
Some content <strong>is not saved</strong> on this page. If you exit without saving it, it will be lost. Do
|
|
828
|
-
you want to discard your changes?
|
|
829
|
-
</S.ModalContent>
|
|
830
|
-
</Modal>
|
|
831
850
|
</>
|
|
832
851
|
);
|
|
833
852
|
};
|
|
@@ -851,6 +870,7 @@ const mapStateToProps = (state: IRootState): IPageEditorStateProps => ({
|
|
|
851
870
|
currentSiteErrorPages: state.sites.currentSiteErrorPages,
|
|
852
871
|
skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
|
|
853
872
|
schemaVersion: state.structuredData.schemaVersion,
|
|
873
|
+
accessGrants: state.pageEditor.accessGrants,
|
|
854
874
|
});
|
|
855
875
|
|
|
856
876
|
interface IPageEditorStateProps {
|
|
@@ -872,6 +892,7 @@ interface IPageEditorStateProps {
|
|
|
872
892
|
currentSiteErrorPages: number[];
|
|
873
893
|
skipReviewOnPublish?: boolean;
|
|
874
894
|
schemaVersion: string;
|
|
895
|
+
accessGrants: PageAccessGrantsSummary;
|
|
875
896
|
}
|
|
876
897
|
|
|
877
898
|
const mapDispatchToProps = {
|
|
@@ -895,6 +916,7 @@ const mapDispatchToProps = {
|
|
|
895
916
|
schedulePublication: pageEditorActions.schedulePublication,
|
|
896
917
|
restorePage: pageEditorActions.restorePage,
|
|
897
918
|
updateEditorContent: pageEditorActions.updateEditorContent,
|
|
919
|
+
updatePageAccessGrants: pageEditorActions.updatePageAccessGrants,
|
|
898
920
|
};
|
|
899
921
|
|
|
900
922
|
interface IPageEditorDispatchProps {
|
|
@@ -923,6 +945,11 @@ interface IPageEditorDispatchProps {
|
|
|
923
945
|
schedulePublication(date: string | null, isDraft: boolean): Promise<boolean>;
|
|
924
946
|
restorePage(id: number | number[]): Promise<boolean>;
|
|
925
947
|
updateEditorContent(selectedEditorID: number, key: string, value: any): void;
|
|
948
|
+
updatePageAccessGrants(data: {
|
|
949
|
+
siteID: number | "global";
|
|
950
|
+
pageID: number | null;
|
|
951
|
+
accessGrants: PageAccessGrantsSummary;
|
|
952
|
+
}): Promise<boolean>;
|
|
926
953
|
}
|
|
927
954
|
|
|
928
955
|
type IProps = IPageEditorStateProps & IPageEditorDispatchProps & RouteComponentProps;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
|
|
3
1
|
import { FieldsBehavior } from "@ax/components";
|
|
4
2
|
import { getModuleStyles } from "@ax/helpers";
|
|
5
|
-
import { IMenuItemConfig } from "@ax/types";
|
|
3
|
+
import type { IMenuItemConfig } from "@ax/types";
|
|
6
4
|
|
|
7
5
|
import * as S from "./style";
|
|
8
6
|
|
|
@@ -25,8 +23,8 @@ const Form = (props: IProps): JSX.Element => {
|
|
|
25
23
|
text: "You can choose how to view the children of this section in navigation modules.",
|
|
26
24
|
};
|
|
27
25
|
|
|
28
|
-
const headerValue = form
|
|
29
|
-
const footerValue = form
|
|
26
|
+
const headerValue = form?.headerStyle ? form.headerStyle : headerOptions[0] ? headerOptions[0].value : null;
|
|
27
|
+
const footerValue = form?.footerStyle ? form.footerStyle : footerOptions[0] ? footerOptions[0].value : null;
|
|
30
28
|
|
|
31
29
|
return (
|
|
32
30
|
<>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { useState } from "react";
|
|
3
2
|
import { connect } from "react-redux";
|
|
3
|
+
|
|
4
|
+
import { Button, FloatingPanel } from "@ax/components";
|
|
4
5
|
import { menuActions } from "@ax/containers/Navigation";
|
|
5
|
-
import {
|
|
6
|
-
import { FloatingPanel, Button } from "@ax/components";
|
|
6
|
+
import type { IMenuItem, IMenuItemConfig, IRootState } from "@ax/types";
|
|
7
7
|
|
|
8
8
|
import Form from "./Form";
|
|
9
9
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { connect } from "react-redux";
|
|
3
2
|
|
|
4
|
-
import { IRootState } from "@ax/types";
|
|
5
|
-
import { menuActions } from "@ax/containers/Navigation/Menu";
|
|
6
3
|
import { FieldsBehavior } from "@ax/components";
|
|
4
|
+
import { menuActions } from "@ax/containers/Navigation/Menu";
|
|
5
|
+
import type { IRootState } from "@ax/types";
|
|
7
6
|
|
|
8
7
|
const ConnectedField = (props: IProps) => {
|
|
9
8
|
const { form, type, name, updateFormValue, setIsGalleryOpened } = props;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { connect } from "react-redux";
|
|
3
2
|
|
|
3
|
+
import { FieldsBehavior } from "@ax/components";
|
|
4
4
|
import { menuActions } from "@ax/containers/Navigation";
|
|
5
5
|
import { sitesActions } from "@ax/containers/Sites";
|
|
6
|
-
import { FieldsBehavior } from "@ax/components";
|
|
7
|
-
import { IRootState, IMenuForm, ISchemaField } from "@ax/types";
|
|
8
6
|
import { getMenuItems } from "@ax/helpers";
|
|
7
|
+
import type { IMenuForm, IRootState, ISchemaField } from "@ax/types";
|
|
9
8
|
|
|
10
9
|
import ConnectedField from "./ConnectedField";
|
|
11
10
|
|
|
@@ -34,7 +33,7 @@ const Form = (props: IProps): JSX.Element => {
|
|
|
34
33
|
const typeLink = type ? type : "link";
|
|
35
34
|
|
|
36
35
|
const menuItems = getMenuItems(typeLink);
|
|
37
|
-
const schemaFields = menuItems
|
|
36
|
+
const schemaFields = menuItems?.fields ? menuItems.fields : [];
|
|
38
37
|
|
|
39
38
|
const generateFields = (fields: ISchemaField[]) =>
|
|
40
39
|
fields.map((field: ISchemaField) => (
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { useState } from "react";
|
|
3
2
|
import { connect } from "react-redux";
|
|
4
|
-
import { menuActions } from "@ax/containers/Navigation";
|
|
5
3
|
|
|
6
|
-
import {
|
|
4
|
+
import { Button, FloatingPanel } from "@ax/components";
|
|
5
|
+
import { menuActions } from "@ax/containers/Navigation";
|
|
6
|
+
import type { IMenuForm, IMenuItem, IRootState } from "@ax/types";
|
|
7
7
|
|
|
8
8
|
import Form from "./Form";
|
|
9
9
|
|
|
10
|
-
import { IRootState, IMenuItem, IMenuForm } from "@ax/types";
|
|
11
10
|
import * as S from "./style";
|
|
12
11
|
|
|
13
12
|
const SidePanel = (props: IProps): JSX.Element => {
|
|
@@ -40,7 +39,7 @@ const SidePanel = (props: IProps): JSX.Element => {
|
|
|
40
39
|
};
|
|
41
40
|
|
|
42
41
|
const editItemAction = () => {
|
|
43
|
-
menuItem = { ...menuItem, editorID: item
|
|
42
|
+
menuItem = { ...menuItem, editorID: item?.editorID };
|
|
44
43
|
updateMenuItem(menuItem);
|
|
45
44
|
toggleModal();
|
|
46
45
|
};
|
|
@@ -61,6 +61,8 @@ const Editor = (props: IProps) => {
|
|
|
61
61
|
keywordsFilter,
|
|
62
62
|
isDirty,
|
|
63
63
|
onNavigateWithDirty,
|
|
64
|
+
isRestrictedPage,
|
|
65
|
+
onRestrictionsClick,
|
|
64
66
|
} = props;
|
|
65
67
|
|
|
66
68
|
if (!site) {
|
|
@@ -102,6 +104,8 @@ const Editor = (props: IProps) => {
|
|
|
102
104
|
toggleKeywordsPreview={toggleKeywordsPreview}
|
|
103
105
|
isKeywordsPreviewOpen={isKeywordsPreviewOpen}
|
|
104
106
|
keywordsFilter={keywordsFilter}
|
|
107
|
+
isRestrictedPage={isRestrictedPage}
|
|
108
|
+
onRestrictionsClick={onRestrictionsClick}
|
|
105
109
|
/>
|
|
106
110
|
}
|
|
107
111
|
rightPanel={
|
|
@@ -183,6 +187,8 @@ interface IPageBrowserDispatchProps {
|
|
|
183
187
|
keywordsFilter: string[];
|
|
184
188
|
isDirty?: boolean;
|
|
185
189
|
onNavigateWithDirty?: (navigateCallback: () => void) => void;
|
|
190
|
+
isRestrictedPage?: boolean;
|
|
191
|
+
onRestrictionsClick?(): void;
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
type IProps = IEditorStateProps & IPageBrowserDispatchProps;
|
|
@@ -26,6 +26,8 @@ const PageBrowser = (props: IProps) => {
|
|
|
26
26
|
setScrollEditorID,
|
|
27
27
|
toggleHeadingsPreview,
|
|
28
28
|
toggleKeywordsPreview,
|
|
29
|
+
isRestrictedPage,
|
|
30
|
+
onRestrictionsClick,
|
|
29
31
|
} = props;
|
|
30
32
|
|
|
31
33
|
if (!currentSiteInfo) {
|
|
@@ -70,6 +72,8 @@ const PageBrowser = (props: IProps) => {
|
|
|
70
72
|
toggleKeywordsPreview={toggleKeywordsPreview}
|
|
71
73
|
headingFilter={headingsFilter}
|
|
72
74
|
keywordsFilter={keywordsFilter}
|
|
75
|
+
isRestrictedPage={isRestrictedPage}
|
|
76
|
+
onRestrictionsClick={onRestrictionsClick}
|
|
73
77
|
/>
|
|
74
78
|
);
|
|
75
79
|
};
|
|
@@ -100,6 +104,8 @@ interface IPageBrowserDispatchProps {
|
|
|
100
104
|
setScrollEditorID(editorID: number | null): void;
|
|
101
105
|
toggleHeadingsPreview?(): void;
|
|
102
106
|
toggleKeywordsPreview?(): void;
|
|
107
|
+
isRestrictedPage?: boolean;
|
|
108
|
+
onRestrictionsClick?(): void;
|
|
103
109
|
}
|
|
104
110
|
|
|
105
111
|
type IProps = IPageBrowserStateProps & IPageBrowserDispatchProps;
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import PageBrowser from "../PageBrowser";
|
|
2
|
+
|
|
2
3
|
import * as S from "./style";
|
|
3
4
|
|
|
4
|
-
const PreviewBrowser = () => {
|
|
5
|
+
const PreviewBrowser = (props: IPreviewProps) => {
|
|
6
|
+
const { isRestrictedPage } = props;
|
|
7
|
+
|
|
5
8
|
return (
|
|
6
9
|
<S.BrowserWrapper>
|
|
7
|
-
<PageBrowser isTemplateActivated={true} isReadOnly={true} isPreview={true} />
|
|
10
|
+
<PageBrowser isTemplateActivated={true} isReadOnly={true} isPreview={true} isRestrictedPage={isRestrictedPage} />
|
|
8
11
|
</S.BrowserWrapper>
|
|
9
12
|
);
|
|
10
13
|
};
|
|
11
14
|
|
|
15
|
+
interface IPreviewProps {
|
|
16
|
+
isRestrictedPage?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
export default PreviewBrowser;
|
|
@@ -1,10 +1,49 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import type React from "react";
|
|
2
2
|
|
|
3
|
+
import { FieldsBehavior, Modal } from "@ax/components";
|
|
3
4
|
import type { IModal } from "@ax/types";
|
|
4
|
-
import { Modal, FieldsBehavior } from "@ax/components";
|
|
5
5
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
8
|
+
const DirtyNavigateModal = (props: IDirtyNavigateModal): JSX.Element => {
|
|
9
|
+
const { isOpen, onConfirm, onCancel } = props;
|
|
10
|
+
|
|
11
|
+
const mainAction = {
|
|
12
|
+
title: "Yes, discard changes",
|
|
13
|
+
onClick: onConfirm,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const secondaryAction = {
|
|
17
|
+
title: "Cancel",
|
|
18
|
+
onClick: onCancel,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Modal
|
|
23
|
+
isOpen={isOpen}
|
|
24
|
+
hide={onCancel}
|
|
25
|
+
size="S"
|
|
26
|
+
title="Unsaved changes"
|
|
27
|
+
mainAction={mainAction}
|
|
28
|
+
secondaryAction={secondaryAction}
|
|
29
|
+
height="auto"
|
|
30
|
+
>
|
|
31
|
+
<S.ModalContent>
|
|
32
|
+
<>
|
|
33
|
+
Some content <strong>is not saved</strong> on this page. If you exit without saving it, it will be lost. Do
|
|
34
|
+
you want to discard your changes?
|
|
35
|
+
</>
|
|
36
|
+
</S.ModalContent>
|
|
37
|
+
</Modal>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
interface IDirtyNavigateModal {
|
|
42
|
+
isOpen: boolean;
|
|
43
|
+
onConfirm: () => void;
|
|
44
|
+
onCancel: () => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
8
47
|
const DeleteModal = (props: IDeleteModal): JSX.Element => {
|
|
9
48
|
const { isOpen, toggleModal, isTranslated, deleteAllVersions, setDeleteAllVersions, onDelete, isDeleting } = props;
|
|
10
49
|
|
|
@@ -74,4 +113,72 @@ interface IDeleteModal extends IModal {
|
|
|
74
113
|
isDeleting?: boolean;
|
|
75
114
|
}
|
|
76
115
|
|
|
77
|
-
|
|
116
|
+
const UserEditingModal = (props: IUserEditingModal): JSX.Element => {
|
|
117
|
+
const { isOpen, toggleModal, userEditing, onBack } = props;
|
|
118
|
+
|
|
119
|
+
const mainAction = {
|
|
120
|
+
title: "Preview Page",
|
|
121
|
+
onClick: () => toggleModal(),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const secondaryAction = {
|
|
125
|
+
title: "Ok, go back",
|
|
126
|
+
onClick: onBack,
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Modal
|
|
131
|
+
isOpen={isOpen}
|
|
132
|
+
hide={() => toggleModal()}
|
|
133
|
+
size="S"
|
|
134
|
+
title="This page is currently being edited"
|
|
135
|
+
mainAction={mainAction}
|
|
136
|
+
secondaryAction={secondaryAction}
|
|
137
|
+
>
|
|
138
|
+
{isOpen && (
|
|
139
|
+
<S.ModalContent>
|
|
140
|
+
<p>
|
|
141
|
+
<strong>{userEditing?.name}</strong> is currently working on this page. You can preview the page but{" "}
|
|
142
|
+
<strong>you cannot make changes to it</strong> until {userEditing?.name} leaves the page.
|
|
143
|
+
</p>
|
|
144
|
+
</S.ModalContent>
|
|
145
|
+
)}
|
|
146
|
+
</Modal>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
interface IUserEditingModal {
|
|
151
|
+
isOpen: boolean;
|
|
152
|
+
toggleModal: () => void;
|
|
153
|
+
userEditing?: { name: string; id: number } | null;
|
|
154
|
+
onBack: () => void;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const UnpublishModal = (props: IUnpublishModal): JSX.Element => {
|
|
158
|
+
const { isOpen, toggleModal } = props;
|
|
159
|
+
|
|
160
|
+
const mainAction = {
|
|
161
|
+
title: "Ok",
|
|
162
|
+
onClick: () => toggleModal(),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<Modal isOpen={isOpen} hide={() => toggleModal()} size="S" title="Unpublish Modified Page" mainAction={mainAction}>
|
|
167
|
+
{isOpen && (
|
|
168
|
+
<S.ModalContent>
|
|
169
|
+
<p>
|
|
170
|
+
There are some saved changes that are not published on this page. To Unpublish this page,{" "}
|
|
171
|
+
<strong>you must publish these changes or discard them.</strong>
|
|
172
|
+
</p>
|
|
173
|
+
</S.ModalContent>
|
|
174
|
+
)}
|
|
175
|
+
</Modal>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
interface IUnpublishModal {
|
|
180
|
+
isOpen: boolean;
|
|
181
|
+
toggleModal: () => void;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export { UnpublishModal, UserEditingModal, DeleteModal, DirtyNavigateModal };
|