aio-login 8.0.3 → 9.0.1
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/index.css +10 -9
- package/index.d.ts +83 -69
- package/index.js +315 -239
- package/package.json +1 -1
package/index.css
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
padding: 0 6px;
|
|
23
23
|
outline: none;
|
|
24
24
|
flex-shrink: 0;
|
|
25
|
-
margin-top: 30px;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
.ai-login-form {
|
|
@@ -34,6 +33,7 @@
|
|
|
34
33
|
display: flex;
|
|
35
34
|
flex-direction: column;
|
|
36
35
|
flex-shrink: 0;
|
|
36
|
+
min-width: 300px;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
.ai-login-title {
|
|
@@ -65,14 +65,6 @@
|
|
|
65
65
|
height: 48px;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
.ai-login-errors {
|
|
69
|
-
display: flex;
|
|
70
|
-
flex-direction: column;
|
|
71
|
-
gap: 6px;
|
|
72
|
-
padding: 12px;
|
|
73
|
-
box-sizing: border-box;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
68
|
.ai-login-error {
|
|
77
69
|
color: red;
|
|
78
70
|
display: flex;
|
|
@@ -110,3 +102,12 @@
|
|
|
110
102
|
.ai-login button:disabled {
|
|
111
103
|
opacity: 0.3;
|
|
112
104
|
}
|
|
105
|
+
.ai-form-item-label{
|
|
106
|
+
font-size:12px;
|
|
107
|
+
display:flex;
|
|
108
|
+
gap:4px;
|
|
109
|
+
align-items: center;
|
|
110
|
+
}
|
|
111
|
+
.ai-form-required{
|
|
112
|
+
color:red;
|
|
113
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,31 +1,43 @@
|
|
|
1
1
|
import { FC, ReactNode } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { I_formInput } from "aio-input";
|
|
3
3
|
import './index.css';
|
|
4
4
|
type I_loginMode = 'userpass' | 'register' | 'otpcode' | 'otpnumber';
|
|
5
|
-
type
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
export type I_login_key = 'registerButton' | 'userpassButton' | 'otpnumberButton' | 'otpcodeButton' | 'registerTitle' | 'userpassTitle' | 'otpcodeTitle' | 'otpnumberTitle' | 'switchuserpass' | 'switchregister' | 'switchotpnumber' | 'repasswordMatch' | 'usernameRequired' | 'passwordRequired' | 'repasswordRequired' | 'otpnumberRequired' | 'otpcodeLength' | 'registerError' | 'userpassError' | 'otpcodeError' | 'otpnumberError' | 'username' | 'password' | 'repassword' | 'otpnumber' | 'otpcode';
|
|
6
|
+
type I_login_model<T> = {
|
|
7
|
+
userpass: {
|
|
8
|
+
username: string;
|
|
9
|
+
password: string;
|
|
10
|
+
};
|
|
10
11
|
otpnumber: string;
|
|
11
12
|
otpcode: string;
|
|
12
|
-
register:
|
|
13
|
+
register: {
|
|
14
|
+
username: string;
|
|
15
|
+
password: string;
|
|
16
|
+
repassword: string;
|
|
17
|
+
properties: {
|
|
18
|
+
[key in keyof T]?: T[key] | undefined;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
13
21
|
};
|
|
14
|
-
type
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
type I_registerInputs = {
|
|
23
|
+
[field: string]: I_formInput;
|
|
24
|
+
};
|
|
25
|
+
type I_AILogin<T> = {
|
|
26
|
+
app: FC<{
|
|
27
|
+
user: T;
|
|
28
|
+
token: string;
|
|
29
|
+
base_url: string;
|
|
30
|
+
logout: () => void;
|
|
31
|
+
}>;
|
|
32
|
+
base_url: string;
|
|
33
|
+
checkToken: {
|
|
17
34
|
url: string;
|
|
35
|
+
method?: 'post' | 'get';
|
|
18
36
|
body?: any;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}>;
|
|
37
|
+
getResult?: (response: any) => boolean;
|
|
38
|
+
};
|
|
22
39
|
before?: (mode: I_loginMode) => ReactNode;
|
|
23
40
|
after?: (mode: I_loginMode) => ReactNode;
|
|
24
|
-
renderApp: (p: {
|
|
25
|
-
user: any;
|
|
26
|
-
token: string;
|
|
27
|
-
logout: () => void;
|
|
28
|
-
}) => ReactNode;
|
|
29
41
|
translate?: (key: I_login_key) => string | undefined;
|
|
30
42
|
fa?: boolean;
|
|
31
43
|
id: string;
|
|
@@ -33,69 +45,71 @@ type I_AILogin = {
|
|
|
33
45
|
html: ReactNode;
|
|
34
46
|
time: number;
|
|
35
47
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
validate?: (p: {
|
|
49
|
+
field: string;
|
|
50
|
+
data: I_login_model<T>;
|
|
51
|
+
value: any;
|
|
52
|
+
input: I_formInput;
|
|
53
|
+
}) => string | undefined;
|
|
54
|
+
otpnumber?: {
|
|
55
|
+
path: string;
|
|
56
|
+
method: 'post' | 'get';
|
|
57
|
+
body?: (data: I_login_model<T>) => any;
|
|
58
|
+
onSuccess: (response: any) => Promise<{
|
|
59
|
+
message?: string;
|
|
48
60
|
}>;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
};
|
|
62
|
+
otpcode?: {
|
|
63
|
+
length: number;
|
|
64
|
+
method: 'post' | 'get';
|
|
65
|
+
body?: (data: I_login_model<T>) => any;
|
|
66
|
+
path: string;
|
|
67
|
+
onSuccess: (response: any) => Promise<{
|
|
68
|
+
user: T;
|
|
69
|
+
token: string;
|
|
70
|
+
message?: string;
|
|
59
71
|
}>;
|
|
60
72
|
};
|
|
61
73
|
userpass?: {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
message?: string;
|
|
70
|
-
}>;
|
|
71
|
-
onCatch: (response: any) => string;
|
|
74
|
+
path: string;
|
|
75
|
+
method: 'post' | 'get';
|
|
76
|
+
body?: (data: I_login_model<T>) => any;
|
|
77
|
+
onSuccess: (response: any) => Promise<{
|
|
78
|
+
user: T;
|
|
79
|
+
token: string;
|
|
80
|
+
message?: string;
|
|
72
81
|
}>;
|
|
73
82
|
};
|
|
74
83
|
register?: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
api: (model: I_login_model, mode: I_loginMode) => Promise<{
|
|
82
|
-
method: 'post' | 'get';
|
|
83
|
-
url: string;
|
|
84
|
-
body?: any;
|
|
85
|
-
onSuccess: (response: any) => Promise<{
|
|
86
|
-
message?: string;
|
|
87
|
-
}>;
|
|
88
|
-
onCatch: (response: any) => string;
|
|
84
|
+
inputs?: (model: I_login_model<T>) => I_registerInputs;
|
|
85
|
+
path: string;
|
|
86
|
+
method: 'post' | 'get';
|
|
87
|
+
body?: (data: I_login_model<T>) => any;
|
|
88
|
+
onSuccess: (response: any) => Promise<{
|
|
89
|
+
message?: string;
|
|
89
90
|
}>;
|
|
91
|
+
defaultData?: any;
|
|
90
92
|
};
|
|
93
|
+
getStatus?: (response: any) => number;
|
|
94
|
+
getMessage?: (response: any) => string;
|
|
91
95
|
mode?: I_loginMode;
|
|
92
|
-
attrs?:
|
|
96
|
+
attrs?: {
|
|
97
|
+
[key: string]: any;
|
|
98
|
+
};
|
|
93
99
|
setAttrs?: (key: I_login_key) => any;
|
|
94
100
|
mock?: {
|
|
95
|
-
user:
|
|
101
|
+
user: T;
|
|
96
102
|
token: string;
|
|
97
103
|
};
|
|
98
104
|
};
|
|
99
|
-
export declare function AIOLogin_updateCatchedUser(loginId: string, newUser:
|
|
100
|
-
|
|
101
|
-
|
|
105
|
+
export declare function AIOLogin_updateCatchedUser<T>(loginId: string, newUser: T): any;
|
|
106
|
+
export type I_AuthContext<T> = {
|
|
107
|
+
user?: T;
|
|
108
|
+
token?: string;
|
|
109
|
+
logout: () => void;
|
|
110
|
+
base_url: string;
|
|
111
|
+
};
|
|
112
|
+
declare const useLogin: <T extends Record<string, any>>(props: I_AILogin<T>) => {
|
|
113
|
+
render: () => JSX.Element;
|
|
114
|
+
};
|
|
115
|
+
export default useLogin;
|
package/index.js
CHANGED
|
@@ -7,14 +7,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import { AddToAttrs, Storage } from "aio-utils";
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
import { useEffect, useState } from "react";
|
|
12
|
+
import { useForm } from "aio-input";
|
|
13
|
+
import { AddToAttrs, FixUrl, Storage } from "aio-utils";
|
|
15
14
|
import { Loading, Alert } from "aio-popup";
|
|
16
15
|
import axios from "axios";
|
|
17
16
|
import './index.css';
|
|
17
|
+
import { Navigate, Route, Routes } from "react-router-dom";
|
|
18
18
|
export function AIOLogin_updateCatchedUser(loginId, newUser) {
|
|
19
19
|
const storage = new Storage('ai-login' + loginId);
|
|
20
20
|
const storedData = storage.load('data');
|
|
@@ -24,135 +24,120 @@ export function AIOLogin_updateCatchedUser(loginId, newUser) {
|
|
|
24
24
|
const newStoredData = Object.assign(Object.assign({}, storedData), { user: newUser });
|
|
25
25
|
return storage.save('data', newStoredData);
|
|
26
26
|
}
|
|
27
|
-
const
|
|
28
|
-
const { translate = () => { },
|
|
29
|
-
const
|
|
30
|
-
const [data, setData] = useState();
|
|
31
|
-
const [storage] = useState(new Storage('ai-login' + props.id));
|
|
32
|
-
const [model, setModel] = useState(getModel);
|
|
27
|
+
const useLoading = (rootProps) => {
|
|
28
|
+
const { register, translate = () => { }, fa, validate = () => { return undefined; }, userpass, splash, otpnumber, otpcode } = rootProps;
|
|
29
|
+
const [storage] = useState(new Storage('ai-login' + rootProps.id));
|
|
33
30
|
const [loading] = useState(new Loading());
|
|
34
|
-
const [
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const [mode, setMode] = useState(getMode());
|
|
39
|
-
function getModeKey() {
|
|
40
|
-
if (props.mode) {
|
|
41
|
-
return props.mode;
|
|
42
|
-
}
|
|
43
|
-
if (props.userpass) {
|
|
44
|
-
return 'userpass';
|
|
45
|
-
}
|
|
46
|
-
if (props.otp) {
|
|
47
|
-
return 'otpnumber';
|
|
48
|
-
}
|
|
49
|
-
return 'userpass';
|
|
50
|
-
}
|
|
31
|
+
const [splashing, setSplashing] = useState(!!rootProps.splash);
|
|
32
|
+
const [data, setData] = useState();
|
|
33
|
+
const [checkingToken, setCheckingToken] = useState();
|
|
34
|
+
const [mode, setMode] = useState(getMode);
|
|
51
35
|
function getMode(mode) {
|
|
52
|
-
let
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
return (_jsxs(_Fragment, { children: [getInput({ mode: res.key, field: 'username', type: 'text' }), getInput({ mode: res.key, field: 'password', type: 'text' })] }));
|
|
56
|
-
};
|
|
57
|
-
res.shouldReturnsUserAndToken = true;
|
|
36
|
+
let key = 'userpass';
|
|
37
|
+
if (mode) {
|
|
38
|
+
key = mode;
|
|
58
39
|
}
|
|
59
|
-
else if (
|
|
60
|
-
|
|
61
|
-
const inputs = (props.register.inputs || (() => []))(modelRef.current) || [];
|
|
62
|
-
res.inputs = () => {
|
|
63
|
-
return (_jsxs(_Fragment, { children: [getInput({ mode: res.key, field: 'username', type: 'text' }), getInput({ mode: res.key, field: 'password', type: 'password' }), getInput({ mode: res.key, field: 'repassword', type: 'password' }), inputs.map((input) => getInput({ mode: res.key, field: input.field, type: input.type, inputProps: input }))] }));
|
|
64
|
-
};
|
|
65
|
-
}
|
|
40
|
+
else if (rootProps.mode) {
|
|
41
|
+
key = rootProps.mode;
|
|
66
42
|
}
|
|
67
|
-
else if (
|
|
68
|
-
|
|
43
|
+
else if (userpass) {
|
|
44
|
+
key = 'userpass';
|
|
69
45
|
}
|
|
70
|
-
else if (
|
|
71
|
-
|
|
72
|
-
res.shouldReturnsUserAndToken = true;
|
|
46
|
+
else if (otpnumber) {
|
|
47
|
+
key = 'otpnumber';
|
|
73
48
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return res;
|
|
77
|
-
}
|
|
78
|
-
function getInput(p) {
|
|
79
|
-
const inputProps = p.inputProps || {};
|
|
80
|
-
let model = modelRef.current;
|
|
81
|
-
if (p.mode === 'register') {
|
|
82
|
-
model = model.register;
|
|
49
|
+
else {
|
|
50
|
+
key = 'userpass';
|
|
83
51
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
setModel(Object.assign(Object.assign({}, model), { register: Object.assign(Object.assign({}, model.register), { [p.field]: v }) }));
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
setModel(Object.assign(Object.assign({}, model), { [p.field]: v }));
|
|
93
|
-
}
|
|
52
|
+
return {
|
|
53
|
+
key,
|
|
54
|
+
submitText: trans(key + 'Button'),
|
|
55
|
+
shouldReturnsUserAndToken: key === 'userpass' || key === 'otpcode',
|
|
56
|
+
title: _jsx("div", { className: "ai-login-title", children: trans(key + 'Title') })
|
|
94
57
|
};
|
|
95
|
-
return (_createElement(AIOInput, Object.assign({}, inputProps, { maxLength, filter, preview, rtl, label, onChange, inputAttrs, key: `${p.mode}-${p.field}`, value: model[p.field], type: p.type })));
|
|
96
58
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
register
|
|
59
|
+
const formHook = useForm({
|
|
60
|
+
initData: () => getModel(), fa,
|
|
61
|
+
isFieldActive: (field) => mode.key === field.split('.')[0],
|
|
62
|
+
inputs: () => {
|
|
63
|
+
let inputs = {
|
|
64
|
+
'userpass.username': { type: 'text', label: trans('username') },
|
|
65
|
+
'userpass.password': { type: 'password', preview: true, label: trans('password') },
|
|
66
|
+
'register.username': { type: 'text', label: trans('username') },
|
|
67
|
+
'register.password': { type: 'password', preview: true, label: trans('password') },
|
|
68
|
+
'register.repassword': { type: 'password', preview: true, label: trans('repassword') },
|
|
69
|
+
'otpnumber': { type: 'text', maxLength: 11, filter: ['number'], label: trans('otpnumber') },
|
|
70
|
+
'otpcode': { type: 'text', maxLength: (otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4, filter: ['number'], label: trans('otpcode') }
|
|
71
|
+
};
|
|
72
|
+
if (register && register.inputs) {
|
|
73
|
+
const registerInputs = register.inputs({});
|
|
74
|
+
for (let field in registerInputs) {
|
|
75
|
+
const input = registerInputs[field];
|
|
76
|
+
inputs[`register.properties.${field}`] = Object.assign(Object.assign({}, input), { inputProps: Object.assign(Object.assign({}, input.inputAttrs), { 'aria-label': `aio-login-${field}` }) });
|
|
77
|
+
}
|
|
107
78
|
}
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
79
|
+
return inputs;
|
|
80
|
+
},
|
|
81
|
+
validate: ({ field, data, value, input }) => {
|
|
82
|
+
if (field === 'otpcode') {
|
|
83
|
+
if ((value || '').length !== ((otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4)) {
|
|
84
|
+
return trans('otpcodeLength');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (!value) {
|
|
88
|
+
if (field === 'otpnumber') {
|
|
89
|
+
return trans('otpnumberRequired');
|
|
90
|
+
}
|
|
91
|
+
if (field === 'userpass.username') {
|
|
92
|
+
return trans('usernameRequired');
|
|
93
|
+
}
|
|
94
|
+
if (field === 'userpass.password') {
|
|
95
|
+
return trans('passwordRequired');
|
|
96
|
+
}
|
|
97
|
+
if (field === 'register.username') {
|
|
98
|
+
return trans('usernameRequired');
|
|
99
|
+
}
|
|
100
|
+
if (field === 'register.password') {
|
|
101
|
+
return trans('passwordRequired');
|
|
102
|
+
}
|
|
103
|
+
if (field === 'register.repassword') {
|
|
104
|
+
return trans('repasswordRequired');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (field === 'register.repassword' && data.register.password !== value) {
|
|
108
|
+
return trans('repasswordMatch');
|
|
109
|
+
}
|
|
110
|
+
return validate({ field, data, value, input });
|
|
111
|
+
},
|
|
112
|
+
onSubmit: (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
113
|
+
const { path, method, body = () => { }, onSuccess } = rootProps[mode.key];
|
|
114
|
+
const { base_url } = rootProps;
|
|
115
|
+
const url = FixUrl(base_url, path);
|
|
116
|
+
loading.show('login0');
|
|
117
|
+
loading.hide('login0');
|
|
118
|
+
axios[method](url, body(data)).then(success).catch(response => {
|
|
119
|
+
const subtext = getMessage(response, mode.key);
|
|
120
|
+
Alert({ type: 'error', text: trans(`${mode.key}Error`), subtext });
|
|
121
|
+
});
|
|
122
|
+
})
|
|
123
|
+
});
|
|
124
|
+
function changeMode(mode) { formHook.setData(getModel()); setMode(getMode(mode)); }
|
|
140
125
|
function success_1(response, mode) {
|
|
141
126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
-
if (!
|
|
127
|
+
if (!rootProps[mode]) {
|
|
143
128
|
return;
|
|
144
129
|
}
|
|
145
|
-
const { onSuccess } =
|
|
130
|
+
const { onSuccess } = rootProps[mode];
|
|
146
131
|
loading.show('login0');
|
|
147
132
|
const res = yield onSuccess(response);
|
|
148
133
|
loading.hide('login0');
|
|
149
134
|
if (typeof res !== 'object' || !res.user || typeof res.token !== 'string') {
|
|
150
135
|
const message = `onSuccess of props.${mode}.${mode === 'userpass' ? 'api' : 'codeApi'} should returns {user:any,token:string}`;
|
|
151
|
-
|
|
136
|
+
Alert({ type: 'error', text: trans(`${mode}Error`), subtext: message });
|
|
152
137
|
}
|
|
153
138
|
else {
|
|
154
139
|
if (res.message) {
|
|
155
|
-
|
|
140
|
+
Alert({ type: 'success', text: res.message });
|
|
156
141
|
}
|
|
157
142
|
const { user, token } = res;
|
|
158
143
|
storage.save('data', { user, token });
|
|
@@ -162,15 +147,15 @@ const AILogin = (props) => {
|
|
|
162
147
|
}
|
|
163
148
|
function success_2(response, mode) {
|
|
164
149
|
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
-
if (!
|
|
150
|
+
if (!rootProps[mode]) {
|
|
166
151
|
return;
|
|
167
152
|
}
|
|
168
|
-
const { onSuccess } =
|
|
153
|
+
const { onSuccess } = rootProps[mode];
|
|
169
154
|
loading.show('login0');
|
|
170
155
|
const res = yield onSuccess(response);
|
|
171
156
|
loading.hide('login0');
|
|
172
157
|
if (res.message) {
|
|
173
|
-
|
|
158
|
+
Alert({ type: 'success', text: res.message });
|
|
174
159
|
}
|
|
175
160
|
if (mode === 'otpnumber') {
|
|
176
161
|
setMode(getMode('otpcode'));
|
|
@@ -190,154 +175,245 @@ const AILogin = (props) => {
|
|
|
190
175
|
}
|
|
191
176
|
});
|
|
192
177
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
setAlert({ type: 'error', text: 'Error', subtext: response.message });
|
|
178
|
+
const getStatus = (error, name) => {
|
|
179
|
+
let text = `${name} unknown status.`, subtext = 'please set getStatus props in useLogin for extracting status';
|
|
180
|
+
if (error.response) {
|
|
181
|
+
const data = error.response.data;
|
|
182
|
+
let status = error.response.status;
|
|
183
|
+
if (typeof status !== 'number') {
|
|
184
|
+
const { getStatus = () => { } } = rootProps;
|
|
185
|
+
status = getStatus(error);
|
|
186
|
+
if (typeof status === 'number') {
|
|
187
|
+
return status;
|
|
204
188
|
}
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
function changeMode(mode) { setModel(getModel()); setMode(getMode(mode)); }
|
|
209
|
-
function mode_props(key) { return { className: 'ai-login-mode', onClick: () => changeMode(key) }; }
|
|
210
|
-
function mode_layout() {
|
|
211
|
-
return (_jsxs("div", { className: "ai-login-modes", children: [props.userpass && mode.key !== 'userpass' && _jsx("button", Object.assign({}, mode_props('userpass'), { children: trans('switchuserpass') })), props.register && mode.key !== 'register' && _jsx("button", Object.assign({}, mode_props('register'), { children: trans('switchregister') })), props.otp && mode.key !== 'otpnumber' && _jsx("button", Object.assign({}, mode_props('otpnumber'), { children: trans('switchotp') }))] }));
|
|
212
|
-
}
|
|
213
|
-
function validate() {
|
|
214
|
-
const model = modelRef.current;
|
|
215
|
-
if (mode.key === 'otpcode') {
|
|
216
|
-
if ((model.otpcode || '').length !== otpLength) {
|
|
217
|
-
return trans('otpcodeLength');
|
|
218
189
|
}
|
|
219
190
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (
|
|
227
|
-
return
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (mode.key === 'register') {
|
|
231
|
-
if (!model.register.username) {
|
|
232
|
-
return trans('usernameRequired');
|
|
191
|
+
Alert({ type: 'error', text, subtext });
|
|
192
|
+
};
|
|
193
|
+
const getMessage = (error, name) => {
|
|
194
|
+
let text = `${name} unknown message.`, subtext = 'please set getMessage props in useLogin for extracting message';
|
|
195
|
+
if (error.response) {
|
|
196
|
+
const data = error.response.data;
|
|
197
|
+
if (typeof data === 'string') {
|
|
198
|
+
return data;
|
|
233
199
|
}
|
|
234
|
-
if (
|
|
235
|
-
return
|
|
200
|
+
else if (data === null || data === void 0 ? void 0 : data.message) {
|
|
201
|
+
return data.message;
|
|
236
202
|
}
|
|
237
|
-
if (
|
|
238
|
-
return
|
|
203
|
+
else if (data === null || data === void 0 ? void 0 : data.error) {
|
|
204
|
+
return data.error;
|
|
239
205
|
}
|
|
240
|
-
|
|
241
|
-
|
|
206
|
+
else {
|
|
207
|
+
const { getMessage = () => '' } = rootProps;
|
|
208
|
+
const message = getMessage(error);
|
|
209
|
+
if (message) {
|
|
210
|
+
return message;
|
|
211
|
+
}
|
|
242
212
|
}
|
|
243
213
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
214
|
+
else if (typeof error.request === 'string') {
|
|
215
|
+
return error.request;
|
|
216
|
+
}
|
|
217
|
+
else if (typeof error.message === 'string') {
|
|
218
|
+
return error.message;
|
|
219
|
+
}
|
|
220
|
+
Alert({ text, subtext, type: 'error' });
|
|
221
|
+
return 'unkown message';
|
|
222
|
+
};
|
|
223
|
+
const checkTokenCatch = (error) => {
|
|
224
|
+
const status = getStatus(error, 'checking token');
|
|
225
|
+
if (status === 401) {
|
|
226
|
+
logout();
|
|
227
|
+
}
|
|
228
|
+
const message = getMessage(error, 'checking token');
|
|
229
|
+
let text = 'error in checking token';
|
|
230
|
+
if (rootProps.fa) {
|
|
231
|
+
text = 'خطا در بررسی توکن';
|
|
232
|
+
}
|
|
233
|
+
Alert({ type: 'error', text, subtext: message });
|
|
234
|
+
};
|
|
235
|
+
const checkTokenThen = (response, user, token) => {
|
|
236
|
+
const { checkToken } = rootProps;
|
|
237
|
+
const { getResult = () => true } = checkToken;
|
|
238
|
+
const res = getResult(response);
|
|
239
|
+
if (res === true) {
|
|
240
|
+
setData({ user, token });
|
|
241
|
+
setCheckingToken(true);
|
|
242
|
+
}
|
|
243
|
+
else if (res === false) {
|
|
244
|
+
logout();
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
Alert({ type: 'error', text: 'check token error', subtext: 'checkToken.getResult should returns boolean' });
|
|
263
248
|
}
|
|
264
|
-
return (_jsx("div", { className: `ai-login-${type}`, children: content }));
|
|
265
249
|
};
|
|
266
|
-
function logout() { storage.remove('data'); window.location.reload(); }
|
|
267
250
|
function CheckToken() {
|
|
268
251
|
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
-
if (
|
|
270
|
-
setTimeout(() => { setSplashing(false); },
|
|
252
|
+
if (rootProps.splash) {
|
|
253
|
+
setTimeout(() => { setSplashing(false); }, rootProps.splash.time);
|
|
271
254
|
}
|
|
272
|
-
if (
|
|
273
|
-
setData({ user:
|
|
255
|
+
if (rootProps.mock) {
|
|
256
|
+
setData({ user: rootProps.mock.user, token: rootProps.mock.token });
|
|
274
257
|
return;
|
|
275
258
|
}
|
|
276
|
-
const storedData = storage.load('data', {})
|
|
259
|
+
const storedData = storage.load('data', {});
|
|
260
|
+
const { user, token } = storedData;
|
|
277
261
|
loading.show('login0');
|
|
278
|
-
const {
|
|
262
|
+
const { checkToken } = rootProps;
|
|
263
|
+
const { url, method = 'get', body } = checkToken;
|
|
279
264
|
loading.hide('login0');
|
|
280
265
|
if (user && token) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (res === true) {
|
|
292
|
-
setData({ user, token });
|
|
293
|
-
}
|
|
294
|
-
else if (res === false) {
|
|
295
|
-
logout();
|
|
296
|
-
}
|
|
297
|
-
else {
|
|
298
|
-
setAlert({ type: 'error', text: 'checkToken failed', subtext: 'checkToken props should return string as error or true as token is valid and false as token is invalid' });
|
|
299
|
-
}
|
|
300
|
-
})
|
|
301
|
-
.catch(response => {
|
|
302
|
-
let res, message = '';
|
|
303
|
-
try {
|
|
304
|
-
res = onCatch(response);
|
|
305
|
-
}
|
|
306
|
-
catch (err) {
|
|
307
|
-
message = err.message;
|
|
308
|
-
}
|
|
309
|
-
if (typeof res === 'string') {
|
|
310
|
-
message = res;
|
|
311
|
-
}
|
|
312
|
-
else if (res === false) {
|
|
313
|
-
logout();
|
|
314
|
-
}
|
|
315
|
-
else {
|
|
316
|
-
message = 'AILogin checkToken onCatch props should returns string as error or false as invalid token';
|
|
317
|
-
}
|
|
318
|
-
if (message) {
|
|
319
|
-
setAlert({ type: 'error', text: 'checkToken failed', subtext: message });
|
|
320
|
-
}
|
|
321
|
-
else if (response.message) {
|
|
322
|
-
setAlert({ type: 'error', text: 'Error', subtext: response.message });
|
|
323
|
-
}
|
|
324
|
-
});
|
|
266
|
+
const headers = { authorization: `Bearer ${token}` };
|
|
267
|
+
if (method === 'get') {
|
|
268
|
+
axios.get(url, { headers }).then(response => checkTokenThen(response, user, token)).catch(error => checkTokenCatch(error));
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
axios.post(url, body, { headers }).then(response => checkTokenThen(response, user, token)).catch(error => checkTokenCatch(error));
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
logout();
|
|
325
276
|
}
|
|
326
|
-
setWeightingCheckToken(false);
|
|
327
277
|
});
|
|
328
278
|
}
|
|
279
|
+
function logout() {
|
|
280
|
+
storage.remove('data');
|
|
281
|
+
setCheckingToken(false);
|
|
282
|
+
setData(undefined);
|
|
283
|
+
}
|
|
284
|
+
function trans(key) {
|
|
285
|
+
const dic = {
|
|
286
|
+
username: { en: 'User Name', fa: 'نام کاربری' },
|
|
287
|
+
password: { en: 'Password', fa: 'رمز عبور' },
|
|
288
|
+
repassword: { en: 'User Name', fa: 'تکرار رمز عبور' },
|
|
289
|
+
otpnumber: { en: 'Phone Number', fa: 'شماره همراه' },
|
|
290
|
+
otpcode: { en: 'One Time Code', fa: 'کد یکبار مصرف' },
|
|
291
|
+
registerButton: { en: 'Register', fa: 'ثبت نام' },
|
|
292
|
+
userpassButton: { en: 'Login', fa: 'ورود' },
|
|
293
|
+
otpnumberButton: { en: 'Send Number', fa: 'ارسال شماره همراه' },
|
|
294
|
+
otpcodeButton: { en: 'Login', fa: 'ورود' },
|
|
295
|
+
registerTitle: { en: 'Register', fa: 'ثبت نام' },
|
|
296
|
+
userpassTitle: { en: 'Login', fa: 'ورود' },
|
|
297
|
+
otpcodeTitle: { en: 'One Time Code', fa: 'کد یکبار مصرف' },
|
|
298
|
+
otpnumberTitle: { en: 'Phone Number', fa: 'شماره همراه' },
|
|
299
|
+
switchuserpass: { en: 'login by user name', fa: 'ورود با نام کاربری' },
|
|
300
|
+
switchregister: { en: 'Go To Register', fa: 'ثبت نام' },
|
|
301
|
+
switchotpnumber: { en: 'login by otp', fa: 'ورود با رمز یکبار مصرف' },
|
|
302
|
+
repasswordMatch: { en: 'Password is not match with Re password', fa: 'رمز عبور با تکرار آن مطابقت ندارد' },
|
|
303
|
+
usernameRequired: { en: 'User Name is required', fa: 'نام کاربری ضروری است' },
|
|
304
|
+
passwordRequired: { en: 'password is required', fa: 'رمز عبور ضروری است' },
|
|
305
|
+
repasswordRequired: { en: 'Re Password is required', fa: 'تکرار رمز عبور ضروری است' },
|
|
306
|
+
otpnumberRequired: { en: 'Phone Number is required', fa: 'شماره همراه ضروری است' },
|
|
307
|
+
otpcodeLength: { en: `otp code should be ${(otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4} digit`, fa: `کد یکبار مصرف باید ${(otpcode === null || otpcode === void 0 ? void 0 : otpcode.length) || 4} رقم باشد` },
|
|
308
|
+
registerError: { en: 'Registeration failed', fa: 'ثبت نام با خطا روبرو شد' },
|
|
309
|
+
userpassError: { en: 'login by username failed', fa: 'ورود با نام کاربری با خطا روبرو شد' },
|
|
310
|
+
otpcodeError: { en: 'login by otp failed', fa: 'ورود با کد یکبار مصرف با خطا روبرو شد' },
|
|
311
|
+
otpnumberError: { en: 'send otp number for receive otp code failed', fa: 'ارسال شماره همراه برای دریافت کد یکبار مصرف با خطا روبرو شد' },
|
|
312
|
+
};
|
|
313
|
+
return fa ? dic[key].fa : translate(key) || dic[key].en;
|
|
314
|
+
}
|
|
329
315
|
useEffect(() => { CheckToken(); }, []);
|
|
330
|
-
function
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
316
|
+
function getModel() {
|
|
317
|
+
let model = {
|
|
318
|
+
userpass: { username: '', password: '' },
|
|
319
|
+
otpnumber: '', otpcode: '',
|
|
320
|
+
register: { username: '', password: '', repassword: '', properties: {} }
|
|
321
|
+
};
|
|
322
|
+
if (!register) {
|
|
323
|
+
return model;
|
|
324
|
+
}
|
|
325
|
+
if (register && register.inputs && register.defaultData) {
|
|
326
|
+
model.register.properties = Object.assign({}, register.defaultData);
|
|
327
|
+
}
|
|
328
|
+
return model;
|
|
329
|
+
}
|
|
330
|
+
const getFormNode = () => {
|
|
331
|
+
let registerInputs = {};
|
|
332
|
+
if (register && register.inputs) {
|
|
333
|
+
registerInputs = register.inputs(formHook.data);
|
|
334
|
+
}
|
|
335
|
+
const registerFields = Object.keys(registerInputs);
|
|
336
|
+
return {
|
|
337
|
+
scroll: true,
|
|
338
|
+
v: [
|
|
339
|
+
{ input: 'userpass.username', show: mode.key === 'userpass' },
|
|
340
|
+
{ input: 'userpass.password', show: mode.key === 'userpass' },
|
|
341
|
+
{ input: 'register.username', show: mode.key === 'register' },
|
|
342
|
+
{ input: 'register.password', show: mode.key === 'register' },
|
|
343
|
+
{ input: 'register.repassword', show: mode.key === 'register' },
|
|
344
|
+
{ input: 'otpnumber', show: mode.key === 'otpnumber' },
|
|
345
|
+
{ input: 'otpcode', show: mode.key === 'otpcode' },
|
|
346
|
+
{ v: registerFields.map((field) => ({ input: `register.properties.${field}`, show: mode.key === 'register' })) }
|
|
347
|
+
]
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
function renderMode(modeKey) {
|
|
351
|
+
if (mode.key === modeKey) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
return _jsx("button", { className: 'ai-login-mode', onClick: () => changeMode(modeKey), children: trans(`switch${modeKey}`) });
|
|
355
|
+
}
|
|
356
|
+
function renderModes() {
|
|
357
|
+
return (_jsxs("div", { className: "ai-login-modes", children: [userpass && renderMode('userpass'), register && renderMode('register'), otpnumber && renderMode('otpnumber')] }));
|
|
358
|
+
}
|
|
359
|
+
function renderLoginBox() {
|
|
360
|
+
const { title } = mode;
|
|
361
|
+
return formHook.render({
|
|
362
|
+
attrs: { className: "ai-login-form" },
|
|
363
|
+
v: [
|
|
364
|
+
{ html: title },
|
|
365
|
+
getFormNode(),
|
|
366
|
+
{ html: _jsx("div", { style: { height: 24 } }), size: 24, },
|
|
367
|
+
{ submitButton: { text: mode.submitText, attrs: { className: 'ai-login-submit' } } },
|
|
368
|
+
{ html: renderModes() }
|
|
369
|
+
]
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
const bf_layout = (type) => {
|
|
373
|
+
const fn = rootProps[type];
|
|
374
|
+
let content = null;
|
|
375
|
+
if (fn) {
|
|
376
|
+
content = fn(mode.key);
|
|
377
|
+
}
|
|
378
|
+
return (_jsx("div", { className: `ai-login-${type}`, children: content }));
|
|
379
|
+
};
|
|
380
|
+
function renderLoginPage() {
|
|
381
|
+
if (checkingToken || splashing) {
|
|
382
|
+
return splash ? splash.html : null;
|
|
334
383
|
}
|
|
335
384
|
if (!data) {
|
|
336
|
-
const attrs = AddToAttrs(
|
|
337
|
-
return (_jsxs("div", Object.assign({}, attrs, { children: [bf_layout('before'), " ",
|
|
385
|
+
const attrs = AddToAttrs(rootProps.attrs, { className: 'ai-login', style: { direction: !!rootProps.fa ? 'rtl' : undefined } });
|
|
386
|
+
return (_jsxs("div", Object.assign({}, attrs, { children: [bf_layout('before'), " ", renderLoginBox(), " ", bf_layout('after')] })));
|
|
338
387
|
}
|
|
339
|
-
return
|
|
388
|
+
return _jsx(Navigate, { to: "/" });
|
|
340
389
|
}
|
|
341
|
-
|
|
390
|
+
function renderApp() {
|
|
391
|
+
const { user, token } = data || {};
|
|
392
|
+
const { app, base_url } = rootProps;
|
|
393
|
+
if (user && token) {
|
|
394
|
+
const COMP = app;
|
|
395
|
+
return _jsx(COMP, { user: user, token: token, logout: logout, base_url: base_url });
|
|
396
|
+
}
|
|
397
|
+
if (checkingToken === false) {
|
|
398
|
+
return _jsx(Navigate, { to: "/login" });
|
|
399
|
+
}
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
logout, storage,
|
|
404
|
+
splashing, loading, checkingToken,
|
|
405
|
+
data, setData,
|
|
406
|
+
getMessage, trans,
|
|
407
|
+
getModel, formHook,
|
|
408
|
+
mode, getMode, setMode, changeMode,
|
|
409
|
+
renderApp, renderLoginBox, renderLoginPage
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
const useLogin = (props) => {
|
|
413
|
+
const render = () => {
|
|
414
|
+
const hook = useLoading(props);
|
|
415
|
+
return (_jsxs(Routes, { children: [_jsx(Route, { path: '/login', element: hook.renderLoginPage() }), _jsx(Route, { path: "/*", element: hook.renderApp() })] }));
|
|
416
|
+
};
|
|
417
|
+
return { render };
|
|
342
418
|
};
|
|
343
|
-
export default
|
|
419
|
+
export default useLogin;
|