@etsoo/materialui 1.2.42 → 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 +0 -8
- 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 +1 -1
- package/src/DataGridEx.tsx +10 -0
- package/src/GridDataCacheType.ts +10 -0
- package/src/ResponsibleContainer.tsx +2 -11
- 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
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GridDataGet,
|
|
3
3
|
GridLoadDataProps,
|
|
4
|
+
GridLoaderStates,
|
|
5
|
+
ListOnScrollProps,
|
|
4
6
|
ScrollerListForwardRef,
|
|
7
|
+
ScrollerListRef,
|
|
5
8
|
useCombinedRefs,
|
|
6
9
|
useDimensions
|
|
7
10
|
} from "@etsoo/react";
|
|
@@ -13,6 +16,7 @@ import { ScrollerListEx } from "../ScrollerListEx";
|
|
|
13
16
|
import { SearchBar } from "../SearchBar";
|
|
14
17
|
import { CommonPage } from "./CommonPage";
|
|
15
18
|
import { ListPageProps } from "./ListPageProps";
|
|
19
|
+
import { GridDataCacheType } from "../GridDataCacheType";
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
22
|
* Fixed height list page
|
|
@@ -42,6 +46,8 @@ export function FixedListPage<
|
|
|
42
46
|
mRef,
|
|
43
47
|
sizeReadyMiliseconds = 0,
|
|
44
48
|
pageProps = {},
|
|
49
|
+
cacheKey,
|
|
50
|
+
cacheMinutes = 120,
|
|
45
51
|
...rest
|
|
46
52
|
} = props;
|
|
47
53
|
|
|
@@ -53,6 +59,8 @@ export function FixedListPage<
|
|
|
53
59
|
ref?: ScrollerListForwardRef<T>;
|
|
54
60
|
}>({});
|
|
55
61
|
|
|
62
|
+
const initLoadedRef = React.useRef<boolean>();
|
|
63
|
+
|
|
56
64
|
// Scroll container
|
|
57
65
|
const [scrollContainer, updateScrollContainer] = React.useState<
|
|
58
66
|
HTMLElement | undefined
|
|
@@ -84,9 +92,61 @@ export function FixedListPage<
|
|
|
84
92
|
|
|
85
93
|
const localLoadData = (props: GridLoadDataProps) => {
|
|
86
94
|
const data = GridDataGet(props, fieldTemplate);
|
|
95
|
+
|
|
96
|
+
if (cacheKey)
|
|
97
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
98
|
+
|
|
87
99
|
return loadData(data);
|
|
88
100
|
};
|
|
89
101
|
|
|
102
|
+
type DataType = GridDataCacheType<T>;
|
|
103
|
+
|
|
104
|
+
const onUpdateRows = (rows: T[], state: GridLoaderStates<T>) => {
|
|
105
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
106
|
+
const data: DataType = { rows, state, creation: new Date().valueOf() };
|
|
107
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const onInitLoad = (
|
|
112
|
+
ref: ScrollerListRef
|
|
113
|
+
): [T[], Partial<GridLoaderStates<T>>?] | null | undefined => {
|
|
114
|
+
// Avoid repeatedly load from cache
|
|
115
|
+
if (initLoadedRef.current || !cacheKey) return undefined;
|
|
116
|
+
|
|
117
|
+
// Cache data
|
|
118
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
119
|
+
if (cacheData) {
|
|
120
|
+
const { rows, state, creation } = JSON.parse(cacheData) as DataType;
|
|
121
|
+
|
|
122
|
+
// 120 minutes
|
|
123
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
124
|
+
sessionStorage.removeItem(cacheKey);
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Scroll position
|
|
129
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
130
|
+
if (scrollData) {
|
|
131
|
+
const { scrollOffset } = JSON.parse(scrollData) as ListOnScrollProps;
|
|
132
|
+
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Update flag value
|
|
136
|
+
initLoadedRef.current = true;
|
|
137
|
+
|
|
138
|
+
// Return cached rows and state
|
|
139
|
+
return [rows, state];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return undefined;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const onListScroll = (props: ListOnScrollProps) => {
|
|
146
|
+
if (!cacheKey || !initLoadedRef.current) return;
|
|
147
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
148
|
+
};
|
|
149
|
+
|
|
90
150
|
// Watch container
|
|
91
151
|
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
92
152
|
const rect = dimensions[0][2];
|
|
@@ -110,6 +170,9 @@ export function FixedListPage<
|
|
|
110
170
|
height={height}
|
|
111
171
|
loadData={localLoadData}
|
|
112
172
|
mRef={refs}
|
|
173
|
+
onUpdateRows={onUpdateRows}
|
|
174
|
+
onInitLoad={onInitLoad}
|
|
175
|
+
onScroll={onListScroll}
|
|
113
176
|
oRef={(element) => {
|
|
114
177
|
if (element != null) updateScrollContainer(element);
|
|
115
178
|
}}
|
|
@@ -120,6 +183,15 @@ export function FixedListPage<
|
|
|
120
183
|
}
|
|
121
184
|
}, [rect]);
|
|
122
185
|
|
|
186
|
+
const f =
|
|
187
|
+
typeof fields == "function"
|
|
188
|
+
? fields(
|
|
189
|
+
JSON.parse(
|
|
190
|
+
sessionStorage.getItem(`${cacheKey}-searchbar`) ?? "{}"
|
|
191
|
+
) as DataTypes.BasicTemplateType<F>
|
|
192
|
+
)
|
|
193
|
+
: fields;
|
|
194
|
+
|
|
123
195
|
const { paddings, ...pageRest } = pageProps;
|
|
124
196
|
|
|
125
197
|
// Layout
|
|
@@ -127,7 +199,7 @@ export function FixedListPage<
|
|
|
127
199
|
<CommonPage {...pageRest} paddings={{}} scrollContainer={scrollContainer}>
|
|
128
200
|
<Stack>
|
|
129
201
|
<Box ref={dimensions[0][0]} sx={{ padding: paddings }}>
|
|
130
|
-
<SearchBar fields={
|
|
202
|
+
<SearchBar fields={f} onSubmit={onSubmit} />
|
|
131
203
|
</Box>
|
|
132
204
|
{list}
|
|
133
205
|
</Stack>
|
package/src/pages/ListPage.tsx
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
2
|
+
GridDataGet,
|
|
3
|
+
GridLoadDataProps,
|
|
4
|
+
GridLoaderStates,
|
|
5
|
+
ListOnScrollProps,
|
|
6
|
+
ScrollerListForwardRef,
|
|
7
|
+
ScrollerListRef,
|
|
8
|
+
useCombinedRefs
|
|
9
|
+
} from "@etsoo/react";
|
|
10
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
11
|
+
import { Box, Stack } from "@mui/material";
|
|
12
|
+
import React from "react";
|
|
13
|
+
import { MUGlobal } from "../MUGlobal";
|
|
14
|
+
import { ScrollerListEx } from "../ScrollerListEx";
|
|
15
|
+
import { SearchBar } from "../SearchBar";
|
|
16
|
+
import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
|
|
17
|
+
import { ListPageProps } from "./ListPageProps";
|
|
18
|
+
import { GridDataCacheType } from "../GridDataCacheType";
|
|
15
19
|
|
|
16
20
|
/**
|
|
17
21
|
* List page
|
|
@@ -19,72 +23,136 @@ import { ListPageProps } from './ListPageProps';
|
|
|
19
23
|
* @returns Component
|
|
20
24
|
*/
|
|
21
25
|
export function ListPage<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
T extends object,
|
|
27
|
+
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
|
|
28
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>
|
|
25
29
|
>(props: ListPageProps<T, F, D>) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
30
|
+
// Destruct
|
|
31
|
+
const {
|
|
32
|
+
fields,
|
|
33
|
+
fieldTemplate,
|
|
34
|
+
loadData,
|
|
35
|
+
mRef,
|
|
36
|
+
pageProps = {},
|
|
37
|
+
cacheKey,
|
|
38
|
+
cacheMinutes = 120,
|
|
39
|
+
...rest
|
|
40
|
+
} = props;
|
|
41
|
+
|
|
42
|
+
pageProps.paddings ??= MUGlobal.pagePaddings;
|
|
43
|
+
|
|
44
|
+
// States
|
|
45
|
+
const [states] = React.useState<{
|
|
46
|
+
data?: FormData;
|
|
47
|
+
ref?: ScrollerListForwardRef<T>;
|
|
48
|
+
}>({});
|
|
49
|
+
|
|
50
|
+
const refs = useCombinedRefs(mRef, (ref: ScrollerListForwardRef<T>) => {
|
|
51
|
+
if (ref == null) return;
|
|
52
|
+
|
|
53
|
+
const first = states.ref == null;
|
|
54
|
+
|
|
55
|
+
states.ref = ref;
|
|
56
|
+
|
|
57
|
+
if (first) reset();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const initLoadedRef = React.useRef<boolean>();
|
|
61
|
+
|
|
62
|
+
const reset = () => {
|
|
63
|
+
if (states.data == null || states.ref == null) return;
|
|
64
|
+
states.ref.reset({ data: states.data });
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// On submit callback
|
|
68
|
+
const onSubmit = (data: FormData, _reset: boolean) => {
|
|
69
|
+
states.data = data;
|
|
70
|
+
reset();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const localLoadData = (props: GridLoadDataProps) => {
|
|
74
|
+
const data = GridDataGet(props, fieldTemplate);
|
|
75
|
+
return loadData(data);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
type DataType = GridDataCacheType<T>;
|
|
79
|
+
|
|
80
|
+
const onUpdateRows = (rows: T[], state: GridLoaderStates<T>) => {
|
|
81
|
+
if (state.currentPage > 0 && cacheKey) {
|
|
82
|
+
const data: DataType = { rows, state, creation: new Date().valueOf() };
|
|
83
|
+
sessionStorage.setItem(cacheKey, JSON.stringify(data));
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const onInitLoad = (
|
|
88
|
+
ref: ScrollerListRef
|
|
89
|
+
): [T[], Partial<GridLoaderStates<T>>?] | null | undefined => {
|
|
90
|
+
// Avoid repeatedly load from cache
|
|
91
|
+
if (initLoadedRef.current || !cacheKey) return undefined;
|
|
92
|
+
|
|
93
|
+
// Cache data
|
|
94
|
+
const cacheData = sessionStorage.getItem(cacheKey);
|
|
95
|
+
if (cacheData) {
|
|
96
|
+
const { rows, state, creation } = JSON.parse(cacheData) as DataType;
|
|
97
|
+
|
|
98
|
+
// 120 minutes
|
|
99
|
+
if (new Date().valueOf() - creation > cacheMinutes * 60000) {
|
|
100
|
+
sessionStorage.removeItem(cacheKey);
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Scroll position
|
|
105
|
+
const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
|
|
106
|
+
if (scrollData) {
|
|
107
|
+
const { scrollOffset } = JSON.parse(scrollData) as ListOnScrollProps;
|
|
108
|
+
globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Update flag value
|
|
112
|
+
initLoadedRef.current = true;
|
|
113
|
+
|
|
114
|
+
// Return cached rows and state
|
|
115
|
+
return [rows, state];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return undefined;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const onListScroll = (props: ListOnScrollProps) => {
|
|
122
|
+
if (!cacheKey || !initLoadedRef.current) return;
|
|
123
|
+
sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const f =
|
|
127
|
+
typeof fields == "function"
|
|
128
|
+
? fields(
|
|
129
|
+
JSON.parse(
|
|
130
|
+
sessionStorage.getItem(`${cacheKey}-searchbar`) ?? "{}"
|
|
131
|
+
) as DataTypes.BasicTemplateType<F>
|
|
132
|
+
)
|
|
133
|
+
: fields;
|
|
134
|
+
|
|
135
|
+
// Layout
|
|
136
|
+
return (
|
|
137
|
+
<CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
|
|
138
|
+
<Stack>
|
|
139
|
+
<Box
|
|
140
|
+
sx={{
|
|
141
|
+
paddingBottom: pageProps.paddings
|
|
142
|
+
}}
|
|
143
|
+
>
|
|
144
|
+
<SearchBar fields={f} onSubmit={onSubmit} />
|
|
145
|
+
</Box>
|
|
146
|
+
<ScrollerListEx<T, D>
|
|
147
|
+
autoLoad={false}
|
|
148
|
+
loadData={localLoadData}
|
|
149
|
+
onUpdateRows={onUpdateRows}
|
|
150
|
+
onInitLoad={onInitLoad}
|
|
151
|
+
onScroll={onListScroll}
|
|
152
|
+
mRef={refs}
|
|
153
|
+
{...rest}
|
|
154
|
+
/>
|
|
155
|
+
</Stack>
|
|
156
|
+
</CommonPage>
|
|
157
|
+
);
|
|
90
158
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
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
|
/**
|
|
6
6
|
* List page props
|
|
7
7
|
*/
|
|
8
8
|
export type ListPageProps<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
> = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>,
|
|
9
|
+
T extends object,
|
|
10
|
+
F extends DataTypes.BasicTemplate,
|
|
11
|
+
D extends DataTypes.Keys<T>
|
|
12
|
+
> = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>, "loadData">;
|
|
@@ -9,10 +9,22 @@ export type SearchPageProps<
|
|
|
9
9
|
T extends object,
|
|
10
10
|
F extends DataTypes.BasicTemplate
|
|
11
11
|
> = Omit<GridLoader<T>, "loadData"> & {
|
|
12
|
+
/**
|
|
13
|
+
* Cache key
|
|
14
|
+
*/
|
|
15
|
+
cacheKey?: string;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Cache minutes
|
|
19
|
+
*/
|
|
20
|
+
cacheMinutes?: number;
|
|
21
|
+
|
|
12
22
|
/**
|
|
13
23
|
* Search fields
|
|
14
24
|
*/
|
|
15
|
-
fields:
|
|
25
|
+
fields:
|
|
26
|
+
| React.ReactElement[]
|
|
27
|
+
| ((data: DataTypes.BasicTemplateType<F>) => React.ReactElement[]);
|
|
16
28
|
|
|
17
29
|
/**
|
|
18
30
|
* Search field template
|
package/src/pages/TablePage.tsx
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from
|
|
7
|
-
import { DataTypes, IdDefaultType } from
|
|
8
|
-
import { Box, Stack } from
|
|
9
|
-
import React from
|
|
10
|
-
import { MUGlobal } from
|
|
11
|
-
import { SearchBar } from
|
|
12
|
-
import { TableEx, TableExMethodRef, TableExMinWidth } from
|
|
13
|
-
import { CommonPage, CommonPageScrollContainer } from
|
|
14
|
-
import { TablePageProps } from
|
|
2
|
+
GridDataGet,
|
|
3
|
+
GridLoadDataProps,
|
|
4
|
+
useCombinedRefs,
|
|
5
|
+
useDimensions
|
|
6
|
+
} from "@etsoo/react";
|
|
7
|
+
import { DataTypes, IdDefaultType } from "@etsoo/shared";
|
|
8
|
+
import { Box, Stack } from "@mui/material";
|
|
9
|
+
import React from "react";
|
|
10
|
+
import { MUGlobal } from "../MUGlobal";
|
|
11
|
+
import { SearchBar } from "../SearchBar";
|
|
12
|
+
import { TableEx, TableExMethodRef, TableExMinWidth } from "../TableEx";
|
|
13
|
+
import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
|
|
14
|
+
import { TablePageProps } from "./TablePageProps";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Table page
|
|
@@ -19,108 +19,122 @@ import { TablePageProps } from './TablePageProps';
|
|
|
19
19
|
* @returns Component
|
|
20
20
|
*/
|
|
21
21
|
export function TablePage<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
T extends object,
|
|
23
|
+
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
|
|
24
|
+
D extends DataTypes.Keys<T> = IdDefaultType<T>
|
|
25
25
|
>(props: TablePageProps<T, F, D>) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
26
|
+
// Destruct
|
|
27
|
+
const {
|
|
28
|
+
columns,
|
|
29
|
+
fields,
|
|
30
|
+
fieldTemplate,
|
|
31
|
+
loadData,
|
|
32
|
+
mRef,
|
|
33
|
+
sizeReadyMiliseconds = 0,
|
|
34
|
+
pageProps = {},
|
|
35
|
+
cacheKey,
|
|
36
|
+
cacheMinutes = 120,
|
|
37
|
+
...rest
|
|
38
|
+
} = props;
|
|
39
|
+
|
|
40
|
+
pageProps.paddings ??= MUGlobal.pagePaddings;
|
|
41
|
+
|
|
42
|
+
// States
|
|
43
|
+
const [states] = React.useState<{
|
|
44
|
+
data?: FormData;
|
|
45
|
+
ref?: TableExMethodRef<T>;
|
|
46
|
+
}>({});
|
|
47
|
+
|
|
48
|
+
const refs = useCombinedRefs(
|
|
49
|
+
mRef,
|
|
50
|
+
(ref: TableExMethodRef<T> | null | undefined) => {
|
|
51
|
+
if (ref == null) return;
|
|
52
|
+
|
|
53
|
+
const first = states.ref == null;
|
|
54
|
+
|
|
55
|
+
states.ref = ref;
|
|
56
|
+
|
|
57
|
+
if (first) reset();
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const reset = () => {
|
|
62
|
+
if (states.data == null || states.ref == null) return;
|
|
63
|
+
states.ref.reset({ data: states.data });
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// On submit callback
|
|
67
|
+
const onSubmit = (data: FormData, _reset: boolean) => {
|
|
68
|
+
states.data = data;
|
|
69
|
+
reset();
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const localLoadData = (props: GridLoadDataProps) => {
|
|
73
|
+
const data = GridDataGet(props, fieldTemplate);
|
|
74
|
+
|
|
75
|
+
if (cacheKey)
|
|
76
|
+
sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
|
|
77
|
+
|
|
78
|
+
return loadData(data);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Total width
|
|
82
|
+
const totalWidth = React.useMemo(
|
|
83
|
+
() =>
|
|
84
|
+
columns.reduce((previousValue, { width, minWidth }) => {
|
|
85
|
+
return previousValue + (width ?? minWidth ?? TableExMinWidth);
|
|
86
|
+
}, 0),
|
|
87
|
+
[columns]
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Watch container
|
|
91
|
+
const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
|
|
92
|
+
const rect = dimensions[0][2];
|
|
93
|
+
const list = React.useMemo(() => {
|
|
94
|
+
if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
|
|
95
|
+
let maxHeight =
|
|
96
|
+
document.documentElement.clientHeight - (rect.top + rect.height + 1);
|
|
97
|
+
|
|
98
|
+
const style = window.getComputedStyle(dimensions[0][1]!);
|
|
99
|
+
const paddingBottom = parseFloat(style.paddingBottom);
|
|
100
|
+
if (!isNaN(paddingBottom)) maxHeight -= paddingBottom;
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<TableEx<T, D>
|
|
104
|
+
autoLoad={false}
|
|
105
|
+
columns={columns}
|
|
106
|
+
loadData={localLoadData}
|
|
107
|
+
maxHeight={maxHeight}
|
|
108
|
+
mRef={refs}
|
|
109
|
+
{...rest}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}, [rect]);
|
|
114
|
+
|
|
115
|
+
const f =
|
|
116
|
+
typeof fields == "function"
|
|
117
|
+
? fields(
|
|
118
|
+
JSON.parse(
|
|
119
|
+
sessionStorage.getItem(`${cacheKey}-searchbar`) ?? "{}"
|
|
120
|
+
) as DataTypes.BasicTemplateType<F>
|
|
121
|
+
)
|
|
122
|
+
: fields;
|
|
123
|
+
|
|
124
|
+
// Layout
|
|
125
|
+
return (
|
|
126
|
+
<CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
|
|
127
|
+
<Stack>
|
|
128
|
+
<Box
|
|
129
|
+
ref={dimensions[0][0]}
|
|
130
|
+
sx={{
|
|
131
|
+
paddingBottom: pageProps.paddings
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
134
|
+
<SearchBar fields={f} onSubmit={onSubmit} />
|
|
135
|
+
</Box>
|
|
136
|
+
{list}
|
|
137
|
+
</Stack>
|
|
138
|
+
</CommonPage>
|
|
139
|
+
);
|
|
126
140
|
}
|