Remove opportunity specific code on Kanban (#11000)

In this PR:
- clean board from opportunity specific logic
- remove in place creation in board
- trigger creation in right drawer instead
This commit is contained in:
Charles Bochet
2025-03-18 23:54:40 +01:00
committed by GitHub
parent d47debaff6
commit a4bd00ae29
73 changed files with 725 additions and 2366 deletions

View File

@ -7,6 +7,7 @@ import { RecoilRoot, useSetRecoilState } from 'recoil';
import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
@ -130,13 +131,19 @@ describe('useActivityTargetObjectRecords', () => {
objectMetadataItemsState,
);
const { activityTargetObjectRecords } =
useActivityTargetObjectRecords(task);
const setRecordFromStore = useSetRecoilState(
recordStoreFamilyState(task.id),
);
const { activityTargetObjectRecords } = useActivityTargetObjectRecords(
task.id,
);
return {
activityTargetObjectRecords,
setCurrentWorkspaceMember,
setObjectMetadataItems,
setRecordFromStore,
};
},
{ wrapper: Wrapper },
@ -145,6 +152,7 @@ describe('useActivityTargetObjectRecords', () => {
act(() => {
result.current.setCurrentWorkspaceMember(mockWorkspaceMembers[0]);
result.current.setObjectMetadataItems(generatedMockObjectMetadataItems);
result.current.setRecordFromStore(task);
});
const activityTargetObjectRecords =

View File

@ -8,14 +8,19 @@ import { Task } from '@/activities/types/Task';
import { TaskTarget } from '@/activities/types/TaskTarget';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { isDefined } from 'twenty-shared';
export const useActivityTargetObjectRecords = (
activity?: Task | Note,
activityRecordId?: string,
activityTargets?: NoteTarget[] | TaskTarget[],
) => {
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const activity = useRecoilValue(
recordStoreFamilyState(activityRecordId ?? ''),
) as Note | Task | null;
if (!isDefined(activity) && !isDefined(activityTargets)) {
return { activityTargetObjectRecords: [] };
}

View File

@ -7,8 +7,6 @@ import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTa
import { useOpenActivityTargetInlineCellEditMode } from '@/activities/inline-cell/hooks/useOpenActivityTargetInlineCellEditMode';
import { useUpdateActivityTargetFromInlineCell } from '@/activities/inline-cell/hooks/useUpdateActivityTargetFromInlineCell';
import { ActivityEditorHotkeyScope } from '@/activities/types/ActivityEditorHotkeyScope';
import { Note } from '@/activities/types/Note';
import { Task } from '@/activities/types/Task';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFieldContext } from '@/object-record/hooks/useFieldContext';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
@ -22,7 +20,7 @@ import { MultipleRecordPicker } from '@/object-record/record-picker/multiple-rec
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
type ActivityTargetsInlineCellProps = {
activity: Task | Note;
activityRecordId: string;
showLabel?: boolean;
maxWidth?: number;
activityObjectNameSingular:
@ -31,15 +29,15 @@ type ActivityTargetsInlineCellProps = {
};
export const ActivityTargetsInlineCell = ({
activity,
activityRecordId,
showLabel = true,
maxWidth,
activityObjectNameSingular,
}: ActivityTargetsInlineCellProps) => {
const { activityTargetObjectRecords } =
useActivityTargetObjectRecords(activity);
useActivityTargetObjectRecords(activityRecordId);
const multipleRecordPickerInstanceId = `multiple-record-picker-target-${activity.id}`;
const multipleRecordPickerInstanceId = `multiple-record-picker-target-${activityRecordId}`;
const { closeInlineCell } = useInlineCell();
@ -58,7 +56,7 @@ export const ActivityTargetsInlineCell = ({
const { FieldContextProvider: ActivityTargetsContextProvider } =
useFieldContext({
objectNameSingular: activityObjectNameSingular,
objectRecordId: activity.id,
objectRecordId: activityRecordId,
fieldMetadataName: fieldDefinition.metadata.fieldName,
fieldPosition: 3,
overridenIsFieldEmpty: activityTargetObjectRecords.length === 0,
@ -70,11 +68,11 @@ export const ActivityTargetsInlineCell = ({
const { updateActivityTargetFromInlineCell } =
useUpdateActivityTargetFromInlineCell({
activityObjectNameSingular,
activityId: activity.id,
activityId: activityRecordId,
});
return (
<RecordFieldInputScope recordFieldInputScopeId={activity?.id ?? ''}>
<RecordFieldInputScope recordFieldInputScopeId={activityRecordId}>
<FieldFocusContextProvider>
{ActivityTargetsContextProvider && (
<ActivityTargetsContextProvider>

View File

@ -96,7 +96,7 @@ export const NoteCard = ({
{NoteTargetsContextProvider && (
<NoteTargetsContextProvider>
<ActivityTargetsInlineCell
activity={note}
activityRecordId={note.id}
activityObjectNameSingular={CoreObjectNameSingular.Note}
/>
</NoteTargetsContextProvider>

View File

@ -132,7 +132,7 @@ export const TaskRow = ({ task }: { task: Task }) => {
<TaskTargetsContextProvider>
<ActivityTargetsInlineCell
activityObjectNameSingular={CoreObjectNameSingular.Task}
activity={task}
activityRecordId={task.id}
showLabel={false}
maxWidth={200}
/>

View File

@ -11,6 +11,8 @@ import { TimelineActivity } from '@/activities/timeline-activities/types/Timelin
import { getTimelineActivityAuthorFullName } from '@/activities/timeline-activities/utils/getTimelineActivityAuthorFullName';
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { MOBILE_VIEWPORT } from 'twenty-ui';
import { beautifyPastDateRelativeToNow } from '~/utils/date-utils';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
@ -104,7 +106,10 @@ export const EventRow = ({
}: EventRowProps) => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const { labelIdentifierValue } = useContext(TimelineActivityContext);
const { recordId } = useContext(TimelineActivityContext);
const recordFromStore = useRecoilValue(recordStoreFamilyState(recordId));
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(event.createdAt);
const linkedObjectMetadataItem = useLinkedObjectObjectMetadataItem(
event.linkedObjectMetadataId,
@ -114,6 +119,18 @@ export const EventRow = ({
return null;
}
if (isUndefinedOrNull(recordFromStore)) {
return null;
}
if (isUndefinedOrNull(mainObjectMetadataItem)) {
return null;
}
const labelIdentifier = getObjectRecordIdentifier({
objectMetadataItem: mainObjectMetadataItem,
record: recordFromStore,
});
const authorFullName = getTimelineActivityAuthorFullName(
event,
currentWorkspaceMember,
@ -143,7 +160,7 @@ export const EventRow = ({
<StyledSummary>
<EventRowDynamicComponent
authorFullName={authorFullName}
labelIdentifierValue={labelIdentifierValue}
labelIdentifierValue={labelIdentifier.name}
event={event}
mainObjectMetadataItem={mainObjectMetadataItem}
linkedObjectMetadataItem={linkedObjectMetadataItem}

View File

@ -17,9 +17,7 @@ const meta: Meta<typeof TimelineActivities> = {
SnackBarDecorator,
(Story) => {
return (
<TimelineActivityContext.Provider
value={{ labelIdentifierValue: 'Mock' }}
>
<TimelineActivityContext.Provider value={{ recordId: 'mock-id' }}>
<Story />
</TimelineActivityContext.Provider>
);

View File

@ -1,10 +1,10 @@
import { createContext } from 'react';
type TimelineActivityContextValue = {
labelIdentifierValue: string;
recordId: string;
};
export const TimelineActivityContext =
createContext<TimelineActivityContextValue>({
labelIdentifierValue: '',
recordId: '',
});

View File

@ -16,9 +16,7 @@ const meta: Meta<typeof EventCardMessage> = {
SnackBarDecorator,
(Story) => {
return (
<TimelineActivityContext.Provider
value={{ labelIdentifierValue: 'Mock' }}
>
<TimelineActivityContext.Provider value={{ recordId: 'mock-id' }}>
<Story />
</TimelineActivityContext.Provider>
);