@griddo/ax 1.72.11 → 1.73.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/scripts/griddo-sync-schemas.js +1 -1
- package/src/__tests__/components/ErrorCenter/ErrorCenter.test.tsx +186 -0
- package/src/__tests__/components/Flag/Flag.test.tsx +60 -0
- package/src/__tests__/components/FloatingMenu/FloatingMenu.test.tsx +712 -0
- package/src/__tests__/components/FloatingPanel/FloatingPanel.test.tsx +149 -0
- package/src/__tests__/components/GuardModal/GuardModal.test.tsx +31 -0
- package/src/__tests__/components/Icon/Icon.test.tsx +76 -0
- package/src/__tests__/components/IconAction/IconAction.test.tsx +91 -0
- package/src/__tests__/components/Notification/Notification.test.tsx +206 -0
- package/src/__tests__/components/Notification/SubNotification/Subnotification.test.tsx +46 -0
- package/src/__tests__/components/ReorderArrows/ReorderArrows.test.tsx +96 -0
- package/src/__tests__/components/ResizePanel/ResizePanel.test.tsx +200 -0
- package/src/__tests__/components/SearchField/SearchField.test.tsx +375 -0
- package/src/api/analytics.tsx +4 -4
- package/src/components/ActionMenu/style.tsx +1 -0
- package/src/components/ConfigPanel/Form/ConnectedField/NavConnectedField/index.tsx +1 -1
- package/src/components/ConfigPanel/Form/ConnectedField/PageConnectedField/Field/index.tsx +2 -1
- package/src/components/ConfigPanel/Form/index.tsx +22 -1
- package/src/components/ConfigPanel/Form/style.tsx +19 -0
- package/src/components/ConfigPanel/GlobalPageForm/index.tsx +22 -3
- package/src/components/ConfigPanel/GlobalPageForm/style.tsx +18 -2
- package/src/components/ConfigPanel/NavigationForm/Field/index.tsx +25 -13
- package/src/components/ConfigPanel/index.tsx +8 -0
- package/src/components/ErrorCenter/index.tsx +8 -4
- package/src/components/Fields/DateField/DatePickerInput/index.tsx +30 -8
- package/src/components/Fields/DateField/index.tsx +8 -2
- package/src/components/Fields/Select/index.tsx +1 -0
- package/src/components/Flag/index.tsx +13 -11
- package/src/components/FloatingMenu/index.tsx +23 -7
- package/src/components/FloatingMenu/style.tsx +1 -0
- package/src/components/FloatingPanel/index.tsx +9 -3
- package/src/components/GuardModal/index.tsx +3 -3
- package/src/components/Icon/index.tsx +2 -1
- package/src/components/IconAction/index.tsx +3 -3
- package/src/components/MainWrapper/AppBar/index.tsx +3 -1
- package/src/components/MainWrapper/AppBar/style.tsx +3 -0
- package/src/components/MenuItem/index.tsx +1 -1
- package/src/components/Modal/index.tsx +1 -1
- package/src/components/Notification/SubNotification/index.tsx +33 -0
- package/src/components/Notification/SubNotification/style.tsx +49 -0
- package/src/components/Notification/index.tsx +31 -17
- package/src/components/Notification/style.tsx +33 -8
- package/src/components/ReorderArrows/index.tsx +3 -3
- package/src/components/ResizePanel/ResizeHandle/index.tsx +29 -38
- package/src/components/ResizePanel/index.tsx +13 -15
- package/src/components/SearchField/index.tsx +9 -8
- package/src/containers/Analytics/actions.tsx +14 -4
- package/src/containers/App/actions.tsx +18 -6
- package/src/containers/App/reducer.tsx +1 -0
- package/src/containers/Domains/actions.tsx +8 -1
- package/src/containers/Navigation/Defaults/actions.tsx +16 -2
- package/src/containers/PageEditor/actions.tsx +82 -6
- package/src/containers/PageEditor/utils.tsx +28 -10
- package/src/containers/Redirects/actions.tsx +16 -2
- package/src/containers/Sites/actions.tsx +80 -3
- package/src/containers/StructuredData/actions.tsx +24 -3
- package/src/containers/Users/actions.tsx +8 -1
- package/src/forms/errors.tsx +1 -0
- package/src/forms/fields.tsx +6 -3
- package/src/forms/validators.tsx +14 -4
- package/src/guards/error/index.tsx +17 -21
- package/src/helpers/dates.tsx +2 -0
- package/src/helpers/index.tsx +2 -0
- package/src/hooks/modals.tsx +4 -4
- package/src/modules/Content/OptionTable/index.tsx +20 -7
- package/src/modules/Content/index.tsx +4 -7
- package/src/modules/Content/utils.tsx +18 -13
- package/src/modules/FramePreview/index.tsx +39 -12
- package/src/modules/GlobalEditor/index.tsx +17 -20
- package/src/modules/Navigation/Menus/List/Table/index.tsx +2 -2
- package/src/modules/PageEditor/Editor/index.tsx +13 -0
- package/src/modules/PageEditor/index.tsx +17 -20
- package/src/modules/Redirects/RedirectItem/index.tsx +17 -3
- package/src/modules/Settings/ContentTypes/DataPacks/Item/index.tsx +1 -1
- package/src/modules/StructuredData/Form/index.tsx +10 -13
|
@@ -10,7 +10,7 @@ const noteText = "This is Global content and you cannot edit it here. To do so,
|
|
|
10
10
|
const noteTitle = "Global content";
|
|
11
11
|
|
|
12
12
|
const GlobalPageForm = (props: IProps): JSX.Element => {
|
|
13
|
-
const { selectedTab, setSelectedTab, schema, pageTitle, setHistoryPush, actions } = props;
|
|
13
|
+
const { selectedTab, setSelectedTab, schema, pageTitle, setHistoryPush, actions, header, footer } = props;
|
|
14
14
|
const tabs = ["content", "config"];
|
|
15
15
|
|
|
16
16
|
const handleGetGlobalPage = async () => {
|
|
@@ -32,12 +32,28 @@ const GlobalPageForm = (props: IProps): JSX.Element => {
|
|
|
32
32
|
options: { excludeDetailPages: true },
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
const handleRestoreHeader = () =>
|
|
36
|
+
actions.restorePageNavigationAction && actions.restorePageNavigationAction("header");
|
|
37
|
+
|
|
38
|
+
const handleRestoreFooter = () =>
|
|
39
|
+
actions.restorePageNavigationAction && actions.restorePageNavigationAction("footer");
|
|
40
|
+
|
|
35
41
|
return (
|
|
36
42
|
<section>
|
|
37
43
|
<Tabs tabs={tabs} active={selectedTab} setSelectedTab={setSelectedTab} />
|
|
38
|
-
<S.
|
|
44
|
+
<S.NoteWrapper>
|
|
39
45
|
<NoteField value={{ text: noteText, title: noteTitle }} />
|
|
40
|
-
</S.
|
|
46
|
+
</S.NoteWrapper>
|
|
47
|
+
{selectedTab === "content" && header === 0 && (
|
|
48
|
+
<S.FieldWrapper>
|
|
49
|
+
This page doesn't have a header. Click <S.Link onClick={handleRestoreHeader}>here</S.Link> to restore it.
|
|
50
|
+
</S.FieldWrapper>
|
|
51
|
+
)}
|
|
52
|
+
{selectedTab === "content" && footer === 0 && (
|
|
53
|
+
<S.FieldWrapper>
|
|
54
|
+
This page doesn't have a footer. Click <S.Link onClick={handleRestoreFooter}>here</S.Link> to restore it.
|
|
55
|
+
</S.FieldWrapper>
|
|
56
|
+
)}
|
|
41
57
|
{selectedTab === "content" && (
|
|
42
58
|
<S.DataWrapper>
|
|
43
59
|
<S.IconWrapper>
|
|
@@ -70,9 +86,12 @@ interface IProps {
|
|
|
70
86
|
schema: ISchema;
|
|
71
87
|
pageTitle?: string;
|
|
72
88
|
setHistoryPush?: (path: string, isEditor: boolean) => void;
|
|
89
|
+
header?: number | null;
|
|
90
|
+
footer?: number | null;
|
|
73
91
|
actions: {
|
|
74
92
|
getGlobalFromLocalPageAction(): Promise<void>;
|
|
75
93
|
saveCurrentSiteInfoAction(): Promise<void>;
|
|
94
|
+
restorePageNavigationAction(type: string): Promise<void>;
|
|
76
95
|
};
|
|
77
96
|
}
|
|
78
97
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Button } from "@ax/components";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const NoteWrapper = styled.div`
|
|
5
5
|
margin-top: ${(p) => p.theme.spacing.s};
|
|
6
6
|
margin-bottom: ${(p) => p.theme.spacing.m};
|
|
7
7
|
`;
|
|
@@ -33,4 +33,20 @@ const StyledButton = styled(Button)`
|
|
|
33
33
|
margin-left: auto;
|
|
34
34
|
`;
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
const FieldWrapper = styled.div`
|
|
37
|
+
margin-top: ${(p) => p.theme.spacing.s};
|
|
38
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
39
|
+
background-color: ${(p) => p.theme.color?.uiBackground03};
|
|
40
|
+
padding: ${(p) => p.theme.spacing?.s};
|
|
41
|
+
border-radius: ${(p) => p.theme.radii?.s};
|
|
42
|
+
${(p) => p.theme.textStyle?.uiXS};
|
|
43
|
+
color: ${(p) => p.theme.color?.textMediumEmphasis};
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
const Link = styled.span`
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
font-weight: bold;
|
|
49
|
+
color: ${(p) => p.theme.color?.interactive01};
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
export { NoteWrapper, FieldWrapper, DataWrapper, IconWrapper, DataTitle, StyledButton, Link };
|
|
@@ -7,10 +7,8 @@ import { IRootState } from "@ax/types";
|
|
|
7
7
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
10
|
-
const pageEditorID = 0;
|
|
11
|
-
|
|
12
10
|
const Field = (props: IProps) => {
|
|
13
|
-
const { type, defaults, updateEditorContent, selectedContent, theme } = props;
|
|
11
|
+
const { type, defaults, updateEditorContent, selectedContent, theme, removeNavigationFromPage } = props;
|
|
14
12
|
const { isOpen, toggleModal } = useModal();
|
|
15
13
|
const isDefault = selectedContent.setAsDefault;
|
|
16
14
|
|
|
@@ -27,21 +25,17 @@ const Field = (props: IProps) => {
|
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
const optionsType = `${type}s`;
|
|
30
|
-
|
|
31
|
-
const actionMenuOptions = [
|
|
32
|
-
{
|
|
33
|
-
label: "replace",
|
|
34
|
-
icon: "change",
|
|
35
|
-
action: toggleModal,
|
|
36
|
-
},
|
|
37
|
-
];
|
|
38
|
-
|
|
39
28
|
const actionMenuIcon = "more";
|
|
29
|
+
const pageEditorID = 0;
|
|
40
30
|
|
|
41
31
|
const handleReplace = (option: any) => {
|
|
42
32
|
updateEditorContent(pageEditorID, type, option.id);
|
|
43
33
|
};
|
|
44
34
|
|
|
35
|
+
const handleRemove = () => {
|
|
36
|
+
removeNavigationFromPage(type);
|
|
37
|
+
};
|
|
38
|
+
|
|
45
39
|
const setDefault = {
|
|
46
40
|
title: `Set the default ${type}`,
|
|
47
41
|
action: () => {
|
|
@@ -52,12 +46,28 @@ const Field = (props: IProps) => {
|
|
|
52
46
|
checked: selectedContent.setAsDefault,
|
|
53
47
|
};
|
|
54
48
|
|
|
49
|
+
const actionMenuOptions = [
|
|
50
|
+
{
|
|
51
|
+
label: "remove",
|
|
52
|
+
icon: "delete",
|
|
53
|
+
action: handleRemove,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
if (hasMultipleOptions) {
|
|
58
|
+
actionMenuOptions.unshift({
|
|
59
|
+
label: "replace",
|
|
60
|
+
icon: "change",
|
|
61
|
+
action: toggleModal,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
return (
|
|
56
66
|
<>
|
|
57
67
|
<S.Component isArray disabled>
|
|
58
68
|
<S.Label containerInfo>{selectedContent.title}</S.Label>
|
|
59
69
|
<S.HiddenButtonsWrapper>
|
|
60
|
-
|
|
70
|
+
<ActionMenu options={actionMenuOptions} icon={actionMenuIcon} />
|
|
61
71
|
</S.HiddenButtonsWrapper>
|
|
62
72
|
</S.Component>
|
|
63
73
|
{hasMultipleOptions && (
|
|
@@ -87,6 +97,7 @@ interface IStateProps {
|
|
|
87
97
|
|
|
88
98
|
interface IDispatchProps {
|
|
89
99
|
updateEditorContent: (selectedEditorID: number, key: string, value: any) => void;
|
|
100
|
+
removeNavigationFromPage: (key: string) => void;
|
|
90
101
|
}
|
|
91
102
|
|
|
92
103
|
type IProps = IField & IStateProps & IDispatchProps;
|
|
@@ -98,6 +109,7 @@ const mapStateToProps = (state: IRootState) => ({
|
|
|
98
109
|
|
|
99
110
|
const mapDispatchToProps = {
|
|
100
111
|
updateEditorContent: pageEditorActions.updateEditorContent,
|
|
112
|
+
removeNavigationFromPage: pageEditorActions.removeNavigationFromPage,
|
|
101
113
|
};
|
|
102
114
|
|
|
103
115
|
export default connect(mapStateToProps, mapDispatchToProps)(Field);
|
|
@@ -34,6 +34,8 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
34
34
|
userEditing,
|
|
35
35
|
theme,
|
|
36
36
|
lastElementAddedId,
|
|
37
|
+
header,
|
|
38
|
+
footer,
|
|
37
39
|
} = props;
|
|
38
40
|
|
|
39
41
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
@@ -66,6 +68,8 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
66
68
|
pageTitle={pageTitle}
|
|
67
69
|
setHistoryPush={setHistoryPush}
|
|
68
70
|
actions={actions}
|
|
71
|
+
header={header}
|
|
72
|
+
footer={footer}
|
|
69
73
|
/>
|
|
70
74
|
);
|
|
71
75
|
} else {
|
|
@@ -80,6 +84,8 @@ const ConfigPanel = (props: IStateProps): JSX.Element => {
|
|
|
80
84
|
isGlobal={isGlobal}
|
|
81
85
|
theme={theme}
|
|
82
86
|
setHistoryPush={setHistoryPush}
|
|
87
|
+
header={header}
|
|
88
|
+
footer={footer}
|
|
83
89
|
/>
|
|
84
90
|
);
|
|
85
91
|
}
|
|
@@ -119,6 +125,8 @@ interface IStateProps {
|
|
|
119
125
|
userEditing?: IUserEditing | null;
|
|
120
126
|
theme: string;
|
|
121
127
|
lastElementAddedId?: null | number;
|
|
128
|
+
header?: number | null;
|
|
129
|
+
footer?: number | null;
|
|
122
130
|
}
|
|
123
131
|
|
|
124
132
|
export default ConfigPanel;
|
|
@@ -4,7 +4,7 @@ import { Icon } from "@ax/components";
|
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const ErrorCenter = (props:
|
|
7
|
+
const ErrorCenter = (props: IErrorCenterProps): JSX.Element => {
|
|
8
8
|
const { errors, actions } = props;
|
|
9
9
|
|
|
10
10
|
const goToElement = (key: string) => {
|
|
@@ -26,9 +26,13 @@ const ErrorCenter = (props: IProps): JSX.Element => {
|
|
|
26
26
|
|
|
27
27
|
const icon = item.type === "warning" ? "warning" : "alert";
|
|
28
28
|
const isClicable = !!item.editorID || !!item.hasDeactivatedPackage || !!item.key;
|
|
29
|
-
|
|
30
29
|
return (
|
|
31
|
-
<S.Wrapper
|
|
30
|
+
<S.Wrapper
|
|
31
|
+
data-testid="error-center-wrapper"
|
|
32
|
+
key={`${item.editorID}${item.key}`}
|
|
33
|
+
clickable={isClicable}
|
|
34
|
+
onClick={handleClick}
|
|
35
|
+
>
|
|
32
36
|
<S.Header type={item.type}>
|
|
33
37
|
<Icon name={icon} size="16" />
|
|
34
38
|
<S.Type>{item.type}</S.Type>
|
|
@@ -51,7 +55,7 @@ const ErrorCenter = (props: IProps): JSX.Element => {
|
|
|
51
55
|
);
|
|
52
56
|
};
|
|
53
57
|
|
|
54
|
-
interface
|
|
58
|
+
export interface IErrorCenterProps {
|
|
55
59
|
errors: IErrorItem[];
|
|
56
60
|
actions?: {
|
|
57
61
|
goToError(editorID: number | null, tab: string, template: boolean): void;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React, { useEffect, useState, forwardRef } from "react";
|
|
2
2
|
|
|
3
|
-
import { isValidDate, stringToDate, getStringifyDateRange } from "@ax/helpers";
|
|
3
|
+
import { isValidDate, stringToDate, getStringifyDateRange, getRange, isValidDateRange } from "@ax/helpers";
|
|
4
4
|
|
|
5
5
|
import { Icon, IconAction } from "@ax/components";
|
|
6
6
|
|
|
7
7
|
import * as S from "./style";
|
|
8
8
|
|
|
9
9
|
const DatePickerInput = (props: IDatePickerProps, ref: any): JSX.Element => {
|
|
10
|
-
const { dates, onClick, handleChange, isOpen, error, disabled } = props;
|
|
10
|
+
const { dates, onClick, handleChange, isOpen, error, disabled, handleValidation, validators } = props;
|
|
11
11
|
const { start, end } = dates;
|
|
12
12
|
const placeholder = "dd/mm/yyyy";
|
|
13
13
|
|
|
@@ -19,15 +19,29 @@ const DatePickerInput = (props: IDatePickerProps, ref: any): JSX.Element => {
|
|
|
19
19
|
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
20
20
|
const inputValue = e.target.value;
|
|
21
21
|
setValue(inputValue);
|
|
22
|
+
const range = getRange(inputValue);
|
|
23
|
+
const isRange = range.length === 2;
|
|
22
24
|
|
|
23
|
-
if (
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (isRange && isValidDateRange(inputValue)) {
|
|
26
|
+
const start = stringToDate(range[0]);
|
|
27
|
+
const end = stringToDate(range[1]);
|
|
28
|
+
handleChange([start, end]);
|
|
29
|
+
} else {
|
|
30
|
+
if (isValidDate(inputValue)) {
|
|
31
|
+
const date = stringToDate(inputValue);
|
|
32
|
+
handleChange([date, null]);
|
|
33
|
+
} else if (!inputValue) {
|
|
34
|
+
handleChange([null, null]);
|
|
35
|
+
}
|
|
28
36
|
}
|
|
29
37
|
};
|
|
30
38
|
|
|
39
|
+
const handleOnBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
|
40
|
+
const inputValue = e.target.value;
|
|
41
|
+
|
|
42
|
+
handleValidation && handleValidation(inputValue, validators);
|
|
43
|
+
};
|
|
44
|
+
|
|
31
45
|
const CalendarIcon = <IconAction icon="calendar" onClick={onClick} />;
|
|
32
46
|
const CloseIcon = (
|
|
33
47
|
<S.IconWrapper>
|
|
@@ -37,7 +51,13 @@ const DatePickerInput = (props: IDatePickerProps, ref: any): JSX.Element => {
|
|
|
37
51
|
|
|
38
52
|
return (
|
|
39
53
|
<S.InputWrapper error={error}>
|
|
40
|
-
<S.Input
|
|
54
|
+
<S.Input
|
|
55
|
+
value={value || ""}
|
|
56
|
+
placeholder={placeholder}
|
|
57
|
+
onChange={handleOnChange}
|
|
58
|
+
onBlur={handleOnBlur}
|
|
59
|
+
disabled={disabled}
|
|
60
|
+
/>
|
|
41
61
|
<S.ButtonWrapper>{isOpen ? CloseIcon : CalendarIcon}</S.ButtonWrapper>
|
|
42
62
|
</S.InputWrapper>
|
|
43
63
|
);
|
|
@@ -50,6 +70,8 @@ interface IDatePickerProps {
|
|
|
50
70
|
isOpen: boolean;
|
|
51
71
|
error?: boolean;
|
|
52
72
|
disabled?: boolean;
|
|
73
|
+
handleValidation?: (value: string, validators?: Record<string, unknown>) => void;
|
|
74
|
+
validators?: Record<string, unknown>;
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
export default forwardRef(DatePickerInput);
|
|
@@ -28,11 +28,14 @@ const DateField = (props: IDateFieldProps): JSX.Element => {
|
|
|
28
28
|
selectsRange = false,
|
|
29
29
|
disabled,
|
|
30
30
|
handleValidation,
|
|
31
|
+
validators,
|
|
31
32
|
} = props;
|
|
32
33
|
|
|
33
34
|
const currentDate = new Date();
|
|
34
35
|
const defaultValue = mandatory ? dateToString(currentDate, "yyyy/MM/dd") : null;
|
|
35
36
|
const stringDate = value && typeof value === "number" ? dateToString(new Date(value * 1000)) : value;
|
|
37
|
+
const dateValidators = { format: "date", ...validators };
|
|
38
|
+
|
|
36
39
|
const dateValue = stringDate && (isValidDate(stringDate) || isValidDateRange(stringDate)) ? stringDate : defaultValue;
|
|
37
40
|
const isRange = dateValue && dateValue.split(" - ").length > 1;
|
|
38
41
|
const { isOpen, toggleModal } = useModal();
|
|
@@ -77,7 +80,7 @@ const DateField = (props: IDateFieldProps): JSX.Element => {
|
|
|
77
80
|
setDates(rangeDates);
|
|
78
81
|
onChange(selectedDate);
|
|
79
82
|
|
|
80
|
-
handleValidation && handleValidation(
|
|
83
|
+
handleValidation && handleValidation(selectedDate, dateValidators);
|
|
81
84
|
};
|
|
82
85
|
|
|
83
86
|
const { start, end } = dates;
|
|
@@ -91,6 +94,8 @@ const DateField = (props: IDateFieldProps): JSX.Element => {
|
|
|
91
94
|
isOpen={isOpen}
|
|
92
95
|
error={error}
|
|
93
96
|
disabled={disabled}
|
|
97
|
+
handleValidation={handleValidation}
|
|
98
|
+
validators={dateValidators}
|
|
94
99
|
/>
|
|
95
100
|
);
|
|
96
101
|
|
|
@@ -126,7 +131,8 @@ export interface IDateFieldProps {
|
|
|
126
131
|
futureDate?: boolean;
|
|
127
132
|
pastDate?: boolean;
|
|
128
133
|
disabled?: boolean;
|
|
129
|
-
handleValidation?: (value: string) => void;
|
|
134
|
+
handleValidation?: (value: string, validators?: Record<string, unknown>) => void;
|
|
135
|
+
validators?: Record<string, unknown>;
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
export default DateField;
|
|
@@ -10,30 +10,32 @@ const getImage = (name: string) => {
|
|
|
10
10
|
pt: "Pt_PT",
|
|
11
11
|
};
|
|
12
12
|
const filename = simpleIcons[name?.toLowerCase()] || name;
|
|
13
|
+
|
|
13
14
|
try {
|
|
14
15
|
return require(`./components/${filename}`).default;
|
|
15
16
|
} catch (err) {
|
|
16
17
|
return null;
|
|
17
18
|
}
|
|
18
19
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const name = this.props.name.charAt(0).toUpperCase() + this.props.name.slice(1);
|
|
20
|
+
const Flag = (props: IProps) => {
|
|
21
|
+
const name = props.name.charAt(0).toUpperCase() + props.name.slice(1);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
const size = props.size ? props.size : "24";
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const Svg = getImage(name);
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
return null;
|
|
27
|
+
if (Svg) {
|
|
28
|
+
return <Svg height={size} width={size} viewBox="0 0 512 512" />;
|
|
31
29
|
}
|
|
32
|
-
}
|
|
33
30
|
|
|
34
|
-
|
|
31
|
+
return null;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface IStateProps {
|
|
35
35
|
name: string;
|
|
36
36
|
size?: string;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
type IProps = IStateProps;
|
|
40
|
+
|
|
41
|
+
export default Flag;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { useRef, useState } from "react";
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { useHandleClickOutside } from "@ax/hooks";
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const FloatingMenu = (props:
|
|
7
|
+
const FloatingMenu = (props: IFloatingProps) => {
|
|
8
8
|
const {
|
|
9
9
|
children,
|
|
10
10
|
isInAppBar,
|
|
@@ -13,13 +13,23 @@ const FloatingMenu = (props: IProps) => {
|
|
|
13
13
|
closeOnSelect = true,
|
|
14
14
|
isCheckGroup,
|
|
15
15
|
reactiveToHover,
|
|
16
|
-
offset
|
|
16
|
+
offset,
|
|
17
17
|
} = props;
|
|
18
18
|
const wrapper = useRef<any>(null);
|
|
19
19
|
const button = useRef<any>(null);
|
|
20
20
|
const menuOptions = useRef<any>(null);
|
|
21
21
|
const [isOpen, setOpen] = useState(false);
|
|
22
22
|
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (isOpen && menuOptions.current) {
|
|
25
|
+
const bounding = menuOptions.current.getBoundingClientRect();
|
|
26
|
+
if (bounding.bottom > (window.innerHeight || document.documentElement.clientHeight)) {
|
|
27
|
+
menuOptions.current.scrollIntoView({ block: "end", behavior: "smooth" });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
+
}, [isOpen]);
|
|
32
|
+
|
|
23
33
|
const handleClickOutside = (e: any) => {
|
|
24
34
|
if (wrapper.current.contains(e.target)) {
|
|
25
35
|
return;
|
|
@@ -51,8 +61,7 @@ const FloatingMenu = (props: IProps) => {
|
|
|
51
61
|
const handleMouseEnter = (e: React.MouseEvent<HTMLDivElement>) =>
|
|
52
62
|
reactiveToHover && !isOpen ? handleClick(e) : null;
|
|
53
63
|
|
|
54
|
-
const handleMouseLeave = (e: React.MouseEvent<HTMLDivElement>) =>
|
|
55
|
-
reactiveToHover && isOpen && setOpen(false);
|
|
64
|
+
const handleMouseLeave = (e: React.MouseEvent<HTMLDivElement>) => reactiveToHover && isOpen && setOpen(false);
|
|
56
65
|
|
|
57
66
|
useHandleClickOutside(isOpen, handleClickOutside);
|
|
58
67
|
|
|
@@ -67,8 +76,15 @@ const FloatingMenu = (props: IProps) => {
|
|
|
67
76
|
<S.ButtonWrapper ref={button} data-testid="floating-menu-button">
|
|
68
77
|
<Button />
|
|
69
78
|
</S.ButtonWrapper>
|
|
79
|
+
|
|
70
80
|
{isOpen && (
|
|
71
|
-
<S.MenuWrapper
|
|
81
|
+
<S.MenuWrapper
|
|
82
|
+
isInAppBar={isInAppBar}
|
|
83
|
+
ref={menuOptions}
|
|
84
|
+
position={position}
|
|
85
|
+
offset={offset}
|
|
86
|
+
data-testid="floating-menu-wrapper"
|
|
87
|
+
>
|
|
72
88
|
<S.Menu>{children}</S.Menu>
|
|
73
89
|
</S.MenuWrapper>
|
|
74
90
|
)}
|
|
@@ -76,7 +92,7 @@ const FloatingMenu = (props: IProps) => {
|
|
|
76
92
|
);
|
|
77
93
|
};
|
|
78
94
|
|
|
79
|
-
interface
|
|
95
|
+
export interface IFloatingProps {
|
|
80
96
|
children: any;
|
|
81
97
|
Button: any;
|
|
82
98
|
isInAppBar?: boolean;
|
|
@@ -6,7 +6,7 @@ import { IconAction } from "@ax/components";
|
|
|
6
6
|
|
|
7
7
|
import * as S from "./style";
|
|
8
8
|
|
|
9
|
-
const FloatingPanel = (props:
|
|
9
|
+
const FloatingPanel = (props: IFloatingPanelProps): JSX.Element | null => {
|
|
10
10
|
const {
|
|
11
11
|
children,
|
|
12
12
|
title,
|
|
@@ -40,7 +40,13 @@ const FloatingPanel = (props: IProps): JSX.Element | null => {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
return createPortal(
|
|
43
|
-
<S.Wrapper
|
|
43
|
+
<S.Wrapper
|
|
44
|
+
data-testid="floating-panel"
|
|
45
|
+
ref={node}
|
|
46
|
+
isOpen={isOpen}
|
|
47
|
+
isOpenedSecond={isOpenedSecond}
|
|
48
|
+
secondary={secondary}
|
|
49
|
+
>
|
|
44
50
|
<S.Header>
|
|
45
51
|
<S.Title>{title}</S.Title>
|
|
46
52
|
{!isOpenedSecond && (
|
|
@@ -55,7 +61,7 @@ const FloatingPanel = (props: IProps): JSX.Element | null => {
|
|
|
55
61
|
);
|
|
56
62
|
};
|
|
57
63
|
|
|
58
|
-
interface
|
|
64
|
+
export interface IFloatingPanelProps {
|
|
59
65
|
isOpen: boolean;
|
|
60
66
|
isOpenedSecond?: boolean;
|
|
61
67
|
children: JSX.Element[] | JSX.Element | boolean;
|
|
@@ -4,7 +4,7 @@ import { Modal } from "@ax/components";
|
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const GuardModal = (props:
|
|
7
|
+
const GuardModal = (props: IGuardModalProps): JSX.Element => {
|
|
8
8
|
const { isOpen, discardChanges, toggleModal } = props;
|
|
9
9
|
|
|
10
10
|
const mainAction = {
|
|
@@ -33,12 +33,12 @@ const GuardModal = (props: IProps): JSX.Element => {
|
|
|
33
33
|
mainAction={mainAction}
|
|
34
34
|
secondaryAction={secondaryAction}
|
|
35
35
|
>
|
|
36
|
-
{<S.ModalContent>{modalText}</S.ModalContent>}
|
|
36
|
+
{<S.ModalContent data-testid='guard-modal-content'>{modalText}</S.ModalContent>}
|
|
37
37
|
</Modal>
|
|
38
38
|
);
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
interface
|
|
41
|
+
export interface IGuardModalProps {
|
|
42
42
|
isOpen: boolean;
|
|
43
43
|
discardChanges: () => void;
|
|
44
44
|
toggleModal: () => void;
|
|
@@ -7,6 +7,7 @@ const getImage = (name: string) => {
|
|
|
7
7
|
return null;
|
|
8
8
|
}
|
|
9
9
|
};
|
|
10
|
+
|
|
10
11
|
const Icon = (props: IProps) => {
|
|
11
12
|
const name =
|
|
12
13
|
props.name &&
|
|
@@ -28,7 +29,7 @@ const Icon = (props: IProps) => {
|
|
|
28
29
|
return null;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
interface IStateProps {
|
|
32
|
+
export interface IStateProps {
|
|
32
33
|
name: string;
|
|
33
34
|
size?: string;
|
|
34
35
|
fill?: string;
|
|
@@ -27,11 +27,11 @@ const IconAction = (props: IIconActionProps): JSX.Element => {
|
|
|
27
27
|
);
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
interface IIconActionProps {
|
|
30
|
+
export interface IIconActionProps {
|
|
31
31
|
icon: string;
|
|
32
32
|
disabled?: boolean;
|
|
33
|
-
size?: "s" | "m"
|
|
34
|
-
onClick?:
|
|
33
|
+
size?: "s" | "m";
|
|
34
|
+
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
35
35
|
inversed?: boolean;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -124,7 +124,9 @@ const AppBar = (props: IProps): JSX.Element => {
|
|
|
124
124
|
|
|
125
125
|
const ErrorCenterBtn = () => (
|
|
126
126
|
<S.ErrorWrapper>
|
|
127
|
-
<
|
|
127
|
+
<Tooltip content="Error center" bottom>
|
|
128
|
+
<Icon name="alert" size="24" />
|
|
129
|
+
</Tooltip>
|
|
128
130
|
</S.ErrorWrapper>
|
|
129
131
|
);
|
|
130
132
|
|
|
@@ -92,6 +92,7 @@ const LanguageWrapper = styled.div`
|
|
|
92
92
|
position: relative;
|
|
93
93
|
display: flex;
|
|
94
94
|
align-items: center;
|
|
95
|
+
cursor: pointer;
|
|
95
96
|
`;
|
|
96
97
|
|
|
97
98
|
const FlagWrapper = styled.div``;
|
|
@@ -113,6 +114,7 @@ const Separator = styled.div`
|
|
|
113
114
|
const IconStatusWrapper = styled.div`
|
|
114
115
|
position: relative;
|
|
115
116
|
height: ${(p) => p.theme.spacing.m};
|
|
117
|
+
cursor: pointer;
|
|
116
118
|
`;
|
|
117
119
|
|
|
118
120
|
const Header = styled.section<{ inversed?: boolean }>`
|
|
@@ -169,6 +171,7 @@ const ErrorWrapper = styled.div`
|
|
|
169
171
|
path {
|
|
170
172
|
fill: ${(p) => p.theme.color.error};
|
|
171
173
|
}
|
|
174
|
+
cursor: pointer;
|
|
172
175
|
}
|
|
173
176
|
`;
|
|
174
177
|
|
|
@@ -13,7 +13,7 @@ const MenuItem = (props: IMenuItemProps): JSX.Element => {
|
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const handleExtendedAction = (e: React.MouseEvent<
|
|
16
|
+
const handleExtendedAction = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
17
17
|
e.stopPropagation();
|
|
18
18
|
extendedAction && extendedAction.action();
|
|
19
19
|
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Icon } from "@ax/components";
|
|
3
|
+
|
|
4
|
+
import * as S from "./style";
|
|
5
|
+
|
|
6
|
+
const SubNotification = (props: ISubNotificationProps): JSX.Element => {
|
|
7
|
+
const { text } = props;
|
|
8
|
+
|
|
9
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
10
|
+
|
|
11
|
+
const handleClose = () => {
|
|
12
|
+
setIsVisible(false);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<S.Wrapper isVisible={isVisible} data-testid="subnotification-wrapper">
|
|
17
|
+
<S.Row>
|
|
18
|
+
<S.Text>{text}</S.Text>
|
|
19
|
+
<S.ActionsWrapper>
|
|
20
|
+
<S.CloseWrapper onClick={handleClose} data-testid="subnotification-close-button">
|
|
21
|
+
<Icon name="close" size="16" />
|
|
22
|
+
</S.CloseWrapper>
|
|
23
|
+
</S.ActionsWrapper>
|
|
24
|
+
</S.Row>
|
|
25
|
+
</S.Wrapper>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export interface ISubNotificationProps {
|
|
30
|
+
text: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default SubNotification;
|