@etsoo/react 1.5.13 → 1.5.17
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.d.ts +0 -13
- package/lib/app/ReactApp.js +6 -31
- package/lib/app/{Utils.d.ts → ReactUtils.d.ts} +7 -2
- package/lib/app/{Utils.js → ReactUtils.js} +20 -10
- package/lib/app/ServiceApp.d.ts +6 -5
- package/lib/app/ServiceApp.js +14 -7
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/mu/BackButton.js +18 -11
- package/lib/mu/ButtonLink.js +2 -2
- package/lib/mu/ComboBox.js +2 -2
- package/lib/mu/IconButtonLink.js +2 -2
- package/lib/mu/ResponsibleContainer.js +2 -2
- package/lib/mu/SearchBar.js +2 -2
- package/lib/mu/SelectEx.js +2 -2
- package/lib/mu/Tiplist.js +3 -3
- package/lib/mu/pages/ViewPage.d.ts +4 -0
- package/lib/mu/pages/ViewPage.js +12 -2
- package/package.json +2 -2
- package/src/app/ReactApp.ts +9 -33
- package/src/app/{Utils.ts → ReactUtils.ts} +20 -4
- package/src/app/ServiceApp.ts +16 -7
- package/src/index.ts +1 -1
- package/src/mu/BackButton.tsx +23 -15
- package/src/mu/ButtonLink.tsx +3 -2
- package/src/mu/ComboBox.tsx +2 -2
- package/src/mu/IconButtonLink.tsx +2 -2
- package/src/mu/ResponsibleContainer.tsx +2 -2
- package/src/mu/SearchBar.tsx +2 -2
- package/src/mu/SelectEx.tsx +2 -2
- package/src/mu/Tiplist.tsx +3 -3
- package/src/mu/pages/ViewPage.tsx +31 -0
package/lib/app/ReactApp.d.ts
CHANGED
|
@@ -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
|
package/lib/app/ReactApp.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ActionResultError, BridgeUtils, CoreApp, createClient } from '@etsoo/appscript';
|
|
2
2
|
import { WindowStorage } from '@etsoo/shared';
|
|
3
|
-
import { navigate } from '@reach/router';
|
|
4
3
|
import React from 'react';
|
|
5
4
|
import { NotifierMU } from '../mu/NotifierMU';
|
|
6
5
|
import { ProgressCount } from '../mu/ProgressCount';
|
|
@@ -8,7 +7,7 @@ import { CultureState } from '../states/CultureState';
|
|
|
8
7
|
import { PageActionType, PageState } from '../states/PageState';
|
|
9
8
|
import { UserActionType, UserState } from '../states/UserState';
|
|
10
9
|
import { Labels } from './Labels';
|
|
11
|
-
import {
|
|
10
|
+
import { ReactUtils } from './ReactUtils';
|
|
12
11
|
/**
|
|
13
12
|
* Global application
|
|
14
13
|
*/
|
|
@@ -66,9 +65,9 @@ export class ReactApp extends CoreApp {
|
|
|
66
65
|
*/
|
|
67
66
|
this.userState = new UserState();
|
|
68
67
|
this.history =
|
|
69
|
-
|
|
70
|
-
?
|
|
71
|
-
:
|
|
68
|
+
BridgeUtils.host == null
|
|
69
|
+
? undefined
|
|
70
|
+
: ReactUtils.getMemoryHistory(BridgeUtils.host.getStartUrl());
|
|
72
71
|
this.cultureState = new CultureState(settings.currentCulture);
|
|
73
72
|
this.pageState = new PageState();
|
|
74
73
|
globalApp = this;
|
|
@@ -91,31 +90,6 @@ export class ReactApp extends CoreApp {
|
|
|
91
90
|
ReactApp._notifierProvider = NotifierMU.setup();
|
|
92
91
|
return NotifierMU.instance;
|
|
93
92
|
}
|
|
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
93
|
/**
|
|
120
94
|
* Override alert action result
|
|
121
95
|
* @param result Action result
|
|
@@ -224,7 +198,8 @@ export class ReactApp extends CoreApp {
|
|
|
224
198
|
* @param url Url
|
|
225
199
|
*/
|
|
226
200
|
redirectTo(url) {
|
|
227
|
-
|
|
201
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
202
|
+
navigate(url);
|
|
228
203
|
}
|
|
229
204
|
/**
|
|
230
205
|
* Set page data
|
|
@@ -3,7 +3,7 @@ import React from 'react';
|
|
|
3
3
|
/**
|
|
4
4
|
* React utils
|
|
5
5
|
*/
|
|
6
|
-
export declare namespace
|
|
6
|
+
export declare namespace ReactUtils {
|
|
7
7
|
/**
|
|
8
8
|
* Format input value
|
|
9
9
|
* @param value Input value
|
|
@@ -15,7 +15,12 @@ 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
|
+
/**
|
|
20
|
+
* Get navigate function, works with memory history
|
|
21
|
+
* @returns NavigateFn
|
|
22
|
+
*/
|
|
23
|
+
function getNavigateFn(): import("@reach/router").NavigateFn;
|
|
19
24
|
/**
|
|
20
25
|
* Is safe click
|
|
21
26
|
* @param event Mouse event
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createHistory, createMemorySource } from '@reach/router';
|
|
1
|
+
import { createHistory, createMemorySource, navigate } from '@reach/router';
|
|
2
2
|
/**
|
|
3
3
|
* React utils
|
|
4
4
|
*/
|
|
5
|
-
export var
|
|
6
|
-
(function (
|
|
5
|
+
export var ReactUtils;
|
|
6
|
+
(function (ReactUtils) {
|
|
7
7
|
// Memory history
|
|
8
8
|
// https://github.com/reach/router/issues/225
|
|
9
9
|
let memoryHistory;
|
|
@@ -23,19 +23,29 @@ export var Utils;
|
|
|
23
23
|
return value;
|
|
24
24
|
return String(value);
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
ReactUtils.formatInputValue = formatInputValue;
|
|
27
27
|
/**
|
|
28
28
|
* Get memory history
|
|
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
|
}
|
|
38
|
-
|
|
38
|
+
ReactUtils.getMemoryHistory = getMemoryHistory;
|
|
39
|
+
/**
|
|
40
|
+
* Get navigate function, works with memory history
|
|
41
|
+
* @returns NavigateFn
|
|
42
|
+
*/
|
|
43
|
+
function getNavigateFn() {
|
|
44
|
+
if (memoryHistory == null)
|
|
45
|
+
return navigate;
|
|
46
|
+
return memoryHistory.navigate;
|
|
47
|
+
}
|
|
48
|
+
ReactUtils.getNavigateFn = getNavigateFn;
|
|
39
49
|
/**
|
|
40
50
|
* Is safe click
|
|
41
51
|
* @param event Mouse event
|
|
@@ -61,7 +71,7 @@ export var Utils;
|
|
|
61
71
|
}
|
|
62
72
|
return true;
|
|
63
73
|
}
|
|
64
|
-
|
|
74
|
+
ReactUtils.isSafeClick = isSafeClick;
|
|
65
75
|
/**
|
|
66
76
|
* Trigger input change event
|
|
67
77
|
* @param input Form input
|
|
@@ -99,5 +109,5 @@ export var Utils;
|
|
|
99
109
|
input.dispatchEvent(inputEvent);
|
|
100
110
|
}
|
|
101
111
|
}
|
|
102
|
-
|
|
103
|
-
})(
|
|
112
|
+
ReactUtils.triggerChange = triggerChange;
|
|
113
|
+
})(ReactUtils || (ReactUtils = {}));
|
package/lib/app/ServiceApp.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
37
|
-
* @param url Url
|
|
38
|
-
* @returns Parsed Url
|
|
36
|
+
* Load SmartERP core
|
|
39
37
|
*/
|
|
40
|
-
|
|
38
|
+
loadSmartERP(): void;
|
|
41
39
|
/**
|
|
42
40
|
* Go to the login page
|
|
43
41
|
* @param tryLogin Try to login again
|
|
@@ -66,8 +64,11 @@ export declare class ServiceApp<U extends IServiceUser = IServiceUser, P extends
|
|
|
66
64
|
serviceEncrypt(message: string, passphrase?: string, iterations?: number): string;
|
|
67
65
|
/**
|
|
68
66
|
* Try login
|
|
67
|
+
* @param data Additional data
|
|
68
|
+
* @param showLoading Show loading bar or not
|
|
69
|
+
* @returns Result
|
|
69
70
|
*/
|
|
70
|
-
tryLogin<D extends {} = {}>(data?: D): Promise<boolean>;
|
|
71
|
+
tryLogin<D extends {} = {}>(data?: D, showLoading?: boolean): Promise<boolean>;
|
|
71
72
|
/**
|
|
72
73
|
* User login extended
|
|
73
74
|
* @param user Core system user
|
package/lib/app/ServiceApp.js
CHANGED
|
@@ -40,12 +40,15 @@ export class ServiceApp extends ReactApp {
|
|
|
40
40
|
this._serviceUser = value;
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
|
-
* @param url Url
|
|
45
|
-
* @returns Parsed Url
|
|
43
|
+
* Load SmartERP core
|
|
46
44
|
*/
|
|
47
|
-
|
|
48
|
-
|
|
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
|
|
@@ -206,10 +209,13 @@ export class ServiceApp extends ReactApp {
|
|
|
206
209
|
}
|
|
207
210
|
/**
|
|
208
211
|
* Try login
|
|
212
|
+
* @param data Additional data
|
|
213
|
+
* @param showLoading Show loading bar or not
|
|
214
|
+
* @returns Result
|
|
209
215
|
*/
|
|
210
|
-
async tryLogin(data) {
|
|
216
|
+
async tryLogin(data, showLoading) {
|
|
211
217
|
// Reset user state
|
|
212
|
-
const result = await super.tryLogin(data);
|
|
218
|
+
const result = await super.tryLogin(data, showLoading);
|
|
213
219
|
if (!result)
|
|
214
220
|
return false;
|
|
215
221
|
// Refresh token
|
|
@@ -228,6 +234,7 @@ export class ServiceApp extends ReactApp {
|
|
|
228
234
|
});
|
|
229
235
|
},
|
|
230
236
|
data,
|
|
237
|
+
showLoading,
|
|
231
238
|
relogin: true
|
|
232
239
|
});
|
|
233
240
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ export * from './app/IServiceUser';
|
|
|
6
6
|
export * from './app/ISmartERPUser';
|
|
7
7
|
export * from './app/Labels';
|
|
8
8
|
export * from './app/ReactApp';
|
|
9
|
+
export * from './app/ReactUtils';
|
|
9
10
|
export * from './app/RefreshTokenRQ';
|
|
10
11
|
export * from './app/ServiceApp';
|
|
11
|
-
export * from './app/Utils';
|
|
12
12
|
export * from './components/GridColumn';
|
|
13
13
|
export * from './components/GridLoader';
|
|
14
14
|
export * from './components/ListItemReact';
|
package/lib/index.js
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
|
// components
|
|
14
14
|
export * from './components/GridColumn';
|
|
15
15
|
export * from './components/GridLoader';
|
package/lib/mu/BackButton.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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
|
-
import {
|
|
4
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
5
5
|
/**
|
|
6
6
|
* BackButton
|
|
7
7
|
* @param props Props
|
|
@@ -10,20 +10,27 @@ import { useNavigate } from '@reach/router';
|
|
|
10
10
|
export function BackButton(props) {
|
|
11
11
|
// Destruct
|
|
12
12
|
const { color = 'primary', size = 'small', onClick, ...rest } = props;
|
|
13
|
-
//
|
|
14
|
-
const
|
|
13
|
+
// Theme
|
|
14
|
+
const theme = useTheme();
|
|
15
|
+
// Color
|
|
16
|
+
const pColor = color != 'inherit' && color != 'default' && color in theme.palette
|
|
17
|
+
? theme.palette[color]
|
|
18
|
+
: theme.palette.primary;
|
|
15
19
|
// Click handler
|
|
16
|
-
const onClickLocal = (event) => {
|
|
20
|
+
const onClickLocal = async (event) => {
|
|
17
21
|
if (onClick)
|
|
18
22
|
onClick(event);
|
|
19
|
-
|
|
23
|
+
// Navigate
|
|
24
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
25
|
+
await navigate(-1);
|
|
26
|
+
const history = ReactUtils.getMemoryHistory();
|
|
27
|
+
if (history) {
|
|
28
|
+
console.log(history);
|
|
29
|
+
}
|
|
20
30
|
};
|
|
21
31
|
return (React.createElement(IconButton, { "aria-label": "Back", color: color, size: size, onClick: onClickLocal, sx: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
color in theme.palette
|
|
25
|
-
? theme.palette[color]
|
|
26
|
-
: theme.palette.primary)().light}`
|
|
32
|
+
backgroundColor: pColor.contrastText,
|
|
33
|
+
border: `1px solid ${pColor.light}`
|
|
27
34
|
}, ...rest },
|
|
28
35
|
React.createElement(ArrowBackIcon, null)));
|
|
29
36
|
}
|
package/lib/mu/ButtonLink.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Button } 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
|
* ButtonLink
|
|
6
6
|
* @param props Props
|
|
@@ -10,7 +10,7 @@ export function ButtonLink(props) {
|
|
|
10
10
|
// Destruct
|
|
11
11
|
const { href, ...rest } = props;
|
|
12
12
|
// Navigate
|
|
13
|
-
const navigate =
|
|
13
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
14
14
|
const onClick = href.includes('://')
|
|
15
15
|
? () => window.open(href, '_blank')
|
|
16
16
|
: () => navigate(href);
|
package/lib/mu/ComboBox.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Keyboard } from '@etsoo/shared';
|
|
2
2
|
import { Autocomplete } from '@mui/material';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { Utils } from '../app/Utils';
|
|
5
4
|
import { Utils as SharedUtils } from '@etsoo/shared';
|
|
6
5
|
import { InputField } from './InputField';
|
|
7
6
|
import { SearchField } from './SearchField';
|
|
7
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
8
8
|
/**
|
|
9
9
|
* ComboBox
|
|
10
10
|
* @param props Props
|
|
@@ -71,7 +71,7 @@ export function ComboBox(props) {
|
|
|
71
71
|
const newValue = value != null ? `${Reflect.get(value, idField)}` : '';
|
|
72
72
|
if (newValue !== input.value) {
|
|
73
73
|
// Different value, trigger change event
|
|
74
|
-
|
|
74
|
+
ReactUtils.triggerChange(input, newValue, false);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
};
|
package/lib/mu/IconButtonLink.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IconButton } 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
|
* IconButtonLink
|
|
6
6
|
* @param props Props
|
|
@@ -10,7 +10,7 @@ export function IconButtonLink(props) {
|
|
|
10
10
|
// Destruct
|
|
11
11
|
const { href, ...rest } = props;
|
|
12
12
|
// Navigate
|
|
13
|
-
const navigate =
|
|
13
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
14
14
|
// Layout
|
|
15
15
|
return React.createElement(IconButton, { ...rest, onClick: () => navigate(href) });
|
|
16
16
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, Stack } from '@mui/material';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Labels } from '../app/Labels';
|
|
4
|
-
import {
|
|
4
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
5
5
|
import { GridDataGet } from '../components/GridLoader';
|
|
6
6
|
import useCombinedRefs from '../uses/useCombinedRefs';
|
|
7
7
|
import { useDimensions } from '../uses/useDimensions';
|
|
@@ -126,7 +126,7 @@ export function ResponsibleContainer(props) {
|
|
|
126
126
|
return [
|
|
127
127
|
React.createElement(Box, { className: "ListBox", sx: { height: heightLocal } },
|
|
128
128
|
React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction &&
|
|
129
|
-
|
|
129
|
+
ReactUtils.isSafeClick(event) &&
|
|
130
130
|
quickAction(data), oRef: (element) => {
|
|
131
131
|
if (element != null && elementReady)
|
|
132
132
|
elementReady(element, false);
|
package/lib/mu/SearchBar.js
CHANGED
|
@@ -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
|
// Cached width attribute name
|
|
9
9
|
const cachedWidthName = 'data-cached-width';
|
|
10
10
|
// Reset form
|
|
@@ -20,7 +20,7 @@ const resetForm = (form) => {
|
|
|
20
20
|
continue;
|
|
21
21
|
// Ignore readOnly without data-reset=true inputs
|
|
22
22
|
if (!input.readOnly || input.dataset.reset === 'true') {
|
|
23
|
-
|
|
23
|
+
ReactUtils.triggerChange(input, '', true);
|
|
24
24
|
}
|
|
25
25
|
continue;
|
|
26
26
|
}
|
package/lib/mu/SelectEx.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { Utils as AppUtils } from '../app/Utils';
|
|
2
1
|
import { Checkbox, FormControl, InputLabel, ListItemText, MenuItem, OutlinedInput, Select } from '@mui/material';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import { MUGlobal } from './MUGlobal';
|
|
5
4
|
import { ListItemRightIcon } from './ListItemRightIcon';
|
|
6
5
|
import { Utils } from '@etsoo/shared';
|
|
6
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
7
7
|
/**
|
|
8
8
|
* Extended select component
|
|
9
9
|
* @param props Props
|
|
@@ -65,7 +65,7 @@ export function SelectEx(props) {
|
|
|
65
65
|
const input = (_a = divRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('input');
|
|
66
66
|
if (input) {
|
|
67
67
|
// Different value, trigger change event
|
|
68
|
-
|
|
68
|
+
ReactUtils.triggerChange(input, id, false);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
};
|
package/lib/mu/Tiplist.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DataTypes } from '@etsoo/shared';
|
|
2
2
|
import { Autocomplete } from '@mui/material';
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
5
5
|
import { InputField } from './InputField';
|
|
6
6
|
import { SearchField } from './SearchField';
|
|
7
7
|
/**
|
|
@@ -75,7 +75,7 @@ export function Tiplist(props) {
|
|
|
75
75
|
const input = inputRef.current;
|
|
76
76
|
if (input && input.value !== '') {
|
|
77
77
|
// Different value, trigger change event
|
|
78
|
-
|
|
78
|
+
ReactUtils.triggerChange(input, '', false);
|
|
79
79
|
}
|
|
80
80
|
if (states.options.length > 0) {
|
|
81
81
|
// Reset options
|
|
@@ -106,7 +106,7 @@ export function Tiplist(props) {
|
|
|
106
106
|
const newValue = (_a = DataTypes.getStringValue(value, idField)) !== null && _a !== void 0 ? _a : '';
|
|
107
107
|
if (newValue !== input.value) {
|
|
108
108
|
// Different value, trigger change event
|
|
109
|
-
|
|
109
|
+
ReactUtils.triggerChange(input, newValue, false);
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
};
|
package/lib/mu/pages/ViewPage.js
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "1.5.17",
|
|
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.
|
|
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/ReactApp.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
NotificationReturn
|
|
15
15
|
} from '@etsoo/notificationbase';
|
|
16
16
|
import { DataTypes, WindowStorage } from '@etsoo/shared';
|
|
17
|
-
import { History
|
|
17
|
+
import { History } from '@reach/router';
|
|
18
18
|
import React from 'react';
|
|
19
19
|
import { NotifierMU } from '../mu/NotifierMU';
|
|
20
20
|
import { ProgressCount } from '../mu/ProgressCount';
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
} from '../states/UserState';
|
|
36
36
|
import { InputDialogProps } from './InputDialogProps';
|
|
37
37
|
import { Labels } from './Labels';
|
|
38
|
-
import {
|
|
38
|
+
import { ReactUtils } from './ReactUtils';
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Global application
|
|
@@ -219,43 +219,18 @@ export class ReactApp<
|
|
|
219
219
|
new WindowStorage(),
|
|
220
220
|
name
|
|
221
221
|
);
|
|
222
|
+
|
|
222
223
|
this.history =
|
|
223
|
-
|
|
224
|
-
?
|
|
225
|
-
:
|
|
224
|
+
BridgeUtils.host == null
|
|
225
|
+
? undefined
|
|
226
|
+
: ReactUtils.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
|
|
@@ -395,7 +370,8 @@ export class ReactApp<
|
|
|
395
370
|
* @param url Url
|
|
396
371
|
*/
|
|
397
372
|
override redirectTo(url: string) {
|
|
398
|
-
|
|
373
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
374
|
+
navigate(url);
|
|
399
375
|
}
|
|
400
376
|
|
|
401
377
|
/**
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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
|
|
39
|
+
export function getMemoryHistory(initialPath?: string | null) {
|
|
35
40
|
if (memoryHistory == null) {
|
|
36
|
-
memoryHistory = createHistory(
|
|
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
|
package/src/app/ServiceApp.ts
CHANGED
|
@@ -69,12 +69,14 @@ export class ServiceApp<
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
*
|
|
73
|
-
* @param url Url
|
|
74
|
-
* @returns Parsed Url
|
|
72
|
+
* Load SmartERP core
|
|
75
73
|
*/
|
|
76
|
-
|
|
77
|
-
|
|
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 {} = {}>(
|
|
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';
|
package/src/mu/BackButton.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
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
|
-
import {
|
|
4
|
+
import { ReactUtils } from '../app/ReactUtils';
|
|
5
|
+
import { BridgeUtils } from '@etsoo/appscript';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* BackButton props
|
|
@@ -17,13 +18,27 @@ export function BackButton(props: BackButtonProps) {
|
|
|
17
18
|
// Destruct
|
|
18
19
|
const { color = 'primary', size = 'small', onClick, ...rest } = props;
|
|
19
20
|
|
|
20
|
-
//
|
|
21
|
-
const
|
|
21
|
+
// Theme
|
|
22
|
+
const theme = useTheme();
|
|
23
|
+
|
|
24
|
+
// Color
|
|
25
|
+
const pColor =
|
|
26
|
+
color != 'inherit' && color != 'default' && color in theme.palette
|
|
27
|
+
? theme.palette[color]
|
|
28
|
+
: theme.palette.primary;
|
|
22
29
|
|
|
23
30
|
// Click handler
|
|
24
|
-
const onClickLocal = (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
31
|
+
const onClickLocal = async (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
25
32
|
if (onClick) onClick(event);
|
|
26
|
-
|
|
33
|
+
|
|
34
|
+
// Navigate
|
|
35
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
36
|
+
await navigate(-1);
|
|
37
|
+
|
|
38
|
+
const history = ReactUtils.getMemoryHistory();
|
|
39
|
+
if (history) {
|
|
40
|
+
console.log(history);
|
|
41
|
+
}
|
|
27
42
|
};
|
|
28
43
|
|
|
29
44
|
return (
|
|
@@ -33,15 +48,8 @@ export function BackButton(props: BackButtonProps) {
|
|
|
33
48
|
size={size}
|
|
34
49
|
onClick={onClickLocal}
|
|
35
50
|
sx={{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
(() =>
|
|
39
|
-
color != 'inherit' &&
|
|
40
|
-
color != 'default' &&
|
|
41
|
-
color in theme.palette
|
|
42
|
-
? theme.palette[color]
|
|
43
|
-
: theme.palette.primary)().light
|
|
44
|
-
}`
|
|
51
|
+
backgroundColor: pColor.contrastText,
|
|
52
|
+
border: `1px solid ${pColor.light}`
|
|
45
53
|
}}
|
|
46
54
|
{...rest}
|
|
47
55
|
>
|
package/src/mu/ButtonLink.tsx
CHANGED
|
@@ -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 =
|
|
25
|
+
const navigate = ReactUtils.getNavigateFn();
|
|
26
|
+
|
|
26
27
|
const onClick = href.includes('://')
|
|
27
28
|
? () => window.open(href, '_blank')
|
|
28
29
|
: () => navigate(href);
|
package/src/mu/ComboBox.tsx
CHANGED
|
@@ -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
|
-
|
|
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 =
|
|
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 {
|
|
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
|
-
|
|
329
|
+
ReactUtils.isSafeClick(event) &&
|
|
330
330
|
quickAction(data)
|
|
331
331
|
}
|
|
332
332
|
oRef={(element) => {
|
package/src/mu/SearchBar.tsx
CHANGED
|
@@ -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
|
-
|
|
51
|
+
ReactUtils.triggerChange(input, '', true);
|
|
52
52
|
}
|
|
53
53
|
continue;
|
|
54
54
|
}
|
package/src/mu/SelectEx.tsx
CHANGED
|
@@ -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
|
-
|
|
148
|
+
ReactUtils.triggerChange(input, id as string, false);
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
};
|
package/src/mu/Tiplist.tsx
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
|
|
189
|
+
ReactUtils.triggerChange(input, newValue, false);
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
};
|
|
@@ -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>
|