Optimize metadata queries (#7013)
In this PR: 1. Refactor guards to avoid duplicated queries: WorkspaceAuthGuard and UserAuthGuard only check for existence of workspace and user in the request without querying the database
This commit is contained in:
committed by
Charles Bochet
parent
cf8b1161cc
commit
523df5398a
@ -4,17 +4,6 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { FieldMetadata } from './FieldMetadata';
|
||||
|
||||
export type FieldDefinitionRelationType =
|
||||
| 'FROM_MANY_OBJECTS'
|
||||
| 'FROM_ONE_OBJECT'
|
||||
| 'TO_MANY_OBJECTS'
|
||||
| 'TO_ONE_OBJECT';
|
||||
|
||||
export type RelationDirections = {
|
||||
from: FieldDefinitionRelationType;
|
||||
to: FieldDefinitionRelationType;
|
||||
};
|
||||
|
||||
export type FieldDefinition<T extends FieldMetadata> = {
|
||||
fieldMetadataId: string;
|
||||
label: string;
|
||||
|
||||
@ -3,8 +3,8 @@ import { ThemeColor } from 'twenty-ui';
|
||||
import { RATING_VALUES } from '@/object-record/record-field/meta-types/constants/RatingValues';
|
||||
import { ZodHelperLiteral } from '@/object-record/record-field/types/ZodHelperLiteral';
|
||||
import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect';
|
||||
import { WithNarrowedStringLiteralProperty } from '~/types/WithNarrowedStringLiteralProperty';
|
||||
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { CurrencyCode } from './CurrencyCode';
|
||||
|
||||
export type FieldUuidMetadata = {
|
||||
@ -110,35 +110,17 @@ export type FieldPositionMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldDefinitionRelationType =
|
||||
| 'FROM_MANY_OBJECTS'
|
||||
| 'FROM_ONE_OBJECT'
|
||||
| 'TO_MANY_OBJECTS'
|
||||
| 'TO_ONE_OBJECT';
|
||||
|
||||
export type FieldRelationMetadata = {
|
||||
fieldName: string;
|
||||
objectMetadataNameSingular?: string;
|
||||
relationFieldMetadataId: string;
|
||||
relationObjectMetadataNamePlural: string;
|
||||
relationObjectMetadataNameSingular: string;
|
||||
relationType?: FieldDefinitionRelationType;
|
||||
relationType?: RelationDefinitionType;
|
||||
targetFieldMetadataName?: string;
|
||||
useEditButton?: boolean;
|
||||
};
|
||||
|
||||
export type FieldRelationOneMetadata = WithNarrowedStringLiteralProperty<
|
||||
FieldRelationMetadata,
|
||||
'relationType',
|
||||
'TO_ONE_OBJECT'
|
||||
>;
|
||||
|
||||
export type FieldRelationManyMetadata = WithNarrowedStringLiteralProperty<
|
||||
FieldRelationMetadata,
|
||||
'relationType',
|
||||
'FROM_MANY_OBJECTS'
|
||||
>;
|
||||
|
||||
export type FieldSelectMetadata = {
|
||||
objectMetadataNameSingular?: string;
|
||||
fieldName: string;
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldRelationManyMetadata } from '../FieldMetadata';
|
||||
import { FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldRelationFromManyObjects = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>,
|
||||
): field is FieldDefinition<FieldRelationManyMetadata> =>
|
||||
isFieldRelation(field) && field.metadata.relationType === 'FROM_MANY_OBJECTS';
|
||||
): field is FieldDefinition<FieldMetadata> =>
|
||||
isFieldRelation(field) &&
|
||||
field.metadata.relationType === RelationDefinitionType.OneToMany;
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldRelationOneMetadata } from '../FieldMetadata';
|
||||
import { FieldMetadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldRelationToOneObject = (
|
||||
field: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>,
|
||||
): field is FieldDefinition<FieldRelationOneMetadata> =>
|
||||
isFieldRelation(field) && field.metadata.relationType === 'TO_ONE_OBJECT';
|
||||
): field is FieldDefinition<FieldMetadata> =>
|
||||
isFieldRelation(field) &&
|
||||
field.metadata.relationType === RelationDefinitionType.ManyToOne;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
csvDownloader,
|
||||
displayedExportProgress,
|
||||
@ -35,7 +36,10 @@ describe('generateCsv', () => {
|
||||
{ label: 'Nested', metadata: { fieldName: 'nested' } },
|
||||
{
|
||||
label: 'Relation',
|
||||
metadata: { fieldName: 'relation', relationType: 'TO_ONE_OBJECT' },
|
||||
metadata: {
|
||||
fieldName: 'relation',
|
||||
relationType: RelationDefinitionType.ManyToOne,
|
||||
},
|
||||
},
|
||||
] as ColumnDefinition<FieldMetadata>[];
|
||||
const rows = [
|
||||
|
||||
@ -9,6 +9,7 @@ import {
|
||||
} from '@/object-record/record-index/options/hooks/useTableData';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
@ -43,7 +44,7 @@ export const generateCsv: GenerateExport = ({
|
||||
const columnsToExport = columns.filter(
|
||||
(col) =>
|
||||
!('relationType' in col.metadata && col.metadata.relationType) ||
|
||||
col.metadata.relationType === 'TO_ONE_OBJECT',
|
||||
col.metadata.relationType === RelationDefinitionType.ManyToOne,
|
||||
);
|
||||
|
||||
const objectIdColumn: ColumnDefinition<FieldMetadata> = {
|
||||
|
||||
@ -7,6 +7,7 @@ import { Task } from '@/activities/types/Task';
|
||||
import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
|
||||
import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
@ -56,6 +57,8 @@ export const RecordShowContainer = ({
|
||||
objectNameSingular,
|
||||
});
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const { labelIdentifierFieldMetadataItem } =
|
||||
useLabelIdentifierFieldMetadataItem({
|
||||
objectNameSingular,
|
||||
@ -119,7 +122,7 @@ export const RecordShowContainer = ({
|
||||
const availableFieldMetadataItems = objectMetadataItem.fields
|
||||
.filter(
|
||||
(fieldMetadataItem) =>
|
||||
isFieldCellSupported(fieldMetadataItem) &&
|
||||
isFieldCellSupported(fieldMetadataItem, objectMetadataItems) &&
|
||||
fieldMetadataItem.id !== labelIdentifierFieldMetadataItem?.id,
|
||||
)
|
||||
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useCallback, useContext } from 'react';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconComponent,
|
||||
@ -11,6 +11,7 @@ import {
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
|
||||
import { RecordChip } from '@/object-record/components/RecordChip';
|
||||
@ -37,6 +38,7 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { AnimatedEaseInOut } from '@/ui/utilities/animation/components/AnimatedEaseInOut';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledListItem = styled(RecordDetailRecordsListItem)<{
|
||||
isDropdownOpen?: boolean;
|
||||
@ -89,12 +91,14 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
relationType,
|
||||
} = fieldDefinition.metadata as FieldRelationMetadata;
|
||||
|
||||
const isToOneObject = relationType === 'TO_ONE_OBJECT';
|
||||
const isToOneObject = relationType === RelationDefinitionType.ManyToOne;
|
||||
const { objectMetadataItem: relationObjectMetadataItem } =
|
||||
useObjectMetadataItem({
|
||||
objectNameSingular: relationObjectMetadataNameSingular,
|
||||
});
|
||||
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const { updateOneRecord: updateOneRelationRecord } = useUpdateOneRecord({
|
||||
@ -111,7 +115,7 @@ export const RecordDetailRelationRecordsListItem = ({
|
||||
const availableRelationFieldMetadataItems = relationObjectMetadataItem.fields
|
||||
.filter(
|
||||
(fieldMetadataItem) =>
|
||||
isFieldCellSupported(fieldMetadataItem) &&
|
||||
isFieldCellSupported(fieldMetadataItem, objectMetadataItems) &&
|
||||
fieldMetadataItem.id !==
|
||||
relationObjectMetadataItem.labelIdentifierFieldMetadataId &&
|
||||
fieldMetadataItem.id !== relationFieldMetadataId,
|
||||
|
||||
@ -32,6 +32,7 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
|
||||
type RecordDetailRelationSectionProps = {
|
||||
loading: boolean;
|
||||
@ -67,8 +68,8 @@ export const RecordDetailRelationSection = ({
|
||||
>(recordStoreFamilySelector({ recordId, fieldName }));
|
||||
|
||||
// TODO: use new relation type
|
||||
const isToOneObject = relationType === 'TO_ONE_OBJECT';
|
||||
const isFromManyObjects = relationType === 'FROM_MANY_OBJECTS';
|
||||
const isToOneObject = relationType === RelationDefinitionType.ManyToOne;
|
||||
const isToManyObjects = RelationDefinitionType.OneToMany;
|
||||
|
||||
const relationRecords: ObjectRecord[] =
|
||||
fieldValue && isToOneObject
|
||||
@ -160,7 +161,7 @@ export const RecordDetailRelationSection = ({
|
||||
<RecordDetailSectionHeader
|
||||
title={fieldDefinition.label}
|
||||
link={
|
||||
isFromManyObjects
|
||||
isToManyObjects
|
||||
? {
|
||||
to: filterLinkHref,
|
||||
label: `All (${relationRecords.length})`,
|
||||
|
||||
@ -34,22 +34,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: '0cf72416-3d94-4d94-abf3-7dc9d734435b',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
fromObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: '79c2d29c-76f6-432f-91c9-df1259b73d95',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'company',
|
||||
namePlural: 'companies',
|
||||
isSystem: false,
|
||||
isRemote: false,
|
||||
},
|
||||
fromFieldMetadataId: '7b281010-5f47-4771-b3f5-f4bcd24ed1b5',
|
||||
},
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -94,8 +78,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: "''",
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -114,8 +96,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: "''",
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -134,22 +114,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: 'd76f949d-023d-4b45-a71e-f39e3b1562ba',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: '82222ca2-dd40-44ec-b8c5-eb0eca9ec625',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'activityTarget',
|
||||
namePlural: 'activityTargets',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: 'f5f515cc-6d8a-44c3-b2d4-f04b9868a9c5',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -194,22 +158,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: 'a5a61d23-8ac9-4014-9441-ec3a1781a661',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: '494b9b7c-a44e-4d52-b274-cdfb0e322165',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'opportunity',
|
||||
namePlural: 'opportunities',
|
||||
isSystem: false,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: '86559a6f-6afc-4d5c-9bed-fc74d063791b',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -254,22 +202,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: '456f7875-b48c-4795-a0c7-a69d7339afee',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: 'eba13fca-57b7-470c-8c23-a0e640e04ffb',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'calendarEventParticipant',
|
||||
namePlural: 'calendarEventParticipants',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: 'c1cdebda-b514-4487-9b9c-aa59d8fca8eb',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -314,8 +246,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: 'now',
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -334,22 +264,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: '31542774-fb15-4d01-b00b-8fc94887f458',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: 'f08422e2-14cd-4966-9cd3-bce0302cc56f',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'favorite',
|
||||
namePlural: 'favorites',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: '67d28b17-ff3c-49b4-a6da-1354be9634b0',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -394,8 +308,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: {
|
||||
primaryLinkUrl: "''",
|
||||
primaryLinkLabel: "''",
|
||||
@ -417,22 +329,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: 'c0cc3456-afa4-46e0-820d-2db0b63a8273',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: '0e3c9a9d-8a60-4671-a466-7b840a422da2',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'attachment',
|
||||
namePlural: 'attachments',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: 'a920a0d6-8e71-4ab8-90b9-ab540e04732a',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -477,8 +373,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: "''",
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -497,8 +391,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -517,8 +409,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: "''",
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -537,8 +427,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: "''",
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -557,8 +445,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: 'now',
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -577,8 +463,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
@ -597,22 +481,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: '25150feb-fcd7-407e-b5fa-ffe58a0450ac',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: '83b5ff3e-975e-4dc9-ba4d-c645a0d8afb2',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'timelineActivity',
|
||||
namePlural: 'timelineActivities',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: '556a12d4-ef0a-4232-963f-0f317f4c5ef5',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -657,8 +525,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: {
|
||||
lastName: "''",
|
||||
firstName: "''",
|
||||
@ -680,8 +546,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: {
|
||||
primaryLinkUrl: "''",
|
||||
primaryLinkLabel: "''",
|
||||
@ -703,22 +567,6 @@ export const mockPerformance = {
|
||||
isNullable: true,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: {
|
||||
__typename: 'relation',
|
||||
id: 'e2eb7156-6e65-4bf8-922b-670179744f27',
|
||||
relationType: 'ONE_TO_MANY',
|
||||
toObjectMetadata: {
|
||||
__typename: 'object',
|
||||
id: 'ffd8e640-84b7-4ed6-99e9-14def0f9d82b',
|
||||
dataSourceId: '0fd9fd54-0e8d-4f78-911c-76b33436a768',
|
||||
nameSingular: 'messageParticipant',
|
||||
namePlural: 'messageParticipants',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
toFieldMetadataId: '8c4593a1-ad40-4681-92fe-43ad4fe60205',
|
||||
},
|
||||
toRelationMetadata: null,
|
||||
defaultValue: null,
|
||||
options: null,
|
||||
relationDefinition: {
|
||||
@ -763,8 +611,6 @@ export const mockPerformance = {
|
||||
isNullable: false,
|
||||
createdAt: '2024-05-16T10:54:27.788Z',
|
||||
updatedAt: '2024-05-16T10:54:27.788Z',
|
||||
fromRelationMetadata: null,
|
||||
toRelationMetadata: null,
|
||||
defaultValue: 'uuid',
|
||||
options: null,
|
||||
relationDefinition: null,
|
||||
|
||||
@ -6,7 +6,10 @@ import { useOpenSpreadsheetImportDialog } from '@/spreadsheet-import/hooks/useOp
|
||||
import { SpreadsheetImportDialogOptions } from '@/spreadsheet-import/types';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationDefinitionType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useOpenObjectRecordsSpreasheetImportDialog = (
|
||||
objectNameSingular: string,
|
||||
@ -37,7 +40,8 @@ export const useOpenObjectRecordsSpreasheetImportDialog = (
|
||||
(!fieldMetadataItem.isSystem || fieldMetadataItem.name === 'id') &&
|
||||
fieldMetadataItem.name !== 'createdAt' &&
|
||||
(fieldMetadataItem.type !== FieldMetadataType.Relation ||
|
||||
fieldMetadataItem.toRelationMetadata),
|
||||
fieldMetadataItem.relationDefinition?.direction ===
|
||||
RelationDefinitionType.ManyToOne),
|
||||
)
|
||||
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
|
||||
fieldMetadataItemA.name.localeCompare(fieldMetadataItemB.name),
|
||||
|
||||
@ -2,14 +2,14 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
|
||||
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { TABLE_COLUMNS_DENY_LIST } from '@/object-record/relation-picker/constants/TableColumnsDenyList';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const filterAvailableTableColumns = (
|
||||
columnDefinition: ColumnDefinition<FieldMetadata>,
|
||||
): boolean => {
|
||||
if (
|
||||
isFieldRelation(columnDefinition) &&
|
||||
columnDefinition.metadata?.relationType !== 'TO_ONE_OBJECT' &&
|
||||
columnDefinition.metadata?.relationType !== 'FROM_MANY_OBJECTS'
|
||||
columnDefinition.metadata?.relationType !== RelationDefinitionType.ManyToOne
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4,10 +4,7 @@ import { generateEmptyFieldValue } from '@/object-record/utils/generateEmptyFiel
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const generateDefaultFieldValue = (
|
||||
fieldMetadataItem: Pick<
|
||||
FieldMetadataItem,
|
||||
'defaultValue' | 'type' | 'fromRelationMetadata'
|
||||
>,
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'defaultValue' | 'type'>,
|
||||
) => {
|
||||
const defaultValue = isFieldValueEmpty({
|
||||
fieldValue: fieldMetadataItem.defaultValue,
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationDefinitionType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const generateEmptyFieldValue = (
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'type' | 'fromRelationMetadata'>,
|
||||
fieldMetadataItem: Pick<FieldMetadataItem, 'type' | 'relationDefinition'>,
|
||||
) => {
|
||||
switch (fieldMetadataItem.type) {
|
||||
case FieldMetadataType.Email:
|
||||
@ -62,10 +63,8 @@ export const generateEmptyFieldValue = (
|
||||
}
|
||||
case FieldMetadataType.Relation: {
|
||||
if (
|
||||
!isNonEmptyString(
|
||||
fieldMetadataItem.fromRelationMetadata?.toObjectMetadata
|
||||
?.nameSingular,
|
||||
)
|
||||
fieldMetadataItem.relationDefinition?.direction ===
|
||||
RelationDefinitionType.ManyToOne
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isObjectMetadataAvailableForRelation } from '@/object-metadata/utils/isObjectMetadataAvailableForRelation';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationMetadataType,
|
||||
RelationDefinitionType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
export const isFieldCellSupported = (
|
||||
fieldMetadataItem: FieldMetadataItem,
|
||||
objectMetadataItems: ObjectMetadataItem[],
|
||||
) => {
|
||||
if (
|
||||
[
|
||||
FieldMetadataType.Uuid,
|
||||
@ -18,17 +22,17 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
}
|
||||
|
||||
if (fieldMetadataItem.type === FieldMetadataType.Relation) {
|
||||
const relationMetadata =
|
||||
fieldMetadataItem.fromRelationMetadata ??
|
||||
fieldMetadataItem.toRelationMetadata;
|
||||
const relationObjectMetadataItem =
|
||||
fieldMetadataItem.fromRelationMetadata?.toObjectMetadata ??
|
||||
fieldMetadataItem.toRelationMetadata?.fromObjectMetadata;
|
||||
const relationObjectMetadataItemId =
|
||||
fieldMetadataItem.relationDefinition?.targetObjectMetadata.id;
|
||||
|
||||
const relationObjectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.id === relationObjectMetadataItemId,
|
||||
);
|
||||
|
||||
// Hack to display targets on Notes and Tasks
|
||||
if (
|
||||
fieldMetadataItem.fromRelationMetadata?.toObjectMetadata?.nameSingular ===
|
||||
CoreObjectNameSingular.NoteTarget &&
|
||||
fieldMetadataItem.relationDefinition?.targetObjectMetadata
|
||||
?.nameSingular === CoreObjectNameSingular.NoteTarget &&
|
||||
fieldMetadataItem.relationDefinition?.sourceObjectMetadata
|
||||
.nameSingular === CoreObjectNameSingular.Note
|
||||
) {
|
||||
@ -36,8 +40,8 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
}
|
||||
|
||||
if (
|
||||
fieldMetadataItem.fromRelationMetadata?.toObjectMetadata?.nameSingular ===
|
||||
CoreObjectNameSingular.TaskTarget &&
|
||||
fieldMetadataItem.relationDefinition?.targetObjectMetadata
|
||||
?.nameSingular === CoreObjectNameSingular.TaskTarget &&
|
||||
fieldMetadataItem.relationDefinition?.sourceObjectMetadata
|
||||
.nameSingular === CoreObjectNameSingular.Task
|
||||
) {
|
||||
@ -45,9 +49,10 @@ export const isFieldCellSupported = (fieldMetadataItem: FieldMetadataItem) => {
|
||||
}
|
||||
|
||||
if (
|
||||
!relationMetadata ||
|
||||
!fieldMetadataItem.relationDefinition ||
|
||||
// TODO: Many to many relations are not supported yet.
|
||||
relationMetadata.relationType === RelationMetadataType.ManyToMany ||
|
||||
fieldMetadataItem.relationDefinition.direction ===
|
||||
RelationDefinitionType.ManyToMany ||
|
||||
!relationObjectMetadataItem ||
|
||||
!isObjectMetadataAvailableForRelation(relationObjectMetadataItem)
|
||||
) {
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isFieldRelationToOneValue } from '@/object-record/record-field/types/guards/isFieldRelationToOneValue';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { RelationDefinitionType } from '~/generated-metadata/graphql';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { getUrlHostName } from '~/utils/url/getUrlHostName';
|
||||
@ -29,7 +29,8 @@ export const sanitizeRecordInput = ({
|
||||
|
||||
if (
|
||||
fieldMetadataItem.type === FieldMetadataType.Relation &&
|
||||
isFieldRelationToOneValue(fieldValue)
|
||||
fieldMetadataItem.relationDefinition?.direction ===
|
||||
RelationDefinitionType.ManyToOne
|
||||
) {
|
||||
const relationIdFieldName = `${fieldMetadataItem.name}Id`;
|
||||
const relationIdFieldMetadataItem = objectMetadataItem.fields.find(
|
||||
@ -41,6 +42,14 @@ export const sanitizeRecordInput = ({
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
fieldMetadataItem.type === FieldMetadataType.Relation &&
|
||||
fieldMetadataItem.relationDefinition?.direction ===
|
||||
RelationDefinitionType.OneToMany
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return [fieldName, fieldValue];
|
||||
})
|
||||
.filter(isDefined),
|
||||
|
||||
Reference in New Issue
Block a user