@griddo/ax 1.73.28 → 1.74.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/config/griddo-config/index.js +24 -3
- package/config/webpackSchemas.config.js +3 -5
- package/package.json +3 -2
- package/scripts/griddo-sync-schemas.js +4 -3
- package/src/__mocks__/axios/SitesList.ts +84 -0
- package/src/__mocks__/store/SitesList.ts +714 -0
- package/src/__tests__/components/Avatar/Avatar.test.tsx +119 -0
- package/src/__tests__/components/Avatar/__snapshots__/Avatar.test.tsx.snap +61 -0
- package/src/__tests__/components/Fields/ReferenceField/ReferenceField.test.tsx +10 -10
- package/src/__tests__/components/LanguageMenu/LanguageMenu.test.tsx +221 -0
- package/src/__tests__/components/Loading/Loading.test.tsx +23 -0
- package/src/__tests__/components/Login/Login.test.tsx +247 -0
- package/src/__tests__/components/Login/RecoveryModal/RecoveryModal.test.tsx +185 -0
- package/src/__tests__/components/TableFilters/LiveFilter/LiveFilter.test.tsx +6 -6
- package/src/__tests__/modules/Sites/Sites.test.tsx +259 -0
- package/src/__tests__/modules/Sites/SitesList/ListView/BulkHeader/BulkHeader.test.tsx +51 -0
- package/src/__tests__/modules/Sites/SitesList/SitesList.test.tsx +896 -0
- package/src/api/sites.tsx +43 -4
- package/src/components/ActionMenu/index.tsx +1 -1
- package/src/components/Avatar/index.tsx +4 -4
- package/src/components/Browser/index.tsx +27 -20
- package/src/components/BrowserContent/index.tsx +6 -0
- package/src/components/Fields/AsyncSelect/style.tsx +6 -3
- package/src/components/Fields/CheckField/index.tsx +1 -0
- package/src/components/Fields/DateField/style.tsx +3 -1
- package/src/components/Fields/HeadingField/index.tsx +14 -5
- package/src/components/Fields/ImageField/index.tsx +3 -0
- package/src/components/Fields/ImageField/style.tsx +2 -2
- package/src/components/Fields/Select/style.tsx +2 -0
- package/src/components/Fields/SliderField/index.tsx +2 -1
- package/src/components/Fields/TextField/index.tsx +1 -0
- package/src/components/Icon/components/BulletList.js +16 -0
- package/src/components/Icon/components/Grid2.js +16 -0
- package/src/components/Icon/svgs/Bullet-list.svg +3 -0
- package/src/components/Icon/svgs/Grid-2.svg +3 -0
- package/src/components/IconAction/index.tsx +4 -2
- package/src/components/IconAction/style.tsx +8 -2
- package/src/components/LanguageMenu/index.tsx +13 -6
- package/src/components/Login/RecoveryModal/index.tsx +5 -4
- package/src/components/Login/index.tsx +13 -3
- package/src/components/Login/style.tsx +12 -25
- package/src/components/Pagination/style.tsx +1 -1
- package/src/components/SearchField/index.tsx +9 -1
- package/src/components/SideModal/style.tsx +8 -8
- package/src/components/TableFilters/LastAccessFilter/index.tsx +52 -0
- package/src/components/TableFilters/LastAccessFilter/style.tsx +31 -0
- package/src/components/TableFilters/LiveFilter/index.tsx +7 -5
- package/src/components/TableFilters/NameFilter/index.tsx +4 -3
- package/src/components/TableFilters/index.tsx +2 -0
- package/src/components/TableList/index.tsx +2 -1
- package/src/components/TableList/style.tsx +2 -2
- package/src/components/index.tsx +2 -0
- package/src/containers/App/actions.tsx +5 -0
- package/src/containers/App/interfaces.tsx +1 -1
- package/src/containers/App/reducer.tsx +1 -1
- package/src/containers/Navigation/Defaults/actions.tsx +3 -1
- package/src/containers/PageEditor/actions.tsx +6 -3
- package/src/containers/Sites/actions.tsx +76 -11
- package/src/containers/Sites/constants.tsx +2 -0
- package/src/containers/Sites/interfaces.tsx +12 -0
- package/src/containers/Sites/reducer.tsx +8 -0
- package/src/helpers/schemas.tsx +27 -1
- package/src/hooks/iframe.ts +56 -0
- package/src/hooks/index.tsx +3 -0
- package/src/modules/Content/index.tsx +4 -3
- package/src/modules/FramePreview/index.tsx +25 -39
- package/src/modules/GlobalEditor/Editor/index.tsx +2 -2
- package/src/modules/GlobalEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/DefaultsBrowser/index.tsx +11 -7
- package/src/modules/Navigation/Defaults/DefaultsEditor/Editor/index.tsx +4 -3
- package/src/modules/Navigation/Menus/List/Table/SidePanel/Form/index.tsx +1 -0
- package/src/modules/PageEditor/Editor/index.tsx +2 -2
- package/src/modules/PageEditor/PageBrowser/index.tsx +16 -4
- package/src/modules/PageEditor/index.tsx +8 -7
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/Editor/ConfigPanel/Field/index.tsx +12 -11
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/TemplateConfig/TemplateEditor/index.tsx +3 -17
- package/src/modules/Settings/ContentTypes/DataPacks/Config/Form/style.tsx +2 -10
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/index.tsx +72 -0
- package/src/modules/Sites/SitesList/GridView/GridHeaderFilter/style.tsx +32 -0
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/index.tsx +17 -27
- package/src/modules/Sites/SitesList/{SiteItem → GridView/GridSiteItem}/style.tsx +14 -25
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/index.tsx +64 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/TableHeader/style.tsx +50 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/index.tsx +75 -0
- package/src/modules/Sites/SitesList/ListView/BulkHeader/style.tsx +8 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/index.tsx +200 -0
- package/src/modules/Sites/SitesList/ListView/ListSiteItem/style.tsx +112 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/index.tsx +50 -0
- package/src/modules/Sites/SitesList/RecentSiteItem/style.tsx +28 -0
- package/src/modules/Sites/SitesList/SiteModal/index.tsx +4 -3
- package/src/modules/Sites/SitesList/atoms.tsx +47 -0
- package/src/modules/Sites/SitesList/hooks.tsx +102 -0
- package/src/modules/Sites/SitesList/index.tsx +272 -19
- package/src/modules/Sites/SitesList/style.tsx +157 -4
- package/src/modules/Sites/SitesList/utils.tsx +33 -0
- package/src/modules/Sites/index.tsx +6 -11
- package/src/modules/StructuredData/StructuredDataList/BulkHeader/TableHeader/index.tsx +1 -1
- package/src/types/index.tsx +25 -2
package/src/api/sites.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosResponse } from "axios";
|
|
2
|
-
import { IGetGlobalPagesParams, IGetSitePagesParams } from "@ax/types";
|
|
2
|
+
import { IGetGlobalPagesParams, IGetSitePagesParams, IGetSitesParams } from "@ax/types";
|
|
3
3
|
import { template } from "./config";
|
|
4
4
|
import { sendRequest, sendInitialRequest, IServiceConfig } from "./utils";
|
|
5
5
|
|
|
@@ -69,11 +69,21 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
69
69
|
endpoint: ["/site/", "/publish"],
|
|
70
70
|
method: "POST",
|
|
71
71
|
},
|
|
72
|
+
PUBLISH_SITE_BULK: {
|
|
73
|
+
...template,
|
|
74
|
+
endpoint: "/site/publish/bulk",
|
|
75
|
+
method: "POST",
|
|
76
|
+
},
|
|
72
77
|
UNPUBLISH_SITE: {
|
|
73
78
|
...template,
|
|
74
79
|
endpoint: ["/site/", "/unpublish"],
|
|
75
80
|
method: "POST",
|
|
76
81
|
},
|
|
82
|
+
UNPUBLISH_SITE_BULK: {
|
|
83
|
+
...template,
|
|
84
|
+
endpoint: "/site/unpublish/bulk",
|
|
85
|
+
method: "POST",
|
|
86
|
+
},
|
|
77
87
|
IMPORT_PAGE: {
|
|
78
88
|
...template,
|
|
79
89
|
endpoint: ["/site/", "/pages/global/imports/"],
|
|
@@ -101,10 +111,33 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
101
111
|
},
|
|
102
112
|
};
|
|
103
113
|
|
|
104
|
-
const getAllSites = async (
|
|
114
|
+
const getAllSites = async (params: IGetSitesParams = { recentSitesNumber: 7 }) => {
|
|
105
115
|
const { host, endpoint } = SERVICES.GET_ALL_SITES;
|
|
106
|
-
|
|
107
|
-
|
|
116
|
+
const { token, language, recentSitesNumber, searchQuery, filterQuery, page, itemsPerPage, pagination } = params;
|
|
117
|
+
|
|
118
|
+
const queryParams =
|
|
119
|
+
language && recentSitesNumber
|
|
120
|
+
? `?recentSitesNumber=${recentSitesNumber}&language=${language}`
|
|
121
|
+
: (language && `?language=${language}`) || `?recentSitesNumber=${recentSitesNumber}`;
|
|
122
|
+
|
|
123
|
+
SERVICES.GET_ALL_SITES.dynamicUrl = `${host}${endpoint}${queryParams}`;
|
|
124
|
+
|
|
125
|
+
if (pagination) {
|
|
126
|
+
const paginationParams = `&pagination=true&page=${page}&itemsPerPage=${itemsPerPage}`;
|
|
127
|
+
SERVICES.GET_ALL_SITES.dynamicUrl = `${SERVICES.GET_ALL_SITES.dynamicUrl}${paginationParams}`;
|
|
128
|
+
}
|
|
129
|
+
if (filterQuery) {
|
|
130
|
+
SERVICES.GET_ALL_SITES.dynamicUrl = `${SERVICES.GET_ALL_SITES.dynamicUrl}${filterQuery}`;
|
|
131
|
+
}
|
|
132
|
+
if (searchQuery && searchQuery.trim() !== "") {
|
|
133
|
+
SERVICES.GET_ALL_SITES.dynamicUrl = `${SERVICES.GET_ALL_SITES.dynamicUrl}${searchQuery}`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (token) {
|
|
137
|
+
return sendInitialRequest(SERVICES.GET_ALL_SITES, token, { recentSitesNumber: 7 });
|
|
138
|
+
} else {
|
|
139
|
+
return sendRequest(SERVICES.GET_ALL_SITES);
|
|
140
|
+
}
|
|
108
141
|
};
|
|
109
142
|
|
|
110
143
|
const getSiteInfo = async (siteID: number) => {
|
|
@@ -280,6 +313,7 @@ const getSiteImages = async (
|
|
|
280
313
|
host,
|
|
281
314
|
endpoint: [prefix, suffix],
|
|
282
315
|
} = SERVICES.GET_SITE_IMAGES;
|
|
316
|
+
|
|
283
317
|
const items = itemsPerPage ? `&itemsPerPage=${itemsPerPage}` : "";
|
|
284
318
|
const thumb = thumbWidth && thumbHeight ? `&thumbWidth=${thumbWidth}&thumbHeight=${thumbHeight}` : "";
|
|
285
319
|
SERVICES.GET_SITE_IMAGES.dynamicUrl = `${host}${prefix}${site}${suffix}?page=${page}${items}${thumb}${query}`;
|
|
@@ -318,6 +352,8 @@ const publishSite = (siteID: number) => {
|
|
|
318
352
|
return sendRequest(SERVICES.PUBLISH_SITE);
|
|
319
353
|
};
|
|
320
354
|
|
|
355
|
+
const publishSiteBulk = (ids: number[]) => sendRequest(SERVICES.PUBLISH_SITE_BULK, { sites: ids });
|
|
356
|
+
|
|
321
357
|
const unpublishSite = (siteID: number) => {
|
|
322
358
|
const {
|
|
323
359
|
host,
|
|
@@ -327,6 +363,7 @@ const unpublishSite = (siteID: number) => {
|
|
|
327
363
|
SERVICES.UNPUBLISH_SITE.dynamicUrl = `${host}${prefix}${siteID}${suffix}`;
|
|
328
364
|
return sendRequest(SERVICES.UNPUBLISH_SITE);
|
|
329
365
|
};
|
|
366
|
+
const unpublishSiteBulk = (ids: number[]) => sendRequest(SERVICES.UNPUBLISH_SITE_BULK, { sites: ids });
|
|
330
367
|
|
|
331
368
|
export default {
|
|
332
369
|
getAllSites,
|
|
@@ -339,7 +376,9 @@ export default {
|
|
|
339
376
|
createSite,
|
|
340
377
|
updateSite,
|
|
341
378
|
publishSite,
|
|
379
|
+
publishSiteBulk,
|
|
342
380
|
unpublishSite,
|
|
381
|
+
unpublishSiteBulk,
|
|
343
382
|
getGlobalPages,
|
|
344
383
|
getGlobalPagesLight,
|
|
345
384
|
importPage,
|
|
@@ -8,7 +8,7 @@ const ActionMenu = (props: IProps): JSX.Element => {
|
|
|
8
8
|
const { options, icon, className, tooltip } = props;
|
|
9
9
|
|
|
10
10
|
const MoreInfoButton = () => (
|
|
11
|
-
<S.IconActionWrapper>
|
|
11
|
+
<S.IconActionWrapper data-testid="more-info-button">
|
|
12
12
|
<IconAction icon={icon} />
|
|
13
13
|
</S.IconActionWrapper>
|
|
14
14
|
);
|
|
@@ -2,17 +2,17 @@ import React from "react";
|
|
|
2
2
|
import { getInitials } from "@ax/helpers";
|
|
3
3
|
import * as S from "./style";
|
|
4
4
|
|
|
5
|
-
const Avatar = (props:
|
|
5
|
+
const Avatar = (props: IAvatarProps): JSX.Element => {
|
|
6
6
|
const { image, name } = props;
|
|
7
7
|
|
|
8
8
|
return (
|
|
9
|
-
<S.AvatarWrapper>
|
|
10
|
-
<S.Avatar image={image} initials={getInitials(name)} />
|
|
9
|
+
<S.AvatarWrapper data-testid="avatar-wrapper">
|
|
10
|
+
<S.Avatar image={image} initials={getInitials(name)} data-testid="avatar" />
|
|
11
11
|
</S.AvatarWrapper>
|
|
12
12
|
);
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
interface
|
|
15
|
+
export interface IAvatarProps {
|
|
16
16
|
image?: string | null;
|
|
17
17
|
name?: string;
|
|
18
18
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useEffect, useState
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { findByEditorID } from "@ax/forms";
|
|
4
4
|
import { copyTextToClipboard } from "@ax/helpers";
|
|
5
|
-
import { useToast } from "@ax/hooks";
|
|
5
|
+
import { useOnMessageReceivedFromIframe, useToast } from "@ax/hooks";
|
|
6
|
+
|
|
6
7
|
import Icon from "../Icon";
|
|
7
8
|
import Tooltip from "../Tooltip";
|
|
8
9
|
import Toast from "../Toast";
|
|
@@ -24,9 +25,9 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
24
25
|
disabled,
|
|
25
26
|
siteID,
|
|
26
27
|
isPreview,
|
|
27
|
-
setSelectedContent,
|
|
28
28
|
showIframe,
|
|
29
29
|
browserRef,
|
|
30
|
+
actions,
|
|
30
31
|
} = props;
|
|
31
32
|
|
|
32
33
|
const { id, entity } = content;
|
|
@@ -36,21 +37,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
36
37
|
const [resolution, setResolution] = useState("desktop");
|
|
37
38
|
const { isVisible, toggleToast, setIsVisible } = useToast();
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
(ev: MessageEvent<{ type: string; message: string }>) => {
|
|
41
|
-
if (typeof ev.data !== "object") return;
|
|
42
|
-
if (!ev.data.type) return;
|
|
43
|
-
if (ev.data.type !== "module-click") return;
|
|
44
|
-
if (!ev.data.message) return;
|
|
45
|
-
setSelectedContent(ev.data.message);
|
|
46
|
-
},
|
|
47
|
-
[setSelectedContent]
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
window.addEventListener("message", onMessageReceivedFromIframe);
|
|
52
|
-
return () => window.removeEventListener("message", onMessageReceivedFromIframe);
|
|
53
|
-
}, [onMessageReceivedFromIframe]);
|
|
40
|
+
useOnMessageReceivedFromIframe(actions);
|
|
54
41
|
|
|
55
42
|
useEffect(() => {
|
|
56
43
|
localStorage.setItem("selectedID", "0");
|
|
@@ -70,7 +57,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
70
57
|
const isNavigationModule = ["header", "footer"].includes(selectedComponent.type);
|
|
71
58
|
|
|
72
59
|
if (!isPreview && (!disabled || isNavigationModule)) {
|
|
73
|
-
|
|
60
|
+
actions?.setSelectedContentAction(editorID);
|
|
74
61
|
}
|
|
75
62
|
};
|
|
76
63
|
|
|
@@ -102,6 +89,21 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
102
89
|
message: "URL Copied",
|
|
103
90
|
};
|
|
104
91
|
|
|
92
|
+
const deleteModuleSelected = (editorID: number) => {
|
|
93
|
+
actions?.setSelectedContentAction(0);
|
|
94
|
+
actions?.deleteModuleAction(editorID);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const duplicateModuleSelected = async (editorID: number) => {
|
|
98
|
+
const duplicatedEditorID = await actions?.duplicateModuleAction(editorID);
|
|
99
|
+
actions?.setSelectedContentAction(duplicatedEditorID);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const moduleActions = {
|
|
103
|
+
deleteModuleAction: deleteModuleSelected,
|
|
104
|
+
duplicateModuleAction: duplicateModuleSelected,
|
|
105
|
+
};
|
|
106
|
+
|
|
105
107
|
return (
|
|
106
108
|
<S.BrowserWrapper ref={browserRef}>
|
|
107
109
|
<S.NavBar>
|
|
@@ -150,6 +152,7 @@ const Browser = (props: IBrowserProps): JSX.Element => {
|
|
|
150
152
|
footer={footer}
|
|
151
153
|
languageID={content.language}
|
|
152
154
|
pageLanguages={content.pageLanguages}
|
|
155
|
+
moduleActions={moduleActions}
|
|
153
156
|
renderer="editor"
|
|
154
157
|
/>
|
|
155
158
|
</S.Wrapper>
|
|
@@ -164,7 +167,6 @@ interface IBrowserProps {
|
|
|
164
167
|
header?: any;
|
|
165
168
|
footer?: any;
|
|
166
169
|
url: string;
|
|
167
|
-
setSelectedContent?: any;
|
|
168
170
|
isPage: boolean;
|
|
169
171
|
theme: string;
|
|
170
172
|
socials: any;
|
|
@@ -175,6 +177,11 @@ interface IBrowserProps {
|
|
|
175
177
|
isPreview?: boolean;
|
|
176
178
|
showIframe?: boolean;
|
|
177
179
|
browserRef?: any;
|
|
180
|
+
actions?: {
|
|
181
|
+
setSelectedContentAction: any;
|
|
182
|
+
deleteModuleAction(editorID: number): void;
|
|
183
|
+
duplicateModuleAction(editorID: number): Promise<number>;
|
|
184
|
+
};
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
export default Browser;
|
|
@@ -18,6 +18,7 @@ const BrowserContent = (props: IProps) => {
|
|
|
18
18
|
languageID,
|
|
19
19
|
pageLanguages,
|
|
20
20
|
selectEditorID,
|
|
21
|
+
moduleActions,
|
|
21
22
|
renderer,
|
|
22
23
|
} = props;
|
|
23
24
|
|
|
@@ -44,6 +45,7 @@ const BrowserContent = (props: IProps) => {
|
|
|
44
45
|
publicApiUrl={PUBLIC_API_URL}
|
|
45
46
|
instance={INSTANCE}
|
|
46
47
|
siteId={siteID}
|
|
48
|
+
moduleActions={moduleActions}
|
|
47
49
|
>
|
|
48
50
|
<Preview
|
|
49
51
|
isPage={isPage}
|
|
@@ -77,6 +79,10 @@ interface IProps {
|
|
|
77
79
|
parentComponent: string | undefined | null,
|
|
78
80
|
e: React.SyntheticEvent
|
|
79
81
|
): void;
|
|
82
|
+
moduleActions?: {
|
|
83
|
+
deleteModuleAction(editorID: number): void;
|
|
84
|
+
duplicateModuleAction(editorID: number): void;
|
|
85
|
+
};
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
export default BrowserContent;
|
|
@@ -15,6 +15,8 @@ export const StyledSelect = styled(AsyncSelect)<{ isDisabled: boolean | undefine
|
|
|
15
15
|
height: ${(p) => p.theme.spacing.l};
|
|
16
16
|
min-width: calc(${(p) => p.theme.spacing.xl} * 4);
|
|
17
17
|
max-width: calc(${(p) => p.theme.spacing.xl} * 6);
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
|
|
18
20
|
:hover {
|
|
19
21
|
border-color: ${(p) => (p.error ? p.theme.color.error : p.theme.color.uiLine)};
|
|
20
22
|
}
|
|
@@ -59,13 +61,14 @@ export const StyledSelect = styled(AsyncSelect)<{ isDisabled: boolean | undefine
|
|
|
59
61
|
min-height: ${(p) => p.theme.spacing.l};
|
|
60
62
|
padding: ${(p) => p.theme.spacing.s};
|
|
61
63
|
&:first-child {
|
|
62
|
-
${(p) =>
|
|
64
|
+
${(p) =>
|
|
65
|
+
!p.mandatory &&
|
|
66
|
+
p.hasEmptyOption &&
|
|
63
67
|
css`
|
|
64
68
|
font-style: italic;
|
|
65
69
|
color: ${(p) => p.theme.color.textLowEmphasis};
|
|
66
70
|
background-color: ${(p) => p.theme.color.uiLineInverse};
|
|
67
|
-
`
|
|
68
|
-
}
|
|
71
|
+
`}
|
|
69
72
|
}
|
|
70
73
|
:hover {
|
|
71
74
|
cursor: pointer;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
|
|
3
3
|
export const DatePickerWrapper = styled.div`
|
|
4
|
-
.react-datepicker-popper
|
|
4
|
+
.react-datepicker-popper,
|
|
5
|
+
.react-datepicker-popper[data-placement^="bottom"],
|
|
6
|
+
.react-datepicker-popper[data-placement^="bottom-start"] {
|
|
5
7
|
margin-top: 0
|
|
6
8
|
z-index: 2;
|
|
7
9
|
}
|
|
@@ -7,17 +7,25 @@ import * as S from "./style";
|
|
|
7
7
|
const HeadingField = (props: IHeadingFieldProps): JSX.Element => {
|
|
8
8
|
const { value, onChange, options, showAdvanced } = props;
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const getContentValue = () => value?.content || props.default?.content || "";
|
|
11
|
+
const getTagValue = () => value?.tag || props.default?.tag || "";
|
|
12
12
|
|
|
13
|
-
const
|
|
13
|
+
const handleChange = (newValue: string) => {
|
|
14
|
+
const tag = getTagValue();
|
|
15
|
+
onChange({ content: newValue, tag });
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handleSelectChange = (newValue: string) => {
|
|
19
|
+
const content = getContentValue();
|
|
20
|
+
onChange({ content, tag: newValue });
|
|
21
|
+
};
|
|
14
22
|
|
|
15
23
|
return (
|
|
16
24
|
<>
|
|
17
|
-
<TextField {...props} value={
|
|
25
|
+
<TextField {...props} value={getContentValue()} onChange={handleChange} />
|
|
18
26
|
{showAdvanced && (
|
|
19
27
|
<S.AdvancedWrapper data-testid="text-field-advanced-wrapper">
|
|
20
|
-
<FieldsBehavior fieldType="Select" options={options} value={
|
|
28
|
+
<FieldsBehavior fieldType="Select" options={options} value={getTagValue()} onChange={handleSelectChange} />
|
|
21
29
|
</S.AdvancedWrapper>
|
|
22
30
|
)}
|
|
23
31
|
</>
|
|
@@ -30,6 +38,7 @@ interface IHeadingFieldProps {
|
|
|
30
38
|
onChange: (value: IHeadingField) => void;
|
|
31
39
|
options: IOption[];
|
|
32
40
|
showAdvanced: boolean;
|
|
41
|
+
default: IHeadingField;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
interface IOption {
|
|
@@ -19,6 +19,7 @@ const ImageField = (props: IImageFieldProps) => {
|
|
|
19
19
|
site,
|
|
20
20
|
setIsGalleryOpened,
|
|
21
21
|
cropPreview = false,
|
|
22
|
+
fullWidth = false,
|
|
22
23
|
} = props;
|
|
23
24
|
|
|
24
25
|
const isLinkableImage = selectedContent && selectedContent.component === "LinkableImage";
|
|
@@ -73,6 +74,7 @@ const ImageField = (props: IImageFieldProps) => {
|
|
|
73
74
|
preview={!!previewSrc}
|
|
74
75
|
disabled={disabled}
|
|
75
76
|
onClick={handleClick}
|
|
77
|
+
fullWidth={fullWidth}
|
|
76
78
|
>
|
|
77
79
|
<S.IconWrapper>
|
|
78
80
|
<Icon name="image" size="18" />
|
|
@@ -114,6 +116,7 @@ export interface IImageFieldProps {
|
|
|
114
116
|
validators?: Record<string, unknown>;
|
|
115
117
|
site: ISite;
|
|
116
118
|
cropPreview?: boolean;
|
|
119
|
+
fullWidth?: boolean;
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
export default memo(ImageField);
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
import { Wrapper } from "@ax/components/FieldsBehavior/style";
|
|
3
3
|
|
|
4
|
-
const FieldWrapper = styled.div<{ error?: boolean; preview: boolean; disabled?: boolean }>`
|
|
4
|
+
const FieldWrapper = styled.div<{ error?: boolean; preview: boolean; disabled?: boolean; fullWidth?: boolean }>`
|
|
5
5
|
position: relative;
|
|
6
6
|
display: ${(p) => (p.preview ? `none` : `flex`)};
|
|
7
7
|
justify-content: center;
|
|
8
8
|
align-items: center;
|
|
9
9
|
flex-flow: column nowrap;
|
|
10
10
|
min-height: ${(p) => `calc(${p.theme.spacing.l} * 2)`};
|
|
11
|
-
max-width: ${(p) => `calc(${p.theme.spacing.xl} * 5)`};
|
|
11
|
+
max-width: ${(p) => (!p.fullWidth ? `calc(${p.theme.spacing.xl} * 5) ` : '100%')};
|
|
12
12
|
width: 100%;
|
|
13
13
|
background-color: ${(p) => p.theme.colors.uiBackground02};
|
|
14
14
|
border: ${(p) =>
|
|
@@ -18,6 +18,8 @@ export const StyledSelect = styled(Select)<{
|
|
|
18
18
|
box-shadow: none;
|
|
19
19
|
height: ${(p) => p.theme.spacing?.l};
|
|
20
20
|
max-width: calc(${(p) => p.theme.spacing?.xl} * 6);
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
|
|
21
23
|
:hover {
|
|
22
24
|
border-color: ${(p) => (p.error ? p.theme.color?.error : p.theme.color?.uiLine)};
|
|
23
25
|
}
|
|
@@ -17,7 +17,8 @@ const SliderField = (props: ITextFieldProps): JSX.Element => {
|
|
|
17
17
|
if (bubbleRef.current) {
|
|
18
18
|
bubbleRef.current.style.left = setBubbleLeft();
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
21
|
+
}, [bubbleRef, value]);
|
|
21
22
|
|
|
22
23
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
23
24
|
const newValue = e.target.value;
|
|
@@ -96,6 +96,7 @@ const TextField = (props: ITextFieldProps): JSX.Element => {
|
|
|
96
96
|
icon={hasBackgroundIcon}
|
|
97
97
|
hasPrefix={!!prefix}
|
|
98
98
|
prefixWidth={width}
|
|
99
|
+
aria-label={name}
|
|
99
100
|
/>
|
|
100
101
|
{hasBackgroundIcon && (
|
|
101
102
|
<S.BackgroundIcon data-testid="backgroundIconComponent" onClick={onClickIcon}>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
function SvgBulletList(props) {
|
|
4
|
+
return (
|
|
5
|
+
<svg width={24} height={24} fill="none" {...props}>
|
|
6
|
+
<path
|
|
7
|
+
fillRule="evenodd"
|
|
8
|
+
clipRule="evenodd"
|
|
9
|
+
d="M2.5 6C2.5 5.17 3.17 4.5 4 4.5C4.83 4.5 5.5 5.17 5.5 6C5.5 6.83 4.83 7.5 4 7.5C3.17 7.5 2.5 6.83 2.5 6ZM2.5 12C2.5 11.17 3.17 10.5 4 10.5C4.83 10.5 5.5 11.17 5.5 12C5.5 12.83 4.83 13.5 4 13.5C3.17 13.5 2.5 12.83 2.5 12ZM4 16.5C3.17 16.5 2.5 17.18 2.5 18C2.5 18.82 3.18 19.5 4 19.5C4.82 19.5 5.5 18.82 5.5 18C5.5 17.18 4.83 16.5 4 16.5ZM8 19C7.44772 19 7 18.5523 7 18C7 17.4477 7.44772 17 8 17H20C20.5523 17 21 17.4477 21 18C21 18.5523 20.5523 19 20 19H8ZM7 12C7 12.5523 7.44772 13 8 13H20C20.5523 13 21 12.5523 21 12C21 11.4477 20.5523 11 20 11H8C7.44772 11 7 11.4477 7 12ZM7 6C7 5.44772 7.44772 5 8 5H20C20.5523 5 21 5.44772 21 6C21 6.55228 20.5523 7 20 7H8C7.44772 7 7 6.55228 7 6Z"
|
|
10
|
+
fill="#5057FF"
|
|
11
|
+
/>
|
|
12
|
+
</svg>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default SvgBulletList;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
function SvgGrid2(props) {
|
|
4
|
+
return (
|
|
5
|
+
<svg width={24} height={24} fill="none" {...props}>
|
|
6
|
+
<path
|
|
7
|
+
fillRule="evenodd"
|
|
8
|
+
clipRule="evenodd"
|
|
9
|
+
d="M5 9H9V5H5V9ZM5 11C3.89543 11 3 10.1046 3 9V5C3 3.89543 3.89543 3 5 3H9C10.1046 3 11 3.89543 11 5V9C11 10.1046 10.1046 11 9 11H5ZM5 19H9V15H5V19ZM5 21C3.89543 21 3 20.1046 3 19V15C3 13.8954 3.89543 13 5 13H9C10.1046 13 11 13.8954 11 15V19C11 20.1046 10.1046 21 9 21H5ZM15 19H19V15H15V19ZM15 21C13.8954 21 13 20.1046 13 19V15C13 13.8954 13.8954 13 15 13H19C20.1046 13 21 13.8954 21 15V19C21 20.1046 20.1046 21 19 21H15ZM15 9H19V5H15V9ZM15 11C13.8954 11 13 10.1046 13 9V5C13 3.89543 13.8954 3 15 3H19C20.1046 3 21 3.89543 21 5V9C21 10.1046 20.1046 11 19 11H15Z"
|
|
10
|
+
fill="#5057FF"
|
|
11
|
+
/>
|
|
12
|
+
</svg>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default SvgGrid2;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 6C2.5 5.17 3.17 4.5 4 4.5C4.83 4.5 5.5 5.17 5.5 6C5.5 6.83 4.83 7.5 4 7.5C3.17 7.5 2.5 6.83 2.5 6ZM2.5 12C2.5 11.17 3.17 10.5 4 10.5C4.83 10.5 5.5 11.17 5.5 12C5.5 12.83 4.83 13.5 4 13.5C3.17 13.5 2.5 12.83 2.5 12ZM4 16.5C3.17 16.5 2.5 17.18 2.5 18C2.5 18.82 3.18 19.5 4 19.5C4.82 19.5 5.5 18.82 5.5 18C5.5 17.18 4.83 16.5 4 16.5ZM8 19C7.44772 19 7 18.5523 7 18C7 17.4477 7.44772 17 8 17H20C20.5523 17 21 17.4477 21 18C21 18.5523 20.5523 19 20 19H8ZM7 12C7 12.5523 7.44772 13 8 13H20C20.5523 13 21 12.5523 21 12C21 11.4477 20.5523 11 20 11H8C7.44772 11 7 11.4477 7 12ZM7 6C7 5.44772 7.44772 5 8 5H20C20.5523 5 21 5.44772 21 6C21 6.55228 20.5523 7 20 7H8C7.44772 7 7 6.55228 7 6Z" fill="#5057FF"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 9H9V5H5V9ZM5 11C3.89543 11 3 10.1046 3 9V5C3 3.89543 3.89543 3 5 3H9C10.1046 3 11 3.89543 11 5V9C11 10.1046 10.1046 11 9 11H5ZM5 19H9V15H5V19ZM5 21C3.89543 21 3 20.1046 3 19V15C3 13.8954 3.89543 13 5 13H9C10.1046 13 11 13.8954 11 15V19C11 20.1046 10.1046 21 9 21H5ZM15 19H19V15H15V19ZM15 21C13.8954 21 13 20.1046 13 19V15C13 13.8954 13.8954 13 15 13H19C20.1046 13 21 13.8954 21 15V19C21 20.1046 20.1046 21 19 21H15ZM15 9H19V5H15V9ZM15 11C13.8954 11 13 10.1046 13 9V5C13 3.89543 13.8954 3 15 3H19C20.1046 3 21 3.89543 21 5V9C21 10.1046 20.1046 11 19 11H15Z" fill="#5057FF"/>
|
|
3
|
+
</svg>
|
|
@@ -4,7 +4,7 @@ import { Icon } from "@ax/components";
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
6
|
const IconAction = (props: IIconActionProps): JSX.Element => {
|
|
7
|
-
const { icon, onClick, disabled, inversed, size = "m" } = props;
|
|
7
|
+
const { icon, onClick, disabled, inversed, size = "m", active } = props;
|
|
8
8
|
const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
9
9
|
if (onClick !== undefined) {
|
|
10
10
|
e.preventDefault();
|
|
@@ -19,8 +19,9 @@ const IconAction = (props: IIconActionProps): JSX.Element => {
|
|
|
19
19
|
onClick={handleOnClick}
|
|
20
20
|
size={size}
|
|
21
21
|
inversed={inversed}
|
|
22
|
+
active={active}
|
|
22
23
|
>
|
|
23
|
-
<S.Icon>
|
|
24
|
+
<S.Icon data-testid={`icon-action-${icon}`}>
|
|
24
25
|
<Icon name={icon} />
|
|
25
26
|
</S.Icon>
|
|
26
27
|
</S.Button>
|
|
@@ -33,6 +34,7 @@ export interface IIconActionProps {
|
|
|
33
34
|
size?: "s" | "m";
|
|
34
35
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
35
36
|
inversed?: boolean;
|
|
37
|
+
active?: boolean;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
export default IconAction;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
|
|
3
|
-
export const Button = styled.button<{
|
|
4
|
-
|
|
3
|
+
export const Button = styled.button<{
|
|
4
|
+
size: string | undefined;
|
|
5
|
+
inversed?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
active?: boolean;
|
|
8
|
+
}>`
|
|
9
|
+
background: ${(p) => (p.active ? p.theme.color?.overlayHoverPrimary : "transparent")};
|
|
5
10
|
border: none;
|
|
6
11
|
border-radius: 50%;
|
|
7
12
|
color: inherit;
|
|
@@ -22,6 +27,7 @@ export const Button = styled.button<{ size: string | undefined; inversed?: boole
|
|
|
22
27
|
opacity: 0;
|
|
23
28
|
transition: opacity 0.1s;
|
|
24
29
|
}
|
|
30
|
+
|
|
25
31
|
:hover:before {
|
|
26
32
|
background-color: ${(p) => p.theme.color?.overlayHoverPrimary};
|
|
27
33
|
opacity: 1;
|
|
@@ -5,7 +5,7 @@ import { Flag, Icon } from "@ax/components";
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
import { ILanguage } from "@ax/types";
|
|
7
7
|
|
|
8
|
-
const LanguageMenu = (props:
|
|
8
|
+
const LanguageMenu = (props: ILanguageMenuProps): JSX.Element => {
|
|
9
9
|
const { availableLanguages, language, setLanguage, isInAppBar, currentLanguages } = props;
|
|
10
10
|
|
|
11
11
|
const getCurrentLanguage = (lang: string) =>
|
|
@@ -30,18 +30,23 @@ const LanguageMenu = (props: IProps): JSX.Element => {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
|
-
<S.LanguageIcon>
|
|
33
|
+
<S.LanguageIcon data-testid="language-icon">
|
|
34
34
|
<Icon name={iconName} />
|
|
35
35
|
</S.LanguageIcon>
|
|
36
36
|
);
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
const languageMenuItem = (item: ILanguage) => (
|
|
40
|
-
<S.LanguageItem
|
|
40
|
+
<S.LanguageItem
|
|
41
|
+
key={item.locale}
|
|
42
|
+
selected={item.locale === language}
|
|
43
|
+
onClick={setLanguage(item)}
|
|
44
|
+
data-testid="language-menu-item"
|
|
45
|
+
>
|
|
41
46
|
<S.LanguageItemWrapper>
|
|
42
47
|
<S.LanguageLabel>
|
|
43
48
|
<Flag name={item.locale} />
|
|
44
|
-
<S.LanguageText>
|
|
49
|
+
<S.LanguageText data-testid="language-text">
|
|
45
50
|
<S.Locale>{item.label}</S.Locale> - {item.language}
|
|
46
51
|
</S.LanguageText>
|
|
47
52
|
</S.LanguageLabel>
|
|
@@ -54,11 +59,13 @@ const LanguageMenu = (props: IProps): JSX.Element => {
|
|
|
54
59
|
);
|
|
55
60
|
|
|
56
61
|
return (
|
|
57
|
-
<S.ActionMenu data-testid="language-menu">
|
|
62
|
+
<S.ActionMenu data-testid="language-menu">
|
|
63
|
+
{availableLanguages && availableLanguages.map((item: any) => languageMenuItem(item))}
|
|
64
|
+
</S.ActionMenu>
|
|
58
65
|
);
|
|
59
66
|
};
|
|
60
67
|
|
|
61
|
-
interface
|
|
68
|
+
export interface ILanguageMenuProps {
|
|
62
69
|
language?: string | null;
|
|
63
70
|
availableLanguages?: any[] | null;
|
|
64
71
|
currentLanguages?: any[];
|
|
@@ -45,7 +45,7 @@ const RecoveryModal = (props: IRecoveryProps): JSX.Element => {
|
|
|
45
45
|
|
|
46
46
|
const ModalContent = !modalState.isMailSent ? (
|
|
47
47
|
<>
|
|
48
|
-
<p>Forgot your password? No problem, we
|
|
48
|
+
<p>Forgot your password? No problem, we'll send you an email with instructions to reset it.</p>
|
|
49
49
|
<FieldsBehavior
|
|
50
50
|
fieldType="TextField"
|
|
51
51
|
placeholder="Type your email"
|
|
@@ -55,6 +55,7 @@ const RecoveryModal = (props: IRecoveryProps): JSX.Element => {
|
|
|
55
55
|
onChange={handleModalChange}
|
|
56
56
|
error={modalState.error}
|
|
57
57
|
helptext={errorText}
|
|
58
|
+
name="email"
|
|
58
59
|
/>
|
|
59
60
|
</>
|
|
60
61
|
) : (
|
|
@@ -62,7 +63,7 @@ const RecoveryModal = (props: IRecoveryProps): JSX.Element => {
|
|
|
62
63
|
<p>
|
|
63
64
|
We sent you an email with further instructions to reset your password to <strong>{modalState.input}</strong>.
|
|
64
65
|
</p>
|
|
65
|
-
<p>If you don
|
|
66
|
+
<p>If you don't receive it, please check your spam folder or contact support.</p>
|
|
66
67
|
</>
|
|
67
68
|
);
|
|
68
69
|
|
|
@@ -75,12 +76,12 @@ const RecoveryModal = (props: IRecoveryProps): JSX.Element => {
|
|
|
75
76
|
mainAction={mainAction}
|
|
76
77
|
secondaryAction={secondaryAction}
|
|
77
78
|
>
|
|
78
|
-
{isOpen ? <S.ModalContent>{ModalContent}</S.ModalContent> : null}
|
|
79
|
+
{isOpen ? <S.ModalContent data-testid="recovery-modal-content">{ModalContent}</S.ModalContent> : null}
|
|
79
80
|
</Modal>
|
|
80
81
|
);
|
|
81
82
|
};
|
|
82
83
|
|
|
83
|
-
interface IRecoveryProps {
|
|
84
|
+
export interface IRecoveryProps {
|
|
84
85
|
isOpen: boolean;
|
|
85
86
|
toggleModal(): void;
|
|
86
87
|
}
|
|
@@ -42,7 +42,7 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
42
42
|
const icon = viewPass ? "hide" : "view";
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
|
-
<S.Wrapper>
|
|
45
|
+
<S.Wrapper data-testid="login-wrapper">
|
|
46
46
|
<S.Main>
|
|
47
47
|
<S.Header>
|
|
48
48
|
<S.Subtitle>{textWelcome}</S.Subtitle>
|
|
@@ -56,6 +56,7 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
56
56
|
autoComplete="email"
|
|
57
57
|
value={email}
|
|
58
58
|
onChange={_handleEmail}
|
|
59
|
+
name="email"
|
|
59
60
|
/>
|
|
60
61
|
<FieldsBehavior
|
|
61
62
|
fieldType="TextField"
|
|
@@ -67,6 +68,7 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
67
68
|
icon={icon}
|
|
68
69
|
onClickIcon={_togglePassword}
|
|
69
70
|
iconPosition="in"
|
|
71
|
+
name="password"
|
|
70
72
|
/>
|
|
71
73
|
<FieldsBehavior
|
|
72
74
|
fieldType="UniqueCheck"
|
|
@@ -74,12 +76,20 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
74
76
|
value={rememberMe}
|
|
75
77
|
onChange={handleRememberMe}
|
|
76
78
|
options={[{ title: "Remember me" }]}
|
|
79
|
+
name="rememberMe"
|
|
77
80
|
/>
|
|
78
81
|
<Button type="submit" disabled={isLoggingIn ? true : false}>
|
|
79
82
|
{btnText}
|
|
80
83
|
</Button>
|
|
81
84
|
<S.Password>
|
|
82
|
-
<span
|
|
85
|
+
<span
|
|
86
|
+
onClick={toggleModal}
|
|
87
|
+
onKeyPress={toggleModal}
|
|
88
|
+
role="checkbox"
|
|
89
|
+
aria-checked="false"
|
|
90
|
+
tabIndex={0}
|
|
91
|
+
data-testid="forgot-button"
|
|
92
|
+
>
|
|
83
93
|
Forgot your password?
|
|
84
94
|
</span>
|
|
85
95
|
</S.Password>
|
|
@@ -90,7 +100,7 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
90
100
|
);
|
|
91
101
|
};
|
|
92
102
|
|
|
93
|
-
interface ILoginProps {
|
|
103
|
+
export interface ILoginProps {
|
|
94
104
|
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
|
|
95
105
|
email: string;
|
|
96
106
|
handleEmail: (email: string) => void;
|