Refactor flat entity maps to be universal oriented (#17665)
# Introduction
In preparation of the workspace agnostic builder, we're migrating
`FlatEntityMaps` to be universal identifier oriented and based
As in the builder context there're won't be any ids at all
Please also note that the FlatEntity is a UniversalFlatEntity superset
From
```ts
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
export type FlatEntityMaps<T extends SyncableFlatEntity> = {
byId: Partial<Record<string, T>>;
idByUniversalIdentifier: Partial<Record<string, string>>;
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>;
};
```
To
```ts
export type FlatEntityMaps<
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
> = {
byUniversalIdentifier: Partial<Record<string, T>>;
universalIdentifierById: Partial<Record<string, string>>;
universalIdentifiersByApplicationId: Partial<Record<string, string[]>>; // this might make more sense to be migrated to universalIdentifiersByApplicationUniversalIdentifier but it's the main topic of this PR
};
```
## Low level maps tools
Had to refactor find | create | delete | replace | find-many | get-sub
tools ( through mutations and or throw equivalent )
This commit is contained in:
+25
-6
@@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
@@ -31,7 +32,10 @@ export class DashboardSyncService {
|
||||
},
|
||||
);
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[pageLayoutId];
|
||||
const pageLayout = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: pageLayoutId,
|
||||
flatEntityMaps: flatPageLayoutMaps,
|
||||
});
|
||||
|
||||
return (
|
||||
isDefined(pageLayout) && pageLayout.type === PageLayoutType.DASHBOARD
|
||||
@@ -96,13 +100,19 @@ export class DashboardSyncService {
|
||||
},
|
||||
);
|
||||
|
||||
const tab = flatPageLayoutTabMaps.byId[tabId];
|
||||
const tab = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: tabId,
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(tab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[tab.pageLayoutId];
|
||||
const pageLayout = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: tab.pageLayoutId,
|
||||
flatEntityMaps: flatPageLayoutMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(pageLayout) ||
|
||||
@@ -143,19 +153,28 @@ export class DashboardSyncService {
|
||||
},
|
||||
);
|
||||
|
||||
const widget = flatPageLayoutWidgetMaps.byId[widgetId];
|
||||
const widget = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: widgetId,
|
||||
flatEntityMaps: flatPageLayoutWidgetMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(widget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tab = flatPageLayoutTabMaps.byId[widget.pageLayoutTabId];
|
||||
const tab = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: widget.pageLayoutTabId,
|
||||
flatEntityMaps: flatPageLayoutTabMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(tab)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageLayout = flatPageLayoutMaps.byId[tab.pageLayoutId];
|
||||
const pageLayout = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: tab.pageLayoutId,
|
||||
flatEntityMaps: flatPageLayoutMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(pageLayout) ||
|
||||
|
||||
+58
-10
@@ -58,14 +58,38 @@ describe('BarChartDataService', () => {
|
||||
mockExecuteGroupByQuery = jest.fn();
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps = jest.fn().mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[mockGroupByField.id]: mockGroupByField,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
[mockSelectField.id]: mockSelectField,
|
||||
byUniversalIdentifier: {
|
||||
'group-by-field-universal-id': {
|
||||
...mockGroupByField,
|
||||
universalIdentifier: 'group-by-field-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
'select-field-universal-id': {
|
||||
...mockSelectField,
|
||||
universalIdentifier: 'select-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[mockGroupByField.id]: 'group-by-field-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
[mockSelectField.id]: 'select-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -294,14 +318,38 @@ describe('BarChartDataService', () => {
|
||||
beforeEach(() => {
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[mockGroupByField.id]: mockGroupByField,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
[mockSelectField.id]: mockSelectField,
|
||||
byUniversalIdentifier: {
|
||||
'group-by-field-universal-id': {
|
||||
...mockGroupByField,
|
||||
universalIdentifier: 'group-by-field-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
'select-field-universal-id': {
|
||||
...mockSelectField,
|
||||
universalIdentifier: 'select-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[mockGroupByField.id]: 'group-by-field-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
[mockSelectField.id]: 'select-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
+35
-6
@@ -65,15 +65,44 @@ describe('LineChartDataService', () => {
|
||||
useValue: {
|
||||
getOrRecomputeManyOrAllFlatEntityMaps: jest.fn().mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[mockGroupByFieldX.id]: mockGroupByFieldX,
|
||||
[mockGroupByFieldXText.id]: mockGroupByFieldXText,
|
||||
[mockGroupByFieldY.id]: mockGroupByFieldY,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
byUniversalIdentifier: {
|
||||
'group-by-field-x-universal-id': {
|
||||
...mockGroupByFieldX,
|
||||
universalIdentifier: 'group-by-field-x-universal-id',
|
||||
},
|
||||
'group-by-field-x-text-universal-id': {
|
||||
...mockGroupByFieldXText,
|
||||
universalIdentifier: 'group-by-field-x-text-universal-id',
|
||||
},
|
||||
'group-by-field-y-universal-id': {
|
||||
...mockGroupByFieldY,
|
||||
universalIdentifier: 'group-by-field-y-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[mockGroupByFieldX.id]: 'group-by-field-x-universal-id',
|
||||
[mockGroupByFieldXText.id]:
|
||||
'group-by-field-x-text-universal-id',
|
||||
[mockGroupByFieldY.id]: 'group-by-field-y-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
+102
-17
@@ -56,14 +56,38 @@ describe('PieChartDataService', () => {
|
||||
mockExecuteGroupByQuery = jest.fn();
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps = jest.fn().mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[mockGroupByField.id]: mockGroupByField,
|
||||
[mockSelectField.id]: mockSelectField,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
byUniversalIdentifier: {
|
||||
'group-by-field-universal-id': {
|
||||
...mockGroupByField,
|
||||
universalIdentifier: 'group-by-field-universal-id',
|
||||
},
|
||||
'select-field-universal-id': {
|
||||
...mockSelectField,
|
||||
universalIdentifier: 'select-field-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[mockGroupByField.id]: 'group-by-field-universal-id',
|
||||
[mockSelectField.id]: 'select-field-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -244,13 +268,33 @@ describe('PieChartDataService', () => {
|
||||
it('should format select field values using option labels', async () => {
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[mockSelectField.id]: mockSelectField,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
byUniversalIdentifier: {
|
||||
'select-field-universal-id': {
|
||||
...mockSelectField,
|
||||
universalIdentifier: 'select-field-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[mockSelectField.id]: 'select-field-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -293,8 +337,16 @@ describe('PieChartDataService', () => {
|
||||
|
||||
it('should throw when object metadata is not found', async () => {
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue({
|
||||
flatObjectMetadataMaps: { byId: {} },
|
||||
flatFieldMetadataMaps: { byId: {} },
|
||||
flatObjectMetadataMaps: {
|
||||
byUniversalIdentifier: {},
|
||||
universalIdentifierById: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byUniversalIdentifier: {},
|
||||
universalIdentifierById: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
|
||||
await expect(
|
||||
@@ -315,9 +367,22 @@ describe('PieChartDataService', () => {
|
||||
it('should throw when field metadata is not found', async () => {
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byUniversalIdentifier: {},
|
||||
universalIdentifierById: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: { byId: {} },
|
||||
});
|
||||
|
||||
await expect(
|
||||
@@ -347,13 +412,33 @@ describe('PieChartDataService', () => {
|
||||
beforeEach(() => {
|
||||
mockGetOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue({
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { [objectMetadataId]: mockObjectMetadata },
|
||||
byUniversalIdentifier: {
|
||||
'test-object-universal-id': {
|
||||
...mockObjectMetadata,
|
||||
universalIdentifier: 'test-object-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[objectMetadataId]: 'test-object-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: {
|
||||
[booleanField.id]: booleanField,
|
||||
[mockAggregateField.id]: mockAggregateField,
|
||||
byUniversalIdentifier: {
|
||||
'boolean-field-universal-id': {
|
||||
...booleanField,
|
||||
universalIdentifier: 'boolean-field-universal-id',
|
||||
},
|
||||
'aggregate-field-universal-id': {
|
||||
...mockAggregateField,
|
||||
universalIdentifier: 'aggregate-field-universal-id',
|
||||
},
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[booleanField.id]: 'boolean-field-universal-id',
|
||||
[mockAggregateField.id]: 'aggregate-field-universal-id',
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
+12
-8
@@ -9,6 +9,7 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
|
||||
@@ -78,7 +79,10 @@ export class BarChartDataService {
|
||||
);
|
||||
}
|
||||
|
||||
const flatObjectMetadata = flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new ChartDataException(
|
||||
@@ -92,12 +96,12 @@ export class BarChartDataService {
|
||||
|
||||
const primaryAxisGroupByField = getFieldMetadata(
|
||||
configuration.primaryAxisGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const aggregateField = getFieldMetadata(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const isTwoDimensional = isDefined(
|
||||
@@ -109,7 +113,7 @@ export class BarChartDataService {
|
||||
if (isTwoDimensional) {
|
||||
secondaryAxisGroupByField = getFieldMetadata(
|
||||
configuration.secondaryAxisGroupByFieldMetadataId!,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -131,11 +135,11 @@ export class BarChartDataService {
|
||||
|
||||
const objectIdByNameSingular: Record<string, string> = {};
|
||||
|
||||
for (const objectId in flatObjectMetadataMaps.byId) {
|
||||
const objMetadata = flatObjectMetadataMaps.byId[objectId];
|
||||
|
||||
for (const objMetadata of Object.values(
|
||||
flatObjectMetadataMaps.byUniversalIdentifier,
|
||||
)) {
|
||||
if (isDefined(objMetadata)) {
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objectId;
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objMetadata.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -89,12 +89,12 @@ export class ChartDataQueryService {
|
||||
|
||||
const primaryGroupByField = getFieldMetadata(
|
||||
groupByFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const aggregateField = getFieldMetadata(
|
||||
aggregateFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const isPrimaryFieldDate = isFieldMetadataDateKind(
|
||||
@@ -146,7 +146,7 @@ export class ChartDataQueryService {
|
||||
if (isDefined(secondaryGroupByFieldMetadataId)) {
|
||||
const secondaryGroupByField = getFieldMetadata(
|
||||
secondaryGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const isSecondaryFieldDate = isFieldMetadataDateKind(
|
||||
|
||||
+12
-8
@@ -8,6 +8,7 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { type AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
|
||||
@@ -77,7 +78,10 @@ export class LineChartDataService {
|
||||
);
|
||||
}
|
||||
|
||||
const flatObjectMetadata = flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new ChartDataException(
|
||||
@@ -91,12 +95,12 @@ export class LineChartDataService {
|
||||
|
||||
const primaryAxisGroupByField = getFieldMetadata(
|
||||
configuration.primaryAxisGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const aggregateField = getFieldMetadata(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const isTwoDimensional = isDefined(
|
||||
@@ -108,7 +112,7 @@ export class LineChartDataService {
|
||||
if (isTwoDimensional) {
|
||||
secondaryAxisGroupByField = getFieldMetadata(
|
||||
configuration.secondaryAxisGroupByFieldMetadataId!,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -132,11 +136,11 @@ export class LineChartDataService {
|
||||
|
||||
const objectIdByNameSingular: Record<string, string> = {};
|
||||
|
||||
for (const objectId in flatObjectMetadataMaps.byId) {
|
||||
const objMetadata = flatObjectMetadataMaps.byId[objectId];
|
||||
|
||||
for (const objMetadata of Object.values(
|
||||
flatObjectMetadataMaps.byUniversalIdentifier,
|
||||
)) {
|
||||
if (isDefined(objMetadata)) {
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objectId;
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objMetadata.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-6
@@ -8,6 +8,7 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
|
||||
@@ -77,7 +78,10 @@ export class PieChartDataService {
|
||||
);
|
||||
}
|
||||
|
||||
const flatObjectMetadata = flatObjectMetadataMaps.byId[objectMetadataId];
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new ChartDataException(
|
||||
@@ -91,7 +95,7 @@ export class PieChartDataService {
|
||||
|
||||
const groupByField = getFieldMetadata(
|
||||
configuration.groupByFieldMetadataId,
|
||||
flatFieldMetadataMaps.byId,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const limit =
|
||||
@@ -100,11 +104,11 @@ export class PieChartDataService {
|
||||
|
||||
const objectIdByNameSingular: Record<string, string> = {};
|
||||
|
||||
for (const objectId in flatObjectMetadataMaps.byId) {
|
||||
const objMetadata = flatObjectMetadataMaps.byId[objectId];
|
||||
|
||||
for (const objMetadata of Object.values(
|
||||
flatObjectMetadataMaps.byUniversalIdentifier,
|
||||
)) {
|
||||
if (isDefined(objMetadata)) {
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objectId;
|
||||
objectIdByNameSingular[objMetadata.nameSingular] = objMetadata.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-11
@@ -63,19 +63,24 @@ describe('isRelationNestedFieldDateKind', () => {
|
||||
});
|
||||
|
||||
const flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata> = {
|
||||
byId: {
|
||||
[companyObjectId]: companyObject,
|
||||
byUniversalIdentifier: {
|
||||
[companyObject.universalIdentifier as string]: companyObject,
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[companyObjectId]: companyObject.universalIdentifier as string,
|
||||
},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
};
|
||||
|
||||
const flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata> = {
|
||||
byId: {
|
||||
[createdAtFieldId]: createdAtField,
|
||||
[nameFieldId]: nameField,
|
||||
byUniversalIdentifier: {
|
||||
[createdAtField.universalIdentifier as string]: createdAtField,
|
||||
[nameField.universalIdentifier as string]: nameField,
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[createdAtFieldId]: createdAtField.universalIdentifier as string,
|
||||
[nameFieldId]: nameField.universalIdentifier as string,
|
||||
},
|
||||
idByUniversalIdentifier: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
};
|
||||
|
||||
@@ -193,13 +198,23 @@ describe('isRelationNestedFieldDateKind', () => {
|
||||
relationFieldMetadata: personRelationField,
|
||||
relationNestedFieldName: 'birthDate',
|
||||
flatObjectMetadataMaps: {
|
||||
byId: { 'object-with-date-id': objectWithDateField },
|
||||
idByUniversalIdentifier: {},
|
||||
byUniversalIdentifier: {
|
||||
[objectWithDateField.universalIdentifier as string]:
|
||||
objectWithDateField,
|
||||
},
|
||||
universalIdentifierById: {
|
||||
'object-with-date-id':
|
||||
objectWithDateField.universalIdentifier as string,
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
flatFieldMetadataMaps: {
|
||||
byId: { [dateFieldId]: dateField },
|
||||
idByUniversalIdentifier: {},
|
||||
byUniversalIdentifier: {
|
||||
[dateField.universalIdentifier as string]: dateField,
|
||||
},
|
||||
universalIdentifierById: {
|
||||
[dateFieldId]: dateField.universalIdentifier as string,
|
||||
},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
},
|
||||
});
|
||||
|
||||
+9
-2
@@ -14,6 +14,7 @@ import {
|
||||
|
||||
import { type ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -46,7 +47,10 @@ export const convertChartFilterToGqlOperationFilter = ({
|
||||
const fieldIds = flatObjectMetadata.fieldIds ?? [];
|
||||
const fields: PartialFieldMetadataItem[] = fieldIds
|
||||
.map((fieldId: string) => {
|
||||
const field = flatFieldMetadataMaps.byId[fieldId];
|
||||
const field = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: fieldId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(field)) {
|
||||
return null;
|
||||
@@ -70,7 +74,10 @@ export const convertChartFilterToGqlOperationFilter = ({
|
||||
|
||||
const convertedRecordFilters: RecordFilter[] = recordFilters.map(
|
||||
(recordFilter) => {
|
||||
const field = flatFieldMetadataMaps.byId[recordFilter.fieldMetadataId];
|
||||
const field = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: recordFilter.fieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
id: recordFilter.id,
|
||||
|
||||
+7
-2
@@ -1,5 +1,7 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import {
|
||||
ChartDataException,
|
||||
@@ -9,9 +11,12 @@ import {
|
||||
|
||||
export const getFieldMetadata = (
|
||||
fieldMetadataId: string,
|
||||
fieldMetadataById: Partial<Record<string, FlatFieldMetadata>>,
|
||||
flatFieldMetadataMaps: FlatEntityMaps<FlatFieldMetadata>,
|
||||
): FlatFieldMetadata => {
|
||||
const fieldMetadata = fieldMetadataById[fieldMetadataId];
|
||||
const fieldMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: fieldMetadataId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(fieldMetadata)) {
|
||||
throw new ChartDataException(
|
||||
|
||||
+11
-2
@@ -1,5 +1,6 @@
|
||||
import { isDefined, isFieldMetadataDateKind } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
@@ -30,7 +31,10 @@ export const isRelationNestedFieldDateKind = ({
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetObjectMetadata = flatObjectMetadataMaps.byId[targetObjectId];
|
||||
const targetObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: targetObjectId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(targetObjectMetadata)) {
|
||||
return false;
|
||||
@@ -41,7 +45,12 @@ export const isRelationNestedFieldDateKind = ({
|
||||
const targetFieldIds = targetObjectMetadata.fieldIds;
|
||||
|
||||
const nestedFieldMetadata = targetFieldIds
|
||||
.map((fieldId: string) => flatFieldMetadataMaps.byId[fieldId])
|
||||
.map((fieldId: string) =>
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: fieldId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
}),
|
||||
)
|
||||
.find(
|
||||
(fieldMetadata: FlatFieldMetadata | undefined) =>
|
||||
isDefined(fieldMetadata) && fieldMetadata.name === nestedFieldName,
|
||||
|
||||
+5
-1
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -138,7 +139,10 @@ export class WorkflowCommonWorkspaceService {
|
||||
);
|
||||
}
|
||||
|
||||
const flatObjectMetadata = flatObjectMetadataMaps.byId[objectId];
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new WorkflowCommonException(
|
||||
|
||||
+5
-1
@@ -1,5 +1,6 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
@@ -39,7 +40,10 @@ export const generateFakeFormResponse = ({
|
||||
);
|
||||
}
|
||||
|
||||
const flatObjectMetadata = flatObjectMetadataMaps.byId[objectId];
|
||||
const flatObjectMetadata = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: objectId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
if (!isDefined(flatObjectMetadata)) {
|
||||
throw new Error(
|
||||
|
||||
+5
-2
@@ -2,6 +2,7 @@ import { isString } from 'class-validator';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined, resolveRichTextVariables } from 'twenty-shared/utils';
|
||||
|
||||
import { findManyFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type ObjectMetadataInfo } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
|
||||
export const resolveRichTextFieldsInRecord = (
|
||||
@@ -11,8 +12,10 @@ export const resolveRichTextFieldsInRecord = (
|
||||
): Record<string, unknown> => {
|
||||
const { flatObjectMetadata, flatFieldMetadataMaps } = objectMetadataInfo;
|
||||
|
||||
const richTextFieldNames = flatObjectMetadata.fieldIds
|
||||
.map((fieldId) => flatFieldMetadataMaps.byId[fieldId])
|
||||
const richTextFieldNames = findManyFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityIds: flatObjectMetadata.fieldIds,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
})
|
||||
.filter((field) => field?.type === FieldMetadataType.RICH_TEXT_V2)
|
||||
.map((field) => field?.name)
|
||||
.filter(isDefined);
|
||||
|
||||
+5
-2
@@ -5,6 +5,7 @@ import { resolveInput } from 'twenty-shared/utils';
|
||||
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/interfaces/workflow-action.interface';
|
||||
|
||||
import { LogicFunctionExecutorService } from 'src/engine/core-modules/logic-function/logic-function-executor/services/logic-function-executor.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import {
|
||||
WorkflowStepExecutorException,
|
||||
@@ -57,8 +58,10 @@ export class LogicFunctionWorkflowAction implements WorkflowAction {
|
||||
},
|
||||
);
|
||||
|
||||
const logicFunction =
|
||||
flatLogicFunctionMaps.byId[workflowActionInput.logicFunctionId];
|
||||
const logicFunction = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: workflowActionInput.logicFunctionId,
|
||||
flatEntityMaps: flatLogicFunctionMaps,
|
||||
});
|
||||
|
||||
if (!logicFunction) {
|
||||
throw new WorkflowStepExecutorException(
|
||||
|
||||
+5
-1
@@ -17,6 +17,7 @@ import {
|
||||
RecordCrudExceptionCode,
|
||||
} from 'src/engine/core-modules/record-crud/exceptions/record-crud.exception';
|
||||
import { FindRecordsService } from 'src/engine/core-modules/record-crud/services/find-records.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import {
|
||||
WorkflowStepExecutorException,
|
||||
@@ -73,7 +74,10 @@ export class FindRecordsWorkflowAction implements WorkflowAction {
|
||||
|
||||
const fields = flatObjectMetadata.fieldIds
|
||||
.map((fieldId) => {
|
||||
const field = flatFieldMetadataMaps.byId[fieldId];
|
||||
const field = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: fieldId,
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
if (!field) {
|
||||
return null;
|
||||
|
||||
+5
-1
@@ -18,6 +18,7 @@ import { InjectMessageQueue } from 'src/engine/core-modules/message-queue/decora
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/core-modules/message-queue/services/message-queue.service';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { buildFieldMapsFromFlatObjectMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/build-field-maps-from-flat-object-metadata.util';
|
||||
@@ -277,7 +278,10 @@ export class WorkflowDatabaseEventTriggerListener {
|
||||
}
|
||||
|
||||
const relatedObjectMetadataNameSingular =
|
||||
flatObjectMetadataMaps.byId[relatedObjectMetadataId]?.nameSingular;
|
||||
findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: relatedObjectMetadataId,
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
})?.nameSingular;
|
||||
|
||||
if (!isDefined(relatedObjectMetadataNameSingular)) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user