FieldDisplay & FieldInput (#1708)

* Removed view field duplicate types

* wip

* wip 2

* wip 3

* Unified state for fields

* Renaming

* Wip

* Post merge

* Post post merge

* wip

* Delete unused file

* Boolean and Probability

* Finished InlineCell

* Renamed EditableCell to TableCell

* Finished double texts

* Finished MoneyField

* Fixed bug inline cell click outside

* Fixed hotkey scope

* Final fixes

* Phone

* Fix url and number input validation

* Fix

* Fix position

* wip refactor activity editor

* Fixed activity editor

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-09-27 18:18:02 +02:00
committed by GitHub
parent d9feabbc63
commit cbadcba188
290 changed files with 3152 additions and 4481 deletions

View File

@ -58,6 +58,7 @@ export const ActivityAssigneePicker = ({
lastName: user.lastName,
avatarType: 'rounded',
avatarUrl: user.avatarUrl ?? '',
originalEntity: user,
}),
selectedIds: activity?.accountOwner?.id ? [activity?.accountOwner?.id] : [],
});

View File

@ -8,9 +8,7 @@ import { ActivityComments } from '@/activities/components/ActivityComments';
import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown';
import { GET_ACTIVITIES } from '@/activities/graphql/queries/getActivities';
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
import { EditableFieldHotkeyScope } from '@/ui/editable-field/types/EditableFieldHotkeyScope';
import { DateEditableField } from '@/ui/editable-field/variants/components/DateEditableField';
import { IconCalendar } from '@/ui/icon/index';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import {
Activity,
@ -22,6 +20,7 @@ import {
import { debounce } from '~/utils/debounce';
import { ActivityAssigneeEditableField } from '../editable-fields/components/ActivityAssigneeEditableField';
import { ActivityEditorDateField } from '../editable-fields/components/ActivityEditorDateField';
import { ActivityRelationEditableField } from '../editable-fields/components/ActivityRelationEditableField';
import { ACTIVITY_UPDATE_FRAGMENT } from '../graphql/fragments/activityUpdateFragment';
import { CommentForDrawer } from '../types/CommentForDrawer';
@ -185,26 +184,12 @@ export const ActivityEditor = ({
<PropertyBox>
{activity.type === ActivityType.Task && (
<>
<DateEditableField
value={activity.dueAt}
Icon={IconCalendar}
label="Due date"
onSubmit={(newDate) => {
updateActivityMutation({
variables: {
where: {
id: activity.id,
},
data: {
dueAt: newDate,
},
},
refetchQueries: [getOperationName(GET_ACTIVITIES) ?? ''],
});
}}
hotkeyScope={EditableFieldHotkeyScope.EditableField}
/>
<ActivityAssigneeEditableField activity={activity} />
<RecoilScope>
<ActivityEditorDateField activityId={activity.id} />
</RecoilScope>
<RecoilScope>
<ActivityAssigneeEditableField activity={activity} />
</RecoilScope>
</>
)}
<ActivityRelationEditableField activity={activity} />

View File

@ -1,12 +1,11 @@
import { EditableField } from '@/ui/editable-field/components/EditableField';
import { FieldRecoilScopeContext } from '@/ui/editable-field/states/recoil-scope-contexts/FieldRecoilScopeContext';
import { InlineCell } from '@/ui/editable-field/components/InlineCell';
import { EditableFieldHotkeyScope } from '@/ui/editable-field/types/EditableFieldHotkeyScope';
import { FieldContext } from '@/ui/field/contexts/FieldContext';
import { FieldDefinition } from '@/ui/field/types/FieldDefinition';
import { FieldRelationMetadata } from '@/ui/field/types/FieldMetadata';
import { IconUserCircle } from '@/ui/icon';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { UserChip } from '@/users/components/UserChip';
import { Company, User } from '~/generated/graphql';
import { ActivityAssigneeEditableFieldEditMode } from './ActivityAssigneeEditableFieldEditMode';
import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import { Company, User, useUpdateActivityMutation } from '~/generated/graphql';
type OwnProps = {
activity: Pick<Company, 'id' | 'accountOwnerId'> & {
@ -16,32 +15,25 @@ type OwnProps = {
export const ActivityAssigneeEditableField = ({ activity }: OwnProps) => {
return (
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope>
<EditableField
customEditHotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
label="Assignee"
IconLabel={IconUserCircle}
editModeContent={
<ActivityAssigneeEditableFieldEditMode activity={activity} />
}
displayModeContent={
activity.assignee?.displayName ? (
<UserChip
id={activity.assignee.id}
name={activity.assignee?.displayName ?? ''}
pictureUrl={activity.assignee?.avatarUrl ?? ''}
/>
) : (
<></>
)
}
isDisplayModeContentEmpty={!activity.assignee}
isDisplayModeFixHeight={true}
/>
</RecoilScope>
</RecoilScope>
<FieldContext.Provider
value={{
entityId: activity.id,
recoilScopeId: 'assignee',
fieldDefinition: {
key: 'assignee',
name: 'Assignee',
Icon: IconUserCircle,
type: 'relation',
metadata: {
fieldName: 'assignee',
relationType: Entity.User,
},
} satisfies FieldDefinition<FieldRelationMetadata>,
useUpdateEntityMutation: useUpdateActivityMutation,
hotkeyScope: EditableFieldHotkeyScope.EditableField,
}}
>
<InlineCell />
</FieldContext.Provider>
);
};

View File

@ -1,7 +1,7 @@
import styled from '@emotion/styled';
import { ActivityAssigneePicker } from '@/activities/components/ActivityAssigneePicker';
import { useEditableField } from '@/ui/editable-field/hooks/useEditableField';
import { useInlineCell } from '@/ui/editable-field/hooks/useInlineCell';
import { Activity, User } from '~/generated/graphql';
const StyledContainer = styled.div`
@ -23,7 +23,7 @@ export const ActivityAssigneeEditableFieldEditMode = ({
onSubmit,
onCancel,
}: OwnProps) => {
const { closeEditableField } = useEditableField();
const { closeInlineCell: closeEditableField } = useInlineCell();
const handleSubmit = () => {
closeEditableField();

View File

@ -0,0 +1,38 @@
import { InlineCell } from '@/ui/editable-field/components/InlineCell';
import { EditableFieldHotkeyScope } from '@/ui/editable-field/types/EditableFieldHotkeyScope';
import { FieldContext } from '@/ui/field/contexts/FieldContext';
import { FieldDefinition } from '@/ui/field/types/FieldDefinition';
import { FieldDateMetadata } from '@/ui/field/types/FieldMetadata';
import { IconCalendar } from '@/ui/icon/index';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useUpdateActivityMutation } from '~/generated/graphql';
type OwnProps = {
activityId: string;
};
export const ActivityEditorDateField = ({ activityId }: OwnProps) => {
return (
<RecoilScope>
<FieldContext.Provider
value={{
entityId: activityId,
recoilScopeId: 'activityDueAt',
fieldDefinition: {
key: 'activityDueAt',
name: 'Due date',
Icon: IconCalendar,
type: 'date',
metadata: {
fieldName: 'dueAt',
},
} satisfies FieldDefinition<FieldDateMetadata>,
useUpdateEntityMutation: useUpdateActivityMutation,
hotkeyScope: EditableFieldHotkeyScope.EditableField,
}}
>
<InlineCell />
</FieldContext.Provider>
</RecoilScope>
);
};

View File

@ -1,5 +1,5 @@
import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips';
import { EditableField } from '@/ui/editable-field/components/EditableField';
import { InlineCellContainer } from '@/ui/editable-field/components/InlineCellContainer';
import { FieldRecoilScopeContext } from '@/ui/editable-field/states/recoil-scope-contexts/FieldRecoilScopeContext';
import { IconArrowUpRight } from '@/ui/icon';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
@ -23,7 +23,7 @@ export const ActivityRelationEditableField = ({ activity }: OwnProps) => {
return (
<RecoilScope CustomRecoilScopeContext={FieldRecoilScopeContext}>
<RecoilScope>
<EditableField
<InlineCellContainer
useEditButton
customEditHotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,

View File

@ -5,7 +5,7 @@ import { useHandleCheckableActivityTargetChange } from '@/activities/hooks/useHa
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '@/activities/utils/flatMapAndSortEntityForSelectArrayByName';
import { useFilteredSearchCompanyQuery } from '@/companies/hooks/useFilteredSearchCompanyQuery';
import { useFilteredSearchPeopleQuery } from '@/people/hooks/useFilteredSearchPeopleQuery';
import { useEditableField } from '@/ui/editable-field/hooks/useEditableField';
import { useInlineCell } from '@/ui/editable-field/hooks/useInlineCell';
import { MultipleEntitySelect } from '@/ui/input/relation-picker/components/MultipleEntitySelect';
import { Activity, ActivityTarget } from '~/generated/graphql';
import { assertNotNull } from '~/utils/assert';
@ -88,7 +88,7 @@ export const ActivityRelationEditableFieldEditMode = ({
const handleCheckItemsChange = useHandleCheckableActivityTargetChange({
activity,
});
const { closeEditableField } = useEditableField();
const { closeInlineCell: closeEditableField } = useInlineCell();
const handleSubmit = useCallback(() => {
handleCheckItemsChange(selectedEntityIds, entitiesToSelect);

View File

@ -1,7 +1,9 @@
import React from 'react';
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { ActivityEditor } from '@/activities/components/ActivityEditor';
import { entityFieldsFamilyState } from '@/ui/field/states/entityFieldsFamilyState';
import { useGetActivityQuery } from '~/generated/graphql';
import '@blocknote/core/style.css';
@ -27,12 +29,20 @@ export const RightDrawerActivity = ({
showComment = true,
autoFillTitle = false,
}: OwnProps) => {
const [, setEntityFields] = useRecoilState(
entityFieldsFamilyState(activityId),
);
const { data } = useGetActivityQuery({
variables: {
activityId: activityId ?? '',
},
skip: !activityId,
onCompleted: (data) => {
setEntityFields(data?.findManyActivities[0] ?? {});
},
});
const activity = data?.findManyActivities[0];
if (!activity) {