Only fetch steps and trigger for the current workflow version (#15003)
Avoid fetching full steps and trigger for versions that are not the current version. Because those won't be used anyway. Better for performances. Only difficulty was for the `createDraft` mutation. I needed to return the full created version so I can store it in cache and use it as new `currentVersion`. Otherwise the current version is considered as incomplete for a short time, since workflow is fetched separately from the current version. --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@@ -1689,7 +1689,7 @@ export type Mutation = {
|
||||
createCoreViewGroup: CoreViewGroup;
|
||||
createCoreViewSort: CoreViewSort;
|
||||
createDatabaseConfigVariable: Scalars['Boolean'];
|
||||
createDraftFromWorkflowVersion: WorkflowVersion;
|
||||
createDraftFromWorkflowVersion: WorkflowVersionDto;
|
||||
createEmailingDomain: EmailingDomain;
|
||||
createFile: File;
|
||||
createOIDCIdentityProvider: SetupSsoOutput;
|
||||
@@ -4468,9 +4468,16 @@ export type WorkflowStepPositionUpdateInput = {
|
||||
position: WorkflowStepPositionInput;
|
||||
};
|
||||
|
||||
export type WorkflowVersion = {
|
||||
__typename?: 'WorkflowVersion';
|
||||
export type WorkflowVersionDto = {
|
||||
__typename?: 'WorkflowVersionDTO';
|
||||
createdAt: Scalars['String'];
|
||||
id: Scalars['UUID'];
|
||||
name: Scalars['String'];
|
||||
status: Scalars['String'];
|
||||
steps?: Maybe<Scalars['JSON']>;
|
||||
trigger?: Maybe<Scalars['JSON']>;
|
||||
updatedAt: Scalars['String'];
|
||||
workflowId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type WorkflowVersionStepChanges = {
|
||||
@@ -5911,7 +5918,7 @@ export type CreateDraftFromWorkflowVersionMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateDraftFromWorkflowVersionMutation = { __typename?: 'Mutation', createDraftFromWorkflowVersion: { __typename?: 'WorkflowVersion', id: string } };
|
||||
export type CreateDraftFromWorkflowVersionMutation = { __typename?: 'Mutation', createDraftFromWorkflowVersion: { __typename?: 'WorkflowVersionDTO', id: string, name: string, status: string, trigger?: any | null, steps?: any | null, createdAt: string, updatedAt: string } };
|
||||
|
||||
export type CreateWorkflowVersionEdgeMutationVariables = Exact<{
|
||||
input: CreateWorkflowVersionEdgeInput;
|
||||
@@ -13103,6 +13110,12 @@ export const CreateDraftFromWorkflowVersionDocument = gql`
|
||||
mutation CreateDraftFromWorkflowVersion($input: CreateDraftFromWorkflowVersionInput!) {
|
||||
createDraftFromWorkflowVersion(input: $input) {
|
||||
id
|
||||
name
|
||||
status
|
||||
trigger
|
||||
steps
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1646,7 +1646,7 @@ export type Mutation = {
|
||||
createCoreViewGroup: CoreViewGroup;
|
||||
createCoreViewSort: CoreViewSort;
|
||||
createDatabaseConfigVariable: Scalars['Boolean'];
|
||||
createDraftFromWorkflowVersion: WorkflowVersion;
|
||||
createDraftFromWorkflowVersion: WorkflowVersionDto;
|
||||
createEmailingDomain: EmailingDomain;
|
||||
createFile: File;
|
||||
createOIDCIdentityProvider: SetupSsoOutput;
|
||||
@@ -4296,9 +4296,16 @@ export type WorkflowStepPositionUpdateInput = {
|
||||
position: WorkflowStepPositionInput;
|
||||
};
|
||||
|
||||
export type WorkflowVersion = {
|
||||
__typename?: 'WorkflowVersion';
|
||||
export type WorkflowVersionDto = {
|
||||
__typename?: 'WorkflowVersionDTO';
|
||||
createdAt: Scalars['String'];
|
||||
id: Scalars['UUID'];
|
||||
name: Scalars['String'];
|
||||
status: Scalars['String'];
|
||||
steps?: Maybe<Scalars['JSON']>;
|
||||
trigger?: Maybe<Scalars['JSON']>;
|
||||
updatedAt: Scalars['String'];
|
||||
workflowId: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type WorkflowVersionStepChanges = {
|
||||
|
||||
+3
-3
@@ -9,15 +9,15 @@ type CalendarEventDetailsEffectProps = {
|
||||
export const CalendarEventDetailsEffect = ({
|
||||
record,
|
||||
}: CalendarEventDetailsEffectProps) => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (!record) {
|
||||
return;
|
||||
}
|
||||
|
||||
upsertRecords([record]);
|
||||
}, [record, upsertRecords]);
|
||||
upsertRecordsInStore([record]);
|
||||
}, [record, upsertRecordsInStore]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
+2
-2
@@ -94,7 +94,7 @@ export const EventCardCalendarEvent = ({
|
||||
}: {
|
||||
calendarEventId: string;
|
||||
}) => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { openCalendarEventInCommandMenu } =
|
||||
useOpenCalendarEventInCommandMenu();
|
||||
|
||||
@@ -118,7 +118,7 @@ export const EventCardCalendarEvent = ({
|
||||
},
|
||||
},
|
||||
onCompleted: (data) => {
|
||||
upsertRecords([data]);
|
||||
upsertRecordsInStore([data]);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -59,7 +59,7 @@ export const EventCardMessage = ({
|
||||
messageId: string;
|
||||
authorFullName: string;
|
||||
}) => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { openEmailThreadInCommandMenu } = useOpenEmailThreadInCommandMenu();
|
||||
|
||||
const {
|
||||
@@ -80,7 +80,7 @@ export const EventCardMessage = ({
|
||||
},
|
||||
},
|
||||
onCompleted: (data) => {
|
||||
upsertRecords([data]);
|
||||
upsertRecordsInStore([data]);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+49
-3
@@ -1,26 +1,45 @@
|
||||
import { type ApolloCache, type StoreObject } from '@apollo/client';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const triggerAttachRelationOptimisticEffect = ({
|
||||
cache,
|
||||
sourceObjectNameSingular,
|
||||
sourceRecordId,
|
||||
targetObjectNameSingular,
|
||||
targetObjectMetadataItem,
|
||||
fieldNameOnTargetRecord,
|
||||
targetRecordId,
|
||||
upsertRecordsInStore,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
sourceObjectNameSingular: string;
|
||||
sourceRecordId: string;
|
||||
targetObjectNameSingular: string;
|
||||
targetObjectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'fields' | 'nameSingular' | 'id' | 'readableFields'
|
||||
>;
|
||||
fieldNameOnTargetRecord: string;
|
||||
targetRecordId: string;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
}) => {
|
||||
const sourceRecordTypeName = capitalize(sourceObjectNameSingular);
|
||||
const targetRecordTypeName = capitalize(targetObjectNameSingular);
|
||||
const targetRecordTypeName = capitalize(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
);
|
||||
|
||||
const targetRecordCacheId = cache.identify({
|
||||
id: targetRecordId,
|
||||
@@ -65,6 +84,19 @@ export const triggerAttachRelationOptimisticEffect = ({
|
||||
},
|
||||
];
|
||||
|
||||
upsertRecordsInStore([
|
||||
getRecordFromRecordNode({
|
||||
recordNode: {
|
||||
id: targetRecordId,
|
||||
[fieldNameOnTargetRecord]: {
|
||||
...targetRecordFieldValue,
|
||||
edges: nextEdges,
|
||||
},
|
||||
__typename: targetRecordTypeName,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
return {
|
||||
...targetRecordFieldValue,
|
||||
edges: nextEdges,
|
||||
@@ -76,4 +108,18 @@ export const triggerAttachRelationOptimisticEffect = ({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const newCachedRecord = getRecordFromCache({
|
||||
cache,
|
||||
objectMetadataItem: targetObjectMetadataItem,
|
||||
objectMetadataItems,
|
||||
recordId: targetRecordId,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
if (!isDefined(newCachedRecord)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upsertRecordsInStore([newCachedRecord]);
|
||||
};
|
||||
|
||||
+6
@@ -13,6 +13,7 @@ import { type CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObje
|
||||
import { encodeCursor } from '@/apollo/utils/encodeCursor';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||
@@ -33,7 +34,9 @@ type TriggerCreateRecordsOptimisticEffectArgs = {
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
};
|
||||
|
||||
export const triggerCreateRecordsOptimisticEffect = ({
|
||||
cache,
|
||||
objectMetadataItem,
|
||||
@@ -42,6 +45,7 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
||||
shouldMatchRootQueryFilter,
|
||||
checkForRecordInCache = false,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: TriggerCreateRecordsOptimisticEffectArgs) => {
|
||||
const getRecordNodeFromCache = (recordId: string): RecordGqlNode | null => {
|
||||
const cachedRecord = getRecordFromCache({
|
||||
@@ -69,6 +73,8 @@ export const triggerCreateRecordsOptimisticEffect = ({
|
||||
currentSourceRecord,
|
||||
updatedSourceRecord: record,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+11
@@ -5,6 +5,8 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
|
||||
import { type RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge';
|
||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||
import { type RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const triggerDestroyRecordsOptimisticEffect = ({
|
||||
@@ -12,11 +14,18 @@ export const triggerDestroyRecordsOptimisticEffect = ({
|
||||
objectMetadataItem,
|
||||
recordsToDestroy,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
recordsToDestroy: RecordGqlNode[];
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
}) => {
|
||||
cache.modify<StoreObject>({
|
||||
fields: {
|
||||
@@ -75,6 +84,8 @@ export const triggerDestroyRecordsOptimisticEffect = ({
|
||||
currentSourceRecord: recordToDestroy,
|
||||
updatedSourceRecord: null,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
cache.evict({ id: cache.identify(recordToDestroy) });
|
||||
|
||||
+36
-4
@@ -1,24 +1,42 @@
|
||||
import { type ApolloCache, type StoreObject } from '@apollo/client';
|
||||
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||
import { capitalize } from 'twenty-shared/utils';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const triggerDetachRelationOptimisticEffect = ({
|
||||
cache,
|
||||
sourceObjectNameSingular,
|
||||
sourceRecordId,
|
||||
targetObjectNameSingular,
|
||||
targetObjectMetadataItem,
|
||||
fieldNameOnTargetRecord,
|
||||
targetRecordId,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
sourceObjectNameSingular: string;
|
||||
sourceRecordId: string;
|
||||
targetObjectNameSingular: string;
|
||||
targetObjectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'fields' | 'nameSingular' | 'id' | 'readableFields'
|
||||
>;
|
||||
fieldNameOnTargetRecord: string;
|
||||
targetRecordId: string;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
}) => {
|
||||
const targetRecordTypeName = capitalize(targetObjectNameSingular);
|
||||
const targetRecordTypeName = capitalize(
|
||||
targetObjectMetadataItem.nameSingular,
|
||||
);
|
||||
|
||||
const targetRecordCacheId = cache.identify({
|
||||
id: targetRecordId,
|
||||
@@ -58,4 +76,18 @@ export const triggerDetachRelationOptimisticEffect = ({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const newCachedRecord = getRecordFromCache({
|
||||
cache,
|
||||
objectMetadataItem: targetObjectMetadataItem,
|
||||
objectMetadataItems,
|
||||
recordId: targetRecordId,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
if (!isDefined(newCachedRecord)) {
|
||||
return;
|
||||
}
|
||||
|
||||
upsertRecordsInStore([newCachedRecord]);
|
||||
};
|
||||
|
||||
+12
-2
@@ -9,9 +9,10 @@ import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||
import { type RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter';
|
||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||
// TODO: add extensive unit tests for this function
|
||||
// That will also serve as documentation
|
||||
export const triggerUpdateRecordOptimisticEffect = ({
|
||||
@@ -20,12 +21,19 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
||||
currentRecord,
|
||||
updatedRecord,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
currentRecord: RecordGqlNode;
|
||||
updatedRecord: RecordGqlNode;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
}) => {
|
||||
triggerUpdateRelationsOptimisticEffect({
|
||||
cache,
|
||||
@@ -33,6 +41,8 @@ export const triggerUpdateRecordOptimisticEffect = ({
|
||||
currentSourceRecord: currentRecord,
|
||||
updatedSourceRecord: updatedRecord,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
cache.modify<StoreObject>({
|
||||
|
||||
+12
-1
@@ -9,8 +9,10 @@ import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
||||
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
|
||||
import { type RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { isRecordMatchingFilter } from '@/object-record/record-filter/utils/isRecordMatchingFilter';
|
||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
|
||||
|
||||
// TODO: add extensive unit tests for this function
|
||||
// That will also serve as documentation
|
||||
@@ -20,12 +22,19 @@ export const triggerUpdateRecordOptimisticEffectByBatch = ({
|
||||
currentRecords,
|
||||
updatedRecords,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: {
|
||||
cache: ApolloCache<unknown>;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
currentRecords: RecordGqlNode[];
|
||||
updatedRecords: RecordGqlNode[];
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
}) => {
|
||||
for (const [index, currentRecord] of currentRecords.entries()) {
|
||||
triggerUpdateRelationsOptimisticEffect({
|
||||
@@ -34,6 +43,8 @@ export const triggerUpdateRecordOptimisticEffectByBatch = ({
|
||||
currentSourceRecord: currentRecord,
|
||||
updatedSourceRecord: updatedRecords[index],
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+48
-5
@@ -12,9 +12,10 @@ import { type RecordGqlConnection } from '@/object-record/graphql/types/RecordGq
|
||||
import { type RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { isFieldMorphRelation } from '@/object-record/record-field/ui/types/guards/isFieldMorphRelation';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ApolloCache } from '@apollo/client';
|
||||
import { isArray } from '@sniptt/guards';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { FieldMetadataType, type ObjectPermissions } from 'twenty-shared/types';
|
||||
import {
|
||||
computeMorphRelationFieldName,
|
||||
CustomError,
|
||||
@@ -28,13 +29,21 @@ type TriggerUpdateRelationsOptimisticEffectArgs = {
|
||||
currentSourceRecord: RecordGqlNode | null;
|
||||
updatedSourceRecord: RecordGqlNode | null;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
};
|
||||
|
||||
export const triggerUpdateRelationsOptimisticEffect = ({
|
||||
cache,
|
||||
sourceObjectMetadataItem,
|
||||
currentSourceRecord,
|
||||
updatedSourceRecord,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: TriggerUpdateRelationsOptimisticEffectArgs) => {
|
||||
const isDeletion =
|
||||
isDefined(updatedSourceRecord) &&
|
||||
@@ -57,6 +66,8 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
||||
sourceObjectMetadataItem,
|
||||
cache,
|
||||
isDeletion,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,6 +80,8 @@ export const triggerUpdateRelationsOptimisticEffect = ({
|
||||
sourceObjectMetadataItem,
|
||||
cache,
|
||||
isDeletion,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -82,6 +95,8 @@ const triggerUpdateRelationOptimisticEffect = ({
|
||||
sourceObjectMetadataItem,
|
||||
cache,
|
||||
isDeletion,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
}: {
|
||||
fieldMetadataItemOnSourceRecord: FieldMetadataItem;
|
||||
updatedSourceRecord: RecordGqlNode | null;
|
||||
@@ -90,6 +105,11 @@ const triggerUpdateRelationOptimisticEffect = ({
|
||||
sourceObjectMetadataItem: ObjectMetadataItem;
|
||||
cache: ApolloCache<unknown>;
|
||||
isDeletion: boolean;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
}) => {
|
||||
const fieldDoesNotExist =
|
||||
isDefined(updatedSourceRecord) &&
|
||||
@@ -175,6 +195,8 @@ const triggerUpdateRelationOptimisticEffect = ({
|
||||
objectMetadataItem: fullTargetObjectMetadataItem,
|
||||
recordsToDestroy: targetRecordsToDetachFrom,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
} else if (isDefined(currentSourceRecord)) {
|
||||
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => {
|
||||
@@ -183,8 +205,11 @@ const triggerUpdateRelationOptimisticEffect = ({
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: currentSourceRecord.id,
|
||||
fieldNameOnTargetRecord: gqlFieldNameOnTargetRecord,
|
||||
targetObjectNameSingular: targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataItem: fullTargetObjectMetadataItem,
|
||||
targetRecordId: targetRecordToDetachFrom.id,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -201,8 +226,11 @@ const triggerUpdateRelationOptimisticEffect = ({
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: updatedSourceRecord.id,
|
||||
fieldNameOnTargetRecord: gqlFieldNameOnTargetRecord,
|
||||
targetObjectNameSingular: targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataItem: fullTargetObjectMetadataItem,
|
||||
targetRecordId: targetRecordToAttachTo.id,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -216,6 +244,8 @@ const triggerUpdateMorphRelationOptimisticEffect = ({
|
||||
sourceObjectMetadataItem,
|
||||
cache,
|
||||
isDeletion,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
}: {
|
||||
fieldMetadataItemOnSourceRecord: FieldMetadataItem;
|
||||
updatedSourceRecord: RecordGqlNode | null;
|
||||
@@ -224,6 +254,11 @@ const triggerUpdateMorphRelationOptimisticEffect = ({
|
||||
sourceObjectMetadataItem: ObjectMetadataItem;
|
||||
cache: ApolloCache<unknown>;
|
||||
isDeletion: boolean;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
}) => {
|
||||
const morphRelations = fieldMetadataItemOnSourceRecord.morphRelations;
|
||||
if (!morphRelations) {
|
||||
@@ -309,6 +344,8 @@ const triggerUpdateMorphRelationOptimisticEffect = ({
|
||||
objectMetadataItem: fullTargetObjectMetadataItem,
|
||||
recordsToDestroy: targetRecordsToDetachFrom,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
} else if (isDefined(currentSourceRecord)) {
|
||||
targetRecordsToDetachFrom.forEach((targetRecordToDetachFrom) => {
|
||||
@@ -317,8 +354,11 @@ const triggerUpdateMorphRelationOptimisticEffect = ({
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: currentSourceRecord.id,
|
||||
fieldNameOnTargetRecord: targetFieldMetadata.name,
|
||||
targetObjectNameSingular: targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataItem: fullTargetObjectMetadataItem,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
targetRecordId: targetRecordToDetachFrom.id,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -335,8 +375,11 @@ const triggerUpdateMorphRelationOptimisticEffect = ({
|
||||
sourceObjectNameSingular: sourceObjectMetadataItem.nameSingular,
|
||||
sourceRecordId: updatedSourceRecord.id,
|
||||
fieldNameOnTargetRecord: targetFieldMetadata.name,
|
||||
targetObjectNameSingular: targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataItem: fullTargetObjectMetadataItem,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
targetRecordId: targetRecordToAttachTo.id,
|
||||
upsertRecordsInStore,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useU
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
|
||||
export const CommandMenuCalendarEventPage = () => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const viewableRecordId = useRecoilComponentValue(
|
||||
viewableRecordIdComponentState,
|
||||
);
|
||||
@@ -20,7 +20,7 @@ export const CommandMenuCalendarEventPage = () => {
|
||||
recordGqlFields: FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE.fields,
|
||||
// TODO: this is not executed on sub-sequent runs, make sure that it is intended
|
||||
onCompleted: (record) => {
|
||||
upsertRecords([record]);
|
||||
upsertRecordsInStore([record]);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ export const useEmailThreadInCommandMenu = () => {
|
||||
const viewableRecordId = useRecoilComponentValue(
|
||||
viewableRecordIdComponentState,
|
||||
);
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const [lastMessageId, setLastMessageId] = useState<string | null>(null);
|
||||
const [lastMessageChannelId, setLastMessageChannelId] = useState<
|
||||
string | null
|
||||
@@ -35,7 +35,7 @@ export const useEmailThreadInCommandMenu = () => {
|
||||
id: true,
|
||||
},
|
||||
onCompleted: (record) => {
|
||||
upsertRecords([record]);
|
||||
upsertRecordsInStore([record]);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+6
-1
@@ -2,6 +2,8 @@ import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { deleteRecordFromCache } from '@/object-record/cache/utils/deleteRecordFromCache';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
export const useDeleteRecordFromCache = ({
|
||||
@@ -10,11 +12,12 @@ export const useDeleteRecordFromCache = ({
|
||||
objectNameSingular: string;
|
||||
}) => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
return (recordToDestroy: ObjectRecord) => {
|
||||
@@ -23,6 +26,8 @@ export const useDeleteRecordFromCache = ({
|
||||
objectMetadataItems,
|
||||
recordToDestroy,
|
||||
cache: apolloCoreClient.cache,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
+10
@@ -4,17 +4,25 @@ import { triggerDestroyRecordsOptimisticEffect } from '@/apollo/optimistic-effec
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type ObjectPermissions } from 'twenty-shared/types';
|
||||
|
||||
export const deleteRecordFromCache = ({
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
recordToDestroy,
|
||||
cache,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
recordToDestroy: ObjectRecord;
|
||||
cache: ApolloCache<object>;
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
ObjectPermissions & { objectMetadataId: string }
|
||||
>;
|
||||
upsertRecordsInStore: (records: ObjectRecord[]) => void;
|
||||
}) => {
|
||||
triggerDestroyRecordsOptimisticEffect({
|
||||
cache,
|
||||
@@ -26,5 +34,7 @@ export const deleteRecordFromCache = ({
|
||||
__typename: getObjectTypename(objectMetadataItem.nameSingular),
|
||||
},
|
||||
],
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
};
|
||||
|
||||
+5
-2
@@ -12,10 +12,13 @@ import { isEmptyObject } from '~/utils/isEmptyObject';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export type GetRecordFromCacheArgs = {
|
||||
cache: ApolloCache<object>;
|
||||
cache: ApolloCache<unknown>;
|
||||
recordId: string;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'fields' | 'nameSingular' | 'id' | 'readableFields'
|
||||
>;
|
||||
recordGqlFields?: RecordGqlFields;
|
||||
objectPermissionsByObjectMetadataId: Record<
|
||||
string,
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { generateDepthRecordGqlFieldsFromFields } from '@/object-record/graphql/
|
||||
|
||||
export type GenerateDepthRecordGqlFields = {
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItem: Pick<ObjectMetadataItem, 'fields'>;
|
||||
depth: 0 | 1;
|
||||
shouldOnlyLoadRelationIdentifiers?: boolean;
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { type FieldActorForInputValue } from '@/object-record/record-field/ui/types/FieldMetadata';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { computeOptimisticRecordFromInput } from '@/object-record/utils/computeOptimisticRecordFromInput';
|
||||
import { getCreateManyRecordsMutationResponseField } from '@/object-record/utils/getCreateManyRecordsMutationResponseField';
|
||||
@@ -51,6 +52,7 @@ export const useCreateManyRecords = <
|
||||
shouldRefetchAggregateQueries = true,
|
||||
}: useCreateManyRecordsProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
@@ -171,6 +173,7 @@ export const useCreateManyRecords = <
|
||||
objectMetadataItems,
|
||||
shouldMatchRootQueryFilter,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -208,6 +211,7 @@ export const useCreateManyRecords = <
|
||||
shouldMatchRootQueryFilter,
|
||||
checkForRecordInCache: true,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -218,6 +222,8 @@ export const useCreateManyRecords = <
|
||||
objectMetadataItem,
|
||||
cache: apolloCoreClient.cache,
|
||||
recordToDestroy,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -226,6 +232,8 @@ export const useCreateManyRecords = <
|
||||
objectMetadataItem,
|
||||
recordsToDestroy: recordsCreatedInCache,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
throw error;
|
||||
|
||||
@@ -17,6 +17,7 @@ import { useCreateOneRecordMutation } from '@/object-record/hooks/useCreateOneRe
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { computeOptimisticCreateRecordBaseRecordInput } from '@/object-record/utils/computeOptimisticCreateRecordBaseRecordInput';
|
||||
import { computeOptimisticRecordFromInput } from '@/object-record/utils/computeOptimisticRecordFromInput';
|
||||
@@ -39,6 +40,7 @@ export const useCreateOneRecord = <
|
||||
skipPostOptimisticEffect = false,
|
||||
shouldMatchRootQueryFilter,
|
||||
}: useCreateOneRecordProps) => {
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const [loading, setLoading] = useState(false);
|
||||
@@ -123,6 +125,7 @@ export const useCreateOneRecord = <
|
||||
objectMetadataItems,
|
||||
shouldMatchRootQueryFilter,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -147,6 +150,7 @@ export const useCreateOneRecord = <
|
||||
shouldMatchRootQueryFilter,
|
||||
checkForRecordInCache: true,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,6 +167,8 @@ export const useCreateOneRecord = <
|
||||
objectMetadataItem,
|
||||
cache: apolloCoreClient.cache,
|
||||
recordToDestroy: recordCreatedInCache,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
triggerDestroyRecordsOptimisticEffect({
|
||||
@@ -170,6 +176,8 @@ export const useCreateOneRecord = <
|
||||
objectMetadataItem,
|
||||
recordsToDestroy: [recordCreatedInCache],
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
throw error;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useDeleteManyRecordsMutation } from '@/object-record/hooks/useDeleteMan
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getDeleteManyRecordsMutationResponseField } from '@/object-record/utils/getDeleteManyRecordsMutationResponseField';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@@ -34,6 +35,7 @@ export const useDeleteManyRecords = ({
|
||||
objectNameSingular,
|
||||
}: useDeleteManyRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const apiConfig = useRecoilValue(apiConfigState);
|
||||
|
||||
const mutationPageSize =
|
||||
@@ -133,6 +135,8 @@ export const useDeleteManyRecords = ({
|
||||
currentRecords: cachedRecordsNode,
|
||||
updatedRecords: computedOptimisticRecordsNode,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -203,6 +207,8 @@ export const useDeleteManyRecords = ({
|
||||
currentRecords: computedOptimisticRecordsNode,
|
||||
updatedRecords: cachedRecordsNode,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
throw error;
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useDeleteOneRecordMutation } from '@/object-record/hooks/useDeleteOneRe
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getDeleteOneRecordMutationResponseField } from '@/object-record/utils/getDeleteOneRecordMutationResponseField';
|
||||
import { isNull } from '@sniptt/guards';
|
||||
@@ -26,6 +27,7 @@ export const useDeleteOneRecord = ({
|
||||
objectNameSingular,
|
||||
}: useDeleteOneRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
@@ -100,6 +102,8 @@ export const useDeleteOneRecord = ({
|
||||
currentRecord: cachedRecordNode,
|
||||
updatedRecord: optimisticRecordNode,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,6 +125,8 @@ export const useDeleteOneRecord = ({
|
||||
currentRecord: optimisticRecordNode,
|
||||
updatedRecord: record,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -150,6 +156,8 @@ export const useDeleteOneRecord = ({
|
||||
currentRecord: optimisticRecordNode,
|
||||
updatedRecord: cachedRecordNode,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
throw error;
|
||||
@@ -164,16 +172,17 @@ export const useDeleteOneRecord = ({
|
||||
return deletedRecord.data?.[mutationResponseField] ?? null;
|
||||
},
|
||||
[
|
||||
apolloCoreClient,
|
||||
deleteOneRecordMutation,
|
||||
getRecordFromCache,
|
||||
mutationResponseField,
|
||||
apolloCoreClient,
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
deleteOneRecordMutation,
|
||||
refetchAggregateQueries,
|
||||
objectNameSingular,
|
||||
registerObjectOperation,
|
||||
objectNameSingular,
|
||||
mutationResponseField,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useDestroyManyRecordsMutation } from '@/object-record/hooks/useDestroyM
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getDestroyManyRecordsMutationResponseField } from '@/object-record/utils/getDestroyManyRecordsMutationResponseField';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@@ -31,6 +32,7 @@ export const useDestroyManyRecords = ({
|
||||
objectNameSingular,
|
||||
}: useDestroyManyRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const apiConfig = useRecoilValue(apiConfigState);
|
||||
|
||||
const mutationPageSize =
|
||||
@@ -112,6 +114,8 @@ export const useDestroyManyRecords = ({
|
||||
objectMetadataItem,
|
||||
recordsToDestroy: cachedRecords,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -123,6 +127,7 @@ export const useDestroyManyRecords = ({
|
||||
recordsToCreate: cachedRecords,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordF
|
||||
import { useDestroyOneRecordMutation } from '@/object-record/hooks/useDestroyOneRecordMutation';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { getDestroyOneRecordMutationResponseField } from '@/object-record/utils/getDestroyOneRecordMutationResponseField';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -21,6 +22,7 @@ export const useDestroyOneRecord = ({
|
||||
objectNameSingular,
|
||||
}: useDestroyOneRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
@@ -67,6 +69,8 @@ export const useDestroyOneRecord = ({
|
||||
objectMetadataItem,
|
||||
recordsToDestroy: [cachedRecord],
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -78,6 +82,7 @@ export const useDestroyOneRecord = ({
|
||||
recordsToCreate: [originalRecord],
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -91,15 +96,16 @@ export const useDestroyOneRecord = ({
|
||||
return deletedRecord.data?.[mutationResponseField] ?? null;
|
||||
},
|
||||
[
|
||||
getRecordFromCache,
|
||||
apolloCoreClient,
|
||||
destroyOneRecordMutation,
|
||||
getRecordFromCache,
|
||||
mutationResponseField,
|
||||
objectMetadataItem,
|
||||
objectNameSingular,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
registerObjectOperation,
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
+8
-3
@@ -17,7 +17,7 @@ export const useLoadSelectedRecordsInContextStore = ({
|
||||
objectRecordIds,
|
||||
objectMetadataItemId,
|
||||
}: UseLoadSelectedRecordsInContextStoreProps) => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { findManyRecordsLazy } = useLazyFindManyRecords({
|
||||
objectNameSingular,
|
||||
@@ -57,10 +57,15 @@ export const useLoadSelectedRecordsInContextStore = ({
|
||||
|
||||
const { records } = await findManyRecordsLazy();
|
||||
|
||||
upsertRecords(records ?? []);
|
||||
upsertRecordsInStore(records ?? []);
|
||||
};
|
||||
},
|
||||
[objectRecordIds, objectMetadataItemId, findManyRecordsLazy, upsertRecords],
|
||||
[
|
||||
objectRecordIds,
|
||||
objectMetadataItemId,
|
||||
findManyRecordsLazy,
|
||||
upsertRecordsInStore,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -116,14 +116,14 @@ export const useMergeManyRecords = <
|
||||
}
|
||||
},
|
||||
[
|
||||
apolloCoreClient,
|
||||
findDuplicateRecordsQuery,
|
||||
findOneRecordQuery,
|
||||
mergeManyRecordsMutation,
|
||||
objectMetadataItem.namePlural,
|
||||
refetchAggregateQueries,
|
||||
apolloCoreClient,
|
||||
mergeManyRecordsMutation,
|
||||
findOneRecordQuery,
|
||||
findDuplicateRecordsQuery,
|
||||
registerObjectOperation,
|
||||
objectNameSingular,
|
||||
refetchAggregateQueries,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { DEFAULT_MUTATION_BATCH_SIZE } from '@/object-record/constants/DefaultMu
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useRestoreManyRecordsMutation } from '@/object-record/hooks/useRestoreManyRecordsMutation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getRestoreManyRecordsMutationResponseField } from '@/object-record/utils/getRestoreManyRecordsMutationResponseField';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@@ -32,6 +33,7 @@ export const useRestoreManyRecords = ({
|
||||
objectNameSingular,
|
||||
}: useRestoreManyRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const apiConfig = useRecoilValue(apiConfigState);
|
||||
|
||||
@@ -122,6 +124,8 @@ export const useRestoreManyRecords = ({
|
||||
currentRecord: cachedRecordWithConnection,
|
||||
updatedRecord: optimisticRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -182,6 +186,8 @@ export const useRestoreManyRecords = ({
|
||||
currentRecord: optimisticRecordWithConnection,
|
||||
updatedRecord: cachedRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions
|
||||
import { useRefetchAggregateQueries } from '@/object-record/hooks/useRefetchAggregateQueries';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpdateOneRecordMutation } from '@/object-record/hooks/useUpdateOneRecordMutation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { computeOptimisticRecordFromInput } from '@/object-record/utils/computeOptimisticRecordFromInput';
|
||||
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
|
||||
@@ -38,6 +39,7 @@ export const useUpdateOneRecord = <
|
||||
recordGqlFields,
|
||||
}: useUpdateOneRecordProps) => {
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
@@ -138,6 +140,8 @@ export const useUpdateOneRecord = <
|
||||
currentRecord: cachedRecordWithConnection,
|
||||
updatedRecord: optimisticRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -167,6 +171,8 @@ export const useUpdateOneRecord = <
|
||||
currentRecord: computedOptimisticRecord,
|
||||
updatedRecord: record,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -213,6 +219,8 @@ export const useUpdateOneRecord = <
|
||||
currentRecord: optimisticRecordWithConnection,
|
||||
updatedRecord: cachedRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
throw error;
|
||||
|
||||
@@ -11,6 +11,8 @@ import { type RecordGqlFields } from '@/object-record/graphql/record-gql-fields/
|
||||
import { generateDepthRecordGqlFieldsFromObject } from '@/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromObject';
|
||||
import { generateDepthRecordGqlFieldsFromRecord } from '@/object-record/graphql/record-gql-fields/utils/generateDepthRecordGqlFieldsFromRecord';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useRegisterObjectOperation } from '@/object-record/hooks/useRegisterObjectOperation';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { computeOptimisticRecordFromInput } from '@/object-record/utils/computeOptimisticRecordFromInput';
|
||||
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
|
||||
@@ -29,6 +31,8 @@ type UpdateOneRecordArgs<UpdatedObjectRecord> = {
|
||||
};
|
||||
export const useUpdateOneRecordV2 = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { registerObjectOperation } = useRegisterObjectOperation();
|
||||
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
|
||||
@@ -133,6 +137,8 @@ export const useUpdateOneRecordV2 = () => {
|
||||
currentRecord: cachedRecordWithConnection,
|
||||
updatedRecord: optimisticRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -171,6 +177,8 @@ export const useUpdateOneRecordV2 = () => {
|
||||
currentRecord: computedOptimisticRecord,
|
||||
updatedRecord: record,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
},
|
||||
})
|
||||
@@ -217,11 +225,17 @@ export const useUpdateOneRecordV2 = () => {
|
||||
currentRecord: optimisticRecordWithConnection,
|
||||
updatedRecord: cachedRecordWithConnection,
|
||||
objectMetadataItems,
|
||||
upsertRecordsInStore,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
|
||||
throw error;
|
||||
});
|
||||
|
||||
registerObjectOperation(objectMetadataItem.nameSingular, {
|
||||
type: 'update-one',
|
||||
result: { updatedRecord, updateInput: updateOneRecordInput },
|
||||
});
|
||||
return updatedRecord?.data?.[mutationResponseField] ?? null;
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ export const RecordIndexCalendarDataLoaderEffect = () => {
|
||||
|
||||
const { objectMetadataItem } = useRecordCalendarContextOrThrow();
|
||||
|
||||
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const setRecordIndexAllRecordIdsSelector = useSetRecoilComponentState(
|
||||
recordIndexAllRecordIdsComponentSelector,
|
||||
|
||||
+3
-3
@@ -24,13 +24,13 @@ export const RecordDetailRelationRecordsListItemEffect = ({
|
||||
objectRecordId: relationRecordId,
|
||||
});
|
||||
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(record)) {
|
||||
upsertRecords([record]);
|
||||
upsertRecordsInStore([record]);
|
||||
}
|
||||
}, [record, upsertRecords]);
|
||||
}, [record, upsertRecordsInStore]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
+17
-13
@@ -30,6 +30,7 @@ import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient
|
||||
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { isFieldArray } from '@/object-record/record-field/ui/types/guards/isFieldArray';
|
||||
@@ -42,6 +43,7 @@ import { isFieldRichText } from '@/object-record/record-field/ui/types/guards/is
|
||||
import { isFieldRichTextV2 } from '@/object-record/record-field/ui/types/guards/isFieldRichTextV2';
|
||||
import { isFieldRichTextValue } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValue';
|
||||
import { isFieldRichTextV2Value } from '@/object-record/record-field/ui/types/guards/isFieldRichTextValueV2';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { getForeignKeyNameFromRelationFieldName } from '@/object-record/utils/getForeignKeyNameFromRelationFieldName';
|
||||
import { computeMorphRelationFieldName, isDefined } from 'twenty-shared/utils';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
@@ -72,11 +74,13 @@ export const usePersistField = ({
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: objectMetadataItem?.nameSingular ?? '',
|
||||
});
|
||||
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const persistField = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
({
|
||||
async ({
|
||||
recordId,
|
||||
fieldDefinition,
|
||||
valueToPersist,
|
||||
@@ -202,7 +206,7 @@ export const usePersistField = ({
|
||||
return;
|
||||
}
|
||||
|
||||
updateOneRecord?.({
|
||||
const newRecord = await updateOneRecord?.({
|
||||
idToUpdate: recordId,
|
||||
updateOneRecordInput: {
|
||||
[getForeignKeyNameFromRelationFieldName(fieldName)]:
|
||||
@@ -210,10 +214,11 @@ export const usePersistField = ({
|
||||
},
|
||||
});
|
||||
|
||||
set(
|
||||
recordStoreFamilySelector({ recordId, fieldName }),
|
||||
valueToPersist,
|
||||
);
|
||||
upsertRecordsInStore([
|
||||
getRecordFromRecordNode({
|
||||
recordNode: newRecord,
|
||||
}),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -263,19 +268,17 @@ export const usePersistField = ({
|
||||
candidateObjectMetadataItem.namePlural,
|
||||
});
|
||||
|
||||
updateOneRecord?.({
|
||||
const newRecord = await updateOneRecord?.({
|
||||
idToUpdate: recordId,
|
||||
updateOneRecordInput: {
|
||||
[`${computedFieldName}Id`]: valueToPersist.id,
|
||||
},
|
||||
});
|
||||
set(
|
||||
recordStoreFamilySelector({
|
||||
recordId,
|
||||
fieldName: computedFieldName,
|
||||
upsertRecordsInStore([
|
||||
getRecordFromRecordNode({
|
||||
recordNode: newRecord,
|
||||
}),
|
||||
valueToPersist,
|
||||
);
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -310,6 +313,7 @@ export const usePersistField = ({
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
updateOneRecord,
|
||||
upsertRecordsInStore,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ export const useLoadRecordIndexBoardColumn = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
const { setRecordIdsForColumn } = useSetRecordIdsForColumn(recordBoardId);
|
||||
const { upsertRecords: upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const recordGroupDefinition = useRecoilValue(
|
||||
recordGroupDefinitionFamilyState(columnId),
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ export const useMergePreview = ({
|
||||
const { mergeManyRecords } = useMergeManyRecords({
|
||||
objectNameSingular,
|
||||
});
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { isLoading: isLoadingRelationships } = useMergeRecordRelationships({
|
||||
objectNameSingular,
|
||||
@@ -56,7 +56,7 @@ export const useMergePreview = ({
|
||||
}
|
||||
|
||||
setMergePreviewRecord(previewRecord);
|
||||
upsertRecords([previewRecord]);
|
||||
upsertRecordsInStore([previewRecord]);
|
||||
} catch {
|
||||
setMergePreviewRecord(null);
|
||||
} finally {
|
||||
|
||||
+4
-3
@@ -2,9 +2,10 @@ import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useUpsertRecordsInStore = () => {
|
||||
const upsertRecords = useRecoilCallback(
|
||||
const upsertRecordsInStore = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(records: ObjectRecord[]) => {
|
||||
for (const record of records) {
|
||||
@@ -12,7 +13,7 @@ export const useUpsertRecordsInStore = () => {
|
||||
.getLoadable(recordStoreFamilyState(record.id))
|
||||
.getValue();
|
||||
|
||||
if (JSON.stringify(currentRecord) !== JSON.stringify(record)) {
|
||||
if (!isDeeplyEqual(currentRecord, record)) {
|
||||
set(recordStoreFamilyState(record.id), {
|
||||
...currentRecord,
|
||||
...record,
|
||||
@@ -24,6 +25,6 @@ export const useUpsertRecordsInStore = () => {
|
||||
);
|
||||
|
||||
return {
|
||||
upsertRecords,
|
||||
upsertRecordsInStore,
|
||||
};
|
||||
};
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
|
||||
import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
|
||||
import { RecordTableActionRow } from '@/object-record/record-table/record-table-row/components/RecordTableActionRow';
|
||||
import { useAssignRecordsToStore } from '@/object-record/record-table/virtualization/hooks/useAssignRecordsToStore';
|
||||
import { useLoadRecordsToVirtualRows } from '@/object-record/record-table/virtualization/hooks/useLoadRecordsToVirtualRows';
|
||||
import { totalNumberOfRecordsToVirtualizeComponentState } from '@/object-record/record-table/virtualization/states/totalNumberOfRecordsToVirtualizeComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
@@ -34,7 +34,7 @@ export const RecordTableNoRecordGroupAddNew = () => {
|
||||
);
|
||||
|
||||
const { loadRecordsToVirtualRows } = useLoadRecordsToVirtualRows();
|
||||
const { assignRecordsToStore } = useAssignRecordsToStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const handleButtonClick = useRecoilCallback(
|
||||
() => async () => {
|
||||
@@ -42,7 +42,7 @@ export const RecordTableNoRecordGroupAddNew = () => {
|
||||
position: 'last',
|
||||
});
|
||||
|
||||
assignRecordsToStore({ records: [createdRecord] });
|
||||
upsertRecordsInStore([createdRecord]);
|
||||
|
||||
if (isDefined(totalNumberOfRecordsToVirtualize)) {
|
||||
loadRecordsToVirtualRows({
|
||||
@@ -53,7 +53,7 @@ export const RecordTableNoRecordGroupAddNew = () => {
|
||||
},
|
||||
[
|
||||
createNewIndexRecord,
|
||||
assignRecordsToStore,
|
||||
upsertRecordsInStore,
|
||||
loadRecordsToVirtualRows,
|
||||
totalNumberOfRecordsToVirtualize,
|
||||
],
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useAssignRecordsToStore = () => {
|
||||
const assignRecordsToStore = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
<T extends ObjectRecord>({ records }: { records: T[] }) => {
|
||||
for (const record of records) {
|
||||
const currentRecord = snapshot
|
||||
.getLoadable(recordStoreFamilyState(record.id))
|
||||
.getValue();
|
||||
|
||||
if (!isDeeplyEqual(currentRecord, record)) {
|
||||
const newRecord = {
|
||||
...currentRecord,
|
||||
...record,
|
||||
};
|
||||
|
||||
set(recordStoreFamilyState(record.id), newRecord);
|
||||
}
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return {
|
||||
assignRecordsToStore,
|
||||
};
|
||||
};
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { useLazyFindManyRecordsWithOffset } from '@/object-record/hooks/useLazyFindManyRecordsWithOffset';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { RECORD_TABLE_ROW_HEIGHT } from '@/object-record/record-table/constants/RecordTableRowHeight';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { useAssignRecordsToStore } from '@/object-record/record-table/virtualization/hooks/useAssignRecordsToStore';
|
||||
import { useLoadRecordsToVirtualRows } from '@/object-record/record-table/virtualization/hooks/useLoadRecordsToVirtualRows';
|
||||
|
||||
import { dataPagesLoadedComponentState } from '@/object-record/record-table/virtualization/states/dataPagesLoadedComponentState';
|
||||
@@ -30,7 +30,7 @@ export const useTriggerFetchPages = () => {
|
||||
const { objectNameSingular } = useRecordTableContextOrThrow();
|
||||
const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement();
|
||||
|
||||
const { assignRecordsToStore } = useAssignRecordsToStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { loadRecordsToVirtualRows } = useLoadRecordsToVirtualRows();
|
||||
|
||||
@@ -193,7 +193,7 @@ export const useTriggerFetchPages = () => {
|
||||
startingRealIndex: startingRealIndexInThisUIPage,
|
||||
});
|
||||
|
||||
assignRecordsToStore({ records: recordsSlice });
|
||||
upsertRecordsInStore(recordsSlice);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ export const useTriggerFetchPages = () => {
|
||||
findManyRecordsLazyWithOffset,
|
||||
totalNumberOfRecordsToVirtualizeCallbackState,
|
||||
loadRecordsToVirtualRows,
|
||||
assignRecordsToStore,
|
||||
upsertRecordsInStore,
|
||||
lastScrollPositionCallbackState,
|
||||
scrollWrapperHTMLElement,
|
||||
lowDetailsActivatedCallbackState,
|
||||
|
||||
+4
-4
@@ -1,5 +1,6 @@
|
||||
import { useRecordIndexTableFetchMore } from '@/object-record/record-index/hooks/useRecordIndexTableFetchMore';
|
||||
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { RECORD_TABLE_HORIZONTAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableHorizontalScrollShadowVisibilityCssVariableName';
|
||||
import { RECORD_TABLE_VERTICAL_SCROLL_SHADOW_VISIBILITY_CSS_VARIABLE_NAME } from '@/object-record/record-table/constants/RecordTableVerticalScrollShadowVisibilityCssVariableName';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
@@ -8,7 +9,6 @@ import { isRecordTableInitialLoadingComponentState } from '@/object-record/recor
|
||||
import { isRecordTableScrolledHorizontallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledHorizontallyComponentState';
|
||||
import { isRecordTableScrolledVerticallyComponentState } from '@/object-record/record-table/states/isRecordTableScrolledVerticallyComponentState';
|
||||
import { updateRecordTableCSSVariable } from '@/object-record/record-table/utils/updateRecordTableCSSVariable';
|
||||
import { useAssignRecordsToStore } from '@/object-record/record-table/virtualization/hooks/useAssignRecordsToStore';
|
||||
import { useLoadRecordsToVirtualRows } from '@/object-record/record-table/virtualization/hooks/useLoadRecordsToVirtualRows';
|
||||
import { useReapplyRowSelection } from '@/object-record/record-table/virtualization/hooks/useReapplyRowSelection';
|
||||
import { useResetNumberOfRecordsToVirtualize } from '@/object-record/record-table/virtualization/hooks/useResetNumberOfRecordsToVirtualize';
|
||||
@@ -92,7 +92,7 @@ export const useTriggerInitialRecordTableDataLoad = () => {
|
||||
useResetNumberOfRecordsToVirtualize();
|
||||
|
||||
const { resetTableFocuses } = useResetTableFocuses(recordTableId);
|
||||
const { assignRecordsToStore } = useAssignRecordsToStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { loadRecordsToVirtualRows } = useLoadRecordsToVirtualRows();
|
||||
|
||||
@@ -165,7 +165,7 @@ export const useTriggerInitialRecordTableDataLoad = () => {
|
||||
totalCount,
|
||||
});
|
||||
|
||||
assignRecordsToStore({ records });
|
||||
upsertRecordsInStore(records);
|
||||
|
||||
loadRecordsToVirtualRows({
|
||||
records,
|
||||
@@ -210,7 +210,7 @@ export const useTriggerInitialRecordTableDataLoad = () => {
|
||||
dataLoadingStatusByRealIndexCallbackState,
|
||||
recordIdByRealIndexCallbackState,
|
||||
resetNumberOfRecordsToVirtualize,
|
||||
assignRecordsToStore,
|
||||
upsertRecordsInStore,
|
||||
loadRecordsToVirtualRows,
|
||||
reapplyRowSelection,
|
||||
],
|
||||
|
||||
-13
@@ -157,19 +157,6 @@ export const computeOptimisticRecordFromInput = ({
|
||||
continue;
|
||||
}
|
||||
|
||||
const relationIdFieldMetadataItem = objectMetadataItem.fields.find(
|
||||
(field) => field.name === relationFieldIdName,
|
||||
);
|
||||
|
||||
if (
|
||||
!isDefined(relationIdFieldMetadataItem) &&
|
||||
!isDefined(fieldMetadataItem.settings?.joinColumnName)
|
||||
) {
|
||||
throw new Error(
|
||||
'Should never occur, encountered unknown relationId within relations definitions',
|
||||
);
|
||||
}
|
||||
|
||||
if (isNull(recordInputFieldIdValue)) {
|
||||
optimisticRecord[relationFieldIdName] = null;
|
||||
optimisticRecord[fieldMetadataItem.name] = null;
|
||||
|
||||
+4
@@ -8,6 +8,7 @@ import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNo
|
||||
import { updateRecordFromCache } from '@/object-record/cache/utils/updateRecordFromCache';
|
||||
import { useGenerateDepthRecordGqlFieldsFromObject } from '@/object-record/graphql/record-gql-fields/hooks/useGenerateDepthRecordGqlFieldsFromObject';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { useOnDbEvent } from '@/subscription/hooks/useOnDbEvent';
|
||||
@@ -49,6 +50,7 @@ export const ListenRecordUpdatesEffect = ({
|
||||
},
|
||||
[],
|
||||
);
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
useOnDbEvent({
|
||||
input: { recordId, action: DatabaseEventAction.UPDATED },
|
||||
@@ -89,6 +91,8 @@ export const ListenRecordUpdatesEffect = ({
|
||||
currentRecord: cachedRecordNode,
|
||||
updatedRecord: updatedRecord,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
setRecordInStore(computedOptimisticRecord);
|
||||
|
||||
+3
-71
@@ -1,34 +1,15 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
|
||||
import { triggerDestroyRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerDestroyRecordsOptimisticEffect';
|
||||
import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { CREATE_CORE_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/createCoreViewFilterGroup';
|
||||
import { DESTROY_CORE_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/destroyCoreViewFilterGroup';
|
||||
import { UPDATE_CORE_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/updateCoreViewFilterGroup';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { type ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { isNull } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewFilterGroup } from '~/generated/graphql';
|
||||
|
||||
export const usePersistViewFilterGroupRecords = () => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: CoreObjectNameSingular.ViewFilterGroup,
|
||||
});
|
||||
|
||||
const getRecordFromCache = useGetRecordFromCache({
|
||||
objectNameSingular: CoreObjectNameSingular.ViewFilterGroup,
|
||||
});
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const createCoreViewFilterGroupRecord = useCallback(
|
||||
@@ -47,18 +28,6 @@ export const usePersistViewFilterGroupRecords = () => {
|
||||
viewFilterGroup.positionInViewFilterGroup,
|
||||
} satisfies Partial<CoreViewFilterGroup>,
|
||||
},
|
||||
update: (cache, { data }) => {
|
||||
const record = data?.createCoreViewFilterGroup;
|
||||
if (!isDefined(record)) return;
|
||||
|
||||
triggerCreateRecordsOptimisticEffect({
|
||||
cache,
|
||||
objectMetadataItem,
|
||||
recordsToCreate: [record],
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
if (!result.data) {
|
||||
@@ -67,12 +36,7 @@ export const usePersistViewFilterGroupRecords = () => {
|
||||
|
||||
return { newRecordId: result.data.createCoreViewFilterGroup.id };
|
||||
},
|
||||
[
|
||||
apolloClient,
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
],
|
||||
[apolloClient],
|
||||
);
|
||||
|
||||
const createCoreViewFilterGroupRecords = useCallback(
|
||||
@@ -133,29 +97,11 @@ export const usePersistViewFilterGroupRecords = () => {
|
||||
viewFilterGroup.positionInViewFilterGroup,
|
||||
} satisfies Partial<CoreViewFilterGroup>,
|
||||
},
|
||||
update: (cache, { data }) => {
|
||||
const record = data?.updateCoreViewFilterGroup;
|
||||
if (!isDefined(record)) return;
|
||||
|
||||
const cachedRecord = getRecordFromCache<ViewFilterGroup>(
|
||||
record.id,
|
||||
cache,
|
||||
);
|
||||
if (isNull(cachedRecord)) return;
|
||||
|
||||
triggerUpdateRecordOptimisticEffect({
|
||||
cache,
|
||||
objectMetadataItem,
|
||||
currentRecord: cachedRecord,
|
||||
updatedRecord: record,
|
||||
objectMetadataItems,
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
[apolloClient, getRecordFromCache, objectMetadataItem, objectMetadataItems],
|
||||
[apolloClient],
|
||||
);
|
||||
|
||||
const deleteCoreViewFilterGroupRecords = useCallback(
|
||||
@@ -168,25 +114,11 @@ export const usePersistViewFilterGroupRecords = () => {
|
||||
variables: {
|
||||
id: viewFilterGroupId,
|
||||
},
|
||||
update: (cache, { data }) => {
|
||||
const record = data?.destroyCoreViewFilterGroup;
|
||||
if (!isDefined(record)) return;
|
||||
|
||||
const cachedRecord = getRecordFromCache(record.id, cache);
|
||||
if (isNull(cachedRecord)) return;
|
||||
|
||||
triggerDestroyRecordsOptimisticEffect({
|
||||
cache,
|
||||
objectMetadataItem,
|
||||
recordsToDestroy: [cachedRecord],
|
||||
objectMetadataItems,
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
[apolloClient, getRecordFromCache, objectMetadataItem, objectMetadataItems],
|
||||
[apolloClient],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+6
@@ -6,6 +6,12 @@ export const CREATE_DRAFT_FROM_WORKFLOW_VERSION = gql`
|
||||
) {
|
||||
createDraftFromWorkflowVersion(input: $input) {
|
||||
id
|
||||
name
|
||||
status
|
||||
trigger
|
||||
steps
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -3,8 +3,11 @@ import { useMutation } from '@apollo/client';
|
||||
import { triggerUpdateRecordOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRecordOptimisticEffect';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { ACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/mutations/activateWorkflowVersion';
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -21,11 +24,15 @@ export const useActivateWorkflowVersion = () => {
|
||||
>(ACTIVATE_WORKFLOW_VERSION, {
|
||||
client: apolloCoreClient,
|
||||
});
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { objectMetadataItem: objectMetadataItemWorkflowVersion } =
|
||||
useObjectMetadataItem({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
});
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
|
||||
const activateWorkflowVersion = async ({
|
||||
workflowVersionId,
|
||||
@@ -75,7 +82,9 @@ export const useActivateWorkflowVersion = () => {
|
||||
...newlyActiveWorkflowVersion,
|
||||
status: 'ACTIVE',
|
||||
},
|
||||
objectMetadataItems: [objectMetadataItemWorkflowVersion],
|
||||
objectMetadataItems: objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,7 +109,9 @@ export const useActivateWorkflowVersion = () => {
|
||||
...workflowVersion,
|
||||
status: 'ARCHIVED',
|
||||
},
|
||||
objectMetadataItems: [objectMetadataItemWorkflowVersion],
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,6 +5,8 @@ import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { DEACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/mutations/deactivateWorkflowVersion';
|
||||
import { type WorkflowVersion } from '@/workflow/types/Workflow';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -12,9 +14,12 @@ import {
|
||||
type DeactivateWorkflowVersionMutation,
|
||||
type DeactivateWorkflowVersionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
|
||||
export const useDeactivateWorkflowVersion = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const [mutate] = useMutation<
|
||||
DeactivateWorkflowVersionMutation,
|
||||
DeactivateWorkflowVersionMutationVariables
|
||||
@@ -22,6 +27,8 @@ export const useDeactivateWorkflowVersion = () => {
|
||||
client: apolloCoreClient,
|
||||
});
|
||||
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { objectMetadataItem: objectMetadataItemWorkflowVersion } =
|
||||
useObjectMetadataItem({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
@@ -67,7 +74,9 @@ export const useDeactivateWorkflowVersion = () => {
|
||||
...workflowVersion,
|
||||
status: 'DEACTIVATED',
|
||||
},
|
||||
objectMetadataItems: [objectMetadataItemWorkflowVersion],
|
||||
objectMetadataItems,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { useGenerateDepthRecordGqlFieldsFromObject } from '@/object-record/graphql/record-gql-fields/hooks/useGenerateDepthRecordGqlFieldsFromObject';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { computeOptimisticCreateRecordBaseRecordInput } from '@/object-record/utils/computeOptimisticCreateRecordBaseRecordInput';
|
||||
import { computeOptimisticRecordFromInput } from '@/object-record/utils/computeOptimisticRecordFromInput';
|
||||
@@ -27,6 +28,7 @@ import {
|
||||
|
||||
export const useRunWorkflowVersion = () => {
|
||||
const apolloCoreClient = useApolloCoreClient();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowRun,
|
||||
@@ -128,6 +130,7 @@ export const useRunWorkflowVersion = () => {
|
||||
objectMetadataItems,
|
||||
shouldMatchRootQueryFilter: true,
|
||||
objectPermissionsByObjectMetadataId,
|
||||
upsertRecordsInStore,
|
||||
});
|
||||
|
||||
setRecordInStore(recordCreatedInCache);
|
||||
|
||||
@@ -2,16 +2,21 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import {
|
||||
type Workflow,
|
||||
type WorkflowVersion,
|
||||
type WorkflowWithCurrentVersion,
|
||||
} from '@/workflow/types/Workflow';
|
||||
import { useMemo } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type WorkflowWithAllVersions = Omit<Workflow, 'versions'> & {
|
||||
versions: Array<
|
||||
Pick<WorkflowVersion, 'id' | 'status' | 'name' | 'createdAt'>
|
||||
>;
|
||||
};
|
||||
|
||||
export const useWorkflowWithCurrentVersion = (
|
||||
workflowId: string | undefined,
|
||||
): WorkflowWithCurrentVersion | undefined => {
|
||||
// TODO: we should only load the data for the current version
|
||||
const { record: workflow } = useFindOneRecord<Workflow>({
|
||||
const { record: workflow } = useFindOneRecord<WorkflowWithAllVersions>({
|
||||
objectNameSingular: CoreObjectNameSingular.Workflow,
|
||||
objectRecordId: workflowId,
|
||||
recordGqlFields: {
|
||||
@@ -23,41 +28,38 @@ export const useWorkflowWithCurrentVersion = (
|
||||
id: true,
|
||||
status: true,
|
||||
name: true,
|
||||
steps: true,
|
||||
trigger: true,
|
||||
workflowId: true,
|
||||
deletedAt: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
},
|
||||
skip: !isDefined(workflowId),
|
||||
});
|
||||
|
||||
return useMemo(() => {
|
||||
if (!isDefined(workflow)) {
|
||||
return undefined;
|
||||
}
|
||||
const draftVersion = workflow?.versions.find(
|
||||
(workflowVersion) => workflowVersion.status === 'DRAFT',
|
||||
);
|
||||
|
||||
const draftVersion = workflow.versions.find(
|
||||
(workflowVersion) => workflowVersion.status === 'DRAFT',
|
||||
);
|
||||
const workflowVersions = [...(workflow?.versions ?? [])];
|
||||
|
||||
const workflowVersions = [...workflow.versions];
|
||||
workflowVersions.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
||||
|
||||
workflowVersions.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
||||
const latestVersion = workflowVersions[0];
|
||||
|
||||
const latestVersion = workflowVersions[0];
|
||||
const currentVersionWithoutSteps = draftVersion ?? latestVersion;
|
||||
|
||||
const currentVersion = draftVersion ?? latestVersion;
|
||||
const { record: currentVersionWithSteps } = useFindOneRecord<WorkflowVersion>(
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
objectRecordId: currentVersionWithoutSteps?.id,
|
||||
skip: !isDefined(currentVersionWithoutSteps?.id),
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDefined(currentVersion)) {
|
||||
return undefined;
|
||||
}
|
||||
if (!isDefined(workflow) || !isDefined(currentVersionWithSteps)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
...workflow,
|
||||
currentVersion,
|
||||
};
|
||||
}, [workflow]);
|
||||
return {
|
||||
...workflow,
|
||||
currentVersion: currentVersionWithSteps,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -131,7 +131,9 @@ export type Workflow = {
|
||||
__typename: 'Workflow';
|
||||
id: string;
|
||||
name: string;
|
||||
versions: Array<WorkflowVersion>;
|
||||
versions: Array<
|
||||
Pick<WorkflowVersion, 'id' | 'status' | 'name' | 'createdAt'>
|
||||
>;
|
||||
lastPublishedVersionId: string;
|
||||
statuses: Array<WorkflowStatus> | null;
|
||||
};
|
||||
|
||||
+4
-5
@@ -38,6 +38,8 @@ export const WorkflowDiagramEffect = () => {
|
||||
workflowLastCreatedStepIdComponentState,
|
||||
);
|
||||
|
||||
const currentVersion = workflowWithCurrentVersion?.currentVersion;
|
||||
|
||||
const computeAndMergeNewWorkflowDiagram = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
return (currentVersion: WorkflowVersion) => {
|
||||
@@ -84,13 +86,10 @@ export const WorkflowDiagramEffect = () => {
|
||||
[workflowDiagramState, workflowLastCreatedStepIdState],
|
||||
);
|
||||
|
||||
const currentVersion = workflowWithCurrentVersion?.currentVersion;
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(currentVersion)) {
|
||||
setFlow(undefined);
|
||||
setWorkflowDiagram(undefined);
|
||||
|
||||
// setFlow(undefined);
|
||||
// setWorkflowDiagram(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { useEffect } from 'react';
|
||||
import { type Decorator } from '@storybook/react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
|
||||
|
||||
export const RecordStoreDecorator: Decorator = (Story, context) => {
|
||||
const { records } = context.parameters;
|
||||
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
useEffect(() => {
|
||||
upsertRecords(records);
|
||||
upsertRecordsInStore(records);
|
||||
});
|
||||
|
||||
return <Story />;
|
||||
|
||||
@@ -10,10 +10,10 @@ export const JestRecordStoreSetter = ({
|
||||
children: ReactNode;
|
||||
records: ObjectRecord[];
|
||||
}) => {
|
||||
const { upsertRecords } = useUpsertRecordsInStore();
|
||||
const { upsertRecordsInStore } = useUpsertRecordsInStore();
|
||||
|
||||
useEffect(() => {
|
||||
upsertRecords(records);
|
||||
upsertRecordsInStore(records);
|
||||
});
|
||||
|
||||
return <>{children}</>;
|
||||
|
||||
+28
-2
@@ -1,9 +1,35 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
@ObjectType('WorkflowVersion')
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { WorkflowVersionStatus } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
|
||||
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
|
||||
|
||||
@ObjectType('WorkflowVersionDTO')
|
||||
export class WorkflowVersionDTO {
|
||||
@Field(() => UUIDScalarType)
|
||||
id: string;
|
||||
|
||||
@Field(() => String)
|
||||
name: string;
|
||||
|
||||
@Field(() => String)
|
||||
createdAt: string;
|
||||
|
||||
@Field(() => String)
|
||||
updatedAt: string;
|
||||
|
||||
@Field(() => UUIDScalarType)
|
||||
workflowId: string;
|
||||
|
||||
@Field(() => String)
|
||||
status: WorkflowVersionStatus;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
trigger: WorkflowTrigger | null;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
steps: WorkflowAction[] | null;
|
||||
}
|
||||
|
||||
+6
-10
@@ -4,6 +4,7 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql';
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { CreateDraftFromWorkflowVersionInput } from 'src/engine/core-modules/workflow/dtos/create-draft-from-workflow-version-input.dto';
|
||||
import { UpdateWorkflowVersionPositionsInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-version-positions-input.dto';
|
||||
import { WorkflowVersionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-version.dto';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
@@ -13,7 +14,6 @@ import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
|
||||
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
|
||||
import { WorkflowVersionWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version/workflow-version.workspace-service';
|
||||
import { UpdateWorkflowVersionPositionsInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-version-positions-input.dto';
|
||||
|
||||
@Resolver()
|
||||
@UsePipes(ResolverValidationPipe)
|
||||
@@ -40,15 +40,11 @@ export class WorkflowVersionResolver {
|
||||
workflowVersionIdToCopy,
|
||||
}: CreateDraftFromWorkflowVersionInput,
|
||||
): Promise<WorkflowVersionDTO> {
|
||||
return {
|
||||
id: await this.workflowVersionWorkspaceService.createDraftFromWorkflowVersion(
|
||||
{
|
||||
workspaceId,
|
||||
workflowId,
|
||||
workflowVersionIdToCopy,
|
||||
},
|
||||
),
|
||||
};
|
||||
return this.workflowVersionWorkspaceService.createDraftFromWorkflowVersion({
|
||||
workspaceId,
|
||||
workflowId,
|
||||
workflowVersionIdToCopy,
|
||||
});
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean)
|
||||
|
||||
+5
-1
@@ -115,7 +115,11 @@ export class WorkflowVersionWorkspaceService {
|
||||
trigger: newWorkflowVersionTrigger,
|
||||
});
|
||||
|
||||
return draftWorkflowVersion.id;
|
||||
return {
|
||||
...draftWorkflowVersion,
|
||||
steps: newWorkflowVersionSteps,
|
||||
trigger: newWorkflowVersionTrigger,
|
||||
};
|
||||
}
|
||||
|
||||
async updateWorkflowVersionPositions({
|
||||
|
||||
Reference in New Issue
Block a user