@etsoo/react 1.5.12 → 1.5.16

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.
Files changed (46) hide show
  1. package/lib/app/Labels.d.ts +1 -0
  2. package/lib/app/Labels.js +1 -0
  3. package/lib/app/ReactApp.d.ts +0 -13
  4. package/lib/app/ReactApp.js +6 -31
  5. package/lib/app/{Utils.d.ts → ReactUtils.d.ts} +7 -2
  6. package/lib/app/{Utils.js → ReactUtils.js} +20 -10
  7. package/lib/app/ServiceApp.d.ts +6 -5
  8. package/lib/app/ServiceApp.js +14 -7
  9. package/lib/index.d.ts +2 -1
  10. package/lib/index.js +2 -1
  11. package/lib/mu/BackButton.d.ts +13 -0
  12. package/lib/mu/BackButton.js +32 -0
  13. package/lib/mu/BridgeCloseButton.d.ts +5 -1
  14. package/lib/mu/BridgeCloseButton.js +5 -9
  15. package/lib/mu/ButtonLink.js +2 -2
  16. package/lib/mu/ComboBox.js +2 -2
  17. package/lib/mu/IconButtonLink.js +2 -2
  18. package/lib/mu/ResponsibleContainer.js +2 -2
  19. package/lib/mu/SearchBar.js +2 -2
  20. package/lib/mu/SelectEx.js +2 -2
  21. package/lib/mu/Tiplist.js +3 -3
  22. package/lib/mu/pages/CommonPage.js +4 -2
  23. package/lib/mu/pages/CommonPageProps.d.ts +5 -1
  24. package/lib/mu/pages/EditPage.d.ts +5 -0
  25. package/lib/mu/pages/EditPage.js +4 -2
  26. package/lib/mu/pages/ViewPage.d.ts +4 -0
  27. package/lib/mu/pages/ViewPage.js +13 -3
  28. package/package.json +2 -2
  29. package/src/app/Labels.ts +1 -0
  30. package/src/app/ReactApp.ts +9 -36
  31. package/src/app/{Utils.ts → ReactUtils.ts} +20 -4
  32. package/src/app/ServiceApp.ts +16 -7
  33. package/src/index.ts +2 -1
  34. package/src/mu/BackButton.tsx +53 -0
  35. package/src/mu/BridgeCloseButton.tsx +17 -16
  36. package/src/mu/ButtonLink.tsx +3 -2
  37. package/src/mu/ComboBox.tsx +2 -2
  38. package/src/mu/IconButtonLink.tsx +2 -2
  39. package/src/mu/ResponsibleContainer.tsx +2 -2
  40. package/src/mu/SearchBar.tsx +2 -2
  41. package/src/mu/SelectEx.tsx +2 -2
  42. package/src/mu/Tiplist.tsx +3 -3
  43. package/src/mu/pages/CommonPage.tsx +5 -0
  44. package/src/mu/pages/CommonPageProps.ts +6 -1
  45. package/src/mu/pages/EditPage.tsx +9 -0
  46. package/src/mu/pages/ViewPage.tsx +36 -1
@@ -1,9 +1,11 @@
1
1
  import { Utils } from '@etsoo/shared';
2
2
  import { Grid, LinearProgress, Stack, Typography } from '@mui/material';
3
3
  import React from 'react';
4
+ import { Labels } from '../../app/Labels';
4
5
  import { globalApp } from '../../app/ReactApp';
5
6
  import { GridDataFormat } from '../GridDataFormat';
6
7
  import { MUGlobal } from '../MUGlobal';
8
+ import { PullToRefreshUI } from '../PullToRefreshUI';
7
9
  import { CommonPage } from './CommonPage';
8
10
  function formatItemData(fieldData) {
9
11
  if (fieldData == null)
@@ -62,9 +64,13 @@ function getItemField(field, data) {
62
64
  */
63
65
  export function ViewPage(props) {
64
66
  // Destruct
65
- const { actions, children, fields, loadData, paddings = MUGlobal.pagePaddings, supportRefresh = true, ...rest } = props;
67
+ const { actions, children, fields, loadData, paddings = MUGlobal.pagePaddings, supportRefresh = true, fabColumnDirection = true, supportBack = true, pullToRefresh = true, ...rest } = props;
66
68
  // Data
67
69
  const [data, setData] = React.useState();
70
+ // Labels
71
+ const labels = Labels.CommonPage;
72
+ // Container
73
+ const pullContainer = '#page-container';
68
74
  // Load data
69
75
  const refresh = async () => {
70
76
  const result = await loadData();
@@ -72,7 +78,7 @@ export function ViewPage(props) {
72
78
  return;
73
79
  setData(result);
74
80
  };
75
- return (React.createElement(CommonPage, { paddings: paddings, onRefresh: supportRefresh ? refresh : undefined, onUpdate: supportRefresh ? undefined : refresh, ...rest, scrollContainer: global }, data == null ? (React.createElement(LinearProgress, null)) : (React.createElement(React.Fragment, null,
81
+ return (React.createElement(CommonPage, { paddings: paddings, onRefresh: supportRefresh ? refresh : undefined, onUpdate: supportRefresh ? undefined : refresh, ...rest, scrollContainer: globalThis, fabColumnDirection: fabColumnDirection, supportBack: supportBack }, data == null ? (React.createElement(LinearProgress, null)) : (React.createElement(React.Fragment, null,
76
82
  React.createElement(Grid, { container: true, justifyContent: "left", spacing: paddings, className: "ET-ViewPage", sx: {
77
83
  '.MuiTypography-subtitle2': {
78
84
  fontWeight: 'bold'
@@ -91,5 +97,9 @@ export function ViewPage(props) {
91
97
  React.createElement(Typography, { variant: "subtitle2" }, itemData)));
92
98
  })),
93
99
  actions != null && (React.createElement(Stack, { className: "ET-ViewPage-Actions", direction: "row", width: "100%", flexWrap: "wrap", justifyContent: "flex-end", paddingTop: paddings, paddingBottom: paddings, gap: paddings }, Utils.getResult(actions, data, refresh))),
94
- Utils.getResult(children, data, refresh)))));
100
+ Utils.getResult(children, data, refresh),
101
+ pullToRefresh && (React.createElement(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: refresh, shouldPullToRefresh: () => {
102
+ const container = document.querySelector(pullContainer);
103
+ return !(container === null || container === void 0 ? void 0 : container.scrollTop);
104
+ } }))))));
95
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.5.12",
3
+ "version": "1.5.16",
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.2.48",
53
+ "@etsoo/appscript": "^1.2.50",
54
54
  "@etsoo/notificationbase": "^1.1.1",
55
55
  "@etsoo/shared": "^1.1.11",
56
56
  "@mui/icons-material": "^5.4.1",
package/src/app/Labels.ts CHANGED
@@ -9,6 +9,7 @@ export namespace Labels {
9
9
  */
10
10
  export const CommonPage = {
11
11
  add: 'Add',
12
+ back: 'Back',
12
13
  delete: 'Delete',
13
14
  more: 'More',
14
15
  pullToRefresh: 'Pull down to refresh',
@@ -35,7 +35,7 @@ import {
35
35
  } from '../states/UserState';
36
36
  import { InputDialogProps } from './InputDialogProps';
37
37
  import { Labels } from './Labels';
38
- import { Utils } from './Utils';
38
+ import { ReactUtils } from './ReactUtils';
39
39
 
40
40
  /**
41
41
  * Global application
@@ -56,12 +56,10 @@ export function ReactAppStateDetector(props: IStateProps) {
56
56
  const { targetFields, update } = props;
57
57
 
58
58
  // Context
59
- const { state } =
59
+ const { state = {} } =
60
60
  globalApp == null
61
- ? ({ state: {} } as UserCalls<IUser>)
62
- : React.useContext(
63
- (globalApp.userState as UserState<IUser>).context
64
- );
61
+ ? ({} as UserCalls<IUser>)
62
+ : React.useContext(globalApp.userState.context);
65
63
 
66
64
  // Ready
67
65
  React.useEffect(() => {
@@ -221,43 +219,18 @@ export class ReactApp<
221
219
  new WindowStorage(),
222
220
  name
223
221
  );
222
+
224
223
  this.history =
225
- window.location.hostname === ''
226
- ? Utils.getMemoryHistory(this.getHostUrl(window.location.href))
227
- : undefined;
224
+ BridgeUtils.host == null
225
+ ? undefined
226
+ : ReactUtils.getMemoryHistory(BridgeUtils.host.getStartUrl());
227
+
228
228
  this.cultureState = new CultureState(settings.currentCulture);
229
229
  this.pageState = new PageState<P>();
230
230
 
231
231
  globalApp = this;
232
232
  }
233
233
 
234
- /**
235
- * Get parsed Url under bridge host
236
- * @param url Url
237
- * @returns Parsed Url
238
- */
239
- protected getHostUrl(url: string) {
240
- return this.getHostUrlBase(url, 'core');
241
- }
242
-
243
- /**
244
- * Get parsed Url under bridge host
245
- * @param url Url
246
- * @param name App name in the host environment
247
- * @returns Parsed Url
248
- */
249
- protected getHostUrlBase(url: string, name: string) {
250
- if (url.startsWith('/')) return url;
251
-
252
- const identifier = `/${name}/`;
253
- const pos = url.indexOf(identifier);
254
- if (pos === -1) return '/';
255
-
256
- return url
257
- .substring(pos + identifier.length - 1)
258
- .replace('/index.html', '/'); // Router take / as start
259
- }
260
-
261
234
  /**
262
235
  * Override alert action result
263
236
  * @param result Action result
@@ -1,10 +1,15 @@
1
- import { createHistory, createMemorySource, History } from '@reach/router';
1
+ import {
2
+ createHistory,
3
+ createMemorySource,
4
+ History,
5
+ navigate
6
+ } from '@reach/router';
2
7
  import React from 'react';
3
8
 
4
9
  /**
5
10
  * React utils
6
11
  */
7
- export namespace Utils {
12
+ export namespace ReactUtils {
8
13
  // Memory history
9
14
  // https://github.com/reach/router/issues/225
10
15
  let memoryHistory: History | null;
@@ -31,13 +36,24 @@ export namespace Utils {
31
36
  * @param initialPath Initial path
32
37
  * @returns History
33
38
  */
34
- export function getMemoryHistory(initialPath: string = '/') {
39
+ export function getMemoryHistory(initialPath?: string | null) {
35
40
  if (memoryHistory == null) {
36
- memoryHistory = createHistory(createMemorySource(initialPath));
41
+ memoryHistory = createHistory(
42
+ createMemorySource(initialPath ?? '/')
43
+ );
37
44
  }
38
45
  return memoryHistory;
39
46
  }
40
47
 
48
+ /**
49
+ * Get navigate function, works with memory history
50
+ * @returns NavigateFn
51
+ */
52
+ export function getNavigateFn() {
53
+ if (memoryHistory == null) return navigate;
54
+ return memoryHistory.navigate;
55
+ }
56
+
41
57
  /**
42
58
  * Is safe click
43
59
  * @param event Mouse event
@@ -69,12 +69,14 @@ export class ServiceApp<
69
69
  }
70
70
 
71
71
  /**
72
- * Get parsed Url under bridge host
73
- * @param url Url
74
- * @returns Parsed Url
72
+ * Load SmartERP core
75
73
  */
76
- protected override getHostUrl(url: string) {
77
- return this.getHostUrlBase(url, 's' + this.settings.serviceId);
74
+ loadSmartERP() {
75
+ if (BridgeUtils.host == null) {
76
+ window.location.href = this.settings.webUrl;
77
+ } else {
78
+ BridgeUtils.host.loadApp('core');
79
+ }
78
80
  }
79
81
 
80
82
  /**
@@ -300,10 +302,16 @@ export class ServiceApp<
300
302
 
301
303
  /**
302
304
  * Try login
305
+ * @param data Additional data
306
+ * @param showLoading Show loading bar or not
307
+ * @returns Result
303
308
  */
304
- override async tryLogin<D extends {} = {}>(data?: D) {
309
+ override async tryLogin<D extends {} = {}>(
310
+ data?: D,
311
+ showLoading?: boolean
312
+ ) {
305
313
  // Reset user state
306
- const result = await super.tryLogin(data);
314
+ const result = await super.tryLogin(data, showLoading);
307
315
  if (!result) return false;
308
316
 
309
317
  // Refresh token
@@ -323,6 +331,7 @@ export class ServiceApp<
323
331
  });
324
332
  },
325
333
  data,
334
+ showLoading,
326
335
  relogin: true
327
336
  });
328
337
  }
package/src/index.ts CHANGED
@@ -7,9 +7,9 @@ export * from './app/IServiceUser';
7
7
  export * from './app/ISmartERPUser';
8
8
  export * from './app/Labels';
9
9
  export * from './app/ReactApp';
10
+ export * from './app/ReactUtils';
10
11
  export * from './app/RefreshTokenRQ';
11
12
  export * from './app/ServiceApp';
12
- export * from './app/Utils';
13
13
 
14
14
  // components
15
15
  export * from './components/GridColumn';
@@ -38,6 +38,7 @@ export * from './mu/texts/MoneyText';
38
38
  export * from './mu/texts/NumberText';
39
39
 
40
40
  export * from './mu/AuditDisplay';
41
+ export * from './mu/BackButton';
41
42
  export * from './mu/BridgeCloseButton';
42
43
  export * from './mu/ButtonLink';
43
44
  export * from './mu/ComboBox';
@@ -0,0 +1,53 @@
1
+ import { IconButton, IconButtonProps, useTheme } from '@mui/material';
2
+ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
3
+ import React from 'react';
4
+ import { ReactUtils } from '../app/ReactUtils';
5
+
6
+ /**
7
+ * BackButton props
8
+ */
9
+ export interface BackButtonProps extends IconButtonProps {}
10
+
11
+ /**
12
+ * BackButton
13
+ * @param props Props
14
+ * @returns Component
15
+ */
16
+ export function BackButton(props: BackButtonProps) {
17
+ // Destruct
18
+ const { color = 'primary', size = 'small', onClick, ...rest } = props;
19
+
20
+ // Navigate
21
+ const navigate = ReactUtils.getNavigateFn();
22
+
23
+ // Theme
24
+ const theme = useTheme();
25
+
26
+ // Color
27
+ const pColor =
28
+ color != 'inherit' && color != 'default' && color in theme.palette
29
+ ? theme.palette[color]
30
+ : theme.palette.primary;
31
+
32
+ // Click handler
33
+ const onClickLocal = (event: React.MouseEvent<HTMLButtonElement>) => {
34
+ if (onClick) onClick(event);
35
+ navigate(-1);
36
+ };
37
+
38
+ return (
39
+ <IconButton
40
+ aria-label="Back"
41
+ color={color}
42
+ size={size}
43
+ onClick={onClickLocal}
44
+ sx={{
45
+ backgroundColor: pColor.contrastText,
46
+ border: `1px solid ${pColor.light}`
47
+ }}
48
+ {...rest}
49
+ >
50
+ <ArrowBackIcon />
51
+ </IconButton>
52
+ );
53
+ }
@@ -1,6 +1,6 @@
1
1
  import { BridgeUtils, IBridgeHost } from '@etsoo/appscript';
2
2
  import CloseIcon from '@mui/icons-material/Close';
3
- import { IconButton, IconButtonProps } from '@mui/material';
3
+ import { Box, BoxProps, IconButton, IconButtonProps } from '@mui/material';
4
4
  import React from 'react';
5
5
  import { globalApp } from '../app/ReactApp';
6
6
 
@@ -8,6 +8,11 @@ import { globalApp } from '../app/ReactApp';
8
8
  * Bridge close button props
9
9
  */
10
10
  export interface BridgeCloseButtonProps extends IconButtonProps {
11
+ /**
12
+ * Box props
13
+ */
14
+ boxProps?: BoxProps;
15
+
11
16
  /**
12
17
  * Validate the host
13
18
  * @param host Host
@@ -23,6 +28,7 @@ export interface BridgeCloseButtonProps extends IconButtonProps {
23
28
  export function BridgeCloseButton(props: BridgeCloseButtonProps) {
24
29
  // Destruct
25
30
  const {
31
+ boxProps,
26
32
  onClick,
27
33
  title = typeof globalApp === 'undefined'
28
34
  ? 'Close'
@@ -45,20 +51,15 @@ export function BridgeCloseButton(props: BridgeCloseButtonProps) {
45
51
  };
46
52
 
47
53
  return (
48
- <IconButton
49
- aria-label="close"
50
- color="secondary"
51
- onClick={onClickLocal}
52
- title={title}
53
- sx={{
54
- position: 'absolute',
55
- zIndex: (theme) => theme.zIndex.appBar + 1,
56
- top: (theme) => theme.spacing(0.5),
57
- right: (theme) => theme.spacing(0.5)
58
- }}
59
- {...rest}
60
- >
61
- <CloseIcon />
62
- </IconButton>
54
+ <Box {...boxProps}>
55
+ <IconButton
56
+ aria-label="close"
57
+ onClick={onClickLocal}
58
+ title={title}
59
+ {...rest}
60
+ >
61
+ <CloseIcon />
62
+ </IconButton>
63
+ </Box>
63
64
  );
64
65
  }
@@ -1,6 +1,6 @@
1
1
  import { Button, ButtonProps } from '@mui/material';
2
- import { useNavigate } from '@reach/router';
3
2
  import React from 'react';
3
+ import { ReactUtils } from '../app/ReactUtils';
4
4
 
5
5
  /**
6
6
  * ButtonLink props
@@ -22,7 +22,8 @@ export function ButtonLink(props: ButtonLinkProps) {
22
22
  const { href, ...rest } = props;
23
23
 
24
24
  // Navigate
25
- const navigate = useNavigate();
25
+ const navigate = ReactUtils.getNavigateFn();
26
+
26
27
  const onClick = href.includes('://')
27
28
  ? () => window.open(href, '_blank')
28
29
  : () => navigate(href);
@@ -2,11 +2,11 @@ import { IdLabelDto } from '@etsoo/appscript';
2
2
  import { Keyboard } from '@etsoo/shared';
3
3
  import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
4
4
  import React from 'react';
5
- import { Utils } from '../app/Utils';
6
5
  import { Utils as SharedUtils } from '@etsoo/shared';
7
6
  import { AutocompleteExtendedProps } from './AutocompleteExtendedProps';
8
7
  import { InputField } from './InputField';
9
8
  import { SearchField } from './SearchField';
9
+ import { ReactUtils } from '../app/ReactUtils';
10
10
 
11
11
  /**
12
12
  * ComboBox props
@@ -152,7 +152,7 @@ export function ComboBox<T extends {} = IdLabelDto>(props: ComboBoxProps<T>) {
152
152
 
153
153
  if (newValue !== input.value) {
154
154
  // Different value, trigger change event
155
- Utils.triggerChange(input, newValue, false);
155
+ ReactUtils.triggerChange(input, newValue, false);
156
156
  }
157
157
  }
158
158
  };
@@ -1,6 +1,6 @@
1
1
  import { IconButton, IconButtonProps } from '@mui/material';
2
- import { useNavigate } from '@reach/router';
3
2
  import React from 'react';
3
+ import { ReactUtils } from '../app/ReactUtils';
4
4
 
5
5
  /**
6
6
  * IconButtonLink props
@@ -22,7 +22,7 @@ export function IconButtonLink(props: IconButtonLinkProps) {
22
22
  const { href, ...rest } = props;
23
23
 
24
24
  // Navigate
25
- const navigate = useNavigate();
25
+ const navigate = ReactUtils.getNavigateFn();
26
26
 
27
27
  // Layout
28
28
  return <IconButton {...rest} onClick={() => navigate(href)} />;
@@ -3,7 +3,7 @@ import { Box, Stack, SxProps, Theme } from '@mui/material';
3
3
  import React from 'react';
4
4
  import { ListChildComponentProps } from 'react-window';
5
5
  import { Labels } from '../app/Labels';
6
- import { Utils } from '../app/Utils';
6
+ import { ReactUtils } from '../app/ReactUtils';
7
7
  import { GridColumn } from '../components/GridColumn';
8
8
  import {
9
9
  GridDataGet,
@@ -326,7 +326,7 @@ export function ResponsibleContainer<
326
326
  mRef={mRefs}
327
327
  onClick={(event, data) =>
328
328
  quickAction &&
329
- Utils.isSafeClick(event) &&
329
+ ReactUtils.isSafeClick(event) &&
330
330
  quickAction(data)
331
331
  }
332
332
  oRef={(element) => {
@@ -2,9 +2,9 @@ import { Button, Drawer, IconButton, Stack, useTheme } from '@mui/material';
2
2
  import React from 'react';
3
3
  import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
4
4
  import { useDimensions } from '../uses/useDimensions';
5
- import { Utils as AppUtils } from '../app/Utils';
6
5
  import { DomUtils } from '@etsoo/shared';
7
6
  import { Labels } from '../app/Labels';
7
+ import { ReactUtils } from '../app/ReactUtils';
8
8
 
9
9
  /**
10
10
  * Search bar props
@@ -48,7 +48,7 @@ const resetForm = (form: HTMLFormElement) => {
48
48
 
49
49
  // Ignore readOnly without data-reset=true inputs
50
50
  if (!input.readOnly || input.dataset.reset === 'true') {
51
- AppUtils.triggerChange(input, '', true);
51
+ ReactUtils.triggerChange(input, '', true);
52
52
  }
53
53
  continue;
54
54
  }
@@ -1,4 +1,3 @@
1
- import { Utils as AppUtils } from '../app/Utils';
2
1
  import {
3
2
  Checkbox,
4
3
  FormControl,
@@ -15,6 +14,7 @@ import { MUGlobal } from './MUGlobal';
15
14
  import { IdLabelDto } from '@etsoo/appscript';
16
15
  import { ListItemRightIcon } from './ListItemRightIcon';
17
16
  import { Utils } from '@etsoo/shared';
17
+ import { ReactUtils } from '../app/ReactUtils';
18
18
 
19
19
  /**
20
20
  * Extended select component props
@@ -145,7 +145,7 @@ export function SelectEx<T extends {} = IdLabelDto>(props: SelectExProps<T>) {
145
145
  const input = divRef.current?.querySelector('input');
146
146
  if (input) {
147
147
  // Different value, trigger change event
148
- AppUtils.triggerChange(input, id as string, false);
148
+ ReactUtils.triggerChange(input, id as string, false);
149
149
  }
150
150
  }
151
151
  };
@@ -2,7 +2,7 @@ import { IdLabelDto } from '@etsoo/appscript';
2
2
  import { DataTypes } from '@etsoo/shared';
3
3
  import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
4
4
  import React from 'react';
5
- import { Utils } from '../app/Utils';
5
+ import { ReactUtils } from '../app/ReactUtils';
6
6
  import { AutocompleteExtendedProps } from './AutocompleteExtendedProps';
7
7
  import { InputField } from './InputField';
8
8
  import { SearchField } from './SearchField';
@@ -152,7 +152,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
152
152
 
153
153
  if (input && input.value !== '') {
154
154
  // Different value, trigger change event
155
- Utils.triggerChange(input, '', false);
155
+ ReactUtils.triggerChange(input, '', false);
156
156
  }
157
157
 
158
158
  if (states.options.length > 0) {
@@ -186,7 +186,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
186
186
  const newValue = DataTypes.getStringValue(value, idField) ?? '';
187
187
  if (newValue !== input.value) {
188
188
  // Different value, trigger change event
189
- Utils.triggerChange(input, newValue, false);
189
+ ReactUtils.triggerChange(input, newValue, false);
190
190
  }
191
191
  }
192
192
  };
@@ -8,6 +8,7 @@ import { MoreFab } from '../MoreFab';
8
8
  import { ReactAppStateDetector } from '../../app/ReactApp';
9
9
  import { Container, Fab } from '@mui/material';
10
10
  import RefreshIcon from '@mui/icons-material/Refresh';
11
+ import { BackButton } from '../BackButton';
11
12
 
12
13
  /**
13
14
  * Default scroll container
@@ -34,6 +35,7 @@ export function CommonPage(props: CommonPageProps) {
34
35
  onUpdateAll,
35
36
  paddings = MUGlobal.pagePaddings,
36
37
  scrollContainer,
38
+ supportBack = false,
37
39
  targetFields,
38
40
  sx = {},
39
41
  ...rest
@@ -115,6 +117,9 @@ export function CommonPage(props: CommonPageProps) {
115
117
  title={labels.more}
116
118
  actions={moreActions}
117
119
  />
120
+ {supportBack && (
121
+ <BackButton title={labels.back} size={fabSize} />
122
+ )}
118
123
  </FabBox>
119
124
  {children}
120
125
  </Container>
@@ -20,7 +20,7 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
20
20
  fabSize?: CustomFabSize;
21
21
 
22
22
  /**
23
- * Fab flex column direction?
23
+ * Fab flex column direction, undefined to hide it
24
24
  */
25
25
  fabColumnDirection?: boolean;
26
26
 
@@ -59,6 +59,11 @@ export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
59
59
  */
60
60
  scrollContainer?: HTMLElement | object;
61
61
 
62
+ /**
63
+ * Support back click
64
+ */
65
+ supportBack?: boolean;
66
+
62
67
  /**
63
68
  * State last changed fields
64
69
  */
@@ -6,6 +6,7 @@ import { CommonPage, CommonPageScrollContainer } from './CommonPage';
6
6
  import { CommonPageProps } from './CommonPageProps';
7
7
  import SaveIcon from '@mui/icons-material/Save';
8
8
  import DeleteIcon from '@mui/icons-material/Delete';
9
+ import { BackButton } from '../BackButton';
9
10
 
10
11
  /**
11
12
  * Add / Edit page props
@@ -25,6 +26,12 @@ export interface EditPageProps extends Omit<CommonPageProps, 'onSubmit'> {
25
26
  * On delete callback
26
27
  */
27
28
  onDelete?: () => Promise<void> | void;
29
+
30
+ /**
31
+ * Support back click
32
+ * @default true
33
+ */
34
+ supportBack?: boolean;
28
35
  }
29
36
 
30
37
  /**
@@ -40,6 +47,7 @@ export function EditPage(props: EditPageProps) {
40
47
  onSubmit,
41
48
  paddings = MUGlobal.pagePaddings,
42
49
  scrollContainer = CommonPageScrollContainer,
50
+ supportBack = true,
43
51
  ...rest
44
52
  } = props;
45
53
 
@@ -91,6 +99,7 @@ export function EditPage(props: EditPageProps) {
91
99
  >
92
100
  {labels.save}
93
101
  </Button>
102
+ {supportBack && <BackButton title={labels.back} />}
94
103
  </Grid>
95
104
  </form>
96
105
  </CommonPage>