fix: when field metadata SELECT type is edited update view groups (#8344)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Jérémy M
2024-11-06 11:41:44 +01:00
committed by GitHub
parent e36363fe15
commit ac7d740135
11 changed files with 304 additions and 28 deletions

View File

@ -0,0 +1,151 @@
import { Injectable } from '@nestjs/common';
import { In } from 'typeorm';
import {
FieldMetadataComplexOption,
FieldMetadataDefaultOption,
} from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { isSelectFieldMetadataType } from 'src/engine/metadata-modules/field-metadata/utils/is-select-field-metadata-type.util';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-group.workspace-entity';
import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity';
type Differences<T> = {
created: T[];
updated: { old: T; new: T }[];
deleted: T[];
};
@Injectable()
export class FieldMetadataRelatedRecordsService {
constructor(
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {}
public async updateRelatedViewGroups(
oldFieldMetadata: FieldMetadataEntity,
newFieldMetadata: FieldMetadataEntity,
) {
if (
!isSelectFieldMetadataType(newFieldMetadata.type) ||
!isSelectFieldMetadataType(oldFieldMetadata.type)
) {
return;
}
const views = await this.getFieldMetadataViews(newFieldMetadata);
const { created, updated, deleted } = this.getOptionsDifferences(
oldFieldMetadata.options,
newFieldMetadata.options,
);
const viewGroupRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewGroupWorkspaceEntity>(
newFieldMetadata.workspaceId,
'viewGroup',
);
for (const view of views) {
const maxPosition = view.viewGroups.reduce(
(max, viewGroup) => Math.max(max, viewGroup.position),
0,
);
const viewGroupsToCreate = created.map((option, index) =>
viewGroupRepository.create({
fieldMetadataId: newFieldMetadata.id,
fieldValue: option.value,
position: maxPosition + index,
isVisible: true,
viewId: view.id,
}),
);
await viewGroupRepository.insert(viewGroupsToCreate);
for (const { old: oldOption, new: newOption } of updated) {
const viewGroup = view.viewGroups.find(
(viewGroup) => viewGroup.fieldValue === oldOption.value,
);
if (!viewGroup) {
throw new Error(`View group not found for option ${oldOption.value}`);
}
await viewGroupRepository.update(
{
id: viewGroup.id,
},
{
fieldValue: newOption.value,
},
);
}
const valuesToDelete = deleted.map((option) => option.value);
await viewGroupRepository.delete({
fieldMetadataId: newFieldMetadata.id,
fieldValue: In(valuesToDelete),
});
}
}
private getOptionsDifferences(
oldOptions: (FieldMetadataDefaultOption | FieldMetadataComplexOption)[],
newOptions: (FieldMetadataDefaultOption | FieldMetadataComplexOption)[],
) {
const differences: Differences<
FieldMetadataDefaultOption | FieldMetadataComplexOption
> = {
created: [],
updated: [],
deleted: [],
};
const oldOptionsMap = new Map(
oldOptions.map((option) => [option.id, option]),
);
const newOptionsMap = new Map(
newOptions.map((option) => [option.id, option]),
);
for (const newOption of newOptions) {
const oldOption = oldOptionsMap.get(newOption.id);
if (!oldOption) {
differences.created.push(newOption);
} else if (oldOption.value !== newOption.value) {
differences.updated.push({ old: oldOption, new: newOption });
}
}
for (const oldOption of oldOptions) {
if (!newOptionsMap.has(oldOption.id)) {
differences.deleted.push(oldOption);
}
}
return differences;
}
private async getFieldMetadataViews(
fieldMetadata: FieldMetadataEntity,
): Promise<ViewWorkspaceEntity[]> {
const viewRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<ViewWorkspaceEntity>(
fieldMetadata.workspaceId,
'view',
);
return await viewRepository.find({
where: {
kanbanFieldMetadataId: fieldMetadata.id,
},
relations: ['viewGroups'],
});
}
}