Spread in parent and requires FlatEntity.__universal (#17753)
# Introduction Requiring the spreaded `__universal` record that aggregates all the universal identifier ( relations fk and aggregators ) of an entity to its root It's blockin for https://github.com/twentyhq/twenty/pull/17687 to be finalized because if we don't we would have to migrated all related entities at once in order for them to always have the universal properties ## `resolveEntityRelationUniversalIdentifiers` Introduced `resolveEntityRelationUniversalIdentifiers` a centralized utility that resolves foreign key IDs to universal identifiers using ALL_METADATA_RELATIONS metadata. It provides strict typing for both input (foreign keys) and output (universal identifiers), with nullability dynamically inferred from entity relation types. Strictly and dynamically typed for both output and input To do so added a new type and const/runtime grain to ALL_METADATA_RELATIONS `isNullable`to many-to-one entries, derived from the entity relation property types. And fixed incorrectly typed typeorm entities ### Usage ```ts const { availabilityObjectMetadataUniversalIdentifier, frontComponentUniversalIdentifier, } = resolveEntityRelationUniversalIdentifiers({ metadataName: 'commandMenuItem', foreignKeyValues: { availabilityObjectMetadataId: createCommandMenuItemInput.availabilityObjectMetadataId, frontComponentId: createCommandMenuItemInput.frontComponentId, }, flatEntityMaps: { flatObjectMetadataMaps, flatFrontComponentMaps }, }); ```
This commit is contained in:
+60
-8
@@ -121,6 +121,8 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
} = await this.migrateFavoriteFolders({
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
existingFlatNavigationMenuItemMaps,
|
||||
});
|
||||
|
||||
@@ -128,7 +130,11 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
await this.migrateFavorites({
|
||||
workspaceId,
|
||||
twentyStandardApplicationId: twentyStandardFlatApplication.id,
|
||||
twentyStandardApplicationUniversalIdentifier:
|
||||
twentyStandardFlatApplication.universalIdentifier,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
folderIdMapping,
|
||||
@@ -189,10 +195,12 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
private async migrateFavoriteFolders({
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
existingFlatNavigationMenuItemMaps,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
existingFlatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
}): Promise<{
|
||||
folderIdMapping: Map<string, Map<string, string>>;
|
||||
@@ -270,12 +278,17 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
userWorkspaceId,
|
||||
targetRecordId: null,
|
||||
targetObjectMetadataId: null,
|
||||
targetObjectMetadataUniversalIdentifier: null,
|
||||
viewId: null,
|
||||
viewUniversalIdentifier: null,
|
||||
folderId: null,
|
||||
folderUniversalIdentifier: null,
|
||||
name: favoriteFolder.name,
|
||||
position: favoriteFolder.position,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
@@ -297,12 +310,17 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
userWorkspaceId: null,
|
||||
targetRecordId: null,
|
||||
targetObjectMetadataId: null,
|
||||
targetObjectMetadataUniversalIdentifier: null,
|
||||
viewId: null,
|
||||
viewUniversalIdentifier: null,
|
||||
folderId: null,
|
||||
folderUniversalIdentifier: null,
|
||||
name: favoriteFolder.name,
|
||||
position: favoriteFolder.position,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
@@ -325,7 +343,9 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
private async migrateFavorites({
|
||||
workspaceId,
|
||||
twentyStandardApplicationId,
|
||||
twentyStandardApplicationUniversalIdentifier,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
folderIdMapping,
|
||||
@@ -334,7 +354,9 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
}: {
|
||||
workspaceId: string;
|
||||
twentyStandardApplicationId: string;
|
||||
twentyStandardApplicationUniversalIdentifier: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
flatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
flatViewMaps: FlatEntityMaps<FlatView>;
|
||||
folderIdMapping: Map<string, Map<string, string>>;
|
||||
@@ -471,13 +493,18 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
continue;
|
||||
}
|
||||
|
||||
const { applicationId, universalIdentifier } =
|
||||
this.getApplicationIdAndUniversalIdentifierForViewFavorite({
|
||||
viewId: favorite.viewId,
|
||||
flatViewMaps,
|
||||
twentyStandardApplicationId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
const {
|
||||
applicationId,
|
||||
applicationUniversalIdentifier,
|
||||
universalIdentifier,
|
||||
} = this.getApplicationIdAndUniversalIdentifierForViewFavorite({
|
||||
viewId: favorite.viewId,
|
||||
flatViewMaps,
|
||||
twentyStandardApplicationId,
|
||||
twentyStandardApplicationUniversalIdentifier,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -487,12 +514,17 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
userWorkspaceId,
|
||||
targetRecordId: null,
|
||||
targetObjectMetadataId: null,
|
||||
targetObjectMetadataUniversalIdentifier: null,
|
||||
viewId: favorite.viewId,
|
||||
viewUniversalIdentifier:
|
||||
flatViewMaps.universalIdentifierById[favorite.viewId] ?? null,
|
||||
folderId,
|
||||
folderUniversalIdentifier: folderId,
|
||||
name: null,
|
||||
position: favorite.position,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
applicationUniversalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
@@ -525,12 +557,20 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
userWorkspaceId,
|
||||
targetRecordId,
|
||||
targetObjectMetadataId,
|
||||
targetObjectMetadataUniversalIdentifier:
|
||||
flatObjectMetadataMaps.universalIdentifierById[
|
||||
targetObjectMetadataId
|
||||
] ?? null,
|
||||
viewId: null,
|
||||
viewUniversalIdentifier: null,
|
||||
folderId,
|
||||
folderUniversalIdentifier: folderId,
|
||||
name: null,
|
||||
position: favorite.position,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
@@ -548,13 +588,21 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
viewId,
|
||||
flatViewMaps,
|
||||
twentyStandardApplicationId,
|
||||
twentyStandardApplicationUniversalIdentifier,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
viewId: string;
|
||||
flatViewMaps: FlatEntityMaps<FlatView>;
|
||||
twentyStandardApplicationId: string;
|
||||
twentyStandardApplicationUniversalIdentifier: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): { applicationId: string; universalIdentifier: string } {
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
applicationId: string;
|
||||
applicationUniversalIdentifier: string;
|
||||
universalIdentifier: string;
|
||||
} {
|
||||
const flatView = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatViewMaps,
|
||||
flatEntityId: viewId,
|
||||
@@ -573,10 +621,14 @@ export class MigrateFavoritesToNavigationMenuItemsCommand extends ActiveOrSuspen
|
||||
return !isDefined(matchingStandardItem)
|
||||
? {
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
universalIdentifier: uuidv4(),
|
||||
}
|
||||
: {
|
||||
applicationId: twentyStandardApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
twentyStandardApplicationUniversalIdentifier,
|
||||
universalIdentifier: matchingStandardItem.universalIdentifier,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,6 +106,12 @@ export class AgentService {
|
||||
input: CreateAgentInput & { isCustom: boolean },
|
||||
workspaceId: string,
|
||||
): Promise<FlatAgentWithRoleId> {
|
||||
const { flatApplicationMaps, flatRoleMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatApplicationMaps',
|
||||
'flatRoleMaps',
|
||||
]);
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
@@ -113,14 +119,19 @@ export class AgentService {
|
||||
},
|
||||
);
|
||||
|
||||
const flatApplication = isDefined(input.applicationId)
|
||||
? flatApplicationMaps.byId[input.applicationId]
|
||||
: undefined;
|
||||
|
||||
const resolvedFlatApplication =
|
||||
flatApplication ?? workspaceCustomFlatApplication;
|
||||
|
||||
const { flatAgentToCreate, flatRoleTargetToCreate } =
|
||||
fromCreateAgentInputToFlatAgent({
|
||||
createAgentInput: {
|
||||
...input,
|
||||
applicationId:
|
||||
input.applicationId ?? workspaceCustomFlatApplication.id,
|
||||
},
|
||||
createAgentInput: input,
|
||||
workspaceId,
|
||||
flatApplication: resolvedFlatApplication,
|
||||
flatRoleMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -184,10 +195,11 @@ export class AgentService {
|
||||
},
|
||||
);
|
||||
|
||||
const { flatRoleTargetByAgentIdMaps, flatAgentMaps } =
|
||||
const { flatRoleTargetByAgentIdMaps, flatAgentMaps, flatRoleMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatRoleTargetByAgentIdMaps',
|
||||
'flatAgentMaps',
|
||||
'flatRoleMaps',
|
||||
]);
|
||||
|
||||
const {
|
||||
@@ -199,6 +211,7 @@ export class AgentService {
|
||||
updateAgentInput: input,
|
||||
flatAgentMaps,
|
||||
flatRoleTargetByAgentIdMaps,
|
||||
flatRoleMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+36
-26
@@ -6,18 +6,25 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type CreateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/create-agent.input';
|
||||
import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/flat-agent.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
|
||||
export type FromCreateAgentInputToFlatAgentArgs = {
|
||||
createAgentInput: CreateAgentInput & { applicationId: string };
|
||||
createAgentInput: CreateAgentInput;
|
||||
workspaceId: string;
|
||||
flatApplication: FlatApplication;
|
||||
flatRoleMaps: AllFlatEntityMaps['flatRoleMaps'];
|
||||
};
|
||||
|
||||
export const fromCreateAgentInputToFlatAgent = ({
|
||||
createAgentInput: rawCreateAgentInput,
|
||||
workspaceId,
|
||||
flatApplication,
|
||||
flatRoleMaps,
|
||||
}: FromCreateAgentInputToFlatAgentArgs): {
|
||||
flatAgentToCreate: FlatAgent;
|
||||
flatRoleTargetToCreate: FlatRoleTarget | null;
|
||||
@@ -25,16 +32,7 @@ export const fromCreateAgentInputToFlatAgent = ({
|
||||
const { roleId, ...createAgentInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreateAgentInput,
|
||||
[
|
||||
'name',
|
||||
'label',
|
||||
'icon',
|
||||
'description',
|
||||
'prompt',
|
||||
'modelId',
|
||||
'applicationId',
|
||||
'roleId',
|
||||
],
|
||||
['name', 'label', 'icon', 'description', 'prompt', 'modelId', 'roleId'],
|
||||
);
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
@@ -54,7 +52,8 @@ export const fromCreateAgentInputToFlatAgent = ({
|
||||
workspaceId,
|
||||
isCustom: true,
|
||||
universalIdentifier: v4(),
|
||||
applicationId: createAgentInput.applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
modelConfiguration: createAgentInput.modelConfiguration ?? null,
|
||||
evaluationInputs: createAgentInput.evaluationInputs ?? [],
|
||||
createdAt,
|
||||
@@ -62,20 +61,31 @@ export const fromCreateAgentInputToFlatAgent = ({
|
||||
deletedAt: null,
|
||||
};
|
||||
|
||||
const flatRoleTargetToCreate: FlatRoleTarget | null = isDefined(roleId)
|
||||
? {
|
||||
id: v4(),
|
||||
roleId,
|
||||
userWorkspaceId: null,
|
||||
agentId,
|
||||
apiKeyId: null,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
universalIdentifier: v4(),
|
||||
workspaceId,
|
||||
applicationId: createAgentInput.applicationId,
|
||||
}
|
||||
: null;
|
||||
let flatRoleTargetToCreate: FlatRoleTarget | null = null;
|
||||
|
||||
if (isDefined(roleId)) {
|
||||
const { roleUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'roleTarget',
|
||||
foreignKeyValues: { roleId },
|
||||
flatEntityMaps: { flatRoleMaps },
|
||||
});
|
||||
|
||||
flatRoleTargetToCreate = {
|
||||
id: v4(),
|
||||
roleId,
|
||||
roleUniversalIdentifier,
|
||||
userWorkspaceId: null,
|
||||
agentId,
|
||||
apiKeyId: null,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
universalIdentifier: v4(),
|
||||
workspaceId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
flatAgentToCreate,
|
||||
|
||||
+16
-2
@@ -13,9 +13,11 @@ import {
|
||||
import { type UpdateAgentInput } from 'src/engine/metadata-modules/ai/ai-agent/dtos/update-agent.input';
|
||||
import { FLAT_AGENT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-agent/constants/flat-agent-editable-properties.constant';
|
||||
import { type FlatAgentMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-agent-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatAgent } from 'src/engine/metadata-modules/flat-agent/types/flat-agent.type';
|
||||
import { type FlatRoleTargetByAgentIdMaps } from 'src/engine/metadata-modules/flat-agent/types/flat-role-target-by-agent-id-maps.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-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 FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { computeMetadataNameFromLabelOrThrow } from 'src/engine/metadata-modules/utils/compute-metadata-name-from-label-or-throw.util';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
@@ -29,10 +31,12 @@ const computeAgentFlatRoleTargetToUpdate = ({
|
||||
roleId,
|
||||
flatAgent,
|
||||
flatRoleTargetByAgentIdMaps,
|
||||
flatRoleMaps,
|
||||
}: {
|
||||
roleId: string | null | undefined;
|
||||
flatRoleTargetByAgentIdMaps: FlatRoleTargetByAgentIdMaps;
|
||||
flatAgent: FlatAgent;
|
||||
flatRoleMaps: AllFlatEntityMaps['flatRoleMaps'];
|
||||
}): FlatRoleTargetToUpdateCreateDelete => {
|
||||
if (roleId === undefined) {
|
||||
return {};
|
||||
@@ -51,11 +55,17 @@ const computeAgentFlatRoleTargetToUpdate = ({
|
||||
return {};
|
||||
}
|
||||
|
||||
const flatRole = findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatRoleMaps,
|
||||
flatEntityId: roleId,
|
||||
});
|
||||
|
||||
if (isDefined(existingRoleTarget)) {
|
||||
return {
|
||||
flatRoleTargetToUpdate: {
|
||||
...existingRoleTarget,
|
||||
roleId,
|
||||
roleUniversalIdentifier: flatRole.universalIdentifier,
|
||||
updatedAt,
|
||||
},
|
||||
};
|
||||
@@ -65,6 +75,7 @@ const computeAgentFlatRoleTargetToUpdate = ({
|
||||
flatRoleTargetToCreate: {
|
||||
id: v4(),
|
||||
roleId,
|
||||
roleUniversalIdentifier: flatRole.universalIdentifier,
|
||||
userWorkspaceId: null,
|
||||
agentId: flatAgent.id,
|
||||
apiKeyId: null,
|
||||
@@ -73,6 +84,7 @@ const computeAgentFlatRoleTargetToUpdate = ({
|
||||
universalIdentifier: v4(),
|
||||
workspaceId: flatAgent.workspaceId,
|
||||
applicationId: flatAgent.applicationId,
|
||||
applicationUniversalIdentifier: flatAgent.applicationUniversalIdentifier,
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -81,12 +93,13 @@ export type FromUpdateAgentInputToFlatAgentToUpdateArgs = {
|
||||
updateAgentInput: UpdateAgentInput;
|
||||
flatAgentMaps: FlatAgentMaps;
|
||||
flatRoleTargetByAgentIdMaps: FlatRoleTargetByAgentIdMaps;
|
||||
};
|
||||
} & Pick<AllFlatEntityMaps, 'flatRoleMaps'>;
|
||||
|
||||
export const fromUpdateAgentInputToFlatAgentToUpdate = ({
|
||||
updateAgentInput: rawUpdateAgentInput,
|
||||
flatAgentMaps,
|
||||
flatRoleTargetByAgentIdMaps,
|
||||
flatRoleMaps,
|
||||
}: FromUpdateAgentInputToFlatAgentToUpdateArgs): {
|
||||
flatAgentToUpdate: FlatAgent;
|
||||
} & FlatRoleTargetToUpdateCreateDelete => {
|
||||
@@ -139,6 +152,7 @@ export const fromUpdateAgentInputToFlatAgentToUpdate = ({
|
||||
roleId: rawUpdateAgentInput.roleId,
|
||||
flatAgent: existingFlatAgent,
|
||||
flatRoleTargetByAgentIdMaps,
|
||||
flatRoleMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+17
-3
@@ -88,6 +88,14 @@ export class CommandMenuItemService {
|
||||
input: CreateCommandMenuItemInput,
|
||||
workspaceId: string,
|
||||
): Promise<CommandMenuItemDTO> {
|
||||
const { flatObjectMetadataMaps, flatFrontComponentMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps', 'flatFrontComponentMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
@@ -97,7 +105,9 @@ export class CommandMenuItemService {
|
||||
fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate({
|
||||
createCommandMenuItemInput: input,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -149,11 +159,14 @@ export class CommandMenuItemService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps } =
|
||||
const {
|
||||
flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatCommandMenuItemMaps'],
|
||||
flatMapsKeys: ['flatCommandMenuItemMaps', 'flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -161,6 +174,7 @@ export class CommandMenuItemService {
|
||||
fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow({
|
||||
flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps,
|
||||
updateCommandMenuItemInput: input,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+1
-4
@@ -39,9 +39,6 @@ export const transformAgentEntityToFlatAgent = ({
|
||||
applicationId: agentEntity.applicationId,
|
||||
modelConfiguration: agentEntity.modelConfiguration,
|
||||
evaluationInputs: agentEntity.evaluationInputs,
|
||||
__universal: {
|
||||
universalIdentifier: agentEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-6
@@ -72,11 +72,8 @@ export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
applicationId: commandMenuItemEntity.applicationId,
|
||||
createdAt: commandMenuItemEntity.createdAt.toISOString(),
|
||||
updatedAt: commandMenuItemEntity.updatedAt.toISOString(),
|
||||
__universal: {
|
||||
universalIdentifier: commandMenuItemEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+28
-4
@@ -1,6 +1,7 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import {
|
||||
CommandMenuItemException,
|
||||
CommandMenuItemExceptionCode,
|
||||
@@ -8,16 +9,23 @@ import {
|
||||
import { type CreateCommandMenuItemInput } from 'src/engine/metadata-modules/command-menu-item/dtos/create-command-menu-item.input';
|
||||
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/entities/command-menu-item.entity';
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
|
||||
export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
createCommandMenuItemInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
}: {
|
||||
createCommandMenuItemInput: CreateCommandMenuItemInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}): FlatCommandMenuItem => {
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps' | 'flatFrontComponentMaps'
|
||||
>): FlatCommandMenuItem => {
|
||||
const hasWorkflowVersionId = isDefined(
|
||||
createCommandMenuItemInput.workflowVersionId,
|
||||
);
|
||||
@@ -35,11 +43,25 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
const id = uuidv4();
|
||||
const now = new Date().toISOString();
|
||||
|
||||
const {
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'commandMenuItem',
|
||||
foreignKeyValues: {
|
||||
availabilityObjectMetadataId:
|
||||
createCommandMenuItemInput.availabilityObjectMetadataId,
|
||||
frontComponentId: createCommandMenuItemInput.frontComponentId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps, flatFrontComponentMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
workflowVersionId: createCommandMenuItemInput.workflowVersionId ?? null,
|
||||
frontComponentId: createCommandMenuItemInput.frontComponentId ?? null,
|
||||
frontComponentUniversalIdentifier,
|
||||
label: createCommandMenuItemInput.label,
|
||||
icon: createCommandMenuItemInput.icon ?? null,
|
||||
isPinned: createCommandMenuItemInput.isPinned ?? false,
|
||||
@@ -48,8 +70,10 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
CommandMenuItemAvailabilityType.GLOBAL,
|
||||
availabilityObjectMetadataId:
|
||||
createCommandMenuItemInput.availabilityObjectMetadataId ?? null,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+26
-3
@@ -5,20 +5,26 @@ import {
|
||||
CommandMenuItemExceptionCode,
|
||||
} from 'src/engine/metadata-modules/command-menu-item/command-menu-item.exception';
|
||||
import { type UpdateCommandMenuItemInput } from 'src/engine/metadata-modules/command-menu-item/dtos/update-command-menu-item.input';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-command-menu-item/constants/flat-command-menu-item-editable-properties.constant';
|
||||
import { type FlatCommandMenuItemMaps } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item-maps.type';
|
||||
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
|
||||
|
||||
export const fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow =
|
||||
({
|
||||
flatCommandMenuItemMaps,
|
||||
updateCommandMenuItemInput,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
flatCommandMenuItemMaps: FlatCommandMenuItemMaps;
|
||||
updateCommandMenuItemInput: UpdateCommandMenuItemInput;
|
||||
}): FlatCommandMenuItem => {
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps'
|
||||
>): FlatCommandMenuItem => {
|
||||
const existingFlatCommandMenuItem = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updateCommandMenuItemInput.id,
|
||||
flatEntityMaps: flatCommandMenuItemMaps,
|
||||
@@ -33,7 +39,7 @@ export const fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow
|
||||
|
||||
const { id: _id, ...updates } = updateCommandMenuItemInput;
|
||||
|
||||
return {
|
||||
const flatCommandMenuItemToUpdate = {
|
||||
...mergeUpdateInExistingRecord({
|
||||
existing: existingFlatCommandMenuItem,
|
||||
properties: [...FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES],
|
||||
@@ -41,4 +47,21 @@ export const fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow
|
||||
}),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (updates.availabilityObjectMetadataId !== undefined) {
|
||||
const { availabilityObjectMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'commandMenuItem',
|
||||
foreignKeyValues: {
|
||||
availabilityObjectMetadataId:
|
||||
flatCommandMenuItemToUpdate.availabilityObjectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
flatCommandMenuItemToUpdate.availabilityObjectMetadataUniversalIdentifier =
|
||||
availabilityObjectMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatCommandMenuItemToUpdate;
|
||||
};
|
||||
|
||||
+39
-1
@@ -10,7 +10,7 @@ import { type FromMetadataEntityToMetadataName } from 'src/engine/metadata-modul
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
|
||||
type ManyToOneRelationValue<
|
||||
export type ManyToOneRelationValue<
|
||||
TSourceMetadataName extends AllMetadataName,
|
||||
TRelationProperty extends ExtractEntityManyToOneEntityRelationProperties<
|
||||
MetadataEntity<TSourceMetadataName>
|
||||
@@ -29,6 +29,9 @@ type ManyToOneRelationValue<
|
||||
MetadataEntity<TSourceMetadataName>,
|
||||
'id' | 'workspaceId'
|
||||
>;
|
||||
isNullable: null extends MetadataEntity<TSourceMetadataName>[TRelationProperty]
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
: null;
|
||||
|
||||
@@ -84,11 +87,13 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'availabilityObjectMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
frontComponent: {
|
||||
metadataName: 'frontComponent',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'frontComponentId',
|
||||
isNullable: true,
|
||||
},
|
||||
},
|
||||
oneToMany: {},
|
||||
@@ -102,16 +107,19 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'targetObjectMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
folder: {
|
||||
metadataName: 'navigationMenuItem',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'folderId',
|
||||
isNullable: true,
|
||||
},
|
||||
view: {
|
||||
metadataName: 'view',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'viewId',
|
||||
isNullable: true,
|
||||
},
|
||||
},
|
||||
oneToMany: {},
|
||||
@@ -122,6 +130,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: 'fieldIds',
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -129,11 +138,13 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'relationTargetFieldMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
relationTargetObjectMetadata: {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'relationTargetObjectMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
},
|
||||
oneToMany: {
|
||||
@@ -167,6 +178,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
foreignKey: 'objectMetadataId',
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: 'viewIds',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
createdBy: null,
|
||||
@@ -175,16 +187,19 @@ export const ALL_METADATA_RELATIONS = {
|
||||
foreignKey: 'calendarFieldMetadataId',
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'calendarViewIds',
|
||||
isNullable: true,
|
||||
},
|
||||
kanbanAggregateOperationFieldMetadata: {
|
||||
foreignKey: 'kanbanAggregateOperationFieldMetadataId',
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'kanbanAggregateOperationViewIds',
|
||||
isNullable: true,
|
||||
},
|
||||
mainGroupByFieldMetadata: {
|
||||
foreignKey: 'mainGroupByFieldMetadataId',
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'mainGroupByFieldMetadataViewIds',
|
||||
isNullable: true,
|
||||
},
|
||||
},
|
||||
oneToMany: {
|
||||
@@ -204,11 +219,13 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'viewFieldIds',
|
||||
foreignKey: 'fieldMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
view: {
|
||||
metadataName: 'view',
|
||||
flatEntityForeignKeyAggregator: 'viewFieldIds',
|
||||
foreignKey: 'viewId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -221,16 +238,19 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: 'viewFilterIds',
|
||||
foreignKey: 'fieldMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
view: {
|
||||
metadataName: 'view',
|
||||
flatEntityForeignKeyAggregator: 'viewFilterIds',
|
||||
foreignKey: 'viewId',
|
||||
isNullable: false,
|
||||
},
|
||||
viewFilterGroup: {
|
||||
flatEntityForeignKeyAggregator: 'viewFilterIds',
|
||||
foreignKey: 'viewFilterGroupId',
|
||||
metadataName: 'viewFilterGroup',
|
||||
isNullable: true,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -243,6 +263,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'view',
|
||||
flatEntityForeignKeyAggregator: 'viewGroupIds',
|
||||
foreignKey: 'viewId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -255,6 +276,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: 'indexMetadataIds',
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -294,6 +316,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'role',
|
||||
flatEntityForeignKeyAggregator: 'roleTargetIds',
|
||||
foreignKey: 'roleId',
|
||||
isNullable: false,
|
||||
},
|
||||
apiKey: null,
|
||||
workspace: null,
|
||||
@@ -308,12 +331,14 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
application: null,
|
||||
defaultTabToFocusOnMobileAndSidePanel: {
|
||||
metadataName: 'pageLayoutTab',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'defaultTabToFocusOnMobileAndSidePanelId',
|
||||
isNullable: true,
|
||||
},
|
||||
},
|
||||
oneToMany: {
|
||||
@@ -327,6 +352,7 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'pageLayout',
|
||||
flatEntityForeignKeyAggregator: 'tabIds',
|
||||
foreignKey: 'pageLayoutId',
|
||||
isNullable: false,
|
||||
},
|
||||
application: null,
|
||||
},
|
||||
@@ -341,11 +367,13 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'pageLayoutTab',
|
||||
flatEntityForeignKeyAggregator: 'widgetIds',
|
||||
foreignKey: 'pageLayoutTabId',
|
||||
isNullable: false,
|
||||
},
|
||||
objectMetadata: {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
application: null,
|
||||
},
|
||||
@@ -358,26 +386,31 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'role',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'roleId',
|
||||
isNullable: false,
|
||||
},
|
||||
fieldMetadata: {
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'fieldMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspaceMemberFieldMetadata: {
|
||||
metadataName: 'fieldMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'workspaceMemberFieldMetadataId',
|
||||
isNullable: true,
|
||||
},
|
||||
objectMetadata: {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
rowLevelPermissionPredicateGroup: {
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'rowLevelPermissionPredicateGroupId',
|
||||
isNullable: true,
|
||||
},
|
||||
application: null,
|
||||
},
|
||||
@@ -389,17 +422,20 @@ export const ALL_METADATA_RELATIONS = {
|
||||
metadataName: 'objectMetadata',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
foreignKey: 'objectMetadataId',
|
||||
isNullable: false,
|
||||
},
|
||||
role: {
|
||||
metadataName: 'role',
|
||||
foreignKey: 'roleId',
|
||||
flatEntityForeignKeyAggregator: null,
|
||||
isNullable: false,
|
||||
},
|
||||
parentRowLevelPermissionPredicateGroup: {
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
foreignKey: 'parentRowLevelPermissionPredicateGroupId',
|
||||
flatEntityForeignKeyAggregator:
|
||||
'childRowLevelPermissionPredicateGroupIds',
|
||||
isNullable: true,
|
||||
},
|
||||
workspace: null,
|
||||
application: null,
|
||||
@@ -420,11 +456,13 @@ export const ALL_METADATA_RELATIONS = {
|
||||
flatEntityForeignKeyAggregator: 'childViewFilterGroupIds',
|
||||
foreignKey: 'parentViewFilterGroupId',
|
||||
metadataName: 'viewFilterGroup',
|
||||
isNullable: true,
|
||||
},
|
||||
view: {
|
||||
metadataName: 'view',
|
||||
flatEntityForeignKeyAggregator: 'viewFilterGroupIds',
|
||||
foreignKey: 'viewId',
|
||||
isNullable: false,
|
||||
},
|
||||
workspace: null,
|
||||
},
|
||||
|
||||
+3
@@ -8,6 +8,8 @@ import {
|
||||
} from 'src/utils/custom-exception';
|
||||
|
||||
export const FlatEntityMapsExceptionCode = appendCommonExceptionCode({
|
||||
RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND:
|
||||
'RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND',
|
||||
ENTITY_ALREADY_EXISTS: 'ENTITY_ALREADY_EXISTS',
|
||||
ENTITY_NOT_FOUND: 'ENTITY_NOT_FOUND',
|
||||
ENTITY_MALFORMED: 'ENTITY_MALFORMED',
|
||||
@@ -17,6 +19,7 @@ const getFlatEntityMapsExceptionUserFriendlyMessage = (
|
||||
code: keyof typeof FlatEntityMapsExceptionCode,
|
||||
) => {
|
||||
switch (code) {
|
||||
case FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND:
|
||||
case FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS:
|
||||
case FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND:
|
||||
case FlatEntityMapsExceptionCode.ENTITY_MALFORMED:
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import { Catch, type ExceptionFilter, Injectable } from '@nestjs/common';
|
||||
|
||||
import {
|
||||
InternalServerError,
|
||||
NotFoundError,
|
||||
} from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
|
||||
@Catch(FlatEntityMapsException)
|
||||
@Injectable()
|
||||
export class FlatEntityMapsGraphqlApiExceptionFilter
|
||||
implements ExceptionFilter
|
||||
{
|
||||
catch(exception: FlatEntityMapsException) {
|
||||
switch (exception.code) {
|
||||
case FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND:
|
||||
throw new NotFoundError(exception);
|
||||
case FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND:
|
||||
case FlatEntityMapsExceptionCode.ENTITY_ALREADY_EXISTS:
|
||||
case FlatEntityMapsExceptionCode.ENTITY_MALFORMED:
|
||||
case FlatEntityMapsExceptionCode.INTERNAL_SERVER_ERROR:
|
||||
throw new InternalServerError(exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
|
||||
/**
|
||||
* Currently under migration but aims to replace FlatEntity afterwards
|
||||
*/
|
||||
export type FlatEntityFromV2<
|
||||
TEntity,
|
||||
TMetadataName extends AllMetadataName | undefined = undefined,
|
||||
TInnerFlatEntity extends { __universal?: unknown } = FlatEntityFrom<
|
||||
TEntity,
|
||||
TMetadataName
|
||||
>,
|
||||
> = Omit<TInnerFlatEntity, '__universal'> & TInnerFlatEntity['__universal'];
|
||||
+6
-13
@@ -28,18 +28,11 @@ export type FlatEntityFrom<
|
||||
CastRecordTypeOrmDatePropertiesToString<TEntity> &
|
||||
AddSuffixToEntityOneToManyProperties<TEntity, 'ids'> &
|
||||
(TEntity extends SyncableEntity
|
||||
? {
|
||||
/**
|
||||
* /!\ Under migration the idea is at some point to replace FlatEntity by UniversalFlatEntity /!\
|
||||
* Please avoid any usage or contact me ( prastoin ) before doing so
|
||||
* TODO remove with FlatEntity once it has been fully migrated
|
||||
*/
|
||||
__universal?: UniversalFlatEntityExtraProperties<
|
||||
TEntity,
|
||||
TMetadataName extends undefined
|
||||
? FromMetadataEntityToMetadataName<TEntity>
|
||||
: TMetadataName
|
||||
> & { universalIdentifier: string };
|
||||
}
|
||||
? UniversalFlatEntityExtraProperties<
|
||||
TEntity,
|
||||
TMetadataName extends undefined
|
||||
? FromMetadataEntityToMetadataName<TEntity>
|
||||
: TMetadataName
|
||||
> & { universalIdentifier: string }
|
||||
: // eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
{});
|
||||
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
import { FlatEntityMapsExceptionCode } from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
|
||||
const buildFlatEntityMaps = (
|
||||
entries: { id: string; universalIdentifier: string }[],
|
||||
): FlatEntityMaps<any> => ({
|
||||
byUniversalIdentifier: Object.fromEntries(
|
||||
entries.map((entry) => [
|
||||
entry.universalIdentifier,
|
||||
{ universalIdentifier: entry.universalIdentifier, id: entry.id },
|
||||
]),
|
||||
),
|
||||
universalIdentifierById: Object.fromEntries(
|
||||
entries.map((entry) => [entry.id, entry.universalIdentifier]),
|
||||
),
|
||||
universalIdentifiersByApplicationId: {},
|
||||
});
|
||||
|
||||
const EMPTY_FLAT_ENTITY_MAPS: FlatEntityMaps<any> = {
|
||||
byUniversalIdentifier: {},
|
||||
universalIdentifierById: {},
|
||||
universalIdentifiersByApplicationId: {},
|
||||
};
|
||||
|
||||
describe('resolveEntityRelationUniversalIdentifiers', () => {
|
||||
describe('non-nullable relations', () => {
|
||||
it('should resolve universal identifier for a provided foreign key', () => {
|
||||
const result = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId: 'field-id-1',
|
||||
viewId: 'view-id-1',
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps: buildFlatEntityMaps([
|
||||
{ id: 'field-id-1', universalIdentifier: 'field-ui-1' },
|
||||
]),
|
||||
flatViewMaps: buildFlatEntityMaps([
|
||||
{ id: 'view-id-1', universalIdentifier: 'view-ui-1' },
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
fieldMetadataUniversalIdentifier: 'field-ui-1',
|
||||
viewUniversalIdentifier: 'view-ui-1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when a non-nullable foreign key id does not exist in maps', () => {
|
||||
expect(() =>
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId: 'non-existent-id',
|
||||
viewId: 'view-id-1',
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatViewMaps: buildFlatEntityMaps([
|
||||
{ id: 'view-id-1', universalIdentifier: 'view-ui-1' },
|
||||
]),
|
||||
},
|
||||
}),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('nullable relations', () => {
|
||||
it('should return null when a nullable foreign key value is null', () => {
|
||||
const result = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayout',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: null,
|
||||
defaultTabToFocusOnMobileAndSidePanelId: undefined,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
flatPageLayoutTabMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
objectMetadataUniversalIdentifier: null,
|
||||
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('should resolve universal identifier when a nullable foreign key has a valid id', () => {
|
||||
const result = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayout',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: 'obj-id-1',
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps: buildFlatEntityMaps([
|
||||
{ id: 'obj-id-1', universalIdentifier: 'obj-ui-1' },
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
objectMetadataUniversalIdentifier: 'obj-ui-1',
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw when a nullable foreign key has a non-existent id', () => {
|
||||
expect(() =>
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayout',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: 'non-existent-id',
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps: EMPTY_FLAT_ENTITY_MAPS,
|
||||
},
|
||||
}),
|
||||
).toThrow(
|
||||
expect.objectContaining({
|
||||
code: FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('partial foreign key resolution', () => {
|
||||
it('should only resolve universal identifiers for provided foreign keys', () => {
|
||||
const result = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId: 'field-id-1',
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps: buildFlatEntityMaps([
|
||||
{ id: 'field-id-1', universalIdentifier: 'field-ui-1' },
|
||||
]),
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
fieldMetadataUniversalIdentifier: 'field-ui-1',
|
||||
});
|
||||
expect(result).not.toHaveProperty('viewUniversalIdentifier');
|
||||
});
|
||||
});
|
||||
});
|
||||
+3
-4
@@ -7,18 +7,17 @@ import {
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifierOrThrow = <
|
||||
T extends SyncableFlatEntity,
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}: {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifier: string;
|
||||
}): T & {
|
||||
id: string;
|
||||
} => {
|
||||
}): T => {
|
||||
const flatEntity = findFlatEntityByUniversalIdentifier({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export const findFlatEntityByUniversalIdentifier = <
|
||||
T extends SyncableFlatEntity,
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { type SyncableFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { type UniversalSyncableFlatEntity } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/universal-flat-entity-from.type';
|
||||
|
||||
export type FindManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrowArgs<
|
||||
T extends SyncableFlatEntity | UniversalSyncableFlatEntity,
|
||||
> = {
|
||||
flatEntityMaps: FlatEntityMaps<T>;
|
||||
universalIdentifiers: string[];
|
||||
};
|
||||
|
||||
export const findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow =
|
||||
<T extends SyncableFlatEntity | UniversalSyncableFlatEntity>({
|
||||
flatEntityMaps,
|
||||
universalIdentifiers,
|
||||
}: FindManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrowArgs<T>): T[] =>
|
||||
universalIdentifiers.map((universalIdentifier) =>
|
||||
findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps,
|
||||
universalIdentifier,
|
||||
}),
|
||||
);
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
ALL_METADATA_RELATIONS,
|
||||
type ManyToOneRelationValue,
|
||||
} from 'src/engine/metadata-modules/flat-entity/constant/all-metadata-relations.constant';
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type ExtractEntityManyToOneEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/types/extract-entity-many-to-one-entity-relation-properties.type';
|
||||
import { type MetadataEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-entity.type';
|
||||
import { type MetadataManyToOneJoinColumn } from 'src/engine/metadata-modules/flat-entity/types/metadata-many-to-one-join-column.type';
|
||||
import { type MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { type RemoveSuffix } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-builder/types/remove-suffix.type';
|
||||
|
||||
type ManyToOneConfig<T extends AllMetadataName> =
|
||||
(typeof ALL_METADATA_RELATIONS)[T]['manyToOne'];
|
||||
|
||||
type TargetMetadataNamesForForeignKeys<
|
||||
T extends AllMetadataName,
|
||||
TProvidedKeys extends string,
|
||||
> = {
|
||||
[K in keyof ManyToOneConfig<T>]: ManyToOneConfig<T>[K] extends {
|
||||
foreignKey: infer _FK extends TProvidedKeys;
|
||||
metadataName: infer MN extends AllMetadataName;
|
||||
}
|
||||
? MN
|
||||
: never;
|
||||
}[keyof ManyToOneConfig<T>];
|
||||
|
||||
type RequiredFlatEntityMapsForForeignKeys<
|
||||
T extends AllMetadataName,
|
||||
TProvidedKeys extends string,
|
||||
> = Pick<
|
||||
AllFlatEntityMaps,
|
||||
MetadataToFlatEntityMapsKey<
|
||||
TargetMetadataNamesForForeignKeys<T, TProvidedKeys>
|
||||
>
|
||||
>;
|
||||
|
||||
type ResolvedUniversalIdentifiers<
|
||||
T extends AllMetadataName,
|
||||
TProvidedKeys extends Extract<MetadataManyToOneJoinColumn<T>, string>,
|
||||
> = {
|
||||
[K in keyof ManyToOneConfig<T> as ManyToOneConfig<T>[K] extends {
|
||||
foreignKey: infer FK extends string;
|
||||
}
|
||||
? FK extends TProvidedKeys
|
||||
? `${RemoveSuffix<FK, 'Id'>}UniversalIdentifier`
|
||||
: never
|
||||
: never]: ManyToOneConfig<T>[K] extends { isNullable: true }
|
||||
? string | null
|
||||
: string;
|
||||
};
|
||||
|
||||
export const resolveEntityRelationUniversalIdentifiers = <
|
||||
T extends AllMetadataName,
|
||||
TProvidedKeys extends Extract<
|
||||
MetadataManyToOneJoinColumn<T>,
|
||||
string
|
||||
> = Extract<MetadataManyToOneJoinColumn<T>, string>,
|
||||
>({
|
||||
metadataName,
|
||||
foreignKeyValues,
|
||||
flatEntityMaps,
|
||||
}: {
|
||||
metadataName: T;
|
||||
foreignKeyValues: Record<TProvidedKeys, string | null | undefined>;
|
||||
flatEntityMaps: RequiredFlatEntityMapsForForeignKeys<T, TProvidedKeys>;
|
||||
}): ResolvedUniversalIdentifiers<T, TProvidedKeys> => {
|
||||
const relations = ALL_METADATA_RELATIONS[metadataName].manyToOne;
|
||||
const result: Record<string, string | null> = {};
|
||||
|
||||
for (const relation of Object.values(relations) as ManyToOneRelationValue<
|
||||
T,
|
||||
ExtractEntityManyToOneEntityRelationProperties<MetadataEntity<T>>
|
||||
>[]) {
|
||||
if (!isDefined(relation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const {
|
||||
foreignKey,
|
||||
metadataName: targetMetadataName,
|
||||
isNullable,
|
||||
} = relation;
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(foreignKeyValues, foreignKey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const foreignKeyValue =
|
||||
foreignKeyValues[foreignKey as keyof typeof foreignKeyValues];
|
||||
|
||||
const mapsKey = getMetadataFlatEntityMapsKey(
|
||||
targetMetadataName,
|
||||
) as keyof RequiredFlatEntityMapsForForeignKeys<T, TProvidedKeys>;
|
||||
const targetFlatEntityMaps = flatEntityMaps[mapsKey];
|
||||
|
||||
// TODO refactor using the new ALL_METADATA_UNIVERSAL_RELATION afterwards
|
||||
const universalIdentifierKey = foreignKey.replace(
|
||||
/Id$/,
|
||||
'UniversalIdentifier',
|
||||
);
|
||||
|
||||
if (isNullable && !isDefined(foreignKeyValue)) {
|
||||
result[universalIdentifierKey] = null;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const resolvedUniversalIdentifier =
|
||||
targetFlatEntityMaps.universalIdentifierById[foreignKeyValue as string];
|
||||
|
||||
if (!isDefined(resolvedUniversalIdentifier)) {
|
||||
throw new FlatEntityMapsException(
|
||||
t`Could not find ${targetMetadataName} for given ${foreignKey}`,
|
||||
FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
result[universalIdentifierKey] = resolvedUniversalIdentifier;
|
||||
}
|
||||
|
||||
return result as ResolvedUniversalIdentifiers<T, TProvidedKeys>;
|
||||
};
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveUniversalIdentifierFromFlatEntityIdOrThrow = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string;
|
||||
metadataName: T;
|
||||
}): string => {
|
||||
const flatEntity = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
});
|
||||
|
||||
if (!isDefined(flatEntity)) {
|
||||
throw new FlatEntityMapsException(
|
||||
t`Could not find ${metadataName}`,
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return flatEntity.universalIdentifier;
|
||||
};
|
||||
|
||||
// @deprecated Use resolveEntityRelationUniversalIdentifiers instead
|
||||
export const resolveNullableUniversalIdentifierFromFlatEntityId = <
|
||||
T extends AllMetadataName,
|
||||
>({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
}: {
|
||||
flatEntityMaps: MetadataFlatEntityMaps<T>;
|
||||
flatEntityId: string | null | undefined;
|
||||
metadataName: T;
|
||||
}): string | null => {
|
||||
if (!isDefined(flatEntityId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return resolveUniversalIdentifierFromFlatEntityIdOrThrow({
|
||||
flatEntityMaps,
|
||||
flatEntityId,
|
||||
metadataName,
|
||||
});
|
||||
};
|
||||
+5
-1
@@ -1,4 +1,4 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test suite Failure cases should fail when morphRelationsCreationPayload has different relation types 1`] = `
|
||||
{
|
||||
@@ -315,6 +315,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"indexMetadatas": [
|
||||
{
|
||||
"applicationId": Any<String>,
|
||||
"applicationUniversalIdentifier": Any<String>,
|
||||
"createdAt": Any<String>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
@@ -333,12 +334,14 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isUnique": false,
|
||||
"name": "IDX_f687e4e4252800dddd8e5518362",
|
||||
"objectMetadataId": Any<String>,
|
||||
"objectMetadataUniversalIdentifier": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": Any<String>,
|
||||
"applicationUniversalIdentifier": Any<String>,
|
||||
"createdAt": Any<String>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
@@ -357,6 +360,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"isUnique": false,
|
||||
"name": "IDX_cb15d901e889e25d0a9acecb595",
|
||||
"objectMetadataId": Any<String>,
|
||||
"objectMetadataUniversalIdentifier": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
"updatedAt": Any<String>,
|
||||
"workspaceId": Any<String>,
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { type FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { type FlatEntityFromV2 } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from-v2.type';
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
|
||||
export type FlatFieldMetadata<T extends FieldMetadataType = FieldMetadataType> =
|
||||
FlatEntityFromV2<
|
||||
FlatEntityFrom<
|
||||
Omit<
|
||||
FieldMetadataEntity<T>,
|
||||
'relationTargetFieldMetadata' | 'relationTargetObjectMetadata'
|
||||
|
||||
+4
@@ -41,10 +41,14 @@ export const generateIndexForFlatFieldMetadata = ({
|
||||
isCustom: true,
|
||||
isUnique: flatFieldMetadata.isUnique ?? false,
|
||||
objectMetadataId: flatObjectMetadata.id,
|
||||
objectMetadataUniversalIdentifier:
|
||||
flatObjectMetadata.universalIdentifier,
|
||||
universalIdentifier: indexId,
|
||||
updatedAt: createdAt,
|
||||
workspaceId,
|
||||
applicationId: flatFieldMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
flatFieldMetadata.applicationUniversalIdentifier,
|
||||
},
|
||||
flatObjectMetadata,
|
||||
},
|
||||
|
||||
+13
-5
@@ -2,10 +2,10 @@ import { type FromTo } from 'twenty-shared/types';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-universal-identifier-in-universal-flat-entity-maps-or-throw.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { reduceFlatViewGroupsByViewId } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-id.util';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
|
||||
type HandleFlatFieldMetadataDeactivationSideEffectsArgs = FromTo<
|
||||
@@ -59,14 +59,22 @@ export const handleFieldMetadataDeactivationSideEffects = ({
|
||||
flatEntityMaps: flatViewGroupMaps,
|
||||
});
|
||||
|
||||
const { flatViewGroupRecordByViewId } = reduceFlatViewGroupsByViewId({
|
||||
flatViewGroups,
|
||||
});
|
||||
const uniqueViewUniversalIdentifiers = [
|
||||
...new Set(flatViewGroups.map((vg) => vg.viewUniversalIdentifier)),
|
||||
];
|
||||
|
||||
const flatViewsWithViewGroups =
|
||||
findManyFlatEntityByUniversalIdentifierInUniversalFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatViewMaps,
|
||||
universalIdentifiers: uniqueViewUniversalIdentifiers,
|
||||
});
|
||||
|
||||
const viewIdsFromViewGroups = flatViewsWithViewGroups.map((view) => view.id);
|
||||
|
||||
// Note: We assume a view only has view groups related to one field
|
||||
const viewIdsToDelete = [
|
||||
...new Set([
|
||||
...Object.keys(flatViewGroupRecordByViewId),
|
||||
...viewIdsFromViewGroups,
|
||||
...fromFlatFieldMetadata.calendarViewIds,
|
||||
...fromFlatFieldMetadata.mainGroupByFieldMetadataViewIds,
|
||||
]),
|
||||
|
||||
+26
-10
@@ -3,10 +3,11 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-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 { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { reduceFlatViewGroupsByViewId } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-id.util';
|
||||
import { reduceFlatViewGroupsByViewUniversalIdentifier } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-universal-identifier.util';
|
||||
|
||||
type RecomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdateArgs = FromTo<
|
||||
FlatFieldMetadata,
|
||||
@@ -47,15 +48,19 @@ export const recomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdate = ({
|
||||
),
|
||||
flatEntityMaps: allFlatViewGroups,
|
||||
});
|
||||
const { flatViewGroupRecordByViewId, highestViewGroupPositionByViewId } =
|
||||
reduceFlatViewGroupsByViewId({
|
||||
flatViewGroups,
|
||||
});
|
||||
const {
|
||||
flatViewGroupRecordByViewUniversalIdentifier,
|
||||
highestViewGroupPositionByViewUniversalIdentifier,
|
||||
} = reduceFlatViewGroupsByViewUniversalIdentifier({
|
||||
flatViewGroups,
|
||||
});
|
||||
|
||||
for (const viewId in flatViewGroupRecordByViewId) {
|
||||
const flatViewGroups = Object.values(flatViewGroupRecordByViewId[viewId]);
|
||||
for (const viewUniversalIdentifier in flatViewGroupRecordByViewUniversalIdentifier) {
|
||||
const flatViewGroupsForView = Object.values(
|
||||
flatViewGroupRecordByViewUniversalIdentifier[viewUniversalIdentifier],
|
||||
);
|
||||
|
||||
const emptyValueFlatViewGroup = flatViewGroups.find(
|
||||
const emptyValueFlatViewGroup = flatViewGroupsForView.find(
|
||||
(flatViewGroup) => flatViewGroup.fieldValue === '',
|
||||
);
|
||||
|
||||
@@ -63,21 +68,32 @@ export const recomputeViewGroupsOnEnumFlatFieldMetadataIsNullableUpdate = ({
|
||||
toFlatFieldMetadata.isNullable === true &&
|
||||
!isDefined(emptyValueFlatViewGroup)
|
||||
) {
|
||||
const highestViewGroupPosition = highestViewGroupPositionByViewId[viewId];
|
||||
const highestViewGroupPosition =
|
||||
highestViewGroupPositionByViewUniversalIdentifier[
|
||||
viewUniversalIdentifier
|
||||
];
|
||||
const viewGroupId = v4();
|
||||
const createdAt = new Date().toISOString();
|
||||
|
||||
const flatView = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: flatViewMaps,
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
});
|
||||
|
||||
sideEffectResult.flatViewGroupsToCreate.push({
|
||||
id: viewGroupId,
|
||||
universalIdentifier: viewGroupId,
|
||||
fieldValue: '',
|
||||
position: highestViewGroupPosition + 1,
|
||||
applicationUniversalIdentifier:
|
||||
toFlatFieldMetadata.applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
isVisible: true,
|
||||
workspaceId: toFlatFieldMetadata.workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
viewId,
|
||||
viewId: flatView.id,
|
||||
applicationId: toFlatFieldMetadata.applicationId,
|
||||
});
|
||||
} else if (isDefined(emptyValueFlatViewGroup)) {
|
||||
|
||||
+42
-19
@@ -8,11 +8,12 @@ import {
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-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 { compareTwoFlatFieldMetadataEnumOptions } from 'src/engine/metadata-modules/flat-field-metadata/utils/compare-two-flat-field-metadata-enum-options.util';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { reduceFlatViewGroupsByViewId } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-id.util';
|
||||
import { reduceFlatViewGroupsByViewUniversalIdentifier } from 'src/engine/metadata-modules/flat-view-group/utils/reduce-flat-view-groups-by-view-universal-identifier.util';
|
||||
|
||||
type RecomputeViewGroupsOnFlatFieldMetadataOptionsUpdateArgs = {
|
||||
fromFlatFieldMetadata: FlatFieldMetadata<EnumFieldMetadataType>;
|
||||
@@ -85,51 +86,71 @@ export const recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate = ({
|
||||
),
|
||||
);
|
||||
|
||||
const viewGroupsByViewId = reduceFlatViewGroupsByViewId({
|
||||
flatViewGroups: remainingFlatViewGroups,
|
||||
});
|
||||
const viewGroupsByViewUniversalIdentifier =
|
||||
reduceFlatViewGroupsByViewUniversalIdentifier({
|
||||
flatViewGroups: remainingFlatViewGroups,
|
||||
});
|
||||
|
||||
// Count visible view groups per view to enforce the limit
|
||||
const visibleViewGroupCountByViewId = remainingFlatViewGroups.reduce<
|
||||
Record<string, number>
|
||||
>((acc, flatViewGroup) => {
|
||||
if (flatViewGroup.isVisible) {
|
||||
acc[flatViewGroup.viewId] = (acc[flatViewGroup.viewId] ?? 0) + 1;
|
||||
}
|
||||
const visibleViewGroupCountByViewUniversalIdentifier =
|
||||
remainingFlatViewGroups.reduce<Record<string, number>>(
|
||||
(acc, flatViewGroup) => {
|
||||
if (flatViewGroup.isVisible) {
|
||||
acc[flatViewGroup.viewUniversalIdentifier] =
|
||||
(acc[flatViewGroup.viewUniversalIdentifier] ?? 0) + 1;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const viewIds = Object.keys(viewGroupsByViewId.flatViewGroupRecordByViewId);
|
||||
const viewUniversalIdentifiers = Object.keys(
|
||||
viewGroupsByViewUniversalIdentifier.flatViewGroupRecordByViewUniversalIdentifier,
|
||||
);
|
||||
|
||||
const createdAt = new Date().toISOString();
|
||||
const flatViewGroupsToCreate = createdFieldMetadataOptions.flatMap(
|
||||
(option, createdOptionIndex) =>
|
||||
viewIds.map<FlatViewGroup>((viewId) => {
|
||||
viewUniversalIdentifiers.map<FlatViewGroup>((viewUniversalIdentifier) => {
|
||||
const viewGroupHighestPosition =
|
||||
viewGroupsByViewId.highestViewGroupPositionByViewId[viewId];
|
||||
viewGroupsByViewUniversalIdentifier
|
||||
.highestViewGroupPositionByViewUniversalIdentifier[
|
||||
viewUniversalIdentifier
|
||||
];
|
||||
|
||||
if (!isDefined(viewGroupHighestPosition)) {
|
||||
throw new FlatEntityMapsException(
|
||||
'View id highest position not found, should never occur',
|
||||
'View universal identifier highest position not found, should never occur',
|
||||
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const currentVisibleCount = visibleViewGroupCountByViewId[viewId] ?? 0;
|
||||
const currentVisibleCount =
|
||||
visibleViewGroupCountByViewUniversalIdentifier[
|
||||
viewUniversalIdentifier
|
||||
] ?? 0;
|
||||
const isVisible = currentVisibleCount < VIEW_GROUP_VISIBLE_OPTIONS_MAX;
|
||||
|
||||
// Increment the count for future iterations if this group will be visible
|
||||
if (isVisible) {
|
||||
visibleViewGroupCountByViewId[viewId] = currentVisibleCount + 1;
|
||||
visibleViewGroupCountByViewUniversalIdentifier[
|
||||
viewUniversalIdentifier
|
||||
] = currentVisibleCount + 1;
|
||||
}
|
||||
|
||||
const viewGroupId = v4();
|
||||
|
||||
const flatView = findFlatEntityByUniversalIdentifierOrThrow({
|
||||
flatEntityMaps: flatViewMaps,
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
});
|
||||
|
||||
return {
|
||||
id: viewGroupId,
|
||||
fieldMetadataId: fromFlatFieldMetadata.id,
|
||||
viewId,
|
||||
viewId: flatView.id,
|
||||
viewUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -139,6 +160,8 @@ export const recomputeViewGroupsOnFlatFieldMetadataOptionsUpdate = ({
|
||||
fieldValue: option.value,
|
||||
position: viewGroupHighestPosition + createdOptionIndex + 1,
|
||||
applicationId: fromFlatFieldMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
fromFlatFieldMetadata.applicationUniversalIdentifier,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
+5
-3
@@ -1,17 +1,18 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatFrontComponent } from 'src/engine/metadata-modules/flat-front-component/types/flat-front-component.type';
|
||||
import { type CreateFrontComponentInput } from 'src/engine/metadata-modules/front-component/dtos/create-front-component.input';
|
||||
|
||||
export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
|
||||
createFrontComponentInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
}: {
|
||||
createFrontComponentInput: CreateFrontComponentInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
}): FlatFrontComponent => {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -29,6 +30,7 @@ export const fromCreateFrontComponentInputToFlatFrontComponentToCreate = ({
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
universalIdentifier: id,
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-4
@@ -31,9 +31,6 @@ export const fromFrontComponentEntityToFlatFrontComponent = ({
|
||||
applicationId: frontComponentEntity.applicationId,
|
||||
createdAt: frontComponentEntity.createdAt.toISOString(),
|
||||
updatedAt: frontComponentEntity.updatedAt.toISOString(),
|
||||
__universal: {
|
||||
universalIdentifier: frontComponentEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+7
-1
@@ -4,7 +4,13 @@ import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-m
|
||||
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
|
||||
|
||||
type FlatIndexMetadataOverrides = Required<
|
||||
Pick<FlatIndexMetadata, 'universalIdentifier' | 'objectMetadataId'>
|
||||
Pick<
|
||||
FlatIndexMetadata,
|
||||
| 'universalIdentifier'
|
||||
| 'objectMetadataId'
|
||||
| 'objectMetadataUniversalIdentifier'
|
||||
| 'applicationUniversalIdentifier'
|
||||
>
|
||||
> &
|
||||
Partial<FlatIndexMetadata>;
|
||||
export const getFlatIndexMetadataMock = (
|
||||
|
||||
+2
-5
@@ -58,10 +58,7 @@ export const fromIndexMetadataEntityToFlatIndexMetadata = ({
|
||||
updatedAt: indexFieldMetadata.updatedAt.toISOString(),
|
||||
}),
|
||||
),
|
||||
__universal: {
|
||||
universalIdentifier: indexMetadataEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+35
-4
@@ -1,6 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
import { type CreateNavigationMenuItemInput } from 'src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input';
|
||||
@@ -9,14 +12,19 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
|
||||
({
|
||||
createNavigationMenuItemInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
flatNavigationMenuItemMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
}: {
|
||||
createNavigationMenuItemInput: CreateNavigationMenuItemInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
flatNavigationMenuItemMaps: FlatNavigationMenuItemMaps;
|
||||
}): FlatNavigationMenuItem => {
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps' | 'flatViewMaps'
|
||||
>): FlatNavigationMenuItem => {
|
||||
const id = uuidv4();
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -40,6 +48,25 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
|
||||
position = maxPosition + 1;
|
||||
}
|
||||
|
||||
const {
|
||||
targetObjectMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
folderUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'navigationMenuItem',
|
||||
foreignKeyValues: {
|
||||
targetObjectMetadataId:
|
||||
createNavigationMenuItemInput.targetObjectMetadataId,
|
||||
viewId: createNavigationMenuItemInput.viewId,
|
||||
folderId: createNavigationMenuItemInput.folderId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
flatNavigationMenuItemMaps,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
@@ -47,12 +74,16 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate =
|
||||
targetRecordId: createNavigationMenuItemInput.targetRecordId ?? null,
|
||||
targetObjectMetadataId:
|
||||
createNavigationMenuItemInput.targetObjectMetadataId ?? null,
|
||||
targetObjectMetadataUniversalIdentifier,
|
||||
viewId: createNavigationMenuItemInput.viewId ?? null,
|
||||
viewUniversalIdentifier,
|
||||
folderId: createNavigationMenuItemInput.folderId ?? null,
|
||||
folderUniversalIdentifier,
|
||||
name: createNavigationMenuItemInput.name ?? null,
|
||||
position,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+4
-7
@@ -87,12 +87,9 @@ export const fromNavigationMenuItemEntityToFlatNavigationMenuItem = ({
|
||||
applicationId: navigationMenuItemEntity.applicationId,
|
||||
createdAt: navigationMenuItemEntity.createdAt.toISOString(),
|
||||
updatedAt: navigationMenuItemEntity.updatedAt.toISOString(),
|
||||
__universal: {
|
||||
universalIdentifier: navigationMenuItemEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
targetObjectMetadataUniversalIdentifier,
|
||||
folderUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
targetObjectMetadataUniversalIdentifier,
|
||||
folderUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+18
-1
@@ -1,6 +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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_NAVIGATION_MENU_ITEM_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-navigation-menu-item/constants/flat-navigation-menu-item-editable-properties.constant';
|
||||
import { type FlatNavigationMenuItemMaps } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item-maps.type';
|
||||
import { type FlatNavigationMenuItem } from 'src/engine/metadata-modules/flat-navigation-menu-item/types/flat-navigation-menu-item.type';
|
||||
@@ -35,7 +36,7 @@ export const fromUpdateNavigationMenuItemInputToFlatNavigationMenuItemToUpdateOr
|
||||
|
||||
const { id: _id, ...updates } = updateNavigationMenuItemInput;
|
||||
|
||||
return {
|
||||
const flatNavigationMenuItemToUpdate = {
|
||||
...mergeUpdateInExistingRecord({
|
||||
existing: existingFlatNavigationMenuItem,
|
||||
properties: [...FLAT_NAVIGATION_MENU_ITEM_EDITABLE_PROPERTIES],
|
||||
@@ -43,4 +44,20 @@ export const fromUpdateNavigationMenuItemInputToFlatNavigationMenuItemToUpdateOr
|
||||
}),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (updates.folderId !== undefined) {
|
||||
const { folderUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'navigationMenuItem',
|
||||
foreignKeyValues: {
|
||||
folderId: flatNavigationMenuItemToUpdate.folderId,
|
||||
},
|
||||
flatEntityMaps: { flatNavigationMenuItemMaps },
|
||||
});
|
||||
|
||||
flatNavigationMenuItemToUpdate.folderUniversalIdentifier =
|
||||
folderUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatNavigationMenuItemToUpdate;
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { type FlatEntityFromV2 } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from-v2.type';
|
||||
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-from.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
type BaseFlatObjectMetadata = FlatEntityFromV2<
|
||||
type BaseFlatObjectMetadata = FlatEntityFrom<
|
||||
Omit<ObjectMetadataEntity, 'targetRelationFields' | 'dataSourceId'>
|
||||
>;
|
||||
export type FlatObjectMetadata = BaseFlatObjectMetadata & {
|
||||
|
||||
+1
@@ -75,6 +75,7 @@ export const handleFlatObjectMetadataUpdateSideEffect = ({
|
||||
existingFlatObjectMetadata: fromFlatObjectMetadata,
|
||||
flatViewFieldMaps,
|
||||
flatViewMaps,
|
||||
flatFieldMetadataMaps,
|
||||
updatedLabelIdentifierFieldMetadataId:
|
||||
toFlatObjectMetadata.labelIdentifierFieldMetadataId,
|
||||
})
|
||||
|
||||
+17
-1
@@ -2,6 +2,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/metadata-modules/flat-view-field/constants/default-view-field-size.constant';
|
||||
@@ -10,7 +11,10 @@ import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/
|
||||
type RecomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdateArgs = {
|
||||
existingFlatObjectMetadata: FlatObjectMetadata;
|
||||
updatedLabelIdentifierFieldMetadataId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatViewFieldMaps' | 'flatViewMaps'>;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatViewFieldMaps' | 'flatViewMaps' | 'flatFieldMetadataMaps'
|
||||
>;
|
||||
|
||||
type FlatViewFieldToCreateAndUpdate = {
|
||||
flatViewFieldsToCreate: FlatViewField[];
|
||||
@@ -20,6 +24,7 @@ export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({
|
||||
existingFlatObjectMetadata,
|
||||
flatViewFieldMaps,
|
||||
flatViewMaps,
|
||||
flatFieldMetadataMaps,
|
||||
updatedLabelIdentifierFieldMetadataId,
|
||||
}: RecomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdateArgs): FlatViewFieldToCreateAndUpdate => {
|
||||
const flatViews = findManyFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
@@ -27,6 +32,12 @@ export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({
|
||||
flatEntityIds: existingFlatObjectMetadata.viewIds,
|
||||
});
|
||||
|
||||
const updatedLabelIdentifierFieldMetadata =
|
||||
findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityMaps: flatFieldMetadataMaps,
|
||||
flatEntityId: updatedLabelIdentifierFieldMetadataId,
|
||||
});
|
||||
|
||||
const accumulator: FlatViewFieldToCreateAndUpdate = {
|
||||
flatViewFieldsToCreate: [],
|
||||
flatViewFieldsToUpdate: [],
|
||||
@@ -55,10 +66,13 @@ export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const flatViewFieldToCreate: FlatViewField = {
|
||||
fieldMetadataId: updatedLabelIdentifierFieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier:
|
||||
updatedLabelIdentifierFieldMetadata.universalIdentifier,
|
||||
position: lowestViewFieldPosition - 1,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
viewId: flatView.id,
|
||||
viewUniversalIdentifier: flatView.universalIdentifier,
|
||||
workspaceId: flatView.workspaceId,
|
||||
id: viewFieldId,
|
||||
createdAt: createdAt,
|
||||
@@ -67,6 +81,8 @@ export const recomputeViewFieldIdentifierAfterFlatObjectIdentifierUpdate = ({
|
||||
universalIdentifier: viewFieldId,
|
||||
aggregateOperation: null,
|
||||
applicationId: existingFlatObjectMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
existingFlatObjectMetadata.applicationUniversalIdentifier,
|
||||
};
|
||||
|
||||
accumulator.flatViewFieldsToCreate.push(flatViewFieldToCreate);
|
||||
|
||||
+22
-4
@@ -2,19 +2,23 @@ import { PageLayoutTabLayoutMode } from 'twenty-shared/types';
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { type CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout-tab/dtos/inputs/create-page-layout-tab.input';
|
||||
|
||||
export type FromCreatePageLayoutTabInputToFlatPageLayoutTabToCreateArgs = {
|
||||
createPageLayoutTabInput: CreatePageLayoutTabInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<AllFlatEntityMaps, 'flatPageLayoutMaps'>;
|
||||
|
||||
export const fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate = ({
|
||||
createPageLayoutTabInput: rawCreatePageLayoutTabInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutMaps,
|
||||
}: FromCreatePageLayoutTabInputToFlatPageLayoutTabToCreateArgs): FlatPageLayoutTab => {
|
||||
const createPageLayoutTabInput =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -25,18 +29,32 @@ export const fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const pageLayoutTabId = v4();
|
||||
|
||||
const { pageLayoutUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
flatEntityMaps: {
|
||||
flatPageLayoutMaps,
|
||||
},
|
||||
foreignKeyValues: {
|
||||
pageLayoutId: createPageLayoutTabInput.pageLayoutId,
|
||||
},
|
||||
metadataName: 'pageLayoutTab',
|
||||
});
|
||||
|
||||
return {
|
||||
id: pageLayoutTabId,
|
||||
title: createPageLayoutTabInput.title,
|
||||
position: createPageLayoutTabInput.position ?? 0,
|
||||
pageLayoutId: createPageLayoutTabInput.pageLayoutId,
|
||||
pageLayoutUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: pageLayoutTabId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
widgetIds: [],
|
||||
widgetUniversalIdentifiers: [],
|
||||
icon: null,
|
||||
layoutMode: PageLayoutTabLayoutMode.GRID,
|
||||
};
|
||||
|
||||
+5
-8
@@ -48,13 +48,10 @@ export const transformPageLayoutTabEntityToFlatPageLayoutTab = ({
|
||||
widgetIds: pageLayoutTabEntity.widgets.map((widget) => widget.id),
|
||||
icon: pageLayoutTabEntity.icon,
|
||||
layoutMode: pageLayoutTabEntity.layoutMode,
|
||||
__universal: {
|
||||
universalIdentifier: pageLayoutTabEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
pageLayoutUniversalIdentifier,
|
||||
widgetUniversalIdentifiers: pageLayoutTabEntity.widgets.map(
|
||||
(widget) => widget.universalIdentifier,
|
||||
),
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
pageLayoutUniversalIdentifier,
|
||||
widgetUniversalIdentifiers: pageLayoutTabEntity.widgets.map(
|
||||
(widget) => widget.universalIdentifier,
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
|
||||
export type FlatPageLayoutWidgetMaps = FlatEntityMaps<FlatPageLayoutWidget>;
|
||||
export type FlatPageLayoutWidgetMaps = FlatEntityMaps<
|
||||
Omit<FlatPageLayoutWidget, 'universalConfiguration'>
|
||||
>;
|
||||
|
||||
+1
-1
@@ -4,4 +4,4 @@ import { type WidgetConfigurationType } from 'src/engine/metadata-modules/page-l
|
||||
|
||||
export type FlatPageLayoutWidget<
|
||||
T extends WidgetConfigurationType = WidgetConfigurationType,
|
||||
> = FlatEntityFrom<PageLayoutWidgetEntity<T>>;
|
||||
> = Omit<FlatEntityFrom<PageLayoutWidgetEntity<T>>, 'universalConfiguration'>;
|
||||
|
||||
+27
-4
@@ -1,6 +1,9 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input';
|
||||
import { validateWidgetConfigurationInput } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-widget-configuration-input.util';
|
||||
@@ -9,13 +12,18 @@ export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
|
||||
{
|
||||
createPageLayoutWidgetInput: CreatePageLayoutWidgetInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatPageLayoutTabMaps' | 'flatObjectMetadataMaps'
|
||||
>;
|
||||
|
||||
export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
createPageLayoutWidgetInput: rawCreatePageLayoutWidgetInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => {
|
||||
const { pageLayoutTabId, ...createPageLayoutWidgetInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -30,9 +38,22 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const pageLayoutWidgetId = v4();
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id: pageLayoutWidgetId,
|
||||
pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -41,10 +62,12 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
title: createPageLayoutWidgetInput.title,
|
||||
type: createPageLayoutWidgetInput.type,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: createPageLayoutWidgetInput.gridPosition,
|
||||
position: createPageLayoutWidgetInput.position ?? null,
|
||||
configuration: createPageLayoutWidgetInput.configuration,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
conditionalDisplay: null,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-3
@@ -6,9 +6,9 @@ import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout
|
||||
|
||||
type PageLayoutWidgetConfiguration = PageLayoutWidgetEntity['configuration'];
|
||||
|
||||
type UniversalPageLayoutWidgetConfiguration = NonNullable<
|
||||
FlatPageLayoutWidget['__universal']
|
||||
>['universalConfiguration'];
|
||||
type UniversalPageLayoutWidgetConfiguration =
|
||||
// @ts-expect-error Ignoring until the pageLayoutWidget has been universally migrated
|
||||
NonNullable<FlatPageLayoutWidget>['universalConfiguration'];
|
||||
|
||||
// Field metadata IDs in widget configurations don't need to reference existing entities
|
||||
const getFieldMetadataUniversalIdentifier = ({
|
||||
|
||||
+10
-14
@@ -6,7 +6,6 @@ import {
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { fromPageLayoutWidgetConfigurationToUniversalConfiguration } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
|
||||
type FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs =
|
||||
@@ -19,7 +18,6 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
pageLayoutTabIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
}: FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs): FlatPageLayoutWidget => {
|
||||
const pageLayoutWidgetEntityWithoutRelations = removePropertiesFromRecord(
|
||||
pageLayoutWidgetEntity,
|
||||
@@ -66,11 +64,12 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
|
||||
}
|
||||
}
|
||||
|
||||
const configurationWithUniversalIdentifiers =
|
||||
fromPageLayoutWidgetConfigurationToUniversalConfiguration({
|
||||
configuration: pageLayoutWidgetEntityWithoutRelations.configuration,
|
||||
fieldMetadataIdToUniversalIdentifierMap,
|
||||
});
|
||||
// TODO uncomment once page layout widget has been migrated
|
||||
// const configurationWithUniversalIdentifiers =
|
||||
// fromPageLayoutWidgetConfigurationToUniversalConfiguration({
|
||||
// configuration: pageLayoutWidgetEntityWithoutRelations.configuration,
|
||||
// fieldMetadataIdToUniversalIdentifierMap,
|
||||
// });
|
||||
|
||||
return {
|
||||
...pageLayoutWidgetEntityWithoutRelations,
|
||||
@@ -80,12 +79,9 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
|
||||
universalIdentifier:
|
||||
pageLayoutWidgetEntityWithoutRelations.universalIdentifier,
|
||||
applicationId: pageLayoutWidgetEntityWithoutRelations.applicationId,
|
||||
__universal: {
|
||||
universalIdentifier: pageLayoutWidgetEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
universalConfiguration: configurationWithUniversalIdentifiers,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
// universalConfiguration: configurationWithUniversalIdentifiers,
|
||||
};
|
||||
};
|
||||
|
||||
+25
-3
@@ -4,8 +4,10 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
|
||||
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/update-page-layout-widget.input';
|
||||
@@ -25,10 +27,14 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro
|
||||
({
|
||||
updatePageLayoutWidgetInput: rawUpdatePageLayoutWidgetInput,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
updatePageLayoutWidgetInput: UpdatePageLayoutWidgetInputWithId;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}): FlatPageLayoutWidget => {
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps'
|
||||
>): FlatPageLayoutWidget => {
|
||||
const { id: pageLayoutWidgetToUpdateId } =
|
||||
extractAndSanitizeObjectStringFields(rawUpdatePageLayoutWidgetInput, [
|
||||
'id',
|
||||
@@ -63,9 +69,25 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro
|
||||
});
|
||||
}
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
const flatPageLayoutWidgetToUpdate = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPageLayoutWidgetToUpdate,
|
||||
properties: FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
|
||||
if (updatedEditableFieldProperties.objectMetadataId !== undefined) {
|
||||
const { objectMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: flatPageLayoutWidgetToUpdate.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
flatPageLayoutWidgetToUpdate.objectMetadataUniversalIdentifier =
|
||||
objectMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatPageLayoutWidgetToUpdate;
|
||||
};
|
||||
|
||||
+21
-4
@@ -1,6 +1,9 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
@@ -8,13 +11,14 @@ import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/pa
|
||||
export type FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs = {
|
||||
createPageLayoutInput: CreatePageLayoutInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
|
||||
|
||||
export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
|
||||
createPageLayoutInput: rawCreatePageLayoutInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
}: FromCreatePageLayoutInputToFlatPageLayoutToCreateArgs): FlatPageLayout => {
|
||||
const createPageLayoutInput =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -25,18 +29,31 @@ export const fromCreatePageLayoutInputToFlatPageLayoutToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const pageLayoutId = v4();
|
||||
|
||||
const { objectMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayout',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: createPageLayoutInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id: pageLayoutId,
|
||||
name: createPageLayoutInput.name,
|
||||
type: createPageLayoutInput.type ?? PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: createPageLayoutInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: pageLayoutId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
tabIds: [],
|
||||
tabUniversalIdentifiers: [],
|
||||
defaultTabToFocusOnMobileAndSidePanelId: null,
|
||||
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier: null,
|
||||
};
|
||||
};
|
||||
|
||||
+22
-3
@@ -4,8 +4,10 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout/constants/flat-page-layout-editable-properties.constant';
|
||||
import { type FlatPageLayoutMaps } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout-maps.type';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { type UpdatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout.input';
|
||||
@@ -23,10 +25,11 @@ export type UpdatePageLayoutInputWithId = {
|
||||
export const fromUpdatePageLayoutInputToFlatPageLayoutToUpdateOrThrow = ({
|
||||
updatePageLayoutInput: rawUpdatePageLayoutInput,
|
||||
flatPageLayoutMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
updatePageLayoutInput: UpdatePageLayoutInputWithId;
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
}): FlatPageLayout => {
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>): FlatPageLayout => {
|
||||
const { id: pageLayoutToUpdateId } = extractAndSanitizeObjectStringFields(
|
||||
rawUpdatePageLayoutInput,
|
||||
['id'],
|
||||
@@ -49,9 +52,25 @@ export const fromUpdatePageLayoutInputToFlatPageLayoutToUpdateOrThrow = ({
|
||||
FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
const flatPageLayoutToUpdate = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatPageLayoutToUpdate,
|
||||
properties: FLAT_PAGE_LAYOUT_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
|
||||
if (updatedEditableFieldProperties.objectMetadataId !== undefined) {
|
||||
const { objectMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayout',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: flatPageLayoutToUpdate.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
flatPageLayoutToUpdate.objectMetadataUniversalIdentifier =
|
||||
objectMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatPageLayoutToUpdate;
|
||||
};
|
||||
|
||||
+6
-9
@@ -70,14 +70,11 @@ export const transformPageLayoutEntityToFlatPageLayout = ({
|
||||
tabIds: pageLayoutEntity.tabs.map((tab) => tab.id),
|
||||
defaultTabToFocusOnMobileAndSidePanelId:
|
||||
pageLayoutEntity.defaultTabToFocusOnMobileAndSidePanelId,
|
||||
__universal: {
|
||||
universalIdentifier: pageLayoutEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
tabUniversalIdentifiers: pageLayoutEntity.tabs.map(
|
||||
(tab) => tab.universalIdentifier,
|
||||
),
|
||||
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
tabUniversalIdentifiers: pageLayoutEntity.tabs.map(
|
||||
(tab) => tab.universalIdentifier,
|
||||
),
|
||||
defaultTabToFocusOnMobileAndSidePanelUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+2
-5
@@ -44,10 +44,7 @@ export const fromRoleTargetEntityToFlatRoleTarget = ({
|
||||
universalIdentifier: roleTargetEntity.universalIdentifier,
|
||||
createdAt: roleTargetEntity.createdAt.toISOString(),
|
||||
updatedAt: roleTargetEntity.updatedAt.toISOString(),
|
||||
__universal: {
|
||||
universalIdentifier: roleTargetEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+8
-3
@@ -1,17 +1,18 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
|
||||
import { type CreateRoleInput } from 'src/engine/metadata-modules/role/dtos/create-role-input.dto';
|
||||
|
||||
export const fromCreateRoleInputToFlatRoleToCreate = ({
|
||||
createRoleInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
}: {
|
||||
createRoleInput: CreateRoleInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
}): FlatRole => {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -48,12 +49,16 @@ export const fromCreateRoleInputToFlatRoleToCreate = ({
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
universalIdentifier: createRoleInput.universalIdentifier ?? v4(),
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
roleTargetIds: [],
|
||||
roleTargetUniversalIdentifiers: [],
|
||||
objectPermissionIds: [],
|
||||
permissionFlagIds: [],
|
||||
fieldPermissionIds: [],
|
||||
rowLevelPermissionPredicateIds: [],
|
||||
rowLevelPermissionPredicateUniversalIdentifiers: [],
|
||||
rowLevelPermissionPredicateGroupIds: [],
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifiers: [],
|
||||
};
|
||||
};
|
||||
|
||||
+10
-13
@@ -64,20 +64,17 @@ export const fromRoleEntityToFlatRole = ({
|
||||
),
|
||||
rowLevelPermissionPredicateGroupIds:
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(({ id }) => id),
|
||||
__universal: {
|
||||
universalIdentifier: roleEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
roleTargetUniversalIdentifiers: roleEntity.roleTargets.map(
|
||||
applicationUniversalIdentifier,
|
||||
roleTargetUniversalIdentifiers: roleEntity.roleTargets.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicates.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicates.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifiers:
|
||||
roleEntity.rowLevelPermissionPredicateGroups.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
+6
-10
@@ -120,15 +120,11 @@ export const fromRowLevelPermissionPredicateEntityToFlatRowLevelPermissionPredic
|
||||
rowLevelPermissionPredicateEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateEntityWithoutRelations.universalIdentifier,
|
||||
__universal: {
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+12
-16
@@ -106,21 +106,17 @@ export const fromRowLevelPermissionPredicateGroupEntityToFlatRowLevelPermissionP
|
||||
rowLevelPermissionPredicateGroupEntity.rowLevelPermissionPredicates ??
|
||||
[]
|
||||
).map(({ id }) => id),
|
||||
__universal: {
|
||||
universalIdentifier:
|
||||
rowLevelPermissionPredicateGroupEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
childRowLevelPermissionPredicateGroupUniversalIdentifiers: (
|
||||
rowLevelPermissionPredicateGroupEntity.childRowLevelPermissionPredicateGroups ??
|
||||
[]
|
||||
).map(({ universalIdentifier }) => universalIdentifier),
|
||||
rowLevelPermissionPredicateUniversalIdentifiers: (
|
||||
rowLevelPermissionPredicateGroupEntity.rowLevelPermissionPredicates ??
|
||||
[]
|
||||
).map(({ universalIdentifier }) => universalIdentifier),
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
roleUniversalIdentifier,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
childRowLevelPermissionPredicateGroupUniversalIdentifiers: (
|
||||
rowLevelPermissionPredicateGroupEntity.childRowLevelPermissionPredicateGroups ??
|
||||
[]
|
||||
).map(({ universalIdentifier }) => universalIdentifier),
|
||||
rowLevelPermissionPredicateUniversalIdentifiers: (
|
||||
rowLevelPermissionPredicateGroupEntity.rowLevelPermissionPredicates ??
|
||||
[]
|
||||
).map(({ universalIdentifier }) => universalIdentifier),
|
||||
};
|
||||
};
|
||||
|
||||
+5
-3
@@ -1,17 +1,18 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatSkill } from 'src/engine/metadata-modules/flat-skill/types/flat-skill.type';
|
||||
import { type CreateSkillInput } from 'src/engine/metadata-modules/skill/dtos/create-skill.input';
|
||||
|
||||
export const fromCreateSkillInputToFlatSkillToCreate = ({
|
||||
createSkillInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
}: {
|
||||
createSkillInput: CreateSkillInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
}): FlatSkill => {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -39,6 +40,7 @@ export const fromCreateSkillInputToFlatSkillToCreate = ({
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
universalIdentifier: id,
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-4
@@ -35,9 +35,6 @@ export const fromSkillEntityToFlatSkill = ({
|
||||
isActive: skillEntity.isActive,
|
||||
universalIdentifier: skillEntity.universalIdentifier,
|
||||
applicationId: skillEntity.applicationId,
|
||||
__universal: {
|
||||
universalIdentifier: skillEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+19
-4
@@ -1,6 +1,9 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/metadata-modules/flat-view-field/constants/default-view-field-size.constant';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { type CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input';
|
||||
@@ -8,13 +11,15 @@ import { type CreateViewFieldInput } from 'src/engine/metadata-modules/view-fiel
|
||||
export type FromCreateViewFieldInputToFlatViewFieldToCreateArgs = {
|
||||
createViewFieldInput: CreateViewFieldInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<AllFlatEntityMaps, 'flatFieldMetadataMaps' | 'flatViewMaps'>;
|
||||
|
||||
export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
createViewFieldInput: rawCreateViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
}: FromCreateViewFieldInputToFlatViewFieldToCreateArgs): FlatViewField => {
|
||||
const { fieldMetadataId, viewId, ...createViewFieldInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -25,10 +30,19 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewFieldId = createViewFieldInput.id ?? v4();
|
||||
|
||||
const { fieldMetadataUniversalIdentifier, viewUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: { fieldMetadataId, viewId },
|
||||
flatEntityMaps: { flatFieldMetadataMaps, flatViewMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id: viewFieldId,
|
||||
fieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewId,
|
||||
viewUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -38,6 +52,7 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
size: createViewFieldInput.size ?? DEFAULT_VIEW_FIELD_SIZE,
|
||||
position: createViewFieldInput.position ?? 0,
|
||||
aggregateOperation: createViewFieldInput.aggregateOperation ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-6
@@ -58,11 +58,8 @@ export const fromViewFieldEntityToFlatViewField = ({
|
||||
updatedAt: viewFieldEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFieldEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewFieldEntityWithoutRelations.universalIdentifier,
|
||||
__universal: {
|
||||
universalIdentifier: viewFieldEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+28
-4
@@ -1,6 +1,9 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatViewFilterGroup } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group.type';
|
||||
import { type CreateViewFilterGroupInput } from 'src/engine/metadata-modules/view-filter-group/dtos/inputs/create-view-filter-group.input';
|
||||
import { ViewFilterGroupLogicalOperator } from 'src/engine/metadata-modules/view-filter-group/enums/view-filter-group-logical-operator';
|
||||
@@ -8,12 +11,17 @@ import { ViewFilterGroupLogicalOperator } from 'src/engine/metadata-modules/view
|
||||
export const fromCreateViewFilterGroupInputToFlatViewFilterGroupToCreate = ({
|
||||
createViewFilterGroupInput: rawCreateViewFilterGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatViewMaps,
|
||||
flatViewFilterGroupMaps,
|
||||
}: {
|
||||
createViewFilterGroupInput: CreateViewFilterGroupInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewFilterGroup => {
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatViewMaps' | 'flatViewFilterGroupMaps'
|
||||
>): FlatViewFilterGroup => {
|
||||
const { viewId, ...createViewFilterGroupInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreateViewFilterGroupInput,
|
||||
@@ -23,9 +31,21 @@ export const fromCreateViewFilterGroupInputToFlatViewFilterGroupToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewFilterGroupId = createViewFilterGroupInput.id ?? v4();
|
||||
|
||||
const { viewUniversalIdentifier, parentViewFilterGroupUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewFilterGroup',
|
||||
foreignKeyValues: {
|
||||
viewId,
|
||||
parentViewFilterGroupId:
|
||||
createViewFilterGroupInput.parentViewFilterGroupId,
|
||||
},
|
||||
flatEntityMaps: { flatViewMaps, flatViewFilterGroupMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id: viewFilterGroupId,
|
||||
viewId,
|
||||
viewUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -36,10 +56,14 @@ export const fromCreateViewFilterGroupInputToFlatViewFilterGroupToCreate = ({
|
||||
ViewFilterGroupLogicalOperator.AND,
|
||||
parentViewFilterGroupId:
|
||||
createViewFilterGroupInput.parentViewFilterGroupId ?? null,
|
||||
parentViewFilterGroupUniversalIdentifier,
|
||||
positionInViewFilterGroup:
|
||||
createViewFilterGroupInput.positionInViewFilterGroup ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
viewFilterIds: [],
|
||||
viewFilterUniversalIdentifiers: [],
|
||||
childViewFilterGroupIds: [],
|
||||
childViewFilterGroupUniversalIdentifiers: [],
|
||||
};
|
||||
};
|
||||
|
||||
+20
-2
@@ -4,8 +4,9 @@ import {
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter-group/constants/flat-view-filter-group-editable-properties.constant';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter-group/constants/flat-view-filter-group-editable-properties.constant';
|
||||
import { type FlatViewFilterGroupMaps } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group-maps.type';
|
||||
import { type FlatViewFilterGroup } from 'src/engine/metadata-modules/flat-view-filter-group/types/flat-view-filter-group.type';
|
||||
import { type UpdateViewFilterGroupInput } from 'src/engine/metadata-modules/view-filter-group/dtos/inputs/update-view-filter-group.input';
|
||||
@@ -47,9 +48,26 @@ export const fromUpdateViewFilterGroupInputToFlatViewFilterGroupToUpdateOrThrow
|
||||
FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
const flatViewFilterGroupToUpdate = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatViewFilterGroupToUpdate,
|
||||
properties: FLAT_VIEW_FILTER_GROUP_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
|
||||
if (updatedEditableFieldProperties.parentViewFilterGroupId !== undefined) {
|
||||
const { parentViewFilterGroupUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewFilterGroup',
|
||||
foreignKeyValues: {
|
||||
parentViewFilterGroupId:
|
||||
flatViewFilterGroupToUpdate.parentViewFilterGroupId,
|
||||
},
|
||||
flatEntityMaps: { flatViewFilterGroupMaps },
|
||||
});
|
||||
|
||||
flatViewFilterGroupToUpdate.parentViewFilterGroupUniversalIdentifier =
|
||||
parentViewFilterGroupUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatViewFilterGroupToUpdate;
|
||||
};
|
||||
|
||||
+11
-14
@@ -73,19 +73,16 @@ export const fromViewFilterGroupEntityToFlatViewFilterGroup = ({
|
||||
viewFilterIds: viewFilterGroupEntity.viewFilters?.map(({ id }) => id) ?? [],
|
||||
childViewFilterGroupIds:
|
||||
viewFilterGroupEntity.childViewFilterGroups?.map(({ id }) => id) ?? [],
|
||||
__universal: {
|
||||
universalIdentifier: viewFilterGroupEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
parentViewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFilterUniversalIdentifiers:
|
||||
viewFilterGroupEntity.viewFilters?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
childViewFilterGroupUniversalIdentifiers:
|
||||
viewFilterGroupEntity.childViewFilterGroups?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
parentViewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFilterUniversalIdentifiers:
|
||||
viewFilterGroupEntity.viewFilters?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
childViewFilterGroupUniversalIdentifiers:
|
||||
viewFilterGroupEntity.childViewFilterGroups?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
};
|
||||
};
|
||||
|
||||
+35
-4
@@ -2,18 +2,27 @@ import { ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input';
|
||||
|
||||
export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
createViewFilterInput: rawCreateViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
flatViewFilterGroupMaps,
|
||||
}: {
|
||||
createViewFilterInput: CreateViewFilterInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewFilter => {
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatFieldMetadataMaps' | 'flatViewMaps' | 'flatViewFilterGroupMaps'
|
||||
>): FlatViewFilter => {
|
||||
const { fieldMetadataId, viewId, value, ...createViewFilterInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreateViewFilterInput,
|
||||
@@ -30,10 +39,30 @@ export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewFilterId = createViewFilterInput.id ?? v4();
|
||||
|
||||
const {
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFilterGroupUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewFilter',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId,
|
||||
viewId,
|
||||
viewFilterGroupId: createViewFilterInput.viewFilterGroupId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
flatViewFilterGroupMaps,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: viewFilterId,
|
||||
fieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewId,
|
||||
viewUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -42,9 +71,11 @@ export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
operand: createViewFilterInput.operand ?? ViewFilterOperand.CONTAINS,
|
||||
value: value,
|
||||
viewFilterGroupId: createViewFilterInput.viewFilterGroupId ?? null,
|
||||
viewFilterGroupUniversalIdentifier,
|
||||
positionInViewFilterGroup:
|
||||
createViewFilterInput.positionInViewFilterGroup ?? null,
|
||||
subFieldName: createViewFilterInput.subFieldName ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+40
-3
@@ -5,8 +5,10 @@ import {
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant';
|
||||
import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type';
|
||||
import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type';
|
||||
import { type UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input';
|
||||
@@ -19,10 +21,15 @@ import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-
|
||||
export const fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow = ({
|
||||
updateViewFilterInput: rawUpdateViewFilterInput,
|
||||
flatViewFilterMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewFilterGroupMaps,
|
||||
}: {
|
||||
updateViewFilterInput: UpdateViewFilterInput;
|
||||
flatViewFilterMaps: FlatViewFilterMaps;
|
||||
}): FlatViewFilter => {
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatFieldMetadataMaps' | 'flatViewFilterGroupMaps'
|
||||
>): FlatViewFilter => {
|
||||
const { id: viewFilterToUpdateId } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawUpdateViewFilterInput,
|
||||
@@ -46,9 +53,39 @@ export const fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow = ({
|
||||
FLAT_VIEW_FILTER_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
return mergeUpdateInExistingRecord({
|
||||
const flatViewFilterToUpdate = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatViewFilterToUpdate,
|
||||
properties: FLAT_VIEW_FILTER_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
|
||||
if (updatedEditableFieldProperties.fieldMetadataId !== undefined) {
|
||||
const { fieldMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewFilter',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId: flatViewFilterToUpdate.fieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatFieldMetadataMaps },
|
||||
});
|
||||
|
||||
flatViewFilterToUpdate.fieldMetadataUniversalIdentifier =
|
||||
fieldMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (updatedEditableFieldProperties.viewFilterGroupId !== undefined) {
|
||||
const { viewFilterGroupUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewFilter',
|
||||
foreignKeyValues: {
|
||||
viewFilterGroupId: flatViewFilterToUpdate.viewFilterGroupId,
|
||||
},
|
||||
flatEntityMaps: { flatViewFilterGroupMaps },
|
||||
});
|
||||
|
||||
flatViewFilterToUpdate.viewFilterGroupUniversalIdentifier =
|
||||
viewFilterGroupUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatViewFilterToUpdate;
|
||||
};
|
||||
|
||||
+4
-7
@@ -75,12 +75,9 @@ export const fromViewFilterEntityToFlatViewFilter = ({
|
||||
updatedAt: viewFilterEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewFilterEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewFilterEntityWithoutRelations.universalIdentifier,
|
||||
__universal: {
|
||||
universalIdentifier: viewFilterEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewFilterGroupUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+8
@@ -12,11 +12,13 @@ import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/
|
||||
|
||||
type ComputeFlatViewGroupsOnViewCreateArgs = {
|
||||
flatViewToCreateId: string;
|
||||
flatViewToCreateUniversalIdentifier: string;
|
||||
mainGroupByFieldMetadataId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatFieldMetadataMaps'>;
|
||||
|
||||
export const computeFlatViewGroupsOnViewCreate = ({
|
||||
flatViewToCreateId,
|
||||
flatViewToCreateUniversalIdentifier,
|
||||
mainGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps,
|
||||
}: ComputeFlatViewGroupsOnViewCreateArgs): FlatViewGroup[] => {
|
||||
@@ -43,6 +45,7 @@ export const computeFlatViewGroupsOnViewCreate = ({
|
||||
id: viewGroupId,
|
||||
fieldMetadataId: mainGroupByFieldMetadata.id,
|
||||
viewId: flatViewToCreateId,
|
||||
viewUniversalIdentifier: flatViewToCreateUniversalIdentifier,
|
||||
workspaceId: mainGroupByFieldMetadata.workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -52,6 +55,8 @@ export const computeFlatViewGroupsOnViewCreate = ({
|
||||
fieldValue: option.value,
|
||||
position: index,
|
||||
applicationId: mainGroupByFieldMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
mainGroupByFieldMetadata.applicationUniversalIdentifier,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -64,6 +69,7 @@ export const computeFlatViewGroupsOnViewCreate = ({
|
||||
flatViewGroups.push({
|
||||
id: emptyGroupId,
|
||||
viewId: flatViewToCreateId,
|
||||
viewUniversalIdentifier: flatViewToCreateUniversalIdentifier,
|
||||
workspaceId: mainGroupByFieldMetadata.workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -73,6 +79,8 @@ export const computeFlatViewGroupsOnViewCreate = ({
|
||||
fieldValue: '',
|
||||
position: emptyGroupPosition,
|
||||
applicationId: mainGroupByFieldMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
mainGroupByFieldMetadata.applicationUniversalIdentifier,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+18
-4
@@ -1,18 +1,22 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { type CreateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/create-view-group.input';
|
||||
|
||||
export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
createViewGroupInput: rawCreateViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatViewMaps,
|
||||
}: {
|
||||
createViewGroupInput: CreateViewGroupInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewGroup => {
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<AllFlatEntityMaps, 'flatViewMaps'>): FlatViewGroup => {
|
||||
const { viewId, ...createViewGroupInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
rawCreateViewGroupInput,
|
||||
@@ -22,9 +26,18 @@ export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewGroupId = createViewGroupInput.id ?? v4();
|
||||
|
||||
const { viewUniversalIdentifier } = resolveEntityRelationUniversalIdentifiers(
|
||||
{
|
||||
metadataName: 'viewGroup',
|
||||
foreignKeyValues: { viewId },
|
||||
flatEntityMaps: { flatViewMaps },
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
id: viewGroupId,
|
||||
viewId,
|
||||
viewUniversalIdentifier,
|
||||
workspaceId,
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
@@ -33,6 +46,7 @@ export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
isVisible: createViewGroupInput.isVisible ?? true,
|
||||
fieldValue: createViewGroupInput.fieldValue,
|
||||
position: createViewGroupInput.position ?? 0,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+2
-5
@@ -45,10 +45,7 @@ export const fromViewGroupEntityToFlatViewGroup = ({
|
||||
updatedAt: viewGroupEntity.updatedAt.toISOString(),
|
||||
deletedAt: viewGroupEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: viewGroupEntityWithoutRelations.universalIdentifier,
|
||||
__universal: {
|
||||
universalIdentifier: viewGroupEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
|
||||
type FlatViewGroupsByViewId = {
|
||||
flatViewGroupRecordByViewId: Record<string, Record<string, FlatViewGroup>>;
|
||||
highestViewGroupPositionByViewId: Record<string, number>;
|
||||
};
|
||||
export const reduceFlatViewGroupsByViewId = ({
|
||||
flatViewGroups,
|
||||
}: {
|
||||
flatViewGroups: FlatViewGroup[];
|
||||
}): FlatViewGroupsByViewId => {
|
||||
const initialAccumulator: FlatViewGroupsByViewId = {
|
||||
flatViewGroupRecordByViewId: {},
|
||||
highestViewGroupPositionByViewId: {},
|
||||
};
|
||||
|
||||
return flatViewGroups.reduce((accumulator, flatViewGroup) => {
|
||||
const accumulatorHighestPosition =
|
||||
accumulator.highestViewGroupPositionByViewId[flatViewGroup.viewId];
|
||||
|
||||
return {
|
||||
flatViewGroupRecordByViewId: {
|
||||
...accumulator.flatViewGroupRecordByViewId,
|
||||
[flatViewGroup.viewId]: {
|
||||
...accumulator.flatViewGroupRecordByViewId[flatViewGroup.viewId],
|
||||
[flatViewGroup.id]: flatViewGroup,
|
||||
},
|
||||
},
|
||||
highestViewGroupPositionByViewId: {
|
||||
...accumulator.highestViewGroupPositionByViewId,
|
||||
[flatViewGroup.viewId]: isDefined(accumulatorHighestPosition)
|
||||
? Math.max(accumulatorHighestPosition, flatViewGroup.position)
|
||||
: flatViewGroup.position,
|
||||
},
|
||||
};
|
||||
}, initialAccumulator);
|
||||
};
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
|
||||
type FlatViewGroupsByViewUniversalIdentifier = {
|
||||
flatViewGroupRecordByViewUniversalIdentifier: Record<
|
||||
string,
|
||||
Record<string, FlatViewGroup>
|
||||
>;
|
||||
highestViewGroupPositionByViewUniversalIdentifier: Record<string, number>;
|
||||
};
|
||||
|
||||
export const reduceFlatViewGroupsByViewUniversalIdentifier = ({
|
||||
flatViewGroups,
|
||||
}: {
|
||||
flatViewGroups: FlatViewGroup[];
|
||||
}): FlatViewGroupsByViewUniversalIdentifier => {
|
||||
const initialAccumulator: FlatViewGroupsByViewUniversalIdentifier = {
|
||||
flatViewGroupRecordByViewUniversalIdentifier: {},
|
||||
highestViewGroupPositionByViewUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
return flatViewGroups.reduce((accumulator, flatViewGroup) => {
|
||||
const accumulatorHighestPosition =
|
||||
accumulator.highestViewGroupPositionByViewUniversalIdentifier[
|
||||
flatViewGroup.viewUniversalIdentifier
|
||||
];
|
||||
|
||||
return {
|
||||
flatViewGroupRecordByViewUniversalIdentifier: {
|
||||
...accumulator.flatViewGroupRecordByViewUniversalIdentifier,
|
||||
[flatViewGroup.viewUniversalIdentifier]: {
|
||||
...accumulator.flatViewGroupRecordByViewUniversalIdentifier[
|
||||
flatViewGroup.viewUniversalIdentifier
|
||||
],
|
||||
[flatViewGroup.id]: flatViewGroup,
|
||||
},
|
||||
},
|
||||
highestViewGroupPositionByViewUniversalIdentifier: {
|
||||
...accumulator.highestViewGroupPositionByViewUniversalIdentifier,
|
||||
[flatViewGroup.viewUniversalIdentifier]: isDefined(
|
||||
accumulatorHighestPosition,
|
||||
)
|
||||
? Math.max(accumulatorHighestPosition, flatViewGroup.position)
|
||||
: flatViewGroup.position,
|
||||
},
|
||||
};
|
||||
}, initialAccumulator);
|
||||
};
|
||||
+34
-3
@@ -4,7 +4,9 @@ import {
|
||||
} from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
import { computeFlatViewGroupsOnViewCreate } from 'src/engine/metadata-modules/flat-view-group/utils/compute-flat-view-groups-on-view-create.util';
|
||||
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
|
||||
@@ -17,14 +19,16 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
createViewInput: rawCreateViewInput,
|
||||
workspaceId,
|
||||
createdByUserWorkspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
createViewInput: CreateViewInput;
|
||||
workspaceId: string;
|
||||
createdByUserWorkspaceId?: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps'];
|
||||
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
|
||||
}): {
|
||||
flatViewToCreate: FlatView;
|
||||
flatViewGroupsToCreate: FlatViewGroup[];
|
||||
@@ -38,9 +42,27 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const viewId = createViewInput.id ?? v4();
|
||||
|
||||
const {
|
||||
objectMetadataUniversalIdentifier,
|
||||
calendarFieldMetadataUniversalIdentifier,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
mainGroupByFieldMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'view',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId,
|
||||
calendarFieldMetadataId: createViewInput.calendarFieldMetadataId,
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
createViewInput.kanbanAggregateOperationFieldMetadataId,
|
||||
mainGroupByFieldMetadataId: createViewInput.mainGroupByFieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps, flatFieldMetadataMaps },
|
||||
});
|
||||
|
||||
const flatViewToCreate = {
|
||||
id: viewId,
|
||||
objectMetadataId,
|
||||
objectMetadataUniversalIdentifier,
|
||||
workspaceId,
|
||||
name: createViewInput.name,
|
||||
createdAt: createdAt,
|
||||
@@ -49,6 +71,7 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
isCustom: true,
|
||||
anyFieldFilterValue: createViewInput.anyFieldFilterValue ?? null,
|
||||
calendarFieldMetadataId: createViewInput.calendarFieldMetadataId ?? null,
|
||||
calendarFieldMetadataUniversalIdentifier,
|
||||
calendarLayout: createViewInput.calendarLayout ?? null,
|
||||
icon: createViewInput.icon,
|
||||
isCompact: createViewInput.isCompact ?? false,
|
||||
@@ -56,8 +79,10 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
kanbanAggregateOperation: createViewInput.kanbanAggregateOperation ?? null,
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
createViewInput.kanbanAggregateOperationFieldMetadataId ?? null,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
mainGroupByFieldMetadataId:
|
||||
createViewInput.mainGroupByFieldMetadataId ?? null,
|
||||
mainGroupByFieldMetadataUniversalIdentifier,
|
||||
key: createViewInput.key ?? null,
|
||||
openRecordIn: createViewInput.openRecordIn ?? ViewOpenRecordIn.SIDE_PANEL,
|
||||
position: createViewInput.position ?? 0,
|
||||
@@ -66,10 +91,15 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
visibility: createViewInput.visibility ?? ViewVisibility.WORKSPACE,
|
||||
createdByUserWorkspaceId: createdByUserWorkspaceId ?? null,
|
||||
viewFieldIds: [],
|
||||
viewFieldUniversalIdentifiers: [],
|
||||
viewFilterIds: [],
|
||||
viewFilterUniversalIdentifiers: [],
|
||||
viewGroupIds: [],
|
||||
viewGroupUniversalIdentifiers: [],
|
||||
viewFilterGroupIds: [],
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
viewFilterGroupUniversalIdentifiers: [],
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
|
||||
let flatViewGroupsToCreate: FlatViewGroup[] = [];
|
||||
@@ -77,6 +107,7 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
if (isDefined(flatViewToCreate.mainGroupByFieldMetadataId)) {
|
||||
flatViewGroupsToCreate = computeFlatViewGroupsOnViewCreate({
|
||||
flatViewToCreateId: flatViewToCreate.id,
|
||||
flatViewToCreateUniversalIdentifier: flatViewToCreate.universalIdentifier,
|
||||
mainGroupByFieldMetadataId: flatViewToCreate.mainGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
+48
@@ -7,6 +7,7 @@ import {
|
||||
|
||||
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 { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { type FlatViewGroupMaps } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group-maps.type';
|
||||
import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/types/flat-view-group.type';
|
||||
@@ -67,6 +68,53 @@ export const fromUpdateViewInputToFlatViewToUpdateOrThrow = ({
|
||||
update: updatedEditableFieldProperties,
|
||||
});
|
||||
|
||||
if (
|
||||
updatedEditableFieldProperties.kanbanAggregateOperationFieldMetadataId !==
|
||||
undefined
|
||||
) {
|
||||
const { kanbanAggregateOperationFieldMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'view',
|
||||
foreignKeyValues: {
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
flatViewToUpdate.kanbanAggregateOperationFieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatFieldMetadataMaps },
|
||||
});
|
||||
|
||||
flatViewToUpdate.kanbanAggregateOperationFieldMetadataUniversalIdentifier =
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (updatedEditableFieldProperties.calendarFieldMetadataId !== undefined) {
|
||||
const { calendarFieldMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'view',
|
||||
foreignKeyValues: {
|
||||
calendarFieldMetadataId: flatViewToUpdate.calendarFieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatFieldMetadataMaps },
|
||||
});
|
||||
|
||||
flatViewToUpdate.calendarFieldMetadataUniversalIdentifier =
|
||||
calendarFieldMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (updatedEditableFieldProperties.mainGroupByFieldMetadataId !== undefined) {
|
||||
const { mainGroupByFieldMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'view',
|
||||
foreignKeyValues: {
|
||||
mainGroupByFieldMetadataId:
|
||||
flatViewToUpdate.mainGroupByFieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatFieldMetadataMaps },
|
||||
});
|
||||
|
||||
flatViewToUpdate.mainGroupByFieldMetadataUniversalIdentifier =
|
||||
mainGroupByFieldMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
// If changing visibility from WORKSPACE to UNLISTED, ensure createdByUserWorkspaceId is set
|
||||
// This prevents the view from disappearing for the user making the change
|
||||
if (
|
||||
|
||||
+17
-20
@@ -98,26 +98,23 @@ export const fromViewEntityToFlatView = ({
|
||||
viewFilterIds: viewEntity.viewFilters.map(({ id }) => id),
|
||||
viewGroupIds: viewEntity.viewGroups.map(({ id }) => id),
|
||||
viewFilterGroupIds: viewEntity.viewFilterGroups?.map(({ id }) => id) ?? [],
|
||||
__universal: {
|
||||
universalIdentifier: viewEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
calendarFieldMetadataUniversalIdentifier,
|
||||
mainGroupByFieldMetadataUniversalIdentifier,
|
||||
viewFieldUniversalIdentifiers: viewEntity.viewFields.map(
|
||||
applicationUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
kanbanAggregateOperationFieldMetadataUniversalIdentifier,
|
||||
calendarFieldMetadataUniversalIdentifier,
|
||||
mainGroupByFieldMetadataUniversalIdentifier,
|
||||
viewFieldUniversalIdentifiers: viewEntity.viewFields.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewFilterUniversalIdentifiers: viewEntity.viewFilters.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewGroupUniversalIdentifiers: viewEntity.viewGroups.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewFilterGroupUniversalIdentifiers:
|
||||
viewEntity.viewFilterGroups?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewFilterUniversalIdentifiers: viewEntity.viewFilters.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewGroupUniversalIdentifiers: viewEntity.viewGroups.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
),
|
||||
viewFilterGroupUniversalIdentifiers:
|
||||
viewEntity.viewFilterGroups?.map(
|
||||
({ universalIdentifier }) => universalIdentifier,
|
||||
) ?? [],
|
||||
},
|
||||
) ?? [],
|
||||
};
|
||||
};
|
||||
|
||||
+1
@@ -51,6 +51,7 @@ export const handleFlatViewUpdateSideEffect = ({
|
||||
|
||||
sideEffectResult.flatViewGroupsToCreate = computeFlatViewGroupsOnViewCreate({
|
||||
flatViewToCreateId: toFlatView.id,
|
||||
flatViewToCreateUniversalIdentifier: toFlatView.universalIdentifier,
|
||||
mainGroupByFieldMetadataId: newMainGroupByFieldMetadataId,
|
||||
flatFieldMetadataMaps,
|
||||
});
|
||||
|
||||
+5
-3
@@ -1,6 +1,7 @@
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type FlatWebhook } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook.type';
|
||||
import { type CreateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/create-webhook.input';
|
||||
import { generateWebhookSecret } from 'src/engine/metadata-modules/webhook/utils/generate-webhook-secret.util';
|
||||
@@ -8,11 +9,11 @@ import { generateWebhookSecret } from 'src/engine/metadata-modules/webhook/utils
|
||||
export const fromCreateWebhookInputToFlatWebhookToCreate = ({
|
||||
createWebhookInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
flatApplication,
|
||||
}: {
|
||||
createWebhookInput: CreateWebhookInput;
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
}): FlatWebhook => {
|
||||
const now = new Date().toISOString();
|
||||
|
||||
@@ -36,6 +37,7 @@ export const fromCreateWebhookInputToFlatWebhookToCreate = ({
|
||||
updatedAt: now,
|
||||
deletedAt: null,
|
||||
universalIdentifier: id,
|
||||
applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-4
@@ -33,9 +33,6 @@ export const fromWebhookEntityToFlatWebhook = ({
|
||||
createdAt: webhookEntity.createdAt.toISOString(),
|
||||
updatedAt: webhookEntity.updatedAt.toISOString(),
|
||||
deletedAt: webhookEntity.deletedAt?.toISOString() ?? null,
|
||||
__universal: {
|
||||
universalIdentifier: webhookEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-1
@@ -80,7 +80,7 @@ export class FrontComponentService {
|
||||
fromCreateFrontComponentInputToFlatFrontComponentToCreate({
|
||||
createFrontComponentInput: input,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+1
-4
@@ -78,9 +78,6 @@ export const fromCreateLogicFunctionInputToFlatLogicFunction = ({
|
||||
? DEFAULT_TOOL_INPUT_SCHEMA
|
||||
: null,
|
||||
isTool: rawCreateLogicFunctionInput?.isTool ?? false,
|
||||
__universal: {
|
||||
applicationUniversalIdentifier: ownerFlatApplication.universalIdentifier,
|
||||
universalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier: ownerFlatApplication.universalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+1
-4
@@ -34,9 +34,6 @@ export const fromLogicFunctionEntityToFlatLogicFunction = ({
|
||||
createdAt: logicFunctionEntity.createdAt.toISOString(),
|
||||
updatedAt: logicFunctionEntity.updatedAt.toISOString(),
|
||||
deletedAt: logicFunctionEntity.deletedAt?.toISOString() ?? null,
|
||||
__universal: {
|
||||
universalIdentifier: logicFunctionEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier,
|
||||
},
|
||||
applicationUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { APP_FILTER } from '@nestjs/core';
|
||||
|
||||
import { AiAgentMonitorModule } from 'src/engine/metadata-modules/ai/ai-agent-monitor/ai-agent-monitor.module';
|
||||
import { AiAgentModule } from 'src/engine/metadata-modules/ai/ai-agent/ai-agent.module';
|
||||
import { AiChatModule } from 'src/engine/metadata-modules/ai/ai-chat/ai-chat.module';
|
||||
import { CommandMenuItemModule } from 'src/engine/metadata-modules/command-menu-item/command-menu-item.module';
|
||||
import { NavigationMenuItemModule } from 'src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { FlatEntityMapsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/flat-entity/filters/flat-entity-maps-graphql-api-exception.filter';
|
||||
import { FrontComponentModule } from 'src/engine/metadata-modules/front-component/front-component.module';
|
||||
import { LogicFunctionLayerModule } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.module';
|
||||
import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module';
|
||||
import { NavigationMenuItemModule } from 'src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { WebhookModule } from 'src/engine/metadata-modules/webhook/webhook.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/route-trigger.module';
|
||||
import { SearchFieldMetadataModule } from 'src/engine/metadata-modules/search-field-metadata/search-field-metadata.module';
|
||||
import { LogicFunctionLayerModule } from 'src/engine/metadata-modules/logic-function-layer/logic-function-layer.module';
|
||||
import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/logic-function.module';
|
||||
import { SkillModule } from 'src/engine/metadata-modules/skill/skill.module';
|
||||
import { ViewModule } from 'src/engine/metadata-modules/view/view.module';
|
||||
import { WebhookModule } from 'src/engine/metadata-modules/webhook/webhook.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
|
||||
@Module({
|
||||
@@ -42,7 +44,12 @@ import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/work
|
||||
RouteTriggerModule,
|
||||
WebhookModule,
|
||||
],
|
||||
providers: [],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_FILTER,
|
||||
useClass: FlatEntityMapsGraphqlApiExceptionFilter,
|
||||
},
|
||||
],
|
||||
exports: [
|
||||
DataSourceModule,
|
||||
FieldMetadataModule,
|
||||
|
||||
+17
-8
@@ -148,13 +148,20 @@ export class NavigationMenuItemService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatNavigationMenuItemMaps'],
|
||||
},
|
||||
);
|
||||
const {
|
||||
flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
} = await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatNavigationMenuItemMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
'flatViewMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const normalizedInput: CreateNavigationMenuItemInput = {
|
||||
...input,
|
||||
@@ -168,8 +175,10 @@ export class NavigationMenuItemService {
|
||||
fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate({
|
||||
createNavigationMenuItemInput: normalizedInput,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatNavigationMenuItemMaps: existingFlatNavigationMenuItemMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+40
-8
@@ -397,21 +397,35 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
createEmptyFlatEntityMaps(),
|
||||
);
|
||||
|
||||
const optimisticFlatObjectMetadataMaps =
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatObjectMetadataToCreate,
|
||||
flatEntityMaps: createEmptyFlatEntityMaps(),
|
||||
});
|
||||
|
||||
const flatDefaultViewToCreate = await this.computeFlatViewToCreate({
|
||||
objectMetadata: flatObjectMetadataToCreate,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: resolvedOwnerFlatApplication,
|
||||
flatFieldMetadataMaps: optimisticFlatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps: optimisticFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const optimisticFlatViewMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatDefaultViewToCreate,
|
||||
flatEntityMaps: createEmptyFlatEntityMaps(),
|
||||
});
|
||||
|
||||
const flatDefaultViewFieldsToCreate =
|
||||
await this.computeFlatViewFieldsToCreate({
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
objectFlatFieldMetadatas: flatFieldMetadataToCreateOnObject,
|
||||
viewId: flatDefaultViewToCreate.id,
|
||||
workspaceId,
|
||||
labelIdentifierFieldMetadataId:
|
||||
flatObjectMetadataToCreate.labelIdentifierFieldMetadataId,
|
||||
flatFieldMetadataMaps: optimisticFlatFieldMetadataMaps,
|
||||
flatViewMaps: optimisticFlatViewMaps,
|
||||
});
|
||||
|
||||
const isNavigationMenuItemEnabled =
|
||||
@@ -423,6 +437,8 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
view: flatDefaultViewToCreate,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
})
|
||||
: null;
|
||||
|
||||
@@ -515,13 +531,15 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
private async computeFlatViewToCreate({
|
||||
objectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps'];
|
||||
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
|
||||
}) {
|
||||
const defaultViewInput = {
|
||||
objectMetadataId: objectMetadata.id,
|
||||
@@ -535,8 +553,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
const { flatViewToCreate } = fromCreateViewInputToFlatViewToCreate({
|
||||
createViewInput: defaultViewInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
return flatViewToCreate;
|
||||
@@ -546,14 +565,18 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
objectFlatFieldMetadatas,
|
||||
viewId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
labelIdentifierFieldMetadataId,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
objectFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
viewId: string;
|
||||
workspaceId: string;
|
||||
labelIdentifierFieldMetadataId: string | null;
|
||||
flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps'];
|
||||
flatViewMaps: AllFlatEntityMaps['flatViewMaps'];
|
||||
}) {
|
||||
const defaultViewFields = objectFlatFieldMetadatas
|
||||
.filter(
|
||||
@@ -571,8 +594,10 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
viewId: viewId,
|
||||
},
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
workspaceId: workspaceId,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -583,10 +608,12 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
view,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
view: FlatView;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): Promise<FlatNavigationMenuItem> {
|
||||
const { flatNavigationMenuItemMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
@@ -613,12 +640,17 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
userWorkspaceId: null,
|
||||
targetRecordId: null,
|
||||
targetObjectMetadataId: null,
|
||||
targetObjectMetadataUniversalIdentifier: null,
|
||||
viewId: view.id,
|
||||
viewUniversalIdentifier: view.universalIdentifier,
|
||||
folderId: null,
|
||||
folderUniversalIdentifier: null,
|
||||
name: null,
|
||||
position: nextPosition,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+4
-1
@@ -41,10 +41,13 @@ export const buildDefaultIndexesForCustomObject = ({
|
||||
isCustom: false,
|
||||
isUnique: false,
|
||||
objectMetadataId: flatObjectMetadata.id,
|
||||
objectMetadataUniversalIdentifier: flatObjectMetadata.universalIdentifier,
|
||||
universalIdentifier: tsFlatVectorIndexId,
|
||||
updatedAt: createdAt.toISOString(),
|
||||
workspaceId,
|
||||
applicationId: flatObjectMetadata.applicationId ?? null,
|
||||
applicationId: flatObjectMetadata.applicationId,
|
||||
applicationUniversalIdentifier:
|
||||
flatObjectMetadata.applicationUniversalIdentifier,
|
||||
},
|
||||
flatObjectMetadata,
|
||||
});
|
||||
|
||||
+10
-1
@@ -140,11 +140,20 @@ export class PageLayoutTabService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutMaps: existingFlatPageLayoutMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPageLayoutTabToCreate =
|
||||
fromCreatePageLayoutTabInputToFlatPageLayoutTabToCreate({
|
||||
createPageLayoutTabInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+20
-1
@@ -157,11 +157,21 @@ export class PageLayoutWidgetService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutTabMaps, flatObjectMetadataMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutTabMaps', 'flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPageLayoutWidgetToCreate =
|
||||
fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate({
|
||||
createPageLayoutWidgetInput: input,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
await this.validateAndRunWidgetMigration({
|
||||
@@ -203,6 +213,14 @@ export class PageLayoutWidgetService {
|
||||
const existingFlatPageLayoutWidgetMaps =
|
||||
await this.getFlatPageLayoutWidgetMaps(workspaceId);
|
||||
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
this.getExistingWidgetOrThrow(id, existingFlatPageLayoutWidgetMaps);
|
||||
|
||||
const updatePageLayoutWidgetInput: UpdatePageLayoutWidgetInputWithId = {
|
||||
@@ -216,6 +234,7 @@ export class PageLayoutWidgetService {
|
||||
fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThrow({
|
||||
updatePageLayoutWidgetInput,
|
||||
flatPageLayoutWidgetMaps: existingFlatPageLayoutWidgetMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
await this.validateAndRunWidgetMigration({
|
||||
|
||||
+43
-14
@@ -3,7 +3,11 @@ import { Injectable } from '@nestjs/common';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
@@ -46,6 +50,7 @@ export class PageLayoutDuplicationService {
|
||||
flatPageLayoutMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatObjectMetadataMaps,
|
||||
} = await this.getPageLayoutFlatEntityMaps(workspaceId);
|
||||
|
||||
const originalFlatLayout = this.findOriginalLayoutOrThrow(
|
||||
@@ -72,23 +77,41 @@ export class PageLayoutDuplicationService {
|
||||
objectMetadataId: originalFlatLayout.objectMetadataId,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
},
|
||||
);
|
||||
|
||||
const optimisticFlatPageLayoutMaps = addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: newFlatPageLayout,
|
||||
flatEntityMaps: createEmptyFlatEntityMaps(),
|
||||
});
|
||||
|
||||
const { newFlatTabs, originalTabIdToNewTabIdMap } =
|
||||
this.createDuplicatedTabs({
|
||||
originalTabs: originalTabsWithWidgets.map(({ tab }) => tab),
|
||||
newPageLayoutId: newFlatPageLayout.id,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatPageLayoutMaps: optimisticFlatPageLayoutMaps,
|
||||
});
|
||||
|
||||
const optimisticFlatPageLayoutTabMaps = newFlatTabs.reduce(
|
||||
(maps, flatTab) =>
|
||||
addFlatEntityToFlatEntityMapsOrThrow({
|
||||
flatEntity: flatTab,
|
||||
flatEntityMaps: maps,
|
||||
}),
|
||||
createEmptyFlatEntityMaps(),
|
||||
);
|
||||
|
||||
const newFlatWidgets = this.createDuplicatedWidgets({
|
||||
originalTabsWithWidgets,
|
||||
originalTabIdToNewTabIdMap,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatPageLayoutTabMaps: optimisticFlatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -146,11 +169,7 @@ export class PageLayoutDuplicationService {
|
||||
);
|
||||
}
|
||||
|
||||
private async getPageLayoutFlatEntityMaps(workspaceId: string): Promise<{
|
||||
flatPageLayoutMaps: FlatPageLayoutMaps;
|
||||
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
}> {
|
||||
private async getPageLayoutFlatEntityMaps(workspaceId: string) {
|
||||
return this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
@@ -158,6 +177,7 @@ export class PageLayoutDuplicationService {
|
||||
'flatPageLayoutMaps',
|
||||
'flatPageLayoutTabMaps',
|
||||
'flatPageLayoutWidgetMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
@@ -224,12 +244,14 @@ export class PageLayoutDuplicationService {
|
||||
originalTabs,
|
||||
newPageLayoutId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
originalTabs: FlatPageLayoutTab[];
|
||||
newPageLayoutId: string;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
flatPageLayoutMaps: AllFlatEntityMaps['flatPageLayoutMaps'];
|
||||
}): {
|
||||
newFlatTabs: FlatPageLayoutTab[];
|
||||
originalTabIdToNewTabIdMap: Map<string, string>;
|
||||
@@ -245,7 +267,8 @@ export class PageLayoutDuplicationService {
|
||||
pageLayoutId: newPageLayoutId,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutMaps,
|
||||
});
|
||||
|
||||
originalTabIdToNewTabIdMap.set(originalTab.id, newFlatTab.id);
|
||||
@@ -260,7 +283,9 @@ export class PageLayoutDuplicationService {
|
||||
originalTabsWithWidgets,
|
||||
originalTabIdToNewTabIdMap,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
originalTabsWithWidgets: {
|
||||
tab: FlatPageLayoutTab;
|
||||
@@ -268,7 +293,9 @@ export class PageLayoutDuplicationService {
|
||||
}[];
|
||||
originalTabIdToNewTabIdMap: Map<string, string>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
flatApplication: FlatApplication;
|
||||
flatPageLayoutTabMaps: AllFlatEntityMaps['flatPageLayoutTabMaps'];
|
||||
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
|
||||
}): FlatPageLayoutWidget[] {
|
||||
return originalTabsWithWidgets.flatMap(({ tab, widgets }) => {
|
||||
const newTabId = originalTabIdToNewTabIdMap.get(tab.id)!;
|
||||
@@ -284,7 +311,9 @@ export class PageLayoutDuplicationService {
|
||||
pageLayoutTabId: newTabId,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatApplication,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
+56
@@ -6,8 +6,10 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { MetadataFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity-maps.type';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
@@ -109,14 +111,28 @@ export class PageLayoutUpdateService {
|
||||
flatPageLayoutTabMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const { flatObjectMetadataMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const { widgetsToCreate, widgetsToUpdate, widgetsToDelete } =
|
||||
this.computeWidgetOperationsForAllTabs({
|
||||
tabs,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -196,12 +212,14 @@ export class PageLayoutUpdateService {
|
||||
flatPageLayoutTabMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
existingPageLayout: FlatPageLayout;
|
||||
tabs: UpdatePageLayoutTabWithWidgetsInput[];
|
||||
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
tabsToCreate: FlatPageLayoutTab[];
|
||||
tabsToUpdate: FlatPageLayoutTab[];
|
||||
@@ -238,13 +256,17 @@ export class PageLayoutUpdateService {
|
||||
title: tabInput.title,
|
||||
position: tabInput.position,
|
||||
pageLayoutId: existingPageLayout.id,
|
||||
pageLayoutUniversalIdentifier: existingPageLayout.universalIdentifier,
|
||||
workspaceId,
|
||||
createdAt: now.toISOString(),
|
||||
updatedAt: now.toISOString(),
|
||||
deletedAt: null,
|
||||
universalIdentifier: tabId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
widgetIds: [],
|
||||
widgetUniversalIdentifiers: [],
|
||||
icon: null,
|
||||
layoutMode: PageLayoutTabLayoutMode.GRID,
|
||||
};
|
||||
@@ -316,13 +338,19 @@ export class PageLayoutUpdateService {
|
||||
private computeWidgetOperationsForAllTabs({
|
||||
tabs,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
tabs: UpdatePageLayoutTabWithWidgetsInput[];
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
|
||||
flatObjectMetadataMaps: MetadataFlatEntityMaps<'objectMetadata'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
widgetsToCreate: FlatPageLayoutWidget[];
|
||||
widgetsToUpdate: FlatPageLayoutWidget[];
|
||||
@@ -337,8 +365,11 @@ export class PageLayoutUpdateService {
|
||||
tabId: tabInput.id,
|
||||
widgets: tabInput.widgets,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
allWidgetsToCreate.push(...widgetsToCreate);
|
||||
@@ -356,14 +387,20 @@ export class PageLayoutUpdateService {
|
||||
tabId,
|
||||
widgets,
|
||||
flatPageLayoutWidgetMaps,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
tabId: string;
|
||||
widgets: UpdatePageLayoutWidgetWithIdInput[];
|
||||
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
|
||||
flatPageLayoutTabMaps: FlatPageLayoutTabMaps;
|
||||
flatObjectMetadataMaps: MetadataFlatEntityMaps<'objectMetadata'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
widgetsToCreate: FlatPageLayoutWidget[];
|
||||
widgetsToUpdate: FlatPageLayoutWidget[];
|
||||
@@ -394,12 +431,29 @@ export class PageLayoutUpdateService {
|
||||
(widgetInput) => {
|
||||
const widgetId = widgetInput.id ?? v4();
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
id: widgetId,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
configuration: widgetInput.configuration ?? null,
|
||||
@@ -409,6 +463,8 @@ export class PageLayoutUpdateService {
|
||||
deletedAt: null,
|
||||
universalIdentifier: widgetId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
conditionalDisplay: null,
|
||||
};
|
||||
},
|
||||
|
||||
+16
-3
@@ -190,11 +190,20 @@ export class PageLayoutService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatObjectMetadataMaps: existingFlatObjectMetadataMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatPageLayoutToCreate =
|
||||
fromCreatePageLayoutInputToFlatPageLayoutToCreate({
|
||||
createPageLayoutInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -251,11 +260,14 @@ export class PageLayoutService {
|
||||
{ workspaceId },
|
||||
);
|
||||
|
||||
const { flatPageLayoutMaps: existingFlatPageLayoutMaps } =
|
||||
const {
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatPageLayoutMaps'],
|
||||
flatMapsKeys: ['flatPageLayoutMaps', 'flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -268,6 +280,7 @@ export class PageLayoutService {
|
||||
fromUpdatePageLayoutInputToFlatPageLayoutToUpdateOrThrow({
|
||||
updatePageLayoutInput,
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+14
-9
@@ -4,8 +4,8 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/services/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
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 { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { CreateRoleTargetInput } from 'src/engine/metadata-modules/role-target/types/create-role-target.input';
|
||||
import { fromCreateRoleTargetInputToFlatRoleTargetToCreate } from 'src/engine/metadata-modules/role-target/utils/from-create-role-target-input-to-flat-role-target-to-create.util';
|
||||
@@ -56,11 +56,15 @@ export class RoleTargetService {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { flatRoleTargetMaps } =
|
||||
const { flatRoleTargetMaps, flatApplicationMaps, flatRoleMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatRoleTargetMaps'],
|
||||
flatMapsKeys: [
|
||||
'flatRoleTargetMaps',
|
||||
'flatApplicationMaps',
|
||||
'flatRoleMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -75,16 +79,17 @@ export class RoleTargetService {
|
||||
const allFlatRoleTargetsToDelete: FlatRoleTarget[] = [];
|
||||
|
||||
for (const createRoleTargetInput of createRoleTargetInputs) {
|
||||
const flatApplication = isDefined(createRoleTargetInput.applicationId)
|
||||
? flatApplicationMaps.byId[createRoleTargetInput.applicationId]
|
||||
: undefined;
|
||||
|
||||
const { flatRoleTargetToCreate, flatRoleTargetsToDelete } =
|
||||
fromCreateRoleTargetInputToFlatRoleTargetToCreate({
|
||||
createRoleTargetInput: {
|
||||
...createRoleTargetInput,
|
||||
applicationId:
|
||||
createRoleTargetInput.applicationId ??
|
||||
workspaceCustomFlatApplication.id,
|
||||
},
|
||||
createRoleTargetInput,
|
||||
flatRoleTargetMaps,
|
||||
flatRoleMaps,
|
||||
workspaceId,
|
||||
flatApplication: flatApplication ?? workspaceCustomFlatApplication,
|
||||
});
|
||||
|
||||
allFlatRoleTargetsToCreate.push(flatRoleTargetToCreate);
|
||||
|
||||
+18
-3
@@ -1,7 +1,9 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
|
||||
import { findFlatRoleTargetFromForeignKey } from 'src/engine/metadata-modules/flat-role-target/utils/find-flat-role-target-from-foreign-key.util';
|
||||
import { type CreateRoleTargetInput } from 'src/engine/metadata-modules/role-target/types/create-role-target.input';
|
||||
@@ -10,10 +12,13 @@ export const fromCreateRoleTargetInputToFlatRoleTargetToCreate = ({
|
||||
createRoleTargetInput,
|
||||
workspaceId,
|
||||
flatRoleTargetMaps,
|
||||
flatRoleMaps,
|
||||
flatApplication,
|
||||
}: {
|
||||
createRoleTargetInput: CreateRoleTargetInput & { applicationId: string };
|
||||
createRoleTargetInput: CreateRoleTargetInput;
|
||||
workspaceId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatRoleTargetMaps'>): {
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<AllFlatEntityMaps, 'flatRoleTargetMaps' | 'flatRoleMaps'>): {
|
||||
flatRoleTargetToCreate: FlatRoleTarget;
|
||||
flatRoleTargetsToDelete: FlatRoleTarget[];
|
||||
} => {
|
||||
@@ -21,9 +26,18 @@ export const fromCreateRoleTargetInputToFlatRoleTargetToCreate = ({
|
||||
const { roleId, targetId, targetMetadataForeignKey, universalIdentifier } =
|
||||
createRoleTargetInput;
|
||||
|
||||
const { roleUniversalIdentifier } = resolveEntityRelationUniversalIdentifiers(
|
||||
{
|
||||
metadataName: 'roleTarget',
|
||||
foreignKeyValues: { roleId },
|
||||
flatEntityMaps: { flatRoleMaps },
|
||||
},
|
||||
);
|
||||
|
||||
const flatRoleTargetToCreate: FlatRoleTarget = {
|
||||
id: v4(),
|
||||
roleId,
|
||||
roleUniversalIdentifier,
|
||||
userWorkspaceId: null,
|
||||
agentId: null,
|
||||
apiKeyId: null,
|
||||
@@ -31,7 +45,8 @@ export const fromCreateRoleTargetInputToFlatRoleTargetToCreate = ({
|
||||
updatedAt: now.toISOString(),
|
||||
universalIdentifier: universalIdentifier ?? v4(),
|
||||
workspaceId,
|
||||
applicationId: createRoleTargetInput.applicationId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
[targetMetadataForeignKey]: targetId,
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/services/api-key-role.service';
|
||||
@@ -32,6 +33,10 @@ import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.g
|
||||
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { AiAgentRoleService } from 'src/engine/metadata-modules/ai/ai-agent-role/ai-agent-role.service';
|
||||
import {
|
||||
AgentException,
|
||||
AgentExceptionCode,
|
||||
} from 'src/engine/metadata-modules/ai/ai-agent/agent.exception';
|
||||
import { AgentDTO } from 'src/engine/metadata-modules/ai/ai-agent/dtos/agent.dto';
|
||||
import { fromFlatAgentWithRoleIdToAgentDto } from 'src/engine/metadata-modules/flat-agent/utils/from-agent-entity-to-agent-dto.util';
|
||||
import { FieldPermissionDTO } from 'src/engine/metadata-modules/object-permission/dtos/field-permission.dto';
|
||||
@@ -64,6 +69,7 @@ import { UpsertRowLevelPermissionPredicatesResultDTO } from 'src/engine/metadata
|
||||
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
|
||||
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||
|
||||
@@ -91,6 +97,7 @@ export class RoleResolver {
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly rowLevelPermissionPredicateService: RowLevelPermissionPredicateService,
|
||||
private readonly rowLevelPermissionPredicateGroupService: RowLevelPermissionPredicateGroupService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
) {}
|
||||
|
||||
@Query(() => [RoleDTO])
|
||||
@@ -307,16 +314,32 @@ export class RoleResolver {
|
||||
workspace.id,
|
||||
);
|
||||
|
||||
return agents.map((agentEntity) =>
|
||||
fromFlatAgentWithRoleIdToAgentDto({
|
||||
const { flatApplicationMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspace.id, [
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
return agents.map((agentEntity) => {
|
||||
const flatApplication =
|
||||
flatApplicationMaps.byId[agentEntity.applicationId];
|
||||
|
||||
if (!isDefined(flatApplication)) {
|
||||
throw new AgentException(
|
||||
`Application not found for agent ${agentEntity.id}`,
|
||||
AgentExceptionCode.AGENT_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return fromFlatAgentWithRoleIdToAgentDto({
|
||||
...agentEntity,
|
||||
createdAt: agentEntity.createdAt.toISOString(),
|
||||
updatedAt: agentEntity.updatedAt.toISOString(),
|
||||
deletedAt: agentEntity.deletedAt?.toISOString() ?? null,
|
||||
universalIdentifier: agentEntity.universalIdentifier,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
roleId: role.id,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField('apiKeys', () => [ApiKeyForRoleDTO])
|
||||
|
||||
@@ -111,7 +111,7 @@ export class RoleService {
|
||||
const flatRoleToCreate = fromCreateRoleInputToFlatRoleToCreate({
|
||||
createRoleInput: input,
|
||||
workspaceId,
|
||||
applicationId: ownerFlatApplication.id,
|
||||
flatApplication: ownerFlatApplication,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+1
-1
@@ -85,7 +85,7 @@ export class RowLevelPermissionPredicateGroupEntity
|
||||
{ onDelete: 'CASCADE' },
|
||||
)
|
||||
@JoinColumn({ name: 'parentRowLevelPermissionPredicateGroupId' })
|
||||
parentRowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity>;
|
||||
parentRowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity> | null;
|
||||
|
||||
@OneToMany(
|
||||
() => RowLevelPermissionPredicateGroupEntity,
|
||||
|
||||
+2
-2
@@ -87,7 +87,7 @@ export class RowLevelPermissionPredicateEntity
|
||||
onDelete: 'SET NULL',
|
||||
})
|
||||
@JoinColumn({ name: 'workspaceMemberFieldMetadataId' })
|
||||
workspaceMemberFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
workspaceMemberFieldMetadata: Relation<FieldMetadataEntity> | null;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
rowLevelPermissionPredicateGroupId: string | null;
|
||||
@@ -120,5 +120,5 @@ export class RowLevelPermissionPredicateEntity
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'rowLevelPermissionPredicateGroupId' })
|
||||
rowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity>;
|
||||
rowLevelPermissionPredicateGroup: Relation<RowLevelPermissionPredicateGroupEntity> | null;
|
||||
}
|
||||
|
||||
+114
-1
@@ -9,9 +9,11 @@ import { ApplicationService } from 'src/engine/core-modules/application/services
|
||||
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
|
||||
import { fromFlatRowLevelPermissionPredicateToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-to-dto.util';
|
||||
import {
|
||||
@@ -165,6 +167,9 @@ export class RowLevelPermissionPredicateService {
|
||||
const {
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -172,6 +177,9 @@ export class RowLevelPermissionPredicateService {
|
||||
flatMapsKeys: [
|
||||
'flatRowLevelPermissionPredicateMaps',
|
||||
'flatRowLevelPermissionPredicateGroupMaps',
|
||||
'flatRoleMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
@@ -205,7 +213,11 @@ export class RowLevelPermissionPredicateService {
|
||||
roleId,
|
||||
workspaceId,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const { predicatesToCreate, predicatesToUpdate, predicatesToDelete } =
|
||||
@@ -216,7 +228,13 @@ export class RowLevelPermissionPredicateService {
|
||||
objectMetadataId,
|
||||
workspaceId,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
await this.runUpsertMigration({
|
||||
@@ -277,14 +295,20 @@ export class RowLevelPermissionPredicateService {
|
||||
roleId,
|
||||
workspaceId,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatObjectMetadataMaps,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
existingGroups: FlatRowLevelPermissionPredicateGroup[];
|
||||
inputGroups: RowLevelPermissionPredicateGroupInput[];
|
||||
roleId: string;
|
||||
workspaceId: string;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatEntityMaps<FlatRowLevelPermissionPredicateGroup>;
|
||||
flatRoleMaps: AllFlatEntityMaps['flatRoleMaps'];
|
||||
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
groupsToCreate: FlatRowLevelPermissionPredicateGroup[];
|
||||
groupsToUpdate: FlatRowLevelPermissionPredicateGroup[];
|
||||
@@ -295,6 +319,13 @@ export class RowLevelPermissionPredicateService {
|
||||
|
||||
const inputGroupIds = new Set<string>();
|
||||
|
||||
const { roleUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
foreignKeyValues: { roleId },
|
||||
flatEntityMaps: { flatRoleMaps },
|
||||
});
|
||||
|
||||
for (const inputGroup of inputGroups) {
|
||||
const groupId = inputGroup.id ?? v4();
|
||||
const createdAt = new Date().toISOString();
|
||||
@@ -307,33 +338,69 @@ export class RowLevelPermissionPredicateService {
|
||||
});
|
||||
|
||||
if (isDefined(existingGroup) && existingGroup.deletedAt === null) {
|
||||
const { parentRowLevelPermissionPredicateGroupUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
foreignKeyValues: {
|
||||
parentRowLevelPermissionPredicateGroupId:
|
||||
inputGroup.parentRowLevelPermissionPredicateGroupId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
},
|
||||
});
|
||||
|
||||
groupsToUpdate.push({
|
||||
...existingGroup,
|
||||
logicalOperator: inputGroup.logicalOperator,
|
||||
parentRowLevelPermissionPredicateGroupId:
|
||||
inputGroup.parentRowLevelPermissionPredicateGroupId ?? null,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
inputGroup.positionInRowLevelPermissionPredicateGroup ?? null,
|
||||
updatedAt: createdAt,
|
||||
});
|
||||
} else {
|
||||
const {
|
||||
objectMetadataUniversalIdentifier,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicateGroup',
|
||||
foreignKeyValues: {
|
||||
objectMetadataId: inputGroup.objectMetadataId,
|
||||
parentRowLevelPermissionPredicateGroupId:
|
||||
inputGroup.parentRowLevelPermissionPredicateGroupId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
},
|
||||
});
|
||||
|
||||
groupsToCreate.push({
|
||||
id: groupId,
|
||||
workspaceId,
|
||||
roleId,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataId: inputGroup.objectMetadataId,
|
||||
objectMetadataUniversalIdentifier,
|
||||
logicalOperator: inputGroup.logicalOperator,
|
||||
parentRowLevelPermissionPredicateGroupId:
|
||||
inputGroup.parentRowLevelPermissionPredicateGroupId ?? null,
|
||||
parentRowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
inputGroup.positionInRowLevelPermissionPredicateGroup ?? null,
|
||||
childRowLevelPermissionPredicateGroupIds: [],
|
||||
childRowLevelPermissionPredicateGroupUniversalIdentifiers: [],
|
||||
rowLevelPermissionPredicateIds: [],
|
||||
rowLevelPermissionPredicateUniversalIdentifiers: [],
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: groupId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -360,7 +427,12 @@ export class RowLevelPermissionPredicateService {
|
||||
objectMetadataId,
|
||||
workspaceId,
|
||||
flatRowLevelPermissionPredicateMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
flatRoleMaps,
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
workspaceCustomApplicationId,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
existingPredicates: FlatRowLevelPermissionPredicate[];
|
||||
inputPredicates: RowLevelPermissionPredicateInput[];
|
||||
@@ -368,7 +440,12 @@ export class RowLevelPermissionPredicateService {
|
||||
objectMetadataId: string;
|
||||
workspaceId: string;
|
||||
flatRowLevelPermissionPredicateMaps: FlatEntityMaps<FlatRowLevelPermissionPredicate>;
|
||||
flatRowLevelPermissionPredicateGroupMaps: FlatEntityMaps<FlatRowLevelPermissionPredicateGroup>;
|
||||
flatRoleMaps: AllFlatEntityMaps['flatRoleMaps'];
|
||||
flatObjectMetadataMaps: AllFlatEntityMaps['flatObjectMetadataMaps'];
|
||||
flatFieldMetadataMaps: AllFlatEntityMaps['flatFieldMetadataMaps'];
|
||||
workspaceCustomApplicationId: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
}): {
|
||||
predicatesToCreate: FlatRowLevelPermissionPredicate[];
|
||||
predicatesToUpdate: FlatRowLevelPermissionPredicate[];
|
||||
@@ -379,6 +456,13 @@ export class RowLevelPermissionPredicateService {
|
||||
|
||||
const inputPredicateIds = new Set<string>();
|
||||
|
||||
const { roleUniversalIdentifier, objectMetadataUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
foreignKeyValues: { roleId, objectMetadataId },
|
||||
flatEntityMaps: { flatRoleMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
for (const inputPredicate of inputPredicates) {
|
||||
const predicateId = inputPredicate.id ?? v4();
|
||||
const createdAt = new Date().toISOString();
|
||||
@@ -390,6 +474,25 @@ export class RowLevelPermissionPredicateService {
|
||||
flatEntityMaps: flatRowLevelPermissionPredicateMaps,
|
||||
});
|
||||
|
||||
const {
|
||||
fieldMetadataUniversalIdentifier,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'rowLevelPermissionPredicate',
|
||||
foreignKeyValues: {
|
||||
fieldMetadataId: inputPredicate.fieldMetadataId,
|
||||
rowLevelPermissionPredicateGroupId:
|
||||
inputPredicate.rowLevelPermissionPredicateGroupId,
|
||||
workspaceMemberFieldMetadataId:
|
||||
inputPredicate.workspaceMemberFieldMetadataId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatFieldMetadataMaps,
|
||||
flatRowLevelPermissionPredicateGroupMaps,
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
isDefined(existingPredicate) &&
|
||||
existingPredicate.deletedAt === null
|
||||
@@ -397,15 +500,18 @@ export class RowLevelPermissionPredicateService {
|
||||
predicatesToUpdate.push({
|
||||
...existingPredicate,
|
||||
fieldMetadataId: inputPredicate.fieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
operand: inputPredicate.operand,
|
||||
value: inputPredicate.value ?? null,
|
||||
subFieldName: inputPredicate.subFieldName ?? null,
|
||||
workspaceMemberFieldMetadataId:
|
||||
inputPredicate.workspaceMemberFieldMetadataId ?? null,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
workspaceMemberSubFieldName:
|
||||
inputPredicate.workspaceMemberSubFieldName ?? null,
|
||||
rowLevelPermissionPredicateGroupId:
|
||||
inputPredicate.rowLevelPermissionPredicateGroupId ?? null,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
inputPredicate.positionInRowLevelPermissionPredicateGroup ?? null,
|
||||
updatedAt: createdAt,
|
||||
@@ -415,17 +521,22 @@ export class RowLevelPermissionPredicateService {
|
||||
id: predicateId,
|
||||
workspaceId,
|
||||
roleId,
|
||||
roleUniversalIdentifier,
|
||||
objectMetadataId,
|
||||
objectMetadataUniversalIdentifier,
|
||||
fieldMetadataId: inputPredicate.fieldMetadataId,
|
||||
fieldMetadataUniversalIdentifier,
|
||||
operand: inputPredicate.operand,
|
||||
value: inputPredicate.value ?? null,
|
||||
subFieldName: inputPredicate.subFieldName ?? null,
|
||||
workspaceMemberFieldMetadataId:
|
||||
inputPredicate.workspaceMemberFieldMetadataId ?? null,
|
||||
workspaceMemberFieldMetadataUniversalIdentifier,
|
||||
workspaceMemberSubFieldName:
|
||||
inputPredicate.workspaceMemberSubFieldName ?? null,
|
||||
rowLevelPermissionPredicateGroupId:
|
||||
inputPredicate.rowLevelPermissionPredicateGroupId ?? null,
|
||||
rowLevelPermissionPredicateGroupUniversalIdentifier,
|
||||
positionInRowLevelPermissionPredicateGroup:
|
||||
inputPredicate.positionInRowLevelPermissionPredicateGroup ?? null,
|
||||
createdAt,
|
||||
@@ -433,6 +544,8 @@ export class RowLevelPermissionPredicateService {
|
||||
deletedAt: null,
|
||||
universalIdentifier: predicateId,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ export class SkillService {
|
||||
const flatSkillToCreate = fromCreateSkillInputToFlatSkillToCreate({
|
||||
createSkillInput: input,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+11
-1
@@ -76,12 +76,22 @@ export class ViewFieldV2Service {
|
||||
},
|
||||
);
|
||||
|
||||
const { flatFieldMetadataMaps, flatViewMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatFieldMetadataMaps', 'flatViewMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFieldsToCreate = createViewFieldInputs.map(
|
||||
(createViewFieldInput) =>
|
||||
fromCreateViewFieldInputToFlatViewFieldToCreate({
|
||||
createViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export class ViewFilterGroupEntity extends SyncableEntity {
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'parentViewFilterGroupId' })
|
||||
parentViewFilterGroup: Relation<ViewFilterGroupEntity>;
|
||||
parentViewFilterGroup: Relation<ViewFilterGroupEntity> | null;
|
||||
|
||||
@OneToMany(
|
||||
() => ViewFilterGroupEntity,
|
||||
|
||||
+14
-1
@@ -45,11 +45,24 @@ export class ViewFilterGroupService {
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps,
|
||||
} =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewMaps', 'flatViewFilterGroupMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFilterGroupToCreate =
|
||||
fromCreateViewFilterGroupInputToFlatViewFilterGroupToCreate({
|
||||
createViewFilterGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps,
|
||||
});
|
||||
|
||||
const buildAndRunResult =
|
||||
|
||||
+1
-1
@@ -85,5 +85,5 @@ export class ViewFilterEntity
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'viewFilterGroupId' })
|
||||
viewFilterGroup: Relation<ViewFilterGroupEntity>;
|
||||
viewFilterGroup: Relation<ViewFilterGroupEntity> | null;
|
||||
}
|
||||
|
||||
+32
-8
@@ -45,11 +45,26 @@ export class ViewFilterService {
|
||||
},
|
||||
);
|
||||
|
||||
const { flatFieldMetadataMaps, flatViewMaps, flatViewFilterGroupMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatFieldMetadataMaps',
|
||||
'flatViewMaps',
|
||||
'flatViewFilterGroupMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const flatViewFilterToCreate =
|
||||
fromCreateViewFilterInputToFlatViewFilterToCreate({
|
||||
createViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatFieldMetadataMaps,
|
||||
flatViewMaps,
|
||||
flatViewFilterGroupMaps,
|
||||
});
|
||||
|
||||
const buildAndRunResult =
|
||||
@@ -106,18 +121,27 @@ export class ViewFilterService {
|
||||
},
|
||||
);
|
||||
|
||||
const { flatViewFilterMaps: existingFlatViewFilterMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatViewFilterMaps'],
|
||||
},
|
||||
);
|
||||
const {
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps,
|
||||
} = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatViewFilterMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatViewFilterGroupMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const optimisticallyUpdatedFlatViewFilter =
|
||||
fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow({
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
updateViewFilterInput,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatViewFilterGroupMaps: existingFlatViewFilterGroupMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+2
-1
@@ -102,7 +102,8 @@ export class ViewGroupService {
|
||||
return fromCreateViewGroupInputToFlatViewGroupToCreate({
|
||||
createViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatViewMaps,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -118,7 +118,7 @@ export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'kanbanAggregateOperationFieldMetadataId' })
|
||||
kanbanAggregateOperationFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
kanbanAggregateOperationFieldMetadata: Relation<FieldMetadataEntity> | null;
|
||||
|
||||
@Column({
|
||||
type: 'enum',
|
||||
@@ -140,7 +140,7 @@ export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'calendarFieldMetadataId' })
|
||||
calendarFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
calendarFieldMetadata: Relation<FieldMetadataEntity> | null;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
mainGroupByFieldMetadataId: string | null;
|
||||
@@ -154,7 +154,7 @@ export class ViewEntity extends SyncableEntity implements Required<ViewEntity> {
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: 'mainGroupByFieldMetadataId' })
|
||||
mainGroupByFieldMetadata: Relation<FieldMetadataEntity>;
|
||||
mainGroupByFieldMetadata: Relation<FieldMetadataEntity> | null;
|
||||
|
||||
@Column({ nullable: false, default: false, type: 'boolean' })
|
||||
shouldHideEmptyGroups: boolean;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user