Remove overlay-scroll-bar (#11258)
## What - Deprecate overlayscrollbars as we decided to follow the native behavior - rework on performances (avoid calling recoil states too much at field level which is quite expensive) - Also implements: https://github.com/twentyhq/core-team-issues/issues/569 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -107,6 +107,7 @@ export const CalendarEventDetails = ({
|
||||
}),
|
||||
useUpdateRecord: () => [() => undefined, { loading: false }],
|
||||
maxWidth: 300,
|
||||
isReadOnly: false,
|
||||
}}
|
||||
>
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
|
||||
@ -8,17 +8,14 @@ import { useUploadAttachmentFile } from '@/activities/files/hooks/useUploadAttac
|
||||
import { useUpsertActivity } from '@/activities/hooks/useUpsertActivity';
|
||||
import { canCreateActivityState } from '@/activities/states/canCreateActivityState';
|
||||
import { ActivityEditorHotkeyScope } from '@/activities/types/ActivityEditorHotkeyScope';
|
||||
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
|
||||
import { isFieldValueReadOnly } from '@/object-record/record-field/utils/isFieldValueReadOnly';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { useDebouncedCallback } from 'use-debounce';
|
||||
|
||||
@ -26,6 +23,7 @@ import { ActivityRichTextEditorChangeOnActivityIdEffect } from '@/activities/com
|
||||
import { Note } from '@/activities/types/Note';
|
||||
import { Task } from '@/activities/types/Task';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { useIsRecordReadOnly } from '@/object-record/record-field/hooks/useIsRecordReadOnly';
|
||||
import { BlockEditor } from '@/ui/input/editor/components/BlockEditor';
|
||||
import { PartialBlock } from '@blocknote/core';
|
||||
import '@blocknote/core/fonts/inter.css';
|
||||
@ -56,17 +54,11 @@ export const ActivityRichTextEditor = ({
|
||||
objectNameSingular: activityObjectNameSingular,
|
||||
});
|
||||
|
||||
const contextStoreCurrentViewType = useRecoilComponentValueV2(
|
||||
contextStoreCurrentViewTypeComponentState,
|
||||
);
|
||||
|
||||
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();
|
||||
const isRecordReadOnly = useIsRecordReadOnly({ recordId: activityId });
|
||||
|
||||
const isReadOnly = isFieldValueReadOnly({
|
||||
objectNameSingular: activityObjectNameSingular,
|
||||
hasObjectReadOnlyPermission,
|
||||
contextStoreCurrentViewType,
|
||||
isRecordDeleted: activityInStore?.deletedAt !== null,
|
||||
isRecordReadOnly,
|
||||
});
|
||||
|
||||
const {
|
||||
|
||||
@ -196,10 +196,7 @@ export const AttachmentList = ({
|
||||
</StyledHeader>
|
||||
</StyledModalHeader>
|
||||
<ScrollWrapper
|
||||
contextProviderName="modalContent"
|
||||
componentInstanceId={`preview-modal-${previewedAttachment.id}`}
|
||||
scrollbarVariant="no-padding"
|
||||
heightMode="fit-content"
|
||||
>
|
||||
<StyledModalContent>
|
||||
<Suspense
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { ActivityTargetWithTargetRecord } from '@/activities/types/ActivityTargetObject';
|
||||
import { Note } from '@/activities/types/Note';
|
||||
import { NoteTarget } from '@/activities/types/NoteTarget';
|
||||
import { Task } from '@/activities/types/Task';
|
||||
import { TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { getActivityTargetObjectRecords } from '@/activities/utils/getActivityTargetObjectRecords';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useActivityTargetObjectRecords = (
|
||||
@ -25,49 +23,11 @@ export const useActivityTargetObjectRecords = (
|
||||
return { activityTargetObjectRecords: [] };
|
||||
}
|
||||
|
||||
const targets = activityTargets
|
||||
? activityTargets
|
||||
: activity && 'noteTargets' in activity && activity.noteTargets
|
||||
? activity.noteTargets
|
||||
: activity && 'taskTargets' in activity && activity.taskTargets
|
||||
? activity.taskTargets
|
||||
: [];
|
||||
|
||||
const activityTargetObjectRecords = targets
|
||||
.map<ActivityTargetWithTargetRecord | undefined>((activityTarget) => {
|
||||
if (!isDefined(activityTarget)) {
|
||||
throw new Error(`Cannot find activity target`);
|
||||
}
|
||||
|
||||
const correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
isDefined(activityTarget[objectMetadataItem.nameSingular]) &&
|
||||
![CoreObjectNameSingular.Note, CoreObjectNameSingular.Task].includes(
|
||||
objectMetadataItem.nameSingular as CoreObjectNameSingular,
|
||||
),
|
||||
);
|
||||
|
||||
if (!correspondingObjectMetadataItem) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetObjectRecord = activityTarget[
|
||||
correspondingObjectMetadataItem.nameSingular
|
||||
] as ObjectRecord | undefined;
|
||||
|
||||
if (!isDefined(targetObjectRecord)) {
|
||||
throw new Error(
|
||||
`Cannot find target object record of type ${correspondingObjectMetadataItem.nameSingular}, make sure the request for activities eagerly loads for the target objects on activity target relation.`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
activityTarget,
|
||||
targetObject: targetObjectRecord,
|
||||
targetObjectMetadataItem: correspondingObjectMetadataItem,
|
||||
};
|
||||
})
|
||||
.filter(isDefined);
|
||||
const activityTargetObjectRecords = getActivityTargetObjectRecords({
|
||||
activityRecord: activity as Note | Task,
|
||||
objectMetadataItems,
|
||||
activityTargets,
|
||||
});
|
||||
|
||||
return {
|
||||
activityTargetObjectRecords,
|
||||
|
||||
@ -2,13 +2,12 @@ import { useContext } from 'react';
|
||||
|
||||
import { ActivityTargetChips } from '@/activities/components/ActivityTargetChips';
|
||||
import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords';
|
||||
import { useOpenActivityTargetInlineCellEditMode } from '@/activities/inline-cell/hooks/useOpenActivityTargetInlineCellEditMode';
|
||||
import { useUpdateActivityTargetFromInlineCell } from '@/activities/inline-cell/hooks/useUpdateActivityTargetFromInlineCell';
|
||||
import { useOpenActivityTargetCellEditMode } from '@/activities/inline-cell/hooks/useOpenActivityTargetCellEditMode';
|
||||
import { useUpdateActivityTargetFromCell } from '@/activities/inline-cell/hooks/useUpdateActivityTargetFromCell';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { FieldContextProvider } from '@/object-record/record-field/components/FieldContextProvider';
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { FieldFocusContextProvider } from '@/object-record/record-field/contexts/FieldFocusContextProvider';
|
||||
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
||||
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/states/contexts/RecordFieldComponentInstanceContext';
|
||||
import { RecordInlineCellContainer } from '@/object-record/record-inline-cell/components/RecordInlineCellContainer';
|
||||
import { RecordInlineCellContext } from '@/object-record/record-inline-cell/components/RecordInlineCellContext';
|
||||
@ -39,18 +38,15 @@ export const ActivityTargetsInlineCell = ({
|
||||
|
||||
const { closeInlineCell } = useInlineCell(componentInstanceId);
|
||||
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
const { fieldDefinition, isReadOnly } = useContext(FieldContext);
|
||||
|
||||
const isFieldReadOnly = useIsFieldValueReadOnly();
|
||||
const { openActivityTargetCellEditMode } =
|
||||
useOpenActivityTargetCellEditMode();
|
||||
|
||||
const { openActivityTargetInlineCellEditMode } =
|
||||
useOpenActivityTargetInlineCellEditMode();
|
||||
|
||||
const { updateActivityTargetFromInlineCell } =
|
||||
useUpdateActivityTargetFromInlineCell({
|
||||
activityObjectNameSingular,
|
||||
activityId: activityRecordId,
|
||||
});
|
||||
const { updateActivityTargetFromCell } = useUpdateActivityTargetFromCell({
|
||||
activityObjectNameSingular,
|
||||
activityId: activityRecordId,
|
||||
});
|
||||
|
||||
return (
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
@ -73,7 +69,7 @@ export const ActivityTargetsInlineCell = ({
|
||||
MultipleRecordPickerHotkeyScope.MultipleRecordPicker,
|
||||
IconLabel: showLabel ? IconArrowUpRight : undefined,
|
||||
showLabel: showLabel,
|
||||
readonly: isFieldReadOnly,
|
||||
readonly: isReadOnly,
|
||||
labelWidth: fieldDefinition?.labelWidth,
|
||||
editModeContent: (
|
||||
<MultipleRecordPicker
|
||||
@ -82,7 +78,7 @@ export const ActivityTargetsInlineCell = ({
|
||||
closeInlineCell();
|
||||
}}
|
||||
onChange={(morphItem) => {
|
||||
updateActivityTargetFromInlineCell({
|
||||
updateActivityTargetFromCell({
|
||||
recordPickerInstanceId: componentInstanceId,
|
||||
morphItem,
|
||||
activityTargetWithTargetRecords:
|
||||
@ -102,7 +98,7 @@ export const ActivityTargetsInlineCell = ({
|
||||
/>
|
||||
),
|
||||
onOpenEditMode: () => {
|
||||
openActivityTargetInlineCellEditMode({
|
||||
openActivityTargetCellEditMode({
|
||||
recordPickerInstanceId: componentInstanceId,
|
||||
activityTargetObjectRecords,
|
||||
});
|
||||
|
||||
@ -7,21 +7,22 @@ import { multipleRecordPickerSearchFilterComponentState } from '@/object-record/
|
||||
import { multipleRecordPickerSearchableObjectMetadataItemsComponentState } from '@/object-record/record-picker/multiple-record-picker/states/multipleRecordPickerSearchableObjectMetadataItemsComponentState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
type OpenActivityTargetInlineCellEditModeProps = {
|
||||
type OpenActivityTargetCellEditModeProps = {
|
||||
recordPickerInstanceId: string;
|
||||
activityTargetObjectRecords: ActivityTargetWithTargetRecord[];
|
||||
};
|
||||
|
||||
export const useOpenActivityTargetInlineCellEditMode = () => {
|
||||
// TODO: deprecate this once we are supporting one to many through relations
|
||||
export const useOpenActivityTargetCellEditMode = () => {
|
||||
const { performSearch: multipleRecordPickerPerformSearch } =
|
||||
useMultipleRecordPickerPerformSearch();
|
||||
|
||||
const openActivityTargetInlineCellEditMode = useRecoilCallback(
|
||||
const openActivityTargetCellEditMode = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
({
|
||||
recordPickerInstanceId,
|
||||
activityTargetObjectRecords,
|
||||
}: OpenActivityTargetInlineCellEditModeProps) => {
|
||||
}: OpenActivityTargetCellEditModeProps) => {
|
||||
const objectMetadataItems = snapshot
|
||||
.getLoadable(objectMetadataItemsState)
|
||||
.getValue()
|
||||
@ -82,5 +83,5 @@ export const useOpenActivityTargetInlineCellEditMode = () => {
|
||||
[multipleRecordPickerPerformSearch],
|
||||
);
|
||||
|
||||
return { openActivityTargetInlineCellEditMode };
|
||||
return { openActivityTargetCellEditMode };
|
||||
};
|
||||
@ -11,16 +11,17 @@ import { RecordPickerPickableMorphItem } from '@/object-record/record-picker/typ
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { isNull } from '@sniptt/guards';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
type UpdateActivityTargetFromInlineCellProps = {
|
||||
type UpdateActivityTargetFromCellProps = {
|
||||
recordPickerInstanceId: string;
|
||||
morphItem: RecordPickerPickableMorphItem;
|
||||
activityTargetWithTargetRecords: ActivityTargetWithTargetRecord[];
|
||||
};
|
||||
|
||||
export const useUpdateActivityTargetFromInlineCell = ({
|
||||
// TODO: deprecate this hook once we implement one-to-many relation through
|
||||
export const useUpdateActivityTargetFromCell = ({
|
||||
activityObjectNameSingular,
|
||||
activityId,
|
||||
}: {
|
||||
@ -29,27 +30,37 @@ export const useUpdateActivityTargetFromInlineCell = ({
|
||||
| CoreObjectNameSingular.Task;
|
||||
activityId: string;
|
||||
}) => {
|
||||
const joinObjectNameSingular = getJoinObjectNameSingular(
|
||||
activityObjectNameSingular,
|
||||
);
|
||||
|
||||
const { createOneRecord: createOneActivityTarget } = useCreateOneRecord<
|
||||
NoteTarget | TaskTarget
|
||||
>({
|
||||
objectNameSingular: getJoinObjectNameSingular(activityObjectNameSingular),
|
||||
objectNameSingular:
|
||||
joinObjectNameSingular === ''
|
||||
? activityObjectNameSingular
|
||||
: joinObjectNameSingular,
|
||||
});
|
||||
|
||||
const { deleteOneRecord: deleteOneActivityTarget } = useDeleteOneRecord({
|
||||
objectNameSingular: getJoinObjectNameSingular(activityObjectNameSingular),
|
||||
objectNameSingular:
|
||||
joinObjectNameSingular === ''
|
||||
? activityObjectNameSingular
|
||||
: joinObjectNameSingular,
|
||||
});
|
||||
|
||||
const setActivityFromStore = useSetRecoilState(
|
||||
recordStoreFamilyState(activityId),
|
||||
);
|
||||
|
||||
const updateActivityTargetFromInlineCell = useRecoilCallback(
|
||||
const updateActivityTargetFromCell = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async ({
|
||||
morphItem,
|
||||
activityTargetWithTargetRecords,
|
||||
recordPickerInstanceId,
|
||||
}: UpdateActivityTargetFromInlineCellProps) => {
|
||||
}: UpdateActivityTargetFromCellProps) => {
|
||||
const targetObjectName =
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
? 'task'
|
||||
@ -179,5 +190,5 @@ export const useUpdateActivityTargetFromInlineCell = ({
|
||||
],
|
||||
);
|
||||
|
||||
return { updateActivityTargetFromInlineCell };
|
||||
return { updateActivityTargetFromCell };
|
||||
};
|
||||
@ -45,7 +45,6 @@ export const EventList = ({ events, targetableObject }: EventListProps) => {
|
||||
|
||||
return (
|
||||
<ScrollWrapper
|
||||
contextProviderName="eventList"
|
||||
componentInstanceId={`scroll-wrapper-event-list-${targetableObject.id}`}
|
||||
>
|
||||
<StyledTimelineContainer>
|
||||
|
||||
@ -54,6 +54,7 @@ export const EventFieldDiffValue = ({
|
||||
defaultValue: fieldMetadataItem.defaultValue,
|
||||
},
|
||||
hotkeyScope: 'field-event-diff',
|
||||
isReadOnly: false,
|
||||
}}
|
||||
>
|
||||
<FieldDisplay />
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
import { ActivityTargetWithTargetRecord } from '@/activities/types/ActivityTargetObject';
|
||||
import { Note } from '@/activities/types/Note';
|
||||
import { NoteTarget } from '@/activities/types/NoteTarget';
|
||||
import { Task } from '@/activities/types/Task';
|
||||
import { TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type GetActivityTargetObjectRecordsProps = {
|
||||
activityRecord: Note | Task;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
activityTargets?: NoteTarget[] | TaskTarget[];
|
||||
};
|
||||
|
||||
export const getActivityTargetObjectRecords = ({
|
||||
activityRecord,
|
||||
objectMetadataItems,
|
||||
activityTargets,
|
||||
}: GetActivityTargetObjectRecordsProps) => {
|
||||
if (!isDefined(activityRecord) && !isDefined(activityTargets)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const targets = activityTargets
|
||||
? activityTargets
|
||||
: activityRecord &&
|
||||
'noteTargets' in activityRecord &&
|
||||
activityRecord.noteTargets
|
||||
? activityRecord.noteTargets
|
||||
: activityRecord &&
|
||||
'taskTargets' in activityRecord &&
|
||||
activityRecord.taskTargets
|
||||
? activityRecord.taskTargets
|
||||
: [];
|
||||
|
||||
const activityTargetObjectRecords = targets
|
||||
.map<ActivityTargetWithTargetRecord | undefined>((activityTarget) => {
|
||||
if (!isDefined(activityTarget)) {
|
||||
throw new Error(`Cannot find activity target`);
|
||||
}
|
||||
|
||||
const correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
isDefined(activityTarget[objectMetadataItem.nameSingular]) &&
|
||||
![CoreObjectNameSingular.Note, CoreObjectNameSingular.Task].includes(
|
||||
objectMetadataItem.nameSingular as CoreObjectNameSingular,
|
||||
),
|
||||
);
|
||||
|
||||
if (!correspondingObjectMetadataItem) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetObjectRecord = activityTarget[
|
||||
correspondingObjectMetadataItem.nameSingular
|
||||
] as ObjectRecord | undefined;
|
||||
|
||||
if (!isDefined(targetObjectRecord)) {
|
||||
throw new Error(
|
||||
`Cannot find target object record of type ${correspondingObjectMetadataItem.nameSingular}, make sure the request for activities eagerly loads for the target objects on activity target relation.`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
activityTarget,
|
||||
targetObject: targetObjectRecord,
|
||||
targetObjectMetadataItem: correspondingObjectMetadataItem,
|
||||
};
|
||||
})
|
||||
.filter(isDefined);
|
||||
|
||||
return activityTargetObjectRecords;
|
||||
};
|
||||
Reference in New Issue
Block a user