@griddo/ax 11.7.13 → 11.8.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 +3 -2
- package/src/GlobalStore.tsx +3 -0
- package/src/api/index.tsx +4 -0
- package/src/api/logs.tsx +97 -0
- package/src/api/navigation.tsx +1 -1
- package/src/api/pages.tsx +1 -1
- package/src/api/schemas.tsx +18 -0
- package/src/api/users.tsx +17 -0
- package/src/components/ConfigPanel/Form/ConnectedField/NavConnectedField/index.tsx +3 -2
- package/src/components/ConfigPanel/Form/index.tsx +3 -1
- package/src/components/ConfigPanel/index.tsx +3 -0
- package/src/components/Fields/SummaryButton/index.tsx +6 -4
- package/src/components/Fields/TimeField/style.tsx +0 -1
- package/src/components/Fields/TranslateButton/index.tsx +3 -0
- package/src/components/FloatingMenu/index.tsx +25 -1
- package/src/components/FloatingMenu/style.tsx +3 -2
- package/src/components/LanguageMenu/index.tsx +1 -1
- package/src/components/MainWrapper/AppBar/index.tsx +4 -3
- package/src/components/RestoreModal/index.tsx +51 -0
- package/src/components/RestoreModal/style.tsx +7 -0
- package/src/components/SearchField/index.tsx +1 -1
- package/src/components/SearchField/style.tsx +4 -4
- package/src/components/TableFilters/CheckGroupFilter/index.tsx +42 -5
- package/src/components/TableFilters/CheckGroupFilter/style.tsx +8 -1
- package/src/components/TableFilters/SiteFilter/index.tsx +26 -57
- package/src/components/Tag/index.tsx +6 -3
- package/src/components/Tag/style.tsx +2 -2
- package/src/components/index.tsx +2 -0
- package/src/containers/ActivityLog/actions.tsx +262 -0
- package/src/containers/ActivityLog/constants.tsx +6 -0
- package/src/containers/ActivityLog/index.tsx +4 -0
- package/src/containers/ActivityLog/interfaces.tsx +12 -0
- package/src/containers/ActivityLog/reducer.tsx +25 -0
- package/src/containers/Navigation/Defaults/actions.tsx +4 -3
- package/src/containers/StructuredData/actions.tsx +7 -4
- package/src/containers/StructuredData/interfaces.tsx +2 -8
- package/src/containers/StructuredData/reducer.tsx +2 -8
- package/src/containers/Users/actions.tsx +22 -19
- package/src/modules/ActivityLog/DetailModal/index.tsx +108 -0
- package/src/modules/ActivityLog/DetailModal/style.tsx +52 -0
- package/src/modules/ActivityLog/DownloadModal/index.tsx +104 -0
- package/src/modules/ActivityLog/DownloadModal/style.tsx +12 -0
- package/src/modules/ActivityLog/ItemGroup/index.tsx +27 -0
- package/src/modules/ActivityLog/ItemGroup/style.tsx +39 -0
- package/src/modules/ActivityLog/ItemLog/EventItem/index.tsx +167 -0
- package/src/modules/ActivityLog/ItemLog/EventItem/style.tsx +79 -0
- package/src/modules/ActivityLog/ItemLog/index.tsx +24 -0
- package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/index.tsx +170 -0
- package/src/modules/ActivityLog/ItemLogUser/UserItem/EventItem/style.tsx +79 -0
- package/src/modules/ActivityLog/ItemLogUser/UserItem/index.tsx +46 -0
- package/src/modules/ActivityLog/ItemLogUser/UserItem/style.tsx +60 -0
- package/src/modules/ActivityLog/ItemLogUser/index.tsx +25 -0
- package/src/modules/ActivityLog/LogFilters/ContentFilter/index.tsx +79 -0
- package/src/modules/ActivityLog/LogFilters/DateFilter/index.tsx +91 -0
- package/src/modules/ActivityLog/LogFilters/DateFilter/style.tsx +208 -0
- package/src/modules/ActivityLog/LogFilters/EventFilter/index.tsx +80 -0
- package/src/modules/ActivityLog/LogFilters/OrderFilter/index.tsx +49 -0
- package/src/modules/ActivityLog/LogFilters/OrderFilter/style.tsx +35 -0
- package/src/modules/ActivityLog/LogFilters/UserFilter/index.tsx +79 -0
- package/src/modules/ActivityLog/TableHeader/index.tsx +72 -0
- package/src/modules/ActivityLog/TableHeader/style.tsx +73 -0
- package/src/modules/ActivityLog/constants.tsx +10 -0
- package/src/modules/ActivityLog/hooks.tsx +53 -0
- package/src/modules/ActivityLog/index.tsx +313 -0
- package/src/modules/ActivityLog/style.tsx +57 -0
- package/src/modules/ActivityLog/utils.tsx +31 -0
- package/src/modules/Categories/CategoriesList/index.tsx +1 -1
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/Form/index.tsx +3 -0
- package/src/modules/Forms/FormEditor/Editor/FormConfigPanel/index.tsx +3 -0
- package/src/modules/Forms/FormEditor/Editor/index.tsx +5 -2
- package/src/modules/Forms/FormEditor/index.tsx +20 -3
- package/src/modules/GlobalEditor/Editor/index.tsx +3 -0
- package/src/modules/GlobalEditor/index.tsx +48 -9
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +3 -1
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -1
- package/src/modules/Navigation/Defaults/DefaultsEditor/index.tsx +45 -6
- package/src/modules/PageEditor/Editor/index.tsx +4 -1
- package/src/modules/PageEditor/index.tsx +46 -7
- package/src/modules/Redirects/BulkHeader/TableHeader/style.tsx +1 -7
- package/src/modules/StructuredData/Form/index.tsx +56 -7
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +2 -2
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/index.tsx +2 -8
- package/src/modules/StructuredData/StructuredDataList/hooks.tsx +9 -9
- package/src/modules/StructuredData/StructuredDataList/index.tsx +3 -4
- package/src/modules/Users/Roles/index.tsx +0 -2
- package/src/modules/Users/UserEdit/index.tsx +12 -28
- package/src/modules/Users/UserList/BulkHeader/TableHeader/style.tsx +1 -0
- package/src/modules/Users/UserList/UserItem/index.tsx +10 -25
- package/src/modules/Users/UserList/index.tsx +8 -10
- package/src/routes/multisite.tsx +9 -0
- package/src/themes/theme.json +2 -1
- package/src/types/forms.tsx +1 -0
- package/src/types/index.tsx +8 -0
- package/src/types/logs.tsx +12 -0
- package/src/components/TableFilters/SiteFilter/style.tsx +0 -28
|
@@ -12,7 +12,15 @@ import {
|
|
|
12
12
|
ISite,
|
|
13
13
|
} from "@ax/types";
|
|
14
14
|
import { structuredDataActions } from "@ax/containers/StructuredData";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
MainWrapper,
|
|
17
|
+
ErrorToast,
|
|
18
|
+
Notification,
|
|
19
|
+
Loading,
|
|
20
|
+
CancelScheduleModal,
|
|
21
|
+
ScheduleModal,
|
|
22
|
+
RestoreModal,
|
|
23
|
+
} from "@ax/components";
|
|
16
24
|
import { dateToString, getActivatedDataPacksIds, getDefaultTheme } from "@ax/helpers";
|
|
17
25
|
import { appActions } from "@ax/containers/App";
|
|
18
26
|
import { RouteLeavingGuard } from "@ax/guards";
|
|
@@ -50,6 +58,8 @@ const Form = (props: IProps) => {
|
|
|
50
58
|
skipReviewOnPublish,
|
|
51
59
|
setFormValues,
|
|
52
60
|
setCurrentDataID,
|
|
61
|
+
schemaVersion,
|
|
62
|
+
restoreDataContent,
|
|
53
63
|
} = props;
|
|
54
64
|
|
|
55
65
|
const [isNewStructuredData, setIsNewStructuredData] = useState(!currentStructuredDataId);
|
|
@@ -57,6 +67,7 @@ const Form = (props: IProps) => {
|
|
|
57
67
|
const [scheduleDate, setScheduleDate] = useState({ date: dateToString(new Date(), "yyy/MM/dd"), time: "12:00 am" });
|
|
58
68
|
const { isOpen: isScheduleOpen, toggleModal: toggleScheduleModal } = useModal();
|
|
59
69
|
const { isOpen: isCancelScheduleOpen, toggleModal: toggleCancelScheduleModal } = useModal();
|
|
70
|
+
const { isOpen: isRestoreOpen, toggleModal: toggleRestoreModal } = useModal();
|
|
60
71
|
const { isDirty, resetDirty, setIsDirty } = useIsDirty(form);
|
|
61
72
|
const path = site ? "/sites/pages" : "/data";
|
|
62
73
|
|
|
@@ -75,9 +86,12 @@ const Form = (props: IProps) => {
|
|
|
75
86
|
];
|
|
76
87
|
|
|
77
88
|
const activatedDataPacksIds = getActivatedDataPacksIds(activatedDataPacks);
|
|
78
|
-
const
|
|
89
|
+
const disabledDatapack =
|
|
79
90
|
currentStructuredData.local &&
|
|
80
91
|
!activatedDataPacksIds.some((pack: string) => currentStructuredData.dataPacks.includes(pack));
|
|
92
|
+
const isDeleted = !!form?.deleted;
|
|
93
|
+
const isDisabled = isDeleted || disabledDatapack;
|
|
94
|
+
|
|
81
95
|
const isDataTranslatable = currentStructuredData && currentStructuredData.translate;
|
|
82
96
|
const isScheduled = !!form && !!form.publicationScheduled;
|
|
83
97
|
const status = isScheduled
|
|
@@ -88,6 +102,12 @@ const Form = (props: IProps) => {
|
|
|
88
102
|
|
|
89
103
|
let title = "";
|
|
90
104
|
|
|
105
|
+
const packNotificationText =
|
|
106
|
+
"This content is part of disabled content type package. To edit it, you must first activate it.";
|
|
107
|
+
|
|
108
|
+
const deletedNotificationText =
|
|
109
|
+
"This content type has been deleted and can’t be edited. It will be permanently removed from the trash after 30 days.";
|
|
110
|
+
|
|
91
111
|
const theme = getDefaultTheme();
|
|
92
112
|
|
|
93
113
|
useEffect(() => {
|
|
@@ -194,9 +214,6 @@ const Form = (props: IProps) => {
|
|
|
194
214
|
</>
|
|
195
215
|
);
|
|
196
216
|
|
|
197
|
-
const packNotificationText =
|
|
198
|
-
"This content is part of disabled content type package. To edit it, you must first activate it.";
|
|
199
|
-
|
|
200
217
|
const handleClickNotification = () => {
|
|
201
218
|
getSiteDataPack(currentStructuredData.id);
|
|
202
219
|
setHistoryPush("/sites/settings/content-types", false);
|
|
@@ -264,7 +281,7 @@ const Form = (props: IProps) => {
|
|
|
264
281
|
};
|
|
265
282
|
|
|
266
283
|
const downArrowMenu = {
|
|
267
|
-
displayed:
|
|
284
|
+
displayed: !isDeleted,
|
|
268
285
|
button: getPublishButton(form?.draft),
|
|
269
286
|
options: [
|
|
270
287
|
{
|
|
@@ -316,6 +333,15 @@ const Form = (props: IProps) => {
|
|
|
316
333
|
}
|
|
317
334
|
};
|
|
318
335
|
|
|
336
|
+
const handleRestorePage = async () => {
|
|
337
|
+
if (!currentStructuredDataId) return;
|
|
338
|
+
const isRestored = await restoreDataContent(currentStructuredDataId);
|
|
339
|
+
if (isRestored) {
|
|
340
|
+
isRestoreOpen && toggleRestoreModal();
|
|
341
|
+
await getDataContent(currentStructuredDataId);
|
|
342
|
+
}
|
|
343
|
+
};
|
|
344
|
+
|
|
319
345
|
const mainScheduleModalAction = {
|
|
320
346
|
title: "Schedule",
|
|
321
347
|
onClick: handleSchedulePublication,
|
|
@@ -352,7 +378,7 @@ const Form = (props: IProps) => {
|
|
|
352
378
|
errors={errors}
|
|
353
379
|
scheduledPublication={form?.publicationScheduled}
|
|
354
380
|
>
|
|
355
|
-
{
|
|
381
|
+
{disabledDatapack && (
|
|
356
382
|
<S.NotificationWrapper>
|
|
357
383
|
<Notification
|
|
358
384
|
type="error"
|
|
@@ -362,6 +388,16 @@ const Form = (props: IProps) => {
|
|
|
362
388
|
/>
|
|
363
389
|
</S.NotificationWrapper>
|
|
364
390
|
)}
|
|
391
|
+
{isDeleted && (
|
|
392
|
+
<S.NotificationWrapper>
|
|
393
|
+
<Notification
|
|
394
|
+
type="error"
|
|
395
|
+
text={deletedNotificationText}
|
|
396
|
+
btnText="Restore content"
|
|
397
|
+
onClick={toggleRestoreModal}
|
|
398
|
+
/>
|
|
399
|
+
</S.NotificationWrapper>
|
|
400
|
+
)}
|
|
365
401
|
{notification && (
|
|
366
402
|
<S.NotificationWrapper>
|
|
367
403
|
<Notification
|
|
@@ -390,6 +426,15 @@ const Form = (props: IProps) => {
|
|
|
390
426
|
mainModalAction={mainCancelScheduleModalAction}
|
|
391
427
|
secondaryModalAction={secondaryCancelScheduleModalAction}
|
|
392
428
|
/>
|
|
429
|
+
<RestoreModal
|
|
430
|
+
isOpen={isRestoreOpen}
|
|
431
|
+
toggleModal={toggleRestoreModal}
|
|
432
|
+
{...{
|
|
433
|
+
isChild: false,
|
|
434
|
+
hasIssues: schemaVersion !== form?.schemaVersionTimestamp,
|
|
435
|
+
restorePage: handleRestorePage,
|
|
436
|
+
}}
|
|
437
|
+
/>
|
|
393
438
|
</>
|
|
394
439
|
);
|
|
395
440
|
};
|
|
@@ -408,6 +453,7 @@ interface IProps {
|
|
|
408
453
|
errors: IErrorItem[];
|
|
409
454
|
currentStructuredDataId: number | null;
|
|
410
455
|
skipReviewOnPublish?: boolean;
|
|
456
|
+
schemaVersion: string;
|
|
411
457
|
createStructuredDataContent: (payload: any) => Promise<boolean>;
|
|
412
458
|
updateStructuredDataContent: (payload: any) => Promise<boolean>;
|
|
413
459
|
setLanguage(lang: { locale: string; id: number | null }): void;
|
|
@@ -419,6 +465,7 @@ interface IProps {
|
|
|
419
465
|
validateForm(publish?: boolean): Promise<boolean>;
|
|
420
466
|
setFormValues(form: any): Promise<void>;
|
|
421
467
|
setCurrentDataID(currentStructuredDataId: number | null): void;
|
|
468
|
+
restoreDataContent(dataID: number | number[]): Promise<boolean>;
|
|
422
469
|
}
|
|
423
470
|
|
|
424
471
|
const mapStateToProps = (state: IRootState) => ({
|
|
@@ -435,6 +482,7 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
435
482
|
activatedDataPacks: state.dataPacks.activated,
|
|
436
483
|
errors: state.structuredData.errors,
|
|
437
484
|
skipReviewOnPublish: state.app.globalSettings.skipReviewOnPublish,
|
|
485
|
+
schemaVersion: state.structuredData.schemaVersion,
|
|
438
486
|
});
|
|
439
487
|
|
|
440
488
|
const mapDispatchToProps = {
|
|
@@ -449,6 +497,7 @@ const mapDispatchToProps = {
|
|
|
449
497
|
validateForm: structuredDataActions.validateForm,
|
|
450
498
|
setFormValues: structuredDataActions.setFormValues,
|
|
451
499
|
setCurrentDataID: structuredDataActions.setCurrentDataID,
|
|
500
|
+
restoreDataContent: structuredDataActions.restoreStructuredDataContent,
|
|
452
501
|
};
|
|
453
502
|
|
|
454
503
|
export default connect(mapStateToProps, mapDispatchToProps)(Form);
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
TranslationsFilter,
|
|
13
13
|
Tooltip,
|
|
14
14
|
} from "@ax/components";
|
|
15
|
-
import { IColumn, IQueryValue, ISchemaField
|
|
15
|
+
import { IColumn, IQueryValue, ISchemaField } from "@ax/types";
|
|
16
16
|
import { getGlobalPageTypes } from "@ax/helpers";
|
|
17
17
|
|
|
18
18
|
import * as S from "./style";
|
|
@@ -152,7 +152,7 @@ interface IProps {
|
|
|
152
152
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
153
153
|
sortedListStatus: { isAscending: boolean; sortedByDate: boolean; sortedByTitle: boolean; sortedByURL: boolean };
|
|
154
154
|
isAllPages: boolean;
|
|
155
|
-
filterValues:
|
|
155
|
+
filterValues: Record<string, IQueryValue[]>;
|
|
156
156
|
checkState: Record<string, boolean>;
|
|
157
157
|
categoryColumns: ISchemaField[];
|
|
158
158
|
columns: IColumn[];
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { BulkSelectionOptions } from "@ax/components";
|
|
3
|
-
import {
|
|
4
|
-
IColumn,
|
|
5
|
-
IQueryValue,
|
|
6
|
-
ISchemaField,
|
|
7
|
-
IStructuredDataQueryValues,
|
|
8
|
-
IStructuredDataSortedInitialState,
|
|
9
|
-
} from "@ax/types";
|
|
3
|
+
import { IColumn, IQueryValue, ISchemaField, IStructuredDataSortedInitialState } from "@ax/types";
|
|
10
4
|
import { usePermission } from "@ax/hooks";
|
|
11
5
|
import TableHeader from "./TableHeader";
|
|
12
6
|
|
|
@@ -108,7 +102,7 @@ interface IProps {
|
|
|
108
102
|
filterItems: (filterPointer: string, filtersSelected: IQueryValue[]) => void;
|
|
109
103
|
sortedListStatus: IStructuredDataSortedInitialState;
|
|
110
104
|
isAllPages: boolean;
|
|
111
|
-
filterValues:
|
|
105
|
+
filterValues: Record<string, IQueryValue[]>;
|
|
112
106
|
categoryColumns: ISchemaField[];
|
|
113
107
|
columns: IColumn[];
|
|
114
108
|
setColumns: (columns: IColumn[]) => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState } from "react";
|
|
2
|
-
import { IQueryValue, IStructuredData,
|
|
2
|
+
import { IQueryValue, IStructuredData, IStructuredDataSortedInitialState } from "@ax/types";
|
|
3
3
|
|
|
4
4
|
const useSortedListStatus = (): IUseSortedListStatus => {
|
|
5
5
|
const sortedInitialState: IStructuredDataSortedInitialState = {
|
|
@@ -19,10 +19,10 @@ const useSortedListStatus = (): IUseSortedListStatus => {
|
|
|
19
19
|
|
|
20
20
|
const useFilterQuery = (
|
|
21
21
|
currentStructuredData: IStructuredData | null,
|
|
22
|
-
values: Record<string,
|
|
22
|
+
values: Record<string, Record<string, IQueryValue[]>> | null
|
|
23
23
|
): IUseFilterQuery => {
|
|
24
24
|
const structuredDataType = currentStructuredData ? currentStructuredData.id : "all";
|
|
25
|
-
const initialQueryValues:
|
|
25
|
+
const initialQueryValues: Record<string, IQueryValue[]> = {
|
|
26
26
|
types: [{ value: "all", label: "All" }],
|
|
27
27
|
translated: [{ value: "all", label: "All" }],
|
|
28
28
|
liveStatus: [{ value: "all", label: "All" }],
|
|
@@ -32,7 +32,7 @@ const useFilterQuery = (
|
|
|
32
32
|
related: [{ value: "all", label: "All" }],
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const getFilterQuery = (filterValues:
|
|
35
|
+
const getFilterQuery = (filterValues: Record<string, IQueryValue[]>): string => {
|
|
36
36
|
const { types, translated, liveStatus, order, filterSites, categories, related } = filterValues;
|
|
37
37
|
let filterQuery = "";
|
|
38
38
|
|
|
@@ -45,11 +45,11 @@ const useFilterQuery = (
|
|
|
45
45
|
return !stringValues.length
|
|
46
46
|
? filterQuery
|
|
47
47
|
: filterQuery.length
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
? filterQuery.concat(`&${pointer}=${stringValues}`)
|
|
49
|
+
: `&${pointer}=${stringValues}`;
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
const isNotInitialValue = (pointer: keyof
|
|
52
|
+
const isNotInitialValue = (pointer: keyof Record<string, IQueryValue[]>) => {
|
|
53
53
|
return filterValues[pointer] && initialQueryValues[pointer] !== filterValues[pointer];
|
|
54
54
|
};
|
|
55
55
|
|
|
@@ -65,7 +65,7 @@ const useFilterQuery = (
|
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
const initState = values ? values : { all: initialQueryValues };
|
|
68
|
-
const [state, setState] = useState<Record<string,
|
|
68
|
+
const [state, setState] = useState<Record<string, Record<string, IQueryValue[]>>>(initState);
|
|
69
69
|
|
|
70
70
|
const initQuery = values && values[structuredDataType] ? getFilterQuery(values[structuredDataType]) : "";
|
|
71
71
|
const [query, setQuery] = useState(initQuery);
|
|
@@ -118,7 +118,7 @@ interface IUseSortedListStatus {
|
|
|
118
118
|
interface IUseFilterQuery {
|
|
119
119
|
setFiltersSelection(pointer: string, filter: IQueryValue[], isAscendent?: boolean): void;
|
|
120
120
|
resetFilterQuery(): void;
|
|
121
|
-
filterValues: Record<string,
|
|
121
|
+
filterValues: Record<string, Record<string, IQueryValue[]>>;
|
|
122
122
|
query: string;
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
IPage,
|
|
17
17
|
ICheck,
|
|
18
18
|
IColumn,
|
|
19
|
-
IStructuredDataQueryValues,
|
|
20
19
|
IQueryValue,
|
|
21
20
|
ISchemaField,
|
|
22
21
|
IExportDataParams,
|
|
@@ -780,7 +779,7 @@ interface IDispatchProps {
|
|
|
780
779
|
getStructuredDataContents(params: IGetStructuredDataParams): Promise<void>;
|
|
781
780
|
setSelectedStructuredData(id: string, scope: string): void;
|
|
782
781
|
deleteDataContent(dataID: number[]): Promise<boolean>;
|
|
783
|
-
restoreDataContent(dataID: number | number[]):
|
|
782
|
+
restoreDataContent(dataID: number | number[]): Promise<boolean>;
|
|
784
783
|
setDataStatus(dataID: number[], status: string): void;
|
|
785
784
|
setFilter(filter: string | null): void;
|
|
786
785
|
setCurrentPageID(currentPageID: number | null): ISetCurrentPageIDAction;
|
|
@@ -795,7 +794,7 @@ interface IDispatchProps {
|
|
|
795
794
|
getAnalytics(siteId?: number | null): Promise<void>;
|
|
796
795
|
setCurrentDataID(id: number | null): void;
|
|
797
796
|
resetCurrentSiteErrorPages: () => Promise<void>;
|
|
798
|
-
setContentFilters(contentFilters: Record<string,
|
|
797
|
+
setContentFilters(contentFilters: Record<string, Record<string, IQueryValue[]>> | null): void;
|
|
799
798
|
checkUserSession(): Promise<void>;
|
|
800
799
|
updateCurrentSearch(query: string): Promise<void>;
|
|
801
800
|
resetCurrentData(): Promise<void>;
|
|
@@ -817,7 +816,7 @@ interface ICategoriesProps {
|
|
|
817
816
|
currentSitePages: IPage[];
|
|
818
817
|
currentSiteErrorPages: number[];
|
|
819
818
|
skipReviewOnPublish?: boolean;
|
|
820
|
-
contentFilters: Record<string,
|
|
819
|
+
contentFilters: Record<string, Record<string, IQueryValue[]>> | null;
|
|
821
820
|
currentSearch: string;
|
|
822
821
|
}
|
|
823
822
|
|
|
@@ -232,13 +232,11 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
232
232
|
const mapDispatchToProps = {
|
|
233
233
|
getRoles: usersActions.getRoles,
|
|
234
234
|
activateRoles: usersActions.activateRoles,
|
|
235
|
-
resetUserData: usersActions.resetUserData,
|
|
236
235
|
setHistoryPush: appActions.setHistoryPush,
|
|
237
236
|
};
|
|
238
237
|
|
|
239
238
|
interface IDispatchProps {
|
|
240
239
|
getRoles(params?: IGetRoles): Promise<void>;
|
|
241
|
-
resetUserData(): void;
|
|
242
240
|
setHistoryPush(route: string): void;
|
|
243
241
|
activateRoles(params: IActivateRole): Promise<boolean>;
|
|
244
242
|
}
|
|
@@ -4,20 +4,20 @@ import { connect } from "react-redux";
|
|
|
4
4
|
import { appActions } from "@ax/containers/App";
|
|
5
5
|
import { usersActions } from "@ax/containers/Users";
|
|
6
6
|
import { Loading, MainWrapper, Modal, Toast } from "@ax/components";
|
|
7
|
-
import { IRootState, ISite,
|
|
7
|
+
import { IRootState, ISite, IUser } from "@ax/types";
|
|
8
8
|
import { useModal, useShouldBeSaved, useToast } from "@ax/hooks";
|
|
9
9
|
import UserForm from "../UserForm";
|
|
10
10
|
|
|
11
11
|
import * as S from "./style";
|
|
12
12
|
|
|
13
13
|
const UserEdit = (props: IProps) => {
|
|
14
|
-
const { user, updateUser, isSaving, isLoading, deleteUser, currentUser, setHistoryPush, site,
|
|
14
|
+
const { user, updateUser, isSaving, isLoading, deleteUser, currentUser, setHistoryPush, site, removeUserFromSite } =
|
|
15
|
+
props;
|
|
15
16
|
|
|
16
17
|
const { timezone } = user;
|
|
17
18
|
const initForm = { ...user };
|
|
18
19
|
if (!timezone) initForm.timezone = "Europe/Madrid";
|
|
19
20
|
const isSiteView = !!site;
|
|
20
|
-
const sitesIds = sites.map((site: ISite) => site.id);
|
|
21
21
|
const usersRoute = isSiteView ? "/sites/users" : "users";
|
|
22
22
|
const [form, setForm] = useState<IUser>(initForm);
|
|
23
23
|
const { isOpen, toggleModal } = useModal();
|
|
@@ -71,27 +71,10 @@ const UserEdit = (props: IProps) => {
|
|
|
71
71
|
}
|
|
72
72
|
: undefined;
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
if (hasAll) {
|
|
77
|
-
const oldRoleSites = form.roles.filter((siteRole: ISiteRoles) => siteRole.siteId !== "all");
|
|
78
|
-
const roleSites = sitesIds
|
|
79
|
-
.filter((siteId: number) => siteId !== site?.id)
|
|
80
|
-
.map((siteId: number) => {
|
|
81
|
-
return { siteId, roles: hasAll.roles };
|
|
82
|
-
});
|
|
83
|
-
return [...oldRoleSites, ...roleSites];
|
|
84
|
-
} else {
|
|
85
|
-
return form.roles.filter((siteRole: ISiteRoles) => siteRole.siteId !== site?.id);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const removeUserFromSite = async () => {
|
|
90
|
-
if (!user.id) return;
|
|
91
|
-
const updatedSites = getUpdatedSites();
|
|
92
|
-
const formWithUpdatedSites = { ...form, roles: updatedSites };
|
|
74
|
+
const handleRemoveUserFromSite = async () => {
|
|
75
|
+
if (!user.id || !site) return;
|
|
93
76
|
|
|
94
|
-
const updated = await
|
|
77
|
+
const updated = await removeUserFromSite(user.id, site.id);
|
|
95
78
|
if (updated) {
|
|
96
79
|
setHistoryPush(usersRoute);
|
|
97
80
|
}
|
|
@@ -99,7 +82,7 @@ const UserEdit = (props: IProps) => {
|
|
|
99
82
|
|
|
100
83
|
const mainDeleteAction = {
|
|
101
84
|
title: isSiteView ? "Remove user" : "Delete User",
|
|
102
|
-
onClick: isSiteView ?
|
|
85
|
+
onClick: isSiteView ? handleRemoveUserFromSite : handleDelete,
|
|
103
86
|
};
|
|
104
87
|
|
|
105
88
|
const secondaryDeleteAction = { title: "Cancel", onClick: toggleModal };
|
|
@@ -161,8 +144,9 @@ const UserEdit = (props: IProps) => {
|
|
|
161
144
|
size="S"
|
|
162
145
|
>
|
|
163
146
|
<S.ModalContent>
|
|
164
|
-
Before editing an user, <strong>select the user
|
|
165
|
-
selecting any permissions, the user
|
|
147
|
+
Before editing an user, <strong>select the user's permissions and site access</strong>. If you proceed
|
|
148
|
+
without selecting any permissions, the user{" "}
|
|
149
|
+
<strong>won't have access to anything or view any content</strong>.
|
|
166
150
|
</S.ModalContent>
|
|
167
151
|
</Modal>
|
|
168
152
|
{isVisible && <Toast {...toastProps} />}
|
|
@@ -173,7 +157,6 @@ const UserEdit = (props: IProps) => {
|
|
|
173
157
|
const mapStateToProps = (state: IRootState) => ({
|
|
174
158
|
user: state.users.userForm,
|
|
175
159
|
site: state.sites.currentSiteInfo,
|
|
176
|
-
sites: state.sites.sites,
|
|
177
160
|
isSaving: state.app.isSaving,
|
|
178
161
|
isLoading: state.app.isLoading,
|
|
179
162
|
currentUser: state.users.currentUser,
|
|
@@ -183,12 +166,14 @@ interface IDispatchProps {
|
|
|
183
166
|
setHistoryPush(path: string): void;
|
|
184
167
|
updateUser(id: number, data: IUser, isProfile: boolean, isList?: boolean): Promise<boolean>;
|
|
185
168
|
deleteUser(id: number): Promise<boolean>;
|
|
169
|
+
removeUserFromSite(userID: number, siteID: number): Promise<boolean>;
|
|
186
170
|
}
|
|
187
171
|
|
|
188
172
|
const mapDispatchToProps = {
|
|
189
173
|
setHistoryPush: appActions.setHistoryPush,
|
|
190
174
|
updateUser: usersActions.updateUser,
|
|
191
175
|
deleteUser: usersActions.deleteUser,
|
|
176
|
+
removeUserFromSite: usersActions.removeUserFromSite,
|
|
192
177
|
};
|
|
193
178
|
|
|
194
179
|
interface IProfileProps {
|
|
@@ -197,7 +182,6 @@ interface IProfileProps {
|
|
|
197
182
|
isSaving: boolean;
|
|
198
183
|
isLoading: boolean;
|
|
199
184
|
currentUser: IUser | null;
|
|
200
|
-
sites: ISite[];
|
|
201
185
|
}
|
|
202
186
|
|
|
203
187
|
type IProps = IProfileProps & IDispatchProps;
|
|
@@ -18,12 +18,13 @@ const UserItem = (props: IUserItemProps): JSX.Element => {
|
|
|
18
18
|
onChange,
|
|
19
19
|
onClick,
|
|
20
20
|
deleteUser,
|
|
21
|
-
updateUser,
|
|
22
21
|
resendInvitation,
|
|
23
22
|
isSiteView = false,
|
|
24
23
|
roles,
|
|
25
24
|
hoverCheck,
|
|
26
25
|
toggleDeleteToast,
|
|
26
|
+
removeUserFromSite,
|
|
27
|
+
getUsers,
|
|
27
28
|
} = props;
|
|
28
29
|
|
|
29
30
|
const { isOpen, toggleModal } = useModal();
|
|
@@ -36,8 +37,6 @@ const UserItem = (props: IUserItemProps): JSX.Element => {
|
|
|
36
37
|
|
|
37
38
|
const handleOnChange = (value: ICheck) => onChange(value);
|
|
38
39
|
|
|
39
|
-
const sitesIds = sites.map((site: ISite) => site.id);
|
|
40
|
-
|
|
41
40
|
const handleDeleteUser = async () => {
|
|
42
41
|
const deleted = user.id ? await deleteUser(user.id) : false;
|
|
43
42
|
if (deleted) {
|
|
@@ -78,35 +77,20 @@ const UserItem = (props: IUserItemProps): JSX.Element => {
|
|
|
78
77
|
|
|
79
78
|
const menuOptions = user.status === "invited" ? [resendOption, deleteOption] : [deleteOption];
|
|
80
79
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
if (hasAll) {
|
|
84
|
-
const oldRoleSites = user.roles.filter((siteRole: ISiteRoles) => siteRole.siteId !== "all");
|
|
85
|
-
const roleSites = sitesIds
|
|
86
|
-
.filter((site: number) => site !== siteId)
|
|
87
|
-
.map((siteId: number) => {
|
|
88
|
-
return { siteId, roles: hasAll.roles };
|
|
89
|
-
});
|
|
90
|
-
return [...oldRoleSites, ...roleSites];
|
|
91
|
-
} else {
|
|
92
|
-
return user.roles.filter((siteRole: ISiteRoles) => siteRole.siteId !== siteId);
|
|
93
|
-
}
|
|
94
|
-
};
|
|
80
|
+
const handleRemoveUserFromSite = async () => {
|
|
81
|
+
if (!user.id || !siteId) return;
|
|
95
82
|
|
|
96
|
-
|
|
97
|
-
if (!user.id) return;
|
|
98
|
-
const updatedSites = getUpdatedSites();
|
|
99
|
-
const updatedUser = { ...user, roles: updatedSites };
|
|
100
|
-
const updated = await updateUser(user.id, updatedUser, false, true);
|
|
83
|
+
const updated = await removeUserFromSite(user.id, siteId);
|
|
101
84
|
if (updated) {
|
|
102
85
|
toggleModal();
|
|
103
86
|
toggleDeleteToast();
|
|
87
|
+
getUsers();
|
|
104
88
|
}
|
|
105
89
|
};
|
|
106
90
|
|
|
107
91
|
const mainDeleteAction = {
|
|
108
92
|
title: isSiteView ? "Remove user" : "Delete user",
|
|
109
|
-
onClick: isSiteView ?
|
|
93
|
+
onClick: isSiteView ? handleRemoveUserFromSite : handleDeleteUser,
|
|
110
94
|
};
|
|
111
95
|
|
|
112
96
|
const secondaryDeleteAction = { title: "Cancel", onClick: toggleModal };
|
|
@@ -253,18 +237,19 @@ interface IProps {
|
|
|
253
237
|
onChange: (value: ICheck) => void;
|
|
254
238
|
onClick: (id: number) => void;
|
|
255
239
|
toggleDeleteToast: () => void;
|
|
240
|
+
getUsers: () => void;
|
|
256
241
|
}
|
|
257
242
|
|
|
258
243
|
const mapDispatchToProps = {
|
|
259
244
|
deleteUser: usersActions.deleteUser,
|
|
260
|
-
updateUser: usersActions.updateUser,
|
|
261
245
|
resendInvitation: usersActions.resendInvitation,
|
|
246
|
+
removeUserFromSite: usersActions.removeUserFromSite,
|
|
262
247
|
};
|
|
263
248
|
|
|
264
249
|
interface IDispatchProps {
|
|
265
|
-
updateUser(id: number, data: any, isProfile: boolean, isList?: boolean): Promise<boolean>;
|
|
266
250
|
deleteUser(id: number): Promise<boolean>;
|
|
267
251
|
resendInvitation(id: number): Promise<boolean>;
|
|
252
|
+
removeUserFromSite(userID: number, siteID: number): Promise<boolean>;
|
|
268
253
|
}
|
|
269
254
|
|
|
270
255
|
export type IUserItemProps = IProps & IDispatchProps;
|
|
@@ -35,7 +35,6 @@ const UserList = (props: IUserListProps): JSX.Element => {
|
|
|
35
35
|
currentNavItem,
|
|
36
36
|
setHistoryPush,
|
|
37
37
|
getUser,
|
|
38
|
-
resetUserData,
|
|
39
38
|
sites,
|
|
40
39
|
deleteUser,
|
|
41
40
|
removeUsersBulk,
|
|
@@ -77,13 +76,14 @@ const UserList = (props: IUserListProps): JSX.Element => {
|
|
|
77
76
|
setHoverCheck,
|
|
78
77
|
} = useBulkSelection(usersIds);
|
|
79
78
|
|
|
79
|
+
const handleGetUsers = async () => {
|
|
80
|
+
const query = searchQuery ? (filterQuery ? `&query=${searchQuery}` : `?query=${searchQuery}`) : "";
|
|
81
|
+
const currentFilterQuerySite =
|
|
82
|
+
isSiteView && filterQuery ? `${filterQuery}&site=${currentSiteInfo.id}` : filterQuery;
|
|
83
|
+
await getUsers({ filterQuery: currentFilterQuerySite, query }, currentSiteInfo?.id);
|
|
84
|
+
};
|
|
85
|
+
|
|
80
86
|
useEffect(() => {
|
|
81
|
-
const handleGetUsers = async () => {
|
|
82
|
-
const query = searchQuery ? (filterQuery ? `&query=${searchQuery}` : `?query=${searchQuery}`) : "";
|
|
83
|
-
const currentFilterQuerySite =
|
|
84
|
-
isSiteView && filterQuery ? `${filterQuery}&site=${currentSiteInfo.id}` : filterQuery;
|
|
85
|
-
await getUsers({ filterQuery: currentFilterQuerySite, query }, currentSiteInfo?.id);
|
|
86
|
-
};
|
|
87
87
|
handleGetUsers();
|
|
88
88
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89
89
|
}, [filterQuery, searchQuery]);
|
|
@@ -175,7 +175,6 @@ const UserList = (props: IUserListProps): JSX.Element => {
|
|
|
175
175
|
|
|
176
176
|
const handleClick = (id: number | null) => async () => {
|
|
177
177
|
if (id) {
|
|
178
|
-
resetUserData();
|
|
179
178
|
await getUser(id);
|
|
180
179
|
setHistoryPush(`${BASE_URL}/edit`);
|
|
181
180
|
}
|
|
@@ -269,6 +268,7 @@ const UserList = (props: IUserListProps): JSX.Element => {
|
|
|
269
268
|
roles={roles}
|
|
270
269
|
toggleDeleteToast={handleToggleToast}
|
|
271
270
|
hoverCheck={checkState.hoverCheck}
|
|
271
|
+
getUsers={handleGetUsers}
|
|
272
272
|
/>
|
|
273
273
|
);
|
|
274
274
|
})
|
|
@@ -313,7 +313,6 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
313
313
|
const mapDispatchToProps = {
|
|
314
314
|
getUsers: usersActions.getUsers,
|
|
315
315
|
getUser: usersActions.getUser,
|
|
316
|
-
resetUserData: usersActions.resetUserData,
|
|
317
316
|
setHistoryPush: appActions.setHistoryPush,
|
|
318
317
|
deleteUser: usersActions.deleteUser,
|
|
319
318
|
removeUsersBulk: sitesActions.removeUsersBulk,
|
|
@@ -324,7 +323,6 @@ const mapDispatchToProps = {
|
|
|
324
323
|
interface IDispatchProps {
|
|
325
324
|
getUsers(params: any, siteID?: number | null): Promise<void>;
|
|
326
325
|
getUser(id: number): Promise<void>;
|
|
327
|
-
resetUserData(): void;
|
|
328
326
|
setHistoryPush(route: string): void;
|
|
329
327
|
deleteUser(id: number[]): Promise<boolean>;
|
|
330
328
|
removeUsersBulk(siteId: number, users: number[]): void;
|
package/src/routes/multisite.tsx
CHANGED
|
@@ -15,6 +15,7 @@ import FormList from "../modules/Forms/FormList";
|
|
|
15
15
|
import FormEditor from "../modules/Forms/FormEditor";
|
|
16
16
|
import FormCategoriesList from "../modules/Forms/FormCategoriesList";
|
|
17
17
|
import MediaGallery from "../modules/MediaGallery";
|
|
18
|
+
import ActivityLog from "../modules/ActivityLog";
|
|
18
19
|
|
|
19
20
|
export default [
|
|
20
21
|
{
|
|
@@ -214,4 +215,12 @@ export default [
|
|
|
214
215
|
hideNav: true,
|
|
215
216
|
permission: ["global.forms.createForms", "global.forms.editForms"],
|
|
216
217
|
},
|
|
218
|
+
{
|
|
219
|
+
path: "/log",
|
|
220
|
+
component: ActivityLog,
|
|
221
|
+
name: "Log",
|
|
222
|
+
showInNav: true,
|
|
223
|
+
icon: "log",
|
|
224
|
+
permission: "global.accessToActivityLog",
|
|
225
|
+
},
|
|
217
226
|
];
|
package/src/themes/theme.json
CHANGED
package/src/types/forms.tsx
CHANGED
package/src/types/index.tsx
CHANGED
|
@@ -14,6 +14,7 @@ import { IAnalyticsState } from "@ax/containers/Analytics/reducer";
|
|
|
14
14
|
import { IIntegrationsState } from "@ax/containers/Integrations/reducer";
|
|
15
15
|
import { IFileDriveState } from "@ax/containers/FileDrive/reducer";
|
|
16
16
|
import { IFormsState } from "@ax/containers/Forms/reducer";
|
|
17
|
+
import { IActivityLogState } from "@ax/containers/ActivityLog/reducer";
|
|
17
18
|
|
|
18
19
|
import {
|
|
19
20
|
GetFormsParams,
|
|
@@ -40,6 +41,8 @@ import {
|
|
|
40
41
|
IImageFolder,
|
|
41
42
|
} from "./files";
|
|
42
43
|
|
|
44
|
+
import { ILogItemsByDay, ILogItemsByUser, ILogContent } from "./logs";
|
|
45
|
+
|
|
43
46
|
export interface IBreadcrumbItem {
|
|
44
47
|
editorID: number;
|
|
45
48
|
component: string;
|
|
@@ -123,6 +126,7 @@ export interface IAPIPage {
|
|
|
123
126
|
originalLanguage: number;
|
|
124
127
|
language: number;
|
|
125
128
|
publicationScheduled: string | null;
|
|
129
|
+
schemaVersionTimestamp: string;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
export interface IPage extends IAPIPage {
|
|
@@ -253,6 +257,7 @@ export interface IRootState {
|
|
|
253
257
|
integrations: IIntegrationsState;
|
|
254
258
|
fileDrive: IFileDriveState;
|
|
255
259
|
forms: IFormsState;
|
|
260
|
+
activityLog: IActivityLogState;
|
|
256
261
|
}
|
|
257
262
|
|
|
258
263
|
export interface IStyledProps {
|
|
@@ -549,6 +554,7 @@ export interface IStructuredDataContent {
|
|
|
549
554
|
fromPage: boolean;
|
|
550
555
|
dataPacks: string[];
|
|
551
556
|
publicationScheduled: string | null;
|
|
557
|
+
schemaVersionTimestamp: string;
|
|
552
558
|
}
|
|
553
559
|
|
|
554
560
|
export interface IStructuredDataCategory {
|
|
@@ -1137,3 +1143,5 @@ export type {
|
|
|
1137
1143
|
IImage,
|
|
1138
1144
|
IImageFolder,
|
|
1139
1145
|
};
|
|
1146
|
+
|
|
1147
|
+
export type { ILogItemsByDay, ILogItemsByUser, ILogContent };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LogActivityGroupedDayDTO, LogActivityGroupedUserDTO, PaginationResponse } from "@griddo/api-types";
|
|
2
|
+
|
|
3
|
+
export type ILogItemsByUser = Omit<PaginationResponse<LogActivityGroupedUserDTO<LogActivityGroupedUserDTO[]>>, "page">;
|
|
4
|
+
|
|
5
|
+
export type ILogItemsByDay = Omit<PaginationResponse<LogActivityGroupedDayDTO>, "page">;
|
|
6
|
+
|
|
7
|
+
export type ILogContent = {
|
|
8
|
+
id: number;
|
|
9
|
+
title: string | undefined;
|
|
10
|
+
contentType: string | undefined;
|
|
11
|
+
type: string;
|
|
12
|
+
};
|