@griddo/ax 11.7.13-rc.0 → 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
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "11.
|
|
4
|
+
"version": "11.8.0-rc.0",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Diego M. Béjar <diego.bejar@secuoyas.com>",
|
|
@@ -159,6 +159,7 @@
|
|
|
159
159
|
"@babel/preset-env": "7.26.9",
|
|
160
160
|
"@babel/preset-react": "7.26.3",
|
|
161
161
|
"@babel/preset-typescript": "7.26.0",
|
|
162
|
+
"@griddo/api-types": "^1.0.12",
|
|
162
163
|
"@types/jest": "27.5.2",
|
|
163
164
|
"@types/redux-mock-store": "1.0.3",
|
|
164
165
|
"@typescript-eslint/eslint-plugin": "7.18.0",
|
|
@@ -223,5 +224,5 @@
|
|
|
223
224
|
"publishConfig": {
|
|
224
225
|
"access": "public"
|
|
225
226
|
},
|
|
226
|
-
"gitHead": "
|
|
227
|
+
"gitHead": "130006b9b240d0f92e0950041a0d1012af33e556"
|
|
227
228
|
}
|
package/src/GlobalStore.tsx
CHANGED
|
@@ -22,6 +22,7 @@ import { analyticsReducer, analyticsInitialState } from "./containers/Analytics/
|
|
|
22
22
|
import { integrationsReducer, integrationsInitialState } from "./containers/Integrations/reducer";
|
|
23
23
|
import { fileDriveReducer, fileDriveInitialState } from "./containers/FileDrive/reducer";
|
|
24
24
|
import { formsReducer, formsInitialState } from "./containers/Forms/reducer";
|
|
25
|
+
import { activityLogReducer, activityLogInitialState } from "./containers/ActivityLog/reducer";
|
|
25
26
|
import { LOGOUT } from "./containers/App/constants";
|
|
26
27
|
|
|
27
28
|
import { IRootState } from "@ax/types";
|
|
@@ -58,6 +59,7 @@ export class GlobalStore {
|
|
|
58
59
|
integrations: integrationsReducer as Reducer<any, Action<any>>,
|
|
59
60
|
fileDrive: fileDriveReducer as Reducer<any, Action<any>>,
|
|
60
61
|
forms: formsReducer as Reducer<any, Action<any>>,
|
|
62
|
+
activityLog: activityLogReducer as Reducer<any, Action<any>>,
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
const rootReducer = (state: IRootState | undefined, action: any) => {
|
|
@@ -81,6 +83,7 @@ export class GlobalStore {
|
|
|
81
83
|
integrations: integrationsInitialState,
|
|
82
84
|
fileDrive: fileDriveInitialState,
|
|
83
85
|
forms: formsInitialState,
|
|
86
|
+
activityLog: activityLogInitialState,
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
|
package/src/api/index.tsx
CHANGED
|
@@ -20,6 +20,8 @@ import roles from "./roles";
|
|
|
20
20
|
import integrations from "./integrations";
|
|
21
21
|
import forms from "./forms";
|
|
22
22
|
import folders from "./folders";
|
|
23
|
+
import logs from "./logs";
|
|
24
|
+
import schemas from "./schemas";
|
|
23
25
|
|
|
24
26
|
export {
|
|
25
27
|
sites,
|
|
@@ -44,4 +46,6 @@ export {
|
|
|
44
46
|
integrations,
|
|
45
47
|
forms,
|
|
46
48
|
folders,
|
|
49
|
+
logs,
|
|
50
|
+
schemas,
|
|
47
51
|
};
|
package/src/api/logs.tsx
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { AxiosResponse } from "axios";
|
|
2
|
+
import { template } from "./config";
|
|
3
|
+
import { IServiceConfig, sendRequest } from "./utils";
|
|
4
|
+
import { LogActivityExportRequest, LogActivityPaginationRequest } from "@griddo/api-types";
|
|
5
|
+
|
|
6
|
+
const SERVICES: { [key: string]: IServiceConfig } = {
|
|
7
|
+
GET_LOG_ACTIVITY: {
|
|
8
|
+
...template,
|
|
9
|
+
endpoint: "/logs/activity-timeline",
|
|
10
|
+
method: "GET",
|
|
11
|
+
},
|
|
12
|
+
GET_LOG_ACTIVITY_BY_DAY: {
|
|
13
|
+
...template,
|
|
14
|
+
endpoint: "/logs/activity-grouped-day",
|
|
15
|
+
method: "GET",
|
|
16
|
+
},
|
|
17
|
+
GET_LOG_ACTIVITY_BY_USER: {
|
|
18
|
+
...template,
|
|
19
|
+
endpoint: "/logs/activity-grouped-user",
|
|
20
|
+
method: "GET",
|
|
21
|
+
},
|
|
22
|
+
GET_LOG_EVENT_TYPES: {
|
|
23
|
+
...template,
|
|
24
|
+
endpoint: "/logs/activity-events-type",
|
|
25
|
+
method: "GET",
|
|
26
|
+
},
|
|
27
|
+
LOG_EXPORT: {
|
|
28
|
+
...template,
|
|
29
|
+
endpoint: "/logs/activity-timeline/export",
|
|
30
|
+
method: "POST",
|
|
31
|
+
responseType: "blob",
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const getLogActivityTimeline = async (params: LogActivityPaginationRequest): Promise<AxiosResponse> => {
|
|
36
|
+
const { host, endpoint } = SERVICES.GET_LOG_ACTIVITY;
|
|
37
|
+
|
|
38
|
+
const paramsUrl = new URLSearchParams();
|
|
39
|
+
|
|
40
|
+
for (const [clave, valor] of Object.entries(params)) {
|
|
41
|
+
if (valor !== undefined && valor !== null) {
|
|
42
|
+
paramsUrl.append(clave, String(valor));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
SERVICES.GET_LOG_ACTIVITY.dynamicUrl = `${host}${endpoint}?${paramsUrl.toString()}`;
|
|
47
|
+
|
|
48
|
+
return sendRequest(SERVICES.GET_LOG_ACTIVITY);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const getLogActivityTimelineByDay = async (params: LogActivityPaginationRequest): Promise<AxiosResponse> => {
|
|
52
|
+
const { host, endpoint } = SERVICES.GET_LOG_ACTIVITY_BY_DAY;
|
|
53
|
+
|
|
54
|
+
const paramsUrl = new URLSearchParams();
|
|
55
|
+
|
|
56
|
+
for (const [clave, valor] of Object.entries(params)) {
|
|
57
|
+
if (valor !== undefined && valor !== null) {
|
|
58
|
+
paramsUrl.append(clave, String(valor));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
SERVICES.GET_LOG_ACTIVITY_BY_DAY.dynamicUrl = `${host}${endpoint}?${paramsUrl.toString()}`;
|
|
63
|
+
|
|
64
|
+
return sendRequest(SERVICES.GET_LOG_ACTIVITY_BY_DAY);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const getLogActivityTimelineByUser = async (params: LogActivityPaginationRequest): Promise<AxiosResponse> => {
|
|
68
|
+
const { host, endpoint } = SERVICES.GET_LOG_ACTIVITY_BY_USER;
|
|
69
|
+
|
|
70
|
+
const paramsUrl = new URLSearchParams();
|
|
71
|
+
|
|
72
|
+
for (const [clave, valor] of Object.entries(params)) {
|
|
73
|
+
if (valor !== undefined && valor !== null) {
|
|
74
|
+
paramsUrl.append(clave, String(valor));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
SERVICES.GET_LOG_ACTIVITY_BY_USER.dynamicUrl = `${host}${endpoint}?${paramsUrl.toString()}`;
|
|
79
|
+
|
|
80
|
+
return sendRequest(SERVICES.GET_LOG_ACTIVITY_BY_USER);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const getLogActivityEventTypes = async (): Promise<AxiosResponse> => {
|
|
84
|
+
return sendRequest(SERVICES.GET_LOG_EVENT_TYPES);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const logExport = async (data: LogActivityExportRequest): Promise<AxiosResponse> => {
|
|
88
|
+
return sendRequest(SERVICES.LOG_EXPORT, { ...data });
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export default {
|
|
92
|
+
getLogActivityTimeline,
|
|
93
|
+
getLogActivityTimelineByDay,
|
|
94
|
+
getLogActivityTimelineByUser,
|
|
95
|
+
getLogActivityEventTypes,
|
|
96
|
+
logExport,
|
|
97
|
+
};
|
package/src/api/navigation.tsx
CHANGED
|
@@ -77,7 +77,7 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
77
77
|
const getNavigation = (id: number) => {
|
|
78
78
|
const { host, endpoint } = SERVICES.GET_NAVIGATION;
|
|
79
79
|
|
|
80
|
-
SERVICES.GET_NAVIGATION.dynamicUrl = `${host}${endpoint}${id}`;
|
|
80
|
+
SERVICES.GET_NAVIGATION.dynamicUrl = `${host}${endpoint}${id}?skipDelete=false`;
|
|
81
81
|
|
|
82
82
|
return sendRequest(SERVICES.GET_NAVIGATION);
|
|
83
83
|
};
|
package/src/api/pages.tsx
CHANGED
|
@@ -165,7 +165,7 @@ const deletePage = async (pageID: number) => {
|
|
|
165
165
|
return sendRequest(SERVICES.DELETE_PAGE);
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
-
const restorePage = async (id: number
|
|
168
|
+
const restorePage = async (id: number) => {
|
|
169
169
|
const {
|
|
170
170
|
host,
|
|
171
171
|
endpoint: [prefix, suffix],
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { template } from "./config";
|
|
2
|
+
import { IServiceConfig, sendRequest } from "./utils";
|
|
3
|
+
|
|
4
|
+
const SERVICES: { [key: string]: IServiceConfig } = {
|
|
5
|
+
SCHEMAS_SELECT_ALL: {
|
|
6
|
+
...template,
|
|
7
|
+
endpoint: "/schemas/select/all",
|
|
8
|
+
method: "GET",
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const getSchemasSelectAll = async () => {
|
|
13
|
+
return sendRequest(SERVICES.SCHEMAS_SELECT_ALL);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
getSchemasSelectAll,
|
|
18
|
+
};
|
package/src/api/users.tsx
CHANGED
|
@@ -47,6 +47,11 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
47
47
|
endpoint: ["/user/", "/resend"],
|
|
48
48
|
method: "PUT",
|
|
49
49
|
},
|
|
50
|
+
REMOVE_USER_SITE: {
|
|
51
|
+
...template,
|
|
52
|
+
endpoint: ["/user/", "/site/"],
|
|
53
|
+
method: "DELETE",
|
|
54
|
+
},
|
|
50
55
|
};
|
|
51
56
|
|
|
52
57
|
const getUsers = async (params: any) => {
|
|
@@ -133,6 +138,17 @@ const resendInvitation = async (id: number) => {
|
|
|
133
138
|
return sendRequest(SERVICES.RESEND);
|
|
134
139
|
};
|
|
135
140
|
|
|
141
|
+
const removeUserFromSite = async (userID: number, siteID: number) => {
|
|
142
|
+
const {
|
|
143
|
+
host,
|
|
144
|
+
endpoint: [prefix, suffix],
|
|
145
|
+
} = SERVICES.REMOVE_USER_SITE;
|
|
146
|
+
|
|
147
|
+
SERVICES.REMOVE_USER_SITE.dynamicUrl = `${host}${prefix}${userID}${suffix}${siteID}`;
|
|
148
|
+
|
|
149
|
+
return sendRequest(SERVICES.REMOVE_USER_SITE);
|
|
150
|
+
};
|
|
151
|
+
|
|
136
152
|
export default {
|
|
137
153
|
getUsers,
|
|
138
154
|
getSiteUsers,
|
|
@@ -143,4 +159,5 @@ export default {
|
|
|
143
159
|
deleteUser,
|
|
144
160
|
deleteUserBulk,
|
|
145
161
|
resendInvitation,
|
|
162
|
+
removeUserFromSite,
|
|
146
163
|
};
|
|
@@ -27,6 +27,7 @@ const NavConnectedField = (props: any): JSX.Element => {
|
|
|
27
27
|
disabled,
|
|
28
28
|
moduleCopy,
|
|
29
29
|
themeElements,
|
|
30
|
+
isReadOnly,
|
|
30
31
|
} = props;
|
|
31
32
|
|
|
32
33
|
const updateValue = (key: string, value: any) => {
|
|
@@ -44,7 +45,7 @@ const NavConnectedField = (props: any): JSX.Element => {
|
|
|
44
45
|
const defaultNavId = currentDefaultNav && currentDefaultNav.id;
|
|
45
46
|
const selectedContentId = selectedContent && selectedContent.id;
|
|
46
47
|
const isDefaultNav = defaultNavId === selectedContentId;
|
|
47
|
-
const isDisabled = isSetAsDefaultField && isDefaultNav;
|
|
48
|
+
const isDisabled = (isSetAsDefaultField && isDefaultNav) || isReadOnly;
|
|
48
49
|
const isConditional = field.type === "ConditionalField";
|
|
49
50
|
|
|
50
51
|
let isTemplateActivated = true;
|
|
@@ -64,7 +65,7 @@ const NavConnectedField = (props: any): JSX.Element => {
|
|
|
64
65
|
selectedContent,
|
|
65
66
|
isTemplateActivated,
|
|
66
67
|
theme,
|
|
67
|
-
disabled,
|
|
68
|
+
disabled || isDisabled,
|
|
68
69
|
site
|
|
69
70
|
);
|
|
70
71
|
}
|
|
@@ -22,6 +22,7 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
22
22
|
footer,
|
|
23
23
|
isEditLive,
|
|
24
24
|
headerHeight,
|
|
25
|
+
isDisabled,
|
|
25
26
|
} = props;
|
|
26
27
|
|
|
27
28
|
const isAllowedToEditSitePages = usePermission("content.editContentPages");
|
|
@@ -58,7 +59,7 @@ export const Form = (props: IFormProps): JSX.Element => {
|
|
|
58
59
|
isGlobal={isGlobal}
|
|
59
60
|
theme={theme}
|
|
60
61
|
setHistoryPush={setHistoryPush}
|
|
61
|
-
isReadOnly={isEditLive}
|
|
62
|
+
isReadOnly={isEditLive || isDisabled}
|
|
62
63
|
/>
|
|
63
64
|
);
|
|
64
65
|
};
|
|
@@ -149,6 +150,7 @@ export interface IFormProps {
|
|
|
149
150
|
footer?: number | null;
|
|
150
151
|
isEditLive?: boolean;
|
|
151
152
|
headerHeight: number;
|
|
153
|
+
isDisabled: boolean;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
156
|
export default Form;
|
|
@@ -36,6 +36,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
36
36
|
header,
|
|
37
37
|
footer,
|
|
38
38
|
isEditLive,
|
|
39
|
+
isDisabled = false,
|
|
39
40
|
} = props;
|
|
40
41
|
|
|
41
42
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
@@ -91,6 +92,7 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
91
92
|
footer={footer}
|
|
92
93
|
isEditLive={isEditLive}
|
|
93
94
|
headerHeight={headerHeight}
|
|
95
|
+
isDisabled={isDisabled}
|
|
94
96
|
/>
|
|
95
97
|
);
|
|
96
98
|
}
|
|
@@ -136,6 +138,7 @@ export interface IStateProps {
|
|
|
136
138
|
header?: number | null;
|
|
137
139
|
footer?: number | null;
|
|
138
140
|
isEditLive?: boolean;
|
|
141
|
+
isDisabled?: boolean;
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
export default ConfigPanel;
|
|
@@ -6,7 +6,7 @@ import { pageEditorActions } from "@ax/containers/PageEditor";
|
|
|
6
6
|
import * as S from "./style";
|
|
7
7
|
|
|
8
8
|
const SummaryButton = (props: ISummaryButtonProps): JSX.Element => {
|
|
9
|
-
const { autoSummary, getPageSummary } = props;
|
|
9
|
+
const { autoSummary, getPageSummary, disabled } = props;
|
|
10
10
|
|
|
11
11
|
const initialState = {
|
|
12
12
|
isLoading: false,
|
|
@@ -30,8 +30,8 @@ const SummaryButton = (props: ISummaryButtonProps): JSX.Element => {
|
|
|
30
30
|
const buttonText = state.isLoading
|
|
31
31
|
? "Processing..."
|
|
32
32
|
: state.isClicked
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
? "Regenerate SEO data with AI"
|
|
34
|
+
: "Generate SEO data with AI";
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
37
|
<>
|
|
@@ -47,11 +47,12 @@ const SummaryButton = (props: ISummaryButtonProps): JSX.Element => {
|
|
|
47
47
|
onClick={handleClick}
|
|
48
48
|
icon={!state.isLoading ? "Ia" : undefined}
|
|
49
49
|
loader={state.isLoading ? "circle" : undefined}
|
|
50
|
+
disabled={disabled}
|
|
50
51
|
>
|
|
51
52
|
{buttonText}
|
|
52
53
|
</S.StyledButton>
|
|
53
54
|
</S.ButtonWrapper>
|
|
54
|
-
{state.error && <S.ErrorText>We
|
|
55
|
+
{state.error && <S.ErrorText>We're having problems. Please try again in a few minutes.</S.ErrorText>}
|
|
55
56
|
</S.Wrapper>
|
|
56
57
|
) : (
|
|
57
58
|
<></>
|
|
@@ -62,6 +63,7 @@ const SummaryButton = (props: ISummaryButtonProps): JSX.Element => {
|
|
|
62
63
|
|
|
63
64
|
export interface ISummaryButtonProps {
|
|
64
65
|
autoSummary: boolean;
|
|
66
|
+
disabled: boolean;
|
|
65
67
|
getPageSummary: () => Promise<boolean>;
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -3,7 +3,6 @@ import styled from "styled-components";
|
|
|
3
3
|
const FieldWrapper = styled.div<{ error?: boolean; disabled?: boolean }>`
|
|
4
4
|
display: flex;
|
|
5
5
|
height: ${(p) => p.theme.spacing.l};
|
|
6
|
-
max-width: ${(p) => `calc(8 * ${p.theme.spacing.l})`};
|
|
7
6
|
min-width: ${(p) => `calc(5 * ${p.theme.spacing.l})`};
|
|
8
7
|
width: 100%;
|
|
9
8
|
border: 1px solid
|
|
@@ -26,6 +26,7 @@ const TranslateButton = (props: ITranslateButtonProps): JSX.Element => {
|
|
|
26
26
|
isFormIATranslated,
|
|
27
27
|
getFormTranslation,
|
|
28
28
|
setIsFormTranslated,
|
|
29
|
+
disabled,
|
|
29
30
|
} = props;
|
|
30
31
|
|
|
31
32
|
const getContent = (type: "page" | "data" | "form") => {
|
|
@@ -99,6 +100,7 @@ const TranslateButton = (props: ITranslateButtonProps): JSX.Element => {
|
|
|
99
100
|
onClick={toggleModal}
|
|
100
101
|
icon={!state.isLoading ? "Ia" : undefined}
|
|
101
102
|
loader={state.isLoading ? "circle" : undefined}
|
|
103
|
+
disabled={disabled}
|
|
102
104
|
>
|
|
103
105
|
{buttonText}
|
|
104
106
|
</S.StyledButton>
|
|
@@ -136,6 +138,7 @@ export interface ITranslateButtonProps {
|
|
|
136
138
|
isFormIATranslated: boolean;
|
|
137
139
|
contentType: "page" | "data" | "form";
|
|
138
140
|
formContent: FormContent | null;
|
|
141
|
+
disabled: boolean;
|
|
139
142
|
getPageTranslation: (langID: number) => Promise<boolean>;
|
|
140
143
|
getDataContentTranslation: (langID: number) => Promise<boolean>;
|
|
141
144
|
getFormTranslation: (langID: number) => Promise<boolean>;
|
|
@@ -14,6 +14,10 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
|
|
|
14
14
|
isCheckGroup,
|
|
15
15
|
reactiveToHover,
|
|
16
16
|
offset,
|
|
17
|
+
hasMargin = true,
|
|
18
|
+
fixedWidth,
|
|
19
|
+
actionOnClose,
|
|
20
|
+
disabled = false,
|
|
17
21
|
} = props;
|
|
18
22
|
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
19
23
|
const buttonRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -40,6 +44,10 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
|
|
|
40
44
|
return;
|
|
41
45
|
}
|
|
42
46
|
|
|
47
|
+
if (actionOnClose) {
|
|
48
|
+
actionOnClose();
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
setOpen(false);
|
|
44
52
|
};
|
|
45
53
|
|
|
@@ -49,8 +57,16 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
|
|
|
49
57
|
isChecked && setOpen(false);
|
|
50
58
|
};
|
|
51
59
|
|
|
60
|
+
const closeWhenApply = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
61
|
+
const target = e.target as HTMLSpanElement;
|
|
62
|
+
if (target.innerHTML === "Apply") {
|
|
63
|
+
setOpen(false);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
52
67
|
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
|
|
53
68
|
e.stopPropagation();
|
|
69
|
+
if (disabled) return;
|
|
54
70
|
const buttonWasClicked = buttonRef.current?.contains(e.target as HTMLElement);
|
|
55
71
|
const optionWasSelected = isOpen && menuOptionsRef.current?.contains(e.target as HTMLElement);
|
|
56
72
|
|
|
@@ -61,6 +77,8 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
|
|
|
61
77
|
if (optionWasSelected) {
|
|
62
78
|
closeOnSelect ? (isCheckGroup ? closeWhenChecked(e) : setOpen(!isOpen)) : setOpen(true);
|
|
63
79
|
}
|
|
80
|
+
|
|
81
|
+
closeWhenApply(e);
|
|
64
82
|
};
|
|
65
83
|
|
|
66
84
|
const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) =>
|
|
@@ -90,7 +108,9 @@ const FloatingMenu = (props: IFloatingProps): JSX.Element => {
|
|
|
90
108
|
offset={offset}
|
|
91
109
|
data-testid="floating-menu-wrapper"
|
|
92
110
|
>
|
|
93
|
-
<S.Menu
|
|
111
|
+
<S.Menu hasMargin={hasMargin} width={fixedWidth}>
|
|
112
|
+
{children}
|
|
113
|
+
</S.Menu>
|
|
94
114
|
</S.MenuWrapper>
|
|
95
115
|
)}
|
|
96
116
|
</S.Wrapper>
|
|
@@ -106,6 +126,10 @@ export interface IFloatingProps {
|
|
|
106
126
|
isCheckGroup?: boolean;
|
|
107
127
|
reactiveToHover?: boolean;
|
|
108
128
|
offset?: number;
|
|
129
|
+
hasMargin?: boolean;
|
|
130
|
+
fixedWidth?: number;
|
|
131
|
+
actionOnClose?(): void;
|
|
132
|
+
disabled?: boolean;
|
|
109
133
|
}
|
|
110
134
|
|
|
111
135
|
export default FloatingMenu;
|
|
@@ -16,8 +16,9 @@ const MenuWrapper = styled.div<{ isInAppBar?: boolean; position: string; offset?
|
|
|
16
16
|
${(p) => p.position}: ${(p) => (p.offset ? `${p.offset}px` : "0")};
|
|
17
17
|
`;
|
|
18
18
|
|
|
19
|
-
const Menu = styled.div
|
|
20
|
-
padding: ${(p) => p.theme.spacing.xs} 0;
|
|
19
|
+
const Menu = styled.div<{ hasMargin: boolean; width?: number }>`
|
|
20
|
+
padding: ${(p) => (p.hasMargin ? `${p.theme.spacing.xs} 0` : `${p.theme.spacing.xs} 0 0 0`)};
|
|
21
|
+
width: ${(p) => (p.width ? `${p.width}px` : "auto")};
|
|
21
22
|
max-width: ${(p) => `calc(${p.theme.spacing.l} * 5)`};
|
|
22
23
|
min-width: ${(p) => `calc(${p.theme.spacing.m} * 7)`};
|
|
23
24
|
background: ${(p) => p.theme.color.uiBackground02};
|
|
@@ -63,7 +63,7 @@ const LanguageMenu = (props: ILanguageMenuProps): JSX.Element => {
|
|
|
63
63
|
|
|
64
64
|
return (
|
|
65
65
|
<S.ActionMenu data-testid="language-menu">
|
|
66
|
-
{availableLanguages && availableLanguages.map((item) => languageMenuItem(item))}
|
|
66
|
+
{!!availableLanguages.length && availableLanguages.map((item) => languageMenuItem(item))}
|
|
67
67
|
</S.ActionMenu>
|
|
68
68
|
);
|
|
69
69
|
};
|
|
@@ -93,7 +93,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
93
93
|
<Flag name={language.locale} size="24" />
|
|
94
94
|
</S.FlagWrapper>
|
|
95
95
|
<S.LanguageTextWrapper data-testid="language-locale-label">{language.locale}</S.LanguageTextWrapper>
|
|
96
|
-
<DownArrowButton />
|
|
96
|
+
{!!availableLanguages?.length && <DownArrowButton />}
|
|
97
97
|
</>
|
|
98
98
|
) : (
|
|
99
99
|
<></>
|
|
@@ -218,6 +218,7 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
218
218
|
isInAppBar={true}
|
|
219
219
|
position="left"
|
|
220
220
|
offset={rightButton || rightLineButton ? 0 : -85}
|
|
221
|
+
disabled={!availableLanguages.length}
|
|
221
222
|
>
|
|
222
223
|
<LanguageMenu
|
|
223
224
|
language={language.locale}
|
|
@@ -262,13 +263,13 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
262
263
|
type="button"
|
|
263
264
|
buttonStyle="line"
|
|
264
265
|
onClick={rightLineButton.action}
|
|
265
|
-
|
|
266
|
+
{...rightLineButton}
|
|
266
267
|
>
|
|
267
268
|
{rightLineButton.label}
|
|
268
269
|
</Button>
|
|
269
270
|
)}
|
|
270
271
|
{rightButton && (
|
|
271
|
-
<Button className="button" type="button" onClick={rightButton.action}
|
|
272
|
+
<Button className="button" type="button" onClick={rightButton.action} {...rightButton}>
|
|
272
273
|
{rightButton.label}
|
|
273
274
|
</Button>
|
|
274
275
|
)}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import { IModal } from "@ax/types";
|
|
4
|
+
import { Modal } from "@ax/components";
|
|
5
|
+
|
|
6
|
+
import * as S from "./style";
|
|
7
|
+
|
|
8
|
+
const RestorePageModal = (props: IRestorePageProps): JSX.Element => {
|
|
9
|
+
const { isOpen, toggleModal, isChild, hasIssues, restorePage } = props;
|
|
10
|
+
|
|
11
|
+
const buttonText = hasIssues ? "Ok, restore it" : "Yes, restore it";
|
|
12
|
+
|
|
13
|
+
const mainRestoreAction = { title: buttonText, onClick: restorePage };
|
|
14
|
+
const secondaryModalAction = { title: "Cancel", onClick: toggleModal };
|
|
15
|
+
|
|
16
|
+
const title = hasIssues ? "Possible compatibility issues" : "Restore item";
|
|
17
|
+
const modalText = hasIssues ? (
|
|
18
|
+
<>
|
|
19
|
+
Restoring deleted items <strong>may cause conflicts if their structure has changed since removal</strong>. Please
|
|
20
|
+
review the restored content after recovery.
|
|
21
|
+
</>
|
|
22
|
+
) : (
|
|
23
|
+
<>
|
|
24
|
+
You are about to restore this item.{" "}
|
|
25
|
+
<strong>It will reappear on your site exactly as it was before it was deleted.</strong> Are you sure you want to
|
|
26
|
+
continue?
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Modal
|
|
32
|
+
isOpen={isOpen}
|
|
33
|
+
hide={toggleModal}
|
|
34
|
+
title={title}
|
|
35
|
+
secondaryAction={secondaryModalAction}
|
|
36
|
+
mainAction={mainRestoreAction}
|
|
37
|
+
size="S"
|
|
38
|
+
height={240}
|
|
39
|
+
isChild={isChild}
|
|
40
|
+
>
|
|
41
|
+
<S.ModalContent>{modalText}</S.ModalContent>
|
|
42
|
+
</Modal>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
interface IRestorePageProps extends IModal {
|
|
47
|
+
hasIssues: boolean;
|
|
48
|
+
restorePage(): void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default RestorePageModal;
|
|
@@ -12,8 +12,8 @@ const FieldWrapper = styled.div<{ closeOnInactive: boolean; disabled: boolean }>
|
|
|
12
12
|
p.disabled
|
|
13
13
|
? p.theme.color.interactiveDisabled
|
|
14
14
|
: p.closeOnInactive
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
? p.theme.color.interactive01
|
|
16
|
+
: p.theme.color.uiLine};
|
|
17
17
|
border-width: ${(p) => (p.closeOnInactive ? "0 0 1px" : "1px")};
|
|
18
18
|
border-style: solid;
|
|
19
19
|
border-radius: ${(p) => (p.closeOnInactive ? 0 : p.theme.radii.s)};
|
|
@@ -26,13 +26,13 @@ const Input = styled.input<{
|
|
|
26
26
|
closeOnInactive: boolean;
|
|
27
27
|
disabled: boolean;
|
|
28
28
|
small?: boolean;
|
|
29
|
-
inputSize: "M" | "S" | "XS";
|
|
29
|
+
inputSize: "M" | "S" | "XS" | "XXS";
|
|
30
30
|
}>`
|
|
31
31
|
${(p) => p.theme.textStyle.fieldContent};
|
|
32
32
|
color: ${(p) => p.theme.color.textHighEmphasis};
|
|
33
33
|
background-color: ${(p) => p.theme.color.interactiveBackground};
|
|
34
34
|
flex: 1 1 auto;
|
|
35
|
-
height: ${(p) => (p.inputSize === "XS" ? "40px" : p.theme.spacing.l)};
|
|
35
|
+
height: ${(p) => (p.inputSize === "XXS" ? "32px" : p.inputSize === "XS" ? "40px" : p.theme.spacing.l)};
|
|
36
36
|
padding-left: ${(p) => p.theme.spacing.s};
|
|
37
37
|
border: none;
|
|
38
38
|
border-radius: ${(p) => (p.closeOnInactive ? 0 : p.theme.radii.s)};
|