@applica-software-guru/react-admin 1.5.362 → 1.5.364
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/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/ra-lists/Datagrid/DatagridHeader.d.ts.map +1 -1
- 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 +2567 -2575
- 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/Pagination/Pagination.tsx +8 -5
- package/src/components/ra-lists/Datagrid/DatagridHeader.tsx +3 -1
- package/src/components/ra-lists/ListTabsToolbar.tsx +110 -116
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ const Pagination: FC<PaginationProps> = memo((props) => {
|
|
|
18
18
|
const { isLoading, hasNextPage, page, perPage, total, setPage, setPerPage } = useListPaginationContext(props);
|
|
19
19
|
const translate = useTranslate();
|
|
20
20
|
const isSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
|
|
21
|
-
const [currentPage, setCurrentPage] = useState(page - 1);
|
|
21
|
+
const [currentPage, setCurrentPage] = useState(page - 1);
|
|
22
22
|
const { hasCreate } = useResourceDefinition(props);
|
|
23
23
|
const [isSelectedPage, setIsSelectedPage] = useState(false);
|
|
24
24
|
const theme = useTheme();
|
|
@@ -173,10 +173,13 @@ const Pagination: FC<PaginationProps> = memo((props) => {
|
|
|
173
173
|
page={currentPage}
|
|
174
174
|
onPageChange={handlePageChange}
|
|
175
175
|
onRowsPerPageChange={handlePerPageChange}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
176
|
+
ActionsComponent={ActionsComponent as any}
|
|
177
|
+
slotProps={{
|
|
178
|
+
actions: {
|
|
179
|
+
nextButton: {
|
|
180
|
+
disabled: !hasNextPage
|
|
181
|
+
}
|
|
182
|
+
}
|
|
180
183
|
}}
|
|
181
184
|
component="span"
|
|
182
185
|
labelRowsPerPage={translate('ra.navigation.page_rows_per_page')}
|
|
@@ -134,7 +134,9 @@ function DatagridHeader(props: MultiSortDatagridHeaderProps): ReactElement {
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
const source =
|
|
137
|
-
child.props.
|
|
137
|
+
child.props.sortBy ??
|
|
138
|
+
child.props.source ??
|
|
139
|
+
(typeof child.props.label === 'string' ? child.props.label : undefined);
|
|
138
140
|
const sortable = child.props.sortable !== false && !!source;
|
|
139
141
|
const sortInfo = sortable ? getSortForField(source) : null;
|
|
140
142
|
|
|
@@ -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
|
}
|