Move view in metadata-modules/ and create atomic folder + module for each view entity (#14990)

# Introduction
Preparing view-filter and view-group introduction in v2 core engine
Moving view from `core-modules` to `metadata-modules`

## What happened

### Created dedicated modules for each view entity:
- ViewFieldModule
- ViewFilterModule
- ViewFilterGroupModule
- ViewGroupModule
- ViewSortModule

### Each module is now completely independent with its own:
- Controller
- Resolver
- Service
- Entity

### Created dedicated abstraction metadata module folder for:
- flat-view-field
- flat-view

### Dependencies 
- Eleminated circular dep on ViewModule to all others ones
- Granular import not importing the whole viewModule anymore everywhere


close https://github.com/twentyhq/core-team-issues/issues/1703
This commit is contained in:
Paul Rastoin
2025-10-09 15:18:15 +02:00
committed by GitHub
parent c9a1a110e1
commit 59fbe35a8c
198 changed files with 877 additions and 765 deletions
@@ -0,0 +1,115 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
Query,
UseFilters,
UseGuards,
} from '@nestjs/common';
import { isDefined } from 'twenty-shared/utils';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/create-view-field.input';
import { UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import {
generateViewFieldExceptionMessage,
generateViewFieldUserFriendlyExceptionMessage,
ViewFieldException,
ViewFieldExceptionCode,
ViewFieldExceptionMessageKey,
} from 'src/engine/metadata-modules/view-field/exceptions/view-field.exception';
import { ViewFieldRestApiExceptionFilter } from 'src/engine/metadata-modules/view-field/filters/view-field-rest-api-exception.filter';
import { ViewFieldService } from 'src/engine/metadata-modules/view-field/services/view-field.service';
@Controller('rest/metadata/viewFields')
@UseGuards(WorkspaceAuthGuard)
@UseFilters(ViewFieldRestApiExceptionFilter)
export class ViewFieldController {
constructor(private readonly viewFieldService: ViewFieldService) {}
@Get()
async findMany(
@AuthWorkspace() workspace: Workspace,
@Query('viewId') viewId?: string,
): Promise<ViewFieldEntity[]> {
if (viewId) {
return this.viewFieldService.findByViewId(workspace.id, viewId);
}
return this.viewFieldService.findByWorkspaceId(workspace.id);
}
@Get(':id')
async findOne(
@Param('id') id: string,
@AuthWorkspace() workspace: Workspace,
): Promise<ViewFieldEntity> {
const viewField = await this.viewFieldService.findById(id, workspace.id);
if (!isDefined(viewField)) {
throw new ViewFieldException(
generateViewFieldExceptionMessage(
ViewFieldExceptionMessageKey.VIEW_FIELD_NOT_FOUND,
id,
),
ViewFieldExceptionCode.VIEW_FIELD_NOT_FOUND,
{
userFriendlyMessage: generateViewFieldUserFriendlyExceptionMessage(
ViewFieldExceptionMessageKey.VIEW_FIELD_NOT_FOUND,
),
},
);
}
return viewField;
}
@Patch(':id')
async update(
@Param('id') id: string,
@Body() input: UpdateViewFieldInput['update'],
@AuthWorkspace() workspace: Workspace,
): Promise<ViewFieldEntity> {
const updatedViewField = await this.viewFieldService.update(
id,
workspace.id,
input,
);
return updatedViewField;
}
@Post()
async create(
@Body() input: CreateViewFieldInput,
@AuthWorkspace() workspace: Workspace,
): Promise<ViewFieldEntity> {
return this.viewFieldService.create({
...input,
workspaceId: workspace.id,
});
}
@Delete(':id')
async delete(
@Param('id') id: string,
@AuthWorkspace() workspace: Workspace,
): Promise<{ success: boolean }> {
const deletedViewField = await this.viewFieldService.delete(
id,
workspace.id,
);
return { success: isDefined(deletedViewField) };
}
// TODO: the destroy endpoint will be implemented when we settle on a strategy
}