feat: models default views

This commit is contained in:
Ahmed Bouhuolia
2025-06-17 20:53:13 +02:00
parent f624cf7ae6
commit 437bcb8854
39 changed files with 286 additions and 275 deletions

View File

@@ -0,0 +1,12 @@
import { Transformer } from '../Transformer/Transformer';
import { View } from './models/View.model';
export class GetResourceViewTransformer extends Transformer {
public includeAttributes = (): string[] => {
return ['name'];
};
name(view: View) {
return this.context.i18n.t(view.name);
}
}

View File

@@ -1,10 +1,17 @@
import { Injectable } from '@nestjs/common';
import { View } from './models/View.model';
import { ResourceService } from '../Resource/ResourceService';
import { I18nService } from 'nestjs-i18n';
import { TransformerInjectable } from '../Transformer/TransformerInjectable.service';
import { GetResourceViewTransformer } from './GetResourceView.transformer';
@Injectable()
export class GetResourceViewsService {
constructor(private readonly resourceService: ResourceService) {}
constructor(
private readonly resourceService: ResourceService,
private readonly transformerInjectable: TransformerInjectable,
) {}
/**
* Listing resource views.
* @param {string} resourceModel -
@@ -16,6 +23,9 @@ export class GetResourceViewsService {
// Default views.
const defaultViews = resourceModel().getDefaultViews();
return defaultViews;
return this.transformerInjectable.transform(
defaultViews,
new GetResourceViewTransformer(),
);
}
}

View File

@@ -1,20 +1,38 @@
import { Controller, Get, Param } from '@nestjs/common';
import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import {
ApiExtraModels,
ApiOperation,
ApiParam,
ApiResponse,
ApiTags,
getSchemaPath,
} from '@nestjs/swagger';
import { GetResourceViewsService } from './GetResourceViews.service';
import { ViewResponseDto } from './dtos/ViewResponse.dto';
@Controller('views')
@ApiTags('Views')
@ApiExtraModels(ViewResponseDto)
export class ViewsController {
constructor(
private readonly getResourceViewsService: GetResourceViewsService,
) {}
@Get('/resource/:resourceModel')
@ApiResponse({ status: 200, description: 'Specific resource views' })
@ApiParam({
name: 'resourceModel',
description: 'The resource model to get views for',
type: String,
})
@ApiResponse({
status: 200,
description: 'Specific resource views',
schema: { $ref: getSchemaPath(ViewResponseDto) },
})
@ApiOperation({ summary: 'Get the given resource views' })
async getResourceViews(@Param('resourceModel') resourceModel: string) {
const views =
await this.getResourceViewsService.getResourceViews(resourceModel);
return { views };
return views;
}
}

View File

@@ -0,0 +1,14 @@
export function InjectModelDefaultViews(defaultViews: any[]) {
return function (target: any) {
// Define the defaultViews static property on the class
Object.defineProperty(target, 'defaultViews', {
get: function () {
return defaultViews;
},
enumerable: true,
configurable: true,
});
return target;
};
}

View File

@@ -0,0 +1,30 @@
import { ApiProperty } from '@nestjs/swagger';
export class RoleResponseDto {
@ApiProperty({ description: 'The unique identifier of the role' })
id: number;
@ApiProperty({ description: 'The index of the role' })
index: number;
@ApiProperty({ description: 'The field key associated with the role' })
fieldKey: string;
@ApiProperty({
description:
'The comparator used for the role (equals, not_equal, contains, not_contain)',
})
comparator: string;
@ApiProperty({ description: 'The value to compare against' })
value: string;
@ApiProperty({ description: 'The ID of the view this role belongs to' })
viewId: number;
@ApiProperty({ description: 'The creation timestamp' })
createdAt: Date;
@ApiProperty({ description: 'The last update timestamp' })
updatedAt: Date;
}

View File

@@ -0,0 +1,44 @@
import { ApiProperty } from '@nestjs/swagger';
import { ViewColumn } from '../models/ViewColumn.model';
import { RoleResponseDto } from './RoleResponse.dto';
export class ViewResponseDto {
@ApiProperty({ description: 'The unique identifier of the view' })
id: number;
@ApiProperty({ description: 'The name of the view' })
name: string;
@ApiProperty({ description: 'The slug of the view' })
slug: string;
@ApiProperty({ description: 'Whether the view is predefined' })
predefined: boolean;
@ApiProperty({ description: 'The resource model associated with the view' })
resourceModel: string;
@ApiProperty({ description: 'Whether the view is marked as favourite' })
favourite: boolean;
@ApiProperty({ description: 'The roles logic expression for the view' })
rolesLogicExpression: string;
@ApiProperty({
type: [RoleResponseDto],
description: 'The roles associated with the view',
})
roles: RoleResponseDto[];
@ApiProperty({
type: [ViewColumn],
description: 'The columns associated with the view',
})
columns: ViewColumn[];
@ApiProperty({ description: 'The creation timestamp' })
createdAt: Date;
@ApiProperty({ description: 'The last update timestamp' })
updatedAt: Date;
}

View File

@@ -1,7 +1,14 @@
import { Model } from 'objection';
import { BaseModel } from '@/models/Model';
import { ViewRole } from './ViewRole.model';
export class View extends BaseModel {
name: string;
slug: string;
rolesLogicExpression: number;
roles!: Array<ViewRole>;
/**
* Table name.
*/

View File

@@ -2,6 +2,10 @@ import { BaseModel } from '@/models/Model';
import { Model } from 'objection';
export class ViewRole extends BaseModel {
index: number;
fieldKey: string;
comparator: string;
value: string;
/**
* Virtual attributes.
@@ -11,9 +15,7 @@ export class ViewRole extends BaseModel {
}
static get comparators() {
return [
'equals', 'not_equal', 'contains', 'not_contain',
];
return ['equals', 'not_equal', 'contains', 'not_contain'];
}
/**