Skip to content

Commit

Permalink
Merge pull request #8692 from ever-co/enhancement/tag-type
Browse files Browse the repository at this point in the history
[Feat] Tag Type
  • Loading branch information
rahul-rocket authored Jan 6, 2025
2 parents 5f3be79 + 2883b91 commit d159f87
Show file tree
Hide file tree
Showing 15 changed files with 532 additions and 5 deletions.
12 changes: 10 additions & 2 deletions packages/contracts/src/lib/tag.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IRelationalOrganizationTeam } from './organization-team.model';
import { IBasePerTenantAndOrganizationEntityModel } from './base-entity.model';
import { IBasePerTenantAndOrganizationEntityModel, ID } from './base-entity.model';

export interface ITaggable {
tags?: ITag[];
Expand All @@ -12,6 +12,8 @@ export interface ITag extends IBasePerTenantAndOrganizationEntityModel, IRelatio
icon?: string;
description?: string;
isSystem?: boolean;
tagTypeId?: ID;
tagType?: ITagType;
}

export interface ITagFindInput extends IBasePerTenantAndOrganizationEntityModel, Pick<ITag, 'organizationTeamId'> {
Expand All @@ -20,12 +22,18 @@ export interface ITagFindInput extends IBasePerTenantAndOrganizationEntityModel,
textColor?: string;
description?: string;
isSystem?: boolean;
tagTypeId?: ID;
}

export interface ITagCreateInput extends ITag {}

export interface ITagType {
type: string;
tags?: ITag[];
}

export interface ITagUpdateInput extends Partial<ITagCreateInput> {
id?: string;
id?: ID;
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,4 @@ export {
ExpenseCategoryFirstOrCreateCommand
} from './lib/expense-categories';
export { TagModule, TagService, Taggable, AutomationLabelSyncCommand, RelationalTagDTO } from './lib/tags';
export { TagTypeModule, TagTypeService } from './lib/tag-type';
2 changes: 2 additions & 0 deletions packages/core/src/lib/core/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ import {
SocialAccount,
Subscription,
Tag,
TagType,
Task,
TaskEstimation,
TaskLinkedIssue,
Expand Down Expand Up @@ -286,6 +287,7 @@ export const coreEntities = [
SocialAccount,
Subscription,
Tag,
TagType,
Task,
TaskEstimation,
TaskLinkedIssue,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/lib/core/entities/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export * from '../../role/role.entity';
export * from '../../skills/skill.entity';
export * from '../../subscription/subscription.entity';
export * from '../../tags/tag.entity';
export * from '../../tag-type/tag-type.entity';
export * from '../../tasks/daily-plan/daily-plan.entity';
export * from '../../tasks/estimation/task-estimation.entity';
export * from '../../tasks/issue-type/issue-type.entity';
Expand Down

Large diffs are not rendered by default.

35 changes: 35 additions & 0 deletions packages/core/src/lib/tag-type/default-tag-types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ITagType } from '@gauzy/contracts';

/**
* Represents the default tag types used throughout the application.
* Each tag type corresponds to a specific category or grouping.
*
* @constant DEFAULT_TAG_TYPES
* @type {ITagType[]}
*
* @description
* This constant defines an array of objects that represent default tag types.
* Each object contains a `type` property, which is a string describing the tag type.
* These tags can be used to classify various entities such as equipment, income,
* invoices, and more.
*
* Example Usage:
* ```typescript
* console.log(DEFAULT_TAG_TYPES);
* ```
*
*/
export const DEFAULT_TAG_TYPES: ITagType[] = [
{ type: 'Equipment' },
{ type: 'Income' },
{ type: 'Invoice' },
{ type: 'Payment' },
{ type: 'Task' },
{ type: 'Proposals' },
{ type: 'Organization Contact' },
{ type: 'Employee Level' },
{ type: 'Organization Department' },
{ type: 'Warehouse' },
{ type: 'Employee' },
{ type: 'User' }
];
2 changes: 2 additions & 0 deletions packages/core/src/lib/tag-type/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './tag-type.module';
export * from './tag-type.service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { MikroOrmBaseEntityRepository } from '../../core/repository/mikro-orm-base-entity.repository';
import { TagType } from '../tag-type.entity';

export class MikroOrmTagTypeRepository extends MikroOrmBaseEntityRepository<TagType> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TagType } from '../tag-type.entity';

@Injectable()
export class TypeOrmTagTypeRepository extends Repository<TagType> {
constructor(@InjectRepository(TagType) readonly repository: Repository<TagType>) {
super(repository.target, repository.manager, repository.queryRunner);
}
}
61 changes: 61 additions & 0 deletions packages/core/src/lib/tag-type/tag-type.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ApiTags, ApiResponse, ApiOperation } from '@nestjs/swagger';
import { Controller, HttpStatus, Get, Query, UseGuards, ValidationPipe } from '@nestjs/common';
import { FindOptionsWhere } from 'typeorm';
import { IPagination } from '@gauzy/contracts';
import { CrudController, PaginationParams } from '../core/crud';
import { PermissionGuard, TenantPermissionGuard } from '../shared/guards';
import { TagType } from './tag-type.entity';
import { TagTypeService } from './tag-type.service';

@ApiTags('TagTypes')
@UseGuards(TenantPermissionGuard, PermissionGuard)
@Controller('/tag-types')
export class TagTypeController extends CrudController<TagType> {
constructor(private readonly tagTypesService: TagTypeService) {
super(tagTypesService);
}

/**
* GET tag types count
*
* @param data
* @returns
*/
@ApiOperation({ summary: 'Find Tag Types Count ' })
@ApiResponse({
status: HttpStatus.OK,
description: 'Count Tag Types',
type: TagType
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'Record not found'
})
@Get('count')
async getCount(@Query() options: FindOptionsWhere<TagType>): Promise<number> {
return await this.tagTypesService.countBy(options);
}

/**
* GET all tag types
*
* @param options
* @returns
*/
@ApiOperation({
summary: 'Find all tag types.'
})
@ApiResponse({
status: HttpStatus.OK,
description: 'Found tag types.',
type: TagType
})
@ApiResponse({
status: HttpStatus.NOT_FOUND,
description: 'Record not found'
})
@Get()
async findAll(@Query(new ValidationPipe()) options: PaginationParams<TagType>): Promise<IPagination<TagType>> {
return await this.tagTypesService.findAll(options);
}
}
27 changes: 27 additions & 0 deletions packages/core/src/lib/tag-type/tag-type.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { ApiProperty } from '@nestjs/swagger';
import { ITag, ITagType } from '@gauzy/contracts';
import { IsNotEmpty, IsString } from 'class-validator';
import { Tag, TenantOrganizationBaseEntity } from '../core/entities/internal';
import { MultiORMColumn, MultiORMEntity, MultiORMOneToMany } from './../core/decorators/entity';
import { MikroOrmTagTypeRepository } from './repository/mikro-orm-tag-type.repository';

@MultiORMEntity('tag_type', { mikroOrmRepository: () => MikroOrmTagTypeRepository })
export class TagType extends TenantOrganizationBaseEntity implements ITagType {
@ApiProperty({ type: () => String })
@IsNotEmpty()
@IsString()
@MultiORMColumn()
type: string;

/*
|--------------------------------------------------------------------------
| @OneToMany
|--------------------------------------------------------------------------
*/
/**
* tags
*/
@ApiProperty({ type: () => Tag, isArray: true })
@MultiORMOneToMany(() => Tag, (tag) => tag.tagType)
tags?: ITag[];
}
22 changes: 22 additions & 0 deletions packages/core/src/lib/tag-type/tag-type.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { RolePermissionModule } from '../role-permission/role-permission.module';
import { TagType } from './tag-type.entity';
import { TagTypeService } from './tag-type.service';
import { TagTypeController } from './tag-type.controller';
import { TypeOrmTagTypeRepository } from './repository/type-orm-tag-type.repository';

@Module({
imports: [
CqrsModule,
TypeOrmModule.forFeature([TagType]),
MikroOrmModule.forFeature([TagType]),
RolePermissionModule
],
controllers: [TagTypeController],
providers: [TagTypeService, TypeOrmTagTypeRepository],
exports: [TagTypeService]
})
export class TagTypeModule {}
80 changes: 80 additions & 0 deletions packages/core/src/lib/tag-type/tag-type.seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { DataSource } from 'typeorm';
import { IOrganization, ITagType, ITenant } from '@gauzy/contracts';
import { TagType } from './tag-type.entity';
import { DEFAULT_TAG_TYPES } from './default-tag-types';

/**
* Creates and inserts tag types into the database for a specified tenant and organizations.
*
* @function createTagTypes
* @async
* @param {DataSource} dataSource - The TypeORM `DataSource` instance used for database operations.
* @param {ITenant} tenant - The tenant for which the tag types are being created.
* @param {IOrganization[]} organizations - An array of organizations associated with the tag types.
* @returns {Promise<ITagType[]>} - A promise that resolves to the array of created and inserted `ITagType` entities.
*
* @description
* This function iterates over the predefined `DEFAULT_TAG_TYPES` and creates `TagType` entities
* for each organization provided. It assigns the `type` from `DEFAULT_TAG_TYPES`, associates the
* organization and tenant, and saves the resulting entities into the database.
*
* @example
* const organizations = [
* { id: 'org1', name: 'Org 1' },
* { id: 'org2', name: 'Org 2' },
* ];
*
* const tenant = { id: 'tenant1', name: 'Tenant 1' };
*
* const createdTags = await createTagTypes(dataSource, tenant, organizations);
* console.log(createdTags);
*
* @throws Will throw an error if the database save operation fails.
*/
export const createTagTypes = async (
dataSource: DataSource,
tenant: ITenant,
organizations: IOrganization[]
): Promise<ITagType[]> => {
// Array to store the new tag type entities
const tagTypes: TagType[] = [];

// Iterate over the predefined default tag types
DEFAULT_TAG_TYPES.forEach(({ type }) => {
// Create a tag type for each organization
for (const organization of organizations) {
const entity = new TagType();
entity.type = type; // Assign type from default list
entity.organization = organization; // Associate organization
entity.tenant = tenant; // Associate tenant
tagTypes.push(entity);
}
});

// Save the created tag types into the database
return insertTagTypes(dataSource, tagTypes);
};

/**
* Inserts an array of tag types into the database.
*
* @function insertTagTypes
* @async
* @param {DataSource} dataSource - The TypeORM `DataSource` instance used to interact with the database.
* @param {TagType[]} tagTypes - An array of `TagType` entities to be saved into the database.
* @returns {Promise<TagType[]>} - A promise that resolves with the array of saved `TagType` entities.
*
* @example
* // Example usage:
* const tagTypes = [
* { type: 'Equipment' },
* { type: 'Income' },
* ];
*
* await insertTagTypes(dataSource, tagTypes);
*
* @throws Will throw an error if the database save operation fails.
*/
const insertTagTypes = async (dataSource: DataSource, tagTypes: TagType[]): Promise<TagType[]> => {
return await dataSource.manager.save(tagTypes);
};
15 changes: 15 additions & 0 deletions packages/core/src/lib/tag-type/tag-type.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Injectable } from '@nestjs/common';
import { TenantAwareCrudService } from '../core/crud';
import { TagType } from './tag-type.entity';
import { MikroOrmTagTypeRepository } from './repository/mikro-orm-tag-type.repository';
import { TypeOrmTagTypeRepository } from './repository/type-orm-tag-type.repository';

@Injectable()
export class TagTypeService extends TenantAwareCrudService<TagType> {
constructor(
typeOrmTagTypeRepository: TypeOrmTagTypeRepository,
mikroOrmTagTypeRepository: MikroOrmTagTypeRepository
) {
super(typeOrmTagTypeRepository, mikroOrmTagTypeRepository);
}
}
Loading

0 comments on commit d159f87

Please sign in to comment.