Allow users to create Fields and Field widget (#18801)
- Allow users to create a Fields widget or a Field widget; **this PR is focused on Fields widgets as Field widget can't be configured yet** - Automatically create a filled view when the user creates a draft Fields widget in edit mode https://github.com/user-attachments/assets/b2dbba52-c614-44cd-bf6c-095ce9d4ec26 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
GitHub
parent
dc00701448
commit
e9aa6f47e5
@@ -7,7 +7,10 @@ import { useCurrentPageLayoutOrThrow } from '@/page-layout/hooks/useCurrentPageL
|
||||
import { useIsPageLayoutInEditMode } from '@/page-layout/hooks/useIsPageLayoutInEditMode';
|
||||
import { usePageLayoutTabWithVisibleWidgetsOrThrow } from '@/page-layout/hooks/usePageLayoutTabWithVisibleWidgetsOrThrow';
|
||||
import { useReorderPageLayoutWidgets } from '@/page-layout/hooks/useReorderPageLayoutWidgets';
|
||||
import { RecordPageAddWidgetSection } from '@/page-layout/widgets/components/RecordPageAddWidgetSection';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import {
|
||||
FeatureFlagKey,
|
||||
PageLayoutTabLayoutMode,
|
||||
PageLayoutType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
@@ -28,6 +31,10 @@ export const PageLayoutContent = () => {
|
||||
const isRecordPageLayout =
|
||||
currentPageLayout.type === PageLayoutType.RECORD_PAGE;
|
||||
|
||||
const isRecordPageGlobalEditionEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED,
|
||||
);
|
||||
|
||||
const isCanvasLayout = layoutMode === PageLayoutTabLayoutMode.CANVAS;
|
||||
const isVerticalList = layoutMode === PageLayoutTabLayoutMode.VERTICAL_LIST;
|
||||
|
||||
@@ -36,12 +43,19 @@ export const PageLayoutContent = () => {
|
||||
}
|
||||
|
||||
if (isVerticalList) {
|
||||
if (!isRecordPageLayout && isPageLayoutInEditMode) {
|
||||
if (
|
||||
isPageLayoutInEditMode &&
|
||||
isRecordPageLayout &&
|
||||
isRecordPageGlobalEditionEnabled
|
||||
) {
|
||||
return (
|
||||
<PageLayoutVerticalListEditor
|
||||
widgets={activeTab.widgets}
|
||||
onReorder={reorderWidgets}
|
||||
isReorderEnabled={true}
|
||||
trailingElement={
|
||||
isRecordPageLayout ? <RecordPageAddWidgetSection /> : undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+6
-3
@@ -6,16 +6,16 @@ import { WidgetRenderer } from '@/page-layout/widgets/components/WidgetRenderer'
|
||||
import { useIsInPinnedTab } from '@/page-layout/widgets/hooks/useIsInPinnedTab';
|
||||
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { styled } from '@linaria/react';
|
||||
import {
|
||||
DragDropContext,
|
||||
Draggable,
|
||||
Droppable,
|
||||
type DropResult,
|
||||
} from '@hello-pangea/dnd';
|
||||
import { useId } from 'react';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type ReactNode, useId } from 'react';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledVerticalListContainer = styled.div<{
|
||||
variant: PageLayoutVerticalListViewerVariant;
|
||||
@@ -47,12 +47,14 @@ type PageLayoutVerticalListEditorProps = {
|
||||
widgets: PageLayoutWidget[];
|
||||
onReorder: (result: DropResult) => void;
|
||||
isReorderEnabled?: boolean;
|
||||
trailingElement?: ReactNode;
|
||||
};
|
||||
|
||||
export const PageLayoutVerticalListEditor = ({
|
||||
widgets,
|
||||
onReorder,
|
||||
isReorderEnabled = true,
|
||||
trailingElement,
|
||||
}: PageLayoutVerticalListEditorProps) => {
|
||||
const droppableId = `page-layout-vertical-list-${useId()}`;
|
||||
|
||||
@@ -112,6 +114,7 @@ export const PageLayoutVerticalListEditor = ({
|
||||
</Draggable>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
{trailingElement}
|
||||
</StyledVerticalListContainer>
|
||||
)}
|
||||
</Droppable>
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useFieldListFieldMetadataItems } from '@/object-record/record-field-list/hooks/useFieldListFieldMetadataItems';
|
||||
import { usePageLayoutContentContext } from '@/page-layout/contexts/PageLayoutContentContext';
|
||||
import { useCurrentPageLayoutOrThrow } from '@/page-layout/hooks/useCurrentPageLayoutOrThrow';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { addWidgetToTab } from '@/page-layout/utils/addWidgetToTab';
|
||||
import { createDefaultFieldWidget } from '@/page-layout/utils/createDefaultFieldWidget';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { WidgetConfigurationType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useCreateRecordPageFieldWidget = () => {
|
||||
const { tabId } = usePageLayoutContentContext();
|
||||
|
||||
const { targetObjectNameSingular } = useTargetRecord();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const { boxedRelationFieldMetadataItems } = useFieldListFieldMetadataItems({
|
||||
objectNameSingular: targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const { currentPageLayout } = useCurrentPageLayoutOrThrow();
|
||||
|
||||
const pageLayoutDraftState = useAtomComponentStateCallbackState(
|
||||
pageLayoutDraftComponentState,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const createRecordPageFieldWidget = useCallback(() => {
|
||||
const activeTab = currentPageLayout.tabs.find((tab) => tab.id === tabId);
|
||||
const existingWidgets = activeTab?.widgets ?? [];
|
||||
|
||||
const usedFieldMetadataIds = new Set(
|
||||
existingWidgets
|
||||
.filter(
|
||||
(widget) =>
|
||||
widget.configuration.configurationType ===
|
||||
WidgetConfigurationType.FIELD,
|
||||
)
|
||||
.map((widget) => {
|
||||
const configuration = widget.configuration as {
|
||||
fieldMetadataId: string;
|
||||
};
|
||||
return configuration.fieldMetadataId;
|
||||
}),
|
||||
);
|
||||
|
||||
const availableRelationField = boxedRelationFieldMetadataItems.find(
|
||||
(field) => !usedFieldMetadataIds.has(field.id),
|
||||
);
|
||||
|
||||
const fieldMetadataId = availableRelationField?.id ?? '';
|
||||
|
||||
const positionIndex = existingWidgets.length;
|
||||
const widgetId = uuidv4();
|
||||
|
||||
const newWidget = createDefaultFieldWidget({
|
||||
id: widgetId,
|
||||
pageLayoutTabId: tabId,
|
||||
fieldMetadataId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
positionIndex,
|
||||
});
|
||||
|
||||
store.set(pageLayoutDraftState, (prev) => ({
|
||||
...prev,
|
||||
tabs: addWidgetToTab(prev.tabs, tabId, newWidget),
|
||||
}));
|
||||
}, [
|
||||
boxedRelationFieldMetadataItems,
|
||||
currentPageLayout.tabs,
|
||||
objectMetadataItem.id,
|
||||
pageLayoutDraftState,
|
||||
store,
|
||||
tabId,
|
||||
]);
|
||||
|
||||
return { createRecordPageFieldWidget };
|
||||
};
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { usePageLayoutContentContext } from '@/page-layout/contexts/PageLayoutContentContext';
|
||||
import { useCurrentPageLayoutOrThrow } from '@/page-layout/hooks/useCurrentPageLayoutOrThrow';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { addWidgetToTab } from '@/page-layout/utils/addWidgetToTab';
|
||||
import { createDefaultFieldsWidget } from '@/page-layout/utils/createDefaultFieldsWidget';
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { usePerformViewAPIPersist } from '@/views/hooks/internal/usePerformViewAPIPersist';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { ViewType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useCreateRecordPageFieldsWidget = () => {
|
||||
const { tabId } = usePageLayoutContentContext();
|
||||
|
||||
const { targetObjectNameSingular } = useTargetRecord();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const { currentPageLayout } = useCurrentPageLayoutOrThrow();
|
||||
|
||||
const { performViewAPICreate } = usePerformViewAPIPersist();
|
||||
|
||||
const pageLayoutDraftState = useAtomComponentStateCallbackState(
|
||||
pageLayoutDraftComponentState,
|
||||
);
|
||||
|
||||
const pageLayoutEditingWidgetIdState = useAtomComponentStateCallbackState(
|
||||
pageLayoutEditingWidgetIdComponentState,
|
||||
);
|
||||
|
||||
const { navigatePageLayoutSidePanel } = useNavigatePageLayoutSidePanel();
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const createRecordPageFieldsWidget = useCallback(async () => {
|
||||
const viewId = uuidv4();
|
||||
|
||||
const result = await performViewAPICreate(
|
||||
{
|
||||
input: {
|
||||
id: viewId,
|
||||
name: `${objectMetadataItem.labelSingular} Fields`,
|
||||
icon: 'IconList',
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
type: ViewType.FIELDS_WIDGET,
|
||||
},
|
||||
},
|
||||
objectMetadataItem.id,
|
||||
);
|
||||
|
||||
if (result.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
const activeTab = currentPageLayout.tabs.find((tab) => tab.id === tabId);
|
||||
const positionIndex = activeTab?.widgets.length ?? 0;
|
||||
|
||||
const widgetId = uuidv4();
|
||||
|
||||
const newWidget = createDefaultFieldsWidget({
|
||||
id: widgetId,
|
||||
pageLayoutTabId: tabId,
|
||||
viewId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
positionIndex,
|
||||
});
|
||||
|
||||
store.set(pageLayoutDraftState, (prev) => ({
|
||||
...prev,
|
||||
tabs: addWidgetToTab(prev.tabs, tabId, newWidget),
|
||||
}));
|
||||
|
||||
store.set(pageLayoutEditingWidgetIdState, widgetId);
|
||||
|
||||
navigatePageLayoutSidePanel({
|
||||
sidePanelPage: SidePanelPages.PageLayoutFieldsSettings,
|
||||
focusTitleInput: true,
|
||||
resetNavigationStack: true,
|
||||
});
|
||||
}, [
|
||||
currentPageLayout.tabs,
|
||||
navigatePageLayoutSidePanel,
|
||||
objectMetadataItem.id,
|
||||
objectMetadataItem.labelSingular,
|
||||
pageLayoutDraftState,
|
||||
pageLayoutEditingWidgetIdState,
|
||||
performViewAPICreate,
|
||||
store,
|
||||
tabId,
|
||||
]);
|
||||
|
||||
return { createRecordPageFieldsWidget };
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useNavigatePageLayoutSidePanel } from '@/side-panel/pages/page-layout/hooks/useNavigatePageLayoutSidePanel';
|
||||
import { useCallback } from 'react';
|
||||
import { SidePanelPages } from 'twenty-shared/types';
|
||||
|
||||
export const useNavigateToMoreWidgets = () => {
|
||||
const { navigatePageLayoutSidePanel } = useNavigatePageLayoutSidePanel();
|
||||
|
||||
const navigateToMoreWidgets = useCallback(() => {
|
||||
navigatePageLayoutSidePanel({
|
||||
sidePanelPage: SidePanelPages.PageLayoutWidgetTypeSelect,
|
||||
});
|
||||
}, [navigatePageLayoutSidePanel]);
|
||||
|
||||
return { navigateToMoreWidgets };
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import {
|
||||
PageLayoutTabLayoutMode,
|
||||
WidgetConfigurationType,
|
||||
WidgetType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const createDefaultFieldWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
fieldMetadataId,
|
||||
objectMetadataId,
|
||||
positionIndex,
|
||||
}: {
|
||||
id: string;
|
||||
pageLayoutTabId: string;
|
||||
fieldMetadataId: string;
|
||||
objectMetadataId: string;
|
||||
positionIndex: number;
|
||||
}): PageLayoutWidget => {
|
||||
return {
|
||||
__typename: 'PageLayoutWidget',
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title: '',
|
||||
type: WidgetType.FIELD,
|
||||
configuration: {
|
||||
__typename: 'FieldConfiguration',
|
||||
configurationType: WidgetConfigurationType.FIELD,
|
||||
fieldMetadataId,
|
||||
layout: 'CARD',
|
||||
},
|
||||
gridPosition: {
|
||||
__typename: 'GridPosition',
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 12,
|
||||
},
|
||||
position: {
|
||||
__typename: 'PageLayoutWidgetVerticalListPosition',
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
index: positionIndex,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import {
|
||||
PageLayoutTabLayoutMode,
|
||||
WidgetConfigurationType,
|
||||
WidgetType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const createDefaultFieldsWidget = ({
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
viewId,
|
||||
objectMetadataId,
|
||||
positionIndex,
|
||||
}: {
|
||||
id: string;
|
||||
pageLayoutTabId: string;
|
||||
viewId: string;
|
||||
objectMetadataId: string;
|
||||
positionIndex: number;
|
||||
}): PageLayoutWidget => {
|
||||
return {
|
||||
__typename: 'PageLayoutWidget',
|
||||
id,
|
||||
pageLayoutTabId,
|
||||
title: 'Fields',
|
||||
type: WidgetType.FIELDS,
|
||||
configuration: {
|
||||
__typename: 'FieldsConfiguration',
|
||||
configurationType: WidgetConfigurationType.FIELDS,
|
||||
viewId,
|
||||
},
|
||||
gridPosition: {
|
||||
__typename: 'GridPosition',
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 12,
|
||||
},
|
||||
position: {
|
||||
__typename: 'PageLayoutWidgetVerticalListPosition',
|
||||
layoutMode: PageLayoutTabLayoutMode.VERTICAL_LIST,
|
||||
index: positionIndex,
|
||||
},
|
||||
objectMetadataId: objectMetadataId ?? null,
|
||||
isOverridden: false,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
};
|
||||
};
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import { useCreateRecordPageFieldWidget } from '@/page-layout/hooks/useCreateRecordPageFieldWidget';
|
||||
import { useCreateRecordPageFieldsWidget } from '@/page-layout/hooks/useCreateRecordPageFieldsWidget';
|
||||
import { useNavigateToMoreWidgets } from '@/page-layout/hooks/useNavigateToMoreWidgets';
|
||||
import { styled } from '@linaria/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useContext } from 'react';
|
||||
import {
|
||||
IconListDetails,
|
||||
IconListSearch,
|
||||
IconPlus,
|
||||
IconSquarePlus,
|
||||
} from 'twenty-ui/display';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
border: 1px solid transparent;
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const StyledHeader = styled.div`
|
||||
align-items: center;
|
||||
color: ${themeCssVariables.font.color.primary};
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
font-size: ${themeCssVariables.font.size.md};
|
||||
font-weight: ${themeCssVariables.font.weight.medium};
|
||||
gap: ${themeCssVariables.spacing[1]};
|
||||
height: ${themeCssVariables.spacing[6]};
|
||||
padding-inline: ${themeCssVariables.spacing[1]};
|
||||
`;
|
||||
|
||||
const StyledMenuItemList = styled.div`
|
||||
border: 1px solid ${themeCssVariables.border.color.medium};
|
||||
border-radius: ${themeCssVariables.border.radius.md};
|
||||
margin-top: ${themeCssVariables.spacing[2]};
|
||||
overflow: hidden;
|
||||
padding: ${themeCssVariables.spacing[2]};
|
||||
`;
|
||||
|
||||
export const RecordPageAddWidgetSection = () => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
|
||||
const { createRecordPageFieldsWidget } = useCreateRecordPageFieldsWidget();
|
||||
|
||||
const { createRecordPageFieldWidget } = useCreateRecordPageFieldWidget();
|
||||
|
||||
const { navigateToMoreWidgets } = useNavigateToMoreWidgets();
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledHeader>
|
||||
<IconSquarePlus
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.md}
|
||||
color={theme.font.color.extraLight}
|
||||
/>
|
||||
{t`Add widget`}
|
||||
</StyledHeader>
|
||||
<StyledMenuItemList>
|
||||
<MenuItem
|
||||
LeftIcon={IconListDetails}
|
||||
withIconContainer
|
||||
text={t`Fields group`}
|
||||
contextualText={t`Group multiple fields from this record`}
|
||||
onClick={createRecordPageFieldsWidget}
|
||||
/>
|
||||
<MenuItem
|
||||
LeftIcon={IconListSearch}
|
||||
withIconContainer
|
||||
text={t`Field`}
|
||||
contextualText={t`Single field with smart formats`}
|
||||
onClick={createRecordPageFieldWidget}
|
||||
/>
|
||||
<MenuItem
|
||||
LeftIcon={IconPlus}
|
||||
withIconContainer
|
||||
text={t`More widgets`}
|
||||
hasSubMenu
|
||||
onClick={navigateToMoreWidgets}
|
||||
/>
|
||||
</StyledMenuItemList>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
+18
-4
@@ -24,12 +24,14 @@ import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingC
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useSetAtomComponentFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentFamilyState';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { styled } from '@linaria/react';
|
||||
import { type MouseEvent, useContext } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { IconLock } from 'twenty-ui/display';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import {
|
||||
FeatureFlagKey,
|
||||
PageLayoutTabLayoutMode,
|
||||
PageLayoutType,
|
||||
WidgetType,
|
||||
@@ -83,17 +85,27 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
|
||||
const { currentPageLayout } = useCurrentPageLayoutOrThrow();
|
||||
|
||||
const isRecordPageGlobalEditionEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_GLOBAL_EDITION_ENABLED,
|
||||
);
|
||||
|
||||
const isRecordPageLayout =
|
||||
currentPageLayout.type === PageLayoutType.RECORD_PAGE;
|
||||
|
||||
const isLastWidget = useIsCurrentWidgetLastOfTab(widget.id);
|
||||
|
||||
const isReorderEnabled =
|
||||
currentPageLayout.type !== PageLayoutType.RECORD_PAGE;
|
||||
!isRecordPageLayout ||
|
||||
(isRecordPageLayout && isRecordPageGlobalEditionEnabled);
|
||||
|
||||
const isDeletingWidgetEnabled =
|
||||
currentPageLayout.type !== PageLayoutType.RECORD_PAGE;
|
||||
!isRecordPageLayout ||
|
||||
(isRecordPageLayout && isRecordPageGlobalEditionEnabled);
|
||||
|
||||
const isWidgetEditable =
|
||||
isPageLayoutInEditMode &&
|
||||
(currentPageLayout.type !== PageLayoutType.RECORD_PAGE ||
|
||||
(!isRecordPageLayout ||
|
||||
(isRecordPageLayout && isRecordPageGlobalEditionEnabled) ||
|
||||
widget.type === WidgetType.FIELDS);
|
||||
|
||||
// TODO: when we have more widgets without headers, we should use a more generic approach to hide the header
|
||||
@@ -141,7 +153,9 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
|
||||
// TODO: remove once all record page layouts widgets use the editable contain in edit mode
|
||||
const shouldWrapWithEditingWrapper =
|
||||
isWidgetEditable && variant === 'side-column';
|
||||
isWidgetEditable &&
|
||||
variant === 'side-column' &&
|
||||
!isRecordPageGlobalEditionEnabled;
|
||||
|
||||
const widgetCard = (
|
||||
<WidgetCard
|
||||
|
||||
Reference in New Issue
Block a user