@etsoo/materialui 1.4.60 → 1.4.62
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/ButtonPopover.d.ts +29 -0
- package/lib/ButtonPopover.js +57 -0
- package/lib/NotifierMU.js +3 -3
- package/lib/app/ReactApp.js +2 -1
- package/lib/app/ServiceApp.d.ts +1 -0
- package/lib/app/ServiceApp.js +30 -25
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +4 -4
- package/src/ButtonPopover.tsx +102 -0
- package/src/NotifierMU.tsx +18 -3
- package/src/app/ReactApp.ts +2 -1
- package/src/app/ServiceApp.ts +39 -29
- package/src/index.ts +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Button popover props
|
|
4
|
+
*/
|
|
5
|
+
export type ButtonPopoverProps<T> = {
|
|
6
|
+
/**
|
|
7
|
+
* Button component
|
|
8
|
+
* @param callback Button click callback
|
|
9
|
+
* @returns Layout
|
|
10
|
+
*/
|
|
11
|
+
button: (callback: (handler: HTMLElement | null) => void) => React.ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* Children component
|
|
14
|
+
* @param data Data
|
|
15
|
+
* @returns Layout
|
|
16
|
+
*/
|
|
17
|
+
children: (data: T | null) => React.ReactNode;
|
|
18
|
+
/**
|
|
19
|
+
* Load data
|
|
20
|
+
* @returns Data promise
|
|
21
|
+
*/
|
|
22
|
+
loadData?: () => Promise<T | undefined>;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Button popover component
|
|
26
|
+
* @param props Props
|
|
27
|
+
* @returns Component
|
|
28
|
+
*/
|
|
29
|
+
export declare function ButtonPopover<T>(props: ButtonPopoverProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Popover } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Button popover component
|
|
6
|
+
* @param props Props
|
|
7
|
+
* @returns Component
|
|
8
|
+
*/
|
|
9
|
+
export function ButtonPopover(props) {
|
|
10
|
+
// Destruct
|
|
11
|
+
const { button, children, loadData } = props;
|
|
12
|
+
// States
|
|
13
|
+
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
14
|
+
const [data, setData] = React.useState(null);
|
|
15
|
+
const isLoadded = React.useRef(false);
|
|
16
|
+
const open = Boolean(anchorEl);
|
|
17
|
+
// Load data
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (loadData && (!isLoadded.current || open)) {
|
|
20
|
+
// First time or when open
|
|
21
|
+
loadData().then((d) => {
|
|
22
|
+
if (d == null)
|
|
23
|
+
return;
|
|
24
|
+
setData(d);
|
|
25
|
+
isLoadded.current = true;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}, [loadData, open]);
|
|
29
|
+
// Children
|
|
30
|
+
const currentChildren = React.useMemo(() => children(data), [children, data]);
|
|
31
|
+
const handleClose = () => {
|
|
32
|
+
setAnchorEl(null);
|
|
33
|
+
};
|
|
34
|
+
// Layout
|
|
35
|
+
return (_jsxs(React.Fragment, { children: [button((handler) => setAnchorEl(handler)), _jsx(Popover, { anchorEl: anchorEl, open: open, onClose: handleClose, onClick: handleClose, transformOrigin: { horizontal: "right", vertical: "top" }, anchorOrigin: { horizontal: "right", vertical: "bottom" }, slotProps: {
|
|
36
|
+
paper: {
|
|
37
|
+
elevation: 0,
|
|
38
|
+
sx: {
|
|
39
|
+
overflow: "visible",
|
|
40
|
+
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
|
41
|
+
mt: 1,
|
|
42
|
+
"&::before": {
|
|
43
|
+
content: '""',
|
|
44
|
+
display: "block",
|
|
45
|
+
position: "absolute",
|
|
46
|
+
top: 0,
|
|
47
|
+
right: 14,
|
|
48
|
+
width: 10,
|
|
49
|
+
height: 10,
|
|
50
|
+
bgcolor: "background.paper",
|
|
51
|
+
transform: "translateY(-50%) rotate(45deg)",
|
|
52
|
+
zIndex: 0
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, children: currentChildren })] }));
|
|
57
|
+
}
|
package/lib/NotifierMU.js
CHANGED
|
@@ -63,7 +63,7 @@ export class NotificationMU extends NotificationReact {
|
|
|
63
63
|
await this.returnValue(undefined);
|
|
64
64
|
return true;
|
|
65
65
|
};
|
|
66
|
-
return (_jsxs(Dialog, { open: this.open, PaperComponent: draggable ? DraggablePaperComponent : undefined, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen, ...options, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: "dialog-title", children: [icon, _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), inputs] }), _jsx(DialogActions, { children: buttons
|
|
66
|
+
return (_jsxs(Dialog, { open: this.open, PaperComponent: draggable ? DraggablePaperComponent : undefined, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen, ...options, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: draggable ? "dialog-title draggable-dialog-title" : "dialog-title", children: [icon, _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), inputs] }), _jsx(DialogActions, { children: buttons
|
|
67
67
|
? buttons(this, callback)
|
|
68
68
|
: primaryButton && (_jsx(LoadingButton, { ...setupProps, onClick: callback, autoFocus: true, ...primaryButtonProps, children: okLabel })) })] }, this.id));
|
|
69
69
|
}
|
|
@@ -78,7 +78,7 @@ export class NotificationMU extends NotificationReact {
|
|
|
78
78
|
await this.returnValue(value);
|
|
79
79
|
return true;
|
|
80
80
|
};
|
|
81
|
-
return (_jsxs(Dialog, { open: this.open, PaperComponent: draggable ? DraggablePaperComponent : undefined, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen, ...options, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: "dialog-title", children: [_jsx(Help, { color: "action" }), _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), inputs] }), _jsx(DialogActions, { children: buttons ? (buttons(this, callback)) : (_jsxs(React.Fragment, { children: [cancelButton && (_jsx(LoadingButton, { color: "secondary", onClick: async (event) => await callback(event, false), children: cancelLabel })), primaryButton && (_jsx(LoadingButton, { color: "primary", onClick: async (event) => await callback(event, true), autoFocus: true, ...primaryButtonProps, children: okLabel }))] })) })] }, this.id));
|
|
81
|
+
return (_jsxs(Dialog, { open: this.open, PaperComponent: draggable ? DraggablePaperComponent : undefined, className: className, fullWidth: fullWidth, maxWidth: maxWidth, fullScreen: fullScreen, ...options, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: draggable ? "dialog-title draggable-dialog-title" : "dialog-title", children: [_jsx(Help, { color: "action" }), _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), inputs] }), _jsx(DialogActions, { children: buttons ? (buttons(this, callback)) : (_jsxs(React.Fragment, { children: [cancelButton && (_jsx(LoadingButton, { color: "secondary", onClick: async (event) => await callback(event, false), children: cancelLabel })), primaryButton && (_jsx(LoadingButton, { color: "primary", onClick: async (event) => await callback(event, true), autoFocus: true, ...primaryButtonProps, children: okLabel }))] })) })] }, this.id));
|
|
82
82
|
}
|
|
83
83
|
createMessageColor() {
|
|
84
84
|
if (this.type === NotificationMessageType.Danger)
|
|
@@ -177,7 +177,7 @@ export class NotificationMU extends NotificationReact {
|
|
|
177
177
|
event.preventDefault();
|
|
178
178
|
event.currentTarget.elements.namedItem("okButton")?.click();
|
|
179
179
|
return false;
|
|
180
|
-
}, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: "dialog-title", children: [_jsx(Info, { color: "primary" }), _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), localInputs, _jsx(Typography, { variant: "caption", display: "block", ref: errorRef, color: "error" })] }), _jsx(DialogActions, { children: buttons ? (buttons(this, handleSubmit)) : (_jsxs(React.Fragment, { children: [cancelButton && (_jsx(Button, { color: "secondary", onClick: () => {
|
|
180
|
+
}, children: [_jsxs(IconDialogTitle, { draggable: draggable, className: draggable ? "dialog-title draggable-dialog-title" : "dialog-title", children: [_jsx(Info, { color: "primary" }), _jsx("span", { className: "dialogTitle", children: title }), closable && (_jsx(IconButton, { className: "MuiDialogContent-root-close-button", size: "small", onClick: () => this.returnValue("CLOSE"), children: _jsx(CloseIcon, {}) }))] }), _jsxs(DialogContent, { children: [typeof this.content === "string" ? (_jsx(DialogContentText, { children: this.content })) : (this.content), localInputs, _jsx(Typography, { variant: "caption", display: "block", ref: errorRef, color: "error" })] }), _jsx(DialogActions, { children: buttons ? (buttons(this, handleSubmit)) : (_jsxs(React.Fragment, { children: [cancelButton && (_jsx(Button, { color: "secondary", onClick: () => {
|
|
181
181
|
if (this.onReturn)
|
|
182
182
|
this.onReturn(undefined);
|
|
183
183
|
this.dismiss();
|
package/lib/app/ReactApp.js
CHANGED
|
@@ -233,7 +233,8 @@ export class ReactApp extends CoreApp {
|
|
|
233
233
|
*/
|
|
234
234
|
async tryLogin(data) {
|
|
235
235
|
// Destruct
|
|
236
|
-
const { onFailure = () => {
|
|
236
|
+
const { onFailure = (type) => {
|
|
237
|
+
console.log(`Try login failed: ${type}.`);
|
|
237
238
|
this.toLoginPage(rest);
|
|
238
239
|
}, onSuccess, ...rest } = data ?? {};
|
|
239
240
|
// Check status
|
package/lib/app/ServiceApp.d.ts
CHANGED
|
@@ -67,6 +67,7 @@ export declare class ServiceApp<U extends IServiceUser = IServiceUser, P extends
|
|
|
67
67
|
* @param payload Payload
|
|
68
68
|
*/
|
|
69
69
|
switchOrg(organizationId: number, fromOrganizationId?: number, payload?: IApiPayload<IActionResult<U & ServiceUserToken>>): Promise<IActionResult<U & ServiceUserToken> | undefined>;
|
|
70
|
+
protected refreshTokenSucceed(user: U, token: string, callback?: (result?: boolean | IActionResult) => boolean | void): Promise<void>;
|
|
70
71
|
/**
|
|
71
72
|
* Try login
|
|
72
73
|
* @param params Login parameters
|
package/lib/app/ServiceApp.js
CHANGED
|
@@ -180,6 +180,35 @@ export class ServiceApp extends ReactApp {
|
|
|
180
180
|
this.userLoginEx(user, core, true);
|
|
181
181
|
return result;
|
|
182
182
|
}
|
|
183
|
+
async refreshTokenSucceed(user, token, callback) {
|
|
184
|
+
// Check core system token
|
|
185
|
+
const coreToken = this.storage.getData(coreTokenKey);
|
|
186
|
+
if (!coreToken) {
|
|
187
|
+
callback?.({ ok: false, type: "noData", title: "Core token is blank" });
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const coreTokenDecrypted = this.decrypt(coreToken);
|
|
191
|
+
if (!coreTokenDecrypted) {
|
|
192
|
+
callback?.({
|
|
193
|
+
ok: false,
|
|
194
|
+
type: "noData",
|
|
195
|
+
title: "Core token decrypted is blank"
|
|
196
|
+
});
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
// Call the core system API refresh token
|
|
200
|
+
const data = await this.apiRefreshTokenData(this.coreApi, {
|
|
201
|
+
token: coreTokenDecrypted,
|
|
202
|
+
appId: this.settings.appId
|
|
203
|
+
});
|
|
204
|
+
if (data == null)
|
|
205
|
+
return;
|
|
206
|
+
// Cache the core system refresh token
|
|
207
|
+
// Follow similar logic in userLoginEx
|
|
208
|
+
this.saveCoreToken(data);
|
|
209
|
+
// Call the super
|
|
210
|
+
await super.refreshTokenSucceed(user, token, callback);
|
|
211
|
+
}
|
|
183
212
|
/**
|
|
184
213
|
* Try login
|
|
185
214
|
* @param params Login parameters
|
|
@@ -187,37 +216,13 @@ export class ServiceApp extends ReactApp {
|
|
|
187
216
|
async tryLogin(params) {
|
|
188
217
|
// Destruct
|
|
189
218
|
params ??= {};
|
|
190
|
-
let { onFailure,
|
|
219
|
+
let { onFailure, ...rest } = params;
|
|
191
220
|
if (onFailure == null) {
|
|
192
221
|
onFailure = params.onFailure = (type) => {
|
|
193
222
|
console.log(`Try login failed: ${type}.`);
|
|
194
223
|
this.toLoginPage(rest);
|
|
195
224
|
};
|
|
196
225
|
}
|
|
197
|
-
// Check core system token
|
|
198
|
-
const coreToken = this.storage.getData(coreTokenKey);
|
|
199
|
-
if (!coreToken) {
|
|
200
|
-
onFailure("ServiceAppCoreTokenNoData");
|
|
201
|
-
return false;
|
|
202
|
-
}
|
|
203
|
-
const coreTokenDecrypted = this.decrypt(coreToken);
|
|
204
|
-
if (!coreTokenDecrypted) {
|
|
205
|
-
onFailure("ServiceAppCoreTokenNoDecryptedData");
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
params.onSuccess = () => {
|
|
209
|
-
// Call the core system API refresh token
|
|
210
|
-
this.apiRefreshTokenData(this.coreApi, {
|
|
211
|
-
token: coreTokenDecrypted,
|
|
212
|
-
appId: this.settings.appId
|
|
213
|
-
}).then((data) => {
|
|
214
|
-
if (data == null)
|
|
215
|
-
return;
|
|
216
|
-
// Cache the core system refresh token
|
|
217
|
-
this.saveCoreToken(data);
|
|
218
|
-
onSuccess?.();
|
|
219
|
-
});
|
|
220
|
-
};
|
|
221
226
|
return await super.tryLogin(params);
|
|
222
227
|
}
|
|
223
228
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from "./AutocompleteExtendedProps";
|
|
|
38
38
|
export * from "./BackButton";
|
|
39
39
|
export * from "./BridgeCloseButton";
|
|
40
40
|
export * from "./ButtonLink";
|
|
41
|
+
export * from "./ButtonPopover";
|
|
41
42
|
export * from "./ComboBox";
|
|
42
43
|
export * from "./ComboBoxMultiple";
|
|
43
44
|
export * from "./ComboBoxPro";
|
package/lib/index.js
CHANGED
|
@@ -38,6 +38,7 @@ export * from "./AutocompleteExtendedProps";
|
|
|
38
38
|
export * from "./BackButton";
|
|
39
39
|
export * from "./BridgeCloseButton";
|
|
40
40
|
export * from "./ButtonLink";
|
|
41
|
+
export * from "./ButtonPopover";
|
|
41
42
|
export * from "./ComboBox";
|
|
42
43
|
export * from "./ComboBoxMultiple";
|
|
43
44
|
export * from "./ComboBoxPro";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.62",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"@emotion/css": "^11.13.5",
|
|
36
36
|
"@emotion/react": "^11.14.0",
|
|
37
37
|
"@emotion/styled": "^11.14.0",
|
|
38
|
-
"@etsoo/appscript": "^1.5.
|
|
38
|
+
"@etsoo/appscript": "^1.5.87",
|
|
39
39
|
"@etsoo/notificationbase": "^1.1.54",
|
|
40
|
-
"@etsoo/react": "^1.8.
|
|
40
|
+
"@etsoo/react": "^1.8.20",
|
|
41
41
|
"@etsoo/shared": "^1.2.55",
|
|
42
42
|
"@mui/icons-material": "^6.3.1",
|
|
43
43
|
"@mui/material": "^6.3.1",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@types/react-window": "^1.8.8",
|
|
73
73
|
"@vitejs/plugin-react": "^4.3.4",
|
|
74
74
|
"jsdom": "^25.0.1",
|
|
75
|
-
"typescript": "^5.7.
|
|
75
|
+
"typescript": "^5.7.3",
|
|
76
76
|
"vitest": "^2.1.8"
|
|
77
77
|
}
|
|
78
78
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Popover } from "@mui/material";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Button popover props
|
|
6
|
+
*/
|
|
7
|
+
export type ButtonPopoverProps<T> = {
|
|
8
|
+
/**
|
|
9
|
+
* Button component
|
|
10
|
+
* @param callback Button click callback
|
|
11
|
+
* @returns Layout
|
|
12
|
+
*/
|
|
13
|
+
button: (callback: (handler: HTMLElement | null) => void) => React.ReactNode;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Children component
|
|
17
|
+
* @param data Data
|
|
18
|
+
* @returns Layout
|
|
19
|
+
*/
|
|
20
|
+
children: (data: T | null) => React.ReactNode;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Load data
|
|
24
|
+
* @returns Data promise
|
|
25
|
+
*/
|
|
26
|
+
loadData?: () => Promise<T | undefined>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Button popover component
|
|
31
|
+
* @param props Props
|
|
32
|
+
* @returns Component
|
|
33
|
+
*/
|
|
34
|
+
export function ButtonPopover<T>(props: ButtonPopoverProps<T>) {
|
|
35
|
+
// Destruct
|
|
36
|
+
const { button, children, loadData } = props;
|
|
37
|
+
|
|
38
|
+
// States
|
|
39
|
+
const [anchorEl, setAnchorEl] = React.useState<HTMLElement | null>(null);
|
|
40
|
+
const [data, setData] = React.useState<T | null>(null);
|
|
41
|
+
const isLoadded = React.useRef(false);
|
|
42
|
+
|
|
43
|
+
const open = Boolean(anchorEl);
|
|
44
|
+
|
|
45
|
+
// Load data
|
|
46
|
+
React.useEffect(() => {
|
|
47
|
+
if (loadData && (!isLoadded.current || open)) {
|
|
48
|
+
// First time or when open
|
|
49
|
+
loadData().then((d) => {
|
|
50
|
+
if (d == null) return;
|
|
51
|
+
setData(d);
|
|
52
|
+
isLoadded.current = true;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}, [loadData, open]);
|
|
56
|
+
|
|
57
|
+
// Children
|
|
58
|
+
const currentChildren = React.useMemo(() => children(data), [children, data]);
|
|
59
|
+
|
|
60
|
+
const handleClose = () => {
|
|
61
|
+
setAnchorEl(null);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Layout
|
|
65
|
+
return (
|
|
66
|
+
<React.Fragment>
|
|
67
|
+
{button((handler) => setAnchorEl(handler))}
|
|
68
|
+
<Popover
|
|
69
|
+
anchorEl={anchorEl}
|
|
70
|
+
open={open}
|
|
71
|
+
onClose={handleClose}
|
|
72
|
+
onClick={handleClose}
|
|
73
|
+
transformOrigin={{ horizontal: "right", vertical: "top" }}
|
|
74
|
+
anchorOrigin={{ horizontal: "right", vertical: "bottom" }}
|
|
75
|
+
slotProps={{
|
|
76
|
+
paper: {
|
|
77
|
+
elevation: 0,
|
|
78
|
+
sx: {
|
|
79
|
+
overflow: "visible",
|
|
80
|
+
filter: "drop-shadow(0px 2px 8px rgba(0,0,0,0.32))",
|
|
81
|
+
mt: 1,
|
|
82
|
+
"&::before": {
|
|
83
|
+
content: '""',
|
|
84
|
+
display: "block",
|
|
85
|
+
position: "absolute",
|
|
86
|
+
top: 0,
|
|
87
|
+
right: 14,
|
|
88
|
+
width: 10,
|
|
89
|
+
height: 10,
|
|
90
|
+
bgcolor: "background.paper",
|
|
91
|
+
transform: "translateY(-50%) rotate(45deg)",
|
|
92
|
+
zIndex: 0
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}}
|
|
97
|
+
>
|
|
98
|
+
{currentChildren}
|
|
99
|
+
</Popover>
|
|
100
|
+
</React.Fragment>
|
|
101
|
+
);
|
|
102
|
+
}
|
package/src/NotifierMU.tsx
CHANGED
|
@@ -123,7 +123,12 @@ export class NotificationMU extends NotificationReact {
|
|
|
123
123
|
fullScreen={fullScreen}
|
|
124
124
|
{...options}
|
|
125
125
|
>
|
|
126
|
-
<IconDialogTitle
|
|
126
|
+
<IconDialogTitle
|
|
127
|
+
draggable={draggable}
|
|
128
|
+
className={
|
|
129
|
+
draggable ? "dialog-title draggable-dialog-title" : "dialog-title"
|
|
130
|
+
}
|
|
131
|
+
>
|
|
127
132
|
{icon}
|
|
128
133
|
<span className="dialogTitle">{title}</span>
|
|
129
134
|
{closable && (
|
|
@@ -204,7 +209,12 @@ export class NotificationMU extends NotificationReact {
|
|
|
204
209
|
fullScreen={fullScreen}
|
|
205
210
|
{...options}
|
|
206
211
|
>
|
|
207
|
-
<IconDialogTitle
|
|
212
|
+
<IconDialogTitle
|
|
213
|
+
draggable={draggable}
|
|
214
|
+
className={
|
|
215
|
+
draggable ? "dialog-title draggable-dialog-title" : "dialog-title"
|
|
216
|
+
}
|
|
217
|
+
>
|
|
208
218
|
<Help color="action" />
|
|
209
219
|
<span className="dialogTitle">{title}</span>
|
|
210
220
|
{closable && (
|
|
@@ -438,7 +448,12 @@ export class NotificationMU extends NotificationReact {
|
|
|
438
448
|
return false;
|
|
439
449
|
}}
|
|
440
450
|
>
|
|
441
|
-
<IconDialogTitle
|
|
451
|
+
<IconDialogTitle
|
|
452
|
+
draggable={draggable}
|
|
453
|
+
className={
|
|
454
|
+
draggable ? "dialog-title draggable-dialog-title" : "dialog-title"
|
|
455
|
+
}
|
|
456
|
+
>
|
|
442
457
|
<Info color="primary" />
|
|
443
458
|
<span className="dialogTitle">{title}</span>
|
|
444
459
|
{closable && (
|
package/src/app/ReactApp.ts
CHANGED
|
@@ -427,7 +427,8 @@ export class ReactApp<
|
|
|
427
427
|
override async tryLogin(data?: AppTryLoginParams) {
|
|
428
428
|
// Destruct
|
|
429
429
|
const {
|
|
430
|
-
onFailure = () => {
|
|
430
|
+
onFailure = (type: string) => {
|
|
431
|
+
console.log(`Try login failed: ${type}.`);
|
|
431
432
|
this.toLoginPage(rest);
|
|
432
433
|
},
|
|
433
434
|
onSuccess,
|
package/src/app/ServiceApp.ts
CHANGED
|
@@ -244,6 +244,44 @@ export class ServiceApp<
|
|
|
244
244
|
return result;
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
+
protected override async refreshTokenSucceed(
|
|
248
|
+
user: U,
|
|
249
|
+
token: string,
|
|
250
|
+
callback?: (result?: boolean | IActionResult) => boolean | void
|
|
251
|
+
): Promise<void> {
|
|
252
|
+
// Check core system token
|
|
253
|
+
const coreToken = this.storage.getData<string>(coreTokenKey);
|
|
254
|
+
if (!coreToken) {
|
|
255
|
+
callback?.({ ok: false, type: "noData", title: "Core token is blank" });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const coreTokenDecrypted = this.decrypt(coreToken);
|
|
260
|
+
if (!coreTokenDecrypted) {
|
|
261
|
+
callback?.({
|
|
262
|
+
ok: false,
|
|
263
|
+
type: "noData",
|
|
264
|
+
title: "Core token decrypted is blank"
|
|
265
|
+
});
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Call the core system API refresh token
|
|
270
|
+
const data = await this.apiRefreshTokenData(this.coreApi, {
|
|
271
|
+
token: coreTokenDecrypted,
|
|
272
|
+
appId: this.settings.appId
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (data == null) return;
|
|
276
|
+
|
|
277
|
+
// Cache the core system refresh token
|
|
278
|
+
// Follow similar logic in userLoginEx
|
|
279
|
+
this.saveCoreToken(data);
|
|
280
|
+
|
|
281
|
+
// Call the super
|
|
282
|
+
await super.refreshTokenSucceed(user, token, callback);
|
|
283
|
+
}
|
|
284
|
+
|
|
247
285
|
/**
|
|
248
286
|
* Try login
|
|
249
287
|
* @param params Login parameters
|
|
@@ -251,7 +289,7 @@ export class ServiceApp<
|
|
|
251
289
|
override async tryLogin(params?: AppTryLoginParams) {
|
|
252
290
|
// Destruct
|
|
253
291
|
params ??= {};
|
|
254
|
-
let { onFailure,
|
|
292
|
+
let { onFailure, ...rest } = params;
|
|
255
293
|
|
|
256
294
|
if (onFailure == null) {
|
|
257
295
|
onFailure = params.onFailure = (type) => {
|
|
@@ -260,34 +298,6 @@ export class ServiceApp<
|
|
|
260
298
|
};
|
|
261
299
|
}
|
|
262
300
|
|
|
263
|
-
// Check core system token
|
|
264
|
-
const coreToken = this.storage.getData<string>(coreTokenKey);
|
|
265
|
-
if (!coreToken) {
|
|
266
|
-
onFailure("ServiceAppCoreTokenNoData");
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const coreTokenDecrypted = this.decrypt(coreToken);
|
|
271
|
-
if (!coreTokenDecrypted) {
|
|
272
|
-
onFailure("ServiceAppCoreTokenNoDecryptedData");
|
|
273
|
-
return false;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
params.onSuccess = () => {
|
|
277
|
-
// Call the core system API refresh token
|
|
278
|
-
this.apiRefreshTokenData(this.coreApi, {
|
|
279
|
-
token: coreTokenDecrypted,
|
|
280
|
-
appId: this.settings.appId
|
|
281
|
-
}).then((data) => {
|
|
282
|
-
if (data == null) return;
|
|
283
|
-
|
|
284
|
-
// Cache the core system refresh token
|
|
285
|
-
this.saveCoreToken(data);
|
|
286
|
-
|
|
287
|
-
onSuccess?.();
|
|
288
|
-
});
|
|
289
|
-
};
|
|
290
|
-
|
|
291
301
|
return await super.tryLogin(params);
|
|
292
302
|
}
|
|
293
303
|
}
|
package/src/index.ts
CHANGED
|
@@ -43,6 +43,7 @@ export * from "./AutocompleteExtendedProps";
|
|
|
43
43
|
export * from "./BackButton";
|
|
44
44
|
export * from "./BridgeCloseButton";
|
|
45
45
|
export * from "./ButtonLink";
|
|
46
|
+
export * from "./ButtonPopover";
|
|
46
47
|
export * from "./ComboBox";
|
|
47
48
|
export * from "./ComboBoxMultiple";
|
|
48
49
|
export * from "./ComboBoxPro";
|