@etsoo/materialui 1.0.1
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/.eslintignore +3 -0
- package/.eslintrc.json +38 -0
- package/.gitattributes +2 -0
- package/.github/workflows/main.yml +48 -0
- package/.prettierignore +5 -0
- package/.prettierrc +6 -0
- package/LICENSE +21 -0
- package/README.md +16 -0
- package/__tests__/ComboBox.tsx +30 -0
- package/__tests__/MUGlobalTests.tsx +58 -0
- package/__tests__/NotifierMUTests.tsx +217 -0
- package/__tests__/SelectEx.tsx +26 -0
- package/__tests__/tsconfig.json +19 -0
- package/babel.config.json +11 -0
- package/lib/AuditDisplay.d.ts +33 -0
- package/lib/AuditDisplay.js +52 -0
- package/lib/AutocompleteExtendedProps.d.ts +64 -0
- package/lib/AutocompleteExtendedProps.js +1 -0
- package/lib/BackButton.d.ts +13 -0
- package/lib/BackButton.js +33 -0
- package/lib/BridgeCloseButton.d.ts +23 -0
- package/lib/BridgeCloseButton.js +32 -0
- package/lib/ButtonLink.d.ts +17 -0
- package/lib/ButtonLink.js +19 -0
- package/lib/ComboBox.d.ts +38 -0
- package/lib/ComboBox.js +108 -0
- package/lib/CountdownButton.d.ts +23 -0
- package/lib/CountdownButton.js +81 -0
- package/lib/CustomFabProps.d.ts +27 -0
- package/lib/CustomFabProps.js +1 -0
- package/lib/DataGridEx.d.ts +94 -0
- package/lib/DataGridEx.js +329 -0
- package/lib/DataGridRenderers.d.ts +22 -0
- package/lib/DataGridRenderers.js +99 -0
- package/lib/DialogButton.d.ts +54 -0
- package/lib/DialogButton.js +45 -0
- package/lib/DnDList.d.ts +87 -0
- package/lib/DnDList.js +153 -0
- package/lib/DraggablePaperComponent.d.ts +8 -0
- package/lib/DraggablePaperComponent.js +12 -0
- package/lib/EmailInput.d.ts +11 -0
- package/lib/EmailInput.js +15 -0
- package/lib/FabBox.d.ts +21 -0
- package/lib/FabBox.js +31 -0
- package/lib/FlexBox.d.ts +14 -0
- package/lib/FlexBox.js +18 -0
- package/lib/GridDataFormat.d.ts +10 -0
- package/lib/GridDataFormat.js +43 -0
- package/lib/IconButtonLink.d.ts +17 -0
- package/lib/IconButtonLink.js +16 -0
- package/lib/InputField.d.ts +21 -0
- package/lib/InputField.js +39 -0
- package/lib/ItemList.d.ts +56 -0
- package/lib/ItemList.js +69 -0
- package/lib/ListItemRightIcon.d.ts +4 -0
- package/lib/ListItemRightIcon.js +8 -0
- package/lib/ListMoreDisplay.d.ts +35 -0
- package/lib/ListMoreDisplay.js +99 -0
- package/lib/LoadingButton.d.ts +16 -0
- package/lib/LoadingButton.js +41 -0
- package/lib/MUGlobal.d.ts +102 -0
- package/lib/MUGlobal.js +184 -0
- package/lib/MaskInput.d.ts +34 -0
- package/lib/MaskInput.js +43 -0
- package/lib/MobileListItemRenderer.d.ts +17 -0
- package/lib/MobileListItemRenderer.js +35 -0
- package/lib/MoreFab.d.ts +45 -0
- package/lib/MoreFab.js +95 -0
- package/lib/NotifierMU.d.ts +47 -0
- package/lib/NotifierMU.js +387 -0
- package/lib/NotifierPromptProps.d.ts +22 -0
- package/lib/NotifierPromptProps.js +1 -0
- package/lib/OptionGroup.d.ts +58 -0
- package/lib/OptionGroup.js +81 -0
- package/lib/PList.d.ts +15 -0
- package/lib/PList.js +12 -0
- package/lib/ProgressCount.d.ts +44 -0
- package/lib/ProgressCount.js +79 -0
- package/lib/PullToRefreshUI.d.ts +9 -0
- package/lib/PullToRefreshUI.js +18 -0
- package/lib/RLink.d.ts +14 -0
- package/lib/RLink.js +37 -0
- package/lib/ResponsibleContainer.d.ts +87 -0
- package/lib/ResponsibleContainer.js +156 -0
- package/lib/ScrollTopFab.d.ts +7 -0
- package/lib/ScrollTopFab.js +25 -0
- package/lib/ScrollerListEx.d.ts +81 -0
- package/lib/ScrollerListEx.js +167 -0
- package/lib/SearchBar.d.ts +29 -0
- package/lib/SearchBar.js +260 -0
- package/lib/SearchField.d.ts +21 -0
- package/lib/SearchField.js +39 -0
- package/lib/SearchOptionGroup.d.ts +9 -0
- package/lib/SearchOptionGroup.js +14 -0
- package/lib/SelectBool.d.ts +13 -0
- package/lib/SelectBool.js +22 -0
- package/lib/SelectEx.d.ts +50 -0
- package/lib/SelectEx.js +156 -0
- package/lib/ShowDataComparison.d.ts +20 -0
- package/lib/ShowDataComparison.js +58 -0
- package/lib/Switch.d.ts +29 -0
- package/lib/Switch.js +34 -0
- package/lib/SwitchAnt.d.ts +25 -0
- package/lib/SwitchAnt.js +40 -0
- package/lib/TabBox.d.ts +54 -0
- package/lib/TabBox.js +31 -0
- package/lib/TableEx.d.ts +65 -0
- package/lib/TableEx.js +270 -0
- package/lib/TextFieldEx.d.ts +101 -0
- package/lib/TextFieldEx.js +126 -0
- package/lib/Tiplist.d.ts +18 -0
- package/lib/Tiplist.js +157 -0
- package/lib/TooltipClick.d.ts +15 -0
- package/lib/TooltipClick.js +40 -0
- package/lib/UserAvatar.d.ts +24 -0
- package/lib/UserAvatar.js +25 -0
- package/lib/UserAvatarEditor.d.ts +53 -0
- package/lib/UserAvatarEditor.js +129 -0
- package/lib/app/CommonApp.d.ts +38 -0
- package/lib/app/CommonApp.js +149 -0
- package/lib/app/IServiceAppSettings.d.ts +11 -0
- package/lib/app/IServiceAppSettings.js +1 -0
- package/lib/app/IServicePage.d.ts +6 -0
- package/lib/app/IServicePage.js +1 -0
- package/lib/app/IServiceUser.d.ts +14 -0
- package/lib/app/IServiceUser.js +1 -0
- package/lib/app/ISmartERPUser.d.ts +14 -0
- package/lib/app/ISmartERPUser.js +1 -0
- package/lib/app/Labels.d.ts +65 -0
- package/lib/app/Labels.js +62 -0
- package/lib/app/ReactApp.d.ts +195 -0
- package/lib/app/ReactApp.js +296 -0
- package/lib/app/ServiceApp.d.ts +78 -0
- package/lib/app/ServiceApp.js +244 -0
- package/lib/index.d.ts +74 -0
- package/lib/index.js +74 -0
- package/lib/pages/CommonPage.d.ts +11 -0
- package/lib/pages/CommonPage.js +60 -0
- package/lib/pages/CommonPageProps.d.ts +59 -0
- package/lib/pages/CommonPageProps.js +1 -0
- package/lib/pages/DataGridPage.d.ts +9 -0
- package/lib/pages/DataGridPage.js +79 -0
- package/lib/pages/DataGridPageProps.d.ts +17 -0
- package/lib/pages/DataGridPageProps.js +1 -0
- package/lib/pages/EditPage.d.ts +33 -0
- package/lib/pages/EditPage.js +29 -0
- package/lib/pages/FixedListPage.d.ts +15 -0
- package/lib/pages/FixedListPage.js +70 -0
- package/lib/pages/ListPage.d.ts +9 -0
- package/lib/pages/ListPage.js +50 -0
- package/lib/pages/ListPageProps.d.ts +7 -0
- package/lib/pages/ListPageProps.js +1 -0
- package/lib/pages/ResponsivePage.d.ts +9 -0
- package/lib/pages/ResponsivePage.js +45 -0
- package/lib/pages/ResponsivePageProps.d.ts +39 -0
- package/lib/pages/ResponsivePageProps.js +1 -0
- package/lib/pages/SearchPageProps.d.ts +30 -0
- package/lib/pages/SearchPageProps.js +1 -0
- package/lib/pages/TablePage.d.ts +9 -0
- package/lib/pages/TablePage.js +69 -0
- package/lib/pages/TablePageProps.d.ts +7 -0
- package/lib/pages/TablePageProps.js +1 -0
- package/lib/pages/ViewPage.d.ts +66 -0
- package/lib/pages/ViewPage.js +105 -0
- package/lib/texts/DateText.d.ts +34 -0
- package/lib/texts/DateText.js +25 -0
- package/lib/texts/MoneyText.d.ts +21 -0
- package/lib/texts/MoneyText.js +14 -0
- package/lib/texts/NumberText.d.ts +25 -0
- package/lib/texts/NumberText.js +14 -0
- package/package.json +97 -0
- package/src/AuditDisplay.tsx +114 -0
- package/src/AutocompleteExtendedProps.ts +83 -0
- package/src/BackButton.tsx +55 -0
- package/src/BridgeCloseButton.tsx +69 -0
- package/src/ButtonLink.tsx +32 -0
- package/src/ComboBox.tsx +251 -0
- package/src/CountdownButton.tsx +119 -0
- package/src/CustomFabProps.ts +32 -0
- package/src/DataGridEx.tsx +713 -0
- package/src/DataGridRenderers.tsx +140 -0
- package/src/DialogButton.tsx +163 -0
- package/src/DnDList.tsx +344 -0
- package/src/DraggablePaperComponent.tsx +19 -0
- package/src/EmailInput.tsx +24 -0
- package/src/FabBox.tsx +51 -0
- package/src/FlexBox.tsx +20 -0
- package/src/GridDataFormat.tsx +77 -0
- package/src/IconButtonLink.tsx +29 -0
- package/src/InputField.tsx +82 -0
- package/src/ItemList.tsx +204 -0
- package/src/ListItemRightIcon.tsx +9 -0
- package/src/ListMoreDisplay.tsx +205 -0
- package/src/LoadingButton.tsx +75 -0
- package/src/MUGlobal.ts +220 -0
- package/src/MaskInput.tsx +107 -0
- package/src/MobileListItemRenderer.tsx +79 -0
- package/src/MoreFab.tsx +211 -0
- package/src/NotifierMU.tsx +654 -0
- package/src/NotifierPromptProps.ts +24 -0
- package/src/OptionGroup.tsx +223 -0
- package/src/PList.tsx +27 -0
- package/src/ProgressCount.tsx +166 -0
- package/src/PullToRefreshUI.tsx +21 -0
- package/src/RLink.tsx +64 -0
- package/src/ResponsibleContainer.tsx +394 -0
- package/src/ScrollTopFab.tsx +34 -0
- package/src/ScrollerListEx.tsx +387 -0
- package/src/SearchBar.tsx +396 -0
- package/src/SearchField.tsx +82 -0
- package/src/SearchOptionGroup.tsx +31 -0
- package/src/SelectBool.tsx +33 -0
- package/src/SelectEx.tsx +290 -0
- package/src/ShowDataComparison.tsx +106 -0
- package/src/Switch.tsx +94 -0
- package/src/SwitchAnt.tsx +95 -0
- package/src/TabBox.tsx +118 -0
- package/src/TableEx.tsx +558 -0
- package/src/TextFieldEx.tsx +249 -0
- package/src/Tiplist.tsx +303 -0
- package/src/TooltipClick.tsx +84 -0
- package/src/UserAvatar.tsx +64 -0
- package/src/UserAvatarEditor.tsx +287 -0
- package/src/app/CommonApp.ts +223 -0
- package/src/app/IServiceAppSettings.ts +13 -0
- package/src/app/IServicePage.ts +6 -0
- package/src/app/IServiceUser.ts +17 -0
- package/src/app/ISmartERPUser.ts +16 -0
- package/src/app/Labels.ts +77 -0
- package/src/app/ReactApp.ts +504 -0
- package/src/app/ServiceApp.ts +352 -0
- package/src/index.ts +77 -0
- package/src/pages/CommonPage.tsx +128 -0
- package/src/pages/CommonPageProps.ts +70 -0
- package/src/pages/DataGridPage.tsx +140 -0
- package/src/pages/DataGridPageProps.ts +24 -0
- package/src/pages/EditPage.tsx +114 -0
- package/src/pages/FixedListPage.tsx +141 -0
- package/src/pages/ListPage.tsx +90 -0
- package/src/pages/ListPageProps.ts +12 -0
- package/src/pages/ResponsivePage.tsx +68 -0
- package/src/pages/ResponsivePageProps.ts +57 -0
- package/src/pages/SearchPageProps.ts +39 -0
- package/src/pages/TablePage.tsx +126 -0
- package/src/pages/TablePageProps.ts +12 -0
- package/src/pages/ViewPage.tsx +282 -0
- package/src/texts/DateText.tsx +74 -0
- package/src/texts/MoneyText.tsx +49 -0
- package/src/texts/NumberText.tsx +40 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BridgeUtils,
|
|
3
|
+
createClient,
|
|
4
|
+
IActionResult,
|
|
5
|
+
IApi,
|
|
6
|
+
IApiPayload,
|
|
7
|
+
RefreshTokenProps,
|
|
8
|
+
RefreshTokenResult
|
|
9
|
+
} from '@etsoo/appscript';
|
|
10
|
+
import { CoreConstants, RefreshTokenRQ } from '@etsoo/react';
|
|
11
|
+
import { DomUtils } from '@etsoo/shared';
|
|
12
|
+
import { IServiceAppSettings } from './IServiceAppSettings';
|
|
13
|
+
import { IServicePageData } from './IServicePage';
|
|
14
|
+
import { IServiceUser, ServiceLoginResult } from './IServiceUser';
|
|
15
|
+
import { ISmartERPUser } from './ISmartERPUser';
|
|
16
|
+
import { ReactApp } from './ReactApp';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Core Service App
|
|
20
|
+
* Service login to core system, get the refesh token and access token
|
|
21
|
+
* Use the acess token to the service api, get a service access token
|
|
22
|
+
* Use the new acess token and refresh token to login
|
|
23
|
+
*/
|
|
24
|
+
export class ServiceApp<
|
|
25
|
+
U extends IServiceUser = IServiceUser,
|
|
26
|
+
P extends IServicePageData = IServicePageData,
|
|
27
|
+
S extends IServiceAppSettings = IServiceAppSettings
|
|
28
|
+
> extends ReactApp<S, ISmartERPUser, P> {
|
|
29
|
+
/**
|
|
30
|
+
* Service API
|
|
31
|
+
*/
|
|
32
|
+
readonly serviceApi: IApi;
|
|
33
|
+
|
|
34
|
+
private _serviceUser?: U;
|
|
35
|
+
/**
|
|
36
|
+
* Service user
|
|
37
|
+
*/
|
|
38
|
+
get serviceUser() {
|
|
39
|
+
return this._serviceUser;
|
|
40
|
+
}
|
|
41
|
+
protected set serviceUser(value: U | undefined) {
|
|
42
|
+
this._serviceUser = value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Service passphrase
|
|
47
|
+
*/
|
|
48
|
+
protected servicePassphrase: string = '';
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Constructor
|
|
52
|
+
* @param settings Settings
|
|
53
|
+
* @param name Application name
|
|
54
|
+
*/
|
|
55
|
+
constructor(settings: S, name: string) {
|
|
56
|
+
super(settings, name);
|
|
57
|
+
|
|
58
|
+
// Check
|
|
59
|
+
if (settings.serviceId == null || settings.serviceEndpoint == null) {
|
|
60
|
+
throw new Error('No service settings');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Service API
|
|
64
|
+
const api = createClient();
|
|
65
|
+
api.baseUrl = settings.serviceEndpoint;
|
|
66
|
+
|
|
67
|
+
this.setApi(api);
|
|
68
|
+
this.serviceApi = api;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Load SmartERP core
|
|
73
|
+
*/
|
|
74
|
+
loadSmartERP() {
|
|
75
|
+
if (BridgeUtils.host == null) {
|
|
76
|
+
window.location.href = this.settings.webUrl;
|
|
77
|
+
} else {
|
|
78
|
+
BridgeUtils.host.loadApp('core');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Go to the login page
|
|
84
|
+
* @param tryLogin Try to login again
|
|
85
|
+
*/
|
|
86
|
+
override toLoginPage(tryLogin?: boolean) {
|
|
87
|
+
const parameters = `?serviceId=${this.settings.serviceId}&${
|
|
88
|
+
DomUtils.CultureField
|
|
89
|
+
}=${this.culture}${tryLogin ? '' : '&tryLogin=false'}`;
|
|
90
|
+
|
|
91
|
+
if (BridgeUtils.host == null) {
|
|
92
|
+
const coreUrl = this.settings.webUrl;
|
|
93
|
+
window.location.href = coreUrl + parameters;
|
|
94
|
+
} else {
|
|
95
|
+
BridgeUtils.host.loadApp('core', parameters);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Refresh token
|
|
101
|
+
* @param props Props
|
|
102
|
+
*/
|
|
103
|
+
override async refreshToken<D extends object = RefreshTokenRQ>(
|
|
104
|
+
props?: RefreshTokenProps<D>
|
|
105
|
+
) {
|
|
106
|
+
// Destruct
|
|
107
|
+
const {
|
|
108
|
+
callback,
|
|
109
|
+
data,
|
|
110
|
+
relogin = false,
|
|
111
|
+
showLoading = false
|
|
112
|
+
} = props ?? {};
|
|
113
|
+
|
|
114
|
+
// Token
|
|
115
|
+
const token = this.getCacheToken();
|
|
116
|
+
if (token == null || token === '') {
|
|
117
|
+
if (callback) callback(false);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Reqest data
|
|
122
|
+
// Merge additional data passed
|
|
123
|
+
const rq: RefreshTokenRQ = {
|
|
124
|
+
deviceId: this.deviceId,
|
|
125
|
+
timezone: this.getTimeZone(),
|
|
126
|
+
...data
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Login result type
|
|
130
|
+
type LoginResult = IActionResult<U>;
|
|
131
|
+
|
|
132
|
+
// Payload
|
|
133
|
+
const payload: IApiPayload<LoginResult, any> = {
|
|
134
|
+
showLoading,
|
|
135
|
+
config: { headers: { [CoreConstants.TokenHeaderRefresh]: token } },
|
|
136
|
+
onError: (error) => {
|
|
137
|
+
if (callback) callback(error);
|
|
138
|
+
|
|
139
|
+
// Prevent further processing
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
// Success callback
|
|
145
|
+
const success = async (
|
|
146
|
+
result: LoginResult,
|
|
147
|
+
failCallback?: (result: RefreshTokenResult) => void
|
|
148
|
+
) => {
|
|
149
|
+
// Token
|
|
150
|
+
const refreshToken = this.getResponseToken(payload.response);
|
|
151
|
+
if (refreshToken == null || result.data == null) {
|
|
152
|
+
if (failCallback) failCallback(this.get('noData')!);
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// User data
|
|
157
|
+
const userData = result.data;
|
|
158
|
+
|
|
159
|
+
// Use core system access token to service api to exchange service access token
|
|
160
|
+
const serviceResult = await this.serviceApi.put<
|
|
161
|
+
ServiceLoginResult<U>
|
|
162
|
+
>(
|
|
163
|
+
'Auth/ExchangeToken',
|
|
164
|
+
{
|
|
165
|
+
token: this.encryptEnhanced(
|
|
166
|
+
userData.token,
|
|
167
|
+
this.settings.serviceId.toString()
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
showLoading,
|
|
172
|
+
onError: (error) => {
|
|
173
|
+
if (failCallback) failCallback(error);
|
|
174
|
+
|
|
175
|
+
// Prevent further processing
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
if (serviceResult == null) return false;
|
|
182
|
+
|
|
183
|
+
if (!serviceResult.ok) {
|
|
184
|
+
if (failCallback) failCallback(serviceResult);
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (serviceResult.data == null) {
|
|
189
|
+
if (failCallback) failCallback(this.get('noData')!);
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Login
|
|
194
|
+
this.userLoginEx(userData, refreshToken, serviceResult.data);
|
|
195
|
+
|
|
196
|
+
// Success callback
|
|
197
|
+
if (failCallback) failCallback(true);
|
|
198
|
+
|
|
199
|
+
return true;
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
// Call API
|
|
203
|
+
const result = await this.api.put<LoginResult>(
|
|
204
|
+
'Auth/RefreshToken',
|
|
205
|
+
rq,
|
|
206
|
+
payload
|
|
207
|
+
);
|
|
208
|
+
if (result == null) return false;
|
|
209
|
+
|
|
210
|
+
if (!result.ok) {
|
|
211
|
+
if (result.type === 'TokenExpired' && relogin) {
|
|
212
|
+
// Try login
|
|
213
|
+
// Dialog to receive password
|
|
214
|
+
var labels = this.getLabels('reloginTip', 'login');
|
|
215
|
+
this.notifier.prompt(
|
|
216
|
+
labels.reloginTip,
|
|
217
|
+
async (pwd) => {
|
|
218
|
+
if (pwd == null) {
|
|
219
|
+
this.toLoginPage();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Set password for the action
|
|
224
|
+
rq.pwd = this.encrypt(this.hash(pwd));
|
|
225
|
+
|
|
226
|
+
// Submit again
|
|
227
|
+
const result = await this.api.put<LoginResult>(
|
|
228
|
+
'Auth/RefreshToken',
|
|
229
|
+
rq,
|
|
230
|
+
payload
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
if (result == null) return;
|
|
234
|
+
|
|
235
|
+
if (result.ok) {
|
|
236
|
+
await success(
|
|
237
|
+
result,
|
|
238
|
+
(loginResult: RefreshTokenResult) => {
|
|
239
|
+
if (loginResult === true) {
|
|
240
|
+
if (callback) callback(true);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const message =
|
|
245
|
+
this.formatRefreshTokenResult(
|
|
246
|
+
loginResult
|
|
247
|
+
);
|
|
248
|
+
if (message) this.notifier.alert(message);
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Popup message
|
|
255
|
+
this.alertResult(result);
|
|
256
|
+
return false;
|
|
257
|
+
},
|
|
258
|
+
labels.login,
|
|
259
|
+
{ type: 'password' }
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Fake truth to avoid reloading
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (callback) callback(result);
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return await success(result, callback);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Service decrypt message
|
|
275
|
+
* @param messageEncrypted Encrypted message
|
|
276
|
+
* @param passphrase Secret passphrase
|
|
277
|
+
* @returns Pure text
|
|
278
|
+
*/
|
|
279
|
+
serviceDecrypt(messageEncrypted: string, passphrase?: string) {
|
|
280
|
+
return this.decrypt(
|
|
281
|
+
messageEncrypted,
|
|
282
|
+
passphrase ?? this.servicePassphrase
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Service encrypt message
|
|
288
|
+
* @param message Message
|
|
289
|
+
* @param passphrase Secret passphrase
|
|
290
|
+
* @param iterations Iterations, 1000 times, 1 - 99
|
|
291
|
+
* @returns Result
|
|
292
|
+
*/
|
|
293
|
+
serviceEncrypt(message: string, passphrase?: string, iterations?: number) {
|
|
294
|
+
return this.encrypt(
|
|
295
|
+
message,
|
|
296
|
+
passphrase ?? this.servicePassphrase,
|
|
297
|
+
iterations
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Try login
|
|
303
|
+
* @param data Additional data
|
|
304
|
+
* @param showLoading Show loading bar or not
|
|
305
|
+
* @returns Result
|
|
306
|
+
*/
|
|
307
|
+
override async tryLogin<D extends object = {}>(
|
|
308
|
+
data?: D,
|
|
309
|
+
showLoading?: boolean
|
|
310
|
+
) {
|
|
311
|
+
// Reset user state
|
|
312
|
+
const result = await super.tryLogin(data, showLoading);
|
|
313
|
+
if (!result) return false;
|
|
314
|
+
|
|
315
|
+
// Refresh token
|
|
316
|
+
return await this.refreshToken({
|
|
317
|
+
callback: (result) => this.doRefreshTokenResult(result),
|
|
318
|
+
data,
|
|
319
|
+
showLoading,
|
|
320
|
+
relogin: true
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* User login extended
|
|
326
|
+
* @param user Core system user
|
|
327
|
+
* @param refreshToken Refresh token
|
|
328
|
+
* @param serviceUser Service user
|
|
329
|
+
*/
|
|
330
|
+
userLoginEx(
|
|
331
|
+
user: ISmartERPUser,
|
|
332
|
+
refreshToken: string,
|
|
333
|
+
serviceUser: U
|
|
334
|
+
): void {
|
|
335
|
+
// Service user login
|
|
336
|
+
this.servicePassphrase =
|
|
337
|
+
this.decrypt(
|
|
338
|
+
serviceUser.serviceDeviceId,
|
|
339
|
+
this.settings.serviceId.toString()
|
|
340
|
+
) ?? '';
|
|
341
|
+
|
|
342
|
+
// Service user
|
|
343
|
+
this.serviceUser = serviceUser;
|
|
344
|
+
|
|
345
|
+
// Service API token
|
|
346
|
+
this.serviceApi.authorize(this.settings.authScheme, serviceUser.token);
|
|
347
|
+
|
|
348
|
+
// Keep = true, means service could hold the refresh token for long access
|
|
349
|
+
// Trigger Context change and serviceUser is ready then
|
|
350
|
+
super.userLogin(user, refreshToken, true);
|
|
351
|
+
}
|
|
352
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export * from './app/CommonApp';
|
|
2
|
+
export * from './app/IServiceAppSettings';
|
|
3
|
+
export * from './app/IServicePage';
|
|
4
|
+
export * from './app/IServiceUser';
|
|
5
|
+
export * from './app/ISmartERPUser';
|
|
6
|
+
export * from './app/Labels';
|
|
7
|
+
export * from './app/ReactApp';
|
|
8
|
+
export * from './app/ServiceApp';
|
|
9
|
+
|
|
10
|
+
export * from './pages/CommonPage';
|
|
11
|
+
export * from './pages/CommonPageProps';
|
|
12
|
+
export * from './pages/DataGridPage';
|
|
13
|
+
export * from './pages/DataGridPageProps';
|
|
14
|
+
export * from './pages/EditPage';
|
|
15
|
+
export * from './pages/FixedListPage';
|
|
16
|
+
export * from './pages/ListPage';
|
|
17
|
+
export * from './pages/ListPageProps';
|
|
18
|
+
export * from './pages/ResponsivePage';
|
|
19
|
+
export * from './pages/ResponsivePageProps';
|
|
20
|
+
export * from './pages/SearchPageProps';
|
|
21
|
+
export * from './pages/TablePage';
|
|
22
|
+
export * from './pages/ViewPage';
|
|
23
|
+
|
|
24
|
+
export * from './texts/DateText';
|
|
25
|
+
export * from './texts/MoneyText';
|
|
26
|
+
export * from './texts/NumberText';
|
|
27
|
+
|
|
28
|
+
export * from './AuditDisplay';
|
|
29
|
+
export * from './BackButton';
|
|
30
|
+
export * from './BridgeCloseButton';
|
|
31
|
+
export * from './ButtonLink';
|
|
32
|
+
export * from './ComboBox';
|
|
33
|
+
export * from './CountdownButton';
|
|
34
|
+
export * from './CustomFabProps';
|
|
35
|
+
export * from './DataGridEx';
|
|
36
|
+
export * from './DataGridRenderers';
|
|
37
|
+
export * from './DialogButton';
|
|
38
|
+
export * from './DnDList';
|
|
39
|
+
export * from './DraggablePaperComponent';
|
|
40
|
+
export * from './EmailInput';
|
|
41
|
+
export * from './FabBox';
|
|
42
|
+
export * from './FlexBox';
|
|
43
|
+
export * from './GridDataFormat';
|
|
44
|
+
export * from './IconButtonLink';
|
|
45
|
+
export * from './InputField';
|
|
46
|
+
export * from './ItemList';
|
|
47
|
+
export * from './ListItemRightIcon';
|
|
48
|
+
export * from './ListMoreDisplay';
|
|
49
|
+
export * from './LoadingButton';
|
|
50
|
+
export * from './MaskInput';
|
|
51
|
+
export * from './MobileListItemRenderer';
|
|
52
|
+
export * from './MoreFab';
|
|
53
|
+
export * from './MUGlobal';
|
|
54
|
+
export * from './NotifierMU';
|
|
55
|
+
export * from './OptionGroup';
|
|
56
|
+
export * from './PList';
|
|
57
|
+
export * from './ProgressCount';
|
|
58
|
+
export * from './PullToRefreshUI';
|
|
59
|
+
export * from './ResponsibleContainer';
|
|
60
|
+
export * from './RLink';
|
|
61
|
+
export * from './ScrollerListEx';
|
|
62
|
+
export * from './ScrollTopFab';
|
|
63
|
+
export * from './SearchBar';
|
|
64
|
+
export * from './SearchField';
|
|
65
|
+
export * from './SearchOptionGroup';
|
|
66
|
+
export * from './SelectBool';
|
|
67
|
+
export * from './SelectEx';
|
|
68
|
+
export * from './ShowDataComparison';
|
|
69
|
+
export * from './Switch';
|
|
70
|
+
export * from './SwitchAnt';
|
|
71
|
+
export * from './TabBox';
|
|
72
|
+
export * from './TableEx';
|
|
73
|
+
export * from './TextFieldEx';
|
|
74
|
+
export * from './Tiplist';
|
|
75
|
+
export * from './TooltipClick';
|
|
76
|
+
export * from './UserAvatar';
|
|
77
|
+
export * from './UserAvatarEditor';
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FabBox } from '../FabBox';
|
|
3
|
+
import { ScrollTopFab } from '../ScrollTopFab';
|
|
4
|
+
import { MUGlobal } from '../MUGlobal';
|
|
5
|
+
import { CommonPageProps } from './CommonPageProps';
|
|
6
|
+
import { MoreFab } from '../MoreFab';
|
|
7
|
+
import { Container, Fab } from '@mui/material';
|
|
8
|
+
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
9
|
+
import { BackButton } from '../BackButton';
|
|
10
|
+
import { Labels } from '../app/Labels';
|
|
11
|
+
import { ReactAppStateDetector } from '../app/ReactApp';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default scroll container
|
|
15
|
+
*/
|
|
16
|
+
export const CommonPageScrollContainer = global;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Common page
|
|
20
|
+
* @param props Props
|
|
21
|
+
*/
|
|
22
|
+
export function CommonPage(props: CommonPageProps) {
|
|
23
|
+
// Destruct
|
|
24
|
+
const {
|
|
25
|
+
children,
|
|
26
|
+
disableGutters = true,
|
|
27
|
+
fabButtons,
|
|
28
|
+
fabColumnDirection,
|
|
29
|
+
fabPaddingAdjust = 1.5,
|
|
30
|
+
fabSize = 'small',
|
|
31
|
+
maxWidth = false,
|
|
32
|
+
moreActions,
|
|
33
|
+
onRefresh,
|
|
34
|
+
onUpdate,
|
|
35
|
+
onUpdateAll,
|
|
36
|
+
paddings = MUGlobal.pagePaddings,
|
|
37
|
+
scrollContainer,
|
|
38
|
+
supportBack = false,
|
|
39
|
+
targetFields,
|
|
40
|
+
sx = {},
|
|
41
|
+
...rest
|
|
42
|
+
} = props;
|
|
43
|
+
|
|
44
|
+
// Fab padding
|
|
45
|
+
const fabPadding = MUGlobal.increase(
|
|
46
|
+
MUGlobal.pagePaddings,
|
|
47
|
+
fabPaddingAdjust
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (typeof sx === 'object' && sx != null && !Reflect.has(sx, 'padding')) {
|
|
51
|
+
// Set default padding
|
|
52
|
+
Reflect.set(sx, 'padding', paddings);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Labels
|
|
56
|
+
const labels = Labels.CommonPage;
|
|
57
|
+
|
|
58
|
+
// Update
|
|
59
|
+
const update = onUpdateAll
|
|
60
|
+
? onUpdateAll
|
|
61
|
+
: onUpdate
|
|
62
|
+
? (authorized?: boolean) => {
|
|
63
|
+
if (authorized == null || authorized) onUpdate();
|
|
64
|
+
}
|
|
65
|
+
: onRefresh
|
|
66
|
+
? (authorized?: boolean) => {
|
|
67
|
+
if (authorized) onRefresh();
|
|
68
|
+
}
|
|
69
|
+
: undefined;
|
|
70
|
+
|
|
71
|
+
// Return the UI
|
|
72
|
+
return (
|
|
73
|
+
<React.Fragment>
|
|
74
|
+
{update && (
|
|
75
|
+
<ReactAppStateDetector
|
|
76
|
+
targetFields={targetFields}
|
|
77
|
+
update={update}
|
|
78
|
+
/>
|
|
79
|
+
)}
|
|
80
|
+
<Container
|
|
81
|
+
disableGutters={disableGutters}
|
|
82
|
+
maxWidth={maxWidth}
|
|
83
|
+
sx={sx}
|
|
84
|
+
id="page-container"
|
|
85
|
+
{...rest}
|
|
86
|
+
>
|
|
87
|
+
<FabBox
|
|
88
|
+
sx={{
|
|
89
|
+
zIndex: 1,
|
|
90
|
+
bottom: (theme) =>
|
|
91
|
+
MUGlobal.updateWithTheme(fabPadding, theme.spacing),
|
|
92
|
+
right: (theme) =>
|
|
93
|
+
MUGlobal.updateWithTheme(fabPadding, theme.spacing)
|
|
94
|
+
}}
|
|
95
|
+
columnDirection={fabColumnDirection}
|
|
96
|
+
>
|
|
97
|
+
{scrollContainer && (
|
|
98
|
+
<ScrollTopFab
|
|
99
|
+
size={fabSize}
|
|
100
|
+
target={scrollContainer}
|
|
101
|
+
title={labels.scrollTop}
|
|
102
|
+
/>
|
|
103
|
+
)}
|
|
104
|
+
{fabButtons}
|
|
105
|
+
{onRefresh != null && (
|
|
106
|
+
<Fab
|
|
107
|
+
title={labels.refresh}
|
|
108
|
+
size={fabSize}
|
|
109
|
+
onClick={onRefresh}
|
|
110
|
+
sx={{ display: { xs: 'none', md: 'inherit' } }}
|
|
111
|
+
>
|
|
112
|
+
<RefreshIcon />
|
|
113
|
+
</Fab>
|
|
114
|
+
)}
|
|
115
|
+
<MoreFab
|
|
116
|
+
size={fabSize}
|
|
117
|
+
title={labels.more}
|
|
118
|
+
actions={moreActions}
|
|
119
|
+
/>
|
|
120
|
+
{supportBack && (
|
|
121
|
+
<BackButton title={labels.back} size={fabSize} />
|
|
122
|
+
)}
|
|
123
|
+
</FabBox>
|
|
124
|
+
{children}
|
|
125
|
+
</Container>
|
|
126
|
+
</React.Fragment>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { UserKey } from '@etsoo/appscript';
|
|
2
|
+
import { IStateUpdate, ListItemReact } from '@etsoo/react';
|
|
3
|
+
import { ContainerProps } from '@mui/material';
|
|
4
|
+
import { CustomFabSize } from '../CustomFabProps';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Common page props
|
|
8
|
+
* Default container id is 'pageContainer'
|
|
9
|
+
*/
|
|
10
|
+
export interface CommonPageProps extends Omit<ContainerProps, 'id'> {
|
|
11
|
+
/**
|
|
12
|
+
* Fab buttons
|
|
13
|
+
*/
|
|
14
|
+
fabButtons?: React.ReactNode;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Fab size
|
|
18
|
+
*/
|
|
19
|
+
fabSize?: CustomFabSize;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fab flex column direction, undefined to hide it
|
|
23
|
+
*/
|
|
24
|
+
fabColumnDirection?: boolean;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Fab padding adjust
|
|
28
|
+
*/
|
|
29
|
+
fabPaddingAdjust?: number;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* More actions
|
|
33
|
+
*/
|
|
34
|
+
moreActions?: ListItemReact[];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* On refresh callback, only when authorized = true
|
|
38
|
+
*/
|
|
39
|
+
onRefresh?: () => void | PromiseLike<void>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* On page update, when authorized = null or true case, may uses onRefresh
|
|
43
|
+
*/
|
|
44
|
+
onUpdate?: () => void | PromiseLike<void>;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* On page update, all cases with authorized
|
|
48
|
+
*/
|
|
49
|
+
onUpdateAll?: IStateUpdate;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Paddings
|
|
53
|
+
*/
|
|
54
|
+
paddings?: Record<string, string | number>;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Scroll container
|
|
58
|
+
*/
|
|
59
|
+
scrollContainer?: HTMLElement | object;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Support back click
|
|
63
|
+
*/
|
|
64
|
+
supportBack?: boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* State last changed fields
|
|
68
|
+
*/
|
|
69
|
+
targetFields?: UserKey[];
|
|
70
|
+
}
|