@applica-software-guru/react-admin 1.5.314 → 1.5.316

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/package.json CHANGED
@@ -107,5 +107,5 @@
107
107
  "type": "module",
108
108
  "types": "dist/index.d.ts",
109
109
  "typings": "dist/index.d.ts",
110
- "version": "1.5.314"
110
+ "version": "1.5.316"
111
111
  }
@@ -6,6 +6,7 @@ import { Dialog, useMediaQuery, useTheme } from '@mui/material';
6
6
  import _ from 'lodash';
7
7
  import { UseGetIdentityResult, useAuthProvider, useGetIdentity } from 'ra-core';
8
8
  import { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useReducer, useState } from 'react';
9
+ import { useLoading } from 'react-admin';
9
10
 
10
11
  enum LayoutActionType {
11
12
  UPDATE_MEDIA = 'updateMedia',
@@ -154,6 +155,7 @@ function LayoutProvider(props: ILayoutProviderProps) {
154
155
  const handlePasswordChange = useCallback(() => setNeedToChangePassword(false), []);
155
156
  const value = useMemo(() => ({ state, dispatch }), [state, dispatch]);
156
157
  const { logoIcon, logoMain, enableNotification, notification } = props;
158
+ const isLayoutLoading = useLoading();
157
159
 
158
160
  useEffect(() => {
159
161
  dispatch({
@@ -216,6 +218,7 @@ function LayoutProvider(props: ILayoutProviderProps) {
216
218
  }, [theme.palette.mode]);
217
219
 
218
220
  useEffect(() => {
221
+ if (isLayoutLoading) return;
219
222
  // Check if authProvider contains a method called isImpersonating
220
223
  if (!authProvider.isImpersonating) {
221
224
  // eslint-disable-next-line no-console
@@ -225,7 +228,7 @@ function LayoutProvider(props: ILayoutProviderProps) {
225
228
  authProvider?.isImpersonating().then((isImpersonating: boolean) => {
226
229
  setNeedToChangePassword(!isImpersonating && identity?.data?.needToChangePassword === true);
227
230
  });
228
- }, [identity?.data?.needToChangePassword, authProvider]);
231
+ }, [identity?.data?.needToChangePassword, authProvider, isLayoutLoading]);
229
232
 
230
233
  return (
231
234
  <LayoutContext.Provider value={value}>
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable filenames/match-regex */
2
- import { Inbox } from '@mui/icons-material';
2
+ import { DropboxOutlined } from '@ant-design/icons';
3
3
  import { Typography } from '@mui/material';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import { useGetResourceLabel, useResourceContext, useResourceDefinition, useTranslate } from 'ra-core';
@@ -22,6 +22,7 @@ type EmptyProps = {
22
22
  * @example 'my-custom-empty my-custom-empty--full-width'
23
23
  **/
24
24
  className?: string;
25
+ hasCreate?: boolean;
25
26
  };
26
27
 
27
28
  const StyledToolbar = styled('div')(({ theme }) => ({
@@ -35,8 +36,9 @@ const StyledToolbar = styled('div')(({ theme }) => ({
35
36
  * @example
36
37
  * <List empty={<Empty actions={<Button label="Add" onClick={add} />} />} />
37
38
  */
38
- function Empty({ actions, className, ...props }: EmptyProps): JSX.Element {
39
+ function Empty({ actions, className, hasCreate: _hasCreate, ...props }: EmptyProps): JSX.Element {
39
40
  const { hasCreate } = useResourceDefinition(props);
41
+ const canCreate = _hasCreate ?? hasCreate;
40
42
  const resource = useResourceContext(props);
41
43
 
42
44
  const translate = useTranslate();
@@ -53,13 +55,13 @@ function Empty({ actions, className, ...props }: EmptyProps): JSX.Element {
53
55
  return (
54
56
  <Root className={className}>
55
57
  <div className={EmptyClasses.message}>
56
- <Inbox className={EmptyClasses.icon} />
58
+ <DropboxOutlined className={EmptyClasses.icon} />
57
59
  <Typography variant="h4" paragraph>
58
60
  {translate(`resources.${resource}.empty`, {
59
61
  _: emptyMessage
60
62
  })}
61
63
  </Typography>
62
- {hasCreate ? (
64
+ {canCreate ? (
63
65
  <Typography variant="body1">
64
66
  {translate(`resources.${resource}.invite`, {
65
67
  _: inviteMessage
@@ -86,6 +88,7 @@ const Root = styled('span', {
86
88
  overridesResolver: (_, styles) => styles.root
87
89
  })(({ theme }) => ({
88
90
  flex: 1,
91
+ height: 'calc(100vh - 200px)',
89
92
  [`& .${EmptyClasses.message}`]: {
90
93
  textAlign: 'center',
91
94
  opacity: theme.palette.mode === 'light' ? 0.5 : 0.8,
@@ -94,8 +97,7 @@ const Root = styled('span', {
94
97
  },
95
98
 
96
99
  [`& .${EmptyClasses.icon}`]: {
97
- width: '9em',
98
- height: '9em'
100
+ fontSize: '9em'
99
101
  },
100
102
 
101
103
  [`& .${EmptyClasses.toolbar}`]: {
@@ -1,11 +1,9 @@
1
- import { MainCard } from '@/components/MainCard';
2
1
  import { ListView } from '@/components/ra-lists/ListView';
3
2
  import { styled } from '@mui/system';
4
3
  import { ListBase, RaRecord } from 'ra-core';
5
- import React, { ReactElement, isValidElement } from 'react';
4
+ import { ReactElement } from 'react';
6
5
  import { ListProps } from 'react-admin';
7
6
  import { Pagination } from '@/components/Pagination/Pagination';
8
- import { FilterSidebar } from './FilterSidebar';
9
7
  import { ListViewProvider } from './ListViewProvider';
10
8
 
11
9
  /**
@@ -198,25 +196,7 @@ const StyledList = styled(RaList, { slot: 'root' })(({ theme }) => ({
198
196
  }));
199
197
 
200
198
  function List(props: ListProps): ReactElement {
201
- const { aside } = props;
202
-
203
- // Check if 'aside' is a valid React element
204
- const isAsideValid = isValidElement(aside);
205
-
206
- // Determine if 'aside' is a FilterSidebar component
207
- const isFilterSidebar = isAsideValid && aside?.type === FilterSidebar;
208
-
209
- // Use React.Fragment if there's a generic 'aside', otherwise use MainCard
210
- const ListWrapper = isAsideValid && !isFilterSidebar ? React.Fragment : MainCard;
211
-
212
- // Define props for the ListWrapper based on the presence of 'aside'
213
- const listWrapperProps = !aside || isFilterSidebar ? { content: false } : undefined;
214
-
215
- return (
216
- <ListWrapper {...listWrapperProps}>
217
- <StyledList {...props} pagination={<Pagination />} />
218
- </ListWrapper>
219
- );
199
+ return <StyledList {...props} pagination={<Pagination />} />;
220
200
  }
221
201
 
222
202
  export { List };
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable filenames/match-regex */
2
2
  import { Error } from '@/components/Layout/Error';
3
- import { Card, CardContent } from '@mui/material';
3
+ import { Card, CardContent, CircularProgress } from '@mui/material';
4
4
  import { styled, useTheme } from '@mui/material/styles';
5
5
  import { SxProps } from '@mui/system';
6
6
  import clsx from 'clsx';
@@ -16,6 +16,8 @@ import {
16
16
  } from 'react-admin';
17
17
  import { ListToolbar } from './ListToolbar';
18
18
  import { FilterSidebar } from './FilterSidebar';
19
+ import { MainCard } from '@/components/MainCard';
20
+
19
21
  const defaultActions = <DefaultActions />;
20
22
  const defaultPagination = <DefaultPagination />;
21
23
  const defaultEmpty = <Empty />;
@@ -73,10 +75,7 @@ function ListView<RecordType extends RaRecord = any>(props: ListViewProps): Reac
73
75
  {!error && (
74
76
  <Content className={ListClasses.content}>
75
77
  {bulkActionButtons && children && React.isValidElement<any>(children)
76
- ? // FIXME remove in 5.0
77
- cloneElement(children, {
78
- bulkActionButtons
79
- })
78
+ ? cloneElement(children, { bulkActionButtons })
80
79
  : children}
81
80
  </Content>
82
81
  )}
@@ -101,10 +100,38 @@ function ListView<RecordType extends RaRecord = any>(props: ListViewProps): Reac
101
100
  const shouldRenderEmptyPage =
102
101
  !isLoading && data?.length === 0 && !Object.keys(filterValues).length && empty !== false;
103
102
 
103
+ // Check if 'aside' is a valid React element
104
+ const isAsideValid = React.isValidElement(aside);
105
+
106
+ // Determine if 'aside' is a FilterSidebar component
107
+ const isFilterSidebar = isAsideValid && aside?.type === FilterSidebar;
108
+
109
+ // Use React.Fragment if there's a generic 'aside', otherwise use MainCard
110
+ const Wrapper = isLoading || shouldRenderEmptyPage || (isAsideValid && !isFilterSidebar) ? React.Fragment : MainCard;
111
+
112
+ // Define props for the ListWrapper based on the presence of 'aside'
113
+ const wrapperProps =
114
+ !isLoading && !shouldRenderEmptyPage && (!aside || isFilterSidebar) ? { content: false } : undefined;
104
115
  return (
105
116
  <Root className={clsx('list-page', className)} {...rest}>
106
117
  <Title title={title} defaultTitle={defaultTitle} preferenceKey={`${resource}.list.title`} />
107
- {shouldRenderEmptyPage ? renderEmpty() : renderList()}
118
+ <Wrapper {...wrapperProps}>
119
+ {isLoading ? (
120
+ <CircularProgress
121
+ sx={{
122
+ position: 'absolute',
123
+ top: '50%',
124
+ left: '50%',
125
+ marginTop: '-20px',
126
+ marginLeft: '-20px'
127
+ }}
128
+ />
129
+ ) : shouldRenderEmptyPage ? (
130
+ renderEmpty()
131
+ ) : (
132
+ renderList()
133
+ )}
134
+ </Wrapper>
108
135
  {hasAsideSidebar ? <AsideCard aside={aside} /> : null}
109
136
  {/* @ts-ignore */}
110
137
  {hasFilterSidebar ? React.cloneElement(aside, { filters }) : null}
@@ -399,6 +426,9 @@ const Root = styled('div', {
399
426
  })(({ theme }) => ({
400
427
  display: 'flex',
401
428
 
429
+ '& >.MuiPaper-root': {
430
+ flex: 1
431
+ },
402
432
  [`& .${ListClasses.main}`]: {
403
433
  flex: '1 1 auto',
404
434
  display: 'flex',
@@ -415,7 +445,9 @@ const Root = styled('div', {
415
445
 
416
446
  [`& .${ListClasses.actions}`]: {},
417
447
 
418
- [`& .${ListClasses.noResults}`]: {},
448
+ [`& .${ListClasses.noResults}`]: {
449
+ alignContent: 'center'
450
+ },
419
451
 
420
452
  [`& .${ListClasses.asideCard}`]: {
421
453
  [theme.breakpoints.down('md')]: {