diff --git a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldConfigure.tsx b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldConfigure.tsx index c442c2639..457d65033 100644 --- a/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldConfigure.tsx +++ b/packages/twenty-front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldConfigure.tsx @@ -145,14 +145,15 @@ export const SettingsObjectNewFieldConfigure = () => { }); } + navigate(SettingsPath.ObjectDetail, { + objectNamePlural, + }); + // TODO: fix optimistic update logic // Forcing a refetch for now but it's not ideal await apolloClient.refetchQueries({ include: ['FindManyViews', 'CombinedFindManyRecords'], }); - navigate(SettingsPath.ObjectDetail, { - objectNamePlural, - }); setIsSaving(false); } catch (error) { setIsSaving(false); diff --git a/packages/twenty-server/src/engine/api/graphql/graphql-config/hooks/use-cached-metadata.ts b/packages/twenty-server/src/engine/api/graphql/graphql-config/hooks/use-cached-metadata.ts index bcb118d95..771bacf50 100644 --- a/packages/twenty-server/src/engine/api/graphql/graphql-config/hooks/use-cached-metadata.ts +++ b/packages/twenty-server/src/engine/api/graphql/graphql-config/hooks/use-cached-metadata.ts @@ -1,3 +1,5 @@ +import { createHash } from 'crypto'; + import { isDefined } from 'class-validator'; import { Plugin } from 'graphql-yoga'; @@ -20,8 +22,11 @@ export function useCachedMetadata(config: CacheMetadataPluginConfig): Plugin { const localeCacheKey = isDefined(serverContext.req.headers['x-locale']) ? `:${locale}` : ''; + const queryHash = createHash('sha256') + .update(serverContext.req.body.query) + .digest('hex'); - return `graphql:operations:${operationName}:${workspaceId}:${workspaceMetadataVersion}${localeCacheKey}`; + return `graphql:operations:${operationName}:${workspaceId}:${workspaceMetadataVersion}${localeCacheKey}:${queryHash}`; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts index 631bee561..d6d694d5e 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import DataLoader from 'dataloader'; +import { APP_LOCALES } from 'twenty-shared/translations'; import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface'; @@ -37,6 +38,7 @@ export type RelationLoaderPayload = { export type FieldMetadataLoaderPayload = { workspaceId: string; objectMetadata: Pick; + locale?: keyof typeof APP_LOCALES; }; export type IndexMetadataLoaderPayload = { @@ -140,11 +142,34 @@ export class DataloaderService { Object.values(objectMetadataMaps.byId[id].fieldsById).map( // TODO: fix this as we should merge FieldMetadataEntity and FieldMetadataInterface (fieldMetadata) => { + const overridesFieldToCompute = [ + 'icon', + 'label', + 'description', + ] as const satisfies (keyof FieldMetadataInterface)[]; + + const overrides = overridesFieldToCompute.reduce< + Partial< + Record<(typeof overridesFieldToCompute)[number], string> + > + >( + (acc, field) => ({ + ...acc, + [field]: this.fieldMetadataService.resolveOverridableString( + fieldMetadata, + field, + dataLoaderParams[0].locale, + ), + }), + {}, + ); + return { ...fieldMetadata, createdAt: new Date(fieldMetadata.createdAt), updatedAt: new Date(fieldMetadata.updatedAt), workspaceId: workspaceId, + ...overrides, }; }, ), diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts index 63158e972..ca0b7fed8 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.resolver.ts @@ -55,43 +55,6 @@ export class FieldMetadataResolver { private readonly beforeUpdateOneField: BeforeUpdateOneField, ) {} - @ResolveField(() => String, { nullable: true }) - async label( - @Parent() fieldMetadata: FieldMetadataDTO, - @Context() context: I18nContext, - ): Promise { - return this.fieldMetadataService.resolveOverridableString( - fieldMetadata, - 'label', - context.req.headers['x-locale'], - ); - } - - @ResolveField(() => String, { nullable: true }) - async description( - @Parent() fieldMetadata: FieldMetadataDTO, - @Context() context: I18nContext, - ): Promise { - return this.fieldMetadataService.resolveOverridableString( - fieldMetadata, - 'description', - context.req.headers['x-locale'], - ); - } - - @UseGuards(SettingsPermissionsGuard(SettingPermissionType.DATA_MODEL)) - @ResolveField(() => String, { nullable: true }) - async icon( - @Parent() fieldMetadata: FieldMetadataDTO, - @Context() context: I18nContext, - ): Promise { - return this.fieldMetadataService.resolveOverridableString( - fieldMetadata, - 'icon', - context.req.headers['x-locale'], - ); - } - @UseGuards(SettingsPermissionsGuard(SettingPermissionType.DATA_MODEL)) @Mutation(() => FieldMetadataDTO) async createOneField( diff --git a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts index 321422da2..bf63cdba3 100644 --- a/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/field-metadata/field-metadata.service.ts @@ -4,7 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { i18n } from '@lingui/core'; import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import isEmpty from 'lodash.isempty'; -import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations'; +import { APP_LOCALES } from 'twenty-shared/translations'; import { FieldMetadataType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; import { DataSource, FindOneOptions, In, Repository } from 'typeorm'; @@ -608,26 +608,18 @@ export class FieldMetadataService extends TypeOrmQueryService, labelKey: 'label' | 'description' | 'icon', locale: keyof typeof APP_LOCALES | undefined, - ): Promise { + ): string { if (fieldMetadata.isCustom) { return fieldMetadata[labelKey] ?? ''; } - if (!locale || locale === SOURCE_LOCALE) { - if ( - fieldMetadata.standardOverrides && - isDefined(fieldMetadata.standardOverrides[labelKey]) - ) { - return fieldMetadata.standardOverrides[labelKey] as string; - } - - return fieldMetadata[labelKey] ?? ''; - } - const translationValue = // @ts-expect-error legacy noImplicitAny fieldMetadata.standardOverrides?.translations?.[locale]?.[labelKey]; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts index 3b87fe4db..e9abb1f4c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.resolver.ts @@ -134,13 +134,14 @@ export class ObjectMetadataResolver { async fieldsList( @AuthWorkspace() workspace: Workspace, @Parent() objectMetadata: ObjectMetadataDTO, - @Context() context: { loaders: IDataloaders }, + @Context() context: { loaders: IDataloaders } & I18nContext, ): Promise { try { const fieldMetadataItems = await context.loaders.fieldMetadataLoader.load( { objectMetadata, workspaceId: workspace.id, + locale: context.req.headers['x-locale'], }, );