@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
package/.eslintignore
ADDED
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"env": {
|
|
3
|
+
"browser": true,
|
|
4
|
+
"node": true,
|
|
5
|
+
"es6": true,
|
|
6
|
+
"jest": true
|
|
7
|
+
},
|
|
8
|
+
"extends": ["plugin:react/recommended", "airbnb-base", "prettier"],
|
|
9
|
+
"parser": "@typescript-eslint/parser",
|
|
10
|
+
"parserOptions": {
|
|
11
|
+
"ecmaFeatures": {
|
|
12
|
+
"jsx": true
|
|
13
|
+
},
|
|
14
|
+
"ecmaVersion": 6,
|
|
15
|
+
"sourceType": "module"
|
|
16
|
+
},
|
|
17
|
+
"plugins": ["@typescript-eslint"],
|
|
18
|
+
"rules": {
|
|
19
|
+
"class-methods-use-this": "off",
|
|
20
|
+
"import/extensions": ["error", "never"],
|
|
21
|
+
"import/prefer-default-export": "off",
|
|
22
|
+
"@typescript-eslint/no-unused-vars": ["error"]
|
|
23
|
+
},
|
|
24
|
+
"settings": {
|
|
25
|
+
"import/resolver": {
|
|
26
|
+
"node": {
|
|
27
|
+
"paths": ["src"],
|
|
28
|
+
"extensions": [".ts", ".tsx"]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"react": {
|
|
32
|
+
"createClass": "createReactClass",
|
|
33
|
+
"pragma": "React",
|
|
34
|
+
"version": "detect",
|
|
35
|
+
"flowVersion": "0.53"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
package/.gitattributes
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
|
|
2
|
+
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
3
|
+
# https://docs.github.com/en/actions/language-and-framework-guides/publishing-nodejs-packages
|
|
4
|
+
|
|
5
|
+
# Description
|
|
6
|
+
name: Node.js Package
|
|
7
|
+
|
|
8
|
+
# Event to trigger the action
|
|
9
|
+
on: [push]
|
|
10
|
+
# release:
|
|
11
|
+
# types: [created]
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
# Publish to NPM
|
|
15
|
+
publish-npm:
|
|
16
|
+
# Condition: previous build is successful
|
|
17
|
+
# needs: Any previous jobs
|
|
18
|
+
|
|
19
|
+
# Operation system
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
# https://github.com/actions/checkout, This action checks-out your repository under $GITHUB_WORKSPACE
|
|
24
|
+
# so your workflow can access it.
|
|
25
|
+
- uses: actions/checkout@v2
|
|
26
|
+
|
|
27
|
+
# Set up your GitHub Actions workflow with a specific version of node.js
|
|
28
|
+
# Setup .npmrc file to publish to npm
|
|
29
|
+
- uses: actions/setup-node@v1
|
|
30
|
+
with:
|
|
31
|
+
node-version: '18.x'
|
|
32
|
+
registry-url: 'https://registry.npmjs.org'
|
|
33
|
+
|
|
34
|
+
# Named after Continuous Integration, installs dependencies directly from package-lock.json
|
|
35
|
+
# ci vs install
|
|
36
|
+
- run: npm install
|
|
37
|
+
|
|
38
|
+
# Make sure pass the test without any exception
|
|
39
|
+
- run: npm test
|
|
40
|
+
|
|
41
|
+
# Build the package
|
|
42
|
+
- run: npm run build
|
|
43
|
+
|
|
44
|
+
# Publish to npm
|
|
45
|
+
# For scoped package, make it public for free service
|
|
46
|
+
- run: npm publish --access public
|
|
47
|
+
env:
|
|
48
|
+
NODE_AUTH_TOKEN: ${{ secrets.ETSOONpmToken }}
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 ETSOO
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ComboBox } from '../src';
|
|
3
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
4
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
5
|
+
|
|
6
|
+
it('Render ComboBox', async () => {
|
|
7
|
+
// Arrange
|
|
8
|
+
type T = { id: number; name: string };
|
|
9
|
+
const options: T[] = [
|
|
10
|
+
{ id: 1, name: 'Name 1' },
|
|
11
|
+
{ id: 2, name: 'Name 2' }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
render(
|
|
15
|
+
<ComboBox<T>
|
|
16
|
+
name="Test"
|
|
17
|
+
options={options}
|
|
18
|
+
labelField="name"
|
|
19
|
+
label="Test"
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// Act, click the list
|
|
24
|
+
const clicked = fireEvent.click(screen.getByRole('button'));
|
|
25
|
+
expect(clicked).toBeTruthy();
|
|
26
|
+
|
|
27
|
+
// Get list item
|
|
28
|
+
const item = screen.getByText('Name 1');
|
|
29
|
+
expect(item.nodeName).toBe('LI');
|
|
30
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { MUGlobal } from '../src/';
|
|
2
|
+
|
|
3
|
+
// Theme update function
|
|
4
|
+
const updateFunc = (value: number) => `${value * 8}px`;
|
|
5
|
+
|
|
6
|
+
// Arrange
|
|
7
|
+
const paddings = { sx: 2, sm: 3, key: 'a' };
|
|
8
|
+
|
|
9
|
+
test('getMenuItem tests', () => {
|
|
10
|
+
// Assert
|
|
11
|
+
expect(
|
|
12
|
+
MUGlobal.getMenuItem('/user/add', '/user/all').selected
|
|
13
|
+
).toBeTruthy();
|
|
14
|
+
expect(MUGlobal.getMenuItem('/user/add', '/user/*').selected).toBeTruthy();
|
|
15
|
+
expect(
|
|
16
|
+
MUGlobal.getMenuItem('/user/add', '/user/edit').selected
|
|
17
|
+
).toBeFalsy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('half tests', () => {
|
|
21
|
+
// Act
|
|
22
|
+
const result = MUGlobal.half(paddings);
|
|
23
|
+
|
|
24
|
+
// Assert
|
|
25
|
+
expect(paddings).toHaveProperty('sx', 2);
|
|
26
|
+
expect(result).toHaveProperty('sx', 1);
|
|
27
|
+
expect(result).toHaveProperty('sm', 1.5);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('increase tests', () => {
|
|
31
|
+
// Act
|
|
32
|
+
const result = MUGlobal.increase(paddings, 2);
|
|
33
|
+
|
|
34
|
+
// Assert
|
|
35
|
+
expect(paddings).toHaveProperty('sx', 2);
|
|
36
|
+
expect(result).toHaveProperty('sx', 4);
|
|
37
|
+
expect(result).toHaveProperty('sm', 5);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('adjustWithTheme tests', () => {
|
|
41
|
+
// Act
|
|
42
|
+
const result = MUGlobal.adjustWithTheme(160, paddings, updateFunc);
|
|
43
|
+
|
|
44
|
+
// Assert
|
|
45
|
+
expect(paddings).toHaveProperty('sx', 2);
|
|
46
|
+
expect(result).toHaveProperty('sx', '144px');
|
|
47
|
+
expect(result).toHaveProperty('sm', '136px');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('updateWithTheme tests', () => {
|
|
51
|
+
// Act
|
|
52
|
+
const result = MUGlobal.updateWithTheme(paddings, updateFunc);
|
|
53
|
+
|
|
54
|
+
// Assert
|
|
55
|
+
expect(paddings).toHaveProperty('sx', 2);
|
|
56
|
+
expect(result).toHaveProperty('sx', '16px');
|
|
57
|
+
expect(result).toHaveProperty('sm', '24px');
|
|
58
|
+
});
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import {
|
|
2
|
+
INotification,
|
|
3
|
+
NotificationMessageType
|
|
4
|
+
} from '@etsoo/notificationbase';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { createRoot } from 'react-dom/client';
|
|
7
|
+
import { act } from 'react-dom/test-utils';
|
|
8
|
+
import { NotifierMU } from '../src';
|
|
9
|
+
|
|
10
|
+
// Without it will popup error:
|
|
11
|
+
// The current testing environment is not configured to support act
|
|
12
|
+
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
|
|
13
|
+
|
|
14
|
+
// Root
|
|
15
|
+
const root = document.body;
|
|
16
|
+
const container: HTMLElement = document.createElement('div');
|
|
17
|
+
root.append(container);
|
|
18
|
+
|
|
19
|
+
// The state provider
|
|
20
|
+
const Provider = NotifierMU.setup();
|
|
21
|
+
const reactRoot = createRoot(container);
|
|
22
|
+
|
|
23
|
+
act(() => {
|
|
24
|
+
// Concorrent renderer needs act block
|
|
25
|
+
reactRoot.render(<Provider />);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Notifier
|
|
29
|
+
const notifier = NotifierMU.instance;
|
|
30
|
+
|
|
31
|
+
// Timer mock
|
|
32
|
+
// https://jestjs.io/docs/en/timer-mocks
|
|
33
|
+
jest.useFakeTimers();
|
|
34
|
+
|
|
35
|
+
test('Alert tests', async () => {
|
|
36
|
+
// Click
|
|
37
|
+
const handleClick = jest.fn();
|
|
38
|
+
|
|
39
|
+
act(() => {
|
|
40
|
+
// Add the notification
|
|
41
|
+
notifier.alert('Alert message', handleClick);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Button
|
|
45
|
+
const button = root.getElementsByTagName('button');
|
|
46
|
+
|
|
47
|
+
expect(button.length).toBe(1);
|
|
48
|
+
expect(button[0].innerHTML).toContain('OK');
|
|
49
|
+
|
|
50
|
+
await act(async () => {
|
|
51
|
+
button[0].click();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(handleClick).toBeCalled();
|
|
55
|
+
|
|
56
|
+
// Fast forward
|
|
57
|
+
jest.runOnlyPendingTimers();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('Confirm tests', async () => {
|
|
61
|
+
// Click
|
|
62
|
+
const handleClick = jest.fn();
|
|
63
|
+
|
|
64
|
+
act(() => {
|
|
65
|
+
// Add the notification
|
|
66
|
+
notifier.confirm('Confirm message', undefined, handleClick);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Button
|
|
70
|
+
const button = root.getElementsByTagName('button');
|
|
71
|
+
|
|
72
|
+
expect(button.length).toBe(2);
|
|
73
|
+
expect(button[0].innerHTML).toContain('Cancel');
|
|
74
|
+
|
|
75
|
+
await act(async () => {
|
|
76
|
+
button[0].click();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
expect(handleClick).toBeCalled();
|
|
80
|
+
|
|
81
|
+
// Fast forward
|
|
82
|
+
jest.runOnlyPendingTimers();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('Confirm tests without cancel button', async () => {
|
|
86
|
+
// Click
|
|
87
|
+
const handleClick = jest.fn();
|
|
88
|
+
|
|
89
|
+
act(() => {
|
|
90
|
+
// Add the notification
|
|
91
|
+
notifier.confirm('Confirm message', undefined, handleClick, {
|
|
92
|
+
cancelButton: false
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Button
|
|
97
|
+
const button = root.getElementsByTagName('button');
|
|
98
|
+
|
|
99
|
+
expect(button.length).toBe(1);
|
|
100
|
+
expect(button[0].innerHTML).toContain('OK');
|
|
101
|
+
|
|
102
|
+
await act(async () => {
|
|
103
|
+
button[0].click();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(handleClick).toBeCalled();
|
|
107
|
+
|
|
108
|
+
// Fast forward
|
|
109
|
+
jest.runOnlyPendingTimers();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test('Prompt tests', async () => {
|
|
113
|
+
// Click
|
|
114
|
+
const handleClick = jest.fn((result: boolean) => {
|
|
115
|
+
expect(result).toBeTruthy();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
act(() => {
|
|
119
|
+
// Add the notification
|
|
120
|
+
notifier.prompt<boolean>('Prompt message', handleClick, undefined, {
|
|
121
|
+
type: 'switch',
|
|
122
|
+
required: false
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Button
|
|
127
|
+
const button = root.getElementsByTagName('button');
|
|
128
|
+
|
|
129
|
+
expect(button.length).toBe(2); // Switch will generate a button
|
|
130
|
+
expect(button[1].innerHTML).toContain('OK');
|
|
131
|
+
|
|
132
|
+
await act(async () => {
|
|
133
|
+
button[1].click();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
expect(handleClick).toBeCalled();
|
|
137
|
+
|
|
138
|
+
jest.runOnlyPendingTimers();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test('Prompt tests with form submit', async () => {
|
|
142
|
+
// Click
|
|
143
|
+
const handleClick = jest.fn((result: boolean) => {
|
|
144
|
+
expect(result).toBeTruthy();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
act(() => {
|
|
148
|
+
// Add the notification
|
|
149
|
+
notifier.prompt<boolean>('Prompt message', handleClick, undefined, {
|
|
150
|
+
type: 'switch',
|
|
151
|
+
required: false
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
await act(async () => {
|
|
156
|
+
(
|
|
157
|
+
root
|
|
158
|
+
.getElementsByTagName('form')[0]
|
|
159
|
+
.elements.namedItem('okButton') as HTMLButtonElement
|
|
160
|
+
)?.click();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(handleClick).toBeCalled();
|
|
164
|
+
|
|
165
|
+
jest.runOnlyPendingTimers();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test('Message tests', (done) => {
|
|
169
|
+
// Callback
|
|
170
|
+
const callback = jest.fn(() => done());
|
|
171
|
+
|
|
172
|
+
let n: INotification<React.ReactNode, any> | undefined;
|
|
173
|
+
act(() => {
|
|
174
|
+
// Add the notification
|
|
175
|
+
n = notifier.message(
|
|
176
|
+
NotificationMessageType.Danger,
|
|
177
|
+
'Error Message',
|
|
178
|
+
undefined,
|
|
179
|
+
{
|
|
180
|
+
callback
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
expect(n?.timespan).toBe(5);
|
|
186
|
+
|
|
187
|
+
expect(root.innerHTML).toContain('Error Message');
|
|
188
|
+
|
|
189
|
+
act(() => {
|
|
190
|
+
// Here is the bug need further study...
|
|
191
|
+
n?.dismiss();
|
|
192
|
+
|
|
193
|
+
// Fast forward
|
|
194
|
+
jest.runOnlyPendingTimers();
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
expect(root.innerHTML).not.toContain('Error Message');
|
|
198
|
+
expect(callback).toBeCalled();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
test('Loading tests', () => {
|
|
202
|
+
act(() => {
|
|
203
|
+
// Add the notification
|
|
204
|
+
notifier.showLoading('Loading');
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
expect(root.innerHTML).toContain('Loading');
|
|
208
|
+
|
|
209
|
+
act(() => {
|
|
210
|
+
notifier.hideLoading();
|
|
211
|
+
|
|
212
|
+
// Fast forward
|
|
213
|
+
jest.runOnlyPendingTimers();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(root.innerHTML).not.toContain('Loading');
|
|
217
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SelectEx } from '../src';
|
|
3
|
+
import { findByText, fireEvent, render, screen } from '@testing-library/react';
|
|
4
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
5
|
+
|
|
6
|
+
it('Render SelectEx', async () => {
|
|
7
|
+
// Arrange
|
|
8
|
+
type T = { id: number; name: string };
|
|
9
|
+
const options: T[] = [
|
|
10
|
+
{ id: 1, name: 'Name 1' },
|
|
11
|
+
{ id: 2, name: 'Name 2' }
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
// Render component
|
|
15
|
+
const { baseElement } = render(
|
|
16
|
+
<SelectEx<T> options={options} name="test" search labelField="name" />
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// Act, click to show the list
|
|
20
|
+
const button = screen.getByRole('button');
|
|
21
|
+
fireEvent.mouseDown(button); // Not click
|
|
22
|
+
|
|
23
|
+
// Get list item
|
|
24
|
+
const item = await findByText(baseElement, 'Name 2');
|
|
25
|
+
expect(item.nodeName).toBe('SPAN');
|
|
26
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2019",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"allowSyntheticDefaultImports": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"moduleResolution": "node",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "react",
|
|
16
|
+
"declaration": true
|
|
17
|
+
},
|
|
18
|
+
"include": [".."]
|
|
19
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Theme } from '@mui/material';
|
|
2
|
+
import React, { CSSProperties } from 'react';
|
|
3
|
+
import { ListMoreDisplayProps } from './ListMoreDisplay';
|
|
4
|
+
import { AuditLineUpdateData } from './ShowDataComparison';
|
|
5
|
+
/**
|
|
6
|
+
* Audit line data model
|
|
7
|
+
*/
|
|
8
|
+
export interface AuditLine {
|
|
9
|
+
id: number;
|
|
10
|
+
creation: Date;
|
|
11
|
+
user: string;
|
|
12
|
+
action: string;
|
|
13
|
+
changes?: AuditLineUpdateData;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Audit display props
|
|
17
|
+
*/
|
|
18
|
+
export interface AuditDisplayProps extends Omit<ListMoreDisplayProps<AuditLine>, 'children'> {
|
|
19
|
+
/**
|
|
20
|
+
* Get list item style callback
|
|
21
|
+
*/
|
|
22
|
+
getItemStyle?: (index: number, theme: Theme) => CSSProperties;
|
|
23
|
+
/**
|
|
24
|
+
* Item/line renderer
|
|
25
|
+
*/
|
|
26
|
+
itemRenderer?: (data: AuditLine, index: number) => React.ReactNode;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Audit display
|
|
30
|
+
* @param props Props
|
|
31
|
+
* @returns Component
|
|
32
|
+
*/
|
|
33
|
+
export declare function AuditDisplay(props: AuditDisplayProps): JSX.Element;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Utils } from '@etsoo/shared';
|
|
2
|
+
import { Button, Divider, Typography, useTheme } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { globalApp } from './app/ReactApp';
|
|
5
|
+
import { ListMoreDisplay } from './ListMoreDisplay';
|
|
6
|
+
import { ShowDataComparison } from './ShowDataComparison';
|
|
7
|
+
// Get label
|
|
8
|
+
const getLabel = (key) => {
|
|
9
|
+
var _a;
|
|
10
|
+
return (_a = globalApp.get(Utils.formatInitial(key))) !== null && _a !== void 0 ? _a : key;
|
|
11
|
+
};
|
|
12
|
+
// Format date
|
|
13
|
+
const formatDate = (date) => {
|
|
14
|
+
if (typeof globalApp === 'undefined')
|
|
15
|
+
return date.toUTCString();
|
|
16
|
+
return globalApp.formatDate(date, 'ds');
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Audit display
|
|
20
|
+
* @param props Props
|
|
21
|
+
* @returns Component
|
|
22
|
+
*/
|
|
23
|
+
export function AuditDisplay(props) {
|
|
24
|
+
// Theme
|
|
25
|
+
const theme = useTheme();
|
|
26
|
+
// Title
|
|
27
|
+
var title = getLabel('dataComparison');
|
|
28
|
+
// Destruct
|
|
29
|
+
const { getItemStyle = (index, theme) => ({
|
|
30
|
+
padding: [theme.spacing(1.5), theme.spacing(1)].join(' '),
|
|
31
|
+
background: index % 2 === 0
|
|
32
|
+
? theme.palette.grey[100]
|
|
33
|
+
: theme.palette.grey[50]
|
|
34
|
+
}), itemRenderer = (data) => {
|
|
35
|
+
const changes = data.changes;
|
|
36
|
+
return (React.createElement(React.Fragment, null,
|
|
37
|
+
changes != null && (React.createElement(Button, { variant: "outlined", size: "small", onClick: () => ShowDataComparison(changes, title), sx: {
|
|
38
|
+
marginLeft: theme.spacing(1),
|
|
39
|
+
marginTop: theme.spacing(-0.5),
|
|
40
|
+
float: 'right'
|
|
41
|
+
} }, title)),
|
|
42
|
+
React.createElement(Typography, null, formatDate(data.creation) +
|
|
43
|
+
', [' +
|
|
44
|
+
getLabel(data.action) +
|
|
45
|
+
'], ' +
|
|
46
|
+
data.user)));
|
|
47
|
+
}, headerTitle = (React.createElement(React.Fragment, null,
|
|
48
|
+
React.createElement(Typography, null, getLabel('audits')),
|
|
49
|
+
React.createElement(Divider, null))), ...rest } = props;
|
|
50
|
+
// Layout
|
|
51
|
+
return (React.createElement(ListMoreDisplay, { headerTitle: headerTitle, ...rest }, (data, index) => (React.createElement("div", { key: data.id, style: getItemStyle(index, theme) }, itemRenderer(data, index)))));
|
|
52
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DataTypes } from '@etsoo/shared';
|
|
2
|
+
import { AutocompleteProps } from '@mui/material';
|
|
3
|
+
import { ChangeEventHandler } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* Autocomplete extended props
|
|
6
|
+
*/
|
|
7
|
+
export declare type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys<T>> = Omit<AutocompleteProps<T, undefined, false, false>, 'renderInput' | 'options'> & {
|
|
8
|
+
/**
|
|
9
|
+
* Id field
|
|
10
|
+
*/
|
|
11
|
+
idField?: D;
|
|
12
|
+
/**
|
|
13
|
+
* Id value
|
|
14
|
+
*/
|
|
15
|
+
idValue?: T[D];
|
|
16
|
+
/**
|
|
17
|
+
* Autocomplete for the input
|
|
18
|
+
*/
|
|
19
|
+
inputAutoComplete?: string;
|
|
20
|
+
/**
|
|
21
|
+
* If `true`, the label is displayed in an error state.
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
inputError?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The helper text content.
|
|
27
|
+
*/
|
|
28
|
+
inputHelperText?: React.ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* If `dense` or `normal`, will adjust vertical spacing of this and contained components.
|
|
31
|
+
* @default 'none'
|
|
32
|
+
*/
|
|
33
|
+
inputMargin?: 'dense' | 'normal' | 'none';
|
|
34
|
+
/**
|
|
35
|
+
* Input onChange hanlder
|
|
36
|
+
*/
|
|
37
|
+
inputOnChange?: ChangeEventHandler<HTMLInputElement> | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* If `true`, the label will indicate that the `input` is required.
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
inputRequired?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* The variant to use.
|
|
45
|
+
* @default 'outlined'
|
|
46
|
+
*/
|
|
47
|
+
inputVariant?: 'standard' | 'outlined' | 'filled';
|
|
48
|
+
/**
|
|
49
|
+
* Label of the field
|
|
50
|
+
*/
|
|
51
|
+
label: string;
|
|
52
|
+
/**
|
|
53
|
+
* Name of the field
|
|
54
|
+
*/
|
|
55
|
+
name: string;
|
|
56
|
+
/**
|
|
57
|
+
* Is the field read only?
|
|
58
|
+
*/
|
|
59
|
+
readOnly?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Is search field?
|
|
62
|
+
*/
|
|
63
|
+
search?: boolean;
|
|
64
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { IconButtonProps } from '@mui/material';
|
|
3
|
+
/**
|
|
4
|
+
* BackButton props
|
|
5
|
+
*/
|
|
6
|
+
export interface BackButtonProps extends IconButtonProps {
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* BackButton
|
|
10
|
+
* @param props Props
|
|
11
|
+
* @returns Component
|
|
12
|
+
*/
|
|
13
|
+
export declare function BackButton(props: BackButtonProps): JSX.Element;
|