@etsoo/react 1.5.14 → 1.5.15

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.
@@ -108,19 +108,6 @@ export declare class ReactApp<S extends IAppSettings, D extends IUser, P extends
108
108
  * @param name Application name
109
109
  */
110
110
  constructor(settings: S, name: string);
111
- /**
112
- * Get parsed Url under bridge host
113
- * @param url Url
114
- * @returns Parsed Url
115
- */
116
- protected getHostUrl(url: string): string;
117
- /**
118
- * Get parsed Url under bridge host
119
- * @param url Url
120
- * @param name App name in the host environment
121
- * @returns Parsed Url
122
- */
123
- protected getHostUrlBase(url: string, name: string): string;
124
111
  /**
125
112
  * Override alert action result
126
113
  * @param result Action result
@@ -66,9 +66,9 @@ export class ReactApp extends CoreApp {
66
66
  */
67
67
  this.userState = new UserState();
68
68
  this.history =
69
- window.location.hostname === ''
70
- ? Utils.getMemoryHistory(this.getHostUrl(window.location.href))
71
- : undefined;
69
+ BridgeUtils.host == null
70
+ ? undefined
71
+ : Utils.getMemoryHistory(BridgeUtils.host.getStartUrl());
72
72
  this.cultureState = new CultureState(settings.currentCulture);
73
73
  this.pageState = new PageState();
74
74
  globalApp = this;
@@ -91,31 +91,6 @@ export class ReactApp extends CoreApp {
91
91
  ReactApp._notifierProvider = NotifierMU.setup();
92
92
  return NotifierMU.instance;
93
93
  }
94
- /**
95
- * Get parsed Url under bridge host
96
- * @param url Url
97
- * @returns Parsed Url
98
- */
99
- getHostUrl(url) {
100
- return this.getHostUrlBase(url, 'core');
101
- }
102
- /**
103
- * Get parsed Url under bridge host
104
- * @param url Url
105
- * @param name App name in the host environment
106
- * @returns Parsed Url
107
- */
108
- getHostUrlBase(url, name) {
109
- if (url.startsWith('/'))
110
- return url;
111
- const identifier = `/${name}/`;
112
- const pos = url.indexOf(identifier);
113
- if (pos === -1)
114
- return '/';
115
- return url
116
- .substring(pos + identifier.length - 1)
117
- .replace('/index.html', '/'); // Router take / as start
118
- }
119
94
  /**
120
95
  * Override alert action result
121
96
  * @param result Action result
@@ -33,11 +33,9 @@ export declare class ServiceApp<U extends IServiceUser = IServiceUser, P extends
33
33
  */
34
34
  constructor(settings: S, name: string);
35
35
  /**
36
- * Get parsed Url under bridge host
37
- * @param url Url
38
- * @returns Parsed Url
36
+ * Load SmartERP core
39
37
  */
40
- protected getHostUrl(url: string): string;
38
+ loadSmartERP(): void;
41
39
  /**
42
40
  * Go to the login page
43
41
  * @param tryLogin Try to login again
@@ -40,12 +40,15 @@ export class ServiceApp extends ReactApp {
40
40
  this._serviceUser = value;
41
41
  }
42
42
  /**
43
- * Get parsed Url under bridge host
44
- * @param url Url
45
- * @returns Parsed Url
43
+ * Load SmartERP core
46
44
  */
47
- getHostUrl(url) {
48
- return this.getHostUrlBase(url, 's' + this.settings.serviceId);
45
+ loadSmartERP() {
46
+ if (BridgeUtils.host == null) {
47
+ window.location.href = this.settings.webUrl;
48
+ }
49
+ else {
50
+ BridgeUtils.host.loadApp('core');
51
+ }
49
52
  }
50
53
  /**
51
54
  * Go to the login page
@@ -15,7 +15,7 @@ export declare namespace Utils {
15
15
  * @param initialPath Initial path
16
16
  * @returns History
17
17
  */
18
- function getMemoryHistory(initialPath?: string): History;
18
+ function getMemoryHistory(initialPath?: string | null): History;
19
19
  /**
20
20
  * Is safe click
21
21
  * @param event Mouse event
package/lib/app/Utils.js CHANGED
@@ -29,9 +29,9 @@ export var Utils;
29
29
  * @param initialPath Initial path
30
30
  * @returns History
31
31
  */
32
- function getMemoryHistory(initialPath = '/') {
32
+ function getMemoryHistory(initialPath) {
33
33
  if (memoryHistory == null) {
34
- memoryHistory = createHistory(createMemorySource(initialPath));
34
+ memoryHistory = createHistory(createMemorySource(initialPath !== null && initialPath !== void 0 ? initialPath : '/'));
35
35
  }
36
36
  return memoryHistory;
37
37
  }
@@ -1,4 +1,4 @@
1
- import { IconButton } from '@mui/material';
1
+ import { IconButton, useTheme } from '@mui/material';
2
2
  import ArrowBackIcon from '@mui/icons-material/ArrowBack';
3
3
  import React from 'react';
4
4
  import { useNavigate } from '@reach/router';
@@ -12,6 +12,12 @@ export function BackButton(props) {
12
12
  const { color = 'primary', size = 'small', onClick, ...rest } = props;
13
13
  // Navigate
14
14
  const navigate = useNavigate();
15
+ // Theme
16
+ const theme = useTheme();
17
+ // Color
18
+ const pColor = color != 'inherit' && color != 'default' && color in theme.palette
19
+ ? theme.palette[color]
20
+ : theme.palette.primary;
15
21
  // Click handler
16
22
  const onClickLocal = (event) => {
17
23
  if (onClick)
@@ -19,11 +25,8 @@ export function BackButton(props) {
19
25
  navigate(-1);
20
26
  };
21
27
  return (React.createElement(IconButton, { "aria-label": "Back", color: color, size: size, onClick: onClickLocal, sx: {
22
- border: (theme) => `1px solid ${(() => color != 'inherit' &&
23
- color != 'default' &&
24
- color in theme.palette
25
- ? theme.palette[color]
26
- : theme.palette.primary)().light}`
28
+ backgroundColor: pColor.contrastText,
29
+ border: `1px solid ${pColor.light}`
27
30
  }, ...rest },
28
31
  React.createElement(ArrowBackIcon, null)));
29
32
  }
@@ -48,6 +48,10 @@ export interface ViewPageProps<T extends {}> extends Exclude<CommonPageProps, 'c
48
48
  * Load data
49
49
  */
50
50
  loadData: () => PromiseLike<T | undefined>;
51
+ /**
52
+ * Pull to refresh data
53
+ */
54
+ pullToRefresh?: boolean;
51
55
  /**
52
56
  * Support refresh
53
57
  */
@@ -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, fabColumnDirection = true, supportBack = 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();
@@ -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.14",
3
+ "version": "1.5.15",
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.49",
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",
@@ -219,43 +219,18 @@ export class ReactApp<
219
219
  new WindowStorage(),
220
220
  name
221
221
  );
222
+
222
223
  this.history =
223
- window.location.hostname === ''
224
- ? Utils.getMemoryHistory(this.getHostUrl(window.location.href))
225
- : undefined;
224
+ BridgeUtils.host == null
225
+ ? undefined
226
+ : Utils.getMemoryHistory(BridgeUtils.host.getStartUrl());
227
+
226
228
  this.cultureState = new CultureState(settings.currentCulture);
227
229
  this.pageState = new PageState<P>();
228
230
 
229
231
  globalApp = this;
230
232
  }
231
233
 
232
- /**
233
- * Get parsed Url under bridge host
234
- * @param url Url
235
- * @returns Parsed Url
236
- */
237
- protected getHostUrl(url: string) {
238
- return this.getHostUrlBase(url, 'core');
239
- }
240
-
241
- /**
242
- * Get parsed Url under bridge host
243
- * @param url Url
244
- * @param name App name in the host environment
245
- * @returns Parsed Url
246
- */
247
- protected getHostUrlBase(url: string, name: string) {
248
- if (url.startsWith('/')) return url;
249
-
250
- const identifier = `/${name}/`;
251
- const pos = url.indexOf(identifier);
252
- if (pos === -1) return '/';
253
-
254
- return url
255
- .substring(pos + identifier.length - 1)
256
- .replace('/index.html', '/'); // Router take / as start
257
- }
258
-
259
234
  /**
260
235
  * Override alert action result
261
236
  * @param result Action result
@@ -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
  /**
package/src/app/Utils.ts CHANGED
@@ -31,9 +31,11 @@ export namespace Utils {
31
31
  * @param initialPath Initial path
32
32
  * @returns History
33
33
  */
34
- export function getMemoryHistory(initialPath: string = '/') {
34
+ export function getMemoryHistory(initialPath?: string | null) {
35
35
  if (memoryHistory == null) {
36
- memoryHistory = createHistory(createMemorySource(initialPath));
36
+ memoryHistory = createHistory(
37
+ createMemorySource(initialPath ?? '/')
38
+ );
37
39
  }
38
40
  return memoryHistory;
39
41
  }
@@ -1,4 +1,4 @@
1
- import { IconButton, IconButtonProps } from '@mui/material';
1
+ import { IconButton, IconButtonProps, useTheme } from '@mui/material';
2
2
  import ArrowBackIcon from '@mui/icons-material/ArrowBack';
3
3
  import React from 'react';
4
4
  import { useNavigate } from '@reach/router';
@@ -20,6 +20,15 @@ export function BackButton(props: BackButtonProps) {
20
20
  // Navigate
21
21
  const navigate = useNavigate();
22
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
+
23
32
  // Click handler
24
33
  const onClickLocal = (event: React.MouseEvent<HTMLButtonElement>) => {
25
34
  if (onClick) onClick(event);
@@ -33,15 +42,8 @@ export function BackButton(props: BackButtonProps) {
33
42
  size={size}
34
43
  onClick={onClickLocal}
35
44
  sx={{
36
- border: (theme) =>
37
- `1px solid ${
38
- (() =>
39
- color != 'inherit' &&
40
- color != 'default' &&
41
- color in theme.palette
42
- ? theme.palette[color]
43
- : theme.palette.primary)().light
44
- }`
45
+ backgroundColor: pColor.contrastText,
46
+ border: `1px solid ${pColor.light}`
45
47
  }}
46
48
  {...rest}
47
49
  >
@@ -7,6 +7,7 @@ import {
7
7
  Typography
8
8
  } from '@mui/material';
9
9
  import React from 'react';
10
+ import { Labels } from '../../app/Labels';
10
11
  import { globalApp } from '../../app/ReactApp';
11
12
  import {
12
13
  GridColumnRenderProps,
@@ -14,6 +15,7 @@ import {
14
15
  } from '../../components/GridColumn';
15
16
  import { GridDataFormat } from '../GridDataFormat';
16
17
  import { MUGlobal } from '../MUGlobal';
18
+ import { PullToRefreshUI } from '../PullToRefreshUI';
17
19
  import { CommonPage } from './CommonPage';
18
20
  import { CommonPageProps } from './CommonPageProps';
19
21
 
@@ -81,6 +83,11 @@ export interface ViewPageProps<T extends {}>
81
83
  */
82
84
  loadData: () => PromiseLike<T | undefined>;
83
85
 
86
+ /**
87
+ * Pull to refresh data
88
+ */
89
+ pullToRefresh?: boolean;
90
+
84
91
  /**
85
92
  * Support refresh
86
93
  */
@@ -167,12 +174,19 @@ export function ViewPage<T extends {}>(props: ViewPageProps<T>) {
167
174
  supportRefresh = true,
168
175
  fabColumnDirection = true,
169
176
  supportBack = true,
177
+ pullToRefresh = true,
170
178
  ...rest
171
179
  } = props;
172
180
 
173
181
  // Data
174
182
  const [data, setData] = React.useState<T>();
175
183
 
184
+ // Labels
185
+ const labels = Labels.CommonPage;
186
+
187
+ // Container
188
+ const pullContainer = '#page-container';
189
+
176
190
  // Load data
177
191
  const refresh = async () => {
178
192
  const result = await loadData();
@@ -245,6 +259,23 @@ export function ViewPage<T extends {}>(props: ViewPageProps<T>) {
245
259
  </Stack>
246
260
  )}
247
261
  {Utils.getResult(children, data, refresh)}
262
+ {pullToRefresh && (
263
+ <PullToRefreshUI
264
+ mainElement={pullContainer}
265
+ triggerElement={pullContainer}
266
+ instructionsPullToRefresh={labels.pullToRefresh}
267
+ instructionsReleaseToRefresh={
268
+ labels.releaseToRefresh
269
+ }
270
+ instructionsRefreshing={labels.refreshing}
271
+ onRefresh={refresh}
272
+ shouldPullToRefresh={() => {
273
+ const container =
274
+ document.querySelector(pullContainer);
275
+ return !container?.scrollTop;
276
+ }}
277
+ />
278
+ )}
248
279
  </React.Fragment>
249
280
  )}
250
281
  </CommonPage>