Edit simple values in Field widget (#16749)
https://github.com/user-attachments/assets/116b8259-b366-47bf-8068-b5276b138e03
This commit is contained in:
committed by
GitHub
parent
bb73cbc380
commit
1324ad1ee3
+126
@@ -0,0 +1,126 @@
|
||||
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useIsRecordReadOnly } from '@/object-record/read-only/hooks/useIsRecordReadOnly';
|
||||
import { isRecordFieldReadOnly } from '@/object-record/read-only/utils/isRecordFieldReadOnly';
|
||||
import {
|
||||
FieldContext,
|
||||
type GenericFieldContextType,
|
||||
} from '@/object-record/record-field/ui/contexts/FieldContext';
|
||||
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/ui/states/contexts/RecordFieldComponentInstanceContext';
|
||||
import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { useRecordShowContainerActions } from '@/object-record/record-show/hooks/useRecordShowContainerActions';
|
||||
import { getRecordFieldInputInstanceId } from '@/object-record/utils/getRecordFieldInputId';
|
||||
import { useResolveFieldMetadataIdFromNameOrId } from '@/page-layout/hooks/useResolveFieldMetadataIdFromNameOrId';
|
||||
import { FieldWidgetEditAction } from '@/page-layout/widgets/field/components/FieldWidgetEditAction';
|
||||
import { FieldWidgetRelationEditAction } from '@/page-layout/widgets/field/components/FieldWidgetRelationEditAction';
|
||||
import { getFieldWidgetInstanceId } from '@/page-layout/widgets/field/utils/getFieldWidgetInstanceId';
|
||||
import { isFieldWidget } from '@/page-layout/widgets/field/utils/isFieldWidget';
|
||||
import { getObjectPermissionsFromMapByObjectMetadataId } from '@/settings/roles/role-permissions/objects-permissions/utils/getObjectPermissionsFromMapByObjectMetadataId';
|
||||
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
|
||||
import { useCurrentWidget } from '../hooks/useCurrentWidget';
|
||||
|
||||
export const WidgetActionFieldEdit = () => {
|
||||
const widget = useCurrentWidget();
|
||||
const targetRecord = useTargetRecord();
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: targetRecord.targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const fieldMetadataId = isFieldWidget(widget)
|
||||
? widget.configuration.fieldMetadataId
|
||||
: undefined;
|
||||
|
||||
const resolvedFieldMetadataId = useResolveFieldMetadataIdFromNameOrId(
|
||||
fieldMetadataId ?? '',
|
||||
);
|
||||
|
||||
const { fieldMetadataItem } = useFieldMetadataItemById(
|
||||
resolvedFieldMetadataId ?? '',
|
||||
);
|
||||
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const { useUpdateOneObjectRecordMutation } = useRecordShowContainerActions({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
objectRecordId: targetRecord.id,
|
||||
});
|
||||
|
||||
const isRecordReadOnly = useIsRecordReadOnly({
|
||||
recordId: targetRecord.id,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
});
|
||||
|
||||
assertIsDefinedOrThrow(fieldMetadataItem);
|
||||
|
||||
const fieldDefinition = formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: 0,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
});
|
||||
|
||||
const isRelationField =
|
||||
isFieldRelation(fieldDefinition) || isFieldMorphRelation(fieldDefinition);
|
||||
|
||||
if (isRelationField) {
|
||||
return (
|
||||
<FieldWidgetRelationEditAction
|
||||
fieldDefinition={fieldDefinition}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const instanceId = getFieldWidgetInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
isInRightDrawer,
|
||||
});
|
||||
|
||||
const recordFieldInputInstanceId = getRecordFieldInputInstanceId({
|
||||
recordId: targetRecord.id,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
prefix: instanceId,
|
||||
});
|
||||
|
||||
const fieldContextValue = {
|
||||
recordId: targetRecord.id,
|
||||
maxWidth: 200,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition,
|
||||
useUpdateRecord: useUpdateOneObjectRecordMutation,
|
||||
isDisplayModeFixHeight: false,
|
||||
isRecordFieldReadOnly: isRecordFieldReadOnly({
|
||||
isRecordReadOnly,
|
||||
objectPermissions: getObjectPermissionsFromMapByObjectMetadataId({
|
||||
objectPermissionsByObjectMetadataId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
}),
|
||||
fieldMetadataItem: {
|
||||
id: fieldMetadataItem.id,
|
||||
isUIReadOnly: fieldMetadataItem.isUIReadOnly ?? false,
|
||||
},
|
||||
}),
|
||||
anchorId: recordFieldInputInstanceId,
|
||||
} satisfies GenericFieldContextType;
|
||||
|
||||
return (
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: recordFieldInputInstanceId,
|
||||
}}
|
||||
>
|
||||
<FieldContext.Provider value={fieldContextValue}>
|
||||
<FieldWidgetEditAction />
|
||||
</FieldContext.Provider>
|
||||
</RecordFieldComponentInstanceContext.Provider>
|
||||
);
|
||||
};
|
||||
+3
-52
@@ -1,16 +1,8 @@
|
||||
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
|
||||
import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { useResolveFieldMetadataIdFromNameOrId } from '@/page-layout/hooks/useResolveFieldMetadataIdFromNameOrId';
|
||||
import { FieldWidgetRelationEditAction } from '@/page-layout/widgets/field/components/FieldWidgetRelationEditAction';
|
||||
import { isFieldWidget } from '@/page-layout/widgets/field/utils/isFieldWidget';
|
||||
import { type WidgetAction } from '@/page-layout/widgets/types/WidgetAction';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { assertIsDefinedOrThrow, CustomError } from 'twenty-shared/utils';
|
||||
import { CustomError } from 'twenty-shared/utils';
|
||||
import { WidgetType } from '~/generated/graphql';
|
||||
import { useCurrentWidget } from '../hooks/useCurrentWidget';
|
||||
import { WidgetActionFieldEdit } from './WidgetActionFieldEdit';
|
||||
|
||||
type WidgetActionRendererProps = {
|
||||
action: WidgetAction;
|
||||
@@ -18,50 +10,9 @@ type WidgetActionRendererProps = {
|
||||
|
||||
export const WidgetActionRenderer = ({ action }: WidgetActionRendererProps) => {
|
||||
const widget = useCurrentWidget();
|
||||
const targetRecord = useTargetRecord();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: targetRecord.targetObjectNameSingular,
|
||||
});
|
||||
|
||||
const fieldMetadataId = isFieldWidget(widget)
|
||||
? widget.configuration.fieldMetadataId
|
||||
: undefined;
|
||||
|
||||
const resolvedFieldMetadataId = useResolveFieldMetadataIdFromNameOrId(
|
||||
fieldMetadataId ?? '',
|
||||
);
|
||||
|
||||
const { fieldMetadataItem } = useFieldMetadataItemById(
|
||||
resolvedFieldMetadataId ?? '',
|
||||
);
|
||||
|
||||
if (action.id === 'edit' && widget.type === WidgetType.FIELD) {
|
||||
assertIsDefinedOrThrow(fieldMetadataItem);
|
||||
|
||||
const fieldDefinition = formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: 0,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
});
|
||||
|
||||
const isRelationField =
|
||||
isFieldRelation(fieldDefinition) || isFieldMorphRelation(fieldDefinition);
|
||||
|
||||
if (!isRelationField) {
|
||||
throw new Error(
|
||||
'Edit action is only available for relation fields for now',
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldWidgetRelationEditAction
|
||||
fieldDefinition={fieldDefinition}
|
||||
recordId={targetRecord.id}
|
||||
/>
|
||||
);
|
||||
return <WidgetActionFieldEdit />;
|
||||
}
|
||||
|
||||
throw new CustomError(
|
||||
|
||||
+6
-1
@@ -12,6 +12,7 @@ import { FieldWidgetCellEditModePortal } from '@/page-layout/widgets/field/compo
|
||||
import { FieldWidgetCellHoveredPortal } from '@/page-layout/widgets/field/components/FieldWidgetCellHoveredPortal';
|
||||
import { FieldWidgetInlineCell } from '@/page-layout/widgets/field/components/FieldWidgetInlineCell';
|
||||
import { fieldWidgetHoverComponentState } from '@/page-layout/widgets/field/states/fieldWidgetHoverComponentState';
|
||||
import { getFieldWidgetInstanceId } from '@/page-layout/widgets/field/utils/getFieldWidgetInstanceId';
|
||||
import { getObjectPermissionsFromMapByObjectMetadataId } from '@/settings/roles/role-permissions/objects-permissions/utils/getObjectPermissionsFromMapByObjectMetadataId';
|
||||
import { RightDrawerProvider } from '@/ui/layout/right-drawer/contexts/RightDrawerContext';
|
||||
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
|
||||
@@ -41,7 +42,11 @@ export const FieldWidgetDisplay = ({
|
||||
fieldWidgetHoverComponentState,
|
||||
);
|
||||
|
||||
const instanceId = `field-widget-${recordId}-${fieldMetadataItem.name}-${isInRightDrawer ? 'right-drawer' : ''}`;
|
||||
const instanceId = getFieldWidgetInstanceId({
|
||||
recordId,
|
||||
fieldName: fieldMetadataItem.name,
|
||||
isInRightDrawer,
|
||||
});
|
||||
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { FieldContext } from '@/object-record/record-field/ui/contexts/FieldContext';
|
||||
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
|
||||
import { useOpenFieldWidgetFieldInputEditMode } from '@/page-layout/widgets/field/hooks/useOpenFieldWidgetFieldInputEditMode';
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconPencil } from 'twenty-ui/display';
|
||||
import { LightIconButton } from 'twenty-ui/input';
|
||||
|
||||
const StyledEditButton = styled(LightIconButton)`
|
||||
${({ theme }) => css`
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity ${theme.animation.duration.instant}s ease;
|
||||
`}
|
||||
|
||||
.widget:hover & {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FieldWidgetEditAction = () => {
|
||||
const { recordId, fieldDefinition } = useContext(FieldContext);
|
||||
const { openInlineCell } = useInlineCell();
|
||||
const { openFieldInput } = useOpenFieldWidgetFieldInputEditMode();
|
||||
|
||||
const handleClick = () => {
|
||||
openInlineCell();
|
||||
openFieldInput({
|
||||
fieldDefinition,
|
||||
recordId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledEditButton
|
||||
Icon={IconPencil}
|
||||
accent="secondary"
|
||||
onClick={handleClick}
|
||||
/>
|
||||
);
|
||||
};
|
||||
-1
@@ -101,7 +101,6 @@ export const FieldWidgetRelationEditAction = ({
|
||||
isDropdownOpen={isRelationSelectionDropdownOpen}
|
||||
Icon={IconPencil}
|
||||
accent="secondary"
|
||||
className="display-on-widget-hover"
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
export const getFieldWidgetInstanceId = ({
|
||||
recordId,
|
||||
fieldName,
|
||||
isInRightDrawer,
|
||||
}: {
|
||||
recordId: string;
|
||||
fieldName: string;
|
||||
isInRightDrawer: boolean;
|
||||
}): string => {
|
||||
return `field-widget-${recordId}-${fieldName}${isInRightDrawer ? '-right-drawer' : ''}`;
|
||||
};
|
||||
@@ -1,12 +1,13 @@
|
||||
import { useFieldMetadataItemById } from '@/object-metadata/hooks/useFieldMetadataItemById';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
|
||||
import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useIsRecordReadOnly } from '@/object-record/read-only/hooks/useIsRecordReadOnly';
|
||||
import { isRecordFieldReadOnly } from '@/object-record/read-only/utils/isRecordFieldReadOnly';
|
||||
import { useResolveFieldMetadataIdFromNameOrId } from '@/page-layout/hooks/useResolveFieldMetadataIdFromNameOrId';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { isFieldWidget } from '@/page-layout/widgets/field/utils/isFieldWidget';
|
||||
import { type WidgetAction } from '@/page-layout/widgets/types/WidgetAction';
|
||||
import { getObjectPermissionsFromMapByObjectMetadataId } from '@/settings/roles/role-permissions/objects-permissions/utils/getObjectPermissionsFromMapByObjectMetadataId';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -35,6 +36,13 @@ export const useWidgetActions = ({
|
||||
resolvedFieldMetadataId ?? '',
|
||||
);
|
||||
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const isRecordReadOnly = useIsRecordReadOnly({
|
||||
recordId: targetRecord.id,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
});
|
||||
|
||||
const actions: WidgetAction[] = [];
|
||||
|
||||
if (
|
||||
@@ -45,18 +53,19 @@ export const useWidgetActions = ({
|
||||
return actions;
|
||||
}
|
||||
|
||||
const fieldDefinition = formatFieldMetadataItemAsColumnDefinition({
|
||||
field: fieldMetadataItem,
|
||||
position: 0,
|
||||
objectMetadataItem,
|
||||
showLabel: true,
|
||||
labelWidth: 90,
|
||||
const isFieldReadOnly = isRecordFieldReadOnly({
|
||||
isRecordReadOnly,
|
||||
objectPermissions: getObjectPermissionsFromMapByObjectMetadataId({
|
||||
objectPermissionsByObjectMetadataId,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
}),
|
||||
fieldMetadataItem: {
|
||||
id: fieldMetadataItem.id,
|
||||
isUIReadOnly: fieldMetadataItem.isUIReadOnly ?? false,
|
||||
},
|
||||
});
|
||||
|
||||
const isRelationField =
|
||||
isFieldRelation(fieldDefinition) || isFieldMorphRelation(fieldDefinition);
|
||||
|
||||
if (isRelationField) {
|
||||
if (!isFieldReadOnly) {
|
||||
actions.push({
|
||||
id: 'edit',
|
||||
position: 0,
|
||||
|
||||
Reference in New Issue
Block a user