-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add relations to notes/tasks list view #6971
Changes from 1 commit
06ebdc6
d4fd2cf
ca59503
bf043a9
6e663e3
49cf0b8
6e091e4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
import { useApolloClient } from '@apollo/client'; | ||
import { useRecoilValue } from 'recoil'; | ||
import { Nullable } from 'twenty-ui'; | ||
|
||
|
@@ -7,46 +6,40 @@ 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 { getJoinObjectNameSingular } from '@/activities/utils/getJoinObjectNameSingular'; | ||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; | ||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache'; | ||
import { isDefined } from '~/utils/isDefined'; | ||
|
||
export const useActivityTargetObjectRecords = ( | ||
activity: Task | Note, | ||
objectNameSingular: CoreObjectNameSingular, | ||
activity?: Task | Note, | ||
activityTargets?: NoteTarget[] | TaskTarget[], | ||
) => { | ||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState); | ||
|
||
const activityTargets = | ||
'noteTargets' in activity && activity.noteTargets | ||
if(!isDefined(activity) && !isDefined(activityTargets)) { | ||
throw new Error( | ||
`No activity or activity targets`, | ||
); | ||
} | ||
|
||
const targets = activityTargets ? activityTargets : | ||
(activity && 'noteTargets' in activity && activity.noteTargets | ||
? activity.noteTargets | ||
: 'taskTargets' in activity && activity.taskTargets | ||
: activity && 'taskTargets' in activity && activity.taskTargets | ||
? activity.taskTargets | ||
: []; | ||
|
||
const getRecordFromCache = useGetRecordFromCache({ | ||
objectNameSingular: getJoinObjectNameSingular(objectNameSingular), | ||
}); | ||
: []); | ||
|
||
const apolloClient = useApolloClient(); | ||
|
||
const activityTargetObjectRecords = activityTargets | ||
const activityTargetObjectRecords = targets | ||
.map<Nullable<ActivityTargetWithTargetRecord>>((activityTarget) => { | ||
const activityTargetFromCache = getRecordFromCache< | ||
NoteTarget | TaskTarget | ||
>(activityTarget.id, apolloClient.cache); | ||
|
||
if (!isDefined(activityTargetFromCache)) { | ||
if (!isDefined(activityTarget)) { | ||
throw new Error( | ||
`Cannot find activity target ${activityTarget.id} in cache, this shouldn't happen.`, | ||
`Cannot find activity target`, | ||
); | ||
} | ||
|
||
const correspondingObjectMetadataItem = objectMetadataItems.find( | ||
(objectMetadataItem) => | ||
isDefined(activityTargetFromCache[objectMetadataItem.nameSingular]) && | ||
isDefined(activityTarget[objectMetadataItem.nameSingular]) && | ||
![CoreObjectNameSingular.Note, CoreObjectNameSingular.Task].includes( | ||
objectMetadataItem.nameSingular as CoreObjectNameSingular, | ||
), | ||
|
@@ -57,7 +50,7 @@ export const useActivityTargetObjectRecords = ( | |
} | ||
|
||
const targetObjectRecord = | ||
activityTargetFromCache[correspondingObjectMetadataItem.nameSingular]; | ||
activityTarget[correspondingObjectMetadataItem.nameSingular]; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Ensure this bracket alignment is consistent with project style |
||
if (!targetObjectRecord) { | ||
throw new Error( | ||
|
@@ -66,7 +59,7 @@ export const useActivityTargetObjectRecords = ( | |
} | ||
|
||
return { | ||
activityTarget: activityTargetFromCache ?? activityTarget, | ||
activityTarget, | ||
targetObject: targetObjectRecord ?? undefined, | ||
targetObjectMetadataItem: correspondingObjectMetadataItem, | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,11 @@ | ||
import { useActivityTargetObjectRecords } from '@/activities/hooks/useActivityTargetObjectRecords'; | ||
import { NoteTarget } from '@/activities/types/NoteTarget'; | ||
import { TaskTarget } from '@/activities/types/TaskTarget'; | ||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; | ||
import { RecordChip } from '@/object-record/components/RecordChip'; | ||
import { useFieldFocus } from '@/object-record/record-field/hooks/useFieldFocus'; | ||
import { useRelationFromManyFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useRelationFromManyFieldDisplay'; | ||
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; | ||
import { ExpandableList } from '@/ui/layout/expandable-list/components/ExpandableList'; | ||
|
||
export const RelationFromManyFieldDisplay = () => { | ||
|
@@ -14,17 +19,41 @@ export const RelationFromManyFieldDisplay = () => { | |
return null; | ||
} | ||
|
||
return ( | ||
const { fieldName, objectMetadataNameSingular } = fieldDefinition.metadata; | ||
|
||
const renderExpandableList = (records: ObjectRecord[], objectNameSingular: string, recordProp = '') => ( | ||
<ExpandableList isChipCountDisplayed={isFocused}> | ||
{fieldValue.map((record) => { | ||
return ( | ||
<RecordChip | ||
key={record.id} | ||
objectNameSingular={relationObjectNameSingular} | ||
record={record} | ||
/> | ||
); | ||
})} | ||
{records.map((record) => ( | ||
<RecordChip | ||
key={record.id} | ||
objectNameSingular={objectNameSingular} | ||
record={recordProp ? record[recordProp] : record} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. logic: Potential type error. |
||
/> | ||
))} | ||
</ExpandableList> | ||
); | ||
|
||
if ((fieldName === 'noteTargets' && objectMetadataNameSingular !== CoreObjectNameSingular.Note) || | ||
(fieldName === 'taskTargets' && objectMetadataNameSingular !== CoreObjectNameSingular.Task)) { | ||
const objectNameSingular = fieldName === 'noteTargets' ? CoreObjectNameSingular.Note : CoreObjectNameSingular.Task; | ||
const recordProp = fieldName === 'noteTargets' ? 'note' : 'task'; | ||
return renderExpandableList(fieldValue, objectNameSingular, recordProp); | ||
} | ||
|
||
if ((fieldName === 'taskTargets' && objectMetadataNameSingular === CoreObjectNameSingular.Task) || | ||
(fieldName === 'noteTargets' && objectMetadataNameSingular === CoreObjectNameSingular.Note)) { | ||
const { activityTargetObjectRecords } = useActivityTargetObjectRecords(undefined, fieldValue as NoteTarget[] | TaskTarget[]); | ||
return <ExpandableList isChipCountDisplayed={isFocused}> | ||
{activityTargetObjectRecords.map((record) => ( | ||
<RecordChip | ||
key={record.targetObject.id} | ||
objectNameSingular={record.targetObjectMetadataItem.nameSingular} | ||
record={record.targetObject} | ||
/> | ||
))} | ||
</ExpandableList> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style: Indentation is inconsistent with the rest of the file. |
||
|
||
} | ||
|
||
return renderExpandableList(fieldValue, relationObjectNameSingular); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Simplify this logic using optional chaining and nullish coalescing