Page layout refactoring (#14535)

In this PR:
- Refactored the page layout renderer
- Converted all the states to component states
- Removed the page layout edition in settings

TODOs in next PRs:
- Fix bug with the drag selector not taking the scroll into account to
display the dragged area
- Readd the tab edition in edit mode
This commit is contained in:
Raphaël Bosi
2025-09-16 17:42:51 +02:00
committed by GitHub
parent e69131790c
commit 3b868c3d2a
90 changed files with 2070 additions and 1928 deletions
@@ -28,7 +28,7 @@ const StyledTitle = styled.span`
`;
type WidgetHeaderProps = {
displayDragHandle: boolean;
isInEditMode: boolean;
isEmpty?: boolean;
title: string;
onRemove?: () => void;
@@ -36,15 +36,15 @@ type WidgetHeaderProps = {
};
export const WidgetHeader = ({
displayDragHandle = false,
isEmpty = false,
isInEditMode = false,
title,
onEdit,
onRemove,
}: WidgetHeaderProps) => {
return (
<StyledHeader>
{displayDragHandle && (
{isInEditMode && (
<StyledDragHandleButton
Icon={IconGripVertical}
className="drag-handle"
@@ -54,7 +54,7 @@ export const WidgetHeader = ({
/>
)}
<StyledTitle>{isEmpty ? 'Add Widget' : title}</StyledTitle>
{!isEmpty && onEdit && (
{!isEmpty && isInEditMode && onEdit && (
<IconButton
onClick={onEdit}
Icon={IconPencil}
@@ -62,7 +62,7 @@ export const WidgetHeader = ({
size="small"
/>
)}
{!isEmpty && onRemove && (
{!isEmpty && isInEditMode && onRemove && (
<IconButton
onClick={onRemove}
Icon={IconX}
@@ -16,7 +16,7 @@ type WidgetPlaceholderProps = {
export const WidgetPlaceholder = ({ onClick }: WidgetPlaceholderProps) => {
return (
<WidgetContainer onClick={onClick}>
<WidgetHeader displayDragHandle={true} title="Add Widget" isEmpty />
<WidgetHeader isInEditMode={true} title="Add Widget" isEmpty />
<AnimatedPlaceholderEmptyContainer
// eslint-disable-next-line react/jsx-props-no-spreading
{...EMPTY_PLACEHOLDER_TRANSITION_PROPS}
@@ -1,14 +1,15 @@
import { useDeletePageLayoutWidget } from '@/page-layout/hooks/useDeletePageLayoutWidget';
import { useEditPageLayoutWidget } from '@/page-layout/hooks/useEditPageLayoutWidget';
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
import { WidgetContainer } from '@/page-layout/widgets/components/WidgetContainer';
import { WidgetContentRenderer } from '@/page-layout/widgets/components/WidgetContentRenderer';
import { WidgetHeader } from '@/page-layout/widgets/components/WidgetHeader';
import { type Widget as WidgetType } from '@/page-layout/widgets/types/Widget';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import styled from '@emotion/styled';
type WidgetRendererProps = {
widget: WidgetType;
displayDragHandle?: boolean;
onEdit?: () => void;
onRemove?: () => void;
};
const StyledContent = styled.div`
@@ -19,19 +20,24 @@ const StyledContent = styled.div`
justify-content: center;
`;
export const WidgetRenderer = ({
widget,
displayDragHandle = false,
onEdit,
onRemove,
}: WidgetRendererProps) => {
export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
const { deletePageLayoutWidget } = useDeletePageLayoutWidget();
const { handleEditWidget } = useEditPageLayoutWidget();
const isPageLayoutInEditMode = useRecoilComponentValue(
isPageLayoutInEditModeComponentState,
widget.id,
);
return (
<WidgetContainer>
<WidgetHeader
displayDragHandle={displayDragHandle}
isInEditMode={isPageLayoutInEditMode}
title={widget.title}
onEdit={onEdit}
onRemove={onRemove}
onEdit={() =>
handleEditWidget({ widgetId: widget.id, widgetType: widget.type })
}
onRemove={() => deletePageLayoutWidget(widget.id)}
/>
<StyledContent>
<WidgetContentRenderer widget={widget} />
@@ -1,3 +1,4 @@
import { PageLayoutTestWrapper } from '@/page-layout/hooks/__tests__/PageLayoutTestWrapper';
import { GraphType } from '@/page-layout/mocks/mockWidgets';
import { WidgetRenderer } from '@/page-layout/widgets/components/WidgetRenderer';
import { type Meta, type StoryObj } from '@storybook/react';
@@ -7,7 +8,12 @@ import { WidgetType } from '~/generated/graphql';
const meta: Meta<typeof WidgetRenderer> = {
title: 'Modules/PageLayout/Widgets/WidgetRenderer',
component: WidgetRenderer,
decorators: [ComponentDecorator],
decorators: [
(Story, context) => (
<PageLayoutTestWrapper>{Story(context)}</PageLayoutTestWrapper>
),
ComponentDecorator,
],
parameters: {
layout: 'centered',
},
@@ -16,16 +22,6 @@ const meta: Meta<typeof WidgetRenderer> = {
control: 'object',
description: 'Widget',
},
displayDragHandle: {
control: 'boolean',
description: 'Display drag handle',
},
onRemove: {
action: 'onRemove',
},
onEdit: {
action: 'onEdit',
},
},
};
@@ -55,16 +51,10 @@ export const WithNumberChart: Story = {
trendPercentage: 12.5,
},
},
displayDragHandle: true,
},
render: (args) => (
<div style={{ width: '300px', height: '100px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -97,12 +87,7 @@ export const WithGaugeChart: Story = {
},
render: (args) => (
<div style={{ width: '300px', height: '400px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -163,12 +148,7 @@ export const WithPieChart: Story = {
},
render: (args) => (
<div style={{ width: '300px', height: '500px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -206,12 +186,7 @@ export const SmallWidget: Story = {
},
render: (args) => (
<div style={{ width: '300px', height: '100px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -251,12 +226,7 @@ export const MediumWidget: Story = {
},
render: (args) => (
<div style={{ width: '400px', height: '250px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -298,12 +268,7 @@ export const LargeWidget: Story = {
},
render: (args) => (
<div style={{ width: '600px', height: '400px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -341,12 +306,7 @@ export const WideWidget: Story = {
},
render: (args) => (
<div style={{ width: '800px', height: '200px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};
@@ -386,12 +346,7 @@ export const TallWidget: Story = {
},
render: (args) => (
<div style={{ width: '300px', height: '500px' }}>
<WidgetRenderer
widget={args.widget}
displayDragHandle={args.displayDragHandle}
onRemove={args.onRemove}
onEdit={args.onEdit}
/>
<WidgetRenderer widget={args.widget} />
</div>
),
};