@griddo/ax 11.15.9 → 11.16.0-rc.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/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
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
MainWrapper,
|
|
9
9
|
Notification,
|
|
10
10
|
RestoreModal,
|
|
11
|
+
RestrictionsModal,
|
|
11
12
|
ScheduleModal,
|
|
12
13
|
} from "@ax/components";
|
|
13
14
|
import { appActions } from "@ax/containers/App";
|
|
@@ -15,7 +16,7 @@ import { dataPacksActions } from "@ax/containers/Settings/DataPacks";
|
|
|
15
16
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
16
17
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
17
18
|
import { dateToString, getActivatedDataPacksIds, getDefaultTheme } from "@ax/helpers";
|
|
18
|
-
import { useIsDirty,
|
|
19
|
+
import { useIsDirty, useModals, usePermissionsForPage } from "@ax/hooks";
|
|
19
20
|
import type {
|
|
20
21
|
IDataLanguage,
|
|
21
22
|
IDataPack,
|
|
@@ -23,11 +24,16 @@ import type {
|
|
|
23
24
|
ILanguage,
|
|
24
25
|
INotification,
|
|
25
26
|
IRootState,
|
|
27
|
+
ISchema,
|
|
26
28
|
ISchemaField,
|
|
27
29
|
ISite,
|
|
30
|
+
IStructuredData,
|
|
31
|
+
IStructuredDataContent,
|
|
32
|
+
PageAccessGrantsSummary,
|
|
28
33
|
} from "@ax/types";
|
|
29
34
|
|
|
30
35
|
import { DeleteModal } from "../atoms";
|
|
36
|
+
import { getPermission } from "../utils";
|
|
31
37
|
import ConnectedField from "./ConnectedField";
|
|
32
38
|
|
|
33
39
|
import * as S from "./style";
|
|
@@ -62,16 +68,31 @@ const Form = (props: IProps) => {
|
|
|
62
68
|
restoreDataContent,
|
|
63
69
|
} = props;
|
|
64
70
|
|
|
71
|
+
const isPrivateData = currentStructuredData?.private || false;
|
|
72
|
+
|
|
73
|
+
const isAllowedTo = usePermissionsForPage(
|
|
74
|
+
site?.id || "global",
|
|
75
|
+
form?.id || 0,
|
|
76
|
+
{
|
|
77
|
+
publishPages: getPermission("publish", !site, isPrivateData),
|
|
78
|
+
createPages: getPermission("create", !site, isPrivateData),
|
|
79
|
+
deletePages: getPermission("delete", !site, isPrivateData),
|
|
80
|
+
editPages: getPermission("edit", !site, isPrivateData),
|
|
81
|
+
setPagePermissions: site
|
|
82
|
+
? "general.setPermissionPerSimpleContent"
|
|
83
|
+
: "global.globalData.setPermissionPerSimpleContent",
|
|
84
|
+
},
|
|
85
|
+
form?.accessGrants,
|
|
86
|
+
form?.dataLanguages,
|
|
87
|
+
);
|
|
88
|
+
|
|
65
89
|
const [isNewStructuredData, setIsNewStructuredData] = useState(!currentStructuredDataId);
|
|
66
90
|
const [notification, setNotification] = useState<INotification | null>(null);
|
|
67
91
|
const [scheduleDate, setScheduleDate] = useState({
|
|
68
92
|
date: dateToString(new Date(), "yyy/MM/dd"),
|
|
69
93
|
time: "12:00 am",
|
|
70
94
|
});
|
|
71
|
-
const { isOpen
|
|
72
|
-
const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
|
|
73
|
-
const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
|
|
74
|
-
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
95
|
+
const { isOpen, toggleModal } = useModals(["schedule", "cancelSchedule", "restore", "userAccess", "delete"]);
|
|
75
96
|
const [isDeleting, setIsDeleting] = useState(false);
|
|
76
97
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
77
98
|
const { isDirty, resetDirty, setIsDirty } = useIsDirty(form);
|
|
@@ -94,10 +115,11 @@ const Form = (props: IProps) => {
|
|
|
94
115
|
|
|
95
116
|
const activatedDataPacksIds = getActivatedDataPacksIds(activatedDataPacks);
|
|
96
117
|
const disabledDatapack =
|
|
97
|
-
currentStructuredData
|
|
98
|
-
!activatedDataPacksIds.some((pack: string) => currentStructuredData
|
|
118
|
+
currentStructuredData?.local &&
|
|
119
|
+
!activatedDataPacksIds.some((pack: string) => currentStructuredData!.dataPacks.includes(pack));
|
|
99
120
|
const isDeleted = !!form?.deleted;
|
|
100
|
-
const isDisabled = isDeleted || disabledDatapack;
|
|
121
|
+
const isDisabled = isDeleted || disabledDatapack || !isAllowedTo.editPages;
|
|
122
|
+
const isRestricted = !!(form?.accessGrants?.users.length || form?.accessGrants?.roles.length);
|
|
101
123
|
|
|
102
124
|
const isDataTranslatable = currentStructuredData?.translate;
|
|
103
125
|
const isScheduled = !!form && !!form.publicationScheduled;
|
|
@@ -144,18 +166,19 @@ const Form = (props: IProps) => {
|
|
|
144
166
|
);
|
|
145
167
|
});
|
|
146
168
|
|
|
147
|
-
const handleSave = async (publish: boolean, scheduleDate?: string | null) => {
|
|
169
|
+
const handleSave = async (publish: boolean, scheduleDate?: string | null, formToSave?: any) => {
|
|
170
|
+
const currentForm = formToSave || form;
|
|
148
171
|
const validated = publish && !skipReviewOnPublish ? await validateForm(true) : true;
|
|
149
172
|
|
|
150
173
|
if (validated) {
|
|
151
|
-
const status = isNewStructuredData ? true :
|
|
174
|
+
const status = isNewStructuredData ? true : currentForm.draft;
|
|
152
175
|
|
|
153
176
|
const payload: any = {
|
|
154
|
-
...
|
|
177
|
+
...currentForm,
|
|
155
178
|
structuredData: currentStructuredData ? currentStructuredData.id : null,
|
|
156
179
|
draft: publish === true ? false : status,
|
|
157
180
|
relatedSite: site ? site.id : null,
|
|
158
|
-
publicationScheduled: scheduleDate !== undefined ? scheduleDate :
|
|
181
|
+
publicationScheduled: scheduleDate !== undefined ? scheduleDate : currentForm.publicationScheduled,
|
|
159
182
|
};
|
|
160
183
|
|
|
161
184
|
let saved = false;
|
|
@@ -174,7 +197,7 @@ const Form = (props: IProps) => {
|
|
|
174
197
|
return form?.draft ? "Save" : "Save & publish";
|
|
175
198
|
};
|
|
176
199
|
|
|
177
|
-
const handleSaveAndPublish = () => (isNewStructuredData || form
|
|
200
|
+
const handleSaveAndPublish = () => (isNewStructuredData || form?.draft ? handleSave(false) : handleSave(true));
|
|
178
201
|
|
|
179
202
|
const rightButtonProps = {
|
|
180
203
|
label: isSaving ? "Saving" : !isDirty ? "Saved" : getSaveLabel(),
|
|
@@ -197,7 +220,7 @@ const Form = (props: IProps) => {
|
|
|
197
220
|
|
|
198
221
|
const currentLanguages = getCurrentLanguages();
|
|
199
222
|
|
|
200
|
-
const availableLanguages = isDisabled ? currentLanguages : languages;
|
|
223
|
+
const availableLanguages = isDisabled || !isAllowedTo.createPages ? currentLanguages : languages;
|
|
201
224
|
|
|
202
225
|
const setRoute = (path: string) => setHistoryPush(path, true);
|
|
203
226
|
|
|
@@ -208,28 +231,32 @@ const Form = (props: IProps) => {
|
|
|
208
231
|
);
|
|
209
232
|
|
|
210
233
|
const handleClickNotification = () => {
|
|
211
|
-
|
|
212
|
-
|
|
234
|
+
if (currentStructuredData) {
|
|
235
|
+
getSiteDataPack(currentStructuredData.id);
|
|
236
|
+
setHistoryPush("/sites/settings/content-types", false);
|
|
237
|
+
}
|
|
213
238
|
};
|
|
214
239
|
|
|
215
240
|
const removeItem = async () => {
|
|
241
|
+
if (!form) return;
|
|
216
242
|
setIsDeleting(true);
|
|
217
243
|
const deleted = await deleteStructuredDataContent(form.id);
|
|
218
244
|
setIsDeleting(false);
|
|
219
|
-
|
|
245
|
+
toggleModal("delete");
|
|
220
246
|
if (deleted) {
|
|
221
247
|
setHistoryPush(path, true);
|
|
222
248
|
}
|
|
223
249
|
};
|
|
224
250
|
|
|
225
251
|
const publishItem = async () => {
|
|
252
|
+
if (!form) return;
|
|
226
253
|
const validated = skipReviewOnPublish ? true : await validateForm(true);
|
|
227
254
|
if (!validated) return;
|
|
228
255
|
|
|
229
256
|
if (!isNewStructuredData) {
|
|
230
|
-
setDataStatus(form.id, "undraft").then((updated: boolean) => {
|
|
257
|
+
await setDataStatus(form.id, "undraft").then(async (updated: boolean) => {
|
|
231
258
|
if (updated) {
|
|
232
|
-
getDataContent(form.id);
|
|
259
|
+
await getDataContent(form.id);
|
|
233
260
|
}
|
|
234
261
|
});
|
|
235
262
|
} else {
|
|
@@ -237,12 +264,14 @@ const Form = (props: IProps) => {
|
|
|
237
264
|
}
|
|
238
265
|
};
|
|
239
266
|
|
|
240
|
-
const unpublishItem = async () =>
|
|
241
|
-
|
|
267
|
+
const unpublishItem = async () => {
|
|
268
|
+
if (!form) return;
|
|
269
|
+
await setDataStatus(form.id, "draft").then(async (updated: boolean) => {
|
|
242
270
|
if (updated) {
|
|
243
|
-
getDataContent(form.id);
|
|
271
|
+
await getDataContent(form.id);
|
|
244
272
|
}
|
|
245
273
|
});
|
|
274
|
+
};
|
|
246
275
|
|
|
247
276
|
const getPublishButton = (draft: boolean) => {
|
|
248
277
|
if (draft === true || draft === undefined) {
|
|
@@ -266,50 +295,61 @@ const Form = (props: IProps) => {
|
|
|
266
295
|
const date = new Date(`${scheduleDate.date} ${scheduleDate.time}`);
|
|
267
296
|
const dateString = dateToString(date, "dd/MM/yyyy HH:mm:ss");
|
|
268
297
|
handleSave(false, dateString);
|
|
269
|
-
|
|
298
|
+
toggleModal("schedule");
|
|
270
299
|
};
|
|
271
300
|
|
|
272
301
|
const handleCancelSchedulePublication = () => {
|
|
273
302
|
handleSave(false, null);
|
|
274
303
|
setScheduleDate({ date: "", time: "12:00 am" });
|
|
275
|
-
|
|
304
|
+
toggleModal("cancelSchedule");
|
|
276
305
|
};
|
|
277
306
|
|
|
278
307
|
const downArrowMenu = {
|
|
279
308
|
displayed: !isDeleted,
|
|
280
|
-
button: getPublishButton(form?.draft),
|
|
309
|
+
button: isAllowedTo.publishPages ? getPublishButton(form?.draft ?? false) : undefined,
|
|
281
310
|
options: [
|
|
282
311
|
{
|
|
283
312
|
label: "Review",
|
|
284
313
|
icon: "question",
|
|
285
314
|
action: reviewForm,
|
|
286
315
|
},
|
|
287
|
-
{
|
|
288
|
-
label: "Delete",
|
|
289
|
-
icon: "delete",
|
|
290
|
-
action: toggleDeleteModal,
|
|
291
|
-
},
|
|
292
316
|
],
|
|
293
317
|
};
|
|
294
318
|
|
|
295
|
-
if (
|
|
319
|
+
if (isAllowedTo.deletePages) {
|
|
320
|
+
downArrowMenu.options.push({
|
|
321
|
+
label: "Delete",
|
|
322
|
+
icon: "delete",
|
|
323
|
+
action: async () => toggleModal("delete"),
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (status === "offline" && !isScheduled && isAllowedTo.publishPages) {
|
|
296
328
|
downArrowMenu.options.unshift({
|
|
297
329
|
label: "Schedule",
|
|
298
330
|
icon: "calendar",
|
|
299
|
-
action:
|
|
331
|
+
action: async () => toggleModal("schedule"),
|
|
300
332
|
});
|
|
301
333
|
}
|
|
302
334
|
|
|
303
|
-
if (isScheduled) {
|
|
335
|
+
if (isScheduled && isAllowedTo.publishPages) {
|
|
304
336
|
downArrowMenu.options.unshift({
|
|
305
337
|
label: "Cancel Schedule",
|
|
306
338
|
icon: "cancelEvent",
|
|
307
|
-
action:
|
|
339
|
+
action: async () => toggleModal("cancelSchedule"),
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (isAllowedTo.setPagePermissions) {
|
|
344
|
+
downArrowMenu.options.unshift({
|
|
345
|
+
label: "Page user access",
|
|
346
|
+
icon: "users",
|
|
347
|
+
action: async () => toggleModal("userAccess"),
|
|
308
348
|
});
|
|
309
349
|
}
|
|
310
350
|
|
|
311
351
|
const getSelectedDataLanguage = (language: ILanguage): IDataLanguage | undefined =>
|
|
312
|
-
form
|
|
352
|
+
form?.dataLanguages?.find((dataLang: IDataLanguage) => dataLang.language === language.id);
|
|
313
353
|
|
|
314
354
|
const handleLanguage = async (language: ILanguage) => {
|
|
315
355
|
const { locale, id } = language;
|
|
@@ -323,7 +363,9 @@ const Form = (props: IProps) => {
|
|
|
323
363
|
resetDirty();
|
|
324
364
|
} else {
|
|
325
365
|
currentStructuredDataId && (await getDataContent(currentStructuredDataId));
|
|
326
|
-
|
|
366
|
+
if (form) {
|
|
367
|
+
setFormValues({ ...form, canBeTranslated: true } as IStructuredDataContent & Record<string, any>);
|
|
368
|
+
}
|
|
327
369
|
setIsNewStructuredData(true);
|
|
328
370
|
}
|
|
329
371
|
};
|
|
@@ -332,29 +374,17 @@ const Form = (props: IProps) => {
|
|
|
332
374
|
if (!currentStructuredDataId) return;
|
|
333
375
|
const isRestored = await restoreDataContent(currentStructuredDataId);
|
|
334
376
|
if (isRestored) {
|
|
335
|
-
|
|
377
|
+
isOpen("restore") && toggleModal("restore");
|
|
336
378
|
await getDataContent(currentStructuredDataId);
|
|
337
379
|
}
|
|
338
380
|
};
|
|
339
381
|
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
title: "Cancel",
|
|
347
|
-
onClick: toggleScheduleModal,
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
const mainCancelScheduleModalAction = {
|
|
351
|
-
title: "Cancel Schedule",
|
|
352
|
-
onClick: handleCancelSchedulePublication,
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
const secondaryCancelScheduleModalAction = {
|
|
356
|
-
title: "Back",
|
|
357
|
-
onClick: toggleCancelScheduleModal,
|
|
382
|
+
const handleUpdateAccessGrants = async (accessGrants: PageAccessGrantsSummary) => {
|
|
383
|
+
if (!form) return;
|
|
384
|
+
const updatedForm = { ...form, accessGrants } as IStructuredDataContent & Record<string, any>;
|
|
385
|
+
setFormValues(updatedForm);
|
|
386
|
+
await handleSave(false, undefined, updatedForm);
|
|
387
|
+
toggleModal("userAccess");
|
|
358
388
|
};
|
|
359
389
|
|
|
360
390
|
return isLoading && !isDeleting ? (
|
|
@@ -396,7 +426,7 @@ const Form = (props: IProps) => {
|
|
|
396
426
|
type="error"
|
|
397
427
|
text={deletedNotificationText}
|
|
398
428
|
btnText="Restore content"
|
|
399
|
-
onClick={
|
|
429
|
+
onClick={() => toggleModal("restore")}
|
|
400
430
|
/>
|
|
401
431
|
</S.NotificationWrapper>
|
|
402
432
|
)}
|
|
@@ -412,25 +442,33 @@ const Form = (props: IProps) => {
|
|
|
412
442
|
</S.NotificationWrapper>
|
|
413
443
|
)}
|
|
414
444
|
<ErrorToast size="l" />
|
|
415
|
-
<S.Wrapper>
|
|
445
|
+
<S.Wrapper>
|
|
446
|
+
{isRestricted && (
|
|
447
|
+
<S.StyledFloatingNote
|
|
448
|
+
message="Only some users can edit this page."
|
|
449
|
+
icon="users"
|
|
450
|
+
$short={true}
|
|
451
|
+
onClick={isAllowedTo.setPagePermissions ? () => toggleModal("userAccess") : undefined}
|
|
452
|
+
/>
|
|
453
|
+
)}
|
|
454
|
+
{Fields}
|
|
455
|
+
</S.Wrapper>
|
|
416
456
|
</MainWrapper>
|
|
417
457
|
<ScheduleModal
|
|
418
|
-
isOpen={
|
|
419
|
-
toggleModal={
|
|
420
|
-
|
|
421
|
-
secondaryModalAction={secondaryScheduleModalAction}
|
|
458
|
+
isOpen={isOpen("schedule")}
|
|
459
|
+
toggleModal={() => toggleModal("schedule")}
|
|
460
|
+
onSchedule={handleSchedulePublication}
|
|
422
461
|
scheduleDate={scheduleDate}
|
|
423
462
|
setScheduleDate={setScheduleDate}
|
|
424
463
|
/>
|
|
425
464
|
<CancelScheduleModal
|
|
426
|
-
isOpen={
|
|
427
|
-
toggleModal={
|
|
428
|
-
|
|
429
|
-
secondaryModalAction={secondaryCancelScheduleModalAction}
|
|
465
|
+
isOpen={isOpen("cancelSchedule")}
|
|
466
|
+
toggleModal={() => toggleModal("cancelSchedule")}
|
|
467
|
+
onCancelSchedule={handleCancelSchedulePublication}
|
|
430
468
|
/>
|
|
431
469
|
<DeleteModal
|
|
432
|
-
isOpen={
|
|
433
|
-
toggleModal={
|
|
470
|
+
isOpen={isOpen("delete")}
|
|
471
|
+
toggleModal={() => toggleModal("delete")}
|
|
434
472
|
title={title || "this item"}
|
|
435
473
|
arePagesTranslated={arePagesTranslated}
|
|
436
474
|
deleteAllVersions={deleteAllVersions}
|
|
@@ -439,23 +477,30 @@ const Form = (props: IProps) => {
|
|
|
439
477
|
isDeleting={isDeleting}
|
|
440
478
|
/>
|
|
441
479
|
<RestoreModal
|
|
442
|
-
isOpen={
|
|
443
|
-
toggleModal={
|
|
480
|
+
isOpen={isOpen("restore")}
|
|
481
|
+
toggleModal={() => toggleModal("restore")}
|
|
444
482
|
{...{
|
|
445
483
|
isChild: false,
|
|
446
484
|
hasIssues: schemaVersion !== form?.schemaVersionTimestamp,
|
|
447
485
|
restorePage: handleRestorePage,
|
|
448
486
|
}}
|
|
449
487
|
/>
|
|
488
|
+
<RestrictionsModal
|
|
489
|
+
isOpen={isOpen("userAccess")}
|
|
490
|
+
toggleModal={() => toggleModal("userAccess")}
|
|
491
|
+
currentAccessGrants={form?.accessGrants}
|
|
492
|
+
onUpdateAccessGrants={handleUpdateAccessGrants}
|
|
493
|
+
isSaving={isSaving}
|
|
494
|
+
/>
|
|
450
495
|
</>
|
|
451
496
|
);
|
|
452
497
|
};
|
|
453
498
|
|
|
454
499
|
interface IProps {
|
|
455
|
-
schema:
|
|
456
|
-
form:
|
|
500
|
+
schema: ISchema;
|
|
501
|
+
form: (IStructuredDataContent & { deleted?: boolean; canBeTranslated?: boolean }) | null;
|
|
457
502
|
site: ISite | null;
|
|
458
|
-
currentStructuredData:
|
|
503
|
+
currentStructuredData: IStructuredData | null;
|
|
459
504
|
isSaving: boolean;
|
|
460
505
|
isLoading: boolean;
|
|
461
506
|
siteLanguages: ILanguage[];
|
|
@@ -466,8 +511,8 @@ interface IProps {
|
|
|
466
511
|
currentStructuredDataId: number | null;
|
|
467
512
|
skipReviewOnPublish?: boolean;
|
|
468
513
|
schemaVersion: string;
|
|
469
|
-
createStructuredDataContent: (payload: any) => Promise<boolean>;
|
|
470
|
-
updateStructuredDataContent: (payload: any) => Promise<boolean>;
|
|
514
|
+
createStructuredDataContent: (payload: IStructuredDataContent & Record<string, any>) => Promise<boolean>;
|
|
515
|
+
updateStructuredDataContent: (payload: IStructuredDataContent & Record<string, any>) => Promise<boolean>;
|
|
471
516
|
setLanguage(lang: { locale: string; id: number | null }): void;
|
|
472
517
|
getDataContent(id: number): Promise<void>;
|
|
473
518
|
setHistoryPush(path: string, isEditor?: boolean): void;
|
|
@@ -475,7 +520,7 @@ interface IProps {
|
|
|
475
520
|
setDataStatus(id: number, status: string): Promise<boolean>;
|
|
476
521
|
deleteStructuredDataContent(id: number): Promise<boolean>;
|
|
477
522
|
validateForm(publish?: boolean): Promise<boolean>;
|
|
478
|
-
setFormValues(form: any): Promise<void>;
|
|
523
|
+
setFormValues(form: IStructuredDataContent & Record<string, any>): Promise<void>;
|
|
479
524
|
setCurrentDataID(currentStructuredDataId: number | null): void;
|
|
480
525
|
restoreDataContent(dataID: number | number[]): Promise<boolean>;
|
|
481
526
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { FloatingNote } from "@ax/components";
|
|
2
|
+
|
|
1
3
|
import styled from "styled-components";
|
|
2
4
|
|
|
3
5
|
const Wrapper = styled.section`
|
|
@@ -30,4 +32,8 @@ const ModalFields = styled.div`
|
|
|
30
32
|
}
|
|
31
33
|
`;
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
const StyledFloatingNote = styled((props) => <FloatingNote {...props} />)`
|
|
36
|
+
width: 268px;
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
export { Wrapper, NotificationWrapper, ModalContent, ModalFields, StyledFloatingNote };
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
getStructuredDataTitle,
|
|
22
22
|
trimText,
|
|
23
23
|
} from "@ax/helpers";
|
|
24
|
-
import { useModals,
|
|
24
|
+
import { useModals, usePermissionsForPage } from "@ax/hooks";
|
|
25
25
|
import type {
|
|
26
26
|
IAvailableSites,
|
|
27
27
|
ICheck,
|
|
@@ -86,6 +86,7 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
86
86
|
publicationScheduled,
|
|
87
87
|
liveStatus,
|
|
88
88
|
haveDraftPage,
|
|
89
|
+
accessGrants,
|
|
89
90
|
} = globalPage;
|
|
90
91
|
|
|
91
92
|
const activeColumns = columns.filter((col) => col.show).map((col) => col.id);
|
|
@@ -99,13 +100,19 @@ const GlobalPageItem = (props: IGlobalPageItemProps): JSX.Element => {
|
|
|
99
100
|
|
|
100
101
|
const API_URL = process.env.GRIDDO_API_URL || process.env.REACT_APP_API_ENDPOINT;
|
|
101
102
|
|
|
102
|
-
const isAllowedTo =
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
const isAllowedTo = usePermissionsForPage(
|
|
104
|
+
"global",
|
|
105
|
+
globalPage.id,
|
|
106
|
+
{
|
|
107
|
+
duplicatePages: "global.globalData.duplicateGlobalData",
|
|
108
|
+
publishPages: "global.globalData.publishUnpublishAllGlobalData",
|
|
109
|
+
createPages: "global.globalData.createAllGlobalData",
|
|
110
|
+
deletePages: "global.globalData.deleteAllGlobalData",
|
|
111
|
+
editContentPages: "global.globalData.editAllGlobalData",
|
|
112
|
+
},
|
|
113
|
+
accessGrants,
|
|
114
|
+
pageLanguages,
|
|
115
|
+
);
|
|
109
116
|
|
|
110
117
|
const publishedTooltip: Record<string, string> = {
|
|
111
118
|
active: "Live",
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
getHumanLastModifiedDate,
|
|
11
11
|
getScheduleFormatDate,
|
|
12
12
|
} from "@ax/helpers";
|
|
13
|
-
import { useModal,
|
|
13
|
+
import { useModal, usePermissionsForPage } from "@ax/hooks";
|
|
14
14
|
import type {
|
|
15
15
|
ICheck,
|
|
16
16
|
IColumn,
|
|
@@ -25,7 +25,7 @@ import type {
|
|
|
25
25
|
} from "@ax/types";
|
|
26
26
|
|
|
27
27
|
import { DeleteModal } from "../../atoms";
|
|
28
|
-
import { getPermission } from "
|
|
28
|
+
import { getPermission } from "../../utils";
|
|
29
29
|
|
|
30
30
|
import * as S from "./style";
|
|
31
31
|
|
|
@@ -61,19 +61,25 @@ const StructuredDataItem = (props: IStructuredDataItemProps): JSX.Element => {
|
|
|
61
61
|
|
|
62
62
|
const isPrivateData = currentStructuredData?.private || false;
|
|
63
63
|
const isGlobal = !currentSiteInfo;
|
|
64
|
+
const { dataLanguages, publicationScheduled } = structuredData;
|
|
64
65
|
|
|
65
|
-
const isAllowedTo =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
const isAllowedTo = usePermissionsForPage(
|
|
67
|
+
currentSiteInfo?.id || "global",
|
|
68
|
+
structuredData.id,
|
|
69
|
+
{
|
|
70
|
+
duplicatePages: getPermission("duplicate", isGlobal, isPrivateData),
|
|
71
|
+
publishPages: getPermission("publish", isGlobal, isPrivateData),
|
|
72
|
+
createPages: getPermission("create", isGlobal, isPrivateData),
|
|
73
|
+
deletePages: getPermission("delete", isGlobal, isPrivateData),
|
|
74
|
+
},
|
|
75
|
+
structuredData.accessGrants,
|
|
76
|
+
dataLanguages,
|
|
77
|
+
);
|
|
71
78
|
|
|
72
79
|
const { isOpen: isDeleteOpen, toggleModal: toggleDeleteModal } = useModal();
|
|
73
80
|
const [deleteAllVersions, setDeleteAllVersions] = useState(false);
|
|
74
81
|
|
|
75
82
|
const { locale } = lang;
|
|
76
|
-
const { dataLanguages, publicationScheduled } = structuredData;
|
|
77
83
|
|
|
78
84
|
const isScheduledPub = !!publicationScheduled && structuredData.draft;
|
|
79
85
|
const activeColumns = columns.filter((col) => col.show).map((col) => col.id);
|
package/src/modules/StructuredData/{StructuredDataList/StructuredDataItem/utils.tsx → utils.tsx}
RENAMED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
const getPermission = (
|
|
1
|
+
const getPermission = (
|
|
2
|
+
type: "duplicate" | "create" | "delete" | "publish" | "edit",
|
|
3
|
+
isGlobal: boolean,
|
|
4
|
+
isPrivate: boolean,
|
|
5
|
+
) => {
|
|
2
6
|
const permissions: Record<
|
|
3
|
-
"duplicate" | "create" | "delete" | "publish",
|
|
7
|
+
"duplicate" | "create" | "delete" | "publish" | "edit",
|
|
4
8
|
Record<"global" | "site", Record<"default" | "private", string>>
|
|
5
9
|
> = {
|
|
6
10
|
duplicate: {
|
|
@@ -43,6 +47,16 @@ const getPermission = (type: "duplicate" | "create" | "delete" | "publish", isGl
|
|
|
43
47
|
private: "content.publishUnpublishPrivateContentTypes",
|
|
44
48
|
},
|
|
45
49
|
},
|
|
50
|
+
edit: {
|
|
51
|
+
global: {
|
|
52
|
+
default: "global.globalData.editAllGlobalData",
|
|
53
|
+
private: "global.globalData.editContentPrivateContentTypes",
|
|
54
|
+
},
|
|
55
|
+
site: {
|
|
56
|
+
default: "content.editContentPages",
|
|
57
|
+
private: "content.editContentPrivateContentTypes",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
46
60
|
};
|
|
47
61
|
|
|
48
62
|
const privateStr = isPrivate ? "private" : "default";
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from "react";
|
|
2
2
|
import QRCode from "react-qr-code";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { Modal, Pagination, Tag } from "@ax/components";
|
|
5
|
+
import { getStructuredDataTitle } from "@ax/helpers";
|
|
6
|
+
import type { IModal, IPage } from "@ax/types";
|
|
6
7
|
|
|
7
8
|
import * as S from "./style";
|
|
8
9
|
|
|
@@ -44,4 +45,61 @@ interface ILinkDeviceModalProps extends IModal {
|
|
|
44
45
|
token: string;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
const ProfilePagePermissionsList = ({ pages, testId, onPageChange }: IProfilePagePermissionsListProps) => {
|
|
49
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
50
|
+
const itemsPerPage = 10;
|
|
51
|
+
|
|
52
|
+
const totalPages = Math.ceil(pages.length / itemsPerPage);
|
|
53
|
+
const startIndex = (currentPage - 1) * itemsPerPage;
|
|
54
|
+
const endIndex = startIndex + itemsPerPage;
|
|
55
|
+
const paginatedPages = pages.slice(startIndex, endIndex);
|
|
56
|
+
|
|
57
|
+
const handlePageChange = (page: number) => {
|
|
58
|
+
setCurrentPage(page);
|
|
59
|
+
onPageChange?.();
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<>
|
|
64
|
+
<S.PageList data-testid={testId || "profile-pages-list"}>
|
|
65
|
+
{paginatedPages.map((page: IPage) => {
|
|
66
|
+
const siteName = page.site
|
|
67
|
+
? page.availableSites?.find((site) => site.id === page.site)?.name || ""
|
|
68
|
+
: "Global";
|
|
69
|
+
return (
|
|
70
|
+
<S.PageListItem key={page.id}>
|
|
71
|
+
<S.PageItemContent>
|
|
72
|
+
<S.PageItemHeader>
|
|
73
|
+
<S.PageItemType>{getStructuredDataTitle(page.structuredData) || "Page"}</S.PageItemType>
|
|
74
|
+
<S.PageItemSiteTag>
|
|
75
|
+
<Tag text={siteName} type="square" />
|
|
76
|
+
</S.PageItemSiteTag>
|
|
77
|
+
</S.PageItemHeader>
|
|
78
|
+
<S.PageItemTitle>{page.title}</S.PageItemTitle>
|
|
79
|
+
</S.PageItemContent>
|
|
80
|
+
</S.PageListItem>
|
|
81
|
+
);
|
|
82
|
+
})}
|
|
83
|
+
</S.PageList>
|
|
84
|
+
{totalPages > 1 && (
|
|
85
|
+
<S.PaginationWrapper>
|
|
86
|
+
<Pagination
|
|
87
|
+
size="S"
|
|
88
|
+
currPage={currentPage}
|
|
89
|
+
totalItems={pages.length}
|
|
90
|
+
itemsPerPage={itemsPerPage}
|
|
91
|
+
setPage={handlePageChange}
|
|
92
|
+
/>
|
|
93
|
+
</S.PaginationWrapper>
|
|
94
|
+
)}
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
interface IProfilePagePermissionsListProps {
|
|
100
|
+
pages: IPage[];
|
|
101
|
+
testId?: string;
|
|
102
|
+
onPageChange?: () => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { LinkDeviceModal, ProfilePagePermissionsList };
|