@etsoo/react 1.3.53 → 1.3.54
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/app/ReactApp.js +16 -3
- package/lib/mu/pages/CommonPage.js +3 -24
- package/lib/mu/pages/CommonPageProps.d.ts +4 -0
- package/lib/states/IState.d.ts +8 -1
- package/lib/states/UserState.d.ts +1 -0
- package/lib/states/UserState.js +18 -1
- package/package.json +3 -3
- package/src/app/ReactApp.ts +16 -3
- package/src/mu/pages/CommonPage.tsx +8 -30
- package/src/mu/pages/CommonPageProps.ts +5 -0
- package/src/states/IState.ts +9 -1
- package/src/states/UserState.ts +23 -1
package/lib/app/ReactApp.js
CHANGED
|
@@ -19,16 +19,29 @@ let globalApp;
|
|
|
19
19
|
*/
|
|
20
20
|
export function ReactAppStateDetector(props) {
|
|
21
21
|
// Destruct
|
|
22
|
-
const { update } = props;
|
|
22
|
+
const { targetFields, update } = props;
|
|
23
23
|
// Context
|
|
24
24
|
const { state } = globalApp == null
|
|
25
25
|
? { state: {} }
|
|
26
26
|
: React.useContext(globalApp.userState.context);
|
|
27
|
+
// Match fields
|
|
28
|
+
const changedFields = state.lastChangedFields;
|
|
29
|
+
let matchedFields;
|
|
30
|
+
if (targetFields == null || changedFields == null) {
|
|
31
|
+
matchedFields = changedFields;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
matchedFields = [];
|
|
35
|
+
targetFields.forEach((targetField) => {
|
|
36
|
+
if (changedFields.includes(targetField))
|
|
37
|
+
matchedFields === null || matchedFields === void 0 ? void 0 : matchedFields.push(targetField);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
27
40
|
// Ready
|
|
28
41
|
React.useEffect(() => {
|
|
29
42
|
// Callback
|
|
30
|
-
update(state.authorized);
|
|
31
|
-
}, [state.authorized]);
|
|
43
|
+
update(state.authorized, matchedFields);
|
|
44
|
+
}, [state.authorized, matchedFields]);
|
|
32
45
|
// return
|
|
33
46
|
return React.createElement(React.Fragment);
|
|
34
47
|
}
|
|
@@ -22,23 +22,18 @@ export const CommonPageScrollContainer = global;
|
|
|
22
22
|
*/
|
|
23
23
|
export function CommonPage(props) {
|
|
24
24
|
// Destruct
|
|
25
|
-
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, pullContainer, sx = {}, ...rest } = props;
|
|
25
|
+
const { children, disableGutters = true, fabButtons, fabColumnDirection, fabPaddingAdjust = 1.5, fabSize = 'small', maxWidth = false, moreActions, onRefresh, onUpdate, onUpdateAll, paddings = MUGlobal.pagePaddings, scrollContainer, targetFields, pullContainer, sx = {}, ...rest } = props;
|
|
26
26
|
// Merge style
|
|
27
27
|
Object.assign(sx, {
|
|
28
28
|
padding: paddings
|
|
29
29
|
});
|
|
30
|
-
const ref = React.useRef({});
|
|
31
30
|
// Fab padding
|
|
32
31
|
const fabPadding = MUGlobal.increase(MUGlobal.pagePaddings, fabPaddingAdjust);
|
|
33
32
|
// Labels
|
|
34
33
|
const labels = Labels.CommonPage;
|
|
35
34
|
// Update
|
|
36
35
|
const update = onUpdateAll
|
|
37
|
-
?
|
|
38
|
-
ref.current.loading = true;
|
|
39
|
-
await onUpdateAll(authorized);
|
|
40
|
-
ref.current.firstLoaded = true;
|
|
41
|
-
}
|
|
36
|
+
? onUpdateAll
|
|
42
37
|
: onUpdate
|
|
43
38
|
? (authorized) => {
|
|
44
39
|
if (authorized == null || authorized)
|
|
@@ -50,25 +45,9 @@ export function CommonPage(props) {
|
|
|
50
45
|
onRefresh();
|
|
51
46
|
}
|
|
52
47
|
: undefined;
|
|
53
|
-
React.useEffect(() => {
|
|
54
|
-
return () => {
|
|
55
|
-
ref.current.loading = false;
|
|
56
|
-
ref.current.firstLoaded = false;
|
|
57
|
-
};
|
|
58
|
-
}, []);
|
|
59
|
-
React.useEffect(() => {
|
|
60
|
-
if (ref.current.loading) {
|
|
61
|
-
ref.current.loading = false;
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
// onUpdateAll support to load after page loaded
|
|
65
|
-
if (onUpdateAll != null && ref.current.firstLoaded) {
|
|
66
|
-
onUpdateAll();
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
48
|
// Return the UI
|
|
70
49
|
return (React.createElement(React.Fragment, null,
|
|
71
|
-
update && React.createElement(ReactAppStateDetector, { update: update }),
|
|
50
|
+
update && (React.createElement(ReactAppStateDetector, { targetFields: targetFields, update: update })),
|
|
72
51
|
React.createElement(Container, { disableGutters: disableGutters, maxWidth: maxWidth, sx: sx, id: "page-container", ...rest },
|
|
73
52
|
React.createElement(FabBox, { sx: {
|
|
74
53
|
zIndex: 1,
|
package/lib/states/IState.d.ts
CHANGED
|
@@ -17,12 +17,19 @@ export interface IUpdate<S extends IState, A extends IAction> {
|
|
|
17
17
|
* State update interface
|
|
18
18
|
*/
|
|
19
19
|
export interface IStateUpdate {
|
|
20
|
-
(authorized?: boolean): PromiseLike<void> | void;
|
|
20
|
+
(authorized?: boolean, matchedFields?: string[]): PromiseLike<void> | void;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* State update props
|
|
24
24
|
*/
|
|
25
25
|
export interface IStateProps {
|
|
26
|
+
/**
|
|
27
|
+
* State last changed fields
|
|
28
|
+
*/
|
|
29
|
+
targetFields?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* State update callback
|
|
32
|
+
*/
|
|
26
33
|
update: IStateUpdate;
|
|
27
34
|
}
|
|
28
35
|
/**
|
package/lib/states/UserState.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Utils } from '@etsoo/shared';
|
|
1
2
|
import { State } from './State';
|
|
2
3
|
/**
|
|
3
4
|
* User action type
|
|
@@ -26,10 +27,18 @@ export class UserState {
|
|
|
26
27
|
// User reducer
|
|
27
28
|
switch (action.type) {
|
|
28
29
|
case UserActionType.Login:
|
|
29
|
-
|
|
30
|
+
const lastChangedFields = state.authorized && action.user
|
|
31
|
+
? this.getChangedFields(action.user, state)
|
|
32
|
+
: [];
|
|
33
|
+
return {
|
|
34
|
+
...action.user,
|
|
35
|
+
authorized: true,
|
|
36
|
+
lastChangedFields
|
|
37
|
+
};
|
|
30
38
|
case UserActionType.Logout:
|
|
31
39
|
return {
|
|
32
40
|
...state,
|
|
41
|
+
lastChangedFields: undefined,
|
|
33
42
|
token: undefined,
|
|
34
43
|
authorized: false // Flag as unauthorized
|
|
35
44
|
};
|
|
@@ -37,6 +46,7 @@ export class UserState {
|
|
|
37
46
|
if (action.update) {
|
|
38
47
|
var newState = { ...state };
|
|
39
48
|
action.update(newState);
|
|
49
|
+
newState.lastChangedFields = this.getChangedFields(newState, state);
|
|
40
50
|
return newState;
|
|
41
51
|
}
|
|
42
52
|
return state;
|
|
@@ -46,6 +56,7 @@ export class UserState {
|
|
|
46
56
|
return state;
|
|
47
57
|
return {
|
|
48
58
|
...state,
|
|
59
|
+
lastChangedFields: undefined,
|
|
49
60
|
authorized: false // Flag as unauthorized
|
|
50
61
|
};
|
|
51
62
|
default:
|
|
@@ -55,4 +66,10 @@ export class UserState {
|
|
|
55
66
|
this.context = context;
|
|
56
67
|
this.provider = provider;
|
|
57
68
|
}
|
|
69
|
+
getChangedFields(input, init) {
|
|
70
|
+
return Utils.getDataChanges(input, init, [
|
|
71
|
+
'seconds',
|
|
72
|
+
'lastChangedFields'
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
58
75
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.54",
|
|
4
4
|
"description": "TypeScript ReactJs framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@emotion/react": "^11.7.1",
|
|
51
51
|
"@emotion/style": "^0.8.0",
|
|
52
52
|
"@emotion/styled": "^11.6.0",
|
|
53
|
-
"@etsoo/appscript": "^1.1.
|
|
53
|
+
"@etsoo/appscript": "^1.1.79",
|
|
54
54
|
"@etsoo/notificationbase": "^1.0.94",
|
|
55
55
|
"@etsoo/shared": "^1.0.76",
|
|
56
56
|
"@mui/icons-material": "^5.2.4",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"eslint-plugin-react": "^7.27.1",
|
|
90
90
|
"jest": "^27.4.5",
|
|
91
91
|
"react-test-renderer": "^17.0.2",
|
|
92
|
-
"ts-jest": "^27.1.
|
|
92
|
+
"ts-jest": "^27.1.2",
|
|
93
93
|
"typescript": "^4.5.4"
|
|
94
94
|
}
|
|
95
95
|
}
|
package/src/app/ReactApp.ts
CHANGED
|
@@ -42,7 +42,7 @@ let globalApp: IReactApp<IAppSettings, any, IPageData>;
|
|
|
42
42
|
*/
|
|
43
43
|
export function ReactAppStateDetector(props: IStateProps) {
|
|
44
44
|
// Destruct
|
|
45
|
-
const { update } = props;
|
|
45
|
+
const { targetFields, update } = props;
|
|
46
46
|
|
|
47
47
|
// Context
|
|
48
48
|
const { state } =
|
|
@@ -52,11 +52,24 @@ export function ReactAppStateDetector(props: IStateProps) {
|
|
|
52
52
|
(globalApp.userState as UserState<IUser>).context
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
+
// Match fields
|
|
56
|
+
const changedFields = state.lastChangedFields;
|
|
57
|
+
let matchedFields: string[] | undefined;
|
|
58
|
+
if (targetFields == null || changedFields == null) {
|
|
59
|
+
matchedFields = changedFields;
|
|
60
|
+
} else {
|
|
61
|
+
matchedFields = [];
|
|
62
|
+
targetFields.forEach((targetField) => {
|
|
63
|
+
if (changedFields.includes(targetField))
|
|
64
|
+
matchedFields?.push(targetField);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
// Ready
|
|
56
69
|
React.useEffect(() => {
|
|
57
70
|
// Callback
|
|
58
|
-
update(state.authorized);
|
|
59
|
-
}, [state.authorized]);
|
|
71
|
+
update(state.authorized, matchedFields);
|
|
72
|
+
}, [state.authorized, matchedFields]);
|
|
60
73
|
|
|
61
74
|
// return
|
|
62
75
|
return React.createElement(React.Fragment);
|
|
@@ -40,6 +40,7 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
40
40
|
onUpdateAll,
|
|
41
41
|
paddings = MUGlobal.pagePaddings,
|
|
42
42
|
scrollContainer,
|
|
43
|
+
targetFields,
|
|
43
44
|
pullContainer,
|
|
44
45
|
sx = {},
|
|
45
46
|
...rest
|
|
@@ -50,11 +51,6 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
50
51
|
padding: paddings
|
|
51
52
|
});
|
|
52
53
|
|
|
53
|
-
const ref = React.useRef<{
|
|
54
|
-
firstLoaded?: boolean;
|
|
55
|
-
loading?: boolean;
|
|
56
|
-
}>({});
|
|
57
|
-
|
|
58
54
|
// Fab padding
|
|
59
55
|
const fabPadding = MUGlobal.increase(
|
|
60
56
|
MUGlobal.pagePaddings,
|
|
@@ -66,11 +62,7 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
66
62
|
|
|
67
63
|
// Update
|
|
68
64
|
const update = onUpdateAll
|
|
69
|
-
?
|
|
70
|
-
ref.current.loading = true;
|
|
71
|
-
await onUpdateAll(authorized);
|
|
72
|
-
ref.current.firstLoaded = true;
|
|
73
|
-
}
|
|
65
|
+
? onUpdateAll
|
|
74
66
|
: onUpdate
|
|
75
67
|
? (authorized?: boolean) => {
|
|
76
68
|
if (authorized == null || authorized) onUpdate();
|
|
@@ -81,29 +73,15 @@ export function CommonPage(props: CommonPageProps) {
|
|
|
81
73
|
}
|
|
82
74
|
: undefined;
|
|
83
75
|
|
|
84
|
-
React.useEffect(() => {
|
|
85
|
-
return () => {
|
|
86
|
-
ref.current.loading = false;
|
|
87
|
-
ref.current.firstLoaded = false;
|
|
88
|
-
};
|
|
89
|
-
}, []);
|
|
90
|
-
|
|
91
|
-
React.useEffect(() => {
|
|
92
|
-
if (ref.current.loading) {
|
|
93
|
-
ref.current.loading = false;
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// onUpdateAll support to load after page loaded
|
|
98
|
-
if (onUpdateAll != null && ref.current.firstLoaded) {
|
|
99
|
-
onUpdateAll();
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
76
|
// Return the UI
|
|
104
77
|
return (
|
|
105
78
|
<React.Fragment>
|
|
106
|
-
{update &&
|
|
79
|
+
{update && (
|
|
80
|
+
<ReactAppStateDetector
|
|
81
|
+
targetFields={targetFields}
|
|
82
|
+
update={update}
|
|
83
|
+
/>
|
|
84
|
+
)}
|
|
107
85
|
<Container
|
|
108
86
|
disableGutters={disableGutters}
|
|
109
87
|
maxWidth={maxWidth}
|
package/src/states/IState.ts
CHANGED
|
@@ -20,13 +20,21 @@ export interface IUpdate<S extends IState, A extends IAction> {
|
|
|
20
20
|
* State update interface
|
|
21
21
|
*/
|
|
22
22
|
export interface IStateUpdate {
|
|
23
|
-
(authorized?: boolean): PromiseLike<void> | void;
|
|
23
|
+
(authorized?: boolean, matchedFields?: string[]): PromiseLike<void> | void;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* State update props
|
|
28
28
|
*/
|
|
29
29
|
export interface IStateProps {
|
|
30
|
+
/**
|
|
31
|
+
* State last changed fields
|
|
32
|
+
*/
|
|
33
|
+
targetFields?: string[];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* State update callback
|
|
37
|
+
*/
|
|
30
38
|
update: IStateUpdate;
|
|
31
39
|
}
|
|
32
40
|
|
package/src/states/UserState.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IAction, IUser, IUserData } from '@etsoo/appscript';
|
|
2
|
+
import { Utils } from '@etsoo/shared';
|
|
2
3
|
import { IProviderProps, IUpdate } from './IState';
|
|
3
4
|
import { State } from './State';
|
|
4
5
|
|
|
@@ -73,10 +74,19 @@ export class UserState<D extends IUser> {
|
|
|
73
74
|
// User reducer
|
|
74
75
|
switch (action.type) {
|
|
75
76
|
case UserActionType.Login:
|
|
76
|
-
|
|
77
|
+
const lastChangedFields =
|
|
78
|
+
state.authorized && action.user
|
|
79
|
+
? this.getChangedFields(action.user, state)
|
|
80
|
+
: [];
|
|
81
|
+
return {
|
|
82
|
+
...action.user!,
|
|
83
|
+
authorized: true,
|
|
84
|
+
lastChangedFields
|
|
85
|
+
} as D;
|
|
77
86
|
case UserActionType.Logout:
|
|
78
87
|
return {
|
|
79
88
|
...state, // Keep other user data
|
|
89
|
+
lastChangedFields: undefined,
|
|
80
90
|
token: undefined, // Remove token
|
|
81
91
|
authorized: false // Flag as unauthorized
|
|
82
92
|
};
|
|
@@ -84,6 +94,10 @@ export class UserState<D extends IUser> {
|
|
|
84
94
|
if (action.update) {
|
|
85
95
|
var newState = { ...state };
|
|
86
96
|
action.update(newState);
|
|
97
|
+
newState.lastChangedFields = this.getChangedFields(
|
|
98
|
+
newState,
|
|
99
|
+
state
|
|
100
|
+
);
|
|
87
101
|
return newState;
|
|
88
102
|
}
|
|
89
103
|
return state;
|
|
@@ -93,6 +107,7 @@ export class UserState<D extends IUser> {
|
|
|
93
107
|
|
|
94
108
|
return {
|
|
95
109
|
...state, // Keep other user data and token for refresh
|
|
110
|
+
lastChangedFields: undefined,
|
|
96
111
|
authorized: false // Flag as unauthorized
|
|
97
112
|
};
|
|
98
113
|
default:
|
|
@@ -106,4 +121,11 @@ export class UserState<D extends IUser> {
|
|
|
106
121
|
this.context = context;
|
|
107
122
|
this.provider = provider;
|
|
108
123
|
}
|
|
124
|
+
|
|
125
|
+
private getChangedFields(input: {}, init: {}) {
|
|
126
|
+
return Utils.getDataChanges(input, init, [
|
|
127
|
+
'seconds',
|
|
128
|
+
'lastChangedFields'
|
|
129
|
+
]);
|
|
130
|
+
}
|
|
109
131
|
}
|