Fixed various bugs in activity creation (#6208)
- Fixed activity creation in cache - Fixed activity creation in DB, where the relation target was disappearing after creation - Added an option to match root query filter in creation optimistic effect to avoid adding the newly created record in every mounted query in Apollo cache on the same object (which was causing notes to be duplicated on every object in the cache) - Fixed tab list scope id - Fixed various browser console warnings
This commit is contained in:
@ -3,35 +3,98 @@ import { isNonEmptyArray } from '@sniptt/guards';
|
|||||||
import { CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE } from '@/activities/graphql/operation-signatures/CreateOneActivityOperationSignature';
|
import { CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE } from '@/activities/graphql/operation-signatures/CreateOneActivityOperationSignature';
|
||||||
import { ActivityForEditor } from '@/activities/types/ActivityForEditor';
|
import { ActivityForEditor } from '@/activities/types/ActivityForEditor';
|
||||||
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
import { ActivityTarget } from '@/activities/types/ActivityTarget';
|
||||||
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
|
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
|
||||||
|
import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
|
||||||
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
|
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
|
||||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||||
|
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||||
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
|
||||||
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
|
|
||||||
export const useCreateActivityInDB = () => {
|
export const useCreateActivityInDB = () => {
|
||||||
const { createOneRecord: createOneActivity } = useCreateOneRecord({
|
const { createOneRecord: createOneActivity } = useCreateOneRecord({
|
||||||
objectNameSingular:
|
objectNameSingular:
|
||||||
CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.objectNameSingular,
|
CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.objectNameSingular,
|
||||||
recordGqlFields: CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.fields,
|
recordGqlFields: CREATE_ONE_ACTIVITY_OPERATION_SIGNATURE.fields,
|
||||||
|
shouldMatchRootQueryFilter: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { createManyRecords: createManyActivityTargets } =
|
const { createManyRecords: createManyActivityTargets } =
|
||||||
useCreateManyRecords<ActivityTarget>({
|
useCreateManyRecords<ActivityTarget>({
|
||||||
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||||
skipPostOptmisticEffect: true,
|
shouldMatchRootQueryFilter: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const createActivityInDB = async (activityToCreate: ActivityForEditor) => {
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
await createOneActivity?.({
|
|
||||||
...activityToCreate,
|
const { objectMetadataItem: objectMetadataItemActivityTarget } =
|
||||||
updatedAt: new Date().toISOString(),
|
useObjectMetadataItem({
|
||||||
|
objectNameSingular: CoreObjectNameSingular.ActivityTarget,
|
||||||
});
|
});
|
||||||
|
|
||||||
const activityTargetsToCreate = activityToCreate.activityTargets ?? [];
|
const { objectMetadataItem: objectMetadataItemActivity } =
|
||||||
|
useObjectMetadataItem({
|
||||||
|
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||||
|
});
|
||||||
|
|
||||||
if (isNonEmptyArray(activityTargetsToCreate)) {
|
const cache = useApolloClient().cache;
|
||||||
await createManyActivityTargets(activityTargetsToCreate);
|
|
||||||
}
|
const createActivityInDB = useRecoilCallback(
|
||||||
};
|
({ set }) =>
|
||||||
|
async (activityToCreate: ActivityForEditor) => {
|
||||||
|
const createdActivity = await createOneActivity?.({
|
||||||
|
...activityToCreate,
|
||||||
|
updatedAt: new Date().toISOString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const activityTargetsToCreate = activityToCreate.activityTargets ?? [];
|
||||||
|
|
||||||
|
if (isNonEmptyArray(activityTargetsToCreate)) {
|
||||||
|
await createManyActivityTargets(activityTargetsToCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const activityTargetsConnection = getRecordConnectionFromRecords({
|
||||||
|
objectMetadataItems,
|
||||||
|
objectMetadataItem: objectMetadataItemActivityTarget,
|
||||||
|
records: activityTargetsToCreate.map((activityTarget) => ({
|
||||||
|
...activityTarget,
|
||||||
|
__typename: capitalize(
|
||||||
|
objectMetadataItemActivityTarget.nameSingular,
|
||||||
|
),
|
||||||
|
})),
|
||||||
|
withPageInfo: false,
|
||||||
|
computeReferences: true,
|
||||||
|
isRootLevel: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
modifyRecordFromCache({
|
||||||
|
recordId: createdActivity.id,
|
||||||
|
cache,
|
||||||
|
fieldModifiers: {
|
||||||
|
activityTargets: () => activityTargetsConnection,
|
||||||
|
},
|
||||||
|
objectMetadataItem: objectMetadataItemActivity,
|
||||||
|
});
|
||||||
|
|
||||||
|
set(recordStoreFamilyState(createdActivity.id), {
|
||||||
|
...createdActivity,
|
||||||
|
activityTargets: activityTargetsToCreate,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[
|
||||||
|
cache,
|
||||||
|
createManyActivityTargets,
|
||||||
|
createOneActivity,
|
||||||
|
objectMetadataItemActivity,
|
||||||
|
objectMetadataItemActivityTarget,
|
||||||
|
objectMetadataItems,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createActivityInDB,
|
createActivityInDB,
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { SkeletonLoader } from '@/activities/components/SkeletonLoader';
|
|
||||||
import { TimelineCreateButtonGroup } from '@/activities/timeline/components/TimelineCreateButtonGroup';
|
|
||||||
import { timelineActivitiesForGroupState } from '@/activities/timeline/states/timelineActivitiesForGroupState';
|
|
||||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
|
||||||
import AnimatedPlaceholder from '@/ui/layout/animated-placeholder/components/AnimatedPlaceholder';
|
|
||||||
import {
|
|
||||||
AnimatedPlaceholderEmptyContainer,
|
|
||||||
AnimatedPlaceholderEmptySubTitle,
|
|
||||||
AnimatedPlaceholderEmptyTextContainer,
|
|
||||||
AnimatedPlaceholderEmptyTitle,
|
|
||||||
EMPTY_PLACEHOLDER_TRANSITION_PROPS,
|
|
||||||
} from '@/ui/layout/animated-placeholder/components/EmptyPlaceholderStyled';
|
|
||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
|
||||||
|
|
||||||
import { TimelineItemsContainer } from './TimelineItemsContainer';
|
|
||||||
|
|
||||||
const StyledMainContainer = styled.div`
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: stretch;
|
|
||||||
border-top: ${({ theme }) =>
|
|
||||||
useIsMobile() ? `1px solid ${theme.border.color.medium}` : 'none'};
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
justify-content: center;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const Timeline = ({
|
|
||||||
targetableObject,
|
|
||||||
loading,
|
|
||||||
}: {
|
|
||||||
targetableObject: ActivityTargetableObject;
|
|
||||||
loading: boolean;
|
|
||||||
}) => {
|
|
||||||
const timelineActivitiesForGroup = useRecoilValue(
|
|
||||||
timelineActivitiesForGroupState,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <SkeletonLoader withSubSections />;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timelineActivitiesForGroup.length === 0) {
|
|
||||||
return (
|
|
||||||
<AnimatedPlaceholderEmptyContainer
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
||||||
{...EMPTY_PLACEHOLDER_TRANSITION_PROPS}
|
|
||||||
>
|
|
||||||
<AnimatedPlaceholder type="emptyTimeline" />
|
|
||||||
<AnimatedPlaceholderEmptyTextContainer>
|
|
||||||
<AnimatedPlaceholderEmptyTitle>
|
|
||||||
Add your first Activity
|
|
||||||
</AnimatedPlaceholderEmptyTitle>
|
|
||||||
<AnimatedPlaceholderEmptySubTitle>
|
|
||||||
There are no activities associated with this record.{' '}
|
|
||||||
</AnimatedPlaceholderEmptySubTitle>
|
|
||||||
</AnimatedPlaceholderEmptyTextContainer>
|
|
||||||
<TimelineCreateButtonGroup targetableObject={targetableObject} />
|
|
||||||
</AnimatedPlaceholderEmptyContainer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledMainContainer>
|
|
||||||
<TimelineItemsContainer />
|
|
||||||
</StyledMainContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1,44 +1,30 @@
|
|||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
import { IconCheckbox, IconNotes, IconPaperclip } from 'twenty-ui';
|
import { IconCheckbox, IconNotes, IconPaperclip } from 'twenty-ui';
|
||||||
|
|
||||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
|
||||||
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup';
|
import { ButtonGroup } from '@/ui/input/button/components/ButtonGroup';
|
||||||
import { TAB_LIST_COMPONENT_ID } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
import { TAB_LIST_COMPONENT_ID } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
||||||
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
import { useTabList } from '@/ui/layout/tab/hooks/useTabList';
|
||||||
|
|
||||||
export const TimelineCreateButtonGroup = ({
|
export const TimelineCreateButtonGroup = () => {
|
||||||
targetableObject,
|
|
||||||
}: {
|
|
||||||
targetableObject: ActivityTargetableObject;
|
|
||||||
}) => {
|
|
||||||
const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID);
|
const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID);
|
||||||
const setActiveTabId = useSetRecoilState(activeTabIdState);
|
const setActiveTabId = useSetRecoilState(activeTabIdState);
|
||||||
|
|
||||||
const openCreateActivity = useOpenCreateActivityDrawer();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ButtonGroup variant={'secondary'}>
|
<ButtonGroup variant={'secondary'}>
|
||||||
<Button
|
<Button
|
||||||
Icon={IconNotes}
|
Icon={IconNotes}
|
||||||
title="Note"
|
title="Note"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
openCreateActivity({
|
setActiveTabId('notes');
|
||||||
type: 'Note',
|
}}
|
||||||
targetableObjects: [targetableObject],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
Icon={IconCheckbox}
|
Icon={IconCheckbox}
|
||||||
title="Task"
|
title="Task"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
openCreateActivity({
|
setActiveTabId('tasks');
|
||||||
type: 'Task',
|
}}
|
||||||
targetableObjects: [targetableObject],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
Icon={IconPaperclip}
|
Icon={IconPaperclip}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ export const TimelineActivities = ({
|
|||||||
There are no activities associated with this record.{' '}
|
There are no activities associated with this record.{' '}
|
||||||
</AnimatedPlaceholderEmptySubTitle>
|
</AnimatedPlaceholderEmptySubTitle>
|
||||||
</AnimatedPlaceholderEmptyTextContainer>
|
</AnimatedPlaceholderEmptyTextContainer>
|
||||||
<TimelineCreateButtonGroup targetableObject={targetableObject} />
|
<TimelineCreateButtonGroup />
|
||||||
</AnimatedPlaceholderEmptyContainer>
|
</AnimatedPlaceholderEmptyContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,11 @@ import { RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge';
|
|||||||
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
||||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||||
|
import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter';
|
||||||
|
|
||||||
|
import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRecordQueryVariables';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: for now new records are added to all cached record lists, no matter what the variables (filters, orderBy, etc.) are.
|
TODO: for now new records are added to all cached record lists, no matter what the variables (filters, orderBy, etc.) are.
|
||||||
@ -19,11 +23,13 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
recordsToCreate,
|
recordsToCreate,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
}: {
|
}: {
|
||||||
cache: ApolloCache<unknown>;
|
cache: ApolloCache<unknown>;
|
||||||
objectMetadataItem: ObjectMetadataItem;
|
objectMetadataItem: ObjectMetadataItem;
|
||||||
recordsToCreate: RecordGqlNode[];
|
recordsToCreate: RecordGqlNode[];
|
||||||
objectMetadataItems: ObjectMetadataItem[];
|
objectMetadataItems: ObjectMetadataItem[];
|
||||||
|
shouldMatchRootQueryFilter?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
recordsToCreate.forEach((record) =>
|
recordsToCreate.forEach((record) =>
|
||||||
triggerUpdateRelationsOptimisticEffect({
|
triggerUpdateRelationsOptimisticEffect({
|
||||||
@ -39,12 +45,7 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
|||||||
fields: {
|
fields: {
|
||||||
[objectMetadataItem.namePlural]: (
|
[objectMetadataItem.namePlural]: (
|
||||||
rootQueryCachedResponse,
|
rootQueryCachedResponse,
|
||||||
{
|
{ DELETE: _DELETE, readField, storeFieldName, toReference },
|
||||||
DELETE: _DELETE,
|
|
||||||
readField,
|
|
||||||
storeFieldName: _storeFieldName,
|
|
||||||
toReference,
|
|
||||||
},
|
|
||||||
) => {
|
) => {
|
||||||
const shouldSkip = !isObjectRecordConnectionWithRefs(
|
const shouldSkip = !isObjectRecordConnectionWithRefs(
|
||||||
objectMetadataItem.nameSingular,
|
objectMetadataItem.nameSingular,
|
||||||
@ -55,6 +56,13 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
|||||||
return rootQueryCachedResponse;
|
return rootQueryCachedResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { fieldVariables: rootQueryVariables } =
|
||||||
|
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
|
||||||
|
storeFieldName,
|
||||||
|
);
|
||||||
|
|
||||||
|
const rootQueryFilter = rootQueryVariables?.filter;
|
||||||
|
|
||||||
const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse;
|
const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse;
|
||||||
|
|
||||||
const rootQueryCachedRecordEdges = readField<RecordGqlRefEdge[]>(
|
const rootQueryCachedRecordEdges = readField<RecordGqlRefEdge[]>(
|
||||||
@ -74,6 +82,22 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
|||||||
const hasAddedRecords = recordsToCreate
|
const hasAddedRecords = recordsToCreate
|
||||||
.map((recordToCreate) => {
|
.map((recordToCreate) => {
|
||||||
if (isNonEmptyString(recordToCreate.id)) {
|
if (isNonEmptyString(recordToCreate.id)) {
|
||||||
|
if (
|
||||||
|
isDefined(rootQueryFilter) &&
|
||||||
|
shouldMatchRootQueryFilter === true
|
||||||
|
) {
|
||||||
|
const recordToCreateMatchesThisRootQueryFilter =
|
||||||
|
isRecordMatchingFilter({
|
||||||
|
record: recordToCreate,
|
||||||
|
filter: rootQueryFilter,
|
||||||
|
objectMetadataItem,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!recordToCreateMatchesThisRootQueryFilter) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const recordToCreateReference = toReference(recordToCreate);
|
const recordToCreateReference = toReference(recordToCreate);
|
||||||
|
|
||||||
if (!recordToCreateReference) {
|
if (!recordToCreateReference) {
|
||||||
|
|||||||
@ -18,6 +18,7 @@ type useCreateManyRecordsProps = {
|
|||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||||
skipPostOptmisticEffect?: boolean;
|
skipPostOptmisticEffect?: boolean;
|
||||||
|
shouldMatchRootQueryFilter?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCreateManyRecords = <
|
export const useCreateManyRecords = <
|
||||||
@ -26,6 +27,7 @@ export const useCreateManyRecords = <
|
|||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
recordGqlFields,
|
recordGqlFields,
|
||||||
skipPostOptmisticEffect = false,
|
skipPostOptmisticEffect = false,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
}: useCreateManyRecordsProps) => {
|
}: useCreateManyRecordsProps) => {
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
|
|
||||||
@ -88,6 +90,7 @@ export const useCreateManyRecords = <
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
recordsToCreate: recordsCreatedInCache,
|
recordsToCreate: recordsCreatedInCache,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,6 +114,7 @@ export const useCreateManyRecords = <
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
recordsToCreate: records,
|
recordsToCreate: records,
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { useApolloClient } from '@apollo/client';
|
import { useApolloClient } from '@apollo/client';
|
||||||
|
import { useState } from 'react';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
|
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
|
||||||
@ -19,6 +19,7 @@ type useCreateOneRecordProps = {
|
|||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||||
skipPostOptmisticEffect?: boolean;
|
skipPostOptmisticEffect?: boolean;
|
||||||
|
shouldMatchRootQueryFilter?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCreateOneRecord = <
|
export const useCreateOneRecord = <
|
||||||
@ -27,6 +28,7 @@ export const useCreateOneRecord = <
|
|||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
recordGqlFields,
|
recordGqlFields,
|
||||||
skipPostOptmisticEffect = false,
|
skipPostOptmisticEffect = false,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
}: useCreateOneRecordProps) => {
|
}: useCreateOneRecordProps) => {
|
||||||
const apolloClient = useApolloClient();
|
const apolloClient = useApolloClient();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -76,6 +78,7 @@ export const useCreateOneRecord = <
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
recordsToCreate: [recordCreatedInCache],
|
recordsToCreate: [recordCreatedInCache],
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +100,9 @@ export const useCreateOneRecord = <
|
|||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
recordsToCreate: [record],
|
recordsToCreate: [record],
|
||||||
objectMetadataItems,
|
objectMetadataItems,
|
||||||
|
shouldMatchRootQueryFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { useState } from 'react';
|
import { Fragment, useState } from 'react';
|
||||||
|
|
||||||
import { RecordDetailRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRecordsList';
|
import { RecordDetailRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRecordsList';
|
||||||
import { RecordDetailRelationRecordsListItem } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem';
|
import { RecordDetailRelationRecordsListItem } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListItem';
|
||||||
@ -20,7 +20,7 @@ export const RecordDetailRelationRecordsList = ({
|
|||||||
return (
|
return (
|
||||||
<RecordDetailRecordsList>
|
<RecordDetailRecordsList>
|
||||||
{relationRecords.slice(0, 5).map((relationRecord) => (
|
{relationRecords.slice(0, 5).map((relationRecord) => (
|
||||||
<>
|
<Fragment key={relationRecord.id}>
|
||||||
<RecordDetailRelationRecordsListItemEffect
|
<RecordDetailRelationRecordsListItemEffect
|
||||||
key={`${relationRecord.id}-effect`}
|
key={`${relationRecord.id}-effect`}
|
||||||
relationRecordId={relationRecord.id}
|
relationRecordId={relationRecord.id}
|
||||||
@ -31,7 +31,7 @@ export const RecordDetailRelationRecordsList = ({
|
|||||||
onClick={handleItemClick}
|
onClick={handleItemClick}
|
||||||
relationRecord={relationRecord}
|
relationRecord={relationRecord}
|
||||||
/>
|
/>
|
||||||
</>
|
</Fragment>
|
||||||
))}
|
))}
|
||||||
</RecordDetailRecordsList>
|
</RecordDetailRecordsList>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -11,17 +11,17 @@ const StyledTbody = styled.tbody<{
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
&.first-columns-sticky {
|
&.first-columns-sticky {
|
||||||
td:nth-child(1) {
|
td:nth-of-type(1) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
td:nth-child(2) {
|
td:nth-of-type(2) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 9px;
|
left: 9px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
td:nth-child(3) {
|
td:nth-of-type(3) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 39px;
|
left: 39px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
|||||||
@ -25,17 +25,17 @@ const StyledTableHead = styled.thead<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.first-columns-sticky {
|
&.first-columns-sticky {
|
||||||
th:nth-child(1) {
|
th:nth-of-type(1) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
th:nth-child(2) {
|
th:nth-of-type(2) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 9px;
|
left: 9px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
th:nth-child(3) {
|
th:nth-of-type(3) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
left: 39px;
|
left: 39px;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
@ -55,9 +55,9 @@ const StyledTableHead = styled.thead<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.header-sticky.first-columns-sticky {
|
&.header-sticky.first-columns-sticky {
|
||||||
th:nth-child(1),
|
th:nth-of-type(1),
|
||||||
th:nth-child(2),
|
th:nth-of-type(2),
|
||||||
th:nth-child(3) {
|
th:nth-of-type(3) {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,9 +66,7 @@ export const ShowPageRightContainer = ({
|
|||||||
summary,
|
summary,
|
||||||
isRightDrawer = false,
|
isRightDrawer = false,
|
||||||
}: ShowPageRightContainerProps) => {
|
}: ShowPageRightContainerProps) => {
|
||||||
const { activeTabIdState } = useTabList(
|
const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID);
|
||||||
TAB_LIST_COMPONENT_ID + isRightDrawer,
|
|
||||||
);
|
|
||||||
const activeTabId = useRecoilValue(activeTabIdState);
|
const activeTabId = useRecoilValue(activeTabIdState);
|
||||||
|
|
||||||
const targetObjectNameSingular =
|
const targetObjectNameSingular =
|
||||||
@ -147,7 +145,7 @@ export const ShowPageRightContainer = ({
|
|||||||
<StyledTabListContainer>
|
<StyledTabListContainer>
|
||||||
<TabList
|
<TabList
|
||||||
loading={loading}
|
loading={loading}
|
||||||
tabListId={TAB_LIST_COMPONENT_ID + isRightDrawer}
|
tabListId={TAB_LIST_COMPONENT_ID}
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
/>
|
/>
|
||||||
</StyledTabListContainer>
|
</StyledTabListContainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user