@etsoo/react 1.3.51 → 1.3.55

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.
@@ -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,22 +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 [state] = React.useState({});
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
- ? async (authorized) => {
38
- await onUpdateAll(authorized);
39
- state.loaded = true;
40
- }
36
+ ? onUpdateAll
41
37
  : onUpdate
42
38
  ? (authorized) => {
43
39
  if (authorized == null || authorized)
@@ -49,20 +45,9 @@ export function CommonPage(props) {
49
45
  onRefresh();
50
46
  }
51
47
  : undefined;
52
- React.useEffect(() => {
53
- return () => {
54
- state.loaded = false;
55
- };
56
- }, []);
57
- React.useEffect(() => {
58
- // onUpdateAll support to load after page mounted
59
- if (onUpdateAll != null && state.loaded) {
60
- onUpdateAll();
61
- }
62
- });
63
48
  // Return the UI
64
49
  return (React.createElement(React.Fragment, null,
65
- update && React.createElement(ReactAppStateDetector, { update: update }),
50
+ update && (React.createElement(ReactAppStateDetector, { targetFields: targetFields, update: update })),
66
51
  React.createElement(Container, { disableGutters: disableGutters, maxWidth: maxWidth, sx: sx, id: "page-container", ...rest },
67
52
  React.createElement(FabBox, { sx: {
68
53
  zIndex: 1,
@@ -52,4 +52,8 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
52
52
  * Scroll container
53
53
  */
54
54
  scrollContainer?: HTMLElement | object;
55
+ /**
56
+ * State last changed fields
57
+ */
58
+ targetFields?: string[];
55
59
  }
@@ -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
  /**
@@ -53,4 +53,5 @@ export declare class UserState<D extends IUser> {
53
53
  * Constructor
54
54
  */
55
55
  constructor();
56
+ private getChangedFields;
56
57
  }
@@ -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
- return { ...action.user, authorized: true };
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.objectUpdated(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.51",
3
+ "version": "1.3.55",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,9 +50,9 @@
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.77",
53
+ "@etsoo/appscript": "^1.1.79",
54
54
  "@etsoo/notificationbase": "^1.0.94",
55
- "@etsoo/shared": "^1.0.76",
55
+ "@etsoo/shared": "^1.0.78",
56
56
  "@mui/icons-material": "^5.2.4",
57
57
  "@mui/material": "^5.2.4",
58
58
  "@reach/router": "^1.3.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.1",
92
+ "ts-jest": "^27.1.2",
93
93
  "typescript": "^4.5.4"
94
94
  }
95
95
  }
@@ -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,8 +51,6 @@ export function CommonPage(props: CommonPageProps) {
50
51
  padding: paddings
51
52
  });
52
53
 
53
- const [state] = React.useState<{ loaded?: boolean }>({});
54
-
55
54
  // Fab padding
56
55
  const fabPadding = MUGlobal.increase(
57
56
  MUGlobal.pagePaddings,
@@ -63,10 +62,7 @@ export function CommonPage(props: CommonPageProps) {
63
62
 
64
63
  // Update
65
64
  const update = onUpdateAll
66
- ? async (authorized?: boolean) => {
67
- await onUpdateAll(authorized);
68
- state.loaded = true;
69
- }
65
+ ? onUpdateAll
70
66
  : onUpdate
71
67
  ? (authorized?: boolean) => {
72
68
  if (authorized == null || authorized) onUpdate();
@@ -77,23 +73,15 @@ export function CommonPage(props: CommonPageProps) {
77
73
  }
78
74
  : undefined;
79
75
 
80
- React.useEffect(() => {
81
- return () => {
82
- state.loaded = false;
83
- };
84
- }, []);
85
-
86
- React.useEffect(() => {
87
- // onUpdateAll support to load after page mounted
88
- if (onUpdateAll != null && state.loaded) {
89
- onUpdateAll();
90
- }
91
- });
92
-
93
76
  // Return the UI
94
77
  return (
95
78
  <React.Fragment>
96
- {update && <ReactAppStateDetector update={update} />}
79
+ {update && (
80
+ <ReactAppStateDetector
81
+ targetFields={targetFields}
82
+ update={update}
83
+ />
84
+ )}
97
85
  <Container
98
86
  disableGutters={disableGutters}
99
87
  maxWidth={maxWidth}
@@ -62,4 +62,9 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
62
62
  * Scroll container
63
63
  */
64
64
  scrollContainer?: HTMLElement | object;
65
+
66
+ /**
67
+ * State last changed fields
68
+ */
69
+ targetFields?: string[];
65
70
  }
@@ -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
 
@@ -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
- return { ...action.user!, authorized: true } as D;
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.objectUpdated(input, init, [
127
+ 'seconds',
128
+ 'lastChangedFields'
129
+ ]);
130
+ }
109
131
  }