mirror of
https://github.com/twentyhq/twenty.git
synced 2024-11-27 01:05:08 +03:00
Fix note linked text in timeline view (in dark mode) (#6944)
This PR Fixes https://github.com/twentyhq/twenty/issues/6942 Other improvements : - Fetch activities (note and task) title only when loading timeline, so we don't always have a clickable title. - Fixed IconButton width regression. --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
parent
d1b4f85e8c
commit
91187dcf82
@ -3,7 +3,8 @@ import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { TimelineActivityContext } from '@/activities/timelineActivities/contexts/TimelineActivityContext';
|
||||
import { useLinkedObject } from '@/activities/timelineActivities/hooks/useLinkedObject';
|
||||
|
||||
import { useLinkedObjectObjectMetadataItem } from '@/activities/timelineActivities/hooks/useLinkedObjectObjectMetadataItem';
|
||||
import { EventIconDynamicComponent } from '@/activities/timelineActivities/rows/components/EventIconDynamicComponent';
|
||||
import { EventRowDynamicComponent } from '@/activities/timelineActivities/rows/components/EventRowDynamicComponent';
|
||||
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
|
||||
@ -100,7 +101,7 @@ export const EventRow = ({
|
||||
|
||||
const { labelIdentifierValue } = useContext(TimelineActivityContext);
|
||||
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(event.createdAt);
|
||||
const linkedObjectMetadataItem = useLinkedObject(
|
||||
const linkedObjectMetadataItem = useLinkedObjectObjectMetadataItem(
|
||||
event.linkedObjectMetadataId,
|
||||
);
|
||||
|
||||
|
@ -46,7 +46,7 @@ export const TimelineActivities = ({
|
||||
const isTimelineActivitiesEmpty =
|
||||
!timelineActivities || timelineActivities.length === 0;
|
||||
|
||||
if (loading && isTimelineActivitiesEmpty) {
|
||||
if (loading) {
|
||||
return <SkeletonLoader withSubSections />;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export const useLinkedObject = (id: string) => {
|
||||
export const useLinkedObjectObjectMetadataItem = (id: string) => {
|
||||
const objectMetadataItems: ObjectMetadataItem[] = useRecoilValue(
|
||||
objectMetadataItemsState,
|
||||
);
|
@ -0,0 +1,43 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
|
||||
export const useLinkedObjectsTitle = (linkedObjectIds: string[]) => {
|
||||
const { loading } = useCombinedFindManyRecords({
|
||||
skip: !isNonEmptyArray(linkedObjectIds),
|
||||
operationSignatures: [
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.Task,
|
||||
variables: {
|
||||
filter: {
|
||||
id: {
|
||||
in: linkedObjectIds ?? [],
|
||||
},
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.Note,
|
||||
variables: {
|
||||
filter: {
|
||||
id: {
|
||||
in: linkedObjectIds ?? [],
|
||||
},
|
||||
},
|
||||
},
|
||||
fields: {
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return {
|
||||
loading,
|
||||
};
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import { useLinkedObjectsTitle } from '@/activities/timelineActivities/hooks/useLinkedObjectsTitle';
|
||||
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
|
||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
@ -19,10 +20,10 @@ export const useTimelineActivities = (
|
||||
});
|
||||
|
||||
const {
|
||||
records: TimelineActivities,
|
||||
loading,
|
||||
records: timelineActivities,
|
||||
loading: loadingTimelineActivities,
|
||||
fetchMoreRecords,
|
||||
} = useFindManyRecords({
|
||||
} = useFindManyRecords<TimelineActivity>({
|
||||
objectNameSingular: CoreObjectNameSingular.TimelineActivity,
|
||||
filter: {
|
||||
[targetableObjectFieldIdName]: {
|
||||
@ -38,8 +39,17 @@ export const useTimelineActivities = (
|
||||
fetchPolicy: 'cache-and-network',
|
||||
});
|
||||
|
||||
const activityIds = timelineActivities
|
||||
.filter((timelineActivity) => timelineActivity.name.match(/note|task/i))
|
||||
.map((timelineActivity) => timelineActivity.linkedRecordId);
|
||||
|
||||
const { loading: loadingLinkedObjectsTitle } =
|
||||
useLinkedObjectsTitle(activityIds);
|
||||
|
||||
const loading = loadingTimelineActivities || loadingLinkedObjectsTitle;
|
||||
|
||||
return {
|
||||
timelineActivities: TimelineActivities as TimelineActivity[],
|
||||
timelineActivities,
|
||||
loading,
|
||||
fetchMoreRecords,
|
||||
};
|
@ -1,5 +1,4 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
||||
import {
|
||||
@ -8,15 +7,21 @@ import {
|
||||
StyledEventRowItemColumn,
|
||||
} from '@/activities/timelineActivities/rows/components/EventRowDynamicComponent';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
type EventRowActivityProps = EventRowDynamicComponentProps;
|
||||
|
||||
const StyledLinkedActivity = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
`;
|
||||
|
||||
export const StyledEventRowItemText = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
`;
|
||||
|
||||
export const EventRowActivity = ({
|
||||
event,
|
||||
authorFullName,
|
||||
@ -30,9 +35,21 @@ export const EventRowActivity = ({
|
||||
throw new Error('Could not find linked record id for event');
|
||||
}
|
||||
|
||||
const [activityInStore] = useRecoilState(
|
||||
recordStoreFamilyState(event.linkedRecordId),
|
||||
);
|
||||
const getActivityFromCache = useGetRecordFromCache({
|
||||
objectNameSingular,
|
||||
recordGqlFields: {
|
||||
id: true,
|
||||
title: true,
|
||||
},
|
||||
});
|
||||
|
||||
const activityInStore = getActivityFromCache(event.linkedRecordId);
|
||||
|
||||
const activityTitle = isNonEmptyString(activityInStore?.title)
|
||||
? activityInStore?.title
|
||||
: isNonEmptyString(event.linkedRecordCachedName)
|
||||
? event.linkedRecordCachedName
|
||||
: 'Untitled';
|
||||
|
||||
const openActivityRightDrawer = useOpenActivityRightDrawer({
|
||||
objectNameSingular,
|
||||
@ -44,15 +61,11 @@ export const EventRowActivity = ({
|
||||
<StyledEventRowItemAction>
|
||||
{`${eventAction} a related ${eventObject}`}
|
||||
</StyledEventRowItemAction>
|
||||
{activityInStore ? (
|
||||
<StyledLinkedActivity
|
||||
onClick={() => openActivityRightDrawer(event.linkedRecordId)}
|
||||
>
|
||||
{event.linkedRecordCachedName}
|
||||
</StyledLinkedActivity>
|
||||
) : (
|
||||
<span>{event.linkedRecordCachedName}</span>
|
||||
)}
|
||||
<StyledLinkedActivity
|
||||
onClick={() => openActivityRightDrawer(event.linkedRecordId)}
|
||||
>
|
||||
{activityTitle}
|
||||
</StyledLinkedActivity>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -0,0 +1 @@
|
||||
export type TimelineActivityLinkedObject = 'note' | 'task';
|
@ -0,0 +1,12 @@
|
||||
import { TimelineActivity } from '@/activities/timelineActivities/types/TimelineActivity';
|
||||
import { TimelineActivityLinkedObject } from '@/activities/timelineActivities/types/TimelineActivityLinkedObject';
|
||||
|
||||
export const filterTimelineActivityByLinkedObjectTypes =
|
||||
(linkedObjectTypes: TimelineActivityLinkedObject[]) =>
|
||||
(timelineActivity: TimelineActivity) => {
|
||||
return linkedObjectTypes.some((linkedObjectType) => {
|
||||
const linkedObjectPartInName = timelineActivity.name.split('.')[0];
|
||||
|
||||
return linkedObjectPartInName.includes(linkedObjectType);
|
||||
});
|
||||
};
|
@ -11,13 +11,13 @@ export const useCombinedFindManyRecords = ({
|
||||
skip = false,
|
||||
}: {
|
||||
operationSignatures: RecordGqlOperationSignature[];
|
||||
skip: boolean;
|
||||
skip?: boolean;
|
||||
}) => {
|
||||
const findManyQuery = useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures,
|
||||
});
|
||||
|
||||
const { data } = useQuery<MultiObjectRecordQueryResult>(
|
||||
const { data, loading } = useQuery<MultiObjectRecordQueryResult>(
|
||||
findManyQuery ?? EMPTY_QUERY,
|
||||
{
|
||||
skip,
|
||||
@ -35,5 +35,6 @@ export const useCombinedFindManyRecords = ({
|
||||
|
||||
return {
|
||||
result: resultWithoutConnection,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { IconComponent } from 'twenty-ui';
|
||||
|
||||
export type IconButtonSize = 'medium' | 'small';
|
||||
@ -233,7 +233,7 @@ const StyledButton = styled.button<
|
||||
|
||||
white-space: nowrap;
|
||||
|
||||
width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
min-width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
|
Loading…
Reference in New Issue
Block a user