@griddo/ax 10.1.69 → 10.1.71

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.
Files changed (50) hide show
  1. package/config/jest/setup.js +14 -4
  2. package/package.json +5 -2
  3. package/public/img/logos/logoSQY.svg +3 -0
  4. package/public/img/slider/analytics.png +0 -0
  5. package/public/img/slider/content.png +0 -0
  6. package/public/img/slider/editor.png +0 -0
  7. package/public/img/slider/gallery.png +0 -0
  8. package/public/img/slider/left-on.svg +4 -0
  9. package/public/img/slider/left.svg +4 -0
  10. package/public/img/slider/right-on.svg +4 -0
  11. package/public/img/slider/right.svg +4 -0
  12. package/src/__tests__/components/Login/Login.test.tsx +5 -7
  13. package/src/api/integrations.tsx +18 -1
  14. package/src/components/Fields/CheckField/index.tsx +6 -12
  15. package/src/components/Fields/CheckField/style.tsx +16 -6
  16. package/src/components/Fields/NoteField/style.tsx +8 -8
  17. package/src/components/Fields/TextField/index.tsx +3 -1
  18. package/src/components/Fields/TextField/style.tsx +6 -1
  19. package/src/components/Fields/UniqueCheck/index.tsx +3 -1
  20. package/src/components/FieldsBehavior/index.tsx +4 -3
  21. package/src/components/FieldsBehavior/style.tsx +35 -22
  22. package/src/components/Login/Circle/index.tsx +16 -0
  23. package/src/components/Login/Circle/style.tsx +30 -0
  24. package/src/components/Login/LoginSlider/index.tsx +63 -0
  25. package/src/components/Login/LoginSlider/style.tsx +68 -0
  26. package/src/components/Login/index.tsx +102 -58
  27. package/src/components/Login/style.tsx +121 -16
  28. package/src/components/MainWrapper/AppBar/index.tsx +5 -1
  29. package/src/components/MainWrapper/AppBar/style.tsx +17 -1
  30. package/src/components/MainWrapper/index.tsx +3 -1
  31. package/src/components/MainWrapper/style.tsx +35 -4
  32. package/src/components/TableList/index.tsx +3 -5
  33. package/src/containers/App/actions.tsx +23 -7
  34. package/src/containers/App/constants.tsx +2 -0
  35. package/src/containers/App/interfaces.tsx +6 -0
  36. package/src/containers/App/reducer.tsx +4 -0
  37. package/src/containers/Integrations/actions.tsx +32 -2
  38. package/src/modules/Login/index.tsx +16 -3
  39. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/index.tsx +1 -1
  40. package/src/modules/Settings/Integrations/BulkHeader/TableHeader/style.tsx +2 -2
  41. package/src/modules/Settings/Integrations/IntegrationForm/index.tsx +2 -1
  42. package/src/modules/Settings/Integrations/IntegrationItem/index.tsx +27 -13
  43. package/src/modules/Settings/Integrations/IntegrationItem/style.tsx +32 -5
  44. package/src/modules/Settings/Integrations/index.tsx +114 -81
  45. package/src/modules/Settings/Integrations/style.tsx +20 -1
  46. package/src/modules/Sites/SitesList/index.tsx +18 -3
  47. package/src/modules/Sites/SitesList/style.tsx +28 -1
  48. package/src/modules/Sites/index.tsx +4 -1
  49. package/src/themes/theme.json +4 -0
  50. package/src/types/index.tsx +2 -0
@@ -0,0 +1,68 @@
1
+ import styled, { keyframes } from "styled-components";
2
+
3
+ const PrevAnimation = keyframes`
4
+ to {
5
+ opacity: 0;
6
+ }
7
+ }`;
8
+
9
+ const Wrapper = styled.div`
10
+ position: relative;
11
+ bottom: 0;
12
+
13
+ .prev-slide-anim {
14
+ opacity: 1;
15
+ animation: ${PrevAnimation} 0.8s ease-out;
16
+ animation-fill-mode: forwards;
17
+ }
18
+ `;
19
+
20
+ const BannerWrapper = styled.div`
21
+ position: relative;
22
+ width: 100%;
23
+ height: 100vh;
24
+ padding-left: 100px;
25
+ `;
26
+
27
+ const Title = styled.div`
28
+ color: ${(p) => p.theme.color.textHighEmphasisInverse};
29
+ font-family: Source Sans Pro;
30
+ font-size: 36px;
31
+ font-weight: 300;
32
+ line-height: 48px;
33
+ letter-spacing: 0px;
34
+ text-align: left;
35
+ padding-top: 140px;
36
+ width: 450px;
37
+ `;
38
+
39
+ const Image = styled.div<{ image: string }>`
40
+ background: no-repeat top left url(${(p) => p.image});
41
+ background-size: 130%;
42
+ width: 100%;
43
+ height: 100%;
44
+ margin-top: ${(p) => p.theme.spacing.l};
45
+ `;
46
+
47
+ const Buttons = styled.div`
48
+ display: flex;
49
+ position: absolute;
50
+ left: 100px;
51
+ top: 64px;
52
+ z-index: 10;
53
+ `;
54
+
55
+ const Arrow = styled.div<{ direction: string }>`
56
+ background: ${(p) => `no-repeat url("/img/slider/${p.direction}.svg")`};
57
+ width: 40px;
58
+ height: 40px;
59
+ cursor: pointer;
60
+ &:last-child {
61
+ margin-left: ${(p) => p.theme.spacing.s};
62
+ }
63
+ &:hover {
64
+ background: ${(p) => `no-repeat url("/img/slider/${p.direction}-on.svg")`};
65
+ }
66
+ `;
67
+
68
+ export { Wrapper, BannerWrapper, Title, Image, Buttons, Arrow };
@@ -1,9 +1,10 @@
1
- import React, { useState } from "react";
1
+ import React, { useEffect, useRef, useState } from "react";
2
2
 
3
3
  import { IGlobalSettings } from "@ax/containers/App/reducer";
4
4
  import { useModal } from "@ax/hooks";
5
5
  import { Button, FieldsBehavior, ErrorToast } from "@ax/components";
6
6
  import RecoveryModal from "./RecoveryModal";
7
+ import Circle from "./Circle";
7
8
 
8
9
  import * as S from "./style";
9
10
 
@@ -24,78 +25,119 @@ const Login = (props: ILoginProps): JSX.Element => {
24
25
  settings,
25
26
  rememberMe,
26
27
  handleRememberMe,
28
+ isLoginSuccess,
29
+ handleLoginSuccess,
27
30
  } = props;
28
31
 
29
32
  const [viewPass, setViewPass] = useState(false);
33
+ const [wrapperWidth, setWrapperWidth] = useState<number>(0);
30
34
  const { isOpen, toggleModal } = useModal();
35
+ const wrapperRef = useRef<HTMLDivElement>(null);
36
+
37
+ useEffect(() => {
38
+ const handleResize = () => wrapperRef.current && setWrapperWidth(wrapperRef.current.clientWidth);
39
+
40
+ window.addEventListener("resize", handleResize, false);
41
+
42
+ if (wrapperRef.current) {
43
+ setWrapperWidth(wrapperRef.current.clientWidth);
44
+ }
45
+ }, [wrapperRef.current]);
46
+
31
47
  window.handleErrorClick = toggleModal;
32
- const _handleEmail = (e: string) => handleEmail(e);
33
48
 
34
- const textWelcome = settings.welcomeText1 ? settings.welcomeText1 : "";
35
- const textName = settings.welcomeText2 ? settings.welcomeText2 : "";
49
+ const _handleEmail = (e: string) => handleEmail(e);
36
50
 
37
51
  const _handlePwd = (e: string) => handlePassword(e);
38
- const btnText = isLoggingIn ? "Sending" : "Log in";
39
52
 
40
53
  const _togglePassword = () => setViewPass(!viewPass);
54
+
55
+ const _handleAnimationEnd = () => handleLoginSuccess();
56
+
57
+ const btnText = isLoggingIn ? "Sending" : "Login";
58
+
41
59
  const inputType = viewPass ? "text" : "password";
42
60
  const icon = viewPass ? "hide" : "view";
43
61
 
62
+ const textName = settings.welcomeText2 ? settings.welcomeText2 : "Griddo";
63
+ const nameLogo =
64
+ textName === "Griddo" ? <img src="/img/logos/logoGriddoExtended@3x.svg" alt="Griddo Logo" /> : textName;
65
+
44
66
  return (
45
67
  <S.Wrapper data-testid="login-wrapper">
46
- <S.Main>
47
- <S.Header>
48
- <S.Subtitle>{textWelcome}</S.Subtitle>
49
- <S.Title>{textName}</S.Title>
50
- </S.Header>
51
- <ErrorToast />
52
- <S.Form onSubmit={handleSubmit}>
53
- <FieldsBehavior
54
- fieldType="TextField"
55
- title="Email"
56
- autoComplete="email"
57
- value={email}
58
- onChange={_handleEmail}
59
- name="email"
60
- />
61
- <FieldsBehavior
62
- fieldType="TextField"
63
- title="Password"
64
- inputType={inputType}
65
- value={password}
66
- onChange={_handlePwd}
67
- autoComplete="current-password"
68
- icon={icon}
69
- onClickIcon={_togglePassword}
70
- iconPosition="in"
71
- name="password"
72
- />
73
- <FieldsBehavior
74
- fieldType="UniqueCheck"
75
- title=""
76
- value={rememberMe}
77
- onChange={handleRememberMe}
78
- options={[{ title: "Remember me" }]}
79
- name="rememberMe"
80
- />
81
- <Button type="submit" disabled={isLoggingIn ? true : false}>
82
- {btnText}
83
- </Button>
84
- <S.Password>
85
- <span
86
- onClick={toggleModal}
87
- onKeyPress={toggleModal}
88
- role="checkbox"
89
- aria-checked="false"
90
- tabIndex={0}
91
- data-testid="forgot-button"
92
- >
93
- Forgot your password?
94
- </span>
95
- </S.Password>
96
- <RecoveryModal isOpen={isOpen} toggleModal={toggleModal} />
97
- </S.Form>
98
- </S.Main>
68
+ <S.LeftWrapper className={isLoginSuccess ? "animate" : ""} onAnimationEnd={_handleAnimationEnd} ref={wrapperRef}>
69
+ <S.LoginWrapper className={isLoginSuccess ? "animate" : ""} width={wrapperWidth}>
70
+ <S.Main>
71
+ <S.Header>
72
+ <S.Title>
73
+ <div>Welcome to</div>
74
+ <div>{nameLogo}</div>
75
+ </S.Title>
76
+ <S.Subtitle>To start using {textName}, introduce your email and password.</S.Subtitle>
77
+ </S.Header>
78
+ <ErrorToast />
79
+ <S.Form onSubmit={handleSubmit}>
80
+ <FieldsBehavior
81
+ fieldType="TextField"
82
+ title="Email"
83
+ autoComplete="email"
84
+ value={email}
85
+ onChange={_handleEmail}
86
+ name="email"
87
+ inversed={true}
88
+ placeholder="Type your email"
89
+ />
90
+ <FieldsBehavior
91
+ fieldType="TextField"
92
+ title="Password"
93
+ inputType={inputType}
94
+ value={password}
95
+ onChange={_handlePwd}
96
+ autoComplete="current-password"
97
+ icon={icon}
98
+ onClickIcon={_togglePassword}
99
+ iconPosition="in"
100
+ name="password"
101
+ inversed={true}
102
+ />
103
+ <S.Actions>
104
+ <FieldsBehavior
105
+ fieldType="UniqueCheck"
106
+ title=""
107
+ value={rememberMe}
108
+ onChange={handleRememberMe}
109
+ options={[{ title: "Remember me" }]}
110
+ name="rememberMe"
111
+ inversed={true}
112
+ />
113
+ <S.Password>
114
+ <span
115
+ onClick={toggleModal}
116
+ role="checkbox"
117
+ aria-checked="false"
118
+ tabIndex={0}
119
+ data-testid="forgot-button"
120
+ >
121
+ Lost your password?
122
+ </span>
123
+ </S.Password>
124
+ </S.Actions>
125
+ <Button type="submit" disabled={isLoggingIn ? true : false}>
126
+ {btnText}
127
+ </Button>
128
+ <RecoveryModal isOpen={isOpen} toggleModal={toggleModal} />
129
+ </S.Form>
130
+ </S.Main>
131
+ <S.Secuoyas width={wrapperWidth}>
132
+ Made with care at <img src="/img/logos/logoSQY.svg" alt="Secuoyas logo" />
133
+ </S.Secuoyas>
134
+ </S.LoginWrapper>
135
+ </S.LeftWrapper>
136
+ <S.RightWrapper>
137
+ <Circle animation={1} />
138
+ <Circle animation={2} />
139
+ <S.AnimatedLoginSlider className={isLoginSuccess ? "animate" : ""} />
140
+ </S.RightWrapper>
99
141
  </S.Wrapper>
100
142
  );
101
143
  };
@@ -110,6 +152,8 @@ export interface ILoginProps {
110
152
  settings: IGlobalSettings;
111
153
  rememberMe: boolean;
112
154
  handleRememberMe: () => void;
155
+ isLoginSuccess: boolean;
156
+ handleLoginSuccess: () => void;
113
157
  }
114
158
 
115
159
  export default Login;
@@ -1,33 +1,103 @@
1
- import styled from "styled-components";
1
+ import styled, { keyframes } from "styled-components";
2
+ import LoginSlider from "./LoginSlider";
2
3
 
3
4
  const Wrapper = styled.section`
5
+ position: relative;
6
+ display: flex;
4
7
  height: 100vh;
5
- width: 100vw;
8
+ background: ${(p) => p.theme.color.uiBackground04};
9
+ flex-direction: row;
10
+ `;
11
+
12
+ const LoginAnimation = keyframes`
13
+ to {
14
+ width: 100%;
15
+ }
16
+ }`;
17
+
18
+ const OpacityAnimation = keyframes`
19
+ to {
20
+ opacity: 0;
21
+ }
22
+ }`;
23
+
24
+ const LeftWrapper = styled.div`
25
+ position: relative;
26
+ display: flex;
27
+ width: 45%;
28
+ background: ${(p) => p.theme.color.uiBackground04};
29
+
30
+ &.animate {
31
+ position: absolute;
32
+ top: 0;
33
+ left: 0;
34
+ bottom: 0;
35
+ z-index: 2;
36
+ animation: ${LoginAnimation} 1.2s ease-in;
37
+ animation-fill-mode: forwards;
38
+ }
39
+ `;
40
+
41
+ const LoginWrapper = styled.div<{ width: number }>`
42
+ width: ${(p) => p.width > 0 ? `${p.width}px` : "100%"};
6
43
  display: flex;
7
44
  align-items: center;
8
45
  justify-content: center;
9
- background: ${(p) => p.theme.color.uiBackground01};
46
+
47
+ &.animate {
48
+ opacity: 1;
49
+ margin-right: auto;
50
+ animation: ${OpacityAnimation} 1.2s ease-in;
51
+ animation-fill-mode: forwards;
52
+ }
10
53
  `;
11
54
 
12
- const Main = styled.div`
13
- width: calc(${(p) => p.theme.spacing.xl} * 5);
55
+ const RightWrapper = styled.div`
56
+ background-color: #001B3C;
57
+ position: relative;
58
+ width: 55%;
59
+ height: 100%;
60
+ color: ${(p) => p.theme.color.textHighEmphasisInverse};
61
+ margin-left: auto;
62
+ z-index: 1;
63
+ overflow: hidden;
14
64
  `;
15
65
 
16
- const Header = styled.header`
17
- text-align: center;
18
- border-bottom: 1px solid ${(p) => p.theme.color.uiLine};
19
- padding-bottom: ${(p) => p.theme.spacing.m};
66
+ const AnimatedLoginSlider = styled(LoginSlider)`
67
+ &.animate {
68
+ opacity: 1;
69
+ animation: ${OpacityAnimation} 1.2s ease-in;
70
+ animation-fill-mode: forwards;
71
+ }
20
72
  `;
21
73
 
74
+ const Main = styled.div`
75
+ width: 368px;
76
+ `;
77
+
78
+ const Header = styled.header``;
79
+
22
80
  const Subtitle = styled.p`
23
- ${(p) => p.theme.textStyle.headingXXS};
24
- color: ${(p) => p.theme.color.textMediumEmphasis};
81
+ ${(p) => p.theme.textStyle.uiM};
82
+ color: ${(p) => p.theme.color.textMediumEmphasisInverse};
25
83
  font-weight: normal;
26
84
  margin-bottom: ${(p) => p.theme.spacing.xs};
85
+ width: 280px;
27
86
  `;
28
87
 
29
- const Title = styled.h1`
88
+ const Title = styled.div`
30
89
  ${(p) => p.theme.textStyle.headingM};
90
+ color: ${(p) => p.theme.color.textHighEmphasisInverse};
91
+ display: flex;
92
+ margin-bottom: ${(p) => p.theme.spacing.xs};
93
+ align-items: center;
94
+ div:last-child {
95
+ margin-left: ${(p) => p.theme.spacing.xxs};
96
+ }
97
+ img {
98
+ height: 24px;
99
+ margin-top: ${(p) => p.theme.spacing.xxs};
100
+ }
31
101
  `;
32
102
 
33
103
  const Form = styled.form`
@@ -38,14 +108,49 @@ const Form = styled.form`
38
108
 
39
109
  const Password = styled.div`
40
110
  ${(p) => p.theme.textStyle.uiS};
41
- color: ${(p) => p.theme.color.interactive01};
42
- margin-top: ${(p) => p.theme.spacing.m};
111
+ color: ${(p) => p.theme.color.interactiveInverse};
43
112
  width: 100%;
44
- text-align: center;
113
+ text-align: right;
45
114
 
46
115
  span {
47
116
  cursor: pointer;
48
117
  }
49
118
  `;
50
119
 
51
- export { Wrapper, Main, Header, Subtitle, Title, Form, Password };
120
+ const Actions = styled.div`
121
+ display: flex;
122
+ `;
123
+
124
+ const Secuoyas = styled.div<{ width: number }>`
125
+ ${(p) => p.theme.textStyle.uiXS};
126
+ position: absolute;
127
+ display: flex;
128
+ color: ${(p) => p.theme.color.textMediumEmphasisInverse};
129
+ width: ${(p) => p.width > 0 ? `${p.width}px` : "100%"};
130
+ justify-content: center;
131
+ align-items: center;
132
+ left: 0;
133
+ bottom: ${(p) => p.theme.spacing.m};
134
+ padding-bottom: ${(p) => p.theme.spacing.xs};
135
+ img {
136
+ width: 20px;
137
+ height: 20px;
138
+ margin-left: ${(p) => p.theme.spacing.xs};
139
+ }
140
+ `;
141
+
142
+ export {
143
+ Wrapper,
144
+ Main,
145
+ Header,
146
+ Subtitle,
147
+ Title,
148
+ Form,
149
+ Password,
150
+ Actions,
151
+ Secuoyas,
152
+ LeftWrapper,
153
+ RightWrapper,
154
+ LoginWrapper,
155
+ AnimatedLoginSlider,
156
+ };
@@ -45,6 +45,7 @@ const AppBar = (props: IProps): JSX.Element => {
45
45
  pageStatusActions,
46
46
  filterSearchAction,
47
47
  searchFilters,
48
+ hasAnimation,
48
49
  } = props;
49
50
 
50
51
  const publishedTooltip: any = {
@@ -152,8 +153,10 @@ const AppBar = (props: IProps): JSX.Element => {
152
153
 
153
154
  const languageTooltip = typeof currentPageID === "number" && "Add language";
154
155
 
156
+ const classes = hasAnimation ? `${fixedClass} ${additionalClass} animate` : `${fixedClass} ${additionalClass}`
157
+
155
158
  return (
156
- <S.Header className={`${fixedClass} ${additionalClass}`} inversed={inversed} data-testid="appbar-header">
159
+ <S.Header className={classes} inversed={inversed} data-testid="appbar-header">
157
160
  <S.WrapperTitle>
158
161
  {backLink && (
159
162
  <span data-testid="back-button-wrapper">
@@ -288,6 +291,7 @@ export interface IAppBarProps {
288
291
  };
289
292
  isFromEditor?: boolean;
290
293
  pageStatusActions?: any[];
294
+ hasAnimation?: boolean;
291
295
  }
292
296
 
293
297
  type IProps = IAppBarProps & RouteComponentProps;
@@ -1,4 +1,13 @@
1
- import styled from "styled-components";
1
+ import styled, { keyframes } from "styled-components";
2
+
3
+ const OpacityAnimation = keyframes`
4
+ from {
5
+ opacity: 0;
6
+ }
7
+ to {
8
+ opacity: 1;
9
+ }
10
+ }`;
2
11
 
3
12
  const ActionMenu = styled.ul``;
4
13
 
@@ -131,6 +140,7 @@ const Header = styled.section<{ inversed?: boolean }>`
131
140
  background: ${(p) => (p.inversed ? p.theme.color.uiMainMenuBackground : p.theme.color.uiBackground02)};
132
141
  display: flex;
133
142
  padding-right: ${(p) => p.theme.spacing.s};
143
+ border-bottom: ${(p) => `1px solid ${p.theme.color.uiLine}`};
134
144
 
135
145
  button:first-child {
136
146
  margin-left: ${(p) => p.theme.spacing.m};
@@ -152,6 +162,12 @@ const Header = styled.section<{ inversed?: boolean }>`
152
162
  z-index: 999;
153
163
  }
154
164
 
165
+ &.animate {
166
+ opacity: 0;
167
+ animation: ${OpacityAnimation} 1s ease-in 1.2s;
168
+ animation-fill-mode: forwards;
169
+ }
170
+
155
171
  ${Title} {
156
172
  color: ${(p) => (p.inversed ? p.theme.color.textHighEmphasisInverse : p.theme.color.textHighEmphasis)};
157
173
  }
@@ -6,10 +6,11 @@ import AppBar from "./AppBar";
6
6
  import * as S from "./style";
7
7
 
8
8
  const MainWrapper = (props: IWrapperProps): JSX.Element => {
9
- const { children, fixedAppBar, fullWidth } = props;
9
+ const { children, fixedAppBar, fullWidth, hasAnimation } = props;
10
10
 
11
11
  return (
12
12
  <S.Wrapper fixedAppBar={fixedAppBar} data-testid="main-wrapper">
13
+ {hasAnimation && <S.BackgroundAnimation />}
13
14
  <AppBar {...props} />
14
15
  <S.Main fullWidth={fullWidth} data-testid="main-component" id="main-component">
15
16
  {children}
@@ -52,6 +53,7 @@ export interface IWrapperProps {
52
53
  goToPackage(): void;
53
54
  };
54
55
  pageStatusActions?: any[];
56
+ hasAnimation?: boolean;
55
57
  }
56
58
 
57
59
  export default MainWrapper;
@@ -1,17 +1,48 @@
1
- import styled from "styled-components";
1
+ import styled, { keyframes } from "styled-components";
2
2
 
3
- export const Wrapper = styled.section<{ fixedAppBar: boolean | undefined }>`
3
+ const Wrapper = styled.section<{ fixedAppBar: boolean | undefined }>`
4
4
  height: 100%;
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  padding-top: ${(p) => (p.fixedAppBar ? p.theme.spacing.xl : "0")};
8
8
  `;
9
9
 
10
- export const Main = styled.article<{ fullWidth: boolean | undefined }>`
10
+ const Main = styled.article<{ fullWidth: boolean | undefined }>`
11
11
  position: relative;
12
12
  overflow: ${(p) => (p.fullWidth ? "visible" : "auto")};
13
13
  background: ${(p) => p.theme.color.uiBackground01};
14
- border-top: ${(p) => `1px solid ${p.theme.color.uiLine}`};
15
14
  margin-top: -1px;
16
15
  flex-grow: 1;
17
16
  `;
17
+
18
+ const LoginAnimation = keyframes`
19
+ from {
20
+ width: 100%;
21
+ }
22
+ to {
23
+ width: 72px;
24
+ }
25
+ }`;
26
+
27
+ const OpacityAnimation = keyframes`
28
+ from {
29
+ opacity: 1;
30
+ }
31
+ to {
32
+ opacity: 0;
33
+ }
34
+ }`;
35
+
36
+ const BackgroundAnimation = styled.div`
37
+ position: absolute;
38
+ top: 0;
39
+ left: 0;
40
+ bottom: 0;
41
+ width: 100%;
42
+ background-color: ${(p) => p.theme.color.uiMainMenuBackground};
43
+ z-index: 10;
44
+ animation: ${LoginAnimation} 1.2s ease-in, ${OpacityAnimation} 1s ease-in 1.2s;
45
+ animation-fill-mode: forwards;
46
+ `;
47
+
48
+ export { Wrapper, Main, BackgroundAnimation };
@@ -8,9 +8,7 @@ import * as S from "./style";
8
8
  const TableList = (props: ITableListProps): JSX.Element => {
9
9
  const { tableHeader, children, pagination, isLoading, onScroll, hasFixedHeader, tableRef } = props;
10
10
 
11
- const { totalItems, setPage, itemsPerPage, currPage } = pagination;
12
-
13
- const showPagination = totalItems > itemsPerPage;
11
+ const showPagination = pagination && pagination.totalItems > pagination.itemsPerPage;
14
12
 
15
13
  return (
16
14
  <S.TableList onScroll={onScroll} ref={tableRef} data-testid="table-list">
@@ -24,7 +22,7 @@ const TableList = (props: ITableListProps): JSX.Element => {
24
22
  </S.Table>
25
23
  <S.PaginationWrapper>
26
24
  {showPagination && (
27
- <Pagination totalItems={totalItems} setPage={setPage} itemsPerPage={itemsPerPage} currPage={currPage} />
25
+ <Pagination totalItems={pagination.totalItems} setPage={pagination.setPage} itemsPerPage={pagination.itemsPerPage} currPage={pagination.currPage} />
28
26
  )}
29
27
  </S.PaginationWrapper>
30
28
  </S.TableList>
@@ -38,7 +36,7 @@ const mapStateToProps = (state: IRootState) => ({
38
36
  export interface ITableListProps {
39
37
  tableHeader: JSX.Element | JSX.Element[];
40
38
  children: JSX.Element | JSX.Element[];
41
- pagination: {
39
+ pagination?: {
42
40
  totalItems: number;
43
41
  setPage: any;
44
42
  itemsPerPage: number;
@@ -20,6 +20,7 @@ import {
20
20
  SET_GLOBAL_SETTINGS,
21
21
  SET_USER,
22
22
  SET_SESSION_STARTED_AT,
23
+ SET_HAS_ANIMATION,
23
24
  } from "./constants";
24
25
 
25
26
  import {
@@ -34,6 +35,7 @@ import {
34
35
  ISetGlobalSettings,
35
36
  ISetUserAction,
36
37
  ISetSessionStartedAtAction,
38
+ ISetHasAnimation,
37
39
  } from "./interfaces";
38
40
  import { IError, IUser } from "./reducer";
39
41
 
@@ -45,6 +47,10 @@ function setIsSaving(isSaving: boolean): ISetIsSaving {
45
47
  return { type: SET_IS_SAVING, payload: { isSaving } };
46
48
  }
47
49
 
50
+ function setHasAnimation(hasAnimation: boolean): ISetHasAnimation {
51
+ return { type: SET_HAS_ANIMATION, payload: { hasAnimation } };
52
+ }
53
+
48
54
  const resetStateValues = (dispatch: Dispatch) => {
49
55
  dispatch(setIsLoading(true));
50
56
  dispatch(setIsSaving(false));
@@ -138,13 +144,12 @@ function handleError(response: any, isMultiple = false, msg?: string): (dispatch
138
144
  };
139
145
  }
140
146
 
141
- function login(email: string, password: string, rememberMe: boolean): (dispatch: Dispatch) => Promise<void> {
142
- const welcomePageURI = "/sites";
147
+ function login(email: string, password: string, rememberMe: boolean): (dispatch: Dispatch) => Promise<boolean> {
143
148
  return async (dispatch) => {
144
149
  dispatch(setIsLogging(true));
145
150
  const loginResponse: any = await global.login(email, password);
146
151
  dispatch(setIsLogging(false));
147
- switch (loginResponse.status) {
152
+ switch (loginResponse?.status) {
148
153
  case 200: {
149
154
  const {
150
155
  data: { token },
@@ -153,12 +158,12 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
153
158
  isReqOk(langResponse.status) && dispatch(setGlobalLanguages(langResponse.data.items));
154
159
  dispatch(setToken(loginResponse.data.token));
155
160
  dispatch(setSessionStartedAt(new Date()));
156
- setHistoryPush(welcomePageURI)(dispatch);
161
+ dispatch(setHasAnimation(true));
157
162
  if (rememberMe) {
158
163
  const user: any = { token: loginResponse.data.token };
159
164
  localStorage.setItem("user", JSON.stringify(user));
160
165
  }
161
- break;
166
+ return true;
162
167
  }
163
168
  case 403: {
164
169
  const error = {
@@ -167,11 +172,21 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
167
172
  actionsBelow: true,
168
173
  };
169
174
  handleError(error)(dispatch);
170
- break;
175
+ return false;
176
+ }
177
+ case undefined: {
178
+ const error = {
179
+ data: {
180
+ code: 500,
181
+ message: "An error has occurred. Please contact your system administrator.",
182
+ }
183
+ };
184
+ handleError(error)(dispatch);
185
+ return false;
171
186
  }
172
187
  default:
173
188
  handleError(loginResponse)(dispatch);
174
- break;
189
+ return false;
175
190
  }
176
191
  };
177
192
  }
@@ -225,4 +240,5 @@ export {
225
240
  getGlobalSettings,
226
241
  setUser,
227
242
  checkUserSession,
243
+ setHasAnimation,
228
244
  };