@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.
@@ -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,9 @@
1
+ import { GridLoaderStates } from "@etsoo/react";
2
+ /**
3
+ * Grid data cache type
4
+ */
5
+ export type GridDataCacheType<T> = {
6
+ rows: T[];
7
+ state: GridLoaderStates<T>;
8
+ creation: number;
9
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -22,14 +22,6 @@ export type ResponsibleContainerProps<T extends object, F extends DataTypes.Basi
22
22
  * @returns Adjusted height
23
23
  */
24
24
  adjustFabHeight?: (height: number, isGrid: boolean) => number;
25
- /**
26
- * Cache key
27
- */
28
- cacheKey?: string;
29
- /**
30
- * Cache minutes
31
- */
32
- cacheMinutes?: number;
33
25
  /**
34
26
  * Columns
35
27
  */
@@ -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: fields, onSubmit: onSubmit })),
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: fields, onSubmit: onSubmit })),
110
+ React.createElement(SearchBar, { fields: f, onSubmit: onSubmit })),
68
111
  list)));
69
112
  }
@@ -1,6 +1,6 @@
1
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
2
- import React from 'react';
3
- import { ListPageProps } from './ListPageProps';
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
@@ -1,19 +1,19 @@
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';
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: fields, onSubmit: onSubmit })),
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 '@etsoo/shared';
2
- import { ScrollerListExProps } from '../ScrollerListEx';
3
- import { SearchPageProps } from './SearchPageProps';
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>, 'loadData'>;
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
  */
@@ -1,6 +1,6 @@
1
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
2
- import React from 'react';
3
- import { TablePageProps } from './TablePageProps';
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
@@ -1,19 +1,19 @@
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';
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: fields, onSubmit: onSubmit })),
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.42",
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",
@@ -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
@@ -0,0 +1,10 @@
1
+ import { GridLoaderStates } from "@etsoo/react";
2
+
3
+ /**
4
+ * Grid data cache type
5
+ */
6
+ export type GridDataCacheType<T> = {
7
+ rows: T[];
8
+ state: GridLoaderStates<T>;
9
+ creation: number;
10
+ };
@@ -33,6 +33,7 @@ import {
33
33
  } from "./ScrollerListEx";
34
34
  import { SearchBar } from "./SearchBar";
35
35
  import { Labels } from "./app/Labels";
36
+ import { GridDataCacheType } from "./GridDataCacheType";
36
37
 
37
38
  /**
38
39
  * ResponsibleContainer props
@@ -67,16 +68,6 @@ export type ResponsibleContainerProps<
67
68
  */
68
69
  adjustFabHeight?: (height: number, isGrid: boolean) => number;
69
70
 
70
- /**
71
- * Cache key
72
- */
73
- cacheKey?: string;
74
-
75
- /**
76
- * Cache minutes
77
- */
78
- cacheMinutes?: number;
79
-
80
71
  /**
81
72
  * Columns
82
73
  */
@@ -293,7 +284,7 @@ export function ResponsibleContainer<
293
284
  }
294
285
  );
295
286
 
296
- type DataType = { rows: T[]; state: GridLoaderStates<T>; creation: number };
287
+ type DataType = GridDataCacheType<T>;
297
288
 
298
289
  const onUpdateRows = (rows: T[], state: GridLoaderStates<T>) => {
299
290
  if (state.currentPage > 0 && cacheKey) {
@@ -1,7 +1,10 @@
1
1
  import {
2
2
  GridDataGet,
3
3
  GridLoadDataProps,
4
+ GridLoaderStates,
5
+ GridOnScrollProps,
4
6
  ScrollerGridForwardRef,
7
+ VariableSizeGrid,
5
8
  useCombinedRefs,
6
9
  useDimensions
7
10
  } from "@etsoo/react";
@@ -13,6 +16,7 @@ import { MUGlobal } from "../MUGlobal";
13
16
  import { SearchBar } from "../SearchBar";
14
17
  import { CommonPage } from "./CommonPage";
15
18
  import { DataGridPageProps } from "./DataGridPageProps";
19
+ import { GridDataCacheType } from "../GridDataCacheType";
16
20
 
17
21
  interface LocalStates<T> {
18
22
  data?: FormData;
@@ -41,6 +45,8 @@ export function DataGridPage<
41
45
  mRef,
42
46
  sizeReadyMiliseconds = 100,
43
47
  pageProps = {},
48
+ cacheKey,
49
+ cacheMinutes = 120,
44
50
  ...rest
45
51
  } = props;
46
52
 
@@ -65,6 +71,8 @@ export function DataGridPage<
65
71
  }
66
72
  );
67
73
 
74
+ const initLoadedRef = React.useRef<boolean>();
75
+
68
76
  // On submit callback
69
77
  const onSubmit = (data: FormData, _reset: boolean) => {
70
78
  setStates({ data });
@@ -72,9 +80,64 @@ export function DataGridPage<
72
80
 
73
81
  const localLoadData = (props: GridLoadDataProps) => {
74
82
  const data = GridDataGet(props, fieldTemplate);
83
+
84
+ if (cacheKey)
85
+ sessionStorage.setItem(`${cacheKey}-searchbar`, JSON.stringify(data));
86
+
75
87
  return loadData(data);
76
88
  };
77
89
 
90
+ type DataType = GridDataCacheType<T>;
91
+
92
+ const onUpdateRows = (rows: T[], state: GridLoaderStates<T>) => {
93
+ if (state.currentPage > 0 && cacheKey) {
94
+ const data: DataType = { rows, state, creation: new Date().valueOf() };
95
+ sessionStorage.setItem(cacheKey, JSON.stringify(data));
96
+ }
97
+ };
98
+
99
+ const onInitLoad = (
100
+ ref: VariableSizeGrid<T>
101
+ ): [T[], Partial<GridLoaderStates<T>>?] | null | undefined => {
102
+ // Avoid repeatedly load from cache
103
+ if (initLoadedRef.current || !cacheKey) return undefined;
104
+
105
+ // Cache data
106
+ const cacheData = sessionStorage.getItem(cacheKey);
107
+ if (cacheData) {
108
+ const { rows, state, creation } = JSON.parse(cacheData) as DataType;
109
+
110
+ // 120 minutes
111
+ if (new Date().valueOf() - creation > cacheMinutes * 60000) {
112
+ sessionStorage.removeItem(cacheKey);
113
+ return undefined;
114
+ }
115
+
116
+ // Scroll position
117
+ const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
118
+ if (scrollData) {
119
+ const { scrollLeft, scrollTop } = JSON.parse(
120
+ scrollData
121
+ ) as GridOnScrollProps;
122
+
123
+ globalThis.setTimeout(() => ref.scrollTo({ scrollLeft, scrollTop }), 0);
124
+ }
125
+
126
+ // Update flag value
127
+ initLoadedRef.current = true;
128
+
129
+ // Return cached rows and state
130
+ return [rows, state];
131
+ }
132
+
133
+ return undefined;
134
+ };
135
+
136
+ const onGridScroll = (props: GridOnScrollProps) => {
137
+ if (!cacheKey || !initLoadedRef.current) return;
138
+ sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
139
+ };
140
+
78
141
  // Watch container
79
142
  const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
80
143
  const rect = dimensions[0][2];
@@ -105,6 +168,9 @@ export function DataGridPage<
105
168
  height={gridHeight}
106
169
  loadData={localLoadData}
107
170
  mRef={refs}
171
+ onUpdateRows={onUpdateRows}
172
+ onInitLoad={onInitLoad}
173
+ onScroll={onGridScroll}
108
174
  outerRef={(element?: HTMLDivElement) => {
109
175
  if (element != null) setStates({ element });
110
176
  }}
@@ -119,6 +185,15 @@ export function DataGridPage<
119
185
  ref.reset({ data });
120
186
  }, [ref, data]);
121
187
 
188
+ const f =
189
+ typeof fields == "function"
190
+ ? fields(
191
+ JSON.parse(
192
+ sessionStorage.getItem(`${cacheKey}-searchbar`) ?? "{}"
193
+ ) as DataTypes.BasicTemplateType<F>
194
+ )
195
+ : fields;
196
+
122
197
  // Layout
123
198
  return (
124
199
  <CommonPage {...pageProps} scrollContainer={states.element}>
@@ -129,7 +204,7 @@ export function DataGridPage<
129
204
  paddingBottom: pageProps.paddings
130
205
  }}
131
206
  >
132
- <SearchBar fields={fields} onSubmit={onSubmit} />
207
+ <SearchBar fields={f} onSubmit={onSubmit} />
133
208
  </Box>
134
209
  {list}
135
210
  </Stack>