@etsoo/materialui 1.2.26 → 1.2.28
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/lib/Tiplist.js +20 -15
- package/lib/TiplistPro.js +20 -15
- package/lib/app/IServiceUser.d.ts +5 -1
- package/lib/app/ServiceApp.d.ts +7 -7
- package/lib/app/ServiceApp.js +19 -19
- package/package.json +1 -1
- package/src/Tiplist.tsx +23 -17
- package/src/TiplistPro.tsx +21 -17
- package/src/app/IServiceUser.ts +11 -6
- package/src/app/ServiceApp.ts +308 -319
package/lib/Tiplist.js
CHANGED
|
@@ -11,7 +11,7 @@ import { InputField } from "./InputField";
|
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
13
|
export function Tiplist(props) {
|
|
14
|
-
var _a
|
|
14
|
+
var _a;
|
|
15
15
|
// Labels
|
|
16
16
|
const { noOptions, loading, more, open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
|
|
17
17
|
// Destruct
|
|
@@ -41,9 +41,12 @@ export function Tiplist(props) {
|
|
|
41
41
|
if (localValue != null)
|
|
42
42
|
stateUpdate({ value: localValue });
|
|
43
43
|
}, [localValue]);
|
|
44
|
-
//
|
|
45
|
-
const
|
|
46
|
-
|
|
44
|
+
// Ref
|
|
45
|
+
const state = React.useRef({
|
|
46
|
+
idLoaded: false,
|
|
47
|
+
idSet: false,
|
|
48
|
+
isMounted: false
|
|
49
|
+
});
|
|
47
50
|
// Add readOnly
|
|
48
51
|
const addReadOnly = (params) => {
|
|
49
52
|
if (readOnly != null) {
|
|
@@ -87,7 +90,7 @@ export function Tiplist(props) {
|
|
|
87
90
|
stateUpdate({ loading: true });
|
|
88
91
|
// Load list
|
|
89
92
|
loadData(keyword, id, maxItems).then((options) => {
|
|
90
|
-
if (!
|
|
93
|
+
if (!state.current.isMounted)
|
|
91
94
|
return;
|
|
92
95
|
if (options != null && options.length >= maxItems) {
|
|
93
96
|
options.push({ [idField]: "n/a" });
|
|
@@ -123,42 +126,44 @@ export function Tiplist(props) {
|
|
|
123
126
|
if (localIdValue == null) {
|
|
124
127
|
if (inputValue != null)
|
|
125
128
|
setInputValue(null);
|
|
129
|
+
return;
|
|
126
130
|
}
|
|
127
|
-
|
|
128
|
-
state.idLoaded = false;
|
|
129
|
-
state.idSet = false;
|
|
131
|
+
if (state.current.idLoaded) {
|
|
132
|
+
state.current.idLoaded = false;
|
|
133
|
+
state.current.idSet = false;
|
|
130
134
|
}
|
|
131
135
|
}, [localIdValue]);
|
|
132
136
|
React.useEffect(() => {
|
|
133
137
|
if (localIdValue != null && localIdValue !== "") {
|
|
134
|
-
if (state.idLoaded) {
|
|
138
|
+
if (state.current.idLoaded) {
|
|
135
139
|
// Set default
|
|
136
|
-
if (!state.idSet && states.options.length > 0) {
|
|
140
|
+
if (!state.current.idSet && states.options.length > 0) {
|
|
137
141
|
const item = states.options.find((o) => o[idField] === localIdValue);
|
|
138
142
|
if (item) {
|
|
139
143
|
stateUpdate({
|
|
140
144
|
value: states.options[0]
|
|
141
145
|
});
|
|
142
|
-
state.idSet = true;
|
|
146
|
+
state.current.idSet = true;
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
else {
|
|
147
151
|
// Load id data
|
|
148
152
|
loadDataDirect(undefined, localIdValue);
|
|
149
|
-
state.idLoaded = true;
|
|
153
|
+
state.current.idLoaded = true;
|
|
150
154
|
}
|
|
151
155
|
}
|
|
152
|
-
}, [
|
|
156
|
+
}, [localIdValue, states.options]);
|
|
153
157
|
React.useEffect(() => {
|
|
158
|
+
state.current.isMounted = true;
|
|
154
159
|
return () => {
|
|
155
|
-
|
|
160
|
+
state.current.isMounted = false;
|
|
156
161
|
delayed.clear();
|
|
157
162
|
};
|
|
158
163
|
}, []);
|
|
159
164
|
// Layout
|
|
160
165
|
return (React.createElement("div", null,
|
|
161
|
-
React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: "none" }, name: name, value: `${
|
|
166
|
+
React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: "none" }, name: name, value: `${inputValue !== null && inputValue !== void 0 ? inputValue : (state.current.idSet ? "" : localIdValue !== null && localIdValue !== void 0 ? localIdValue : "")}`, readOnly: true, onChange: inputOnChange }),
|
|
162
167
|
React.createElement(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, onChange: (event, value, reason, details) => {
|
|
163
168
|
// Set value
|
|
164
169
|
setInputValue(value);
|
package/lib/TiplistPro.js
CHANGED
|
@@ -9,7 +9,7 @@ import { globalApp } from "./app/ReactApp";
|
|
|
9
9
|
* @returns Component
|
|
10
10
|
*/
|
|
11
11
|
export function TiplistPro(props) {
|
|
12
|
-
var _a
|
|
12
|
+
var _a;
|
|
13
13
|
// Labels
|
|
14
14
|
const { noOptions, loading, more, open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
|
|
15
15
|
// Destruct
|
|
@@ -41,9 +41,12 @@ export function TiplistPro(props) {
|
|
|
41
41
|
const inputValue = React.useMemo(() => states.value && typeof states.value === "object"
|
|
42
42
|
? states.value.id
|
|
43
43
|
: undefined, [states.value]);
|
|
44
|
-
//
|
|
45
|
-
const
|
|
46
|
-
|
|
44
|
+
// Ref
|
|
45
|
+
const state = React.useRef({
|
|
46
|
+
idLoaded: false,
|
|
47
|
+
idSet: false,
|
|
48
|
+
isMounted: false
|
|
49
|
+
});
|
|
47
50
|
// Change handler
|
|
48
51
|
const changeHandle = (event) => {
|
|
49
52
|
// Stop processing with auto trigger event
|
|
@@ -77,7 +80,7 @@ export function TiplistPro(props) {
|
|
|
77
80
|
stateUpdate({ loading: true });
|
|
78
81
|
// Load list
|
|
79
82
|
loadData(keyword, id, maxItems).then((options) => {
|
|
80
|
-
if (!
|
|
83
|
+
if (!state.current.isMounted)
|
|
81
84
|
return;
|
|
82
85
|
if (options != null && options.length >= maxItems) {
|
|
83
86
|
options.push({ id: -1, name: "n/a" });
|
|
@@ -113,39 +116,41 @@ export function TiplistPro(props) {
|
|
|
113
116
|
if (localIdValue == null) {
|
|
114
117
|
if (inputValue != null)
|
|
115
118
|
setInputValue(null);
|
|
119
|
+
return;
|
|
116
120
|
}
|
|
117
|
-
|
|
118
|
-
state.idLoaded = false;
|
|
119
|
-
state.idSet = false;
|
|
121
|
+
if (state.current.idLoaded) {
|
|
122
|
+
state.current.idLoaded = false;
|
|
123
|
+
state.current.idSet = false;
|
|
120
124
|
}
|
|
121
125
|
}, [localIdValue]);
|
|
122
126
|
React.useEffect(() => {
|
|
123
127
|
if (localIdValue != null && localIdValue !== "") {
|
|
124
|
-
if (state.idLoaded) {
|
|
128
|
+
if (state.current.idLoaded) {
|
|
125
129
|
// Set default
|
|
126
|
-
if (!state.idSet && states.options.length > 0) {
|
|
130
|
+
if (!state.current.idSet && states.options.length > 0) {
|
|
127
131
|
stateUpdate({
|
|
128
132
|
value: states.options.find((o) => o.id === localIdValue)
|
|
129
133
|
});
|
|
130
|
-
state.idSet = true;
|
|
134
|
+
state.current.idSet = true;
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
else {
|
|
134
138
|
// Load id data
|
|
135
139
|
loadDataDirect(undefined, localIdValue);
|
|
136
|
-
state.idLoaded = true;
|
|
140
|
+
state.current.idLoaded = true;
|
|
137
141
|
}
|
|
138
142
|
}
|
|
139
|
-
}, [
|
|
143
|
+
}, [localIdValue, states.options]);
|
|
140
144
|
React.useEffect(() => {
|
|
145
|
+
state.current.isMounted = true;
|
|
141
146
|
return () => {
|
|
142
|
-
|
|
147
|
+
state.current.isMounted = false;
|
|
143
148
|
delayed.clear();
|
|
144
149
|
};
|
|
145
150
|
}, []);
|
|
146
151
|
// Layout
|
|
147
152
|
return (React.createElement("div", null,
|
|
148
|
-
React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: "none" }, name: name, value:
|
|
153
|
+
React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: "none" }, name: name, value: inputValue !== null && inputValue !== void 0 ? inputValue : (state.current.idSet ? "" : localIdValue !== null && localIdValue !== void 0 ? localIdValue : ""), readOnly: true, onChange: inputOnChange }),
|
|
149
154
|
React.createElement(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, freeSolo: true, clearOnBlur: false, onChange: (event, value, reason, details) => {
|
|
150
155
|
if (typeof value === "object") {
|
|
151
156
|
// Set value
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IActionResult, IUser } from
|
|
1
|
+
import { IActionResult, IUser } from "@etsoo/appscript";
|
|
2
2
|
/**
|
|
3
3
|
* Service user interface
|
|
4
4
|
*/
|
|
@@ -7,6 +7,10 @@ export interface IServiceUser extends IUser {
|
|
|
7
7
|
* Service device id
|
|
8
8
|
*/
|
|
9
9
|
serviceDeviceId: string;
|
|
10
|
+
/**
|
|
11
|
+
* Service passphrase encrypted
|
|
12
|
+
*/
|
|
13
|
+
servicePassphrase: string;
|
|
10
14
|
}
|
|
11
15
|
/**
|
|
12
16
|
* Service user login result
|
package/lib/app/ServiceApp.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { IApi, RefreshTokenProps, RefreshTokenRQ } from
|
|
2
|
-
import { IServiceApp } from
|
|
3
|
-
import { IServiceAppSettings } from
|
|
4
|
-
import { IServicePageData } from
|
|
5
|
-
import { IServiceUser } from
|
|
6
|
-
import { ISmartERPUser } from
|
|
7
|
-
import { ReactApp } from
|
|
1
|
+
import { IApi, RefreshTokenProps, RefreshTokenRQ } from "@etsoo/appscript";
|
|
2
|
+
import { IServiceApp } from "./IServiceApp";
|
|
3
|
+
import { IServiceAppSettings } from "./IServiceAppSettings";
|
|
4
|
+
import { IServicePageData } from "./IServicePage";
|
|
5
|
+
import { IServiceUser } from "./IServiceUser";
|
|
6
|
+
import { ISmartERPUser } from "./ISmartERPUser";
|
|
7
|
+
import { ReactApp } from "./ReactApp";
|
|
8
8
|
/**
|
|
9
9
|
* Core Service App
|
|
10
10
|
* Service login to core system, get the refesh token and access token
|
package/lib/app/ServiceApp.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { BridgeUtils, createClient } from
|
|
2
|
-
import { CoreConstants } from
|
|
3
|
-
import { DomUtils } from
|
|
4
|
-
import { ReactApp } from
|
|
1
|
+
import { BridgeUtils, createClient } from "@etsoo/appscript";
|
|
2
|
+
import { CoreConstants } from "@etsoo/react";
|
|
3
|
+
import { DomUtils } from "@etsoo/shared";
|
|
4
|
+
import { ReactApp } from "./ReactApp";
|
|
5
5
|
/**
|
|
6
6
|
* Core Service App
|
|
7
7
|
* Service login to core system, get the refesh token and access token
|
|
@@ -28,10 +28,10 @@ export class ServiceApp extends ReactApp {
|
|
|
28
28
|
/**
|
|
29
29
|
* Service passphrase
|
|
30
30
|
*/
|
|
31
|
-
this.servicePassphrase =
|
|
31
|
+
this.servicePassphrase = "";
|
|
32
32
|
// Check
|
|
33
33
|
if (settings.serviceId == null || settings.serviceEndpoint == null) {
|
|
34
|
-
throw new Error(
|
|
34
|
+
throw new Error("No service settings");
|
|
35
35
|
}
|
|
36
36
|
// Service API
|
|
37
37
|
const api = createClient();
|
|
@@ -48,7 +48,7 @@ export class ServiceApp extends ReactApp {
|
|
|
48
48
|
window.location.href = this.settings.webUrl;
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
BridgeUtils.host.loadApp(
|
|
51
|
+
BridgeUtils.host.loadApp("core");
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
@@ -56,13 +56,13 @@ export class ServiceApp extends ReactApp {
|
|
|
56
56
|
* @param tryLogin Try to login again
|
|
57
57
|
*/
|
|
58
58
|
toLoginPage(tryLogin) {
|
|
59
|
-
const parameters = `?serviceId=${this.settings.serviceId}&${DomUtils.CultureField}=${this.culture}${tryLogin ?
|
|
59
|
+
const parameters = `?serviceId=${this.settings.serviceId}&${DomUtils.CultureField}=${this.culture}${tryLogin ? "" : "&tryLogin=false"}`;
|
|
60
60
|
if (BridgeUtils.host == null) {
|
|
61
61
|
const coreUrl = this.settings.webUrl;
|
|
62
62
|
window.location.href = coreUrl + parameters;
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
BridgeUtils.host.loadApp(
|
|
65
|
+
BridgeUtils.host.loadApp("core", parameters);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
@@ -74,7 +74,7 @@ export class ServiceApp extends ReactApp {
|
|
|
74
74
|
const { callback, data, relogin = false, showLoading = false } = props !== null && props !== void 0 ? props : {};
|
|
75
75
|
// Token
|
|
76
76
|
const token = this.getCacheToken();
|
|
77
|
-
if (token == null || token ===
|
|
77
|
+
if (token == null || token === "") {
|
|
78
78
|
if (callback)
|
|
79
79
|
callback(false);
|
|
80
80
|
return false;
|
|
@@ -103,13 +103,13 @@ export class ServiceApp extends ReactApp {
|
|
|
103
103
|
const refreshToken = this.getResponseToken(payload.response);
|
|
104
104
|
if (refreshToken == null || result.data == null) {
|
|
105
105
|
if (failCallback)
|
|
106
|
-
failCallback(this.get(
|
|
106
|
+
failCallback(this.get("noData"));
|
|
107
107
|
return false;
|
|
108
108
|
}
|
|
109
109
|
// User data
|
|
110
110
|
const userData = result.data;
|
|
111
111
|
// Use core system access token to service api to exchange service access token
|
|
112
|
-
const serviceResult = await this.serviceApi.put(
|
|
112
|
+
const serviceResult = await this.serviceApi.put("Auth/ExchangeToken", {
|
|
113
113
|
token: this.encryptEnhanced(userData.token, this.settings.serviceId.toString())
|
|
114
114
|
}, {
|
|
115
115
|
showLoading,
|
|
@@ -129,7 +129,7 @@ export class ServiceApp extends ReactApp {
|
|
|
129
129
|
}
|
|
130
130
|
if (serviceResult.data == null) {
|
|
131
131
|
if (failCallback)
|
|
132
|
-
failCallback(this.get(
|
|
132
|
+
failCallback(this.get("noData"));
|
|
133
133
|
return false;
|
|
134
134
|
}
|
|
135
135
|
// Login
|
|
@@ -140,14 +140,14 @@ export class ServiceApp extends ReactApp {
|
|
|
140
140
|
return true;
|
|
141
141
|
};
|
|
142
142
|
// Call API
|
|
143
|
-
const result = await this.api.put(
|
|
143
|
+
const result = await this.api.put("Auth/RefreshToken", rq, payload);
|
|
144
144
|
if (result == null)
|
|
145
145
|
return false;
|
|
146
146
|
if (!result.ok) {
|
|
147
|
-
if (result.type ===
|
|
147
|
+
if (result.type === "TokenExpired" && relogin) {
|
|
148
148
|
// Try login
|
|
149
149
|
// Dialog to receive password
|
|
150
|
-
var labels = this.getLabels(
|
|
150
|
+
var labels = this.getLabels("reloginTip", "login");
|
|
151
151
|
this.notifier.prompt(labels.reloginTip, async (pwd) => {
|
|
152
152
|
if (pwd == null) {
|
|
153
153
|
this.toLoginPage();
|
|
@@ -156,7 +156,7 @@ export class ServiceApp extends ReactApp {
|
|
|
156
156
|
// Set password for the action
|
|
157
157
|
rq.pwd = this.encrypt(this.hash(pwd));
|
|
158
158
|
// Submit again
|
|
159
|
-
const result = await this.api.put(
|
|
159
|
+
const result = await this.api.put("Auth/RefreshToken", rq, payload);
|
|
160
160
|
if (result == null)
|
|
161
161
|
return;
|
|
162
162
|
if (result.ok) {
|
|
@@ -175,7 +175,7 @@ export class ServiceApp extends ReactApp {
|
|
|
175
175
|
// Popup message
|
|
176
176
|
this.alertResult(result);
|
|
177
177
|
return false;
|
|
178
|
-
}, labels.login, { type:
|
|
178
|
+
}, labels.login, { type: "password" });
|
|
179
179
|
// Fake truth to avoid reloading
|
|
180
180
|
return true;
|
|
181
181
|
}
|
|
@@ -233,7 +233,7 @@ export class ServiceApp extends ReactApp {
|
|
|
233
233
|
var _a;
|
|
234
234
|
// Service user login
|
|
235
235
|
this.servicePassphrase =
|
|
236
|
-
(_a = this.decrypt(serviceUser.
|
|
236
|
+
(_a = this.decrypt(serviceUser.servicePassphrase, this.settings.serviceId.toString())) !== null && _a !== void 0 ? _a : "";
|
|
237
237
|
// Service user
|
|
238
238
|
this.serviceUser = serviceUser;
|
|
239
239
|
// Service API token
|
package/package.json
CHANGED
package/src/Tiplist.tsx
CHANGED
|
@@ -129,12 +129,12 @@ export function Tiplist<
|
|
|
129
129
|
if (localValue != null) stateUpdate({ value: localValue });
|
|
130
130
|
}, [localValue]);
|
|
131
131
|
|
|
132
|
-
//
|
|
133
|
-
const
|
|
134
|
-
idLoaded
|
|
135
|
-
idSet
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
// Ref
|
|
133
|
+
const state = React.useRef({
|
|
134
|
+
idLoaded: false,
|
|
135
|
+
idSet: false,
|
|
136
|
+
isMounted: false
|
|
137
|
+
});
|
|
138
138
|
|
|
139
139
|
// Add readOnly
|
|
140
140
|
const addReadOnly = (params: AutocompleteRenderInputParams) => {
|
|
@@ -189,7 +189,7 @@ export function Tiplist<
|
|
|
189
189
|
|
|
190
190
|
// Load list
|
|
191
191
|
loadData(keyword, id, maxItems).then((options) => {
|
|
192
|
-
if (!
|
|
192
|
+
if (!state.current.isMounted) return;
|
|
193
193
|
|
|
194
194
|
if (options != null && options.length >= maxItems) {
|
|
195
195
|
options.push({ [idField]: "n/a" } as T);
|
|
@@ -228,36 +228,40 @@ export function Tiplist<
|
|
|
228
228
|
React.useEffect(() => {
|
|
229
229
|
if (localIdValue == null) {
|
|
230
230
|
if (inputValue != null) setInputValue(null);
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (state.current.idLoaded) {
|
|
235
|
+
state.current.idLoaded = false;
|
|
236
|
+
state.current.idSet = false;
|
|
234
237
|
}
|
|
235
238
|
}, [localIdValue]);
|
|
236
239
|
|
|
237
240
|
React.useEffect(() => {
|
|
238
241
|
if (localIdValue != null && (localIdValue as any) !== "") {
|
|
239
|
-
if (state.idLoaded) {
|
|
242
|
+
if (state.current.idLoaded) {
|
|
240
243
|
// Set default
|
|
241
|
-
if (!state.idSet && states.options.length > 0) {
|
|
244
|
+
if (!state.current.idSet && states.options.length > 0) {
|
|
242
245
|
const item = states.options.find((o) => o[idField] === localIdValue);
|
|
243
246
|
if (item) {
|
|
244
247
|
stateUpdate({
|
|
245
248
|
value: states.options[0]
|
|
246
249
|
});
|
|
247
|
-
state.idSet = true;
|
|
250
|
+
state.current.idSet = true;
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
253
|
} else {
|
|
251
254
|
// Load id data
|
|
252
255
|
loadDataDirect(undefined, localIdValue);
|
|
253
|
-
state.idLoaded = true;
|
|
256
|
+
state.current.idLoaded = true;
|
|
254
257
|
}
|
|
255
258
|
}
|
|
256
|
-
}, [
|
|
259
|
+
}, [localIdValue, states.options]);
|
|
257
260
|
|
|
258
261
|
React.useEffect(() => {
|
|
262
|
+
state.current.isMounted = true;
|
|
259
263
|
return () => {
|
|
260
|
-
|
|
264
|
+
state.current.isMounted = false;
|
|
261
265
|
delayed.clear();
|
|
262
266
|
};
|
|
263
267
|
}, []);
|
|
@@ -271,7 +275,9 @@ export function Tiplist<
|
|
|
271
275
|
type="text"
|
|
272
276
|
style={{ display: "none" }}
|
|
273
277
|
name={name}
|
|
274
|
-
value={`${
|
|
278
|
+
value={`${
|
|
279
|
+
inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")
|
|
280
|
+
}`}
|
|
275
281
|
readOnly
|
|
276
282
|
onChange={inputOnChange}
|
|
277
283
|
/>
|
package/src/TiplistPro.tsx
CHANGED
|
@@ -152,12 +152,12 @@ export function TiplistPro<T extends ListType2 = ListType2>(
|
|
|
152
152
|
[states.value]
|
|
153
153
|
);
|
|
154
154
|
|
|
155
|
-
//
|
|
156
|
-
const
|
|
157
|
-
idLoaded
|
|
158
|
-
idSet
|
|
159
|
-
|
|
160
|
-
|
|
155
|
+
// Ref
|
|
156
|
+
const state = React.useRef({
|
|
157
|
+
idLoaded: false,
|
|
158
|
+
idSet: false,
|
|
159
|
+
isMounted: false
|
|
160
|
+
});
|
|
161
161
|
|
|
162
162
|
// Change handler
|
|
163
163
|
const changeHandle = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -199,7 +199,7 @@ export function TiplistPro<T extends ListType2 = ListType2>(
|
|
|
199
199
|
|
|
200
200
|
// Load list
|
|
201
201
|
loadData(keyword, id, maxItems).then((options) => {
|
|
202
|
-
if (!
|
|
202
|
+
if (!state.current.isMounted) return;
|
|
203
203
|
|
|
204
204
|
if (options != null && options.length >= maxItems) {
|
|
205
205
|
options.push({ id: -1, name: "n/a" } as T);
|
|
@@ -238,33 +238,37 @@ export function TiplistPro<T extends ListType2 = ListType2>(
|
|
|
238
238
|
React.useEffect(() => {
|
|
239
239
|
if (localIdValue == null) {
|
|
240
240
|
if (inputValue != null) setInputValue(null);
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (state.current.idLoaded) {
|
|
245
|
+
state.current.idLoaded = false;
|
|
246
|
+
state.current.idSet = false;
|
|
244
247
|
}
|
|
245
248
|
}, [localIdValue]);
|
|
246
249
|
|
|
247
250
|
React.useEffect(() => {
|
|
248
251
|
if (localIdValue != null && (localIdValue as any) !== "") {
|
|
249
|
-
if (state.idLoaded) {
|
|
252
|
+
if (state.current.idLoaded) {
|
|
250
253
|
// Set default
|
|
251
|
-
if (!state.idSet && states.options.length > 0) {
|
|
254
|
+
if (!state.current.idSet && states.options.length > 0) {
|
|
252
255
|
stateUpdate({
|
|
253
256
|
value: states.options.find((o) => o.id === localIdValue)
|
|
254
257
|
});
|
|
255
|
-
state.idSet = true;
|
|
258
|
+
state.current.idSet = true;
|
|
256
259
|
}
|
|
257
260
|
} else {
|
|
258
261
|
// Load id data
|
|
259
262
|
loadDataDirect(undefined, localIdValue);
|
|
260
|
-
state.idLoaded = true;
|
|
263
|
+
state.current.idLoaded = true;
|
|
261
264
|
}
|
|
262
265
|
}
|
|
263
|
-
}, [
|
|
266
|
+
}, [localIdValue, states.options]);
|
|
264
267
|
|
|
265
268
|
React.useEffect(() => {
|
|
269
|
+
state.current.isMounted = true;
|
|
266
270
|
return () => {
|
|
267
|
-
|
|
271
|
+
state.current.isMounted = false;
|
|
268
272
|
delayed.clear();
|
|
269
273
|
};
|
|
270
274
|
}, []);
|
|
@@ -278,7 +282,7 @@ export function TiplistPro<T extends ListType2 = ListType2>(
|
|
|
278
282
|
type="text"
|
|
279
283
|
style={{ display: "none" }}
|
|
280
284
|
name={name}
|
|
281
|
-
value={inputValue ?? localIdValue ?? ""}
|
|
285
|
+
value={inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}
|
|
282
286
|
readOnly
|
|
283
287
|
onChange={inputOnChange}
|
|
284
288
|
/>
|
package/src/app/IServiceUser.ts
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
|
-
import { IActionResult, IUser } from
|
|
1
|
+
import { IActionResult, IUser } from "@etsoo/appscript";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Service user interface
|
|
5
5
|
*/
|
|
6
6
|
export interface IServiceUser extends IUser {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Service device id
|
|
9
|
+
*/
|
|
10
|
+
serviceDeviceId: string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Service passphrase encrypted
|
|
14
|
+
*/
|
|
15
|
+
servicePassphrase: string;
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* Service user login result
|
|
15
20
|
*/
|
|
16
21
|
export type ServiceLoginResult<U extends IServiceUser = IServiceUser> =
|
|
17
|
-
|
|
22
|
+
IActionResult<U>;
|
package/src/app/ServiceApp.ts
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from
|
|
11
|
-
import { CoreConstants } from
|
|
12
|
-
import { DomUtils } from
|
|
13
|
-
import { IServiceApp } from
|
|
14
|
-
import { IServiceAppSettings } from
|
|
15
|
-
import { IServicePageData } from
|
|
16
|
-
import { IServiceUser, ServiceLoginResult } from
|
|
17
|
-
import { ISmartERPUser } from
|
|
18
|
-
import { ReactApp } from
|
|
2
|
+
BridgeUtils,
|
|
3
|
+
createClient,
|
|
4
|
+
IActionResult,
|
|
5
|
+
IApi,
|
|
6
|
+
IApiPayload,
|
|
7
|
+
RefreshTokenProps,
|
|
8
|
+
RefreshTokenResult,
|
|
9
|
+
RefreshTokenRQ
|
|
10
|
+
} from "@etsoo/appscript";
|
|
11
|
+
import { CoreConstants } from "@etsoo/react";
|
|
12
|
+
import { DomUtils } from "@etsoo/shared";
|
|
13
|
+
import { IServiceApp } from "./IServiceApp";
|
|
14
|
+
import { IServiceAppSettings } from "./IServiceAppSettings";
|
|
15
|
+
import { IServicePageData } from "./IServicePage";
|
|
16
|
+
import { IServiceUser, ServiceLoginResult } from "./IServiceUser";
|
|
17
|
+
import { ISmartERPUser } from "./ISmartERPUser";
|
|
18
|
+
import { ReactApp } from "./ReactApp";
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Core Service App
|
|
@@ -24,332 +24,321 @@ import { ReactApp } from './ReactApp';
|
|
|
24
24
|
* Use the new acess token and refresh token to login
|
|
25
25
|
*/
|
|
26
26
|
export class ServiceApp<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
U extends IServiceUser = IServiceUser,
|
|
28
|
+
P extends IServicePageData = IServicePageData,
|
|
29
|
+
S extends IServiceAppSettings = IServiceAppSettings
|
|
30
|
+
>
|
|
31
|
+
extends ReactApp<S, ISmartERPUser, P>
|
|
32
|
+
implements IServiceApp
|
|
33
33
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Service API
|
|
36
|
+
*/
|
|
37
|
+
readonly serviceApi: IApi;
|
|
38
|
+
|
|
39
|
+
private _serviceUser?: U;
|
|
40
|
+
/**
|
|
41
|
+
* Service user
|
|
42
|
+
*/
|
|
43
|
+
get serviceUser() {
|
|
44
|
+
return this._serviceUser;
|
|
45
|
+
}
|
|
46
|
+
protected set serviceUser(value: U | undefined) {
|
|
47
|
+
this._serviceUser = value;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Service passphrase
|
|
52
|
+
*/
|
|
53
|
+
protected servicePassphrase: string = "";
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Constructor
|
|
57
|
+
* @param settings Settings
|
|
58
|
+
* @param name Application name
|
|
59
|
+
*/
|
|
60
|
+
constructor(settings: S, name: string) {
|
|
61
|
+
super(settings, name);
|
|
62
|
+
|
|
63
|
+
// Check
|
|
64
|
+
if (settings.serviceId == null || settings.serviceEndpoint == null) {
|
|
65
|
+
throw new Error("No service settings");
|
|
48
66
|
}
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
protected servicePassphrase: string = '';
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Constructor
|
|
57
|
-
* @param settings Settings
|
|
58
|
-
* @param name Application name
|
|
59
|
-
*/
|
|
60
|
-
constructor(settings: S, name: string) {
|
|
61
|
-
super(settings, name);
|
|
62
|
-
|
|
63
|
-
// Check
|
|
64
|
-
if (settings.serviceId == null || settings.serviceEndpoint == null) {
|
|
65
|
-
throw new Error('No service settings');
|
|
66
|
-
}
|
|
68
|
+
// Service API
|
|
69
|
+
const api = createClient();
|
|
70
|
+
this.setApi(api);
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.setApi(api);
|
|
72
|
+
// Fix the baseUrl done by setupApi (Default is the settings.endpoint)
|
|
73
|
+
api.baseUrl = settings.serviceEndpoint;
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
this.serviceApi = api;
|
|
76
|
+
}
|
|
74
77
|
|
|
75
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Load SmartERP core
|
|
80
|
+
*/
|
|
81
|
+
loadSmartERP() {
|
|
82
|
+
if (BridgeUtils.host == null) {
|
|
83
|
+
window.location.href = this.settings.webUrl;
|
|
84
|
+
} else {
|
|
85
|
+
BridgeUtils.host.loadApp("core");
|
|
76
86
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Go to the login page
|
|
91
|
+
* @param tryLogin Try to login again
|
|
92
|
+
*/
|
|
93
|
+
override toLoginPage(tryLogin?: boolean) {
|
|
94
|
+
const parameters = `?serviceId=${this.settings.serviceId}&${
|
|
95
|
+
DomUtils.CultureField
|
|
96
|
+
}=${this.culture}${tryLogin ? "" : "&tryLogin=false"}`;
|
|
97
|
+
|
|
98
|
+
if (BridgeUtils.host == null) {
|
|
99
|
+
const coreUrl = this.settings.webUrl;
|
|
100
|
+
window.location.href = coreUrl + parameters;
|
|
101
|
+
} else {
|
|
102
|
+
BridgeUtils.host.loadApp("core", parameters);
|
|
87
103
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Refresh token
|
|
108
|
+
* @param props Props
|
|
109
|
+
*/
|
|
110
|
+
override async refreshToken<D extends object = RefreshTokenRQ>(
|
|
111
|
+
props?: RefreshTokenProps<D>
|
|
112
|
+
) {
|
|
113
|
+
// Destruct
|
|
114
|
+
const {
|
|
115
|
+
callback,
|
|
116
|
+
data,
|
|
117
|
+
relogin = false,
|
|
118
|
+
showLoading = false
|
|
119
|
+
} = props ?? {};
|
|
120
|
+
|
|
121
|
+
// Token
|
|
122
|
+
const token = this.getCacheToken();
|
|
123
|
+
if (token == null || token === "") {
|
|
124
|
+
if (callback) callback(false);
|
|
125
|
+
return false;
|
|
104
126
|
}
|
|
105
127
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
// Reqest data
|
|
129
|
+
// Merge additional data passed
|
|
130
|
+
const rq: RefreshTokenRQ = {
|
|
131
|
+
deviceId: this.deviceId,
|
|
132
|
+
timezone: this.getTimeZone(),
|
|
133
|
+
...data
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Login result type
|
|
137
|
+
type LoginResult = IActionResult<U>;
|
|
138
|
+
|
|
139
|
+
// Payload
|
|
140
|
+
const payload: IApiPayload<LoginResult, any> = {
|
|
141
|
+
showLoading,
|
|
142
|
+
config: { headers: { [CoreConstants.TokenHeaderRefresh]: token } },
|
|
143
|
+
onError: (error) => {
|
|
144
|
+
if (callback) callback(error);
|
|
145
|
+
|
|
146
|
+
// Prevent further processing
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Success callback
|
|
152
|
+
const success = async (
|
|
153
|
+
result: LoginResult,
|
|
154
|
+
failCallback?: (result: RefreshTokenResult) => void
|
|
155
|
+
) => {
|
|
156
|
+
// Token
|
|
157
|
+
const refreshToken = this.getResponseToken(payload.response);
|
|
158
|
+
if (refreshToken == null || result.data == null) {
|
|
159
|
+
if (failCallback) failCallback(this.get("noData")!);
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// User data
|
|
164
|
+
const userData = result.data;
|
|
165
|
+
|
|
166
|
+
// Use core system access token to service api to exchange service access token
|
|
167
|
+
const serviceResult = await this.serviceApi.put<ServiceLoginResult<U>>(
|
|
168
|
+
"Auth/ExchangeToken",
|
|
169
|
+
{
|
|
170
|
+
token: this.encryptEnhanced(
|
|
171
|
+
userData.token,
|
|
172
|
+
this.settings.serviceId.toString()
|
|
173
|
+
)
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
showLoading,
|
|
177
|
+
onError: (error) => {
|
|
178
|
+
if (failCallback) failCallback(error);
|
|
179
|
+
|
|
180
|
+
// Prevent further processing
|
|
125
181
|
return false;
|
|
182
|
+
}
|
|
126
183
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
>(
|
|
170
|
-
'Auth/ExchangeToken',
|
|
171
|
-
{
|
|
172
|
-
token: this.encryptEnhanced(
|
|
173
|
-
userData.token,
|
|
174
|
-
this.settings.serviceId.toString()
|
|
175
|
-
)
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
showLoading,
|
|
179
|
-
onError: (error) => {
|
|
180
|
-
if (failCallback) failCallback(error);
|
|
181
|
-
|
|
182
|
-
// Prevent further processing
|
|
183
|
-
return false;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
if (serviceResult == null) return false;
|
|
189
|
-
|
|
190
|
-
if (!serviceResult.ok) {
|
|
191
|
-
if (failCallback) failCallback(serviceResult);
|
|
192
|
-
return false;
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
if (serviceResult == null) return false;
|
|
187
|
+
|
|
188
|
+
if (!serviceResult.ok) {
|
|
189
|
+
if (failCallback) failCallback(serviceResult);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (serviceResult.data == null) {
|
|
194
|
+
if (failCallback) failCallback(this.get("noData")!);
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Login
|
|
199
|
+
this.userLoginEx(userData, refreshToken, serviceResult.data);
|
|
200
|
+
|
|
201
|
+
// Success callback
|
|
202
|
+
if (failCallback) failCallback(true);
|
|
203
|
+
|
|
204
|
+
return true;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
// Call API
|
|
208
|
+
const result = await this.api.put<LoginResult>(
|
|
209
|
+
"Auth/RefreshToken",
|
|
210
|
+
rq,
|
|
211
|
+
payload
|
|
212
|
+
);
|
|
213
|
+
if (result == null) return false;
|
|
214
|
+
|
|
215
|
+
if (!result.ok) {
|
|
216
|
+
if (result.type === "TokenExpired" && relogin) {
|
|
217
|
+
// Try login
|
|
218
|
+
// Dialog to receive password
|
|
219
|
+
var labels = this.getLabels("reloginTip", "login");
|
|
220
|
+
this.notifier.prompt(
|
|
221
|
+
labels.reloginTip,
|
|
222
|
+
async (pwd) => {
|
|
223
|
+
if (pwd == null) {
|
|
224
|
+
this.toLoginPage();
|
|
225
|
+
return;
|
|
193
226
|
}
|
|
194
227
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
return false;
|
|
198
|
-
}
|
|
228
|
+
// Set password for the action
|
|
229
|
+
rq.pwd = this.encrypt(this.hash(pwd));
|
|
199
230
|
|
|
200
|
-
//
|
|
201
|
-
this.
|
|
231
|
+
// Submit again
|
|
232
|
+
const result = await this.api.put<LoginResult>(
|
|
233
|
+
"Auth/RefreshToken",
|
|
234
|
+
rq,
|
|
235
|
+
payload
|
|
236
|
+
);
|
|
202
237
|
|
|
203
|
-
|
|
204
|
-
if (failCallback) failCallback(true);
|
|
238
|
+
if (result == null) return;
|
|
205
239
|
|
|
206
|
-
|
|
207
|
-
|
|
240
|
+
if (result.ok) {
|
|
241
|
+
await success(result, (loginResult: RefreshTokenResult) => {
|
|
242
|
+
if (loginResult === true) {
|
|
243
|
+
if (callback) callback(true);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
208
246
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
payload
|
|
214
|
-
);
|
|
215
|
-
if (result == null) return false;
|
|
216
|
-
|
|
217
|
-
if (!result.ok) {
|
|
218
|
-
if (result.type === 'TokenExpired' && relogin) {
|
|
219
|
-
// Try login
|
|
220
|
-
// Dialog to receive password
|
|
221
|
-
var labels = this.getLabels('reloginTip', 'login');
|
|
222
|
-
this.notifier.prompt(
|
|
223
|
-
labels.reloginTip,
|
|
224
|
-
async (pwd) => {
|
|
225
|
-
if (pwd == null) {
|
|
226
|
-
this.toLoginPage();
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// Set password for the action
|
|
231
|
-
rq.pwd = this.encrypt(this.hash(pwd));
|
|
232
|
-
|
|
233
|
-
// Submit again
|
|
234
|
-
const result = await this.api.put<LoginResult>(
|
|
235
|
-
'Auth/RefreshToken',
|
|
236
|
-
rq,
|
|
237
|
-
payload
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
if (result == null) return;
|
|
241
|
-
|
|
242
|
-
if (result.ok) {
|
|
243
|
-
await success(
|
|
244
|
-
result,
|
|
245
|
-
(loginResult: RefreshTokenResult) => {
|
|
246
|
-
if (loginResult === true) {
|
|
247
|
-
if (callback) callback(true);
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
const message =
|
|
252
|
-
this.formatRefreshTokenResult(
|
|
253
|
-
loginResult
|
|
254
|
-
);
|
|
255
|
-
if (message) this.notifier.alert(message);
|
|
256
|
-
}
|
|
257
|
-
);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Popup message
|
|
262
|
-
this.alertResult(result);
|
|
263
|
-
return false;
|
|
264
|
-
},
|
|
265
|
-
labels.login,
|
|
266
|
-
{ type: 'password' }
|
|
267
|
-
);
|
|
268
|
-
|
|
269
|
-
// Fake truth to avoid reloading
|
|
270
|
-
return true;
|
|
247
|
+
const message = this.formatRefreshTokenResult(loginResult);
|
|
248
|
+
if (message) this.notifier.alert(message);
|
|
249
|
+
});
|
|
250
|
+
return;
|
|
271
251
|
}
|
|
272
252
|
|
|
273
|
-
|
|
253
|
+
// Popup message
|
|
254
|
+
this.alertResult(result);
|
|
274
255
|
return false;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Service decrypt message
|
|
282
|
-
* @param messageEncrypted Encrypted message
|
|
283
|
-
* @param passphrase Secret passphrase
|
|
284
|
-
* @returns Pure text
|
|
285
|
-
*/
|
|
286
|
-
serviceDecrypt(messageEncrypted: string, passphrase?: string) {
|
|
287
|
-
return this.decrypt(
|
|
288
|
-
messageEncrypted,
|
|
289
|
-
passphrase ?? this.servicePassphrase
|
|
256
|
+
},
|
|
257
|
+
labels.login,
|
|
258
|
+
{ type: "password" }
|
|
290
259
|
);
|
|
291
|
-
}
|
|
292
260
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
* @param passphrase Secret passphrase
|
|
297
|
-
* @param iterations Iterations, 1000 times, 1 - 99
|
|
298
|
-
* @returns Result
|
|
299
|
-
*/
|
|
300
|
-
serviceEncrypt(message: string, passphrase?: string, iterations?: number) {
|
|
301
|
-
return this.encrypt(
|
|
302
|
-
message,
|
|
303
|
-
passphrase ?? this.servicePassphrase,
|
|
304
|
-
iterations
|
|
305
|
-
);
|
|
306
|
-
}
|
|
261
|
+
// Fake truth to avoid reloading
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
307
264
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
* @param data Additional data
|
|
311
|
-
* @param showLoading Show loading bar or not
|
|
312
|
-
* @returns Result
|
|
313
|
-
*/
|
|
314
|
-
override async tryLogin<D extends object = {}>(
|
|
315
|
-
data?: D,
|
|
316
|
-
showLoading?: boolean
|
|
317
|
-
) {
|
|
318
|
-
// Reset user state
|
|
319
|
-
const result = await super.tryLogin(data, showLoading);
|
|
320
|
-
if (!result) return false;
|
|
321
|
-
|
|
322
|
-
// Refresh token
|
|
323
|
-
return await this.refreshToken({
|
|
324
|
-
callback: (result) => this.doRefreshTokenResult(result),
|
|
325
|
-
data,
|
|
326
|
-
showLoading,
|
|
327
|
-
relogin: true
|
|
328
|
-
});
|
|
265
|
+
if (callback) callback(result);
|
|
266
|
+
return false;
|
|
329
267
|
}
|
|
330
268
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
269
|
+
return await success(result, callback);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Service decrypt message
|
|
274
|
+
* @param messageEncrypted Encrypted message
|
|
275
|
+
* @param passphrase Secret passphrase
|
|
276
|
+
* @returns Pure text
|
|
277
|
+
*/
|
|
278
|
+
serviceDecrypt(messageEncrypted: string, passphrase?: string) {
|
|
279
|
+
return this.decrypt(messageEncrypted, passphrase ?? this.servicePassphrase);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Service encrypt message
|
|
284
|
+
* @param message Message
|
|
285
|
+
* @param passphrase Secret passphrase
|
|
286
|
+
* @param iterations Iterations, 1000 times, 1 - 99
|
|
287
|
+
* @returns Result
|
|
288
|
+
*/
|
|
289
|
+
serviceEncrypt(message: string, passphrase?: string, iterations?: number) {
|
|
290
|
+
return this.encrypt(
|
|
291
|
+
message,
|
|
292
|
+
passphrase ?? this.servicePassphrase,
|
|
293
|
+
iterations
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Try login
|
|
299
|
+
* @param data Additional data
|
|
300
|
+
* @param showLoading Show loading bar or not
|
|
301
|
+
* @returns Result
|
|
302
|
+
*/
|
|
303
|
+
override async tryLogin<D extends object = {}>(
|
|
304
|
+
data?: D,
|
|
305
|
+
showLoading?: boolean
|
|
306
|
+
) {
|
|
307
|
+
// Reset user state
|
|
308
|
+
const result = await super.tryLogin(data, showLoading);
|
|
309
|
+
if (!result) return false;
|
|
310
|
+
|
|
311
|
+
// Refresh token
|
|
312
|
+
return await this.refreshToken({
|
|
313
|
+
callback: (result) => this.doRefreshTokenResult(result),
|
|
314
|
+
data,
|
|
315
|
+
showLoading,
|
|
316
|
+
relogin: true
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* User login extended
|
|
322
|
+
* @param user Core system user
|
|
323
|
+
* @param refreshToken Refresh token
|
|
324
|
+
* @param serviceUser Service user
|
|
325
|
+
*/
|
|
326
|
+
userLoginEx(user: ISmartERPUser, refreshToken: string, serviceUser: U) {
|
|
327
|
+
// Service user login
|
|
328
|
+
this.servicePassphrase =
|
|
329
|
+
this.decrypt(
|
|
330
|
+
serviceUser.servicePassphrase,
|
|
331
|
+
this.settings.serviceId.toString()
|
|
332
|
+
) ?? "";
|
|
333
|
+
|
|
334
|
+
// Service user
|
|
335
|
+
this.serviceUser = serviceUser;
|
|
336
|
+
|
|
337
|
+
// Service API token
|
|
338
|
+
this.serviceApi.authorize(this.settings.authScheme, serviceUser.token);
|
|
339
|
+
|
|
340
|
+
// Keep = true, means service could hold the refresh token for long access
|
|
341
|
+
// Trigger Context change and serviceUser is ready then
|
|
342
|
+
super.userLogin(user, refreshToken, true);
|
|
343
|
+
}
|
|
355
344
|
}
|