@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
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div<{ isVisible: boolean }>`
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
align-items: center;
|
|
8
|
+
padding: ${(p) => `0 ${p.theme.spacing.m}`};
|
|
9
|
+
color: ${(p) => p.theme.color.textHighEmphasisInverse};
|
|
10
|
+
${(p) => p.theme.textStyle.uiM};
|
|
11
|
+
display: ${(p) => (p.isVisible ? "block" : "none")};
|
|
12
|
+
transition: all 0.5s;
|
|
13
|
+
background-color: ${(p) => p.theme.colors.overlayHoverDark};
|
|
14
|
+
border-bottom: 1px solid ${(p) => p.theme.colors.iconLowEmphasisInverse};
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const Row = styled.div`
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
width: 100%;
|
|
21
|
+
min-height: ${(p) => p.theme.spacing.l};
|
|
22
|
+
z-index: 2;
|
|
23
|
+
padding-left: ${(p) => `calc( ${p.theme.spacing.m} + ${p.theme.spacing.s})`};
|
|
24
|
+
padding-right: ${(p) => p.theme.spacing.xxs};
|
|
25
|
+
|
|
26
|
+
svg {
|
|
27
|
+
width: ${(p) => p.theme.spacing.s};
|
|
28
|
+
height: ${(p) => p.theme.spacing.s};
|
|
29
|
+
path {
|
|
30
|
+
fill: ${(p) => p.theme.color.textHighEmphasisInverse};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
const Text = styled.span``;
|
|
36
|
+
|
|
37
|
+
const ActionsWrapper = styled.div`
|
|
38
|
+
display: flex;
|
|
39
|
+
margin-left: auto;
|
|
40
|
+
align-items: center;
|
|
41
|
+
`;
|
|
42
|
+
|
|
43
|
+
const CloseWrapper = styled.span`
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
width: 16px;
|
|
46
|
+
height: 16px;
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
export { Wrapper, Text, Row, ActionsWrapper, CloseWrapper };
|
|
@@ -1,36 +1,36 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { Icon } from "@ax/components";
|
|
3
|
+
import SubNotification from "./SubNotification";
|
|
3
4
|
|
|
4
5
|
import * as S from "./style";
|
|
5
6
|
|
|
6
|
-
const Notification = (props:
|
|
7
|
-
const { text, type, btnText, resetError, onClick, closeButton = true, actionsBelow } = props;
|
|
7
|
+
const Notification = (props: INotificationProps): JSX.Element => {
|
|
8
|
+
const { text, type, btnText, resetError, onClick, closeButton = true, actionsBelow, subErrors } = props;
|
|
8
9
|
|
|
9
|
-
const [
|
|
10
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
11
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
10
12
|
|
|
11
13
|
const getNotificationIcon = (type: string) => {
|
|
12
14
|
switch (type) {
|
|
13
15
|
case "error":
|
|
14
16
|
case "info":
|
|
15
17
|
return (
|
|
16
|
-
<S.IconWrapper>
|
|
18
|
+
<S.IconWrapper data-testid="alert-icon">
|
|
17
19
|
<Icon name="alert" />
|
|
18
20
|
</S.IconWrapper>
|
|
19
21
|
);
|
|
20
22
|
case "success":
|
|
21
23
|
return (
|
|
22
|
-
<S.IconWrapper>
|
|
24
|
+
<S.IconWrapper data-testid="success-icon">
|
|
23
25
|
<Icon name="done" />
|
|
24
26
|
</S.IconWrapper>
|
|
25
27
|
);
|
|
26
28
|
case "warning":
|
|
27
29
|
return (
|
|
28
|
-
<S.IconWrapper>
|
|
30
|
+
<S.IconWrapper data-testid="warning-icon">
|
|
29
31
|
<Icon name="warning" />
|
|
30
32
|
</S.IconWrapper>
|
|
31
33
|
);
|
|
32
|
-
default:
|
|
33
|
-
return null;
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
@@ -40,37 +40,50 @@ const Notification = (props: IProps) => {
|
|
|
40
40
|
|
|
41
41
|
const handleClose = () => {
|
|
42
42
|
resetError && resetError();
|
|
43
|
-
|
|
43
|
+
setIsVisible(false);
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
const toggleShow = () => setIsOpen(!isOpen);
|
|
47
|
+
|
|
46
48
|
const ActionBtn = () => (
|
|
47
|
-
<S.ActionBtn onClick={handleClick} actionsBelow={actionsBelow}>
|
|
49
|
+
<S.ActionBtn onClick={handleClick} actionsBelow={actionsBelow} data-testid="action-button">
|
|
48
50
|
{btnText}
|
|
49
51
|
</S.ActionBtn>
|
|
50
52
|
);
|
|
51
53
|
|
|
54
|
+
const showText = isOpen ? "Hide errors" : "Show errors";
|
|
55
|
+
|
|
52
56
|
return (
|
|
53
|
-
|
|
54
|
-
<S.
|
|
57
|
+
<S.Wrapper isVisible={isVisible} className={type} data-testid="notification-wrapper">
|
|
58
|
+
<S.NotificationWrapper>
|
|
55
59
|
<S.Row>
|
|
56
60
|
{getNotificationIcon(type)}
|
|
57
61
|
<S.Text>{text}</S.Text>
|
|
58
62
|
<S.ActionsWrapper>
|
|
63
|
+
{subErrors && subErrors.length > 0 && (
|
|
64
|
+
<S.Button onClick={toggleShow} isOpen={isOpen} data-testid="suberrors-button">
|
|
65
|
+
{showText}
|
|
66
|
+
</S.Button>
|
|
67
|
+
)}
|
|
59
68
|
{btnText && !actionsBelow && <ActionBtn />}
|
|
60
69
|
{closeButton && (
|
|
61
|
-
<S.CloseWrapper onClick={handleClose}>
|
|
62
|
-
<Icon name="close" />
|
|
70
|
+
<S.CloseWrapper onClick={handleClose} data-testid="close-button">
|
|
71
|
+
<Icon name="close" size="24" />
|
|
63
72
|
</S.CloseWrapper>
|
|
64
73
|
)}
|
|
65
74
|
</S.ActionsWrapper>
|
|
66
75
|
</S.Row>
|
|
67
76
|
{btnText && actionsBelow && <ActionBtn />}
|
|
68
|
-
</S.
|
|
69
|
-
|
|
77
|
+
</S.NotificationWrapper>
|
|
78
|
+
{isOpen &&
|
|
79
|
+
subErrors &&
|
|
80
|
+
subErrors.length > 0 &&
|
|
81
|
+
subErrors.map((not: { id: number; error: string }) => <SubNotification key={not.id} text={not.error} />)}
|
|
82
|
+
</S.Wrapper>
|
|
70
83
|
);
|
|
71
84
|
};
|
|
72
85
|
|
|
73
|
-
interface
|
|
86
|
+
export interface INotificationProps {
|
|
74
87
|
text: string;
|
|
75
88
|
type: "error" | "info" | "success" | "warning";
|
|
76
89
|
resetError?: () => void;
|
|
@@ -78,6 +91,7 @@ interface IProps {
|
|
|
78
91
|
onClick?: () => void;
|
|
79
92
|
closeButton?: boolean;
|
|
80
93
|
actionsBelow?: boolean;
|
|
94
|
+
subErrors?: { id: number; error: string }[];
|
|
81
95
|
}
|
|
82
96
|
|
|
83
97
|
export default Notification;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import styled from "styled-components";
|
|
2
2
|
|
|
3
|
-
const Wrapper = styled.div<{
|
|
3
|
+
const Wrapper = styled.div<{ isVisible: boolean }>`
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-direction: column;
|
|
6
|
-
|
|
7
|
-
align-items: center;
|
|
8
|
-
display: ${(p) => (p.isOpen ? "block" : "none")};
|
|
9
|
-
padding: ${(p) => `0 ${p.theme.spacing.m}`};
|
|
10
|
-
color: ${(p) => p.theme.color.textHighEmphasisInverse};
|
|
11
|
-
${(p) => p.theme.textStyle.uiL};
|
|
6
|
+
display: ${(p) => (p.isVisible ? "block" : "none")};
|
|
12
7
|
transition: all 0.5s;
|
|
13
8
|
&.error {
|
|
14
9
|
background-color: ${(p) => p.theme.colors.error};
|
|
@@ -24,6 +19,16 @@ const Wrapper = styled.div<{ isOpen: boolean }>`
|
|
|
24
19
|
}
|
|
25
20
|
`;
|
|
26
21
|
|
|
22
|
+
const NotificationWrapper = styled.div`
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
align-items: center;
|
|
27
|
+
padding: ${(p) => `0 ${p.theme.spacing.m}`};
|
|
28
|
+
color: ${(p) => p.theme.color.textHighEmphasisInverse};
|
|
29
|
+
${(p) => p.theme.textStyle.uiL};
|
|
30
|
+
`;
|
|
31
|
+
|
|
27
32
|
const Row = styled.div`
|
|
28
33
|
display: flex;
|
|
29
34
|
align-items: center;
|
|
@@ -74,4 +79,24 @@ const ActionBtn = styled.button<{ actionsBelow?: boolean }>`
|
|
|
74
79
|
margin-bottom: ${(p) => (p.actionsBelow ? p.theme.spacing.s : 0)};
|
|
75
80
|
`;
|
|
76
81
|
|
|
77
|
-
|
|
82
|
+
const Button = styled.div<{ isOpen: boolean }>`
|
|
83
|
+
position: relative;
|
|
84
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
85
|
+
color: ${(p) => p.theme.colors.textHighEmphasisInverse};
|
|
86
|
+
padding-right: ${(p) => p.theme.spacing.s};
|
|
87
|
+
margin-right: ${(p) => p.theme.spacing.m};
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
:after {
|
|
90
|
+
position: absolute;
|
|
91
|
+
right: 0;
|
|
92
|
+
top: ${(p) => (p.isOpen ? `6px` : `2px`)};
|
|
93
|
+
content: "";
|
|
94
|
+
border: solid ${(p) => p.theme.color.interactiveInverse};
|
|
95
|
+
border-width: 0 2px 2px 0;
|
|
96
|
+
display: inline-block;
|
|
97
|
+
padding: 3px;
|
|
98
|
+
transform: ${(p) => (p.isOpen ? `rotate(-135deg)` : `rotate(45deg)`)};
|
|
99
|
+
}
|
|
100
|
+
`;
|
|
101
|
+
|
|
102
|
+
export { Wrapper, NotificationWrapper, Text, IconWrapper, Row, CloseWrapper, ActionBtn, ActionsWrapper, Button };
|
|
@@ -13,13 +13,13 @@ const ReorderArrows = (props: IReorderArrows): JSX.Element => {
|
|
|
13
13
|
const Arrows = () => (
|
|
14
14
|
<>
|
|
15
15
|
{!isFirst && (
|
|
16
|
-
<S.ReorderArrow setMargin={isLast}>
|
|
16
|
+
<S.ReorderArrow data-testid="reorder-last" setMargin={isLast}>
|
|
17
17
|
{" "}
|
|
18
18
|
<IconAction icon="FullArrowUp" size="s" onClick={handleUpClick} />{" "}
|
|
19
19
|
</S.ReorderArrow>
|
|
20
20
|
)}
|
|
21
21
|
{!isLast && (
|
|
22
|
-
<S.ReorderArrow>
|
|
22
|
+
<S.ReorderArrow data-testid="reorder-first">
|
|
23
23
|
{" "}
|
|
24
24
|
<IconAction icon="FullArrowDown" size="s" onClick={handleDownClick} />{" "}
|
|
25
25
|
</S.ReorderArrow>
|
|
@@ -30,7 +30,7 @@ const ReorderArrows = (props: IReorderArrows): JSX.Element => {
|
|
|
30
30
|
return <>{showReorderArrows && <Arrows />}</>;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
interface IReorderArrows {
|
|
33
|
+
export interface IReorderArrows {
|
|
34
34
|
index: number;
|
|
35
35
|
listLength: number;
|
|
36
36
|
handleUpClick: (e: any) => void;
|
|
@@ -2,46 +2,37 @@ import React from "react";
|
|
|
2
2
|
|
|
3
3
|
import * as S from "./style";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
window.addEventListener("
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
window.removeEventListener("
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public handleMouseUp = () => {
|
|
26
|
-
this.removeListeners();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
public handleResize = (e: MouseEvent) => {
|
|
5
|
+
const ResizeHandle = (props: IResizeHandleProps): JSX.Element => {
|
|
6
|
+
const { left } = props;
|
|
7
|
+
|
|
8
|
+
const initListeners = () => {
|
|
9
|
+
window.addEventListener("mousemove", handleResize, false);
|
|
10
|
+
window.addEventListener("mouseup", handleMouseUp, false);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const removeListeners = () => {
|
|
14
|
+
window.removeEventListener("mousemove", handleResize, false);
|
|
15
|
+
window.removeEventListener("mouseup", handleMouseUp, false);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const handleMouseDown = () => initListeners();
|
|
19
|
+
|
|
20
|
+
const handleMouseUp = () => removeListeners();
|
|
21
|
+
|
|
22
|
+
const handleResize = (e: MouseEvent) => {
|
|
30
23
|
e.preventDefault();
|
|
31
|
-
const { onMouseMove } =
|
|
32
|
-
const newWidth = window.document.body.offsetWidth - e.
|
|
24
|
+
const { onMouseMove } = props;
|
|
25
|
+
const newWidth = window.document.body.offsetWidth - e.clientX;
|
|
33
26
|
onMouseMove(newWidth);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<S.HandlerWrapper>
|
|
31
|
+
<S.Handler onMouseDown={handleMouseDown} left={left ? left : 0} data-testid="handler" />
|
|
32
|
+
</S.HandlerWrapper>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
45
36
|
export interface IResizeHandleProps {
|
|
46
37
|
onMouseMove: (value: number) => void;
|
|
47
38
|
left?: number;
|
|
@@ -3,7 +3,7 @@ import ResizeHandle from "./ResizeHandle";
|
|
|
3
3
|
|
|
4
4
|
import * as S from "./style";
|
|
5
5
|
|
|
6
|
-
const ResizePanel = (props:
|
|
6
|
+
const ResizePanel = (props: IResizePanelProps): JSX.Element => {
|
|
7
7
|
const { leftPanel, rightPanel, fixed = true } = props;
|
|
8
8
|
|
|
9
9
|
const [rwidth, setRwidth] = useState(0);
|
|
@@ -12,7 +12,6 @@ const ResizePanel = (props: IProps): JSX.Element => {
|
|
|
12
12
|
const rightPanelRef = useRef<HTMLDivElement>(null);
|
|
13
13
|
|
|
14
14
|
useEffect(() => {
|
|
15
|
-
|
|
16
15
|
if (rightPanelRef.current) {
|
|
17
16
|
setRwidth(rightPanelRef.current.offsetWidth);
|
|
18
17
|
}
|
|
@@ -22,8 +21,7 @@ const ResizePanel = (props: IProps): JSX.Element => {
|
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
window.addEventListener("scroll", handleScroll);
|
|
25
|
-
|
|
26
|
-
},[rightPanelRef]);
|
|
24
|
+
}, [rightPanelRef]);
|
|
27
25
|
|
|
28
26
|
const resize = (value: number) => {
|
|
29
27
|
if (value > 344) {
|
|
@@ -33,24 +31,24 @@ const ResizePanel = (props: IProps): JSX.Element => {
|
|
|
33
31
|
|
|
34
32
|
return (
|
|
35
33
|
<>
|
|
36
|
-
{
|
|
37
|
-
<S.LeftPanel>
|
|
38
|
-
<S.FixedPanel width={rwidth} left={scroll}>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<S.LeftPanel>
|
|
42
|
-
{leftPanel}
|
|
34
|
+
{fixed ? (
|
|
35
|
+
<S.LeftPanel data-testid="left-panel-fixed">
|
|
36
|
+
<S.FixedPanel width={rwidth} left={scroll} data-testid="fixed-panel">
|
|
37
|
+
{leftPanel}
|
|
38
|
+
</S.FixedPanel>
|
|
43
39
|
</S.LeftPanel>
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
) : (
|
|
41
|
+
<S.LeftPanel data-testid="left-panel">{leftPanel}</S.LeftPanel>
|
|
42
|
+
)}
|
|
43
|
+
<S.RightPanel width={rwidth} ref={rightPanelRef} data-testid="right-panel">
|
|
46
44
|
<ResizeHandle left={scroll} onMouseMove={resize} />
|
|
47
|
-
|
|
45
|
+
{rightPanel}
|
|
48
46
|
</S.RightPanel>
|
|
49
47
|
</>
|
|
50
48
|
);
|
|
51
49
|
};
|
|
52
50
|
|
|
53
|
-
interface
|
|
51
|
+
export interface IResizePanelProps {
|
|
54
52
|
leftPanel: JSX.Element | JSX.Element[];
|
|
55
53
|
rightPanel: JSX.Element | JSX.Element[];
|
|
56
54
|
fixed?: boolean;
|
|
@@ -4,7 +4,7 @@ import { Select } from "../Fields";
|
|
|
4
4
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
|
-
const SearchField = (props:
|
|
7
|
+
const SearchField = (props: ISearchFieldProps): JSX.Element => {
|
|
8
8
|
const {
|
|
9
9
|
onChange,
|
|
10
10
|
placeholder,
|
|
@@ -56,12 +56,12 @@ const SearchField = (props: IProps): JSX.Element => {
|
|
|
56
56
|
const showField = isOpen || !closeOnInactive;
|
|
57
57
|
|
|
58
58
|
return (
|
|
59
|
-
<S.Wrapper>
|
|
59
|
+
<S.Wrapper data-testid="search-field-wrapper">
|
|
60
60
|
{showField ? (
|
|
61
|
-
<S.FieldWrapper closeOnInactive={closeOnInactive} disabled={disabled}>
|
|
61
|
+
<S.FieldWrapper closeOnInactive={closeOnInactive} disabled={disabled} data-testid="field-wrapper">
|
|
62
62
|
{searchFilters && searchFilters.length && (
|
|
63
63
|
<>
|
|
64
|
-
<S.FilterWrapper>
|
|
64
|
+
<S.FilterWrapper data-testid="filter-wrapper">
|
|
65
65
|
<Select
|
|
66
66
|
name="filterSelect"
|
|
67
67
|
value={selectValue}
|
|
@@ -82,20 +82,21 @@ const SearchField = (props: IProps): JSX.Element => {
|
|
|
82
82
|
placeholder={placeholder}
|
|
83
83
|
closeOnInactive={closeOnInactive}
|
|
84
84
|
disabled={disabled}
|
|
85
|
+
data-testid="search-input"
|
|
85
86
|
/>
|
|
86
87
|
{inputValue.trim() !== "" && searchOnEnter && <S.HelpText>Press ENTER</S.HelpText>}
|
|
87
88
|
{closeOnInactive || inputValue.length > 0 ? (
|
|
88
|
-
<S.IconCloseWrapper onClick={handleClick}>
|
|
89
|
+
<S.IconCloseWrapper onClick={handleClick} data-testid="icon-close-wrapper">
|
|
89
90
|
<Icon name="close" size="24" />
|
|
90
91
|
</S.IconCloseWrapper>
|
|
91
92
|
) : (
|
|
92
|
-
<S.IconSearchWrapper disabled={disabled}>
|
|
93
|
+
<S.IconSearchWrapper disabled={disabled} data-testid="icon-search-wrapper-2">
|
|
93
94
|
<Icon name="search" size="24" />
|
|
94
95
|
</S.IconSearchWrapper>
|
|
95
96
|
)}
|
|
96
97
|
</S.FieldWrapper>
|
|
97
98
|
) : (
|
|
98
|
-
<S.IconSearchWrapper disabled={disabled} onClick={toggleField}>
|
|
99
|
+
<S.IconSearchWrapper disabled={disabled} onClick={toggleField} data-testid="icon-search-wrapper">
|
|
99
100
|
<Icon name="search" size="24" />
|
|
100
101
|
</S.IconSearchWrapper>
|
|
101
102
|
)}
|
|
@@ -103,7 +104,7 @@ const SearchField = (props: IProps): JSX.Element => {
|
|
|
103
104
|
);
|
|
104
105
|
};
|
|
105
106
|
|
|
106
|
-
interface
|
|
107
|
+
export interface ISearchFieldProps {
|
|
107
108
|
onChange(query: string): void;
|
|
108
109
|
placeholder?: string;
|
|
109
110
|
closeOnInactive?: boolean;
|
|
@@ -28,7 +28,10 @@ function getAnalytics(siteId: number | string = "global"): (dispatch: any) => Pr
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function updateAnalytics(
|
|
31
|
+
function updateAnalytics(
|
|
32
|
+
analyticsState: IAnalytics,
|
|
33
|
+
siteId: number | string = "global"
|
|
34
|
+
): (dispatch: any) => Promise<boolean> {
|
|
32
35
|
return async (dispatch) => {
|
|
33
36
|
try {
|
|
34
37
|
const { scriptCode, dimensions, groups } = analyticsState;
|
|
@@ -38,13 +41,20 @@ function updateAnalytics(analyticsState: IAnalytics, siteId: number | string = "
|
|
|
38
41
|
promises.push(analytics.createDimensions(siteId, { dimensions }));
|
|
39
42
|
promises.push(analytics.createDimensionsGroups(siteId, { groups }));
|
|
40
43
|
return Promise.all(promises);
|
|
41
|
-
}
|
|
44
|
+
};
|
|
42
45
|
|
|
43
46
|
const responseActions = {
|
|
44
47
|
handleSuccess: () => {
|
|
45
48
|
dispatch(getAnalytics());
|
|
46
49
|
},
|
|
47
|
-
handleError: (response: any) =>
|
|
50
|
+
handleError: (response: any) => {
|
|
51
|
+
const {
|
|
52
|
+
data: { message },
|
|
53
|
+
} = response;
|
|
54
|
+
const isMultiple = Array.isArray(message) && message.length > 1;
|
|
55
|
+
const msg = isMultiple ? `The action failed due to ${message.length} errors.` : undefined;
|
|
56
|
+
appActions.handleError(response, isMultiple, msg)(dispatch);
|
|
57
|
+
},
|
|
48
58
|
};
|
|
49
59
|
|
|
50
60
|
return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
|
|
@@ -60,7 +70,7 @@ function updateScriptCode(scriptCode: string, siteId: number): (dispatch: any) =
|
|
|
60
70
|
try {
|
|
61
71
|
const callback = async () => {
|
|
62
72
|
return analytics.updateScriptCode(siteId, { scriptCode });
|
|
63
|
-
}
|
|
73
|
+
};
|
|
64
74
|
|
|
65
75
|
const responseActions = {
|
|
66
76
|
handleSuccess: () => {
|
|
@@ -97,15 +97,25 @@ function resetError(): ISetErrorAction {
|
|
|
97
97
|
return { type: RESET_ERROR, payload: { code: undefined, text: "" } };
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
function handleError(response: any): (dispatch: Dispatch) => Promise<void> {
|
|
100
|
+
function handleError(response: any, isMultiple = false, msg?: string): (dispatch: Dispatch) => Promise<void> {
|
|
101
101
|
return async (dispatch) => {
|
|
102
|
-
const {
|
|
102
|
+
const {
|
|
103
|
+
data: { code, message },
|
|
104
|
+
btnText,
|
|
105
|
+
actionsBelow,
|
|
106
|
+
text,
|
|
107
|
+
} = response;
|
|
108
|
+
|
|
109
|
+
const firstMsg = Array.isArray(message) ? message[0].error : message || text;
|
|
110
|
+
|
|
103
111
|
const error = {
|
|
104
|
-
code
|
|
105
|
-
text:
|
|
112
|
+
code,
|
|
113
|
+
text: msg ? msg : firstMsg,
|
|
106
114
|
btnText,
|
|
107
115
|
actionsBelow,
|
|
116
|
+
subErrors: isMultiple ? message : [],
|
|
108
117
|
};
|
|
118
|
+
|
|
109
119
|
dispatch(setError(error));
|
|
110
120
|
};
|
|
111
121
|
}
|
|
@@ -117,7 +127,7 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
|
|
|
117
127
|
const loginResponse: any = await global.login(email, password);
|
|
118
128
|
dispatch(setIsLogging(false));
|
|
119
129
|
switch (loginResponse.status) {
|
|
120
|
-
case 200:
|
|
130
|
+
case 200: {
|
|
121
131
|
const {
|
|
122
132
|
data: { token },
|
|
123
133
|
} = loginResponse;
|
|
@@ -130,7 +140,8 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
|
|
|
130
140
|
localStorage.setItem("user", JSON.stringify(user));
|
|
131
141
|
}
|
|
132
142
|
break;
|
|
133
|
-
|
|
143
|
+
}
|
|
144
|
+
case 403: {
|
|
134
145
|
const error = {
|
|
135
146
|
...loginResponse,
|
|
136
147
|
btnText: "Lost your password?",
|
|
@@ -138,6 +149,7 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
|
|
|
138
149
|
};
|
|
139
150
|
handleError(error)(dispatch);
|
|
140
151
|
break;
|
|
152
|
+
}
|
|
141
153
|
default:
|
|
142
154
|
handleError(loginResponse)(dispatch);
|
|
143
155
|
break;
|
|
@@ -37,7 +37,14 @@ function updateDomainsRobots(robots: IDomainRobot[]): (dispatch: any) => Promise
|
|
|
37
37
|
handleSuccess: () => {
|
|
38
38
|
dispatch(getDomainsRobots());
|
|
39
39
|
},
|
|
40
|
-
handleError: (response: any) =>
|
|
40
|
+
handleError: (response: any) => {
|
|
41
|
+
const {
|
|
42
|
+
data: { message },
|
|
43
|
+
} = response;
|
|
44
|
+
const isMultiple = Array.isArray(message) && message.length > 1;
|
|
45
|
+
const msg = isMultiple ? `The action failed due to ${message.length} errors.` : undefined;
|
|
46
|
+
appActions.handleError(response, isMultiple, msg)(dispatch);
|
|
47
|
+
},
|
|
41
48
|
};
|
|
42
49
|
|
|
43
50
|
return await handleRequest(callback, responseActions, [appActions.setIsSaving])(dispatch);
|
|
@@ -309,10 +309,17 @@ function deleteNavigation(
|
|
|
309
309
|
const responseActions = {
|
|
310
310
|
handleSuccess: () => getNavigationByType(type)(dispatch, getState),
|
|
311
311
|
handleError: (response: any) => {
|
|
312
|
+
const {
|
|
313
|
+
data: { message },
|
|
314
|
+
} = response;
|
|
315
|
+
|
|
312
316
|
if (isBulk) {
|
|
313
317
|
getNavigationByType(type)(dispatch, getState);
|
|
314
318
|
}
|
|
315
|
-
|
|
319
|
+
|
|
320
|
+
const isMultiple = Array.isArray(message) && message.length > 1;
|
|
321
|
+
const msg = isMultiple ? `The delete action failed due to ${message.length} errors.` : undefined;
|
|
322
|
+
appActions.handleError(response, isMultiple, msg)(dispatch);
|
|
316
323
|
},
|
|
317
324
|
};
|
|
318
325
|
|
|
@@ -335,7 +342,14 @@ function restoreNavigation(
|
|
|
335
342
|
try {
|
|
336
343
|
const responseActions = {
|
|
337
344
|
handleSuccess: () => getNavigationByType(type)(dispatch, getState),
|
|
338
|
-
handleError: (response: any) =>
|
|
345
|
+
handleError: (response: any) => {
|
|
346
|
+
const {
|
|
347
|
+
data: { message },
|
|
348
|
+
} = response;
|
|
349
|
+
const isMultiple = Array.isArray(message) && message.length > 1;
|
|
350
|
+
const msg = isMultiple ? `The restore action failed due to ${message.length} errors.` : undefined;
|
|
351
|
+
appActions.handleError(response, isMultiple, msg)(dispatch);
|
|
352
|
+
},
|
|
339
353
|
};
|
|
340
354
|
|
|
341
355
|
const callback = async () =>
|