@griddo/ax 10.6.21 → 10.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/__tests__/components/Login/RecoveryModal/RecoveryModal.test.tsx +1 -1
- package/src/api/global.tsx +2 -3
- package/src/components/Button/index.tsx +5 -3
- package/src/components/Button/style.tsx +2 -2
- package/src/components/Icon/components/Microsoft.js +10 -0
- package/src/components/Icon/index.tsx +4 -1
- package/src/components/Icon/svgs/microsoft.svg +6 -0
- package/src/components/Login/LoginForm/RecoveryModal/style.tsx +13 -0
- package/src/components/Login/LoginForm/index.tsx +135 -0
- package/src/components/Login/LoginForm/style.tsx +78 -0
- package/src/components/Login/LoginSSO/index.tsx +67 -0
- package/src/components/Login/LoginSSO/style.tsx +99 -0
- package/src/components/Login/LoginSlider/index.tsx +4 -4
- package/src/components/Login/index.tsx +23 -91
- package/src/components/Login/style.tsx +1 -65
- package/src/components/Notification/index.tsx +3 -2
- package/src/containers/App/actions.tsx +25 -2
- package/src/containers/App/reducer.tsx +2 -0
- package/src/modules/Login/constants.tsx +7 -0
- package/src/modules/Login/index.tsx +37 -7
- package/src/routes/publicRoutes.tsx +1 -0
- package/src/components/Login/RecoveryModal/style.tsx +0 -11
- /package/src/components/Login/{RecoveryModal → LoginForm/RecoveryModal}/index.tsx +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@griddo/ax",
|
|
3
3
|
"description": "Griddo Author Experience",
|
|
4
|
-
"version": "10.
|
|
4
|
+
"version": "10.7.0",
|
|
5
5
|
"authors": [
|
|
6
6
|
"Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
|
|
7
7
|
"Carlos Torres <carlos.torres@secuoyas.com>",
|
|
@@ -233,5 +233,5 @@
|
|
|
233
233
|
"publishConfig": {
|
|
234
234
|
"access": "public"
|
|
235
235
|
},
|
|
236
|
-
"gitHead": "
|
|
236
|
+
"gitHead": "0c56d9f6d66dea9fd92f811630b97808227aa693"
|
|
237
237
|
}
|
|
@@ -5,7 +5,7 @@ import { render, cleanup, screen, fireEvent, waitFor, act } from "@testing-libra
|
|
|
5
5
|
import "@testing-library/jest-dom";
|
|
6
6
|
|
|
7
7
|
import { parseTheme } from "@ax/helpers";
|
|
8
|
-
import RecoveryModal, { IRecoveryProps } from "@ax/components/Login/RecoveryModal";
|
|
8
|
+
import RecoveryModal, { IRecoveryProps } from "@ax/components/Login/LoginForm/RecoveryModal";
|
|
9
9
|
import globalTheme from "@ax/themes/theme.json";
|
|
10
10
|
|
|
11
11
|
afterEach(cleanup);
|
package/src/api/global.tsx
CHANGED
|
@@ -34,9 +34,8 @@ const SERVICES: { [key: string]: IServiceConfig } = {
|
|
|
34
34
|
},
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
const login = async (username
|
|
38
|
-
|
|
39
|
-
return sendRequest(SERVICES.LOGIN, { username, password });
|
|
37
|
+
const login = async (data?: { username?: string; password?: string; petitionId?: string }) => {
|
|
38
|
+
return sendRequest(SERVICES.LOGIN, data);
|
|
40
39
|
};
|
|
41
40
|
|
|
42
41
|
const getSettings = () => {
|
|
@@ -12,7 +12,7 @@ enum buttonStyles {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
const Button = (props: IButtonProps): JSX.Element => {
|
|
15
|
-
const { children, type, disabled, icon, buttonStyle, onClick, className, loader, backIcon } = props;
|
|
15
|
+
const { children, type, disabled, icon, buttonStyle, onClick, className, loader, backIcon, iconFill = true } = props;
|
|
16
16
|
|
|
17
17
|
const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
18
18
|
if (onClick !== undefined) {
|
|
@@ -23,8 +23,8 @@ const Button = (props: IButtonProps): JSX.Element => {
|
|
|
23
23
|
|
|
24
24
|
const iconSize = buttonStyle === buttonStyles.MINIMAL ? "16" : "24";
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const iconWrapper = icon ? <Icon name={icon} size={iconSize} /> : loader ? <Loader name={loader} /> : <></>;
|
|
27
|
+
const iconBackWrapper = backIcon ? <Icon name={backIcon} /> : <></>;
|
|
28
28
|
|
|
29
29
|
const buttonContent = (
|
|
30
30
|
<S.Label icon={icon || loader} backIcon={backIcon}>
|
|
@@ -83,6 +83,7 @@ const Button = (props: IButtonProps): JSX.Element => {
|
|
|
83
83
|
type={type}
|
|
84
84
|
disabled={disabled}
|
|
85
85
|
onClick={handleOnClick}
|
|
86
|
+
iconFill={iconFill}
|
|
86
87
|
>
|
|
87
88
|
{buttonContent}
|
|
88
89
|
</S.Button>
|
|
@@ -100,6 +101,7 @@ export interface IButtonProps {
|
|
|
100
101
|
buttonStyle?: "solid" | "text" | "line" | "lineInverse" | "minimal";
|
|
101
102
|
className?: string;
|
|
102
103
|
backIcon?: string;
|
|
104
|
+
iconFill?: boolean;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
export default Button;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import styled from "styled-components";
|
|
3
3
|
|
|
4
|
-
const Button = styled.button
|
|
4
|
+
const Button = styled.button<{ iconFill: boolean }>`
|
|
5
5
|
${(p) => p.theme.textStyle.uiButton};
|
|
6
6
|
background-color: ${(p) => p.theme.color.interactive01};
|
|
7
7
|
border-radius: 4px;
|
|
@@ -55,7 +55,7 @@ const Button = styled.button`
|
|
|
55
55
|
width: ${(p) => p.theme.spacing.s};
|
|
56
56
|
height: ${(p) => p.theme.spacing.s};
|
|
57
57
|
path {
|
|
58
|
-
fill: #ffffff;
|
|
58
|
+
fill: ${(p) => (p.iconFill ? "#ffffff" : "")};
|
|
59
59
|
}
|
|
60
60
|
circle {
|
|
61
61
|
stroke: #ffffff;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
const SvgMicrosoft = (props) => (
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg" width={17} height={16} fill="none" {...props}>
|
|
4
|
+
<path fill="#F35325" d="M1.196.695h6.956v6.957H1.196V.695Z" />
|
|
5
|
+
<path fill="#81BC06" d="M8.848.695h6.956v6.957H8.848V.695Z" />
|
|
6
|
+
<path fill="#05A6F0" d="M1.196 8.348h6.956v6.956H1.196V8.348Z" />
|
|
7
|
+
<path fill="#FFBA08" d="M8.848 8.348h6.956v6.956H8.848V8.348Z" />
|
|
8
|
+
</svg>
|
|
9
|
+
);
|
|
10
|
+
export default SvgMicrosoft;
|
|
@@ -20,6 +20,8 @@ const Icon = (props: IProps) => {
|
|
|
20
20
|
const size = props.size ? props.size : "22";
|
|
21
21
|
const fill = props.fill ? props.fill : "black";
|
|
22
22
|
|
|
23
|
+
const viewBox = props.viewBox ? `0 0 ${props.viewBox} ${props.viewBox}` : "0 0 24 24";
|
|
24
|
+
|
|
23
25
|
const Svg = getImage(name);
|
|
24
26
|
|
|
25
27
|
if (Svg) {
|
|
@@ -28,7 +30,7 @@ const Icon = (props: IProps) => {
|
|
|
28
30
|
data-testid={`icon-component-${name.toLowerCase()}`}
|
|
29
31
|
height={size}
|
|
30
32
|
width={size}
|
|
31
|
-
viewBox=
|
|
33
|
+
viewBox={viewBox}
|
|
32
34
|
fill={fill}
|
|
33
35
|
/>
|
|
34
36
|
);
|
|
@@ -41,6 +43,7 @@ export interface IStateProps {
|
|
|
41
43
|
name: string;
|
|
42
44
|
size?: string;
|
|
43
45
|
fill?: string;
|
|
46
|
+
viewBox?: number;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
type IProps = IStateProps;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M1.19565 0.695312H8.15217V7.65183H1.19565V0.695312Z" fill="#F35325"/>
|
|
3
|
+
<path d="M8.84782 0.695312H15.8043V7.65183H8.84782V0.695312Z" fill="#81BC06"/>
|
|
4
|
+
<path d="M1.19565 8.34766H8.15217V15.3042H1.19565V8.34766Z" fill="#05A6F0"/>
|
|
5
|
+
<path d="M8.84782 8.34766H15.8043V15.3042H8.84782V8.34766Z" fill="#FFBA08"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { IGlobalSettings } from "@ax/containers/App/reducer";
|
|
4
|
+
import { useModal } from "@ax/hooks";
|
|
5
|
+
import { Button, FieldsBehavior, ErrorToast } from "@ax/components";
|
|
6
|
+
import RecoveryModal from "./RecoveryModal";
|
|
7
|
+
|
|
8
|
+
import * as S from "./style";
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
interface Window {
|
|
12
|
+
handleErrorClick: () => void;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const LoginForm = (props: ILoginFormProps): JSX.Element => {
|
|
17
|
+
const {
|
|
18
|
+
handleSubmit,
|
|
19
|
+
email,
|
|
20
|
+
handleEmail,
|
|
21
|
+
password,
|
|
22
|
+
handlePassword,
|
|
23
|
+
isLoggingIn,
|
|
24
|
+
settings,
|
|
25
|
+
rememberMe,
|
|
26
|
+
handleRememberMe,
|
|
27
|
+
} = props;
|
|
28
|
+
|
|
29
|
+
const [viewPass, setViewPass] = useState(false);
|
|
30
|
+
const { isOpen, toggleModal } = useModal();
|
|
31
|
+
|
|
32
|
+
window.handleErrorClick = toggleModal;
|
|
33
|
+
|
|
34
|
+
const _handleEmail = (e: string) => handleEmail(e);
|
|
35
|
+
|
|
36
|
+
const _handlePwd = (e: string) => handlePassword(e);
|
|
37
|
+
|
|
38
|
+
const _togglePassword = () => setViewPass(!viewPass);
|
|
39
|
+
|
|
40
|
+
const btnText = isLoggingIn ? "Sending" : "Login";
|
|
41
|
+
|
|
42
|
+
const inputType = viewPass ? "text" : "password";
|
|
43
|
+
const icon = viewPass ? "hide" : "view";
|
|
44
|
+
|
|
45
|
+
const textName = settings.welcomeText2 ? settings.welcomeText2 : "Griddo";
|
|
46
|
+
const nameLogo =
|
|
47
|
+
textName === "Griddo" ? <img src="/img/logos/logoGriddoExtended@3x.svg" alt="Griddo Logo" /> : textName;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<S.Wrapper>
|
|
51
|
+
<S.Main>
|
|
52
|
+
<S.Header>
|
|
53
|
+
<S.Title>
|
|
54
|
+
<div>Welcome to</div>
|
|
55
|
+
<div>{nameLogo}</div>
|
|
56
|
+
</S.Title>
|
|
57
|
+
<S.Subtitle>To start using {textName}, introduce your email and password.</S.Subtitle>
|
|
58
|
+
</S.Header>
|
|
59
|
+
<ErrorToast />
|
|
60
|
+
<S.Form onSubmit={handleSubmit}>
|
|
61
|
+
<FieldsBehavior
|
|
62
|
+
fieldType="TextField"
|
|
63
|
+
title="Email"
|
|
64
|
+
autoComplete="email"
|
|
65
|
+
value={email}
|
|
66
|
+
onChange={_handleEmail}
|
|
67
|
+
name="email"
|
|
68
|
+
inversed={true}
|
|
69
|
+
placeholder="Type your email"
|
|
70
|
+
/>
|
|
71
|
+
<FieldsBehavior
|
|
72
|
+
fieldType="TextField"
|
|
73
|
+
title="Password"
|
|
74
|
+
inputType={inputType}
|
|
75
|
+
value={password}
|
|
76
|
+
onChange={_handlePwd}
|
|
77
|
+
autoComplete="current-password"
|
|
78
|
+
icon={icon}
|
|
79
|
+
onClickIcon={_togglePassword}
|
|
80
|
+
iconPosition="in"
|
|
81
|
+
name="password"
|
|
82
|
+
inversed={true}
|
|
83
|
+
/>
|
|
84
|
+
<S.Actions>
|
|
85
|
+
<FieldsBehavior
|
|
86
|
+
fieldType="UniqueCheck"
|
|
87
|
+
title=""
|
|
88
|
+
value={rememberMe}
|
|
89
|
+
onChange={handleRememberMe}
|
|
90
|
+
options={[{ title: "Remember me" }]}
|
|
91
|
+
name="rememberMe"
|
|
92
|
+
inversed={true}
|
|
93
|
+
/>
|
|
94
|
+
<S.Password>
|
|
95
|
+
<span
|
|
96
|
+
onClick={toggleModal}
|
|
97
|
+
onKeyDown={toggleModal}
|
|
98
|
+
role="checkbox"
|
|
99
|
+
aria-checked="false"
|
|
100
|
+
tabIndex={0}
|
|
101
|
+
data-testid="forgot-button"
|
|
102
|
+
>
|
|
103
|
+
Lost your password?
|
|
104
|
+
</span>
|
|
105
|
+
</S.Password>
|
|
106
|
+
</S.Actions>
|
|
107
|
+
<Button type="submit" disabled={isLoggingIn ? true : false}>
|
|
108
|
+
{btnText}
|
|
109
|
+
</Button>
|
|
110
|
+
<RecoveryModal isOpen={isOpen} toggleModal={toggleModal} />
|
|
111
|
+
</S.Form>
|
|
112
|
+
</S.Main>
|
|
113
|
+
<S.Secuoyas>
|
|
114
|
+
Made with care at{" "}
|
|
115
|
+
<a href="https://www.secuoyas.com/" target="_blank" rel="noopener noreferrer">
|
|
116
|
+
<img src="/img/logos/logoSQY.svg" alt="Secuoyas logo" />
|
|
117
|
+
</a>
|
|
118
|
+
</S.Secuoyas>
|
|
119
|
+
</S.Wrapper>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export interface ILoginFormProps {
|
|
124
|
+
handleSubmit: (e: React.FormEvent<HTMLFormElement>) => void;
|
|
125
|
+
email: string;
|
|
126
|
+
handleEmail: (email: string) => void;
|
|
127
|
+
password: string;
|
|
128
|
+
handlePassword: (password: string) => void;
|
|
129
|
+
isLoggingIn: boolean;
|
|
130
|
+
settings: IGlobalSettings;
|
|
131
|
+
rememberMe: boolean;
|
|
132
|
+
handleRememberMe: () => void;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export default LoginForm;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
|
|
3
|
+
const Wrapper = styled.div`
|
|
4
|
+
width: 368px;
|
|
5
|
+
position: relative;
|
|
6
|
+
height: 100%;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
const Main = styled.div`
|
|
12
|
+
width: 100%;
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const Header = styled.header``;
|
|
16
|
+
|
|
17
|
+
const Subtitle = styled.p`
|
|
18
|
+
${(p) => p.theme.textStyle.uiM};
|
|
19
|
+
color: ${(p) => p.theme.color.textMediumEmphasisInverse};
|
|
20
|
+
font-weight: normal;
|
|
21
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
22
|
+
width: 280px;
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const Title = styled.div`
|
|
26
|
+
${(p) => p.theme.textStyle.headingM};
|
|
27
|
+
color: ${(p) => p.theme.color.textHighEmphasisInverse};
|
|
28
|
+
display: flex;
|
|
29
|
+
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
30
|
+
align-items: center;
|
|
31
|
+
div:last-child {
|
|
32
|
+
margin-left: ${(p) => p.theme.spacing.xxs};
|
|
33
|
+
}
|
|
34
|
+
img {
|
|
35
|
+
height: 24px;
|
|
36
|
+
margin-top: ${(p) => p.theme.spacing.xxs};
|
|
37
|
+
}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const Form = styled.form`
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
margin-top: ${(p) => p.theme.spacing.m};
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
const Password = styled.div`
|
|
47
|
+
${(p) => p.theme.textStyle.uiS};
|
|
48
|
+
color: ${(p) => p.theme.color.interactiveInverse};
|
|
49
|
+
width: 100%;
|
|
50
|
+
text-align: right;
|
|
51
|
+
|
|
52
|
+
span {
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const Actions = styled.div`
|
|
58
|
+
display: flex;
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
const Secuoyas = styled.div`
|
|
62
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
63
|
+
position: absolute;
|
|
64
|
+
display: flex;
|
|
65
|
+
color: ${(p) => p.theme.color.textMediumEmphasisInverse};
|
|
66
|
+
justify-content: center;
|
|
67
|
+
align-items: center;
|
|
68
|
+
bottom: ${(p) => p.theme.spacing.m};
|
|
69
|
+
padding-bottom: ${(p) => p.theme.spacing.xs};
|
|
70
|
+
width: 100%;
|
|
71
|
+
img {
|
|
72
|
+
width: 20px;
|
|
73
|
+
height: 20px;
|
|
74
|
+
margin-left: ${(p) => p.theme.spacing.xs};
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
export { Wrapper, Main, Header, Subtitle, Title, Form, Password, Actions, Secuoyas };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Icon, ErrorToast } from "@ax/components";
|
|
3
|
+
|
|
4
|
+
import * as S from "./style";
|
|
5
|
+
|
|
6
|
+
const LoginSSO = (props: ILoginSSOProps): JSX.Element => {
|
|
7
|
+
const { handleSSO, errorSSO } = props;
|
|
8
|
+
|
|
9
|
+
const handleClick = () => handleSSO();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<S.Wrapper>
|
|
13
|
+
<S.Main>
|
|
14
|
+
<S.Logo>
|
|
15
|
+
<img src="/img/logos/logoGriddoExtended@3x.svg" alt="Griddo Logo" />
|
|
16
|
+
</S.Logo>
|
|
17
|
+
<S.Welcome>
|
|
18
|
+
Wel
|
|
19
|
+
<br />
|
|
20
|
+
come
|
|
21
|
+
</S.Welcome>
|
|
22
|
+
<S.StartWrapper>
|
|
23
|
+
<ErrorToast />
|
|
24
|
+
{errorSSO ? (
|
|
25
|
+
<>
|
|
26
|
+
<S.StyledNotification text={errorSSO} type="error" closeButton={false} />
|
|
27
|
+
<S.StyledButton type="button" iconFill={false} onClick={handleClick}>
|
|
28
|
+
<S.ContentButton>
|
|
29
|
+
<S.TextButton>Try again</S.TextButton>
|
|
30
|
+
</S.ContentButton>
|
|
31
|
+
</S.StyledButton>
|
|
32
|
+
</>
|
|
33
|
+
) : (
|
|
34
|
+
<>
|
|
35
|
+
<S.Text>
|
|
36
|
+
To start using Griddo, login with your
|
|
37
|
+
<br />
|
|
38
|
+
autentication platform
|
|
39
|
+
</S.Text>
|
|
40
|
+
<S.StyledButton type="button" iconFill={false} onClick={handleClick}>
|
|
41
|
+
<S.ContentButton>
|
|
42
|
+
<S.IconButton>
|
|
43
|
+
<Icon name="microsoft" size="16" viewBox={16} />
|
|
44
|
+
</S.IconButton>
|
|
45
|
+
<S.TextButton>Microsoft ID</S.TextButton>
|
|
46
|
+
</S.ContentButton>
|
|
47
|
+
</S.StyledButton>
|
|
48
|
+
</>
|
|
49
|
+
)}
|
|
50
|
+
</S.StartWrapper>
|
|
51
|
+
</S.Main>
|
|
52
|
+
<S.Secuoyas>
|
|
53
|
+
Made with care at{" "}
|
|
54
|
+
<a href="https://www.secuoyas.com/" target="_blank" rel="noopener noreferrer">
|
|
55
|
+
<img src="/img/logos/logoSQY.svg" alt="Secuoyas logo" />
|
|
56
|
+
</a>
|
|
57
|
+
</S.Secuoyas>
|
|
58
|
+
</S.Wrapper>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
interface ILoginSSOProps {
|
|
63
|
+
handleSSO: () => void;
|
|
64
|
+
errorSSO: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default LoginSSO;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import { Button, Notification } from "@ax/components";
|
|
4
|
+
|
|
5
|
+
const Wrapper = styled.div`
|
|
6
|
+
position: relative;
|
|
7
|
+
height: 100%;
|
|
8
|
+
display: flex;
|
|
9
|
+
align-items: strech;
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
const Main = styled.div`
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const Logo = styled.div`
|
|
18
|
+
margin-top: 15%;
|
|
19
|
+
margin-bottom: ${(p) => p.theme.spacing.m};
|
|
20
|
+
img {
|
|
21
|
+
height: 40px;
|
|
22
|
+
width: auto;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
|
|
26
|
+
const Welcome = styled.div`
|
|
27
|
+
color: #ffffff;
|
|
28
|
+
font-size: 181px;
|
|
29
|
+
line-height: 149.32px;
|
|
30
|
+
word-break: break-word;
|
|
31
|
+
margin-bottom: ${(p) => p.theme.spacing.l};
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
const StartWrapper = styled.div`
|
|
35
|
+
max-width: 416px;
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const Text = styled.div`
|
|
39
|
+
${(p) => p.theme.textStyle.uiM};
|
|
40
|
+
color: ${(p) => p.theme.color.textMediumEmphasisInverse};
|
|
41
|
+
margin-bottom: ${(p) => p.theme.spacing.m};
|
|
42
|
+
`;
|
|
43
|
+
|
|
44
|
+
const StyledButton = styled((props) => <Button {...props} />)`
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
align-items: center;
|
|
48
|
+
height: 40px;
|
|
49
|
+
width: 288px;
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
const ContentButton = styled.div`
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
const IconButton = styled.div`
|
|
58
|
+
width: ${(p) => p.theme.spacing.s};
|
|
59
|
+
height: ${(p) => p.theme.spacing.s};
|
|
60
|
+
margin-right: ${(p) => p.theme.spacing.xs};
|
|
61
|
+
`;
|
|
62
|
+
|
|
63
|
+
const TextButton = styled.div``;
|
|
64
|
+
|
|
65
|
+
const Secuoyas = styled.div`
|
|
66
|
+
${(p) => p.theme.textStyle.uiXS};
|
|
67
|
+
position: absolute;
|
|
68
|
+
display: flex;
|
|
69
|
+
color: ${(p) => p.theme.color.textMediumEmphasisInverse};
|
|
70
|
+
justify-content: center;
|
|
71
|
+
align-items: center;
|
|
72
|
+
left: 0;
|
|
73
|
+
bottom: ${(p) => p.theme.spacing.m};
|
|
74
|
+
padding-bottom: ${(p) => p.theme.spacing.xs};
|
|
75
|
+
img {
|
|
76
|
+
width: 20px;
|
|
77
|
+
height: 20px;
|
|
78
|
+
margin-left: ${(p) => p.theme.spacing.xs};
|
|
79
|
+
}
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
const StyledNotification = styled((props) => <Notification {...props} />)`
|
|
83
|
+
margin-bottom: ${(p) => p.theme.spacing.s};
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
Wrapper,
|
|
88
|
+
Main,
|
|
89
|
+
Logo,
|
|
90
|
+
Welcome,
|
|
91
|
+
StartWrapper,
|
|
92
|
+
Text,
|
|
93
|
+
StyledButton,
|
|
94
|
+
ContentButton,
|
|
95
|
+
IconButton,
|
|
96
|
+
TextButton,
|
|
97
|
+
Secuoyas,
|
|
98
|
+
StyledNotification,
|
|
99
|
+
};
|
|
@@ -14,10 +14,10 @@ const LoginSlider = (props: ILoginSliderProps): JSX.Element => {
|
|
|
14
14
|
const nextSlideElement = customSlider.current.innerSlider.list.querySelector(`[data-index="${next}"]`);
|
|
15
15
|
|
|
16
16
|
setTimeout(() => {
|
|
17
|
-
prevSlideElement.classList.add(
|
|
18
|
-
nextSlideElement.classList.remove(
|
|
19
|
-
},100);
|
|
20
|
-
}
|
|
17
|
+
prevSlideElement.classList.add("prev-slide-anim");
|
|
18
|
+
nextSlideElement.classList.remove("prev-slide-anim");
|
|
19
|
+
}, 100);
|
|
20
|
+
};
|
|
21
21
|
|
|
22
22
|
const settings = {
|
|
23
23
|
dots: false,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from "react";
|
|
2
2
|
|
|
3
3
|
import { IGlobalSettings } from "@ax/containers/App/reducer";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
4
|
+
import { Circle } from "@ax/components";
|
|
5
|
+
import LoginForm from "./LoginForm";
|
|
6
|
+
import LoginSSO from "./LoginSSO";
|
|
7
7
|
|
|
8
8
|
import * as S from "./style";
|
|
9
9
|
|
|
@@ -26,11 +26,11 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
26
26
|
handleRememberMe,
|
|
27
27
|
isLoginSuccess,
|
|
28
28
|
handleLoginSuccess,
|
|
29
|
+
handleSSO,
|
|
30
|
+
errorSSO,
|
|
29
31
|
} = props;
|
|
30
32
|
|
|
31
|
-
const [viewPass, setViewPass] = useState(false);
|
|
32
33
|
const [wrapperWidth, setWrapperWidth] = useState<number>(0);
|
|
33
|
-
const { isOpen, toggleModal } = useModal();
|
|
34
34
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
35
35
|
|
|
36
36
|
useEffect(() => {
|
|
@@ -41,99 +41,29 @@ const Login = (props: ILoginProps): JSX.Element => {
|
|
|
41
41
|
if (wrapperRef.current) {
|
|
42
42
|
setWrapperWidth(wrapperRef.current.clientWidth);
|
|
43
43
|
}
|
|
44
|
-
}, [wrapperRef
|
|
45
|
-
|
|
46
|
-
window.handleErrorClick = toggleModal;
|
|
47
|
-
|
|
48
|
-
const _handleEmail = (e: string) => handleEmail(e);
|
|
49
|
-
|
|
50
|
-
const _handlePwd = (e: string) => handlePassword(e);
|
|
51
|
-
|
|
52
|
-
const _togglePassword = () => setViewPass(!viewPass);
|
|
44
|
+
}, [wrapperRef]);
|
|
53
45
|
|
|
54
46
|
const _handleAnimationEnd = () => handleLoginSuccess();
|
|
55
47
|
|
|
56
|
-
const btnText = isLoggingIn ? "Sending" : "Login";
|
|
57
|
-
|
|
58
|
-
const inputType = viewPass ? "text" : "password";
|
|
59
|
-
const icon = viewPass ? "hide" : "view";
|
|
60
|
-
|
|
61
|
-
const textName = settings.welcomeText2 ? settings.welcomeText2 : "Griddo";
|
|
62
|
-
const nameLogo =
|
|
63
|
-
textName === "Griddo" ? <img src="/img/logos/logoGriddoExtended@3x.svg" alt="Griddo Logo" /> : textName;
|
|
64
|
-
|
|
65
48
|
return (
|
|
66
49
|
<S.Wrapper data-testid="login-wrapper">
|
|
67
50
|
<S.LeftWrapper className={isLoginSuccess ? "animate" : ""} onAnimationEnd={_handleAnimationEnd} ref={wrapperRef}>
|
|
68
51
|
<S.LoginWrapper className={isLoginSuccess ? "animate" : ""} width={wrapperWidth}>
|
|
69
|
-
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
onChange={_handleEmail}
|
|
85
|
-
name="email"
|
|
86
|
-
inversed={true}
|
|
87
|
-
placeholder="Type your email"
|
|
88
|
-
/>
|
|
89
|
-
<FieldsBehavior
|
|
90
|
-
fieldType="TextField"
|
|
91
|
-
title="Password"
|
|
92
|
-
inputType={inputType}
|
|
93
|
-
value={password}
|
|
94
|
-
onChange={_handlePwd}
|
|
95
|
-
autoComplete="current-password"
|
|
96
|
-
icon={icon}
|
|
97
|
-
onClickIcon={_togglePassword}
|
|
98
|
-
iconPosition="in"
|
|
99
|
-
name="password"
|
|
100
|
-
inversed={true}
|
|
101
|
-
/>
|
|
102
|
-
<S.Actions>
|
|
103
|
-
<FieldsBehavior
|
|
104
|
-
fieldType="UniqueCheck"
|
|
105
|
-
title=""
|
|
106
|
-
value={rememberMe}
|
|
107
|
-
onChange={handleRememberMe}
|
|
108
|
-
options={[{ title: "Remember me" }]}
|
|
109
|
-
name="rememberMe"
|
|
110
|
-
inversed={true}
|
|
111
|
-
/>
|
|
112
|
-
<S.Password>
|
|
113
|
-
<span
|
|
114
|
-
onClick={toggleModal}
|
|
115
|
-
onKeyDown={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{" "}
|
|
133
|
-
<a href="https://www.secuoyas.com/" target="_blank">
|
|
134
|
-
<img src="/img/logos/logoSQY.svg" alt="Secuoyas logo" />
|
|
135
|
-
</a>
|
|
136
|
-
</S.Secuoyas>
|
|
52
|
+
{settings.SSOActivated ? (
|
|
53
|
+
<LoginSSO handleSSO={handleSSO} errorSSO={errorSSO} />
|
|
54
|
+
) : (
|
|
55
|
+
<LoginForm
|
|
56
|
+
handleSubmit={handleSubmit}
|
|
57
|
+
email={email}
|
|
58
|
+
handleEmail={handleEmail}
|
|
59
|
+
password={password}
|
|
60
|
+
handlePassword={handlePassword}
|
|
61
|
+
isLoggingIn={isLoggingIn}
|
|
62
|
+
settings={settings}
|
|
63
|
+
rememberMe={rememberMe}
|
|
64
|
+
handleRememberMe={handleRememberMe}
|
|
65
|
+
/>
|
|
66
|
+
)}
|
|
137
67
|
</S.LoginWrapper>
|
|
138
68
|
</S.LeftWrapper>
|
|
139
69
|
<S.RightWrapper>
|
|
@@ -157,6 +87,8 @@ export interface ILoginProps {
|
|
|
157
87
|
handleRememberMe: () => void;
|
|
158
88
|
isLoginSuccess: boolean;
|
|
159
89
|
handleLoginSuccess: () => void;
|
|
90
|
+
handleSSO: () => void;
|
|
91
|
+
errorSSO: string | null;
|
|
160
92
|
}
|
|
161
93
|
|
|
162
94
|
export default Login;
|
|
@@ -71,56 +71,6 @@ const AnimatedLoginSlider = styled(LoginSlider)`
|
|
|
71
71
|
}
|
|
72
72
|
`;
|
|
73
73
|
|
|
74
|
-
const Main = styled.div`
|
|
75
|
-
width: 368px;
|
|
76
|
-
`;
|
|
77
|
-
|
|
78
|
-
const Header = styled.header``;
|
|
79
|
-
|
|
80
|
-
const Subtitle = styled.p`
|
|
81
|
-
${(p) => p.theme.textStyle.uiM};
|
|
82
|
-
color: ${(p) => p.theme.color.textMediumEmphasisInverse};
|
|
83
|
-
font-weight: normal;
|
|
84
|
-
margin-bottom: ${(p) => p.theme.spacing.xs};
|
|
85
|
-
width: 280px;
|
|
86
|
-
`;
|
|
87
|
-
|
|
88
|
-
const Title = styled.div`
|
|
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
|
-
}
|
|
101
|
-
`;
|
|
102
|
-
|
|
103
|
-
const Form = styled.form`
|
|
104
|
-
display: flex;
|
|
105
|
-
flex-direction: column;
|
|
106
|
-
margin-top: ${(p) => p.theme.spacing.m};
|
|
107
|
-
`;
|
|
108
|
-
|
|
109
|
-
const Password = styled.div`
|
|
110
|
-
${(p) => p.theme.textStyle.uiS};
|
|
111
|
-
color: ${(p) => p.theme.color.interactiveInverse};
|
|
112
|
-
width: 100%;
|
|
113
|
-
text-align: right;
|
|
114
|
-
|
|
115
|
-
span {
|
|
116
|
-
cursor: pointer;
|
|
117
|
-
}
|
|
118
|
-
`;
|
|
119
|
-
|
|
120
|
-
const Actions = styled.div`
|
|
121
|
-
display: flex;
|
|
122
|
-
`;
|
|
123
|
-
|
|
124
74
|
const Secuoyas = styled.div<{ width: number }>`
|
|
125
75
|
${(p) => p.theme.textStyle.uiXS};
|
|
126
76
|
position: absolute;
|
|
@@ -139,18 +89,4 @@ const Secuoyas = styled.div<{ width: number }>`
|
|
|
139
89
|
}
|
|
140
90
|
`;
|
|
141
91
|
|
|
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
|
-
};
|
|
92
|
+
export { Wrapper, LeftWrapper, RightWrapper, LoginWrapper, AnimatedLoginSlider, Secuoyas };
|
|
@@ -5,7 +5,7 @@ import SubNotification from "./SubNotification";
|
|
|
5
5
|
import * as S from "./style";
|
|
6
6
|
|
|
7
7
|
const Notification = (props: INotificationProps): JSX.Element => {
|
|
8
|
-
const { text, type, btnText, resetError, onClick, closeButton = true, actionsBelow, subErrors } = props;
|
|
8
|
+
const { text, type, btnText, resetError, onClick, closeButton = true, actionsBelow, subErrors, className } = props;
|
|
9
9
|
|
|
10
10
|
const [isVisible, setIsVisible] = useState(true);
|
|
11
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -60,7 +60,7 @@ const Notification = (props: INotificationProps): JSX.Element => {
|
|
|
60
60
|
const showText = isOpen ? "Hide errors" : "Show errors";
|
|
61
61
|
|
|
62
62
|
return (
|
|
63
|
-
<S.Wrapper isVisible={isVisible} className={type} data-testid="notification-wrapper">
|
|
63
|
+
<S.Wrapper isVisible={isVisible} className={`${type} ${className}`} data-testid="notification-wrapper">
|
|
64
64
|
<S.NotificationWrapper>
|
|
65
65
|
<S.Row>
|
|
66
66
|
{getNotificationIcon(type)}
|
|
@@ -98,6 +98,7 @@ export interface INotificationProps {
|
|
|
98
98
|
closeButton?: boolean;
|
|
99
99
|
actionsBelow?: boolean;
|
|
100
100
|
subErrors?: { id: number; error: string }[];
|
|
101
|
+
className?: string;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
export default Notification;
|
|
@@ -147,10 +147,15 @@ function handleError(response: any, isMultiple = false, msg?: string): (dispatch
|
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
function login(
|
|
150
|
+
function login(
|
|
151
|
+
email?: string,
|
|
152
|
+
password?: string,
|
|
153
|
+
rememberMe?: boolean,
|
|
154
|
+
petitionId?: string
|
|
155
|
+
): (dispatch: Dispatch) => Promise<boolean> {
|
|
151
156
|
return async (dispatch) => {
|
|
152
157
|
dispatch(setIsLogging(true));
|
|
153
|
-
const loginResponse: any = await global.login(email, password);
|
|
158
|
+
const loginResponse: any = await global.login({ username: email, password, petitionId });
|
|
154
159
|
dispatch(setIsLogging(false));
|
|
155
160
|
switch (loginResponse?.status) {
|
|
156
161
|
case 200: {
|
|
@@ -194,6 +199,23 @@ function login(email: string, password: string, rememberMe: boolean): (dispatch:
|
|
|
194
199
|
};
|
|
195
200
|
}
|
|
196
201
|
|
|
202
|
+
function loginSSO(): (dispatch: Dispatch) => Promise<string | null> {
|
|
203
|
+
return async (dispatch) => {
|
|
204
|
+
try {
|
|
205
|
+
dispatch(setIsLogging(true));
|
|
206
|
+
const response: { status: number; data: any } = await global.login();
|
|
207
|
+
|
|
208
|
+
if (isReqOk(response?.status)) {
|
|
209
|
+
return response.data;
|
|
210
|
+
} else {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
} catch (e) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
197
219
|
function getGlobalSettings(): (dispatch: Dispatch) => Promise<void> {
|
|
198
220
|
return async (dispatch) => {
|
|
199
221
|
try {
|
|
@@ -244,4 +266,5 @@ export {
|
|
|
244
266
|
setUser,
|
|
245
267
|
checkUserSession,
|
|
246
268
|
setHasAnimation,
|
|
269
|
+
loginSSO,
|
|
247
270
|
};
|
|
@@ -52,6 +52,7 @@ export interface IGlobalSettings {
|
|
|
52
52
|
skipReviewOnPublish?: boolean;
|
|
53
53
|
autoSummary: boolean;
|
|
54
54
|
autoTranslation: boolean;
|
|
55
|
+
SSOActivated: boolean;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export const initialState = {
|
|
@@ -82,6 +83,7 @@ export const initialState = {
|
|
|
82
83
|
welcomeText2: "",
|
|
83
84
|
autoSummary: false,
|
|
84
85
|
autoTranslation: false,
|
|
86
|
+
SSOActivated: false,
|
|
85
87
|
},
|
|
86
88
|
sessionStartedAt: null,
|
|
87
89
|
hasAnimation: false,
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import React, { useEffect, useState } from "react";
|
|
2
2
|
import { connect } from "react-redux";
|
|
3
|
-
import {
|
|
3
|
+
import { useParams } from "react-router-dom";
|
|
4
4
|
|
|
5
|
+
import { IRootState } from "@ax/types";
|
|
5
6
|
import { appActions } from "@ax/containers/App";
|
|
6
7
|
import { Login } from "@ax/components";
|
|
7
8
|
import { IGlobalSettings } from "@ax/containers/App/reducer";
|
|
9
|
+
import { errorText } from "./constants";
|
|
8
10
|
|
|
9
11
|
const LoginModule = (props: IProps) => {
|
|
10
|
-
const { isLoggingIn, globalSettings, login, resetError, getGlobalSettings, setHistoryPush } = props;
|
|
12
|
+
const { isLoggingIn, globalSettings, login, loginSSO, resetError, getGlobalSettings, setHistoryPush } = props;
|
|
13
|
+
|
|
14
|
+
const { petitionId } = useParams<{ petitionId?: string }>();
|
|
15
|
+
|
|
16
|
+
const errorSSO = petitionId && Object.keys(errorText).includes(petitionId) ? errorText[petitionId] : null;
|
|
11
17
|
|
|
12
18
|
const initState = {
|
|
13
19
|
email: "",
|
|
@@ -18,6 +24,20 @@ const LoginModule = (props: IProps) => {
|
|
|
18
24
|
const [state, setState] = useState(initState);
|
|
19
25
|
const [isSuccess, setIsSuccess] = useState(false);
|
|
20
26
|
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const handleLogin = async () => {
|
|
29
|
+
const isLogged = await login(undefined, undefined, undefined, petitionId);
|
|
30
|
+
if (isLogged) {
|
|
31
|
+
setIsSuccess(true);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (petitionId && !errorSSO) {
|
|
36
|
+
handleLogin();
|
|
37
|
+
}
|
|
38
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
39
|
+
}, [petitionId, errorSSO]);
|
|
40
|
+
|
|
21
41
|
useEffect(() => {
|
|
22
42
|
const prefix = process.env.REACT_APP_SITE_TITLE ? process.env.REACT_APP_SITE_TITLE : "";
|
|
23
43
|
document.title = `${prefix} ${globalSettings.welcomeText2}`;
|
|
@@ -30,11 +50,18 @@ const LoginModule = (props: IProps) => {
|
|
|
30
50
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
|
31
51
|
e.preventDefault();
|
|
32
52
|
const isLogged = await login(state.email, state.password, state.rememberMe);
|
|
33
|
-
if(isLogged){
|
|
53
|
+
if (isLogged) {
|
|
34
54
|
setIsSuccess(true);
|
|
35
55
|
}
|
|
36
56
|
};
|
|
37
57
|
|
|
58
|
+
const handleClickSSO = async () => {
|
|
59
|
+
const urlSSO = await loginSSO();
|
|
60
|
+
if (urlSSO) {
|
|
61
|
+
window.open(urlSSO, "_self");
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
38
65
|
const _handleEmail = (email: string) => {
|
|
39
66
|
resetError();
|
|
40
67
|
setState({ ...state, email });
|
|
@@ -48,7 +75,7 @@ const LoginModule = (props: IProps) => {
|
|
|
48
75
|
const handleLoginSuccess = () => {
|
|
49
76
|
const welcomePageURI = "/sites";
|
|
50
77
|
setHistoryPush(welcomePageURI);
|
|
51
|
-
}
|
|
78
|
+
};
|
|
52
79
|
|
|
53
80
|
const _handleRememberMe = () => setState({ ...state, rememberMe: !state.rememberMe });
|
|
54
81
|
|
|
@@ -65,23 +92,26 @@ const LoginModule = (props: IProps) => {
|
|
|
65
92
|
handleRememberMe={_handleRememberMe}
|
|
66
93
|
isLoginSuccess={isSuccess}
|
|
67
94
|
handleLoginSuccess={handleLoginSuccess}
|
|
95
|
+
handleSSO={handleClickSSO}
|
|
96
|
+
errorSSO={errorSSO}
|
|
68
97
|
/>
|
|
69
98
|
);
|
|
70
99
|
};
|
|
71
100
|
|
|
72
101
|
interface IProps {
|
|
73
|
-
token: string;
|
|
74
102
|
isLoggingIn: boolean;
|
|
75
103
|
children: any;
|
|
76
104
|
globalSettings: IGlobalSettings;
|
|
77
|
-
login(email
|
|
105
|
+
login(email?: string, password?: string, rememberMe?: boolean, petitionId?: string): Promise<boolean>;
|
|
106
|
+
loginSSO(): Promise<string | null>;
|
|
78
107
|
resetError(): void;
|
|
79
108
|
getGlobalSettings(): void;
|
|
80
|
-
setHistoryPush(path: string): Promise<void
|
|
109
|
+
setHistoryPush(path: string): Promise<void>;
|
|
81
110
|
}
|
|
82
111
|
|
|
83
112
|
const mapDispatchToProps = {
|
|
84
113
|
login: appActions.login,
|
|
114
|
+
loginSSO: appActions.loginSSO,
|
|
85
115
|
resetError: appActions.resetError,
|
|
86
116
|
getGlobalSettings: appActions.getGlobalSettings,
|
|
87
117
|
setHistoryPush: appActions.setHistoryPush,
|
|
@@ -4,6 +4,7 @@ import Login from "./../modules/Login";
|
|
|
4
4
|
import PublicPreview from "./../modules/PublicPreview";
|
|
5
5
|
|
|
6
6
|
const publicRoutes = [
|
|
7
|
+
{ path: "/login/:petitionId", component: Login, name: "Login", hideNav: true },
|
|
7
8
|
{ path: "/login", component: Login, name: "Login", hideNav: true },
|
|
8
9
|
{ path: "/new-password/:id/:token", component: ResetPass, name: "Reset Password", hideNav: true },
|
|
9
10
|
{ path: "/set-password/:id/:token", component: CreatePass, name: "Create Password", hideNav: true },
|
|
File without changes
|