@strapi/admin 5.40.0 → 5.41.0

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.
@@ -45,6 +45,14 @@ function _interopNamespaceDefault(e) {
45
45
 
46
46
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
47
47
 
48
+ const getWidgetPermissionsCacheKey = (permissions)=>{
49
+ return permissions.map((permission)=>JSON.stringify({
50
+ action: permission.action,
51
+ subject: permission.subject,
52
+ conditions: permission.conditions ?? [],
53
+ properties: permission.properties ?? {}
54
+ })).sort().join('|');
55
+ };
48
56
  // Styled wrapper for the drag preview
49
57
  const DragPreviewWrapper = styled.styled.div`
50
58
  max-width: ${(props)=>props.$maxWidth};
@@ -84,11 +92,19 @@ const DragPreviewWrapper = styled.styled.div`
84
92
  const user = Auth.useAuth('HomePageCE', (state)=>state.user);
85
93
  const displayName = user?.firstname ?? user?.username ?? user?.email;
86
94
  const getAllWidgets = StrapiApp.useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
95
+ const allWidgets = React__namespace.useMemo(()=>getAllWidgets(), [
96
+ getAllWidgets
97
+ ]);
87
98
  const checkUserHasPermissions = Auth.useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
88
99
  const { data: homepageLayout, isLoading: _isLoadingLayout } = homepage.useGetHomepageLayoutQuery();
100
+ // Prefetch expensive widget data as soon as the homepage route is active.
101
+ homepage.useGetCountDocumentsQuery();
102
+ homepage.useGetKeyStatisticsQuery();
89
103
  const [filteredWidgets, setFilteredWidgets] = React__namespace.useState([]);
90
- const [allAvailableWidgets, setAllAvailableWidgets] = React__namespace.useState([]);
91
- const [loading, setLoading] = React__namespace.useState(true);
104
+ const [widgetPermissionStatus, setWidgetPermissionStatus] = React__namespace.useState(()=>allWidgets.reduce((acc, widget)=>{
105
+ acc[widget.uid] = !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';
106
+ return acc;
107
+ }, {}));
92
108
  const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React__namespace.useState(false);
93
109
  // Use custom hook for widget management
94
110
  const { findWidget, deleteWidget, addWidget, moveWidget, columnWidths, setColumnWidths, handleWidgetResize, saveLayout, isDraggingWidget, draggedWidgetId, handleDragStart, handleDragEnd } = Widgets.useWidgets({
@@ -96,37 +112,102 @@ const DragPreviewWrapper = styled.styled.div`
96
112
  setFilteredWidgets
97
113
  });
98
114
  React__namespace.useEffect(()=>{
115
+ const initialPermissionStatus = allWidgets.reduce((acc, widget)=>{
116
+ acc[widget.uid] = !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';
117
+ return acc;
118
+ }, {});
119
+ setWidgetPermissionStatus(initialPermissionStatus);
120
+ const widgetsWithPermissions = allWidgets.filter((widget)=>widget.permissions && widget.permissions.length > 0);
121
+ if (widgetsWithPermissions.length === 0) {
122
+ return;
123
+ }
124
+ const groupedPermissions = widgetsWithPermissions.reduce((acc, widget)=>{
125
+ const permissions = widget.permissions ?? [];
126
+ const key = getWidgetPermissionsCacheKey(permissions);
127
+ const existingGroup = acc.get(key);
128
+ if (existingGroup) {
129
+ existingGroup.uids.push(widget.uid);
130
+ } else {
131
+ acc.set(key, {
132
+ permissions,
133
+ uids: [
134
+ widget.uid
135
+ ]
136
+ });
137
+ }
138
+ return acc;
139
+ }, new Map());
140
+ let isMounted = true;
99
141
  const checkWidgetsPermissions = async ()=>{
100
- const allWidgets = getAllWidgets();
101
- const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
102
- if (!widget.permissions || widget.permissions.length === 0) return true;
103
- const matchingPermissions = await checkUserHasPermissions(widget.permissions);
104
- return matchingPermissions.length >= widget.permissions.length;
105
- }));
106
- const authorizedWidgetsList = allWidgets.filter((_, i)=>authorizedWidgets[i]);
107
- setAllAvailableWidgets(authorizedWidgetsList);
108
- setLoading(false);
142
+ try {
143
+ const permissionResults = await Promise.all(Array.from(groupedPermissions.values()).map(async ({ permissions, uids })=>{
144
+ const matchingPermissions = await checkUserHasPermissions(permissions);
145
+ const status = matchingPermissions.length >= permissions.length ? 'allowed' : 'denied';
146
+ return {
147
+ uids,
148
+ status
149
+ };
150
+ }));
151
+ if (!isMounted) return;
152
+ setWidgetPermissionStatus((prev)=>{
153
+ const next = {
154
+ ...prev
155
+ };
156
+ permissionResults.forEach(({ uids, status })=>{
157
+ uids.forEach((uid)=>{
158
+ next[uid] = status;
159
+ });
160
+ });
161
+ return next;
162
+ });
163
+ } catch {
164
+ if (!isMounted) return;
165
+ // Keep the UI responsive even when permission checks fail.
166
+ setWidgetPermissionStatus((prev)=>{
167
+ const next = {
168
+ ...prev
169
+ };
170
+ widgetsWithPermissions.forEach((widget)=>{
171
+ next[widget.uid] = 'denied';
172
+ });
173
+ return next;
174
+ });
175
+ }
109
176
  };
110
177
  checkWidgetsPermissions();
178
+ return ()=>{
179
+ isMounted = false;
180
+ };
111
181
  }, [
112
- checkUserHasPermissions,
113
- getAllWidgets
182
+ allWidgets,
183
+ checkUserHasPermissions
184
+ ]);
185
+ const allAvailableWidgets = React__namespace.useMemo(()=>{
186
+ return allWidgets.filter((widget)=>widgetPermissionStatus[widget.uid] === 'allowed');
187
+ }, [
188
+ allWidgets,
189
+ widgetPermissionStatus
190
+ ]);
191
+ const renderableWidgets = React__namespace.useMemo(()=>{
192
+ return allWidgets.filter((widget)=>widgetPermissionStatus[widget.uid] !== 'denied');
193
+ }, [
194
+ allWidgets,
195
+ widgetPermissionStatus
114
196
  ]);
115
197
  React__namespace.useEffect(()=>{
116
- if (allAvailableWidgets.length === 0) return;
117
198
  // If user has customized the homepage layout, apply it
118
199
  if (homepageLayout && homepageLayout.widgets) {
119
- const { filteredWidgets, widths: homepageWidths } = widgetLayout.applyHomepageLayout(allAvailableWidgets, homepageLayout);
200
+ const { filteredWidgets, widths: homepageWidths } = widgetLayout.applyHomepageLayout(renderableWidgets, homepageLayout);
120
201
  setFilteredWidgets(filteredWidgets);
121
202
  setColumnWidths(homepageWidths);
122
203
  } else {
123
204
  // Set default layout when no custom layout exists
124
- setFilteredWidgets(allAvailableWidgets);
125
- setColumnWidths(widgetLayout.createDefaultWidgetWidths(allAvailableWidgets));
205
+ setFilteredWidgets(renderableWidgets);
206
+ setColumnWidths(widgetLayout.createDefaultWidgetWidths(renderableWidgets));
126
207
  }
127
208
  }, [
128
209
  homepageLayout,
129
- allAvailableWidgets,
210
+ renderableWidgets,
130
211
  setColumnWidths
131
212
  ]);
132
213
  const widgetLayout$1 = React__namespace.useMemo(()=>{
@@ -197,14 +278,7 @@ const DragPreviewWrapper = styled.styled.div`
197
278
  paddingBottom: 10,
198
279
  children: [
199
280
  /*#__PURE__*/ jsxRuntime.jsx(Overview.GuidedTourHomepageOverview, {}),
200
- loading ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
201
- position: "absolute",
202
- top: 0,
203
- left: 0,
204
- right: 0,
205
- bottom: 0,
206
- children: /*#__PURE__*/ jsxRuntime.jsx(PageHelpers.Page.Loading, {})
207
- }) : /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
281
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Box, {
208
282
  position: "relative",
209
283
  [widgetLayout.WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true,
210
284
  children: [
@@ -225,7 +299,7 @@ const DragPreviewWrapper = styled.styled.div`
225
299
  onDragStart: handleDragStart,
226
300
  onDragEnd: handleDragEnd,
227
301
  component: widget.component,
228
- children: /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
302
+ children: widgetPermissionStatus[widget.uid] === 'loading' ? /*#__PURE__*/ jsxRuntime.jsx(WidgetHelpers.Widget.Loading, {}) : /*#__PURE__*/ jsxRuntime.jsx(WidgetComponent, {
229
303
  component: widget.component,
230
304
  columnWidth: widgetWidth
231
305
  })
@@ -255,7 +329,7 @@ const DragPreviewWrapper = styled.styled.div`
255
329
  })
256
330
  }),
257
331
  /*#__PURE__*/ jsxRuntime.jsx(DragLayer.DragLayer, {
258
- renderItem: ({ type, item })=>{
332
+ renderItem: ({ type: _type, item })=>{
259
333
  if (!DragLayer.isWidgetDragItem(item)) {
260
334
  return null;
261
335
  }
@@ -1 +1 @@
1
- {"version":3,"file":"HomePage.js","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Grid, Main } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { DragLayer, isWidgetDragItem } from '../../components/DragLayer';\nimport { GapDropZoneManager } from '../../components/GapDropZone';\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { WidgetResizeHandle } from '../../components/ResizeIndicator';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { WidgetRoot } from '../../components/WidgetRoot';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\nimport { useWidgets } from '../../features/Widgets';\nimport { useGetHomepageLayoutQuery } from '../../services/homepage';\nimport {\n getWidgetElement,\n WIDGET_DATA_ATTRIBUTES,\n applyHomepageLayout,\n createDefaultWidgetWidths,\n isLastWidgetInRow,\n canResizeBetweenWidgets,\n getWidgetWidth,\n} from '../../utils/widgetLayout';\n\nimport { AddWidgetModal } from './components/AddWidgetModal';\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\n\n// Styled wrapper for the drag preview\nconst DragPreviewWrapper = styled.div<{ $maxWidth: string }>`\n max-width: ${(props) => props.$maxWidth};\n overflow: hidden;\n opacity: 0.9;\n border: 2px solid ${({ theme }) => theme.colors.primary500};\n border-radius: ${({ theme }) => theme.borderRadius};\n pointer-events: none;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nexport const WidgetComponent = ({\n component,\n columnWidth,\n}: {\n component: () => Promise<React.ComponentType>;\n columnWidth: number;\n}) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType<{\n columnWidth?: number;\n }> | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component {...({ columnWidth } as Record<string, unknown>)} />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [allAvailableWidgets, setAllAvailableWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);\n\n // Use custom hook for widget management\n const {\n findWidget,\n deleteWidget,\n addWidget,\n moveWidget,\n columnWidths,\n setColumnWidths,\n handleWidgetResize,\n saveLayout,\n isDraggingWidget,\n draggedWidgetId,\n handleDragStart,\n handleDragEnd,\n } = useWidgets({\n filteredWidgets,\n setFilteredWidgets,\n });\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n const authorizedWidgetsList = allWidgets.filter((_, i) => authorizedWidgets[i]);\n\n setAllAvailableWidgets(authorizedWidgetsList);\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n React.useEffect(() => {\n if (allAvailableWidgets.length === 0) return;\n\n // If user has customized the homepage layout, apply it\n if (homepageLayout && homepageLayout.widgets) {\n const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(\n allAvailableWidgets,\n homepageLayout\n );\n\n setFilteredWidgets(filteredWidgets);\n setColumnWidths(homepageWidths);\n } else {\n // Set default layout when no custom layout exists\n setFilteredWidgets(allAvailableWidgets);\n setColumnWidths(createDefaultWidgetWidths(allAvailableWidgets));\n }\n }, [homepageLayout, allAvailableWidgets, setColumnWidths]);\n\n const widgetLayout = React.useMemo(() => {\n return filteredWidgets.map((widget, index) => {\n const rightWidgetId = filteredWidgets[index + 1]?.uid;\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n const rightWidgetWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n return {\n widget,\n index,\n isLastInRow: isLastWidgetInRow(index, filteredWidgets, columnWidths),\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize:\n rightWidgetId &&\n canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets),\n };\n });\n }, [filteredWidgets, columnWidths]);\n\n return (\n <Layouts.Root>\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n primaryAction={\n <Button\n variant=\"tertiary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={() => setIsAddWidgetModalOpen(true)}\n fullWidth\n >\n {formatMessage({\n id: 'HomePage.addWidget.button',\n defaultMessage: 'Add Widget',\n })}\n </Button>\n }\n />\n <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <AddWidgetModal\n isOpen={isAddWidgetModalOpen}\n onClose={() => setIsAddWidgetModalOpen(false)}\n onAddWidget={addWidget}\n currentWidgets={filteredWidgets}\n availableWidgets={allAvailableWidgets}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n {loading ? (\n <Box position=\"absolute\" top={0} left={0} right={0} bottom={0}>\n <Page.Loading />\n </Box>\n ) : (\n <Box position=\"relative\" {...{ [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true }}>\n <Grid.Root gap={5}>\n {widgetLayout.map(\n ({\n widget,\n isLastInRow,\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize,\n }) => (\n <React.Fragment key={widget.uid}>\n <Grid.Item col={widgetWidth} xs={12}>\n <WidgetRoot\n uid={widget.uid}\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n findWidget={findWidget}\n deleteWidget={deleteWidget}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n component={widget.component}\n >\n <WidgetComponent\n component={widget.component}\n columnWidth={widgetWidth}\n />\n </WidgetRoot>\n </Grid.Item>\n\n {!isLastInRow && canResize && rightWidgetId && (\n <WidgetResizeHandle\n key={`resize-${widget.uid}`}\n leftWidgetId={widget.uid}\n rightWidgetId={rightWidgetId}\n leftWidgetWidth={widgetWidth}\n rightWidgetWidth={rightWidgetWidth}\n onResize={handleWidgetResize}\n saveLayout={saveLayout}\n filteredWidgets={filteredWidgets}\n />\n )}\n </React.Fragment>\n )\n )}\n </Grid.Root>\n\n {isDraggingWidget && (\n <GapDropZoneManager\n filteredWidgets={filteredWidgets}\n columnWidths={columnWidths}\n draggedWidgetId={draggedWidgetId}\n moveWidget={moveWidget}\n />\n )}\n </Box>\n )}\n </Flex>\n </Layouts.Content>\n\n {/* Add the DragLayer to handle custom drag previews */}\n <DragLayer\n renderItem={({ type, item }) => {\n if (!isWidgetDragItem(item)) {\n return null;\n }\n\n const widgetElement = getWidgetElement(item.id);\n const maxWidth = `${widgetElement?.clientWidth}px`;\n\n return (\n <DragPreviewWrapper $maxWidth={maxWidth}>\n <WidgetRoot\n uid={item.id as WidgetWithUID['uid']}\n title={item.title || { id: `${item.id}`, defaultMessage: item.id }}\n icon={item.icon}\n link={item.link}\n >\n <WidgetComponent component={item.component} columnWidth={4} />\n </WidgetRoot>\n </DragPreviewWrapper>\n );\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["DragPreviewWrapper","styled","div","props","$maxWidth","theme","colors","primary500","borderRadius","WidgetComponent","component","columnWidth","loadedComponent","setLoadedComponent","React","useState","useEffect","loadComponent","resolvedComponent","Component","_jsx","Widget","Loading","HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","data","homepageLayout","isLoading","_isLoadingLayout","useGetHomepageLayoutQuery","filteredWidgets","setFilteredWidgets","allAvailableWidgets","setAllAvailableWidgets","loading","setLoading","isAddWidgetModalOpen","setIsAddWidgetModalOpen","findWidget","deleteWidget","addWidget","moveWidget","columnWidths","setColumnWidths","handleWidgetResize","saveLayout","isDraggingWidget","draggedWidgetId","handleDragStart","handleDragEnd","useWidgets","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","authorizedWidgetsList","filter","_","i","widths","homepageWidths","applyHomepageLayout","createDefaultWidgetWidths","widgetLayout","useMemo","index","rightWidgetId","uid","widgetWidth","getWidgetWidth","rightWidgetWidth","isLastInRow","isLastWidgetInRow","canResize","canResizeBetweenWidgets","Layouts","Root","_jsxs","Main","Page","Title","id","defaultMessage","Header","title","name","subtitle","primaryAction","Button","variant","size","startIcon","Plus","onClick","fullWidth","FreeTrialWelcomeModal","FreeTrialEndedModal","AddWidgetModal","isOpen","onClose","onAddWidget","currentWidgets","availableWidgets","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTourHomepageOverview","Box","position","top","left","right","bottom","WIDGET_DATA_ATTRIBUTES","GRID_CONTAINER","Grid","Fragment","Item","col","xs","WidgetRoot","icon","link","onDragStart","onDragEnd","WidgetResizeHandle","leftWidgetId","leftWidgetWidth","onResize","GapDropZoneManager","DragLayer","renderItem","type","item","isWidgetDragItem","widgetElement","getWidgetElement","maxWidth","clientWidth","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
1
+ {"version":3,"file":"HomePage.js","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Grid, Main } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { DragLayer, isWidgetDragItem } from '../../components/DragLayer';\nimport { GapDropZoneManager } from '../../components/GapDropZone';\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { WidgetResizeHandle } from '../../components/ResizeIndicator';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { WidgetRoot } from '../../components/WidgetRoot';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\nimport { useWidgets } from '../../features/Widgets';\nimport {\n useGetCountDocumentsQuery,\n useGetHomepageLayoutQuery,\n useGetKeyStatisticsQuery,\n} from '../../services/homepage';\nimport {\n getWidgetElement,\n WIDGET_DATA_ATTRIBUTES,\n applyHomepageLayout,\n createDefaultWidgetWidths,\n isLastWidgetInRow,\n canResizeBetweenWidgets,\n getWidgetWidth,\n} from '../../utils/widgetLayout';\n\nimport { AddWidgetModal } from './components/AddWidgetModal';\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\n\ntype WidgetPermissionStatus = 'allowed' | 'denied' | 'loading';\n\nconst getWidgetPermissionsCacheKey = (permissions: NonNullable<WidgetWithUID['permissions']>) => {\n return permissions\n .map((permission) =>\n JSON.stringify({\n action: permission.action,\n subject: permission.subject,\n conditions: permission.conditions ?? [],\n properties: permission.properties ?? {},\n })\n )\n .sort()\n .join('|');\n};\n\n// Styled wrapper for the drag preview\nconst DragPreviewWrapper = styled.div<{ $maxWidth: string }>`\n max-width: ${(props) => props.$maxWidth};\n overflow: hidden;\n opacity: 0.9;\n border: 2px solid ${({ theme }) => theme.colors.primary500};\n border-radius: ${({ theme }) => theme.borderRadius};\n pointer-events: none;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nexport const WidgetComponent = ({\n component,\n columnWidth,\n}: {\n component: () => Promise<React.ComponentType>;\n columnWidth: number;\n}) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType<{\n columnWidth?: number;\n }> | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component {...({ columnWidth } as Record<string, unknown>)} />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const allWidgets = React.useMemo(() => getAllWidgets(), [getAllWidgets]);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();\n // Prefetch expensive widget data as soon as the homepage route is active.\n useGetCountDocumentsQuery();\n useGetKeyStatisticsQuery();\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [widgetPermissionStatus, setWidgetPermissionStatus] = React.useState<\n Record<string, WidgetPermissionStatus>\n >(() =>\n allWidgets.reduce<Record<string, WidgetPermissionStatus>>((acc, widget) => {\n acc[widget.uid] =\n !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';\n return acc;\n }, {})\n );\n const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);\n\n // Use custom hook for widget management\n const {\n findWidget,\n deleteWidget,\n addWidget,\n moveWidget,\n columnWidths,\n setColumnWidths,\n handleWidgetResize,\n saveLayout,\n isDraggingWidget,\n draggedWidgetId,\n handleDragStart,\n handleDragEnd,\n } = useWidgets({\n filteredWidgets,\n setFilteredWidgets,\n });\n\n React.useEffect(() => {\n const initialPermissionStatus = allWidgets.reduce<Record<string, WidgetPermissionStatus>>(\n (acc, widget) => {\n acc[widget.uid] =\n !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';\n return acc;\n },\n {}\n );\n\n setWidgetPermissionStatus(initialPermissionStatus);\n\n const widgetsWithPermissions = allWidgets.filter(\n (widget) => widget.permissions && widget.permissions.length > 0\n );\n\n if (widgetsWithPermissions.length === 0) {\n return;\n }\n\n const groupedPermissions = widgetsWithPermissions.reduce<\n Map<string, { permissions: NonNullable<WidgetWithUID['permissions']>; uids: string[] }>\n >((acc, widget) => {\n const permissions = widget.permissions ?? [];\n const key = getWidgetPermissionsCacheKey(permissions);\n const existingGroup = acc.get(key);\n\n if (existingGroup) {\n existingGroup.uids.push(widget.uid);\n } else {\n acc.set(key, { permissions, uids: [widget.uid] });\n }\n\n return acc;\n }, new Map());\n\n let isMounted = true;\n\n const checkWidgetsPermissions = async () => {\n try {\n const permissionResults = await Promise.all(\n Array.from(groupedPermissions.values()).map(async ({ permissions, uids }) => {\n const matchingPermissions = await checkUserHasPermissions(permissions);\n const status: WidgetPermissionStatus =\n matchingPermissions.length >= permissions.length ? 'allowed' : 'denied';\n\n return { uids, status };\n })\n );\n\n if (!isMounted) return;\n\n setWidgetPermissionStatus((prev) => {\n const next = { ...prev };\n\n permissionResults.forEach(({ uids, status }) => {\n uids.forEach((uid) => {\n next[uid] = status;\n });\n });\n\n return next;\n });\n } catch {\n if (!isMounted) return;\n\n // Keep the UI responsive even when permission checks fail.\n setWidgetPermissionStatus((prev) => {\n const next = { ...prev };\n widgetsWithPermissions.forEach((widget) => {\n next[widget.uid] = 'denied';\n });\n return next;\n });\n }\n };\n\n checkWidgetsPermissions();\n\n return () => {\n isMounted = false;\n };\n }, [allWidgets, checkUserHasPermissions]);\n\n const allAvailableWidgets = React.useMemo(() => {\n return allWidgets.filter((widget) => widgetPermissionStatus[widget.uid] === 'allowed');\n }, [allWidgets, widgetPermissionStatus]);\n\n const renderableWidgets = React.useMemo(() => {\n return allWidgets.filter((widget) => widgetPermissionStatus[widget.uid] !== 'denied');\n }, [allWidgets, widgetPermissionStatus]);\n\n React.useEffect(() => {\n // If user has customized the homepage layout, apply it\n if (homepageLayout && homepageLayout.widgets) {\n const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(\n renderableWidgets,\n homepageLayout\n );\n\n setFilteredWidgets(filteredWidgets);\n setColumnWidths(homepageWidths);\n } else {\n // Set default layout when no custom layout exists\n setFilteredWidgets(renderableWidgets);\n setColumnWidths(createDefaultWidgetWidths(renderableWidgets));\n }\n }, [homepageLayout, renderableWidgets, setColumnWidths]);\n\n const widgetLayout = React.useMemo(() => {\n return filteredWidgets.map((widget, index) => {\n const rightWidgetId = filteredWidgets[index + 1]?.uid;\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n const rightWidgetWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n return {\n widget,\n index,\n isLastInRow: isLastWidgetInRow(index, filteredWidgets, columnWidths),\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize:\n rightWidgetId &&\n canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets),\n };\n });\n }, [filteredWidgets, columnWidths]);\n\n return (\n <Layouts.Root>\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n primaryAction={\n <Button\n variant=\"tertiary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={() => setIsAddWidgetModalOpen(true)}\n fullWidth\n >\n {formatMessage({\n id: 'HomePage.addWidget.button',\n defaultMessage: 'Add Widget',\n })}\n </Button>\n }\n />\n <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <AddWidgetModal\n isOpen={isAddWidgetModalOpen}\n onClose={() => setIsAddWidgetModalOpen(false)}\n onAddWidget={addWidget}\n currentWidgets={filteredWidgets}\n availableWidgets={allAvailableWidgets}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n <Box position=\"relative\" {...{ [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true }}>\n <Grid.Root gap={5}>\n {widgetLayout.map(\n ({\n widget,\n isLastInRow,\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize,\n }) => (\n <React.Fragment key={widget.uid}>\n <Grid.Item col={widgetWidth} xs={12}>\n <WidgetRoot\n uid={widget.uid}\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n findWidget={findWidget}\n deleteWidget={deleteWidget}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n component={widget.component}\n >\n {widgetPermissionStatus[widget.uid] === 'loading' ? (\n <Widget.Loading />\n ) : (\n <WidgetComponent\n component={widget.component}\n columnWidth={widgetWidth}\n />\n )}\n </WidgetRoot>\n </Grid.Item>\n\n {!isLastInRow && canResize && rightWidgetId && (\n <WidgetResizeHandle\n key={`resize-${widget.uid}`}\n leftWidgetId={widget.uid}\n rightWidgetId={rightWidgetId}\n leftWidgetWidth={widgetWidth}\n rightWidgetWidth={rightWidgetWidth}\n onResize={handleWidgetResize}\n saveLayout={saveLayout}\n filteredWidgets={filteredWidgets}\n />\n )}\n </React.Fragment>\n )\n )}\n </Grid.Root>\n\n {isDraggingWidget && (\n <GapDropZoneManager\n filteredWidgets={filteredWidgets}\n columnWidths={columnWidths}\n draggedWidgetId={draggedWidgetId}\n moveWidget={moveWidget}\n />\n )}\n </Box>\n </Flex>\n </Layouts.Content>\n\n {/* Add the DragLayer to handle custom drag previews */}\n <DragLayer\n renderItem={({ type: _type, item }) => {\n if (!isWidgetDragItem(item)) {\n return null;\n }\n\n const widgetElement = getWidgetElement(item.id);\n const maxWidth = `${widgetElement?.clientWidth}px`;\n\n return (\n <DragPreviewWrapper $maxWidth={maxWidth}>\n <WidgetRoot\n uid={item.id as WidgetWithUID['uid']}\n title={item.title || { id: `${item.id}`, defaultMessage: item.id }}\n icon={item.icon}\n link={item.link}\n >\n <WidgetComponent component={item.component} columnWidth={4} />\n </WidgetRoot>\n </DragPreviewWrapper>\n );\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["getWidgetPermissionsCacheKey","permissions","map","permission","JSON","stringify","action","subject","conditions","properties","sort","join","DragPreviewWrapper","styled","div","props","$maxWidth","theme","colors","primary500","borderRadius","WidgetComponent","component","columnWidth","loadedComponent","setLoadedComponent","React","useState","useEffect","loadComponent","resolvedComponent","Component","_jsx","Widget","Loading","HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","allWidgets","useMemo","checkUserHasPermissions","data","homepageLayout","isLoading","_isLoadingLayout","useGetHomepageLayoutQuery","useGetCountDocumentsQuery","useGetKeyStatisticsQuery","filteredWidgets","setFilteredWidgets","widgetPermissionStatus","setWidgetPermissionStatus","reduce","acc","widget","uid","length","isAddWidgetModalOpen","setIsAddWidgetModalOpen","findWidget","deleteWidget","addWidget","moveWidget","columnWidths","setColumnWidths","handleWidgetResize","saveLayout","isDraggingWidget","draggedWidgetId","handleDragStart","handleDragEnd","useWidgets","initialPermissionStatus","widgetsWithPermissions","filter","groupedPermissions","key","existingGroup","get","uids","push","set","Map","isMounted","checkWidgetsPermissions","permissionResults","Promise","all","Array","from","values","matchingPermissions","status","prev","next","forEach","allAvailableWidgets","renderableWidgets","widths","homepageWidths","applyHomepageLayout","createDefaultWidgetWidths","widgetLayout","index","rightWidgetId","widgetWidth","getWidgetWidth","rightWidgetWidth","isLastInRow","isLastWidgetInRow","canResize","canResizeBetweenWidgets","Layouts","Root","_jsxs","Main","Page","Title","id","defaultMessage","Header","title","name","subtitle","primaryAction","Button","variant","size","startIcon","Plus","onClick","fullWidth","FreeTrialWelcomeModal","FreeTrialEndedModal","AddWidgetModal","isOpen","onClose","onAddWidget","currentWidgets","availableWidgets","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTourHomepageOverview","Box","position","WIDGET_DATA_ATTRIBUTES","GRID_CONTAINER","Grid","Fragment","Item","col","xs","WidgetRoot","icon","link","onDragStart","onDragEnd","WidgetResizeHandle","leftWidgetId","leftWidgetWidth","onResize","GapDropZoneManager","DragLayer","renderItem","type","_type","item","isWidgetDragItem","widgetElement","getWidgetElement","maxWidth","clientWidth","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
@@ -18,12 +18,20 @@ import '../../../../ee/admin/src/services/ai.mjs';
18
18
  import { useAuth } from '../../features/Auth.mjs';
19
19
  import { useStrapiApp } from '../../features/StrapiApp.mjs';
20
20
  import { useWidgets } from '../../features/Widgets.mjs';
21
- import { useGetHomepageLayoutQuery } from '../../services/homepage.mjs';
21
+ import { useGetHomepageLayoutQuery, useGetCountDocumentsQuery, useGetKeyStatisticsQuery } from '../../services/homepage.mjs';
22
22
  import { applyHomepageLayout, createDefaultWidgetWidths, getWidgetWidth, canResizeBetweenWidgets, isLastWidgetInRow, WIDGET_DATA_ATTRIBUTES, getWidgetElement } from '../../utils/widgetLayout.mjs';
23
23
  import { AddWidgetModal } from './components/AddWidgetModal.mjs';
24
24
  import { FreeTrialEndedModal } from './components/FreeTrialEndedModal.mjs';
25
25
  import { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal.mjs';
26
26
 
27
+ const getWidgetPermissionsCacheKey = (permissions)=>{
28
+ return permissions.map((permission)=>JSON.stringify({
29
+ action: permission.action,
30
+ subject: permission.subject,
31
+ conditions: permission.conditions ?? [],
32
+ properties: permission.properties ?? {}
33
+ })).sort().join('|');
34
+ };
27
35
  // Styled wrapper for the drag preview
28
36
  const DragPreviewWrapper = styled.div`
29
37
  max-width: ${(props)=>props.$maxWidth};
@@ -63,11 +71,19 @@ const DragPreviewWrapper = styled.div`
63
71
  const user = useAuth('HomePageCE', (state)=>state.user);
64
72
  const displayName = user?.firstname ?? user?.username ?? user?.email;
65
73
  const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state)=>state.widgets.getAll);
74
+ const allWidgets = React.useMemo(()=>getAllWidgets(), [
75
+ getAllWidgets
76
+ ]);
66
77
  const checkUserHasPermissions = useAuth('WidgetRoot', (state)=>state.checkUserHasPermissions);
67
78
  const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();
79
+ // Prefetch expensive widget data as soon as the homepage route is active.
80
+ useGetCountDocumentsQuery();
81
+ useGetKeyStatisticsQuery();
68
82
  const [filteredWidgets, setFilteredWidgets] = React.useState([]);
69
- const [allAvailableWidgets, setAllAvailableWidgets] = React.useState([]);
70
- const [loading, setLoading] = React.useState(true);
83
+ const [widgetPermissionStatus, setWidgetPermissionStatus] = React.useState(()=>allWidgets.reduce((acc, widget)=>{
84
+ acc[widget.uid] = !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';
85
+ return acc;
86
+ }, {}));
71
87
  const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);
72
88
  // Use custom hook for widget management
73
89
  const { findWidget, deleteWidget, addWidget, moveWidget, columnWidths, setColumnWidths, handleWidgetResize, saveLayout, isDraggingWidget, draggedWidgetId, handleDragStart, handleDragEnd } = useWidgets({
@@ -75,37 +91,102 @@ const DragPreviewWrapper = styled.div`
75
91
  setFilteredWidgets
76
92
  });
77
93
  React.useEffect(()=>{
94
+ const initialPermissionStatus = allWidgets.reduce((acc, widget)=>{
95
+ acc[widget.uid] = !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';
96
+ return acc;
97
+ }, {});
98
+ setWidgetPermissionStatus(initialPermissionStatus);
99
+ const widgetsWithPermissions = allWidgets.filter((widget)=>widget.permissions && widget.permissions.length > 0);
100
+ if (widgetsWithPermissions.length === 0) {
101
+ return;
102
+ }
103
+ const groupedPermissions = widgetsWithPermissions.reduce((acc, widget)=>{
104
+ const permissions = widget.permissions ?? [];
105
+ const key = getWidgetPermissionsCacheKey(permissions);
106
+ const existingGroup = acc.get(key);
107
+ if (existingGroup) {
108
+ existingGroup.uids.push(widget.uid);
109
+ } else {
110
+ acc.set(key, {
111
+ permissions,
112
+ uids: [
113
+ widget.uid
114
+ ]
115
+ });
116
+ }
117
+ return acc;
118
+ }, new Map());
119
+ let isMounted = true;
78
120
  const checkWidgetsPermissions = async ()=>{
79
- const allWidgets = getAllWidgets();
80
- const authorizedWidgets = await Promise.all(allWidgets.map(async (widget)=>{
81
- if (!widget.permissions || widget.permissions.length === 0) return true;
82
- const matchingPermissions = await checkUserHasPermissions(widget.permissions);
83
- return matchingPermissions.length >= widget.permissions.length;
84
- }));
85
- const authorizedWidgetsList = allWidgets.filter((_, i)=>authorizedWidgets[i]);
86
- setAllAvailableWidgets(authorizedWidgetsList);
87
- setLoading(false);
121
+ try {
122
+ const permissionResults = await Promise.all(Array.from(groupedPermissions.values()).map(async ({ permissions, uids })=>{
123
+ const matchingPermissions = await checkUserHasPermissions(permissions);
124
+ const status = matchingPermissions.length >= permissions.length ? 'allowed' : 'denied';
125
+ return {
126
+ uids,
127
+ status
128
+ };
129
+ }));
130
+ if (!isMounted) return;
131
+ setWidgetPermissionStatus((prev)=>{
132
+ const next = {
133
+ ...prev
134
+ };
135
+ permissionResults.forEach(({ uids, status })=>{
136
+ uids.forEach((uid)=>{
137
+ next[uid] = status;
138
+ });
139
+ });
140
+ return next;
141
+ });
142
+ } catch {
143
+ if (!isMounted) return;
144
+ // Keep the UI responsive even when permission checks fail.
145
+ setWidgetPermissionStatus((prev)=>{
146
+ const next = {
147
+ ...prev
148
+ };
149
+ widgetsWithPermissions.forEach((widget)=>{
150
+ next[widget.uid] = 'denied';
151
+ });
152
+ return next;
153
+ });
154
+ }
88
155
  };
89
156
  checkWidgetsPermissions();
157
+ return ()=>{
158
+ isMounted = false;
159
+ };
90
160
  }, [
91
- checkUserHasPermissions,
92
- getAllWidgets
161
+ allWidgets,
162
+ checkUserHasPermissions
163
+ ]);
164
+ const allAvailableWidgets = React.useMemo(()=>{
165
+ return allWidgets.filter((widget)=>widgetPermissionStatus[widget.uid] === 'allowed');
166
+ }, [
167
+ allWidgets,
168
+ widgetPermissionStatus
169
+ ]);
170
+ const renderableWidgets = React.useMemo(()=>{
171
+ return allWidgets.filter((widget)=>widgetPermissionStatus[widget.uid] !== 'denied');
172
+ }, [
173
+ allWidgets,
174
+ widgetPermissionStatus
93
175
  ]);
94
176
  React.useEffect(()=>{
95
- if (allAvailableWidgets.length === 0) return;
96
177
  // If user has customized the homepage layout, apply it
97
178
  if (homepageLayout && homepageLayout.widgets) {
98
- const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(allAvailableWidgets, homepageLayout);
179
+ const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(renderableWidgets, homepageLayout);
99
180
  setFilteredWidgets(filteredWidgets);
100
181
  setColumnWidths(homepageWidths);
101
182
  } else {
102
183
  // Set default layout when no custom layout exists
103
- setFilteredWidgets(allAvailableWidgets);
104
- setColumnWidths(createDefaultWidgetWidths(allAvailableWidgets));
184
+ setFilteredWidgets(renderableWidgets);
185
+ setColumnWidths(createDefaultWidgetWidths(renderableWidgets));
105
186
  }
106
187
  }, [
107
188
  homepageLayout,
108
- allAvailableWidgets,
189
+ renderableWidgets,
109
190
  setColumnWidths
110
191
  ]);
111
192
  const widgetLayout = React.useMemo(()=>{
@@ -176,14 +257,7 @@ const DragPreviewWrapper = styled.div`
176
257
  paddingBottom: 10,
177
258
  children: [
178
259
  /*#__PURE__*/ jsx(GuidedTourHomepageOverview, {}),
179
- loading ? /*#__PURE__*/ jsx(Box, {
180
- position: "absolute",
181
- top: 0,
182
- left: 0,
183
- right: 0,
184
- bottom: 0,
185
- children: /*#__PURE__*/ jsx(Page.Loading, {})
186
- }) : /*#__PURE__*/ jsxs(Box, {
260
+ /*#__PURE__*/ jsxs(Box, {
187
261
  position: "relative",
188
262
  [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true,
189
263
  children: [
@@ -204,7 +278,7 @@ const DragPreviewWrapper = styled.div`
204
278
  onDragStart: handleDragStart,
205
279
  onDragEnd: handleDragEnd,
206
280
  component: widget.component,
207
- children: /*#__PURE__*/ jsx(WidgetComponent, {
281
+ children: widgetPermissionStatus[widget.uid] === 'loading' ? /*#__PURE__*/ jsx(Widget.Loading, {}) : /*#__PURE__*/ jsx(WidgetComponent, {
208
282
  component: widget.component,
209
283
  columnWidth: widgetWidth
210
284
  })
@@ -234,7 +308,7 @@ const DragPreviewWrapper = styled.div`
234
308
  })
235
309
  }),
236
310
  /*#__PURE__*/ jsx(DragLayer, {
237
- renderItem: ({ type, item })=>{
311
+ renderItem: ({ type: _type, item })=>{
238
312
  if (!isWidgetDragItem(item)) {
239
313
  return null;
240
314
  }
@@ -1 +1 @@
1
- {"version":3,"file":"HomePage.mjs","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Grid, Main } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { DragLayer, isWidgetDragItem } from '../../components/DragLayer';\nimport { GapDropZoneManager } from '../../components/GapDropZone';\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { WidgetResizeHandle } from '../../components/ResizeIndicator';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { WidgetRoot } from '../../components/WidgetRoot';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\nimport { useWidgets } from '../../features/Widgets';\nimport { useGetHomepageLayoutQuery } from '../../services/homepage';\nimport {\n getWidgetElement,\n WIDGET_DATA_ATTRIBUTES,\n applyHomepageLayout,\n createDefaultWidgetWidths,\n isLastWidgetInRow,\n canResizeBetweenWidgets,\n getWidgetWidth,\n} from '../../utils/widgetLayout';\n\nimport { AddWidgetModal } from './components/AddWidgetModal';\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\n\n// Styled wrapper for the drag preview\nconst DragPreviewWrapper = styled.div<{ $maxWidth: string }>`\n max-width: ${(props) => props.$maxWidth};\n overflow: hidden;\n opacity: 0.9;\n border: 2px solid ${({ theme }) => theme.colors.primary500};\n border-radius: ${({ theme }) => theme.borderRadius};\n pointer-events: none;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nexport const WidgetComponent = ({\n component,\n columnWidth,\n}: {\n component: () => Promise<React.ComponentType>;\n columnWidth: number;\n}) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType<{\n columnWidth?: number;\n }> | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component {...({ columnWidth } as Record<string, unknown>)} />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [allAvailableWidgets, setAllAvailableWidgets] = React.useState<WidgetWithUID[]>([]);\n const [loading, setLoading] = React.useState(true);\n const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);\n\n // Use custom hook for widget management\n const {\n findWidget,\n deleteWidget,\n addWidget,\n moveWidget,\n columnWidths,\n setColumnWidths,\n handleWidgetResize,\n saveLayout,\n isDraggingWidget,\n draggedWidgetId,\n handleDragStart,\n handleDragEnd,\n } = useWidgets({\n filteredWidgets,\n setFilteredWidgets,\n });\n\n React.useEffect(() => {\n const checkWidgetsPermissions = async () => {\n const allWidgets = getAllWidgets();\n const authorizedWidgets = await Promise.all(\n allWidgets.map(async (widget) => {\n if (!widget.permissions || widget.permissions.length === 0) return true;\n const matchingPermissions = await checkUserHasPermissions(widget.permissions);\n return matchingPermissions.length >= widget.permissions.length;\n })\n );\n const authorizedWidgetsList = allWidgets.filter((_, i) => authorizedWidgets[i]);\n\n setAllAvailableWidgets(authorizedWidgetsList);\n setLoading(false);\n };\n\n checkWidgetsPermissions();\n }, [checkUserHasPermissions, getAllWidgets]);\n\n React.useEffect(() => {\n if (allAvailableWidgets.length === 0) return;\n\n // If user has customized the homepage layout, apply it\n if (homepageLayout && homepageLayout.widgets) {\n const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(\n allAvailableWidgets,\n homepageLayout\n );\n\n setFilteredWidgets(filteredWidgets);\n setColumnWidths(homepageWidths);\n } else {\n // Set default layout when no custom layout exists\n setFilteredWidgets(allAvailableWidgets);\n setColumnWidths(createDefaultWidgetWidths(allAvailableWidgets));\n }\n }, [homepageLayout, allAvailableWidgets, setColumnWidths]);\n\n const widgetLayout = React.useMemo(() => {\n return filteredWidgets.map((widget, index) => {\n const rightWidgetId = filteredWidgets[index + 1]?.uid;\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n const rightWidgetWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n return {\n widget,\n index,\n isLastInRow: isLastWidgetInRow(index, filteredWidgets, columnWidths),\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize:\n rightWidgetId &&\n canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets),\n };\n });\n }, [filteredWidgets, columnWidths]);\n\n return (\n <Layouts.Root>\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n primaryAction={\n <Button\n variant=\"tertiary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={() => setIsAddWidgetModalOpen(true)}\n fullWidth\n >\n {formatMessage({\n id: 'HomePage.addWidget.button',\n defaultMessage: 'Add Widget',\n })}\n </Button>\n }\n />\n <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <AddWidgetModal\n isOpen={isAddWidgetModalOpen}\n onClose={() => setIsAddWidgetModalOpen(false)}\n onAddWidget={addWidget}\n currentWidgets={filteredWidgets}\n availableWidgets={allAvailableWidgets}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n {loading ? (\n <Box position=\"absolute\" top={0} left={0} right={0} bottom={0}>\n <Page.Loading />\n </Box>\n ) : (\n <Box position=\"relative\" {...{ [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true }}>\n <Grid.Root gap={5}>\n {widgetLayout.map(\n ({\n widget,\n isLastInRow,\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize,\n }) => (\n <React.Fragment key={widget.uid}>\n <Grid.Item col={widgetWidth} xs={12}>\n <WidgetRoot\n uid={widget.uid}\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n findWidget={findWidget}\n deleteWidget={deleteWidget}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n component={widget.component}\n >\n <WidgetComponent\n component={widget.component}\n columnWidth={widgetWidth}\n />\n </WidgetRoot>\n </Grid.Item>\n\n {!isLastInRow && canResize && rightWidgetId && (\n <WidgetResizeHandle\n key={`resize-${widget.uid}`}\n leftWidgetId={widget.uid}\n rightWidgetId={rightWidgetId}\n leftWidgetWidth={widgetWidth}\n rightWidgetWidth={rightWidgetWidth}\n onResize={handleWidgetResize}\n saveLayout={saveLayout}\n filteredWidgets={filteredWidgets}\n />\n )}\n </React.Fragment>\n )\n )}\n </Grid.Root>\n\n {isDraggingWidget && (\n <GapDropZoneManager\n filteredWidgets={filteredWidgets}\n columnWidths={columnWidths}\n draggedWidgetId={draggedWidgetId}\n moveWidget={moveWidget}\n />\n )}\n </Box>\n )}\n </Flex>\n </Layouts.Content>\n\n {/* Add the DragLayer to handle custom drag previews */}\n <DragLayer\n renderItem={({ type, item }) => {\n if (!isWidgetDragItem(item)) {\n return null;\n }\n\n const widgetElement = getWidgetElement(item.id);\n const maxWidth = `${widgetElement?.clientWidth}px`;\n\n return (\n <DragPreviewWrapper $maxWidth={maxWidth}>\n <WidgetRoot\n uid={item.id as WidgetWithUID['uid']}\n title={item.title || { id: `${item.id}`, defaultMessage: item.id }}\n icon={item.icon}\n link={item.link}\n >\n <WidgetComponent component={item.component} columnWidth={4} />\n </WidgetRoot>\n </DragPreviewWrapper>\n );\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["DragPreviewWrapper","styled","div","props","$maxWidth","theme","colors","primary500","borderRadius","WidgetComponent","component","columnWidth","loadedComponent","setLoadedComponent","React","useState","useEffect","loadComponent","resolvedComponent","Component","_jsx","Widget","Loading","HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","checkUserHasPermissions","data","homepageLayout","isLoading","_isLoadingLayout","useGetHomepageLayoutQuery","filteredWidgets","setFilteredWidgets","allAvailableWidgets","setAllAvailableWidgets","loading","setLoading","isAddWidgetModalOpen","setIsAddWidgetModalOpen","findWidget","deleteWidget","addWidget","moveWidget","columnWidths","setColumnWidths","handleWidgetResize","saveLayout","isDraggingWidget","draggedWidgetId","handleDragStart","handleDragEnd","useWidgets","checkWidgetsPermissions","allWidgets","authorizedWidgets","Promise","all","map","widget","permissions","length","matchingPermissions","authorizedWidgetsList","filter","_","i","widths","homepageWidths","applyHomepageLayout","createDefaultWidgetWidths","widgetLayout","useMemo","index","rightWidgetId","uid","widgetWidth","getWidgetWidth","rightWidgetWidth","isLastInRow","isLastWidgetInRow","canResize","canResizeBetweenWidgets","Layouts","Root","_jsxs","Main","Page","Title","id","defaultMessage","Header","title","name","subtitle","primaryAction","Button","variant","size","startIcon","Plus","onClick","fullWidth","FreeTrialWelcomeModal","FreeTrialEndedModal","AddWidgetModal","isOpen","onClose","onAddWidget","currentWidgets","availableWidgets","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTourHomepageOverview","Box","position","top","left","right","bottom","WIDGET_DATA_ATTRIBUTES","GRID_CONTAINER","Grid","Fragment","Item","col","xs","WidgetRoot","icon","link","onDragStart","onDragEnd","WidgetResizeHandle","leftWidgetId","leftWidgetWidth","onResize","GapDropZoneManager","DragLayer","renderItem","type","item","isWidgetDragItem","widgetElement","getWidgetElement","maxWidth","clientWidth","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
1
+ {"version":3,"file":"HomePage.mjs","sources":["../../../../../../admin/src/pages/Home/HomePage.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box, Button, Flex, Grid, Main } from '@strapi/design-system';\nimport { Plus } from '@strapi/icons';\nimport { useIntl } from 'react-intl';\nimport { styled } from 'styled-components';\n\nimport { DragLayer, isWidgetDragItem } from '../../components/DragLayer';\nimport { GapDropZoneManager } from '../../components/GapDropZone';\nimport { GuidedTourHomepageOverview } from '../../components/GuidedTour/Overview';\nimport { Layouts } from '../../components/Layouts/Layout';\nimport { Page } from '../../components/PageHelpers';\nimport { WidgetResizeHandle } from '../../components/ResizeIndicator';\nimport { Widget } from '../../components/WidgetHelpers';\nimport { WidgetRoot } from '../../components/WidgetRoot';\nimport { useEnterprise } from '../../ee';\nimport { useAuth } from '../../features/Auth';\nimport { useStrapiApp } from '../../features/StrapiApp';\nimport { useWidgets } from '../../features/Widgets';\nimport {\n useGetCountDocumentsQuery,\n useGetHomepageLayoutQuery,\n useGetKeyStatisticsQuery,\n} from '../../services/homepage';\nimport {\n getWidgetElement,\n WIDGET_DATA_ATTRIBUTES,\n applyHomepageLayout,\n createDefaultWidgetWidths,\n isLastWidgetInRow,\n canResizeBetweenWidgets,\n getWidgetWidth,\n} from '../../utils/widgetLayout';\n\nimport { AddWidgetModal } from './components/AddWidgetModal';\nimport { FreeTrialEndedModal } from './components/FreeTrialEndedModal';\nimport { FreeTrialWelcomeModal } from './components/FreeTrialWelcomeModal';\n\nimport type { WidgetWithUID } from '../../core/apis/Widgets';\n\ntype WidgetPermissionStatus = 'allowed' | 'denied' | 'loading';\n\nconst getWidgetPermissionsCacheKey = (permissions: NonNullable<WidgetWithUID['permissions']>) => {\n return permissions\n .map((permission) =>\n JSON.stringify({\n action: permission.action,\n subject: permission.subject,\n conditions: permission.conditions ?? [],\n properties: permission.properties ?? {},\n })\n )\n .sort()\n .join('|');\n};\n\n// Styled wrapper for the drag preview\nconst DragPreviewWrapper = styled.div<{ $maxWidth: string }>`\n max-width: ${(props) => props.$maxWidth};\n overflow: hidden;\n opacity: 0.9;\n border: 2px solid ${({ theme }) => theme.colors.primary500};\n border-radius: ${({ theme }) => theme.borderRadius};\n pointer-events: none;\n`;\n\n/* -------------------------------------------------------------------------------------------------\n * UnstableHomePageCe\n * -----------------------------------------------------------------------------------------------*/\n\nexport const WidgetComponent = ({\n component,\n columnWidth,\n}: {\n component: () => Promise<React.ComponentType>;\n columnWidth: number;\n}) => {\n const [loadedComponent, setLoadedComponent] = React.useState<React.ComponentType<{\n columnWidth?: number;\n }> | null>(null);\n\n React.useEffect(() => {\n const loadComponent = async () => {\n const resolvedComponent = await component();\n\n setLoadedComponent(() => resolvedComponent);\n };\n\n loadComponent();\n }, [component]);\n\n const Component = loadedComponent;\n\n if (!Component) {\n return <Widget.Loading />;\n }\n\n return <Component {...({ columnWidth } as Record<string, unknown>)} />;\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePageCE\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePageCE = () => {\n const { formatMessage } = useIntl();\n const user = useAuth('HomePageCE', (state) => state.user);\n const displayName = user?.firstname ?? user?.username ?? user?.email;\n const getAllWidgets = useStrapiApp('UnstableHomepageCe', (state) => state.widgets.getAll);\n const allWidgets = React.useMemo(() => getAllWidgets(), [getAllWidgets]);\n const checkUserHasPermissions = useAuth('WidgetRoot', (state) => state.checkUserHasPermissions);\n const { data: homepageLayout, isLoading: _isLoadingLayout } = useGetHomepageLayoutQuery();\n // Prefetch expensive widget data as soon as the homepage route is active.\n useGetCountDocumentsQuery();\n useGetKeyStatisticsQuery();\n const [filteredWidgets, setFilteredWidgets] = React.useState<WidgetWithUID[]>([]);\n const [widgetPermissionStatus, setWidgetPermissionStatus] = React.useState<\n Record<string, WidgetPermissionStatus>\n >(() =>\n allWidgets.reduce<Record<string, WidgetPermissionStatus>>((acc, widget) => {\n acc[widget.uid] =\n !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';\n return acc;\n }, {})\n );\n const [isAddWidgetModalOpen, setIsAddWidgetModalOpen] = React.useState(false);\n\n // Use custom hook for widget management\n const {\n findWidget,\n deleteWidget,\n addWidget,\n moveWidget,\n columnWidths,\n setColumnWidths,\n handleWidgetResize,\n saveLayout,\n isDraggingWidget,\n draggedWidgetId,\n handleDragStart,\n handleDragEnd,\n } = useWidgets({\n filteredWidgets,\n setFilteredWidgets,\n });\n\n React.useEffect(() => {\n const initialPermissionStatus = allWidgets.reduce<Record<string, WidgetPermissionStatus>>(\n (acc, widget) => {\n acc[widget.uid] =\n !widget.permissions || widget.permissions.length === 0 ? 'allowed' : 'loading';\n return acc;\n },\n {}\n );\n\n setWidgetPermissionStatus(initialPermissionStatus);\n\n const widgetsWithPermissions = allWidgets.filter(\n (widget) => widget.permissions && widget.permissions.length > 0\n );\n\n if (widgetsWithPermissions.length === 0) {\n return;\n }\n\n const groupedPermissions = widgetsWithPermissions.reduce<\n Map<string, { permissions: NonNullable<WidgetWithUID['permissions']>; uids: string[] }>\n >((acc, widget) => {\n const permissions = widget.permissions ?? [];\n const key = getWidgetPermissionsCacheKey(permissions);\n const existingGroup = acc.get(key);\n\n if (existingGroup) {\n existingGroup.uids.push(widget.uid);\n } else {\n acc.set(key, { permissions, uids: [widget.uid] });\n }\n\n return acc;\n }, new Map());\n\n let isMounted = true;\n\n const checkWidgetsPermissions = async () => {\n try {\n const permissionResults = await Promise.all(\n Array.from(groupedPermissions.values()).map(async ({ permissions, uids }) => {\n const matchingPermissions = await checkUserHasPermissions(permissions);\n const status: WidgetPermissionStatus =\n matchingPermissions.length >= permissions.length ? 'allowed' : 'denied';\n\n return { uids, status };\n })\n );\n\n if (!isMounted) return;\n\n setWidgetPermissionStatus((prev) => {\n const next = { ...prev };\n\n permissionResults.forEach(({ uids, status }) => {\n uids.forEach((uid) => {\n next[uid] = status;\n });\n });\n\n return next;\n });\n } catch {\n if (!isMounted) return;\n\n // Keep the UI responsive even when permission checks fail.\n setWidgetPermissionStatus((prev) => {\n const next = { ...prev };\n widgetsWithPermissions.forEach((widget) => {\n next[widget.uid] = 'denied';\n });\n return next;\n });\n }\n };\n\n checkWidgetsPermissions();\n\n return () => {\n isMounted = false;\n };\n }, [allWidgets, checkUserHasPermissions]);\n\n const allAvailableWidgets = React.useMemo(() => {\n return allWidgets.filter((widget) => widgetPermissionStatus[widget.uid] === 'allowed');\n }, [allWidgets, widgetPermissionStatus]);\n\n const renderableWidgets = React.useMemo(() => {\n return allWidgets.filter((widget) => widgetPermissionStatus[widget.uid] !== 'denied');\n }, [allWidgets, widgetPermissionStatus]);\n\n React.useEffect(() => {\n // If user has customized the homepage layout, apply it\n if (homepageLayout && homepageLayout.widgets) {\n const { filteredWidgets, widths: homepageWidths } = applyHomepageLayout(\n renderableWidgets,\n homepageLayout\n );\n\n setFilteredWidgets(filteredWidgets);\n setColumnWidths(homepageWidths);\n } else {\n // Set default layout when no custom layout exists\n setFilteredWidgets(renderableWidgets);\n setColumnWidths(createDefaultWidgetWidths(renderableWidgets));\n }\n }, [homepageLayout, renderableWidgets, setColumnWidths]);\n\n const widgetLayout = React.useMemo(() => {\n return filteredWidgets.map((widget, index) => {\n const rightWidgetId = filteredWidgets[index + 1]?.uid;\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n const rightWidgetWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n return {\n widget,\n index,\n isLastInRow: isLastWidgetInRow(index, filteredWidgets, columnWidths),\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize:\n rightWidgetId &&\n canResizeBetweenWidgets(widget.uid, rightWidgetId, columnWidths, filteredWidgets),\n };\n });\n }, [filteredWidgets, columnWidths]);\n\n return (\n <Layouts.Root>\n <Main>\n <Page.Title>\n {formatMessage({ id: 'HomePage.head.title', defaultMessage: 'Homepage' })}\n </Page.Title>\n <Layouts.Header\n title={formatMessage(\n { id: 'HomePage.header.title', defaultMessage: 'Hello {name}' },\n { name: displayName }\n )}\n subtitle={formatMessage({\n id: 'HomePage.header.subtitle',\n defaultMessage: 'Welcome to your administration panel',\n })}\n primaryAction={\n <Button\n variant=\"tertiary\"\n size=\"S\"\n startIcon={<Plus />}\n onClick={() => setIsAddWidgetModalOpen(true)}\n fullWidth\n >\n {formatMessage({\n id: 'HomePage.addWidget.button',\n defaultMessage: 'Add Widget',\n })}\n </Button>\n }\n />\n <FreeTrialWelcomeModal />\n <FreeTrialEndedModal />\n <AddWidgetModal\n isOpen={isAddWidgetModalOpen}\n onClose={() => setIsAddWidgetModalOpen(false)}\n onAddWidget={addWidget}\n currentWidgets={filteredWidgets}\n availableWidgets={allAvailableWidgets}\n />\n <Layouts.Content>\n <Flex direction=\"column\" alignItems=\"stretch\" gap={8} paddingBottom={10}>\n <GuidedTourHomepageOverview />\n <Box position=\"relative\" {...{ [WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER]: true }}>\n <Grid.Root gap={5}>\n {widgetLayout.map(\n ({\n widget,\n isLastInRow,\n rightWidgetId,\n widgetWidth,\n rightWidgetWidth,\n canResize,\n }) => (\n <React.Fragment key={widget.uid}>\n <Grid.Item col={widgetWidth} xs={12}>\n <WidgetRoot\n uid={widget.uid}\n title={widget.title}\n icon={widget.icon}\n link={widget.link}\n findWidget={findWidget}\n deleteWidget={deleteWidget}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n component={widget.component}\n >\n {widgetPermissionStatus[widget.uid] === 'loading' ? (\n <Widget.Loading />\n ) : (\n <WidgetComponent\n component={widget.component}\n columnWidth={widgetWidth}\n />\n )}\n </WidgetRoot>\n </Grid.Item>\n\n {!isLastInRow && canResize && rightWidgetId && (\n <WidgetResizeHandle\n key={`resize-${widget.uid}`}\n leftWidgetId={widget.uid}\n rightWidgetId={rightWidgetId}\n leftWidgetWidth={widgetWidth}\n rightWidgetWidth={rightWidgetWidth}\n onResize={handleWidgetResize}\n saveLayout={saveLayout}\n filteredWidgets={filteredWidgets}\n />\n )}\n </React.Fragment>\n )\n )}\n </Grid.Root>\n\n {isDraggingWidget && (\n <GapDropZoneManager\n filteredWidgets={filteredWidgets}\n columnWidths={columnWidths}\n draggedWidgetId={draggedWidgetId}\n moveWidget={moveWidget}\n />\n )}\n </Box>\n </Flex>\n </Layouts.Content>\n\n {/* Add the DragLayer to handle custom drag previews */}\n <DragLayer\n renderItem={({ type: _type, item }) => {\n if (!isWidgetDragItem(item)) {\n return null;\n }\n\n const widgetElement = getWidgetElement(item.id);\n const maxWidth = `${widgetElement?.clientWidth}px`;\n\n return (\n <DragPreviewWrapper $maxWidth={maxWidth}>\n <WidgetRoot\n uid={item.id as WidgetWithUID['uid']}\n title={item.title || { id: `${item.id}`, defaultMessage: item.id }}\n icon={item.icon}\n link={item.link}\n >\n <WidgetComponent component={item.component} columnWidth={4} />\n </WidgetRoot>\n </DragPreviewWrapper>\n );\n }}\n />\n </Main>\n </Layouts.Root>\n );\n};\n\n/* -------------------------------------------------------------------------------------------------\n * HomePage\n * -----------------------------------------------------------------------------------------------*/\n\nconst HomePage = () => {\n const Page = useEnterprise(\n HomePageCE,\n // eslint-disable-next-line import/no-cycle\n async () => (await import('../../../../ee/admin/src/pages/HomePage')).HomePageEE\n );\n\n // block rendering until the EE component is fully loaded\n if (!Page) {\n return null;\n }\n\n return <Page />;\n};\n\nexport { HomePage, HomePageCE };\n"],"names":["getWidgetPermissionsCacheKey","permissions","map","permission","JSON","stringify","action","subject","conditions","properties","sort","join","DragPreviewWrapper","styled","div","props","$maxWidth","theme","colors","primary500","borderRadius","WidgetComponent","component","columnWidth","loadedComponent","setLoadedComponent","React","useState","useEffect","loadComponent","resolvedComponent","Component","_jsx","Widget","Loading","HomePageCE","formatMessage","useIntl","user","useAuth","state","displayName","firstname","username","email","getAllWidgets","useStrapiApp","widgets","getAll","allWidgets","useMemo","checkUserHasPermissions","data","homepageLayout","isLoading","_isLoadingLayout","useGetHomepageLayoutQuery","useGetCountDocumentsQuery","useGetKeyStatisticsQuery","filteredWidgets","setFilteredWidgets","widgetPermissionStatus","setWidgetPermissionStatus","reduce","acc","widget","uid","length","isAddWidgetModalOpen","setIsAddWidgetModalOpen","findWidget","deleteWidget","addWidget","moveWidget","columnWidths","setColumnWidths","handleWidgetResize","saveLayout","isDraggingWidget","draggedWidgetId","handleDragStart","handleDragEnd","useWidgets","initialPermissionStatus","widgetsWithPermissions","filter","groupedPermissions","key","existingGroup","get","uids","push","set","Map","isMounted","checkWidgetsPermissions","permissionResults","Promise","all","Array","from","values","matchingPermissions","status","prev","next","forEach","allAvailableWidgets","renderableWidgets","widths","homepageWidths","applyHomepageLayout","createDefaultWidgetWidths","widgetLayout","index","rightWidgetId","widgetWidth","getWidgetWidth","rightWidgetWidth","isLastInRow","isLastWidgetInRow","canResize","canResizeBetweenWidgets","Layouts","Root","_jsxs","Main","Page","Title","id","defaultMessage","Header","title","name","subtitle","primaryAction","Button","variant","size","startIcon","Plus","onClick","fullWidth","FreeTrialWelcomeModal","FreeTrialEndedModal","AddWidgetModal","isOpen","onClose","onAddWidget","currentWidgets","availableWidgets","Content","Flex","direction","alignItems","gap","paddingBottom","GuidedTourHomepageOverview","Box","position","WIDGET_DATA_ATTRIBUTES","GRID_CONTAINER","Grid","Fragment","Item","col","xs","WidgetRoot","icon","link","onDragStart","onDragEnd","WidgetResizeHandle","leftWidgetId","leftWidgetWidth","onResize","GapDropZoneManager","DragLayer","renderItem","type","_type","item","isWidgetDragItem","widgetElement","getWidgetElement","maxWidth","clientWidth","HomePage","useEnterprise","HomePageEE"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/admin",
3
- "version": "5.40.0",
3
+ "version": "5.41.0",
4
4
  "description": "Strapi Admin",
5
5
  "homepage": "https://strapi.io",
6
6
  "bugs": {
@@ -91,10 +91,10 @@
91
91
  "@reduxjs/toolkit": "1.9.7",
92
92
  "@strapi/design-system": "2.2.0",
93
93
  "@strapi/icons": "2.2.0",
94
- "@strapi/permissions": "5.40.0",
95
- "@strapi/types": "5.40.0",
96
- "@strapi/typescript-utils": "5.40.0",
97
- "@strapi/utils": "5.40.0",
94
+ "@strapi/permissions": "5.41.0",
95
+ "@strapi/types": "5.41.0",
96
+ "@strapi/typescript-utils": "5.41.0",
97
+ "@strapi/utils": "5.41.0",
98
98
  "@testing-library/dom": "10.4.1",
99
99
  "@testing-library/react": "16.3.0",
100
100
  "@testing-library/user-event": "14.6.1",
@@ -112,7 +112,7 @@
112
112
  "fs-extra": "11.2.0",
113
113
  "highlight.js": "^10.4.1",
114
114
  "immer": "9.0.21",
115
- "inquirer": "8.2.5",
115
+ "inquirer": "9.3.8",
116
116
  "invariant": "^2.2.4",
117
117
  "is-localhost-ip": "2.0.0",
118
118
  "json-logic-js": "2.0.5",
@@ -138,7 +138,7 @@
138
138
  "react-redux": "8.1.3",
139
139
  "react-select": "5.8.0",
140
140
  "react-window": "1.8.10",
141
- "rimraf": "5.0.5",
141
+ "rimraf": "6.1.3",
142
142
  "sanitize-html": "2.13.0",
143
143
  "scheduler": "0.23.0",
144
144
  "semver": "7.5.4",
@@ -150,8 +150,8 @@
150
150
  "zod": "3.25.67"
151
151
  },
152
152
  "devDependencies": {
153
- "@strapi/admin-test-utils": "5.40.0",
154
- "@strapi/data-transfer": "5.40.0",
153
+ "@strapi/admin-test-utils": "5.41.0",
154
+ "@strapi/data-transfer": "5.41.0",
155
155
  "@types/codemirror5": "npm:@types/codemirror@^5.60.15",
156
156
  "@types/fs-extra": "11.0.4",
157
157
  "@types/invariant": "2.2.36",