Fix/object record and metadata naming (#2763)

* Fixed object-record and object-metadata naming

* Fix post merge

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Lucas Bordeau
2023-11-29 13:45:57 +01:00
committed by GitHub
parent 3617abb0e6
commit d855a42eca
99 changed files with 614 additions and 691 deletions

View File

@ -28,13 +28,13 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'
import { FileFolder, useUploadImageMutation } from '~/generated/graphql';
import { getLogoUrlFromDomainName } from '~/utils';
import { useFindOneObjectRecord } from '../hooks/useFindOneObjectRecord';
import { useUpdateOneObjectRecord } from '../hooks/useUpdateOneObjectRecord';
import { useFindOneRecord } from '../hooks/useFindOneRecord';
import { useUpdateOneRecord } from '../hooks/useUpdateOneRecord';
export const RecordShowPage = () => {
const { objectNameSingular, objectMetadataId } = useParams<{
const { objectNameSingular, objectRecordId } = useParams<{
objectNameSingular: string;
objectMetadataId: string;
objectRecordId: string;
}>();
const { objectMetadataItem } = useObjectMetadataItem({
@ -48,11 +48,11 @@ export const RecordShowPage = () => {
});
const [, setEntityFields] = useRecoilState(
entityFieldsFamilyState(objectMetadataId ?? ''),
entityFieldsFamilyState(objectRecordId ?? ''),
);
const { object } = useFindOneObjectRecord({
objectRecordId: objectMetadataId,
const { record } = useFindOneRecord({
objectRecordId,
objectNameSingular,
onCompleted: (data) => {
setEntityFields(data);
@ -60,11 +60,14 @@ export const RecordShowPage = () => {
});
const [uploadImage] = useUploadImageMutation();
const { updateOneObject } = useUpdateOneObjectRecord({
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular,
});
const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => {
const useUpdateOneObjectRecordMutation: () => [
(params: any) => any,
any,
] = () => {
const updateEntity = ({
variables,
}: {
@ -75,7 +78,7 @@ export const RecordShowPage = () => {
};
};
}) => {
updateOneObject?.({
updateOneRecord?.({
idToUpdate: variables.where.id,
input: variables.data,
});
@ -85,45 +88,45 @@ export const RecordShowPage = () => {
};
const isFavorite = objectNameSingular
? favorites.some((favorite) => favorite.recordId === object?.id)
? favorites.some((favorite) => favorite.recordId === record?.id)
: false;
const handleFavoriteButtonClick = async () => {
if (!objectNameSingular || !object) return;
if (isFavorite) deleteFavorite(object?.id);
if (!objectNameSingular || !record) return;
if (isFavorite) deleteFavorite(record?.id);
else {
const additionalData =
objectNameSingular === 'person'
? {
labelIdentifier:
object.name.firstName + ' ' + object.name.lastName,
avatarUrl: object.avatarUrl,
record.name.firstName + ' ' + record.name.lastName,
avatarUrl: record.avatarUrl,
avatarType: 'rounded',
link: `/object/personV2/${object.id}`,
recordId: object.id,
link: `/object/personV2/${record.id}`,
recordId: record.id,
}
: objectNameSingular === 'company'
? {
labelIdentifier: object.name,
avatarUrl: getLogoUrlFromDomainName(object.domainName ?? ''),
labelIdentifier: record.name,
avatarUrl: getLogoUrlFromDomainName(record.domainName ?? ''),
avatarType: 'squared',
link: `/object/companyV2/${object.id}`,
recordId: object.id,
link: `/object/companyV2/${record.id}`,
recordId: record.id,
}
: {};
createFavorite(object.id, additionalData);
createFavorite(record.id, additionalData);
}
};
if (!object) return <></>;
if (!record) return <></>;
const pageName =
objectNameSingular === 'person'
? object.name.firstName + ' ' + object.name.lastName
: object.name;
? record.name.firstName + ' ' + record.name.lastName
: record.name;
const recordIdentifiers = identifiersMapper?.(
object,
record,
objectMetadataItem?.nameSingular ?? '',
);
@ -144,12 +147,12 @@ export const RecordShowPage = () => {
if (!avatarUrl) {
return;
}
if (!updateOneObject) {
if (!updateOneRecord) {
return;
}
await updateOneObject({
idToUpdate: object?.id,
await updateOneRecord({
idToUpdate: record?.id,
input: {
avatarUrl,
},
@ -171,7 +174,7 @@ export const RecordShowPage = () => {
<ShowPageAddButton
key="add"
entity={{
id: object.id,
id: record.id,
type:
objectMetadataItem?.nameSingular === 'company'
? 'Company'
@ -186,10 +189,10 @@ export const RecordShowPage = () => {
<ShowPageContainer>
<ShowPageLeftContainer>
<ShowPageSummaryCard
id={object.id}
id={record.id}
logoOrAvatar={recordIdentifiers?.avatarUrl}
title={recordIdentifiers?.name ?? 'No name'}
date={object.createdAt ?? ''}
date={record.createdAt ?? ''}
renderTitleEditComponent={() => <></>}
avatarType={recordIdentifiers?.avatarType ?? 'rounded'}
onUploadPicture={
@ -206,10 +209,10 @@ export const RecordShowPage = () => {
.map((metadataField, index) => {
return (
<FieldContext.Provider
key={object.id + metadataField.id}
key={record.id + metadataField.id}
value={{
entityId: object.id,
recoilScopeId: object.id + metadataField.id,
entityId: record.id,
recoilScopeId: record.id + metadataField.id,
isLabelIdentifier: false,
fieldDefinition:
formatFieldMetadataItemAsColumnDefinition({
@ -217,7 +220,8 @@ export const RecordShowPage = () => {
position: index,
objectMetadataItem,
}),
useUpdateEntityMutation: useUpdateOneObjectMutation,
useUpdateEntityMutation:
useUpdateOneObjectRecordMutation,
hotkeyScope: InlineCellHotkeyScope.InlineCell,
}}
>
@ -228,7 +232,7 @@ export const RecordShowPage = () => {
</PropertyBox>
{objectNameSingular === 'company' ? (
<>
<CompanyTeam company={object} />
<CompanyTeam company={record} />
</>
) : (
<></>
@ -236,7 +240,7 @@ export const RecordShowPage = () => {
</ShowPageLeftContainer>
<ShowPageRightContainer
entity={{
id: object.id,
id: record.id,
// TODO: refacto
type:
objectMetadataItem?.nameSingular === 'company'

View File

@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { RecordTable } from '@/ui/object/record-table/components/RecordTable';
import { TableOptionsDropdownId } from '@/ui/object/record-table/constants/TableOptionsDropdownId';
@ -11,7 +11,7 @@ import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToC
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
import { useUpdateOneObjectRecord } from '../hooks/useUpdateOneObjectRecord';
import { useUpdateOneRecord } from '../hooks/useUpdateOneRecord';
import { RecordTableEffect } from './RecordTableEffect';
@ -32,11 +32,11 @@ export const RecordTableContainer = ({
objectNamePlural,
},
);
const { columnDefinitions } = useComputeDefinitionsFromFieldMetadata(
const { columnDefinitions } = useColumnDefinitionsFromFieldMetadata(
foundObjectMetadataItem,
);
const { updateOneObject } = useUpdateOneObjectRecord({
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular: foundObjectMetadataItem?.nameSingular,
});
@ -57,7 +57,7 @@ export const RecordTableContainer = ({
};
};
}) => {
updateOneObject?.({
updateOneRecord?.({
idToUpdate: variables.where.id,
input: variables.data,
});

View File

@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { useComputeDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useComputeDefinitionsFromFieldMetadata';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecordTableContextMenuEntries';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
@ -31,7 +31,7 @@ export const RecordTableEffect = ({
});
const { columnDefinitions, filterDefinitions, sortDefinitions } =
useComputeDefinitionsFromFieldMetadata(objectMetadataItem);
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const {
setAvailableSortDefinitions,

View File

@ -15,7 +15,7 @@ import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect';
import { RecordTableActionBar } from '@/ui/object/record-table/action-bar/components/RecordTableActionBar';
import { RecordTableContextMenu } from '@/ui/object/record-table/context-menu/components/RecordTableContextMenu';
import { useCreateOneObjectRecord } from '../hooks/useCreateOneObjectRecord';
import { useCreateOneRecord } from '../hooks/useCreateOneRecord';
import { RecordTableContainer } from './RecordTableContainer';
@ -33,7 +33,7 @@ export type RecordTablePageProps = Pick<
export const RecordTablePage = () => {
const objectNamePlural = useParams().objectNamePlural ?? '';
const { objectNotFoundInMetadata, objectMetadataItem } =
const { objectMetadataItemNotFound, objectMetadataItem } =
useObjectMetadataItem({
objectNamePlural,
});
@ -44,14 +44,14 @@ export const RecordTablePage = () => {
useEffect(() => {
if (
objectNotFoundInMetadata &&
objectMetadataItemNotFound &&
onboardingStatus === OnboardingStatus.Completed
) {
navigate('/');
}
}, [objectNotFoundInMetadata, navigate, onboardingStatus]);
}, [objectMetadataItemNotFound, navigate, onboardingStatus]);
const { createOneObject } = useCreateOneObjectRecord({
const { createOneRecord: createOneObject } = useCreateOneRecord({
objectNameSingular: objectMetadataItem?.nameSingular,
});

View File

@ -1,13 +0,0 @@
import { gql } from '@apollo/client';
export const CREATE_ONE_WORKSPACE_MEMBER_V2 = gql`
mutation CreateOneWorkspaceMember($input: WorkspaceMemberCreateInput!) {
createWorkspaceMember(data: $input) {
id
name {
firstName
lastName
}
}
}
`;

View File

@ -2,7 +2,7 @@ import { produce } from 'immer';
import { OptimisticEffectDefinition } from '@/apollo/optimistic-effect/types/OptimisticEffectDefinition';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { PaginatedObjectTypeResults } from '@/object-record/types/PaginatedObjectTypeResults';
import { PaginatedRecordTypeResults } from '@/object-record/types/PaginatedRecordTypeResults';
import { capitalize } from '~/utils/string/capitalize';
export const getRecordOptimisticEffectDefinition = ({
@ -21,8 +21,8 @@ export const getRecordOptimisticEffectDefinition = ({
newData: unknown;
}) => {
const newRecordPaginatedCacheField = produce<
PaginatedObjectTypeResults<any>
>(currentData as PaginatedObjectTypeResults<any>, (draft) => {
PaginatedRecordTypeResults<any>
>(currentData as PaginatedRecordTypeResults<any>, (draft) => {
if (!draft) {
return {
edges: [{ node: newData, cursor: '' }],

View File

@ -6,7 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { capitalize } from '~/utils/string/capitalize';
export const useCreateOneObjectRecord = <T>({
export const useCreateOneRecord = <T>({
objectNameSingular,
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
const { triggerOptimisticEffects } = useOptimisticEffect({
@ -14,22 +14,22 @@ export const useCreateOneObjectRecord = <T>({
});
const {
objectMetadataItem: foundObjectMetadataItem,
objectNotFoundInMetadata,
createOneMutation,
objectMetadataItem,
objectMetadataItemNotFound,
createOneRecordMutation,
} = useObjectMetadataItem({
objectNameSingular,
});
// TODO: type this with a minimal type at least with Record<string, any>
const [mutate] = useMutation(createOneMutation);
const [mutate] = useMutation(createOneRecordMutation);
const createOneObject = async (input: Record<string, any>) => {
if (!foundObjectMetadataItem || !objectNameSingular) {
const createOneRecord = async (input: Record<string, any>) => {
if (!objectMetadataItem || !objectNameSingular) {
return null;
}
const createdObject = await mutate({
const createdRecord = await mutate({
variables: {
input: { ...input, id: v4() },
},
@ -37,13 +37,13 @@ export const useCreateOneObjectRecord = <T>({
triggerOptimisticEffects(
`${capitalize(objectNameSingular)}Edge`,
createdObject.data[`create${capitalize(objectNameSingular)}`],
createdRecord.data[`create${capitalize(objectNameSingular)}`],
);
return createdObject.data[`create${capitalize(objectNameSingular)}`] as T;
return createdRecord.data[`create${capitalize(objectNameSingular)}`] as T;
};
return {
createOneObject,
objectNotFoundInMetadata,
createOneRecord,
objectMetadataItemNotFound,
};
};

View File

@ -6,29 +6,29 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { capitalize } from '~/utils/string/capitalize';
export const useDeleteOneObjectRecord = <T>({
export const useDeleteOneRecord = <T>({
objectNameSingular,
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
const { performOptimisticEvict } = useOptimisticEvict();
const {
objectMetadataItem: foundObjectMetadataItem,
objectNotFoundInMetadata,
deleteOneMutation,
objectMetadataItem,
objectMetadataItemNotFound,
deleteOneRecordMutation,
} = useObjectMetadataItem({
objectNameSingular,
});
// TODO: type this with a minimal type at least with Record<string, any>
const [mutate] = useMutation(deleteOneMutation);
const [mutate] = useMutation(deleteOneRecordMutation);
const deleteOneObject = useCallback(
const deleteOneRecord = useCallback(
async (idToDelete: string) => {
if (!foundObjectMetadataItem || !objectNameSingular) {
if (!objectMetadataItem || !objectNameSingular) {
return null;
}
const deletedObject = await mutate({
const deletedRecord = await mutate({
variables: {
idToDelete,
},
@ -36,18 +36,13 @@ export const useDeleteOneObjectRecord = <T>({
performOptimisticEvict(capitalize(objectNameSingular), 'id', idToDelete);
return deletedObject.data[`create${capitalize(objectNameSingular)}`] as T;
return deletedRecord.data[`create${capitalize(objectNameSingular)}`] as T;
},
[
performOptimisticEvict,
foundObjectMetadataItem,
mutate,
objectNameSingular,
],
[performOptimisticEvict, objectMetadataItem, mutate, objectNameSingular],
);
return {
deleteOneObject,
objectNotFoundInMetadata,
deleteOneRecord,
objectMetadataItemNotFound,
};
};

View File

@ -2,7 +2,7 @@ import { ReactNode } from 'react';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { FieldContext } from '@/ui/object/field/contexts/FieldContext';
import { InlineCellHotkeyScope } from '@/ui/object/record-inline-cell/types/InlineCellHotkeyScope';
@ -28,7 +28,7 @@ export const useFieldContext = ({
);
const useUpdateOneObjectMutation: () => [(params: any) => any, any] = () => {
const { updateOneObject } = useUpdateOneObjectRecord({
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular,
});
@ -42,7 +42,7 @@ export const useFieldContext = ({
};
};
}) => {
updateOneObject?.({
updateOneRecord?.({
idToUpdate: variables.where.id,
input: variables.data,
forceRefetch,

View File

@ -8,6 +8,7 @@ import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimis
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { getRecordOptimisticEffectDefinition } from '@/object-record/graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition';
import { filterUniqueRecordEdgesByCursor } from '@/object-record/utils/filterUniqueRecordEdgesByCursor';
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/search/hooks/useFilteredSearchEntityQuery';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { logError } from '~/utils/logError';
@ -15,18 +16,16 @@ import { capitalize } from '~/utils/string/capitalize';
import { cursorFamilyState } from '../states/cursorFamilyState';
import { hasNextPageFamilyState } from '../states/hasNextPageFamilyState';
import { isFetchingMoreObjectsFamilyState } from '../states/isFetchingMoreObjectsFamilyState';
import { PaginatedObjectType } from '../types/PaginatedObjectType';
import { isFetchingMoreRecordsFamilyState } from '../states/isFetchingMoreRecordsFamilyState';
import { PaginatedRecordType } from '../types/PaginatedRecordType';
import {
PaginatedObjectTypeEdge,
PaginatedObjectTypeResults,
} from '../types/PaginatedObjectTypeResults';
import { mapPaginatedObjectsToObjects } from '../utils/mapPaginatedObjectsToObjects';
PaginatedRecordTypeEdge,
PaginatedRecordTypeResults,
} from '../types/PaginatedRecordTypeResults';
import { mapPaginatedRecordsToRecords } from '../utils/mapPaginatedRecordsToRecords';
// TODO: test with a wrong name
// TODO: add zod to validate that we have at least id on each object
export const useFindManyObjectRecords = <
ObjectType extends { id: string } & Record<string, any>,
export const useFindManyRecords = <
RecordType extends { id: string } & Record<string, any>,
>({
objectNamePlural,
filter,
@ -38,7 +37,7 @@ export const useFindManyObjectRecords = <
filter?: any;
orderBy?: any;
limit?: number;
onCompleted?: (data: PaginatedObjectTypeResults<ObjectType>) => void;
onCompleted?: (data: PaginatedRecordTypeResults<RecordType>) => void;
skip?: boolean;
}) => {
const findManyQueryStateIdentifier =
@ -53,13 +52,16 @@ export const useFindManyObjectRecords = <
);
const [, setIsFetchingMoreObjects] = useRecoilState(
isFetchingMoreObjectsFamilyState(findManyQueryStateIdentifier),
isFetchingMoreRecordsFamilyState(findManyQueryStateIdentifier),
);
const { objectMetadataItem, objectNotFoundInMetadata, findManyQuery } =
useObjectMetadataItem({
objectNamePlural,
});
const {
objectMetadataItem,
objectMetadataItemNotFound,
findManyRecordsQuery,
} = useObjectMetadataItem({
objectNamePlural,
});
const { registerOptimisticEffect } = useOptimisticEffect({
objectNameSingular: objectMetadataItem?.nameSingular,
@ -68,8 +70,8 @@ export const useFindManyObjectRecords = <
const { enqueueSnackBar } = useSnackBar();
const { data, loading, error, fetchMore } = useQuery<
PaginatedObjectType<ObjectType>
>(findManyQuery, {
PaginatedRecordType<RecordType>
>(findManyRecordsQuery, {
skip: skip || !objectMetadataItem || !objectNamePlural,
variables: {
filter: filter ?? {},
@ -112,7 +114,7 @@ export const useFindManyObjectRecords = <
},
});
const fetchMoreObjects = useCallback(async () => {
const fetchMoreRecords = useCallback(async () => {
if (objectNamePlural && hasNextPage) {
setIsFetchingMoreObjects(true);
@ -124,27 +126,13 @@ export const useFindManyObjectRecords = <
lastCursor: isNonEmptyString(lastCursor) ? lastCursor : undefined,
},
updateQuery: (prev, { fetchMoreResult }) => {
const uniqueByCursor = (
a: PaginatedObjectTypeEdge<ObjectType>[],
) => {
const seenCursors = new Set();
return a.filter((item) => {
const currentCursor = item.cursor;
return seenCursors.has(currentCursor)
? false
: seenCursors.add(currentCursor);
});
};
const previousEdges = prev?.[objectNamePlural]?.edges;
const nextEdges = fetchMoreResult?.[objectNamePlural]?.edges;
let newEdges: any[] = [];
let newEdges: PaginatedRecordTypeEdge<RecordType>[] = [];
if (isNonEmptyArray(previousEdges) && isNonEmptyArray(nextEdges)) {
newEdges = uniqueByCursor([
newEdges = filterUniqueRecordEdgesByCursor([
...prev?.[objectNamePlural]?.edges,
...fetchMoreResult?.[objectNamePlural]?.edges,
]);
@ -158,7 +146,7 @@ export const useFindManyObjectRecords = <
edges: newEdges,
pageInfo: fetchMoreResult?.[objectNamePlural].pageInfo,
},
} as PaginatedObjectType<ObjectType>);
} as PaginatedRecordType<RecordType>);
},
});
} catch (error) {
@ -185,11 +173,11 @@ export const useFindManyObjectRecords = <
enqueueSnackBar,
]);
const objects = useMemo(
const records = useMemo(
() =>
objectNamePlural
? mapPaginatedObjectsToObjects({
pagedObjects: data,
? mapPaginatedRecordsToRecords({
pagedRecords: data,
objectNamePlural,
})
: [],
@ -198,10 +186,10 @@ export const useFindManyObjectRecords = <
return {
objectMetadataItem,
objects,
records,
loading,
error,
objectNotFoundInMetadata,
fetchMoreObjects,
objectMetadataItemNotFound,
fetchMoreRecords,
};
};

View File

@ -3,7 +3,7 @@ import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
export const useFindOneObjectRecord = <
export const useFindOneRecord = <
ObjectType extends { id: string } & Record<string, any>,
>({
objectNameSingular,
@ -17,22 +17,19 @@ export const useFindOneObjectRecord = <
skip?: boolean;
depth?: number;
}) => {
const {
objectMetadataItem: foundObjectMetadataItem,
objectNotFoundInMetadata,
findOneQuery,
} = useObjectMetadataItem(
{
objectNameSingular,
},
depth,
);
const { objectMetadataItem, objectMetadataItemNotFound, findOneRecordQuery } =
useObjectMetadataItem(
{
objectNameSingular,
},
depth,
);
const { data, loading, error } = useQuery<
{ [nameSingular: string]: ObjectType },
{ objectRecordId: string }
>(findOneQuery, {
skip: !foundObjectMetadataItem || !objectRecordId || skip,
>(findOneRecordQuery, {
skip: !objectMetadataItem || !objectRecordId || skip,
variables: {
objectRecordId: objectRecordId ?? '',
},
@ -43,13 +40,13 @@ export const useFindOneObjectRecord = <
},
});
const object =
const record =
objectNameSingular && data ? data[objectNameSingular] : undefined;
return {
object,
record,
loading,
error,
objectNotFoundInMetadata,
objectMetadataItemNotFound,
};
};

View File

@ -5,7 +5,7 @@ import { EMPTY_MUTATION } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { capitalize } from '~/utils/string/capitalize';
export const useGenerateCreateOneObjectMutation = ({
export const useGenerateCreateOneRecordMutation = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem | undefined | null;

View File

@ -5,7 +5,7 @@ import { EMPTY_QUERY } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { capitalize } from '~/utils/string/capitalize';
export const useGenerateFindManyCustomObjectsQuery = ({
export const useGenerateFindManyRecordsQuery = ({
objectMetadataItem,
depth,
}: {

View File

@ -4,7 +4,7 @@ import { useMapFieldMetadataToGraphQLQuery } from '@/object-metadata/hooks/useMa
import { EMPTY_QUERY } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const useGenerateFindOneCustomObjectQuery = ({
export const useGenerateFindOneRecordQuery = ({
objectMetadataItem,
depth,
}: {

View File

@ -5,7 +5,7 @@ import { EMPTY_MUTATION } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { capitalize } from '~/utils/string/capitalize';
export const getUpdateOneObjectMutationGraphQLField = ({
export const getUpdateOneRecordMutationGraphQLField = ({
objectNameSingular,
}: {
objectNameSingular: string;
@ -13,7 +13,7 @@ export const getUpdateOneObjectMutationGraphQLField = ({
return `update${capitalize(objectNameSingular)}`;
};
export const useGenerateUpdateOneObjectMutation = ({
export const useGenerateUpdateOneRecordMutation = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem | undefined | null;
@ -26,14 +26,14 @@ export const useGenerateUpdateOneObjectMutation = ({
const capitalizedObjectName = capitalize(objectMetadataItem.nameSingular);
const graphQLFieldForUpdateOneObjectMutation =
getUpdateOneObjectMutationGraphQLField({
const graphQLFieldForUpdateOneRecordMutation =
getUpdateOneRecordMutationGraphQLField({
objectNameSingular: objectMetadataItem.nameSingular,
});
return gql`
mutation UpdateOne${capitalizedObjectName}($idToUpdate: ID!, $input: ${capitalizedObjectName}UpdateInput!) {
${graphQLFieldForUpdateOneObjectMutation}(id: $idToUpdate, data: $input) {
${graphQLFieldForUpdateOneRecordMutation}(id: $idToUpdate, data: $input) {
id
${objectMetadataItem.fields
.map((field) => mapFieldMetadataToGraphQLQuery(field))

View File

@ -9,10 +9,10 @@ import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { getRecordOptimisticEffectDefinition } from '../graphql/optimistic-effect-definition/getRecordOptimisticEffectDefinition';
import { useFindManyObjectRecords } from './useFindManyObjectRecords';
import { useFindManyRecords } from './useFindManyRecords';
export const useObjectRecordTable = () => {
const { scopeId: objectNamePlural } = useRecordTable();
const { scopeId: objectNamePlural, setRecordTableData } = useRecordTable();
const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem(
{
@ -24,8 +24,6 @@ export const useObjectRecordTable = () => {
objectNameSingular: foundObjectMetadataItem?.nameSingular,
});
const { setRecordTableData } = useRecordTable();
const { tableFiltersState, tableSortsState } = useRecordTableScopedStates();
const tableFilters = useRecoilValue(tableFiltersState);
@ -40,7 +38,7 @@ export const useObjectRecordTable = () => {
foundObjectMetadataItem?.fields ?? [],
);
const { objects, loading, fetchMoreObjects } = useFindManyObjectRecords({
const { records, loading, fetchMoreRecords } = useFindManyRecords({
objectNamePlural,
filter,
orderBy,
@ -61,8 +59,8 @@ export const useObjectRecordTable = () => {
});
return {
objects,
records,
loading,
fetchMoreObjects,
fetchMoreRecords,
};
};

View File

@ -4,10 +4,11 @@ import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useDeleteOneObjectRecord } from '@/object-record/hooks/useDeleteOneObjectRecord';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { IconHeart, IconHeartOff, IconTrash } from '@/ui/display/icon';
import { actionBarEntriesState } from '@/ui/navigation/action-bar/states/actionBarEntriesState';
import { contextMenuEntriesState } from '@/ui/navigation/context-menu/states/contextMenuEntriesState';
import { ContextMenuEntry } from '@/ui/navigation/context-menu/types/ContextMenuEntry';
import { useRecordTable } from '@/ui/object/record-table/hooks/useRecordTable';
import { RecordTableScopeInternalContext } from '@/ui/object/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext';
import { selectedRowIdsSelector } from '@/ui/object/record-table/states/selectors/selectedRowIdsSelector';
@ -37,11 +38,9 @@ export const useRecordTableContextMenuEntries = (
recordTableScopeId: scopeId,
});
const { objectMetadataItem: foundObjectMetadataItem } = useObjectMetadataItem(
{
objectNamePlural,
},
);
const { objectMetadataItem } = useObjectMetadataItem({
objectNamePlural,
});
const { createFavorite, deleteFavorite, favorites } = useFavorites({
objectNamePlural,
@ -67,8 +66,8 @@ export const useRecordTableContextMenuEntries = (
}
});
const { deleteOneObject } = useDeleteOneObjectRecord({
objectNameSingular: foundObjectMetadataItem?.nameSingular,
const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: objectMetadataItem?.nameSingular,
});
const handleDeleteClick = useRecoilCallback(({ snapshot }) => async () => {
@ -78,9 +77,9 @@ export const useRecordTableContextMenuEntries = (
resetTableRowSelection();
if (deleteOneObject) {
if (deleteOneRecord) {
for (const rowId of rowIdsToDelete) {
await deleteOneObject(rowId);
await deleteOneRecord(rowId);
}
setTableRowIds((tableRowIds) =>
@ -109,24 +108,24 @@ export const useRecordTableContextMenuEntries = (
// Icon: IconNotes,
// onClick: () => {},
// },
{
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
Icon: isFavorite ? IconHeartOff : IconHeart,
onClick: () => handleFavoriteButtonClick(),
},
{
label: 'Delete',
Icon: IconTrash,
accent: 'danger',
onClick: () => handleDeleteClick(),
},
];
] as ContextMenuEntry[];
if (selectedRowIds.length > 1) {
contextMenuEntries.splice(2, 1);
if (selectedRowIds.length === 1) {
contextMenuEntries.unshift({
label: isFavorite ? 'Remove from favorites' : 'Add to favorites',
Icon: isFavorite ? IconHeartOff : IconHeart,
onClick: () => handleFavoriteButtonClick(),
});
}
setContextMenuEntries(contextMenuEntries as any);
setContextMenuEntries(contextMenuEntries);
}, [
selectedRowIds,
favorites,

View File

@ -5,23 +5,22 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
import { capitalize } from '~/utils/string/capitalize';
export const useUpdateOneObjectRecord = <T>({
export const useUpdateOneRecord = <T>({
objectNameSingular,
}: Pick<ObjectMetadataItemIdentifier, 'objectNameSingular'>) => {
const {
objectMetadataItem: foundObjectMetadataItem,
objectNotFoundInMetadata,
updateOneMutation,
objectMetadataItem,
objectMetadataItemNotFound,
updateOneRecordMutation,
getRecordFromCache,
findManyQuery,
findManyRecordsQuery,
} = useObjectMetadataItem({
objectNameSingular,
});
// TODO: type this with a minimal type at least with Record<string, any>
const [mutate] = useMutation(updateOneMutation);
const [mutateUpdateOneRecord] = useMutation(updateOneRecordMutation);
const updateOneObject = async ({
const updateOneRecord = async ({
idToUpdate,
input,
forceRefetch,
@ -30,13 +29,13 @@ export const useUpdateOneObjectRecord = <T>({
input: Record<string, any>;
forceRefetch?: boolean;
}) => {
if (!foundObjectMetadataItem || !objectNameSingular) {
if (!objectMetadataItem || !objectNameSingular) {
return null;
}
const cachedRecord = getRecordFromCache(idToUpdate);
const updatedObject = await mutate({
const updatedRecord = await mutateUpdateOneRecord({
variables: {
idToUpdate: idToUpdate,
input: {
@ -50,16 +49,16 @@ export const useUpdateOneObjectRecord = <T>({
},
},
refetchQueries: forceRefetch
? [getOperationName(findManyQuery) ?? '']
? [getOperationName(findManyRecordsQuery) ?? '']
: undefined,
awaitRefetchQueries: forceRefetch,
});
return updatedObject.data[`update${capitalize(objectNameSingular)}`] as T;
return updatedRecord.data[`update${capitalize(objectNameSingular)}`] as T;
};
return {
updateOneObject,
objectNotFoundInMetadata,
updateOneRecord,
objectMetadataItemNotFound,
};
};

View File

@ -1,9 +0,0 @@
import { atomFamily } from 'recoil';
export const isFetchingMoreObjectsFamilyState = atomFamily<
boolean,
string | undefined
>({
key: 'isFetchingMoreObjectsFamilyState',
default: false,
});

View File

@ -0,0 +1,9 @@
import { atomFamily } from 'recoil';
export const isFetchingMoreRecordsFamilyState = atomFamily<
boolean,
string | undefined
>({
key: 'isFetchingMoreRecordsFamilyState',
default: false,
});

View File

@ -1,5 +0,0 @@
import { PaginatedObjectTypeResults } from './PaginatedObjectTypeResults';
export type PaginatedObjectType<ObjectType extends { id: string }> = {
[objectNamePlural: string]: PaginatedObjectTypeResults<ObjectType>;
};

View File

@ -1,14 +0,0 @@
export type PaginatedObjectTypeEdge<ObjectType extends { id: string }> = {
node: ObjectType;
cursor: string;
};
export type PaginatedObjectTypeResults<ObjectType extends { id: string }> = {
__typename?: string;
edges: PaginatedObjectTypeEdge<ObjectType>[];
pageInfo: {
hasNextPage: boolean;
startCursor: string;
endCursor: string;
};
};

View File

@ -0,0 +1,5 @@
import { PaginatedRecordTypeResults } from './PaginatedRecordTypeResults';
export type PaginatedRecordType<RecordType extends { id: string }> = {
[objectNamePlural: string]: PaginatedRecordTypeResults<RecordType>;
};

View File

@ -0,0 +1,14 @@
export type PaginatedRecordTypeEdge<RecordType extends { id: string }> = {
node: RecordType;
cursor: string;
};
export type PaginatedRecordTypeResults<RecordType extends { id: string }> = {
__typename?: string;
edges: PaginatedRecordTypeEdge<RecordType>[];
pageInfo: {
hasNextPage: boolean;
startCursor: string;
endCursor: string;
};
};

View File

@ -0,0 +1,17 @@
import { PaginatedRecordTypeEdge } from '@/object-record/types/PaginatedRecordTypeResults';
export const filterUniqueRecordEdgesByCursor = <
RecordType extends { id: string },
>(
arrayToFilter: PaginatedRecordTypeEdge<RecordType>[],
) => {
const seenCursors = new Set();
return arrayToFilter.filter((item) => {
const currentCursor = item.cursor;
return seenCursors.has(currentCursor)
? false
: seenCursors.add(currentCursor);
});
};

View File

@ -4,7 +4,7 @@ import { EMPTY_MUTATION } from '@/object-metadata/hooks/useObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { capitalize } from '~/utils/string/capitalize';
export const useGenerateDeleteOneObjectMutation = ({
export const generateDeleteOneRecordMutation = ({
objectMetadataItem,
}: {
objectMetadataItem: ObjectMetadataItem | undefined | null;

View File

@ -1,24 +0,0 @@
export const mapPaginatedObjectsToObjects = <
ObjectType extends { id: string } & Record<string, any>,
ObjectTypeQuery extends {
[objectNamePlural: string]: {
edges: ObjectEdge[];
};
},
ObjectEdge extends {
node: ObjectType;
},
>({
pagedObjects,
objectNamePlural,
}: {
pagedObjects: ObjectTypeQuery | undefined;
objectNamePlural: string;
}) => {
const formattedObjects: ObjectType[] =
pagedObjects?.[objectNamePlural]?.edges?.map((objectEdge: ObjectEdge) => ({
...objectEdge.node,
})) ?? [];
return formattedObjects;
};

View File

@ -0,0 +1,24 @@
export const mapPaginatedRecordsToRecords = <
RecordType extends { id: string } & Record<string, any>,
RecordTypeQuery extends {
[objectNamePlural: string]: {
edges: RecordEdge[];
};
},
RecordEdge extends {
node: RecordType;
},
>({
pagedRecords,
objectNamePlural,
}: {
pagedRecords: RecordTypeQuery | undefined;
objectNamePlural: string;
}) => {
const formattedRecords: RecordType[] =
pagedRecords?.[objectNamePlural]?.edges?.map((recordEdge: RecordEdge) => ({
...recordEdge.node,
})) ?? [];
return formattedRecords;
};