@applica-software-guru/react-admin 1.5.362 → 1.5.363
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/dist/components/ra-lists/ListTabsToolbar.d.ts +1 -1
- package/dist/components/ra-lists/ListTabsToolbar.d.ts.map +1 -1
- package/dist/react-admin.cjs.js +38 -38
- package/dist/react-admin.cjs.js.gz +0 -0
- package/dist/react-admin.cjs.js.map +1 -1
- package/dist/react-admin.es.js +2561 -2573
- package/dist/react-admin.es.js.gz +0 -0
- package/dist/react-admin.es.js.map +1 -1
- package/dist/react-admin.umd.js +39 -39
- package/dist/react-admin.umd.js.gz +0 -0
- package/dist/react-admin.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ra-lists/ListTabsToolbar.tsx +110 -116
package/package.json
CHANGED
|
@@ -19,147 +19,141 @@ interface ListTabsToolbarProps {
|
|
|
19
19
|
tabs?: ListTabToolbarConfig[];
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const theme = useTheme();
|
|
27
|
-
const [searchParams, setSearchParams] = useSearchParams();
|
|
22
|
+
interface TabFilterState {
|
|
23
|
+
filterValues: Record<string, any>;
|
|
24
|
+
displayedFilters: Record<string, any>;
|
|
25
|
+
}
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
function useListTabs(tabs: ListTabToolbarConfig[]) {
|
|
28
|
+
const [searchParams] = useSearchParams();
|
|
29
|
+
const resource = useResourceContext();
|
|
30
|
+
const { setCurrentTabKey } = useListViewContext();
|
|
31
|
+
const { filterValues, displayedFilters, setFilters } = useListContext();
|
|
32
32
|
|
|
33
|
-
const defaultTabIndex = useMemo(() => tabs.findIndex((tab) => tab.default) ?? 0, [tabs]);
|
|
34
33
|
const resourceKey = useMemo(() => resource.replace(/^entities\//, ''), [resource]);
|
|
35
|
-
const tabGroupKey =
|
|
36
|
-
const tabFiltersKey =
|
|
34
|
+
const tabGroupKey = `${resourceKey}-tab-group`;
|
|
35
|
+
const tabFiltersKey = `${resourceKey}-tab-filters`;
|
|
37
36
|
|
|
38
|
-
const
|
|
39
|
-
const [tabFilterStates, setTabFilterStates] = useSessionStorage(tabFiltersKey, {});
|
|
40
|
-
const initialized = useRef(false);
|
|
41
|
-
|
|
42
|
-
const saveCurrentTabFilters = useMemo(
|
|
43
|
-
() =>
|
|
44
|
-
_.debounce((tabKey: string, filters: any, displayed: any) => {
|
|
45
|
-
setTabFilterStates((prev: any) => ({
|
|
46
|
-
...prev,
|
|
47
|
-
[tabKey]: {
|
|
48
|
-
filterValues: { ...filters },
|
|
49
|
-
displayedFilters: { ...displayed }
|
|
50
|
-
}
|
|
51
|
-
}));
|
|
52
|
-
}, 500),
|
|
53
|
-
[setTabFilterStates]
|
|
54
|
-
);
|
|
37
|
+
const defaultTabIndex = useMemo(() => tabs.findIndex((tab) => tab.default) ?? 0, [tabs]);
|
|
55
38
|
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
const [currentTab, setCurrentTab] = useSessionStorage(tabGroupKey, defaultTabIndex) as [number, (v: number) => void];
|
|
40
|
+
const [tabFilterStates, setTabFilterStates] = useSessionStorage(tabFiltersKey, {}) as [
|
|
41
|
+
Record<string, TabFilterState>,
|
|
42
|
+
(v: any) => void
|
|
43
|
+
];
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
setFilters(tabFilter, {}, debounce);
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
[tabFilterStates, setFilters]
|
|
67
|
-
);
|
|
45
|
+
const initialized = useRef(false);
|
|
46
|
+
const switchingTab = useRef(false);
|
|
68
47
|
|
|
69
|
-
const
|
|
70
|
-
(index: number
|
|
71
|
-
const
|
|
48
|
+
const handleTabChange = useCallback(
|
|
49
|
+
(index: number) => {
|
|
50
|
+
const tab = tabs[index];
|
|
51
|
+
if (!tab) return;
|
|
72
52
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
},
|
|
76
|
-
[tabs, setCurrentTabKey, restoreTabFilters]
|
|
77
|
-
);
|
|
53
|
+
setCurrentTab(index);
|
|
54
|
+
setCurrentTabKey?.(tab.key);
|
|
78
55
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
newParams.set(tabGroupKey, String(index));
|
|
83
|
-
setSearchParams(newParams, { replace: true });
|
|
84
|
-
},
|
|
85
|
-
[searchParams, setSearchParams, tabGroupKey]
|
|
86
|
-
);
|
|
56
|
+
const savedState = tabFilterStates?.[tab.key];
|
|
57
|
+
const nextFilters = savedState?.filterValues ?? tab.filter;
|
|
58
|
+
const nextDisplayed = savedState?.displayedFilters ?? {};
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
60
|
+
if (!_.isEqual(nextFilters, filterValues) || !_.isEqual(nextDisplayed, displayedFilters)) {
|
|
61
|
+
switchingTab.current = true;
|
|
62
|
+
setFilters(nextFilters, nextDisplayed);
|
|
63
|
+
}
|
|
92
64
|
},
|
|
93
|
-
[
|
|
65
|
+
[tabs, tabFilterStates, filterValues, displayedFilters, setCurrentTab, setCurrentTabKey, setFilters]
|
|
94
66
|
);
|
|
95
67
|
|
|
96
68
|
useEffect(() => {
|
|
97
|
-
if (initialized.current
|
|
98
|
-
|
|
99
|
-
if (currentTabKey) {
|
|
100
|
-
saveCurrentTabFilters(currentTabKey, filterValues, displayedFilters);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}, [filterValues, displayedFilters, currentTab, tabs, saveCurrentTabFilters]);
|
|
69
|
+
if (initialized.current) return;
|
|
70
|
+
initialized.current = true;
|
|
104
71
|
|
|
105
|
-
useEffect(() => {
|
|
106
72
|
const param = searchParams.get(tabGroupKey);
|
|
107
|
-
|
|
108
|
-
|
|
73
|
+
const initialIndex = param != null ? Number(param) : Number(currentTab);
|
|
74
|
+
const hasUrlFilter = searchParams.get('filter') !== null;
|
|
75
|
+
|
|
76
|
+
if (hasUrlFilter) {
|
|
77
|
+
setCurrentTab(initialIndex);
|
|
78
|
+
setCurrentTabKey?.(tabs[initialIndex]?.key);
|
|
79
|
+
} else {
|
|
80
|
+
handleTabChange(initialIndex);
|
|
109
81
|
}
|
|
110
|
-
|
|
111
|
-
}, [filterValues]);
|
|
82
|
+
}, [searchParams, tabGroupKey, currentTab, setCurrentTab, setCurrentTabKey, handleTabChange, tabs]);
|
|
112
83
|
|
|
113
84
|
useEffect(() => {
|
|
114
|
-
if (!initialized.current) {
|
|
115
|
-
|
|
116
|
-
|
|
85
|
+
if (!initialized.current || switchingTab.current) {
|
|
86
|
+
switchingTab.current = false;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const currentTabKey = tabs[Number(currentTab)]?.key;
|
|
91
|
+
if (!currentTabKey) return;
|
|
117
92
|
|
|
118
|
-
|
|
119
|
-
|
|
93
|
+
setTabFilterStates((prev: Record<string, TabFilterState>) => {
|
|
94
|
+
const prevState = prev?.[currentTabKey];
|
|
95
|
+
if (
|
|
96
|
+
_.isEqual(prevState?.filterValues, filterValues) &&
|
|
97
|
+
_.isEqual(prevState?.displayedFilters, displayedFilters)
|
|
98
|
+
) {
|
|
99
|
+
return prev;
|
|
120
100
|
}
|
|
101
|
+
return {
|
|
102
|
+
...prev,
|
|
103
|
+
[currentTabKey]: { filterValues, displayedFilters }
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}, [filterValues, displayedFilters, currentTab, tabs, setTabFilterStates]);
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
currentTab,
|
|
110
|
+
handleTabChange: (_: any, val: number) => handleTabChange(val)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
121
113
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
114
|
+
function ListTabsToolbar({ tabs = [] }: ListTabsToolbarProps) {
|
|
115
|
+
const theme = useTheme();
|
|
116
|
+
const { currentTab, handleTabChange } = useListTabs(tabs);
|
|
117
|
+
|
|
118
|
+
if (tabs.length > 0 && tabs.some((tab) => !tab.key)) {
|
|
119
|
+
throw new Error('ListTabsToolbar: Each tab must have a unique key.');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (tabs.length === 0) return null;
|
|
127
123
|
|
|
128
124
|
return (
|
|
129
125
|
<Box sx={{ width: '100%' }}>
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
</Tabs>
|
|
162
|
-
) : null}
|
|
126
|
+
<Tabs
|
|
127
|
+
value={Number(currentTab)}
|
|
128
|
+
onChange={handleTabChange}
|
|
129
|
+
allowScrollButtonsMobile
|
|
130
|
+
variant="scrollable"
|
|
131
|
+
scrollButtons="auto"
|
|
132
|
+
sx={{
|
|
133
|
+
width: '100%',
|
|
134
|
+
'.MuiTabs-scrollButtons.Mui-disabled': {
|
|
135
|
+
opacity: 0.2
|
|
136
|
+
}
|
|
137
|
+
}}
|
|
138
|
+
>
|
|
139
|
+
{tabs.map((tab) => (
|
|
140
|
+
<Tab
|
|
141
|
+
icon={tab.icon}
|
|
142
|
+
key={tab.key}
|
|
143
|
+
label={tab.label}
|
|
144
|
+
sx={{
|
|
145
|
+
flex: '0 0 auto',
|
|
146
|
+
lineHeight: 1,
|
|
147
|
+
whiteSpace: 'nowrap',
|
|
148
|
+
overflow: 'hidden',
|
|
149
|
+
textOverflow: 'ellipsis',
|
|
150
|
+
'& .MuiTab-iconWrapper': {
|
|
151
|
+
marginRight: theme.spacing(0.5)
|
|
152
|
+
}
|
|
153
|
+
}}
|
|
154
|
+
/>
|
|
155
|
+
))}
|
|
156
|
+
</Tabs>
|
|
163
157
|
</Box>
|
|
164
158
|
);
|
|
165
159
|
}
|