@etsoo/materialui 1.2.41 → 1.2.43
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/DataGridEx.d.ts +8 -0
- package/lib/GridDataCacheType.d.ts +9 -0
- package/lib/GridDataCacheType.js +1 -0
- package/lib/ResponsibleContainer.d.ts +2 -2
- package/lib/ResponsibleContainer.js +59 -5
- package/lib/pages/DataGridPage.js +47 -4
- package/lib/pages/FixedListPage.js +47 -4
- package/lib/pages/ListPage.d.ts +3 -3
- package/lib/pages/ListPage.js +52 -11
- package/lib/pages/ListPageProps.d.ts +4 -4
- package/lib/pages/SearchPageProps.d.ts +9 -1
- package/lib/pages/TablePage.d.ts +3 -3
- package/lib/pages/TablePage.js +16 -12
- package/package.json +2 -2
- package/src/DataGridEx.tsx +10 -0
- package/src/GridDataCacheType.ts +10 -0
- package/src/ResponsibleContainer.tsx +108 -4
- package/src/pages/DataGridPage.tsx +76 -1
- package/src/pages/FixedListPage.tsx +73 -1
- package/src/pages/ListPage.tsx +148 -80
- package/src/pages/ListPageProps.ts +7 -7
- package/src/pages/SearchPageProps.ts +13 -1
- package/src/pages/TablePage.tsx +130 -116
package/lib/DataGridEx.d.ts
CHANGED
|
@@ -20,6 +20,14 @@ export type DataGridExProps<T extends object, D extends DataTypes.Keys<T>> = Omi
|
|
|
20
20
|
* Alternating colors for odd/even rows
|
|
21
21
|
*/
|
|
22
22
|
alternatingColors?: [string?, string?];
|
|
23
|
+
/**
|
|
24
|
+
* Cache key
|
|
25
|
+
*/
|
|
26
|
+
cacheKey?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Cache minutes
|
|
29
|
+
*/
|
|
30
|
+
cacheMinutes?: number;
|
|
23
31
|
/**
|
|
24
32
|
* Checkable to choose multiple items
|
|
25
33
|
* @default false
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,7 +8,7 @@ import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from "./
|
|
|
8
8
|
/**
|
|
9
9
|
* ResponsibleContainer props
|
|
10
10
|
*/
|
|
11
|
-
export type ResponsibleContainerProps<T extends object, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridExProps<T, D>, "height" | "itemKey" | "loadData" | "mRef" | "onScroll" | "onItemsRendered"> & {
|
|
11
|
+
export type ResponsibleContainerProps<T extends object, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridExProps<T, D>, "height" | "itemKey" | "loadData" | "mRef" | "onScroll" | "onItemsRendered" | "onInitLoad" | "onUpdateRows"> & {
|
|
12
12
|
/**
|
|
13
13
|
* Height will be deducted
|
|
14
14
|
* @param height Current calcuated height
|
|
@@ -37,7 +37,7 @@ export type ResponsibleContainerProps<T extends object, F extends DataTypes.Basi
|
|
|
37
37
|
/**
|
|
38
38
|
* Search fields
|
|
39
39
|
*/
|
|
40
|
-
fields?: React.ReactElement[];
|
|
40
|
+
fields?: React.ReactElement[] | ((data: DataTypes.BasicTemplateType<F>) => React.ReactElement[]);
|
|
41
41
|
/**
|
|
42
42
|
* Search field template
|
|
43
43
|
*/
|
|
@@ -22,7 +22,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
|
|
|
22
22
|
*/
|
|
23
23
|
export function ResponsibleContainer(props) {
|
|
24
24
|
// Destruct
|
|
25
|
-
const { adjustHeight, adjustFabHeight, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, ...rest } = props;
|
|
25
|
+
const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 120, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, ...rest } = props;
|
|
26
26
|
// Labels
|
|
27
27
|
const labels = Labels.CommonPage;
|
|
28
28
|
// Refs
|
|
@@ -45,6 +45,8 @@ export function ResponsibleContainer(props) {
|
|
|
45
45
|
const localLoadData = (props) => {
|
|
46
46
|
state.mounted = true;
|
|
47
47
|
const data = GridDataGet(props, fieldTemplate);
|
|
48
|
+
if (cacheKey)
|
|
49
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
48
50
|
return loadData(data);
|
|
49
51
|
};
|
|
50
52
|
// On submit callback
|
|
@@ -70,6 +72,54 @@ export function ResponsibleContainer(props) {
|
|
|
70
72
|
state.rect = rect;
|
|
71
73
|
return false;
|
|
72
74
|
});
|
|
75
|
+
const onUpdateRows = (rows, state) => {
|
|
76
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
77
|
+
const data = { rows, state, creation: new Date().valueOf() };
|
|
78
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const onInitLoad = (ref) => {
|
|
82
|
+
// Avoid repeatedly load from cache
|
|
83
|
+
if (refs.current.initLoaded || !cacheKey)
|
|
84
|
+
return undefined;
|
|
85
|
+
// Cache data
|
|
86
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
87
|
+
if (cacheData) {
|
|
88
|
+
const { rows, state, creation } = JSON.parse(cacheData);
|
|
89
|
+
// 120 minutes
|
|
90
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
91
|
+
sessionStorage.removeItem(cacheKey);
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
// Scroll position
|
|
95
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
96
|
+
if (scrollData) {
|
|
97
|
+
if ("resetAfterColumnIndex" in ref) {
|
|
98
|
+
const { scrollLeft, scrollTop } = JSON.parse(scrollData);
|
|
99
|
+
globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const { scrollOffset } = JSON.parse(scrollData);
|
|
103
|
+
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Update flag value
|
|
107
|
+
refs.current.initLoaded = true;
|
|
108
|
+
// Return cached rows and state
|
|
109
|
+
return [rows, state];
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
};
|
|
113
|
+
const onListScroll = (props) => {
|
|
114
|
+
if (!cacheKey || !refs.current.initLoaded)
|
|
115
|
+
return;
|
|
116
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
117
|
+
};
|
|
118
|
+
const onGridScroll = (props) => {
|
|
119
|
+
if (!cacheKey || !refs.current.initLoaded)
|
|
120
|
+
return;
|
|
121
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
122
|
+
};
|
|
73
123
|
// Rect
|
|
74
124
|
const rect = dimensions[0][2];
|
|
75
125
|
// Create list
|
|
@@ -107,7 +157,7 @@ export function ResponsibleContainer(props) {
|
|
|
107
157
|
React.createElement(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), outerRef: (element) => {
|
|
108
158
|
if (element != null && elementReady)
|
|
109
159
|
elementReady(element, true);
|
|
110
|
-
}, columns: columns, ...rest })),
|
|
160
|
+
}, onScroll: onGridScroll, columns: columns, onUpdateRows: onUpdateRows, onInitLoad: onInitLoad, ...rest })),
|
|
111
161
|
true
|
|
112
162
|
];
|
|
113
163
|
}
|
|
@@ -122,17 +172,21 @@ export function ResponsibleContainer(props) {
|
|
|
122
172
|
delete rest.selectable;
|
|
123
173
|
return [
|
|
124
174
|
React.createElement(Box, { className: "ListBox", sx: { height: heightLocal } },
|
|
125
|
-
React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), oRef: (element) => {
|
|
175
|
+
React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, onUpdateRows: onUpdateRows, onInitLoad: onInitLoad, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), oRef: (element) => {
|
|
126
176
|
if (element != null && elementReady)
|
|
127
177
|
elementReady(element, false);
|
|
128
|
-
}, ...rest })),
|
|
178
|
+
}, onScroll: onListScroll, ...rest })),
|
|
129
179
|
false
|
|
130
180
|
];
|
|
131
181
|
})();
|
|
132
182
|
const searchBar = React.useMemo(() => {
|
|
183
|
+
var _a;
|
|
133
184
|
if (!hasFields || showDataGrid == null)
|
|
134
185
|
return;
|
|
135
|
-
|
|
186
|
+
const f = typeof fields == "function"
|
|
187
|
+
? fields(JSON.parse((_a = sessionStorage.getItem(`${cacheKey}-searchbar`)) !== null && _a !== void 0 ? _a : "{}"))
|
|
188
|
+
: fields;
|
|
189
|
+
return (React.createElement(SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}` }));
|
|
136
190
|
}, [showDataGrid, hasFields, searchBarHeight]);
|
|
137
191
|
// Pull container
|
|
138
192
|
const pullContainer = showDataGrid == null
|
|
@@ -11,9 +11,9 @@ import { CommonPage } from "./CommonPage";
|
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
13
|
export function DataGridPage(props) {
|
|
14
|
-
var _a;
|
|
14
|
+
var _a, _b;
|
|
15
15
|
// Destruct
|
|
16
|
-
const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, ...rest } = props;
|
|
16
|
+
const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, cacheKey, cacheMinutes = 120, ...rest } = props;
|
|
17
17
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
18
18
|
// States
|
|
19
19
|
const [states, setStates] = React.useReducer((currentState, newState) => {
|
|
@@ -27,14 +27,54 @@ export function DataGridPage(props) {
|
|
|
27
27
|
states.ref = ref;
|
|
28
28
|
//setStates({ ref });
|
|
29
29
|
});
|
|
30
|
+
const initLoadedRef = React.useRef();
|
|
30
31
|
// On submit callback
|
|
31
32
|
const onSubmit = (data, _reset) => {
|
|
32
33
|
setStates({ data });
|
|
33
34
|
};
|
|
34
35
|
const localLoadData = (props) => {
|
|
35
36
|
const data = GridDataGet(props, fieldTemplate);
|
|
37
|
+
if (cacheKey)
|
|
38
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
36
39
|
return loadData(data);
|
|
37
40
|
};
|
|
41
|
+
const onUpdateRows = (rows, state) => {
|
|
42
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
43
|
+
const data = { rows, state, creation: new Date().valueOf() };
|
|
44
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const onInitLoad = (ref) => {
|
|
48
|
+
// Avoid repeatedly load from cache
|
|
49
|
+
if (initLoadedRef.current || !cacheKey)
|
|
50
|
+
return undefined;
|
|
51
|
+
// Cache data
|
|
52
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
53
|
+
if (cacheData) {
|
|
54
|
+
const { rows, state, creation } = JSON.parse(cacheData);
|
|
55
|
+
// 120 minutes
|
|
56
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
57
|
+
sessionStorage.removeItem(cacheKey);
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
// Scroll position
|
|
61
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
62
|
+
if (scrollData) {
|
|
63
|
+
const { scrollLeft, scrollTop } = JSON.parse(scrollData);
|
|
64
|
+
globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0);
|
|
65
|
+
}
|
|
66
|
+
// Update flag value
|
|
67
|
+
initLoadedRef.current = true;
|
|
68
|
+
// Return cached rows and state
|
|
69
|
+
return [rows, state];
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
};
|
|
73
|
+
const onGridScroll = (props) => {
|
|
74
|
+
if (!cacheKey || !initLoadedRef.current)
|
|
75
|
+
return;
|
|
76
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
77
|
+
};
|
|
38
78
|
// Watch container
|
|
39
79
|
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
40
80
|
const rect = dimensions[0][2];
|
|
@@ -56,7 +96,7 @@ export function DataGridPage(props) {
|
|
|
56
96
|
const gridHeight = states.height;
|
|
57
97
|
if (gridHeight == null)
|
|
58
98
|
return;
|
|
59
|
-
return (React.createElement(DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, outerRef: (element) => {
|
|
99
|
+
return (React.createElement(DataGridEx, { autoLoad: false, height: gridHeight, loadData: localLoadData, mRef: refs, onUpdateRows: onUpdateRows, onInitLoad: onInitLoad, onScroll: onGridScroll, outerRef: (element) => {
|
|
60
100
|
if (element != null)
|
|
61
101
|
setStates({ element });
|
|
62
102
|
}, ...rest }));
|
|
@@ -67,12 +107,15 @@ export function DataGridPage(props) {
|
|
|
67
107
|
return;
|
|
68
108
|
ref.reset({ data });
|
|
69
109
|
}, [ref, data]);
|
|
110
|
+
const f = typeof fields == "function"
|
|
111
|
+
? fields(JSON.parse((_b = sessionStorage.getItem(`${cacheKey}-searchbar`)) !== null && _b !== void 0 ? _b : "{}"))
|
|
112
|
+
: fields;
|
|
70
113
|
// Layout
|
|
71
114
|
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: states.element },
|
|
72
115
|
React.createElement(Stack, null,
|
|
73
116
|
React.createElement(Box, { ref: dimensions[0][0], sx: {
|
|
74
117
|
paddingBottom: pageProps.paddings
|
|
75
118
|
} },
|
|
76
|
-
React.createElement(SearchBar, { fields:
|
|
119
|
+
React.createElement(SearchBar, { fields: f, onSubmit: onSubmit })),
|
|
77
120
|
list)));
|
|
78
121
|
}
|
|
@@ -11,12 +11,13 @@ import { CommonPage } from "./CommonPage";
|
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
13
|
export function FixedListPage(props) {
|
|
14
|
-
var _a;
|
|
14
|
+
var _a, _b;
|
|
15
15
|
// Destruct
|
|
16
|
-
const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, ...rest } = props;
|
|
16
|
+
const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 120, ...rest } = props;
|
|
17
17
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
18
18
|
// States
|
|
19
19
|
const [states] = React.useState({});
|
|
20
|
+
const initLoadedRef = React.useRef();
|
|
20
21
|
// Scroll container
|
|
21
22
|
const [scrollContainer, updateScrollContainer] = React.useState();
|
|
22
23
|
const refs = useCombinedRefs(mRef, (ref) => {
|
|
@@ -39,8 +40,47 @@ export function FixedListPage(props) {
|
|
|
39
40
|
};
|
|
40
41
|
const localLoadData = (props) => {
|
|
41
42
|
const data = GridDataGet(props, fieldTemplate);
|
|
43
|
+
if (cacheKey)
|
|
44
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
42
45
|
return loadData(data);
|
|
43
46
|
};
|
|
47
|
+
const onUpdateRows = (rows, state) => {
|
|
48
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
49
|
+
const data = { rows, state, creation: new Date().valueOf() };
|
|
50
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const onInitLoad = (ref) => {
|
|
54
|
+
// Avoid repeatedly load from cache
|
|
55
|
+
if (initLoadedRef.current || !cacheKey)
|
|
56
|
+
return undefined;
|
|
57
|
+
// Cache data
|
|
58
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
59
|
+
if (cacheData) {
|
|
60
|
+
const { rows, state, creation } = JSON.parse(cacheData);
|
|
61
|
+
// 120 minutes
|
|
62
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
63
|
+
sessionStorage.removeItem(cacheKey);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
// Scroll position
|
|
67
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
68
|
+
if (scrollData) {
|
|
69
|
+
const { scrollOffset } = JSON.parse(scrollData);
|
|
70
|
+
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
71
|
+
}
|
|
72
|
+
// Update flag value
|
|
73
|
+
initLoadedRef.current = true;
|
|
74
|
+
// Return cached rows and state
|
|
75
|
+
return [rows, state];
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
};
|
|
79
|
+
const onListScroll = (props) => {
|
|
80
|
+
if (!cacheKey || !initLoadedRef.current)
|
|
81
|
+
return;
|
|
82
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
83
|
+
};
|
|
44
84
|
// Watch container
|
|
45
85
|
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
46
86
|
const rect = dimensions[0][2];
|
|
@@ -53,17 +93,20 @@ export function FixedListPage(props) {
|
|
|
53
93
|
return (React.createElement(Box, { id: "list-container", sx: {
|
|
54
94
|
height: height + "px"
|
|
55
95
|
} },
|
|
56
|
-
React.createElement(ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, oRef: (element) => {
|
|
96
|
+
React.createElement(ScrollerListEx, { autoLoad: false, height: height, loadData: localLoadData, mRef: refs, onUpdateRows: onUpdateRows, onInitLoad: onInitLoad, onScroll: onListScroll, oRef: (element) => {
|
|
57
97
|
if (element != null)
|
|
58
98
|
updateScrollContainer(element);
|
|
59
99
|
}, ...rest })));
|
|
60
100
|
}
|
|
61
101
|
}, [rect]);
|
|
102
|
+
const f = typeof fields == "function"
|
|
103
|
+
? fields(JSON.parse((_b = sessionStorage.getItem(`${cacheKey}-searchbar`)) !== null && _b !== void 0 ? _b : "{}"))
|
|
104
|
+
: fields;
|
|
62
105
|
const { paddings, ...pageRest } = pageProps;
|
|
63
106
|
// Layout
|
|
64
107
|
return (React.createElement(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer },
|
|
65
108
|
React.createElement(Stack, null,
|
|
66
109
|
React.createElement(Box, { ref: dimensions[0][0], sx: { padding: paddings } },
|
|
67
|
-
React.createElement(SearchBar, { fields:
|
|
110
|
+
React.createElement(SearchBar, { fields: f, onSubmit: onSubmit })),
|
|
68
111
|
list)));
|
|
69
112
|
}
|
package/lib/pages/ListPage.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DataTypes, IdDefaultType } from
|
|
2
|
-
import React from
|
|
3
|
-
import { ListPageProps } from
|
|
1
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { ListPageProps } from "./ListPageProps";
|
|
4
4
|
/**
|
|
5
5
|
* List page
|
|
6
6
|
* @param props Props
|
package/lib/pages/ListPage.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { GridDataGet, useCombinedRefs } from
|
|
2
|
-
import { Box, Stack } from
|
|
3
|
-
import React from
|
|
4
|
-
import { MUGlobal } from
|
|
5
|
-
import { ScrollerListEx } from
|
|
6
|
-
import { SearchBar } from
|
|
7
|
-
import { CommonPage, CommonPageScrollContainer } from
|
|
1
|
+
import { GridDataGet, useCombinedRefs } from "@etsoo/react";
|
|
2
|
+
import { Box, Stack } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { ScrollerListEx } from "../ScrollerListEx";
|
|
6
|
+
import { SearchBar } from "../SearchBar";
|
|
7
|
+
import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
|
|
8
8
|
/**
|
|
9
9
|
* List page
|
|
10
10
|
* @param props Props
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
13
|
export function ListPage(props) {
|
|
14
|
-
var _a;
|
|
14
|
+
var _a, _b;
|
|
15
15
|
// Destruct
|
|
16
|
-
const { fields, fieldTemplate, loadData, mRef, pageProps = {}, ...rest } = props;
|
|
16
|
+
const { fields, fieldTemplate, loadData, mRef, pageProps = {}, cacheKey, cacheMinutes = 120, ...rest } = props;
|
|
17
17
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
18
18
|
// States
|
|
19
19
|
const [states] = React.useState({});
|
|
@@ -25,6 +25,7 @@ export function ListPage(props) {
|
|
|
25
25
|
if (first)
|
|
26
26
|
reset();
|
|
27
27
|
});
|
|
28
|
+
const initLoadedRef = React.useRef();
|
|
28
29
|
const reset = () => {
|
|
29
30
|
if (states.data == null || states.ref == null)
|
|
30
31
|
return;
|
|
@@ -39,12 +40,52 @@ export function ListPage(props) {
|
|
|
39
40
|
const data = GridDataGet(props, fieldTemplate);
|
|
40
41
|
return loadData(data);
|
|
41
42
|
};
|
|
43
|
+
const onUpdateRows = (rows, state) => {
|
|
44
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
45
|
+
const data = { rows, state, creation: new Date().valueOf() };
|
|
46
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const onInitLoad = (ref) => {
|
|
50
|
+
// Avoid repeatedly load from cache
|
|
51
|
+
if (initLoadedRef.current || !cacheKey)
|
|
52
|
+
return undefined;
|
|
53
|
+
// Cache data
|
|
54
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
55
|
+
if (cacheData) {
|
|
56
|
+
const { rows, state, creation } = JSON.parse(cacheData);
|
|
57
|
+
// 120 minutes
|
|
58
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
59
|
+
sessionStorage.removeItem(cacheKey);
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
// Scroll position
|
|
63
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
64
|
+
if (scrollData) {
|
|
65
|
+
const { scrollOffset } = JSON.parse(scrollData);
|
|
66
|
+
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
67
|
+
}
|
|
68
|
+
// Update flag value
|
|
69
|
+
initLoadedRef.current = true;
|
|
70
|
+
// Return cached rows and state
|
|
71
|
+
return [rows, state];
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
};
|
|
75
|
+
const onListScroll = (props) => {
|
|
76
|
+
if (!cacheKey || !initLoadedRef.current)
|
|
77
|
+
return;
|
|
78
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
79
|
+
};
|
|
80
|
+
const f = typeof fields == "function"
|
|
81
|
+
? fields(JSON.parse((_b = sessionStorage.getItem(`${cacheKey}-searchbar`)) !== null && _b !== void 0 ? _b : "{}"))
|
|
82
|
+
: fields;
|
|
42
83
|
// Layout
|
|
43
84
|
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer },
|
|
44
85
|
React.createElement(Stack, null,
|
|
45
86
|
React.createElement(Box, { sx: {
|
|
46
87
|
paddingBottom: pageProps.paddings
|
|
47
88
|
} },
|
|
48
|
-
React.createElement(SearchBar, { fields:
|
|
49
|
-
React.createElement(ScrollerListEx, { autoLoad: false, loadData: localLoadData, mRef: refs, ...rest }))));
|
|
89
|
+
React.createElement(SearchBar, { fields: f, onSubmit: onSubmit })),
|
|
90
|
+
React.createElement(ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: onUpdateRows, onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest }))));
|
|
50
91
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { DataTypes } from
|
|
2
|
-
import { ScrollerListExProps } from
|
|
3
|
-
import { SearchPageProps } from
|
|
1
|
+
import { DataTypes } from "@etsoo/shared";
|
|
2
|
+
import { ScrollerListExProps } from "../ScrollerListEx";
|
|
3
|
+
import { SearchPageProps } from "./SearchPageProps";
|
|
4
4
|
/**
|
|
5
5
|
* List page props
|
|
6
6
|
*/
|
|
7
|
-
export type ListPageProps<T extends object, F extends DataTypes.BasicTemplate, D extends DataTypes.Keys<T>> = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>,
|
|
7
|
+
export type ListPageProps<T extends object, F extends DataTypes.BasicTemplate, D extends DataTypes.Keys<T>> = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>, "loadData">;
|
|
@@ -6,10 +6,18 @@ import { CommonPageProps } from "./CommonPageProps";
|
|
|
6
6
|
* Search page props
|
|
7
7
|
*/
|
|
8
8
|
export type SearchPageProps<T extends object, F extends DataTypes.BasicTemplate> = Omit<GridLoader<T>, "loadData"> & {
|
|
9
|
+
/**
|
|
10
|
+
* Cache key
|
|
11
|
+
*/
|
|
12
|
+
cacheKey?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Cache minutes
|
|
15
|
+
*/
|
|
16
|
+
cacheMinutes?: number;
|
|
9
17
|
/**
|
|
10
18
|
* Search fields
|
|
11
19
|
*/
|
|
12
|
-
fields: React.ReactElement[];
|
|
20
|
+
fields: React.ReactElement[] | ((data: DataTypes.BasicTemplateType<F>) => React.ReactElement[]);
|
|
13
21
|
/**
|
|
14
22
|
* Search field template
|
|
15
23
|
*/
|
package/lib/pages/TablePage.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DataTypes, IdDefaultType } from
|
|
2
|
-
import React from
|
|
3
|
-
import { TablePageProps } from
|
|
1
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { TablePageProps } from "./TablePageProps";
|
|
4
4
|
/**
|
|
5
5
|
* Table page
|
|
6
6
|
* @param props Props
|
package/lib/pages/TablePage.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { GridDataGet, useCombinedRefs, useDimensions } from
|
|
2
|
-
import { Box, Stack } from
|
|
3
|
-
import React from
|
|
4
|
-
import { MUGlobal } from
|
|
5
|
-
import { SearchBar } from
|
|
6
|
-
import { TableEx, TableExMinWidth } from
|
|
7
|
-
import { CommonPage, CommonPageScrollContainer } from
|
|
1
|
+
import { GridDataGet, useCombinedRefs, useDimensions } from "@etsoo/react";
|
|
2
|
+
import { Box, Stack } from "@mui/material";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { MUGlobal } from "../MUGlobal";
|
|
5
|
+
import { SearchBar } from "../SearchBar";
|
|
6
|
+
import { TableEx, TableExMinWidth } from "../TableEx";
|
|
7
|
+
import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
|
|
8
8
|
/**
|
|
9
9
|
* Table page
|
|
10
10
|
* @param props Props
|
|
11
11
|
* @returns Component
|
|
12
12
|
*/
|
|
13
13
|
export function TablePage(props) {
|
|
14
|
-
var _a;
|
|
14
|
+
var _a, _b;
|
|
15
15
|
// Destruct
|
|
16
|
-
const { columns, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, ...rest } = props;
|
|
16
|
+
const { columns, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 120, ...rest } = props;
|
|
17
17
|
(_a = pageProps.paddings) !== null && _a !== void 0 ? _a : (pageProps.paddings = MUGlobal.pagePaddings);
|
|
18
18
|
// States
|
|
19
19
|
const [states] = React.useState({});
|
|
@@ -37,6 +37,8 @@ export function TablePage(props) {
|
|
|
37
37
|
};
|
|
38
38
|
const localLoadData = (props) => {
|
|
39
39
|
const data = GridDataGet(props, fieldTemplate);
|
|
40
|
+
if (cacheKey)
|
|
41
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
40
42
|
return loadData(data);
|
|
41
43
|
};
|
|
42
44
|
// Total width
|
|
@@ -49,8 +51,7 @@ export function TablePage(props) {
|
|
|
49
51
|
const rect = dimensions[0][2];
|
|
50
52
|
const list = React.useMemo(() => {
|
|
51
53
|
if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
|
|
52
|
-
let maxHeight = document.documentElement.clientHeight -
|
|
53
|
-
(rect.top + rect.height + 1);
|
|
54
|
+
let maxHeight = document.documentElement.clientHeight - (rect.top + rect.height + 1);
|
|
54
55
|
const style = window.getComputedStyle(dimensions[0][1]);
|
|
55
56
|
const paddingBottom = parseFloat(style.paddingBottom);
|
|
56
57
|
if (!isNaN(paddingBottom))
|
|
@@ -58,12 +59,15 @@ export function TablePage(props) {
|
|
|
58
59
|
return (React.createElement(TableEx, { autoLoad: false, columns: columns, loadData: localLoadData, maxHeight: maxHeight, mRef: refs, ...rest }));
|
|
59
60
|
}
|
|
60
61
|
}, [rect]);
|
|
62
|
+
const f = typeof fields == "function"
|
|
63
|
+
? fields(JSON.parse((_b = sessionStorage.getItem(`${cacheKey}-searchbar`)) !== null && _b !== void 0 ? _b : "{}"))
|
|
64
|
+
: fields;
|
|
61
65
|
// Layout
|
|
62
66
|
return (React.createElement(CommonPage, { ...pageProps, scrollContainer: CommonPageScrollContainer },
|
|
63
67
|
React.createElement(Stack, null,
|
|
64
68
|
React.createElement(Box, { ref: dimensions[0][0], sx: {
|
|
65
69
|
paddingBottom: pageProps.paddings
|
|
66
70
|
} },
|
|
67
|
-
React.createElement(SearchBar, { fields:
|
|
71
|
+
React.createElement(SearchBar, { fields: f, onSubmit: onSubmit })),
|
|
68
72
|
list)));
|
|
69
73
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.43",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"@emotion/styled": "^11.11.0",
|
|
53
53
|
"@etsoo/appscript": "^1.4.8",
|
|
54
54
|
"@etsoo/notificationbase": "^1.1.25",
|
|
55
|
-
"@etsoo/react": "^1.6.
|
|
55
|
+
"@etsoo/react": "^1.6.84",
|
|
56
56
|
"@etsoo/shared": "^1.2.5",
|
|
57
57
|
"@mui/icons-material": "^5.11.16",
|
|
58
58
|
"@mui/material": "^5.13.0",
|
package/src/DataGridEx.tsx
CHANGED
|
@@ -51,6 +51,16 @@ export type DataGridExProps<
|
|
|
51
51
|
*/
|
|
52
52
|
alternatingColors?: [string?, string?];
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Cache key
|
|
56
|
+
*/
|
|
57
|
+
cacheKey?: string;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Cache minutes
|
|
61
|
+
*/
|
|
62
|
+
cacheMinutes?: number;
|
|
63
|
+
|
|
54
64
|
/**
|
|
55
65
|
* Checkable to choose multiple items
|
|
56
66
|
* @default false
|