Fix tasks (#5199)
## Query depth deprecation I'm deprecating depth parameter in our graphql query / cache tooling. They were obsolete since we introduce the possibility to provide RecordGqlFields ## Refactor combinedFindManyRecordHook The hook can now take an array of operationSignatures ## Fix tasks issues Fix optimistic rendering issue. Note that we still haven't handle optimisticEffect on creation properly
This commit is contained in:
@ -1 +0,0 @@
|
||||
export const MAX_QUERY_DEPTH_FOR_CACHE_INJECTION = 1;
|
||||
@ -7,6 +7,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { prefillRecord } from '@/object-record/utils/prefillRecord';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
@ -32,13 +33,15 @@ export const useCreateOneRecordInCache = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
computeReferences: true,
|
||||
recordGqlFields: generateDepthOneRecordGqlFields({
|
||||
objectMetadataItem,
|
||||
}),
|
||||
})}
|
||||
`;
|
||||
|
||||
const prefilledRecord = prefillRecord({
|
||||
objectMetadataItem,
|
||||
input: record,
|
||||
depth: 1,
|
||||
});
|
||||
|
||||
const recordToCreateWithNestedConnections = getRecordNodeFromRecord({
|
||||
|
||||
@ -5,33 +5,46 @@ import { useRecoilValue } from 'recoil';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
export const useGetRecordFromCache = ({
|
||||
objectNameSingular,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
recordGqlFields?: RecordGqlFields;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const appliedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
return useCallback(
|
||||
<CachedObjectRecord extends ObjectRecord = ObjectRecord>(
|
||||
<T extends ObjectRecord = ObjectRecord>(
|
||||
recordId: string,
|
||||
cache = apolloClient.cache,
|
||||
) => {
|
||||
return getRecordFromCache<CachedObjectRecord>({
|
||||
return getRecordFromCache<T>({
|
||||
cache,
|
||||
recordId,
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
recordGqlFields: appliedRecordGqlFields,
|
||||
});
|
||||
},
|
||||
[objectMetadataItem, objectMetadataItems, apolloClient],
|
||||
[
|
||||
apolloClient.cache,
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
appliedRecordGqlFields,
|
||||
],
|
||||
);
|
||||
};
|
||||
|
||||
@ -3,9 +3,9 @@ import { useApolloClient } from '@apollo/client';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordQueryResult } from '@/object-record/types/ObjectRecordQueryResult';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -22,32 +22,28 @@ export const useReadFindManyRecordsQueryInCache = ({
|
||||
T extends ObjectRecord = ObjectRecord,
|
||||
>({
|
||||
queryVariables,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
queryVariables: ObjectRecordQueryVariables;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
queryVariables: RecordGqlOperationVariables;
|
||||
recordGqlFields?: Record<string, any>;
|
||||
}) => {
|
||||
const findManyRecordsQueryForCacheRead = generateFindManyRecordsQuery({
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
});
|
||||
|
||||
const existingRecordsQueryResult = apolloClient.readQuery<
|
||||
ObjectRecordQueryResult<T>
|
||||
>({
|
||||
query: findManyRecordsQueryForCacheRead,
|
||||
variables: queryVariables,
|
||||
});
|
||||
const existingRecordsQueryResult =
|
||||
apolloClient.readQuery<RecordGqlOperationFindManyResult>({
|
||||
query: findManyRecordsQueryForCacheRead,
|
||||
variables: queryVariables,
|
||||
});
|
||||
|
||||
const existingRecordConnection =
|
||||
existingRecordsQueryResult?.[objectMetadataItem.namePlural];
|
||||
|
||||
const existingObjectRecords = isDefined(existingRecordConnection)
|
||||
? getRecordsFromRecordConnection({
|
||||
? getRecordsFromRecordConnection<T>({
|
||||
recordConnection: existingRecordConnection,
|
||||
})
|
||||
: [];
|
||||
|
||||
@ -3,10 +3,9 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { MAX_QUERY_DEPTH_FOR_CACHE_INJECTION } from '@/object-record/cache/constants/MaxQueryDepthForCacheInjection';
|
||||
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
|
||||
|
||||
export const useUpsertFindManyRecordsQueryInCache = ({
|
||||
@ -22,22 +21,19 @@ export const useUpsertFindManyRecordsQueryInCache = ({
|
||||
T extends ObjectRecord = ObjectRecord,
|
||||
>({
|
||||
queryVariables,
|
||||
depth = MAX_QUERY_DEPTH_FOR_CACHE_INJECTION,
|
||||
objectRecordsToOverwrite,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
computeReferences = false,
|
||||
}: {
|
||||
queryVariables: ObjectRecordQueryVariables;
|
||||
depth?: number;
|
||||
queryVariables: RecordGqlOperationVariables;
|
||||
objectRecordsToOverwrite: T[];
|
||||
queryFields?: Record<string, any>;
|
||||
recordGqlFields?: Record<string, any>;
|
||||
computeReferences?: boolean;
|
||||
}) => {
|
||||
const findManyRecordsQueryForCacheOverwrite = generateFindManyRecordsQuery({
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
depth,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
});
|
||||
|
||||
@ -45,7 +41,7 @@ export const useUpsertFindManyRecordsQueryInCache = ({
|
||||
objectMetadataItems: objectMetadataItems,
|
||||
objectMetadataItem: objectMetadataItem,
|
||||
records: objectRecordsToOverwrite,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
});
|
||||
|
||||
|
||||
6
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefConnection.ts
vendored
Normal file
6
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefConnection.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
|
||||
export type RecordGqlRefConnection = Omit<RecordGqlConnection, 'edges'> & {
|
||||
edges: RecordGqlRefEdge[];
|
||||
};
|
||||
6
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefEdge.ts
vendored
Normal file
6
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefEdge.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import { RecordGqlRefNode } from '@/object-record/cache/types/RecordGqlRefNode';
|
||||
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||
|
||||
export type RecordGqlRefEdge = Omit<RecordGqlEdge, 'node'> & {
|
||||
node: RecordGqlRefNode;
|
||||
};
|
||||
3
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefNode.ts
vendored
Normal file
3
packages/twenty-front/src/modules/object-record/cache/types/RecordGqlRefNode.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { Reference } from '@apollo/client';
|
||||
|
||||
export type RecordGqlRefNode = Reference;
|
||||
@ -2,18 +2,18 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getConnectionTypename } from '@/object-record/cache/utils/getConnectionTypename';
|
||||
import { getEmptyPageInfo } from '@/object-record/cache/utils/getEmptyPageInfo';
|
||||
import { getRecordEdgeFromRecord } from '@/object-record/cache/utils/getRecordEdgeFromRecord';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
|
||||
export const getRecordConnectionFromRecords = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
records,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
withPageInfo = true,
|
||||
computeReferences = false,
|
||||
isRootLevel = true,
|
||||
depth = 1,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectMetadataItem: Pick<
|
||||
@ -21,11 +21,10 @@ export const getRecordConnectionFromRecords = <T extends ObjectRecord>({
|
||||
'fields' | 'namePlural' | 'nameSingular'
|
||||
>;
|
||||
records: T[];
|
||||
queryFields?: Record<string, any>;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
withPageInfo?: boolean;
|
||||
isRootLevel?: boolean;
|
||||
computeReferences?: boolean;
|
||||
depth?: number;
|
||||
}) => {
|
||||
return {
|
||||
__typename: getConnectionTypename(objectMetadataItem.nameSingular),
|
||||
@ -33,14 +32,13 @@ export const getRecordConnectionFromRecords = <T extends ObjectRecord>({
|
||||
return getRecordEdgeFromRecord({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
record,
|
||||
isRootLevel,
|
||||
computeReferences,
|
||||
depth,
|
||||
});
|
||||
}),
|
||||
...(withPageInfo && { pageInfo: getEmptyPageInfo() }),
|
||||
...(withPageInfo && { totalCount: records.length }),
|
||||
} as ObjectRecordConnection<T>;
|
||||
} as RecordGqlConnection;
|
||||
};
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getEdgeTypename } from '@/object-record/cache/utils/getEdgeTypename';
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
|
||||
export const getRecordEdgeFromRecord = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
record,
|
||||
computeReferences = false,
|
||||
isRootLevel = false,
|
||||
@ -17,10 +17,9 @@ export const getRecordEdgeFromRecord = <T extends ObjectRecord>({
|
||||
ObjectMetadataItem,
|
||||
'fields' | 'namePlural' | 'nameSingular'
|
||||
>;
|
||||
queryFields?: Record<string, any>;
|
||||
recordGqlFields?: Record<string, any>;
|
||||
computeReferences?: boolean;
|
||||
isRootLevel?: boolean;
|
||||
depth?: number;
|
||||
record: T;
|
||||
}) => {
|
||||
return {
|
||||
@ -29,13 +28,12 @@ export const getRecordEdgeFromRecord = <T extends ObjectRecord>({
|
||||
...getRecordNodeFromRecord({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
record,
|
||||
computeReferences,
|
||||
isRootLevel,
|
||||
depth: 1,
|
||||
}),
|
||||
},
|
||||
cursor: '',
|
||||
} as ObjectRecordEdge<T>;
|
||||
} as RecordGqlEdge;
|
||||
};
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { ApolloCache, gql } from '@apollo/client';
|
||||
|
||||
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
@ -13,16 +14,21 @@ export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
cache,
|
||||
recordId,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
cache: ApolloCache<object>;
|
||||
recordId: string;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
recordGqlFields?: RecordGqlFields;
|
||||
}) => {
|
||||
if (isUndefinedOrNull(objectMetadataItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const appliedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
||||
|
||||
const cacheReadFragment = gql`
|
||||
@ -30,6 +36,7 @@ export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
|
||||
{
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
recordGqlFields: appliedRecordGqlFields,
|
||||
},
|
||||
)}
|
||||
`;
|
||||
@ -49,7 +56,7 @@ export const getRecordFromCache = <T extends ObjectRecord = ObjectRecord>({
|
||||
return null;
|
||||
}
|
||||
|
||||
return getRecordFromRecordNode({
|
||||
return getRecordFromRecordNode<T>({
|
||||
recordNode: record,
|
||||
}) as CachedObjectRecord<T>;
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
@ -6,7 +7,7 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
export const getRecordFromRecordNode = <T extends ObjectRecord>({
|
||||
recordNode,
|
||||
}: {
|
||||
recordNode: T;
|
||||
recordNode: RecordGqlNode;
|
||||
}): T => {
|
||||
return {
|
||||
...Object.fromEntries(
|
||||
@ -32,5 +33,6 @@ export const getRecordFromRecordNode = <T extends ObjectRecord>({
|
||||
}),
|
||||
),
|
||||
id: recordNode.id,
|
||||
__typename: recordNode.__typename,
|
||||
} as T;
|
||||
};
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { isNull, isUndefined } from '@sniptt/guards';
|
||||
|
||||
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getNodeTypename } from '@/object-record/cache/utils/getNodeTypename';
|
||||
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
|
||||
import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords';
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
@ -16,22 +16,20 @@ import { lowerAndCapitalize } from '~/utils/string/lowerAndCapitalize';
|
||||
export const getRecordNodeFromRecord = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
record,
|
||||
computeReferences = true,
|
||||
isRootLevel = true,
|
||||
depth = 1,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectMetadataItem: Pick<
|
||||
ObjectMetadataItem,
|
||||
'fields' | 'namePlural' | 'nameSingular'
|
||||
>;
|
||||
queryFields?: Record<string, any>;
|
||||
recordGqlFields?: Record<string, any>;
|
||||
computeReferences?: boolean;
|
||||
isRootLevel?: boolean;
|
||||
record: T | null;
|
||||
depth?: number;
|
||||
}) => {
|
||||
if (isNull(record)) {
|
||||
return null;
|
||||
@ -42,13 +40,13 @@ export const getRecordNodeFromRecord = <T extends ObjectRecord>({
|
||||
if (!isRootLevel && computeReferences) {
|
||||
return {
|
||||
__ref: `${nodeTypeName}:${record.id}`,
|
||||
} as unknown as CachedObjectRecord<T>; // Todo Fix typing
|
||||
} as unknown as RecordGqlNode; // Fix typing: we want a Reference in computeReferences mode
|
||||
}
|
||||
|
||||
const nestedRecord = Object.fromEntries(
|
||||
Object.entries(record)
|
||||
.map(([fieldName, value]) => {
|
||||
if (isDefined(queryFields) && !queryFields[fieldName]) {
|
||||
if (isDefined(recordGqlFields) && !recordGqlFields[fieldName]) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -60,14 +58,6 @@ export const getRecordNodeFromRecord = <T extends ObjectRecord>({
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
!isUndefined(depth) &&
|
||||
depth < 1 &&
|
||||
field.type === FieldMetadataType.Relation
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
field.type === FieldMetadataType.Relation &&
|
||||
field.relationDefinition?.direction ===
|
||||
@ -87,15 +77,14 @@ export const getRecordNodeFromRecord = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem: oneToManyObjectMetadataItem,
|
||||
records: value as ObjectRecord[],
|
||||
queryFields:
|
||||
queryFields?.[fieldName] === true ||
|
||||
isUndefined(queryFields?.[fieldName])
|
||||
recordGqlFields:
|
||||
recordGqlFields?.[fieldName] === true ||
|
||||
isUndefined(recordGqlFields?.[fieldName])
|
||||
? undefined
|
||||
: queryFields?.[fieldName],
|
||||
: recordGqlFields?.[fieldName],
|
||||
withPageInfo: false,
|
||||
isRootLevel: false,
|
||||
computeReferences,
|
||||
depth: depth - 1,
|
||||
}),
|
||||
];
|
||||
}
|
||||
@ -159,8 +148,5 @@ export const getRecordNodeFromRecord = <T extends ObjectRecord>({
|
||||
.filter(isDefined),
|
||||
) as T; // Todo fix typing once we have investigated apollo edges / nodes removal
|
||||
|
||||
return {
|
||||
__typename: getNodeTypename(objectMetadataItem.nameSingular),
|
||||
...nestedRecord,
|
||||
};
|
||||
return { ...nestedRecord, __typename: nodeTypeName };
|
||||
};
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
|
||||
export const getRecordsFromRecordConnection = <T extends ObjectRecord>({
|
||||
recordConnection,
|
||||
}: {
|
||||
recordConnection: ObjectRecordConnection<T>;
|
||||
recordConnection: RecordGqlConnection;
|
||||
}): T[] => {
|
||||
return recordConnection.edges.map((edge) =>
|
||||
getRecordFromRecordNode<T>({ recordNode: edge.node }),
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const isObjectRecordConnection = (
|
||||
objectNameSingular: string,
|
||||
value: unknown,
|
||||
): value is ObjectRecordConnection => {
|
||||
): value is RecordGqlConnection => {
|
||||
const objectConnectionTypeName = `${capitalize(
|
||||
objectNameSingular,
|
||||
)}Connection`;
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { StoreValue } from '@apollo/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { CachedObjectRecordConnection } from '@/apollo/types/CachedObjectRecordConnection';
|
||||
import { RecordGqlRefConnection } from '@/object-record/cache/types/RecordGqlRefConnection';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const isObjectRecordConnectionWithRefs = (
|
||||
objectNameSingular: string,
|
||||
storeValue: StoreValue,
|
||||
): storeValue is CachedObjectRecordConnection => {
|
||||
): storeValue is RecordGqlRefConnection => {
|
||||
const objectConnectionTypeName = `${capitalize(
|
||||
objectNameSingular,
|
||||
)}Connection`;
|
||||
|
||||
@ -4,6 +4,7 @@ import gql from 'graphql-tag';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
@ -44,14 +45,13 @@ export const updateRecordFromCache = <T extends ObjectRecord>({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
record,
|
||||
depth: 1,
|
||||
});
|
||||
|
||||
if (isUndefinedOrNull(recordWithConnection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.writeFragment<T & { __typename: string }>({
|
||||
cache.writeFragment<RecordGqlNode>({
|
||||
id: cachedRecordId,
|
||||
fragment: cacheWriteFragment,
|
||||
data: recordWithConnection,
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import { Nullable } from 'twenty-ui';
|
||||
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||
|
||||
export type ObjectRecordConnection<T extends ObjectRecord = ObjectRecord> = {
|
||||
export type RecordGqlConnection = {
|
||||
__typename?: string;
|
||||
edges: ObjectRecordEdge<T>[];
|
||||
edges: RecordGqlEdge[];
|
||||
pageInfo: {
|
||||
hasNextPage?: boolean;
|
||||
hasPreviousPage?: boolean;
|
||||
@ -0,0 +1,7 @@
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
|
||||
export type RecordGqlEdge = {
|
||||
__typename: string;
|
||||
node: RecordGqlNode;
|
||||
cursor: string;
|
||||
};
|
||||
@ -0,0 +1 @@
|
||||
export type RecordGqlFields = Record<string, any>;
|
||||
@ -0,0 +1,5 @@
|
||||
export type RecordGqlNode = {
|
||||
id: string;
|
||||
[key: string]: any;
|
||||
__typename: string;
|
||||
};
|
||||
@ -93,22 +93,22 @@ export type LeafFilter =
|
||||
| undefined;
|
||||
|
||||
export type AndObjectRecordFilter = {
|
||||
and?: ObjectRecordQueryFilter[];
|
||||
and?: RecordGqlOperationFilter[];
|
||||
};
|
||||
|
||||
export type OrObjectRecordFilter = {
|
||||
or?: ObjectRecordQueryFilter[] | ObjectRecordQueryFilter;
|
||||
or?: RecordGqlOperationFilter[] | RecordGqlOperationFilter;
|
||||
};
|
||||
|
||||
export type NotObjectRecordFilter = {
|
||||
not?: ObjectRecordQueryFilter;
|
||||
not?: RecordGqlOperationFilter;
|
||||
};
|
||||
|
||||
export type LeafObjectRecordFilter = {
|
||||
[fieldName: string]: LeafFilter;
|
||||
};
|
||||
|
||||
export type ObjectRecordQueryFilter =
|
||||
export type RecordGqlOperationFilter =
|
||||
| LeafObjectRecordFilter
|
||||
| AndObjectRecordFilter
|
||||
| OrObjectRecordFilter
|
||||
@ -0,0 +1,5 @@
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
|
||||
export type RecordGqlOperationFindManyResult = {
|
||||
[objectNamePlural: string]: RecordGqlConnection;
|
||||
};
|
||||
@ -0,0 +1,5 @@
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
|
||||
export type RecordGqlOperationFindOneResult = {
|
||||
[objectNameSingular: string]: RecordGqlNode;
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
import { RecordGqlFields } from '@/object-record/graphql/types/RecordGqlFields';
|
||||
|
||||
export type RecordGqlOperationGqlRecordFields = RecordGqlFields;
|
||||
@ -0,0 +1,5 @@
|
||||
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
||||
|
||||
export type RecordGqlOperationOrderBy = {
|
||||
[fieldName: string]: OrderBy | { [subFieldName: string]: OrderBy };
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
|
||||
export type RecordGqlOperationSignature = {
|
||||
objectNameSingular: string;
|
||||
variables: RecordGqlOperationVariables;
|
||||
fields?: RecordGqlOperationGqlRecordFields;
|
||||
};
|
||||
@ -0,0 +1,5 @@
|
||||
import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature';
|
||||
|
||||
export type RecordGqlOperationSignatureFactory = (
|
||||
factoryParams: any,
|
||||
) => RecordGqlOperationSignature;
|
||||
@ -0,0 +1,8 @@
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
|
||||
|
||||
export type RecordGqlOperationVariables = {
|
||||
filter?: RecordGqlOperationFilter;
|
||||
orderBy?: RecordGqlOperationOrderBy;
|
||||
limit?: number;
|
||||
};
|
||||
@ -0,0 +1,14 @@
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export const generateDepthOneRecordGqlFields = ({
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}) => {
|
||||
return objectMetadataItem.fields.reduce((acc, field) => {
|
||||
return {
|
||||
...acc,
|
||||
[field.name]: true,
|
||||
};
|
||||
}, {});
|
||||
};
|
||||
@ -1,22 +1,29 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { expect } from '@storybook/test';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
||||
import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter';
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
<RecoilRoot>
|
||||
<JestObjectMetadataItemSetter>{children}</JestObjectMetadataItemSetter>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useGenerateFindManyRecordsForMultipleMetadataItemsQuery', () => {
|
||||
it('should work as expected', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const mockObjectMetadataItems = getObjectMetadataItemsMock();
|
||||
|
||||
return useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
|
||||
targetObjectMetadataItems: mockObjectMetadataItems.slice(0, 2),
|
||||
return useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures: getObjectMetadataItemsMock()
|
||||
.slice(0, 2)
|
||||
.map((item) => ({
|
||||
objectNameSingular: item.nameSingular,
|
||||
variables: {},
|
||||
})),
|
||||
});
|
||||
},
|
||||
{
|
||||
|
||||
@ -2,10 +2,12 @@ import { useApolloClient } from '@apollo/client';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
|
||||
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { useCreateOneRecordInCache } from '@/object-record/cache/hooks/useCreateOneRecordInCache';
|
||||
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { useCreateManyRecordsMutation } from '@/object-record/hooks/useCreateManyRecordsMutation';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getCreateManyRecordsMutationResponseField } from '@/object-record/utils/getCreateManyRecordsMutationResponseField';
|
||||
@ -14,8 +16,7 @@ import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type useCreateManyRecordsProps = {
|
||||
objectNameSingular: string;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
skipPostOptmisticEffect?: boolean;
|
||||
};
|
||||
|
||||
@ -23,8 +24,7 @@ export const useCreateManyRecords = <
|
||||
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
|
||||
>({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth = 1,
|
||||
recordGqlFields,
|
||||
skipPostOptmisticEffect = false,
|
||||
}: useCreateManyRecordsProps) => {
|
||||
const apolloClient = useApolloClient();
|
||||
@ -33,13 +33,15 @@ export const useCreateManyRecords = <
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const computedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const { createManyRecordsMutation } = useCreateManyRecordsMutation({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
});
|
||||
|
||||
const createOneRecordInCache = useCreateOneRecordInCache<CachedObjectRecord>({
|
||||
const createOneRecordInCache = useCreateOneRecordInCache<ObjectRecord>({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
@ -65,7 +67,10 @@ export const useCreateManyRecords = <
|
||||
const recordsCreatedInCache = [];
|
||||
|
||||
for (const recordToCreate of sanitizedCreateManyRecordsInput) {
|
||||
const recordCreatedInCache = createOneRecordInCache(recordToCreate);
|
||||
const recordCreatedInCache = createOneRecordInCache({
|
||||
...recordToCreate,
|
||||
__typename: getObjectTypename(objectMetadataItem.nameSingular),
|
||||
});
|
||||
|
||||
if (isDefined(recordCreatedInCache)) {
|
||||
recordsCreatedInCache.push(recordCreatedInCache);
|
||||
|
||||
@ -5,18 +5,17 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { getCreateManyRecordsMutationResponseField } from '@/object-record/utils/getCreateManyRecordsMutationResponseField';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useCreateManyRecordsMutation = ({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -39,8 +38,7 @@ export const useCreateManyRecordsMutation = ({
|
||||
${mutationResponseField}(data: $data) ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
})}
|
||||
}`;
|
||||
|
||||
|
||||
@ -2,10 +2,12 @@ import { useApolloClient } from '@apollo/client';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { triggerCreateRecordsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect';
|
||||
import { CachedObjectRecord } from '@/apollo/types/CachedObjectRecord';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { useCreateOneRecordInCache } from '@/object-record/cache/hooks/useCreateOneRecordInCache';
|
||||
import { getObjectTypename } from '@/object-record/cache/utils/getObjectTypename';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { useCreateOneRecordMutation } from '@/object-record/hooks/useCreateOneRecordMutation';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getCreateOneRecordMutationResponseField } from '@/object-record/utils/getCreateOneRecordMutationResponseField';
|
||||
@ -14,8 +16,7 @@ import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type useCreateOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
skipPostOptmisticEffect?: boolean;
|
||||
};
|
||||
|
||||
@ -23,7 +24,7 @@ export const useCreateOneRecord = <
|
||||
CreatedObjectRecord extends ObjectRecord = ObjectRecord,
|
||||
>({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
skipPostOptmisticEffect = false,
|
||||
}: useCreateOneRecordProps) => {
|
||||
const apolloClient = useApolloClient();
|
||||
@ -32,14 +33,19 @@ export const useCreateOneRecord = <
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const computedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const { createOneRecordMutation } = useCreateOneRecordMutation({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
});
|
||||
|
||||
const createOneRecordInCache = useCreateOneRecordInCache<CachedObjectRecord>({
|
||||
objectMetadataItem,
|
||||
});
|
||||
const createOneRecordInCache = useCreateOneRecordInCache<CreatedObjectRecord>(
|
||||
{
|
||||
objectMetadataItem,
|
||||
},
|
||||
);
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
@ -57,6 +63,7 @@ export const useCreateOneRecord = <
|
||||
const recordCreatedInCache = createOneRecordInCache({
|
||||
...input,
|
||||
id: idForCreation,
|
||||
__typename: getObjectTypename(objectMetadataItem.nameSingular),
|
||||
});
|
||||
|
||||
if (isDefined(recordCreatedInCache)) {
|
||||
|
||||
@ -5,23 +5,29 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { getCreateOneRecordMutationResponseField } from '@/object-record/utils/getCreateOneRecordMutationResponseField';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useCreateOneRecordMutation = ({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const appliedRecordGqlFields =
|
||||
recordGqlFields ??
|
||||
generateDepthOneRecordGqlFields({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
if (isUndefinedOrNull(objectMetadataItem)) {
|
||||
@ -39,8 +45,7 @@ export const useCreateOneRecordMutation = ({
|
||||
${mutationResponseField}(data: $input) ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields: appliedRecordGqlFields,
|
||||
})}
|
||||
}
|
||||
`;
|
||||
|
||||
@ -4,25 +4,22 @@ import { useQuery } from '@apollo/client';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
||||
import { useFindDuplicateRecordsQuery } from '@/object-record/hooks/useFindDuplicatesRecordsQuery';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
import { getFindDuplicateRecordsQueryResponseField } from '@/object-record/utils/getFindDuplicateRecordsQueryResponseField';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { logError } from '~/utils/logError';
|
||||
|
||||
import { ObjectRecordQueryResult } from '../types/ObjectRecordQueryResult';
|
||||
|
||||
export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectRecordId = '',
|
||||
objectNameSingular,
|
||||
onCompleted,
|
||||
depth,
|
||||
}: ObjectMetadataItemIdentifier & {
|
||||
objectRecordId: string | undefined;
|
||||
onCompleted?: (data: ObjectRecordConnection<T>) => void;
|
||||
onCompleted?: (data: RecordGqlConnection) => void;
|
||||
skip?: boolean;
|
||||
depth?: number;
|
||||
}) => {
|
||||
const findDuplicateQueryStateIdentifier = objectNameSingular;
|
||||
|
||||
@ -32,7 +29,6 @@ export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
|
||||
const { findDuplicateRecordsQuery } = useFindDuplicateRecordsQuery({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
});
|
||||
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
@ -41,7 +37,7 @@ export const useFindDuplicateRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectMetadataItem.nameSingular,
|
||||
);
|
||||
|
||||
const { data, loading, error } = useQuery<ObjectRecordQueryResult<T>>(
|
||||
const { data, loading, error } = useQuery<RecordGqlOperationFindManyResult>(
|
||||
findDuplicateRecordsQuery,
|
||||
{
|
||||
variables: {
|
||||
|
||||
@ -9,10 +9,8 @@ import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useFindDuplicateRecordsQuery = ({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
depth?: number;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -31,7 +29,6 @@ export const useFindDuplicateRecordsQuery = ({
|
||||
node ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
})}
|
||||
cursor
|
||||
}
|
||||
|
||||
@ -8,11 +8,13 @@ import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMembe
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||
import { RecordGqlOperationFindManyResult } from '@/object-record/graphql/types/RecordGqlOperationFindManyResult';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { RecordGqlOperationVariables } from '@/object-record/graphql/types/RecordGqlOperationVariables';
|
||||
import { useFindManyRecordsQuery } from '@/object-record/hooks/useFindManyRecordsQuery';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -22,7 +24,6 @@ import { capitalize } from '~/utils/string/capitalize';
|
||||
import { cursorFamilyState } from '../states/cursorFamilyState';
|
||||
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
|
||||
import { isFetchingMoreRecordsFamilyState } from '../states/isFetchingMoreRecordsFamilyState';
|
||||
import { ObjectRecordQueryResult } from '../types/ObjectRecordQueryResult';
|
||||
|
||||
export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectNameSingular,
|
||||
@ -31,20 +32,19 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
limit,
|
||||
onCompleted,
|
||||
skip,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
fetchPolicy,
|
||||
}: ObjectMetadataItemIdentifier &
|
||||
ObjectRecordQueryVariables & {
|
||||
RecordGqlOperationVariables & {
|
||||
onCompleted?: (
|
||||
records: T[],
|
||||
options?: {
|
||||
pageInfo?: ObjectRecordConnection['pageInfo'];
|
||||
pageInfo?: RecordGqlConnection['pageInfo'];
|
||||
totalCount?: number;
|
||||
},
|
||||
) => void;
|
||||
skip?: boolean;
|
||||
depth?: number;
|
||||
queryFields?: Record<string, any>;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
fetchPolicy?: WatchQueryFetchPolicy;
|
||||
}) => {
|
||||
const findManyQueryStateIdentifier =
|
||||
@ -71,56 +71,55 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
|
||||
const { findManyRecordsQuery } = useFindManyRecordsQuery({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
});
|
||||
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
|
||||
|
||||
const { data, loading, error, fetchMore } = useQuery<
|
||||
ObjectRecordQueryResult<T>
|
||||
>(findManyRecordsQuery, {
|
||||
skip: skip || !objectMetadataItem || !currentWorkspaceMember,
|
||||
variables: {
|
||||
filter,
|
||||
limit,
|
||||
orderBy,
|
||||
},
|
||||
fetchPolicy: fetchPolicy,
|
||||
onCompleted: (data) => {
|
||||
if (!isDefined(data)) {
|
||||
onCompleted?.([]);
|
||||
}
|
||||
const { data, loading, error, fetchMore } =
|
||||
useQuery<RecordGqlOperationFindManyResult>(findManyRecordsQuery, {
|
||||
skip: skip || !objectMetadataItem || !currentWorkspaceMember,
|
||||
variables: {
|
||||
filter,
|
||||
limit,
|
||||
orderBy,
|
||||
},
|
||||
fetchPolicy: fetchPolicy,
|
||||
onCompleted: (data) => {
|
||||
if (!isDefined(data)) {
|
||||
onCompleted?.([]);
|
||||
}
|
||||
|
||||
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
|
||||
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
|
||||
|
||||
const records = getRecordsFromRecordConnection({
|
||||
recordConnection: data?.[objectMetadataItem.namePlural],
|
||||
}) as T[];
|
||||
const records = getRecordsFromRecordConnection({
|
||||
recordConnection: data?.[objectMetadataItem.namePlural],
|
||||
}) as T[];
|
||||
|
||||
onCompleted?.(records, {
|
||||
pageInfo,
|
||||
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
|
||||
});
|
||||
onCompleted?.(records, {
|
||||
pageInfo,
|
||||
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
|
||||
});
|
||||
|
||||
if (isDefined(data?.[objectMetadataItem.namePlural])) {
|
||||
setLastCursor(pageInfo.endCursor ?? '');
|
||||
setHasNextPage(pageInfo.hasNextPage ?? false);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
logError(
|
||||
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
|
||||
error,
|
||||
);
|
||||
enqueueSnackBar(
|
||||
`Error during useFindManyRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
|
||||
{
|
||||
variant: 'error',
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
if (isDefined(data?.[objectMetadataItem.namePlural])) {
|
||||
setLastCursor(pageInfo.endCursor ?? '');
|
||||
setHasNextPage(pageInfo.hasNextPage ?? false);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
logError(
|
||||
`useFindManyRecords for "${objectMetadataItem.namePlural}" error : ` +
|
||||
error,
|
||||
);
|
||||
enqueueSnackBar(
|
||||
`Error during useFindManyRecords for "${objectMetadataItem.namePlural}", ${error.message}`,
|
||||
{
|
||||
variant: 'error',
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const fetchMoreRecords = useCallback(async () => {
|
||||
if (hasNextPage) {
|
||||
@ -138,7 +137,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
const nextEdges =
|
||||
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
|
||||
|
||||
let newEdges: ObjectRecordEdge<T>[] = [];
|
||||
let newEdges: RecordGqlEdge[] = [];
|
||||
|
||||
if (isNonEmptyArray(previousEdges) && isNonEmptyArray(nextEdges)) {
|
||||
newEdges = filterUniqueRecordEdgesByCursor([
|
||||
@ -180,7 +179,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
totalCount:
|
||||
fetchMoreResult?.[objectMetadataItem.namePlural].totalCount,
|
||||
},
|
||||
} as ObjectRecordQueryResult<T>);
|
||||
} as RecordGqlOperationFindManyResult);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
@ -219,7 +218,7 @@ export const useFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
|
||||
const records = useMemo(
|
||||
() =>
|
||||
data?.[objectMetadataItem.namePlural]
|
||||
? getRecordsFromRecordConnection({
|
||||
? getRecordsFromRecordConnection<T>({
|
||||
recordConnection: data?.[objectMetadataItem.namePlural],
|
||||
})
|
||||
: ([] as T[]),
|
||||
|
||||
@ -2,18 +2,16 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { QueryFields } from '@/object-record/query-keys/types/QueryFields';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
|
||||
|
||||
export const useFindManyRecordsQuery = ({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
queryFields?: QueryFields;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
computeReferences?: boolean;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
@ -25,8 +23,7 @@ export const useFindManyRecordsQuery = ({
|
||||
const findManyRecordsQuery = generateFindManyRecordsQuery({
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
queryFields,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
});
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@ import { useQuery } from '@apollo/client';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -11,32 +14,34 @@ import { isDefined } from '~/utils/isDefined';
|
||||
export const useFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectNameSingular,
|
||||
objectRecordId = '',
|
||||
recordGqlFields,
|
||||
onCompleted,
|
||||
skip,
|
||||
depth,
|
||||
}: ObjectMetadataItemIdentifier & {
|
||||
objectRecordId: string | undefined;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
onCompleted?: (data: T) => void;
|
||||
skip?: boolean;
|
||||
depth?: number;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const computedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const { findOneRecordQuery } = useFindOneRecordQuery({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
});
|
||||
|
||||
const { data, loading, error } = useQuery<
|
||||
{ [nameSingular: string]: T },
|
||||
{ objectRecordId: string }
|
||||
>(findOneRecordQuery, {
|
||||
const { data, loading, error } = useQuery<{
|
||||
[nameSingular: string]: RecordGqlNode;
|
||||
}>(findOneRecordQuery, {
|
||||
skip: !objectMetadataItem || !objectRecordId || skip,
|
||||
variables: { objectRecordId },
|
||||
onCompleted: (data) => {
|
||||
const recordWithoutConnection = getRecordFromRecordNode({
|
||||
const recordWithoutConnection = getRecordFromRecordNode<T>({
|
||||
recordNode: { ...data[objectNameSingular] },
|
||||
});
|
||||
|
||||
@ -50,7 +55,7 @@ export const useFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
|
||||
const recordWithoutConnection = useMemo(
|
||||
() =>
|
||||
data?.[objectNameSingular]
|
||||
? getRecordFromRecordNode({
|
||||
? getRecordFromRecordNode<T>({
|
||||
recordNode: data?.[objectNameSingular],
|
||||
})
|
||||
: undefined,
|
||||
|
||||
@ -4,14 +4,15 @@ import { useRecoilValue } from 'recoil';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useFindOneRecordQuery = ({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -30,7 +31,7 @@ export const useFindOneRecordQuery = ({
|
||||
})${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
})}
|
||||
},
|
||||
`;
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { useLazyQuery } from '@apollo/client';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||
import { getRecordFromRecordNode } from '@/object-record/cache/utils/getRecordFromRecordNode';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
type UseLazyFindOneRecordParams = ObjectMetadataItemIdentifier & {
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
};
|
||||
|
||||
type FindOneRecordParams<T extends ObjectRecord> = {
|
||||
@ -16,11 +19,17 @@ type FindOneRecordParams<T extends ObjectRecord> = {
|
||||
|
||||
export const useLazyFindOneRecord = <T extends ObjectRecord = ObjectRecord>({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
recordGqlFields,
|
||||
}: UseLazyFindOneRecordParams) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { findOneRecordQuery } = useFindOneRecordQuery({
|
||||
objectNameSingular,
|
||||
depth,
|
||||
recordGqlFields:
|
||||
recordGqlFields ??
|
||||
generateDepthOneRecordGqlFields({ objectMetadataItem }),
|
||||
});
|
||||
|
||||
const [findOneRecord, { loading, error, data, called }] =
|
||||
|
||||
@ -6,23 +6,23 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat
|
||||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
|
||||
import { getRecordNodeFromRecord } from '@/object-record/cache/utils/getRecordNodeFromRecord';
|
||||
import { updateRecordFromCache } from '@/object-record/cache/utils/updateRecordFromCache';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { useUpdateOneRecordMutation } from '@/object-record/hooks/useUpdateOneRecordMutation';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
|
||||
import { sanitizeRecordInput } from '@/object-record/utils/sanitizeRecordInput';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
type useUpdateOneRecordProps = {
|
||||
objectNameSingular: string;
|
||||
queryFields?: Record<string, any>;
|
||||
depth?: number;
|
||||
recordGqlFields?: Record<string, any>;
|
||||
};
|
||||
|
||||
export const useUpdateOneRecord = <
|
||||
UpdatedObjectRecord extends ObjectRecord = ObjectRecord,
|
||||
>({
|
||||
objectNameSingular,
|
||||
queryFields,
|
||||
depth = 1,
|
||||
recordGqlFields,
|
||||
}: useUpdateOneRecordProps) => {
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
@ -30,12 +30,16 @@ export const useUpdateOneRecord = <
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const computedRecordGqlFields =
|
||||
recordGqlFields ?? generateDepthOneRecordGqlFields({ objectMetadataItem });
|
||||
|
||||
const getRecordFromCache = useGetRecordFromCache({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { updateOneRecordMutation } = useUpdateOneRecordMutation({
|
||||
objectNameSingular,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
});
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
@ -54,14 +58,13 @@ export const useUpdateOneRecord = <
|
||||
}),
|
||||
};
|
||||
|
||||
const cachedRecord = getRecordFromCache<UpdatedObjectRecord>(idToUpdate);
|
||||
const cachedRecord = getRecordFromCache<ObjectRecord>(idToUpdate);
|
||||
|
||||
const cachedRecordWithConnection = getRecordNodeFromRecord<ObjectRecord>({
|
||||
record: cachedRecord,
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
depth,
|
||||
queryFields,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
computeReferences: true,
|
||||
});
|
||||
|
||||
@ -69,6 +72,7 @@ export const useUpdateOneRecord = <
|
||||
...cachedRecord,
|
||||
...sanitizedInput,
|
||||
...{ id: idToUpdate },
|
||||
...{ __typename: capitalize(objectMetadataItem.nameSingular) },
|
||||
};
|
||||
|
||||
const optimisticRecordWithConnection =
|
||||
@ -76,8 +80,7 @@ export const useUpdateOneRecord = <
|
||||
record: optimisticRecord,
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
depth,
|
||||
queryFields,
|
||||
recordGqlFields: computedRecordGqlFields,
|
||||
computeReferences: true,
|
||||
});
|
||||
|
||||
|
||||
@ -5,18 +5,20 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { EMPTY_MUTATION } from '@/object-record/constants/EmptyMutation';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
import { getUpdateOneRecordMutationResponseField } from '@/object-record/utils/getUpdateOneRecordMutationResponseField';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useUpdateOneRecordMutation = ({
|
||||
objectNameSingular,
|
||||
recordGqlFields,
|
||||
computeReferences = false,
|
||||
depth,
|
||||
}: {
|
||||
objectNameSingular: string;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
computeReferences?: boolean;
|
||||
depth?: number;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -28,6 +30,12 @@ export const useUpdateOneRecordMutation = ({
|
||||
return { updateOneRecordMutation: EMPTY_MUTATION };
|
||||
}
|
||||
|
||||
const appliedRecordGqlFields =
|
||||
recordGqlFields ??
|
||||
generateDepthOneRecordGqlFields({
|
||||
objectMetadataItem,
|
||||
});
|
||||
|
||||
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
|
||||
|
||||
const mutationResponseField = getUpdateOneRecordMutationResponseField(
|
||||
@ -40,8 +48,8 @@ export const useUpdateOneRecordMutation = ({
|
||||
{
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
computeReferences,
|
||||
recordGqlFields: appliedRecordGqlFields,
|
||||
},
|
||||
)}
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
// TODO: refactor with scoped state later
|
||||
export const useUpsertRecordFromState = () =>
|
||||
useRecoilCallback(
|
||||
({ set }) =>
|
||||
<T extends { id: string }>(record: T) =>
|
||||
<T extends ObjectRecord>(record: T) =>
|
||||
set(recordStoreFamilyState(record.id), (previousRecord) =>
|
||||
isDeeplyEqual(previousRecord, record) ? previousRecord : record,
|
||||
),
|
||||
|
||||
@ -1,26 +1,21 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getRecordsFromRecordConnection } from '@/object-record/cache/utils/getRecordsFromRecordConnection';
|
||||
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature';
|
||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
||||
import { MultiObjectRecordQueryResult } from '@/object-record/relation-picker/hooks/useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray';
|
||||
|
||||
export const useFindManyRecordsForMultipleMetadataItems = ({
|
||||
objectMetadataItems,
|
||||
export const useCombinedFindManyRecords = ({
|
||||
operationSignatures,
|
||||
skip = false,
|
||||
depth = 2,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
operationSignatures: RecordGqlOperationSignature[];
|
||||
skip: boolean;
|
||||
depth?: number;
|
||||
}) => {
|
||||
const findManyQuery = useGenerateFindManyRecordsForMultipleMetadataItemsQuery(
|
||||
{
|
||||
targetObjectMetadataItems: objectMetadataItems,
|
||||
depth,
|
||||
},
|
||||
);
|
||||
const findManyQuery = useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures,
|
||||
});
|
||||
|
||||
const { data } = useQuery<MultiObjectRecordQueryResult>(
|
||||
findManyQuery ?? EMPTY_QUERY,
|
||||
@ -0,0 +1,109 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { RecordGqlOperationSignature } from '@/object-record/graphql/types/RecordGqlOperationSignature';
|
||||
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useGenerateCombinedFindManyRecordsQuery = ({
|
||||
operationSignatures,
|
||||
}: {
|
||||
operationSignatures: RecordGqlOperationSignature[];
|
||||
}) => {
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
|
||||
if (!isNonEmptyArray(operationSignatures)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filterPerMetadataItemArray = operationSignatures
|
||||
.map(
|
||||
({ objectNameSingular }) =>
|
||||
`$filter${capitalize(objectNameSingular)}: ${capitalize(
|
||||
objectNameSingular,
|
||||
)}FilterInput`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const orderByPerMetadataItemArray = operationSignatures
|
||||
.map(
|
||||
({ objectNameSingular }) =>
|
||||
`$orderBy${capitalize(objectNameSingular)}: ${capitalize(
|
||||
objectNameSingular,
|
||||
)}OrderByInput`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const lastCursorPerMetadataItemArray = operationSignatures
|
||||
.map(
|
||||
({ objectNameSingular }) =>
|
||||
`$lastCursor${capitalize(objectNameSingular)}: String`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const limitPerMetadataItemArray = operationSignatures
|
||||
.map(
|
||||
({ objectNameSingular }) =>
|
||||
`$limit${capitalize(objectNameSingular)}: Int`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const queryKeyWithObjectMetadataItemArray = operationSignatures.map(
|
||||
(queryKey) => {
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.nameSingular === queryKey.objectNameSingular,
|
||||
);
|
||||
|
||||
if (isUndefined(objectMetadataItem)) {
|
||||
throw new Error(
|
||||
`Object metadata item not found for object name singular: ${queryKey.objectNameSingular}`,
|
||||
);
|
||||
}
|
||||
|
||||
return { ...queryKey, objectMetadataItem };
|
||||
},
|
||||
);
|
||||
|
||||
return gql`
|
||||
query CombinedFindManyRecords(
|
||||
${filterPerMetadataItemArray},
|
||||
${orderByPerMetadataItemArray},
|
||||
${lastCursorPerMetadataItemArray},
|
||||
${limitPerMetadataItemArray}
|
||||
) {
|
||||
${queryKeyWithObjectMetadataItemArray
|
||||
.map(
|
||||
({ objectMetadataItem, fields }) =>
|
||||
`${objectMetadataItem.namePlural}(filter: $filter${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, orderBy: $orderBy${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, first: $limit${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, after: $lastCursor${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}){
|
||||
edges {
|
||||
node ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems: objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
recordGqlFields: fields,
|
||||
})}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@ -1,92 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const useGenerateFindManyRecordsForMultipleMetadataItemsQuery = ({
|
||||
targetObjectMetadataItems,
|
||||
depth,
|
||||
}: {
|
||||
targetObjectMetadataItems: ObjectMetadataItem[];
|
||||
depth?: number;
|
||||
}) => {
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
const capitalizedObjectNameSingulars = targetObjectMetadataItems.map(
|
||||
({ nameSingular }) => capitalize(nameSingular),
|
||||
);
|
||||
|
||||
if (!isNonEmptyArray(capitalizedObjectNameSingulars)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filterPerMetadataItemArray = capitalizedObjectNameSingulars
|
||||
.map(
|
||||
(capitalizedObjectNameSingular) =>
|
||||
`$filter${capitalizedObjectNameSingular}: ${capitalizedObjectNameSingular}FilterInput`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const orderByPerMetadataItemArray = capitalizedObjectNameSingulars
|
||||
.map(
|
||||
(capitalizedObjectNameSingular) =>
|
||||
`$orderBy${capitalizedObjectNameSingular}: ${capitalizedObjectNameSingular}OrderByInput`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const lastCursorPerMetadataItemArray = capitalizedObjectNameSingulars
|
||||
.map(
|
||||
(capitalizedObjectNameSingular) =>
|
||||
`$lastCursor${capitalizedObjectNameSingular}: String`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
const limitPerMetadataItemArray = capitalizedObjectNameSingulars
|
||||
.map(
|
||||
(capitalizedObjectNameSingular) =>
|
||||
`$limit${capitalizedObjectNameSingular}: Int`,
|
||||
)
|
||||
.join(', ');
|
||||
|
||||
return gql`
|
||||
query FindManyRecordsMultipleMetadataItems(
|
||||
${filterPerMetadataItemArray},
|
||||
${orderByPerMetadataItemArray},
|
||||
${lastCursorPerMetadataItemArray},
|
||||
${limitPerMetadataItemArray}
|
||||
) {
|
||||
${targetObjectMetadataItems
|
||||
.map(
|
||||
(objectMetadataItem) =>
|
||||
`${objectMetadataItem.namePlural}(filter: $filter${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, orderBy: $orderBy${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, first: $limit${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}, after: $lastCursor${capitalize(
|
||||
objectMetadataItem.nameSingular,
|
||||
)}){
|
||||
edges {
|
||||
node ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems: objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
})}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}`,
|
||||
)
|
||||
.join('\n')}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@ -1,5 +1,5 @@
|
||||
import { OrderBy } from '@/object-metadata/types/OrderBy';
|
||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||
import { RecordGqlOperationOrderBy } from '@/object-record/graphql/types/RecordGqlOperationOrderBy';
|
||||
import { Field } from '~/generated/graphql';
|
||||
import { mapArrayToObject } from '~/utils/array/mapArrayToObject';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -10,7 +10,7 @@ import { Sort } from '../types/Sort';
|
||||
export const turnSortsIntoOrderBy = (
|
||||
sorts: Sort[],
|
||||
fields: Pick<Field, 'id' | 'name'>[],
|
||||
): OrderByField => {
|
||||
): RecordGqlOperationOrderBy => {
|
||||
const fieldsById = mapArrayToObject(fields, ({ id }) => id);
|
||||
const sortsOrderBy = Object.fromEntries(
|
||||
sorts
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export type QueryFields = Record<string, any>;
|
||||
@ -1,10 +0,0 @@
|
||||
import { QueryFields } from '@/object-record/query-keys/types/QueryFields';
|
||||
import { ObjectRecordQueryVariables } from '@/object-record/types/ObjectRecordQueryVariables';
|
||||
|
||||
export type QueryKey = {
|
||||
objectNameSingular: string;
|
||||
variables: ObjectRecordQueryVariables;
|
||||
depth?: number;
|
||||
fields?: QueryFields; // Todo: Fields should be required
|
||||
fieldsFactory?: (fieldsFactoryParam: any) => QueryFields;
|
||||
};
|
||||
@ -1,4 +1,5 @@
|
||||
import { RecordChip } from '@/object-record/components/RecordChip';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
import { useRelationField } from '../../hooks/useRelationField';
|
||||
|
||||
@ -12,7 +13,7 @@ export const RelationFieldDisplay = () => {
|
||||
objectNameSingular={
|
||||
fieldDefinition.metadata.relationObjectMetadataNameSingular
|
||||
}
|
||||
record={fieldValue}
|
||||
record={fieldValue as unknown as ObjectRecord} // Todo: Fix this type
|
||||
maxWidth={maxWidth}
|
||||
/>
|
||||
);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { BooleanFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { BooleanFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingBooleanFilter = ({
|
||||
booleanFilter,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { CurrencyFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { CurrencyFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingCurrencyFilter = ({
|
||||
currencyFilter,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { DateFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { DateFilter } from '@/object-record//graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingDateFilter = ({
|
||||
dateFilter,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { FloatFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { FloatFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingFloatFilter = ({
|
||||
floatFilter,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { StringFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { StringFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingStringFilter = ({
|
||||
stringFilter,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {
|
||||
UUIDFilter,
|
||||
UUIDFilterValue,
|
||||
} from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
} from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
|
||||
export const isMatchingUUIDFilter = ({
|
||||
uuidFilter,
|
||||
|
||||
@ -10,12 +10,12 @@ import {
|
||||
FloatFilter,
|
||||
FullNameFilter,
|
||||
NotObjectRecordFilter,
|
||||
ObjectRecordQueryFilter,
|
||||
OrObjectRecordFilter,
|
||||
RecordGqlOperationFilter,
|
||||
StringFilter,
|
||||
URLFilter,
|
||||
UUIDFilter,
|
||||
} from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
} from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { isMatchingBooleanFilter } from '@/object-record/record-filter/utils/isMatchingBooleanFilter';
|
||||
import { isMatchingCurrencyFilter } from '@/object-record/record-filter/utils/isMatchingCurrencyFilter';
|
||||
import { isMatchingDateFilter } from '@/object-record/record-filter/utils/isMatchingDateFilter';
|
||||
@ -27,15 +27,15 @@ import { isDefined } from '~/utils/isDefined';
|
||||
import { isEmptyObject } from '~/utils/isEmptyObject';
|
||||
|
||||
const isAndFilter = (
|
||||
filter: ObjectRecordQueryFilter,
|
||||
filter: RecordGqlOperationFilter,
|
||||
): filter is AndObjectRecordFilter => 'and' in filter && !!filter.and;
|
||||
|
||||
const isOrFilter = (
|
||||
filter: ObjectRecordQueryFilter,
|
||||
filter: RecordGqlOperationFilter,
|
||||
): filter is OrObjectRecordFilter => 'or' in filter && !!filter.or;
|
||||
|
||||
const isNotFilter = (
|
||||
filter: ObjectRecordQueryFilter,
|
||||
filter: RecordGqlOperationFilter,
|
||||
): filter is NotObjectRecordFilter => 'not' in filter && !!filter.not;
|
||||
|
||||
export const isRecordMatchingFilter = ({
|
||||
@ -44,7 +44,7 @@ export const isRecordMatchingFilter = ({
|
||||
objectMetadataItem,
|
||||
}: {
|
||||
record: any;
|
||||
filter: ObjectRecordQueryFilter;
|
||||
filter: RecordGqlOperationFilter;
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
}): boolean => {
|
||||
if (Object.keys(filter).length === 0) {
|
||||
|
||||
@ -5,11 +5,11 @@ import {
|
||||
CurrencyFilter,
|
||||
DateFilter,
|
||||
FloatFilter,
|
||||
ObjectRecordQueryFilter,
|
||||
RecordGqlOperationFilter,
|
||||
StringFilter,
|
||||
URLFilter,
|
||||
UUIDFilter,
|
||||
} from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
} from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { makeAndFilterVariables } from '@/object-record/utils/makeAndFilterVariables';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { Field } from '~/generated/graphql';
|
||||
@ -27,8 +27,8 @@ export type ObjectDropdownFilter = Omit<Filter, 'definition'> & {
|
||||
export const turnObjectDropdownFilterIntoQueryFilter = (
|
||||
rawUIFilters: ObjectDropdownFilter[],
|
||||
fields: Pick<Field, 'id' | 'name'>[],
|
||||
): ObjectRecordQueryFilter | undefined => {
|
||||
const objectRecordFilters: ObjectRecordQueryFilter[] = [];
|
||||
): RecordGqlOperationFilter | undefined => {
|
||||
const objectRecordFilters: RecordGqlOperationFilter[] = [];
|
||||
|
||||
for (const rawUIFilter of rawUIFilters) {
|
||||
const correspondingField = fields.find(
|
||||
|
||||
@ -6,7 +6,7 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
|
||||
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
|
||||
import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter';
|
||||
import { useRecordBoardQueryFields } from '@/object-record/record-index/hooks/useRecordBoardQueryFields';
|
||||
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
|
||||
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
|
||||
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
|
||||
import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
|
||||
@ -56,7 +56,7 @@ export const useLoadRecordIndexBoard = ({
|
||||
recordIndexIsCompactModeActiveState,
|
||||
);
|
||||
|
||||
const queryFields = useRecordBoardQueryFields({
|
||||
const recordGqlFields = useRecordBoardRecordGqlFields({
|
||||
objectMetadataItem,
|
||||
recordBoardId,
|
||||
});
|
||||
@ -71,7 +71,7 @@ export const useLoadRecordIndexBoard = ({
|
||||
objectNameSingular,
|
||||
filter: requestFilters,
|
||||
orderBy,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
});
|
||||
|
||||
const { setRecordCountInCurrentView } =
|
||||
|
||||
@ -5,7 +5,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
|
||||
import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter';
|
||||
import { useRecordTableQueryFields } from '@/object-record/record-index/hooks/useRecordTableQueryFields';
|
||||
import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
|
||||
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
|
||||
@ -49,7 +49,7 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const params = useFindManyParams(objectNameSingular);
|
||||
|
||||
const queryFields = useRecordTableQueryFields();
|
||||
const recordGqlFields = useRecordTableRecordGqlFields();
|
||||
|
||||
const {
|
||||
records,
|
||||
@ -59,7 +59,7 @@ export const useLoadRecordIndexTable = (objectNameSingular: string) => {
|
||||
queryStateIdentifier,
|
||||
} = useFindManyRecords({
|
||||
...params,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
onCompleted: () => {
|
||||
setLastRowVisible(false);
|
||||
setIsRecordTableInitialLoading(false);
|
||||
|
||||
@ -5,7 +5,7 @@ import { getObjectMetadataIdentifierFields } from '@/object-metadata/utils/getOb
|
||||
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useRecordBoardQueryFields = ({
|
||||
export const useRecordBoardRecordGqlFields = ({
|
||||
objectMetadataItem,
|
||||
recordBoardId,
|
||||
}: {
|
||||
@ -33,7 +33,7 @@ export const useRecordBoardQueryFields = ({
|
||||
identifierQueryFields[imageIdentifierFieldMetadataItem.name] = true;
|
||||
}
|
||||
|
||||
const queryFields: Record<string, any> = {
|
||||
const recordGqlFields: Record<string, any> = {
|
||||
id: true,
|
||||
...Object.fromEntries(
|
||||
visibleFieldDefinitions.map((visibleFieldDefinition) => [
|
||||
@ -45,8 +45,8 @@ export const useRecordBoardQueryFields = ({
|
||||
};
|
||||
|
||||
if (isDefined(kanbanFieldMetadataName)) {
|
||||
queryFields[kanbanFieldMetadataName] = true;
|
||||
recordGqlFields[kanbanFieldMetadataName] = true;
|
||||
}
|
||||
|
||||
return queryFields;
|
||||
return recordGqlFields;
|
||||
};
|
||||
@ -2,12 +2,12 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
|
||||
export const useRecordTableQueryFields = () => {
|
||||
export const useRecordTableRecordGqlFields = () => {
|
||||
const { visibleTableColumnsSelector } = useRecordTableStates();
|
||||
|
||||
const visibleTableColumns = useRecoilValue(visibleTableColumnsSelector());
|
||||
|
||||
const queryFields: Record<string, any> = {
|
||||
const recordGqlFields: Record<string, any> = {
|
||||
id: true,
|
||||
...Object.fromEntries(
|
||||
visibleTableColumns.map((column) => [column.metadata.fieldName, true]),
|
||||
@ -15,5 +15,5 @@ export const useRecordTableQueryFields = () => {
|
||||
position: true,
|
||||
};
|
||||
|
||||
return queryFields;
|
||||
return recordGqlFields;
|
||||
};
|
||||
@ -139,7 +139,6 @@ export const useExportTableData = ({
|
||||
// Todo: this needs to be done on click on the Export not button, not to be reactive. Use Lazy query for example
|
||||
const { totalCount, records, fetchMoreRecords } = useFindManyRecords({
|
||||
...usedFindManyParams,
|
||||
depth: 0,
|
||||
limit: pageSize,
|
||||
onCompleted: (_data, options) => {
|
||||
setHasNextPage(options?.pageInfo?.hasNextPage ?? false);
|
||||
|
||||
@ -17,7 +17,6 @@ export const RecordShowContainer = ({
|
||||
const { record: activity, loading } = useFindOneRecord<Activity>({
|
||||
objectRecordId,
|
||||
objectNameSingular,
|
||||
depth: 3,
|
||||
});
|
||||
|
||||
const setRecordStore = useSetRecoilState(
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory';
|
||||
import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields';
|
||||
|
||||
export const findOneRecordForShowPageOperationSignatureFactory: RecordGqlOperationSignatureFactory =
|
||||
({ objectMetadataItem }: { objectMetadataItem: ObjectMetadataItem }) => ({
|
||||
objectNameSingular: CoreObjectNameSingular.Activity,
|
||||
variables: {},
|
||||
fields: generateDepthOneRecordGqlFields({ objectMetadataItem }),
|
||||
});
|
||||
@ -2,6 +2,7 @@ import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
@ -23,7 +24,7 @@ export const useSetRecordTableData = ({
|
||||
|
||||
return useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
<T extends { id: string }>(newEntityArray: T[], totalCount: number) => {
|
||||
<T extends ObjectRecord>(newEntityArray: T[], totalCount: number) => {
|
||||
for (const entity of newEntityArray) {
|
||||
// TODO: refactor with scoped state later
|
||||
const currentEntity = snapshot
|
||||
|
||||
@ -9,7 +9,7 @@ import { useMultiObjectSearch } from '@/object-record/relation-picker/hooks/useM
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
|
||||
const query = gql`
|
||||
query FindManyRecordsMultipleMetadataItems(
|
||||
query CombinedFindManyRecords(
|
||||
$filterNameSingular: NameSingularFilterInput
|
||||
$orderByNameSingular: NameSingularOrderByInput
|
||||
$lastCursorNameSingular: String
|
||||
|
||||
@ -3,12 +3,12 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsByNamePluralMapSelector } from '@/object-metadata/states/objectMetadataItemsByNamePluralMapSelector';
|
||||
import { getObjectRecordIdentifier } from '@/object-metadata/utils/getObjectRecordIdentifier';
|
||||
import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection';
|
||||
import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export type MultiObjectRecordQueryResult = {
|
||||
[namePlural: string]: ObjectRecordConnection;
|
||||
[namePlural: string]: RecordGqlConnection;
|
||||
};
|
||||
|
||||
export const useMultiObjectRecordsQueryResultFormattedAsObjectRecordForSelectArray =
|
||||
|
||||
@ -4,7 +4,7 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
||||
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
||||
import {
|
||||
MultiObjectRecordQueryResult,
|
||||
@ -84,9 +84,13 @@ export const useMultiObjectSearchMatchesSearchFilterAndSelectedItemsQuery = ({
|
||||
});
|
||||
|
||||
const multiSelectQueryForSelectedIds =
|
||||
useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
|
||||
targetObjectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery,
|
||||
depth: 0,
|
||||
useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures: objectMetadataItemsUsedInSelectedIdsQuery.map(
|
||||
(objectMetadataItem) => ({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
variables: {},
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
const {
|
||||
|
||||
@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { EMPTY_QUERY } from '@/object-record/constants/EmptyQuery';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
||||
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
||||
import {
|
||||
MultiObjectRecordQueryResult,
|
||||
@ -82,11 +82,14 @@ export const useMultiObjectSearchMatchesSearchFilterAndToSelectQuery = ({
|
||||
limit,
|
||||
});
|
||||
|
||||
const multiSelectQuery =
|
||||
useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
|
||||
targetObjectMetadataItems: nonSystemObjectMetadataItems,
|
||||
depth: 0,
|
||||
});
|
||||
const multiSelectQuery = useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures: nonSystemObjectMetadataItems.map(
|
||||
(objectMetadataItem) => ({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
variables: {},
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
const {
|
||||
loading: toSelectAndMatchesSearchFilterObjectRecordsLoading,
|
||||
|
||||
@ -3,7 +3,7 @@ import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { useGenerateFindManyRecordsForMultipleMetadataItemsQuery } from '@/object-record/multiple-objects/hooks/useGenerateFindManyRecordsForMultipleMetadataItemsQuery';
|
||||
import { useGenerateCombinedFindManyRecordsQuery } from '@/object-record/multiple-objects/hooks/useGenerateCombinedFindManyRecordsQuery';
|
||||
import { useLimitPerMetadataItem } from '@/object-record/relation-picker/hooks/useLimitPerMetadataItem';
|
||||
import {
|
||||
MultiObjectRecordQueryResult,
|
||||
@ -67,8 +67,13 @@ export const useMultiObjectSearchSelectedItemsQuery = ({
|
||||
});
|
||||
|
||||
const multiSelectQueryForSelectedIds =
|
||||
useGenerateFindManyRecordsForMultipleMetadataItemsQuery({
|
||||
targetObjectMetadataItems: objectMetadataItemsUsedInSelectedIdsQuery,
|
||||
useGenerateCombinedFindManyRecordsQuery({
|
||||
operationSignatures: objectMetadataItemsUsedInSelectedIdsQuery.map(
|
||||
(objectMetadataItem) => ({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
variables: {},
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
const {
|
||||
|
||||
@ -2,7 +2,7 @@ import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { makeOrFilterVariables } from '@/object-record/utils/makeOrFilterVariables';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields';
|
||||
@ -16,7 +16,7 @@ export const useSearchFilterPerMetadataItem = ({
|
||||
searchFilterValue: string;
|
||||
}) => {
|
||||
const searchFilterPerMetadataItemNameSingular =
|
||||
Object.fromEntries<ObjectRecordQueryFilter>(
|
||||
Object.fromEntries<RecordGqlOperationFilter>(
|
||||
objectMetadataItems
|
||||
.map((objectMetadataItem) => {
|
||||
if (searchFilterValue === '') return null;
|
||||
@ -24,7 +24,7 @@ export const useSearchFilterPerMetadataItem = ({
|
||||
const labelIdentifierFieldMetadataItem =
|
||||
getLabelIdentifierFieldMetadataItem(objectMetadataItem);
|
||||
|
||||
let searchFilter: ObjectRecordQueryFilter = {};
|
||||
let searchFilter: RecordGqlOperationFilter = {};
|
||||
|
||||
if (isDefined(labelIdentifierFieldMetadataItem)) {
|
||||
switch (labelIdentifierFieldMetadataItem.type) {
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordIdentifier } from '@/object-record/types/ObjectRecordIdentifier';
|
||||
|
||||
export type EntityForSelect = ObjectRecordIdentifier & { record: ObjectRecord };
|
||||
export type EntityForSelect = ObjectRecordIdentifier & {
|
||||
record: ObjectRecord;
|
||||
};
|
||||
|
||||
@ -1 +1,4 @@
|
||||
export type ObjectRecord = Record<string, any> & { id: string };
|
||||
export type ObjectRecord = Record<string, any> & {
|
||||
id: string;
|
||||
__typename: string;
|
||||
};
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
|
||||
export type ObjectRecordEdge<T extends ObjectRecord = ObjectRecord> = {
|
||||
__typename?: string;
|
||||
node: T;
|
||||
cursor: string;
|
||||
};
|
||||
@ -1,6 +0,0 @@
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordConnection } from '@/object-record/types/ObjectRecordConnection';
|
||||
|
||||
export type ObjectRecordQueryResult<T extends ObjectRecord> = {
|
||||
[objectNamePlural: string]: ObjectRecordConnection<T>;
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
import { OrderByField } from '@/object-metadata/types/OrderByField';
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
|
||||
export type ObjectRecordQueryVariables = {
|
||||
filter?: ObjectRecordQueryFilter;
|
||||
orderBy?: OrderByField;
|
||||
limit?: number;
|
||||
};
|
||||
@ -1,9 +1,7 @@
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
import { RecordGqlEdge } from '@/object-record/graphql/types/RecordGqlEdge';
|
||||
|
||||
export const filterUniqueRecordEdgesByCursor = <
|
||||
RecordType extends { id: string },
|
||||
>(
|
||||
arrayToFilter: ObjectRecordEdge<RecordType>[],
|
||||
export const filterUniqueRecordEdgesByCursor = (
|
||||
arrayToFilter: RecordGqlEdge[],
|
||||
) => {
|
||||
const seenCursors = new Set();
|
||||
|
||||
|
||||
@ -2,20 +2,18 @@ import gql from 'graphql-tag';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { mapObjectMetadataToGraphQLQuery } from '@/object-metadata/utils/mapObjectMetadataToGraphQLQuery';
|
||||
import { QueryFields } from '@/object-record/query-keys/types/QueryFields';
|
||||
import { RecordGqlOperationGqlRecordFields } from '@/object-record/graphql/types/RecordGqlOperationGqlRecordFields';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
export const generateFindManyRecordsQuery = ({
|
||||
objectMetadataItem,
|
||||
objectMetadataItems,
|
||||
depth,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
queryFields?: QueryFields;
|
||||
depth?: number;
|
||||
recordGqlFields?: RecordGqlOperationGqlRecordFields;
|
||||
computeReferences?: boolean;
|
||||
}) => gql`
|
||||
query FindMany${capitalize(
|
||||
@ -32,8 +30,7 @@ query FindMany${capitalize(
|
||||
node ${mapObjectMetadataToGraphQLQuery({
|
||||
objectMetadataItems,
|
||||
objectMetadataItem,
|
||||
depth,
|
||||
queryFields,
|
||||
recordGqlFields,
|
||||
computeReferences,
|
||||
})}
|
||||
cursor
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const getChildRelationArray = ({
|
||||
childRelation,
|
||||
}: {
|
||||
childRelation: any;
|
||||
}) => {
|
||||
if (isDefined(childRelation.edges) && Array.isArray(childRelation.edges)) {
|
||||
return childRelation.edges.map((edge: ObjectRecordEdge) => edge.node);
|
||||
} else {
|
||||
return childRelation;
|
||||
}
|
||||
};
|
||||
@ -1,9 +1,9 @@
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const makeAndFilterVariables = (
|
||||
filters: (ObjectRecordQueryFilter | undefined)[],
|
||||
): ObjectRecordQueryFilter | undefined => {
|
||||
filters: (RecordGqlOperationFilter | undefined)[],
|
||||
): RecordGqlOperationFilter | undefined => {
|
||||
const definedFilters = filters.filter(isDefined);
|
||||
|
||||
if (!definedFilters.length) return undefined;
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { ObjectRecordQueryFilter } from '@/object-record/record-filter/types/ObjectRecordQueryFilter';
|
||||
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const makeOrFilterVariables = (
|
||||
filters: (ObjectRecordQueryFilter | undefined)[],
|
||||
): ObjectRecordQueryFilter | undefined => {
|
||||
filters: (RecordGqlOperationFilter | undefined)[],
|
||||
): RecordGqlOperationFilter | undefined => {
|
||||
const definedFilters = filters.filter(isDefined);
|
||||
|
||||
if (!definedFilters.length) return undefined;
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { ObjectRecordEdge } from '@/object-record/types/ObjectRecordEdge';
|
||||
|
||||
export const mapEdgeToObjectRecord = <T extends ObjectRecord>(
|
||||
objectRecordEdge: ObjectRecordEdge<T>,
|
||||
) => {
|
||||
return objectRecordEdge.node as T;
|
||||
};
|
||||
@ -8,18 +8,12 @@ import { isDefined } from '~/utils/isDefined';
|
||||
export const prefillRecord = <T extends ObjectRecord>({
|
||||
objectMetadataItem,
|
||||
input,
|
||||
depth = 1,
|
||||
}: {
|
||||
objectMetadataItem: ObjectMetadataItem;
|
||||
input: Record<string, unknown>;
|
||||
depth?: number;
|
||||
}) => {
|
||||
return Object.fromEntries(
|
||||
objectMetadataItem.fields
|
||||
.filter(
|
||||
(fieldMetadataItem) =>
|
||||
depth > 0 || fieldMetadataItem.type !== 'RELATION',
|
||||
)
|
||||
.map((fieldMetadataItem) => {
|
||||
const inputValue = input[fieldMetadataItem.name];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user