Compare commits
12 Commits
8533682303
...
4cb20f6c0d
| Author | SHA1 | Date | |
|---|---|---|---|
| 4cb20f6c0d | |||
| 95c947a587 | |||
| 8348692481 | |||
| 677fc5b384 | |||
| 8481a0e86f | |||
| b32d613a1b | |||
| b0668c7b2c | |||
| ff08da1330 | |||
| 29d647556c | |||
| a22d6ceb81 | |||
| eb6fbc3ce5 | |||
| 9565eda0fd |
@@ -0,0 +1,20 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class TMaddingSomeNewPermissionsToTheEnum1783428145772 implements MigrationInterface {
|
||||
name = 'TMaddingSomeNewPermissionsToTheEnum1783428145772'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum" RENAME TO "permission_name_enum_old"`);
|
||||
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail', 'reseller', 'workspace', 'view_all_workspaces', 'project', 'view_all_projects', 'task', 'task_phase', 'remark')`);
|
||||
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum" USING "name"::"text"::"public"."permission_name_enum"`);
|
||||
await queryRunner.query(`DROP TYPE "public"."permission_name_enum_old"`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TYPE "public"."permission_name_enum_old" AS ENUM('services', 'customers', 'agents', 'developers', 'invoices', 'transactions', 'discounts', 'admins', 'tickets', 'criticisms', 'contacts_us', 'advertisements', 'announcements', 'blogs', 'learnings', 'logs', 'settings', 'bank_accounts', 'payments', 'manage_sso_clients', 'support_plan', 'dmenu', 'dkala', 'dpage', 'dmail', 'reseller', 'workspace', 'project', 'task_phase')`);
|
||||
await queryRunner.query(`ALTER TABLE "permission" ALTER COLUMN "name" TYPE "public"."permission_name_enum_old" USING "name"::"text"::"public"."permission_name_enum_old"`);
|
||||
await queryRunner.query(`DROP TYPE "public"."permission_name_enum"`);
|
||||
await queryRunner.query(`ALTER TYPE "public"."permission_name_enum_old" RENAME TO "permission_name_enum"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -922,14 +922,15 @@ export const enum WorkSpaceMessage {
|
||||
USERS_DONT_BELONG_TO_THIS_WORKSPACE = "کاربران تعیین شده برای این فضای کاری نیستند!",
|
||||
WORKSPACE_SAME_NAME_EXISTS = "فضای کاری با این اسم از قبل وجود دارد!",
|
||||
WORKSPACE_ID_PARAM_NOT_EMPTY = "پارامتر شناسه فضای کار نباید خالی باشد!",
|
||||
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد"
|
||||
WORKSPACE_ID_UUID = "شناسه فضای کار باید uuid باشد",
|
||||
FORBIDDEN = "شما اجازه دسترسی به این فضای کار را ندارید و یا عضو آن نیستید!"
|
||||
}
|
||||
|
||||
export const enum ProjectMessage {
|
||||
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
||||
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
|
||||
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید.",
|
||||
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!"
|
||||
NOT_MEMBER_OF_PROJECT = "شما عضو این پروژه نیستید!",
|
||||
}
|
||||
|
||||
export const enum TaskPhaseMessage {
|
||||
@@ -945,4 +946,12 @@ export const enum TaskMessage {
|
||||
|
||||
export const enum remarkMessage {
|
||||
REMARK_NOT_FOUND = "برچسب مورد نظر پیدا نشد!"
|
||||
}
|
||||
|
||||
export const enum checkListItemMessage {
|
||||
CHECKLISTITEM_NOT_FOUND = "آیتم چک لیست پیدا نشد!"
|
||||
}
|
||||
|
||||
export const enum attachmentMessage {
|
||||
ATTACHMENT_NOT_FOUND = "ضمیمه پیدا نشد!"
|
||||
}
|
||||
@@ -1,33 +1,19 @@
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from '@nestjs/swagger';
|
||||
import { Controller, Post, Patch, Delete, Param, Body } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
|
||||
import { AttachmentService } from '../providers/attachment.service';
|
||||
import { CreateAttachmentDto } from '../dto/attachment/create-attachment.dto';
|
||||
import { UpdateAttachmentDto } from '../dto/attachment/update-attachment.dto';
|
||||
import { TMAttachment } from '../entities/attachment.entity';
|
||||
import { AuthGuards } from '../../../common/decorators/auth-guard.decorator';
|
||||
import { AdminRoute } from '../../../common/decorators/admin.decorator';
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@ApiTags('Task Manager - Attachments')
|
||||
@Controller('task-manager/attachments')
|
||||
export class AttachmentController {
|
||||
constructor(private readonly attachmentService: AttachmentService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: 'Get all attachments, optionally filtered by task' })
|
||||
@ApiQuery({ name: 'taskId', required: false, description: 'Filter attachments by task ID' })
|
||||
@ApiResponse({ status: 200, description: 'List of attachments', type: [TMAttachment] })
|
||||
findAll(@Query('taskId') taskId?: string): Promise<TMAttachment[]> {
|
||||
if (taskId) return this.attachmentService.findByTask(taskId);
|
||||
return this.attachmentService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiOperation({ summary: 'Get an attachment by ID' })
|
||||
@ApiParam({ name: 'id', description: 'Attachment ID' })
|
||||
@ApiResponse({ status: 200, description: 'Attachment found', type: TMAttachment })
|
||||
@ApiResponse({ status: 404, description: 'Attachment not found' })
|
||||
findOne(@Param('id') id: string): Promise<TMAttachment> {
|
||||
return this.attachmentService.findOne(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new attachment' })
|
||||
@ApiResponse({ status: 201, description: 'Attachment created', type: TMAttachment })
|
||||
|
||||
@@ -1,36 +1,20 @@
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger";
|
||||
import { Controller, Post, Patch, Delete, Param, Body } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
||||
import { CheckListItemService } from "../providers/check-list-item.service";
|
||||
import { CreateCheckListItemDto } from "../dto/check-list-item/create-check-list-item.dto";
|
||||
import { UpdateCheckListItemDto } from "../dto/check-list-item/update-check-list-item.dto";
|
||||
import { CursorPaginationDto } from "../../../common/DTO/cursor-pagination.dto";
|
||||
import { TMCheckListItem } from "../entities/check-list-item.entity";
|
||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||
import { AdminRoute } from "../../../common/decorators/admin.decorator";
|
||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@ApiTags("Task Manager - Check List Items")
|
||||
@Controller("task-manager/check-list-items")
|
||||
export class CheckListItemController {
|
||||
constructor(private readonly checkListItemService: CheckListItemService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: "Get all check list items, optionally filtered by task" })
|
||||
@ApiQuery({ name: "taskId", required: false, description: "Filter check list items by task ID" })
|
||||
@ApiQuery({ name: "cursor", required: false, description: "Cursor for pagination (createdAt ISO string)" })
|
||||
@ApiQuery({ name: "limit", required: false, description: "Number of records to return (max 50)" })
|
||||
@ApiResponse({ status: 200, description: "Cursor-paginated list of check list items" })
|
||||
findAll(@Query() pagination: CursorPaginationDto, @Query("taskId") taskId?: string) {
|
||||
if (taskId) return this.checkListItemService.findByTask(taskId, pagination);
|
||||
return this.checkListItemService.findAll(pagination);
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@ApiOperation({ summary: "Get a check list item by ID" })
|
||||
@ApiParam({ name: "id", description: "CheckListItem ID" })
|
||||
@ApiResponse({ status: 200, description: "CheckListItem found", type: TMCheckListItem })
|
||||
@ApiResponse({ status: 404, description: "CheckListItem not found" })
|
||||
findOne(@Param("id") id: string): Promise<TMCheckListItem> {
|
||||
return this.checkListItemService.findOne(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: "Create a new check list item" })
|
||||
@ApiResponse({ status: 201, description: "CheckListItem created", type: TMCheckListItem })
|
||||
@@ -56,4 +40,13 @@ export class CheckListItemController {
|
||||
remove(@Param("id") id: string): Promise<TMCheckListItem> {
|
||||
return this.checkListItemService.remove(id);
|
||||
}
|
||||
|
||||
@Patch("change-status/:id")
|
||||
@ApiOperation({summary: "change status of a check list item."})
|
||||
@ApiParam({name: "id", description: "CheckListItem ID"})
|
||||
@ApiResponse({status: 200, description: "successfully changed the status!"})
|
||||
@ApiResponse({ status: 404, description: "CheckListItem not found" })
|
||||
changeStatus(@Param() paramDto: ParamDto) {
|
||||
return this.checkListItemService.toggleStatus(paramDto.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
import { UserDec } from "../../../common/decorators/user.decorator";
|
||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
import { ITokenPayload } from "../../auth/interfaces/IToken-payload";
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@@ -19,24 +20,6 @@ import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
export class ProjectController {
|
||||
constructor(private readonly projectService: ProjectService) {}
|
||||
|
||||
@Get()
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Get all projects, optionally filtered by workspace" })
|
||||
@ApiResponse({ status: 200, description: "Paginated list of projects" })
|
||||
findAll(@Query() pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
return this.projectService.findAll(pagination);
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Get a project by ID" })
|
||||
@ApiParam({ name: "id", description: "Project ID" })
|
||||
@ApiResponse({ status: 200, description: "Project found", type: TMProject })
|
||||
@ApiResponse({ status: 404, description: "Project not found" })
|
||||
findOne(@Param("id") id: string): Promise<TMProject> {
|
||||
return this.projectService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@PermissionsDec(PermissionEnum.PROJECT)
|
||||
@ApiOperation({ summary: "Create a new project" })
|
||||
@@ -69,26 +52,23 @@ export class ProjectController {
|
||||
}
|
||||
|
||||
@Get("user/workspace/:id")
|
||||
@ApiOperation({ summary: "Get user projects!" })
|
||||
@ApiOperation({ summary: "Get user projects in a specific workspace!" })
|
||||
@ApiResponse({ status: 200, description: "Got user projects successfully!" })
|
||||
@ApiResponse({status: 400, description: "Bad Request!"})
|
||||
findUserProjects(
|
||||
@UserDec("id") userId: string,
|
||||
@Param() paramDto : ParamDto,
|
||||
@ApiResponse({ status: 400, description: "Bad Request!" })
|
||||
findUserProjectsByWorkspace(
|
||||
@UserDec() user: ITokenPayload,
|
||||
@Param() paramDto: ParamDto,
|
||||
@Query() pagination: PaginationDto,
|
||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
return this.projectService.findUserProjects(userId, paramDto.id, pagination);
|
||||
return this.projectService.findUserProjectsByWorkspace(user.id, user.permissions, paramDto.id, pagination);
|
||||
}
|
||||
|
||||
@Get("project/:id")
|
||||
@ApiOperation({summary: "Get project detail"})
|
||||
@ApiResponse({status: 200, description: "Got Project Detail Successfully!"})
|
||||
@ApiResponse({status: 400, description: "Bad request!"})
|
||||
@ApiResponse({status: 404, description: "The project was not found!"})
|
||||
getProjectDetail(@Param() paramDto: ParamDto,
|
||||
@UserDec('id') userId: string
|
||||
): Promise<TMProject | null> {
|
||||
return this.projectService.getProjectDetail(paramDto.id, userId);
|
||||
@ApiOperation({ summary: "Get project detail" })
|
||||
@ApiResponse({ status: 200, description: "Got Project Detail Successfully!" })
|
||||
@ApiResponse({ status: 400, description: "Bad request!" })
|
||||
@ApiResponse({ status: 404, description: "The project was not found!" })
|
||||
getProjectDetail(@Param() paramDto: ParamDto, @UserDec() user: ITokenPayload): Promise<TMProject | null> {
|
||||
return this.projectService.getProjectDetail(paramDto.id, user.id, user.permissions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,40 +1,19 @@
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger";
|
||||
import { Controller, Post, Patch, Delete, Param, Body } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
||||
import { RemarkService } from "../providers/remark.service";
|
||||
import { CreateRemarkDto } from "../dto/remark/create-remark.dto";
|
||||
import { UpdateRemarkDto } from "../dto/remark/update-remark.dto";
|
||||
import { TMRemark } from "../entities/remark.entity";
|
||||
import { AuthGuards } from "../../../common/decorators/auth-guard.decorator";
|
||||
import { AdminRoute } from "../../../common/decorators/admin.decorator";
|
||||
import { PermissionsDec } from "../../../common/decorators/permission.decorator";
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@PermissionsDec(PermissionEnum.REMARK)
|
||||
@ApiTags("Task Manager - Remarks")
|
||||
@Controller("task-manager/remarks")
|
||||
export class RemarkController {
|
||||
constructor(private readonly remarkService: RemarkService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: "Get all remarks, optionally filtered by task" })
|
||||
@ApiQuery({ name: "taskId", required: false, description: "Filter remarks by task ID" })
|
||||
@ApiResponse({ status: 200, description: "List of remarks", type: [TMRemark] })
|
||||
findAll(@Query("taskId") taskId?: string): Promise<TMRemark[]> {
|
||||
if (taskId) return this.remarkService.findByTask(taskId);
|
||||
return this.remarkService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@ApiOperation({ summary: "Get a remark by ID" })
|
||||
@ApiParam({ name: "id", description: "Remark ID" })
|
||||
@ApiResponse({ status: 200, description: "Remark found", type: TMRemark })
|
||||
@ApiResponse({ status: 404, description: "Remark not found" })
|
||||
findOne(@Param("id") id: string): Promise<TMRemark> {
|
||||
return this.remarkService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: "Create a new remark" })
|
||||
@ApiResponse({ status: 201, description: "Remark created", type: TMRemark })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger";
|
||||
import { Controller, Post, Patch, Delete, Param, Body } from "@nestjs/common";
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
||||
import { TaskPhaseService } from "../providers/task-phase.service";
|
||||
import { CreateTaskPhaseDto } from "../dto/task-phase/create-task-phase.dto";
|
||||
import { UpdateTaskPhaseDto } from "../dto/task-phase/update-task-phase.dto";
|
||||
@@ -17,24 +17,6 @@ import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
export class TaskPhaseController {
|
||||
constructor(private readonly taskPhaseService: TaskPhaseService) {}
|
||||
|
||||
@Get()
|
||||
@ApiOperation({ summary: "Get all task phases, optionally filtered by project" })
|
||||
@ApiQuery({ name: "projectId", required: false, description: "Filter task phases by project ID" })
|
||||
@ApiResponse({ status: 200, description: "List of task phases", type: [TMTaskPhase] })
|
||||
findAll(@Query("projectId") projectId?: string): Promise<TMTaskPhase[]> {
|
||||
if (projectId) return this.taskPhaseService.findByProject(projectId);
|
||||
return this.taskPhaseService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
@ApiOperation({ summary: "Get a task phase by ID" })
|
||||
@ApiParam({ name: "id", description: "TaskPhase ID" })
|
||||
@ApiResponse({ status: 200, description: "TaskPhase found", type: TMTaskPhase })
|
||||
@ApiResponse({ status: 404, description: "TaskPhase not found" })
|
||||
findOne(@Param("id") id: string): Promise<TMTaskPhase> {
|
||||
return this.taskPhaseService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@ApiOperation({ summary: "Create a new task phase" })
|
||||
@ApiResponse({ status: 201, description: "TaskPhase created", type: TMTaskPhase })
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from '@nestjs/swagger';
|
||||
import { Controller, Get, Post, Patch, Delete, Param, Body } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger';
|
||||
import { TaskService } from '../providers/task.service';
|
||||
import { CreateTaskDto } from '../dto/task/create-task.dto';
|
||||
import { UpdateTaskDto } from '../dto/task/update-task.dto';
|
||||
@@ -11,6 +11,7 @@ import { UserDec } from '../../../common/decorators/user.decorator';
|
||||
import { ParamDto } from '../../../common/DTO/param.dto';
|
||||
import { PermissionsDec } from '../../../common/decorators/permission.decorator';
|
||||
import { PermissionEnum } from '../../users/enums/permission.enum';
|
||||
import { ITokenPayload } from '../../auth/interfaces/IToken-payload';
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@@ -19,26 +20,6 @@ import { PermissionEnum } from '../../users/enums/permission.enum';
|
||||
export class TaskController {
|
||||
constructor(private readonly taskService: TaskService) {}
|
||||
|
||||
@Get()
|
||||
@PermissionsDec(PermissionEnum.TASK)
|
||||
@ApiOperation({ summary: 'Get all tasks, optionally filtered by phase' })
|
||||
@ApiQuery({ name: 'taskPhaseId', required: false, description: 'Filter tasks by task phase ID' })
|
||||
@ApiResponse({ status: 200, description: 'List of tasks', type: [TMTask] })
|
||||
findAll(@Query('taskPhaseId') taskPhaseId?: string): Promise<TMTask[]> {
|
||||
if (taskPhaseId) return this.taskService.findByPhase(taskPhaseId);
|
||||
return this.taskService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@PermissionsDec(PermissionEnum.TASK)
|
||||
@ApiOperation({ summary: 'Get a task by ID' })
|
||||
@ApiParam({ name: 'id', description: 'Task ID' })
|
||||
@ApiResponse({ status: 200, description: 'Task found', type: TMTask })
|
||||
@ApiResponse({ status: 404, description: 'Task not found' })
|
||||
findOne(@Param('id') id: string): Promise<TMTask> {
|
||||
return this.taskService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@PermissionsDec(PermissionEnum.TASK)
|
||||
@ApiOperation({ summary: 'Create a new task' })
|
||||
@@ -85,9 +66,9 @@ export class TaskController {
|
||||
@ApiResponse({ status: 200, description: 'Task detail received!' })
|
||||
@ApiResponse({ status: 404, description: 'Task not found' })
|
||||
getTaskDetail(
|
||||
@UserDec('id') userId: string,
|
||||
@UserDec() user: ITokenPayload,
|
||||
@Param() paramDto: ParamDto
|
||||
): Promise<TMTask | null> {
|
||||
return this.taskService.getTaskDetail(userId, paramDto.id);
|
||||
return this.taskService.getTaskDetail(user.id, user.permissions, paramDto.id);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,12 @@ import { WorkspaceService } from '../providers/workspace.service';
|
||||
import { CreateWorkspaceDto } from '../dto/workspace/create-workspace.dto';
|
||||
import { UpdateWorkspaceDto } from '../dto/workspace/update-workspace.dto';
|
||||
import { TMWorkspace } from '../entities/workspace.entity';
|
||||
// import { AuthGuards } from '../../../common/decorators/auth-guard.decorator';
|
||||
import { AdminRoute } from '../../../common/decorators/admin.decorator';
|
||||
import { PermissionsDec } from '../../../common/decorators/permission.decorator';
|
||||
import { PermissionEnum } from '../../users/enums/permission.enum';
|
||||
import { UserDec } from '../../../common/decorators/user.decorator';
|
||||
import { AuthGuards } from '../../../common/decorators/auth-guard.decorator';
|
||||
import { ITokenPayload } from '../../auth/interfaces/IToken-payload';
|
||||
|
||||
@AuthGuards()
|
||||
@AdminRoute()
|
||||
@@ -18,24 +18,6 @@ import { AuthGuards } from '../../../common/decorators/auth-guard.decorator';
|
||||
export class WorkspaceController {
|
||||
constructor(private readonly workspaceService: WorkspaceService) {}
|
||||
|
||||
@Get()
|
||||
@PermissionsDec(PermissionEnum.WORKSPACE)
|
||||
@ApiOperation({ summary: 'Get all workspaces' })
|
||||
@ApiResponse({ status: 200, description: 'List of workspaces', type: [TMWorkspace] })
|
||||
findAll(): Promise<TMWorkspace[]> {
|
||||
return this.workspaceService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@PermissionsDec(PermissionEnum.WORKSPACE)
|
||||
@ApiOperation({ summary: 'Get a workspace by ID' })
|
||||
@ApiParam({ name: 'id', description: 'Workspace ID' })
|
||||
@ApiResponse({ status: 200, description: 'Workspace found', type: TMWorkspace })
|
||||
@ApiResponse({ status: 404, description: 'Workspace not found' })
|
||||
findOne(@Param('id') id: string): Promise<TMWorkspace> {
|
||||
return this.workspaceService.findOneOrFail(id);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@PermissionsDec(PermissionEnum.WORKSPACE)
|
||||
@ApiOperation({ summary: 'Create a new workspace' })
|
||||
@@ -68,7 +50,7 @@ export class WorkspaceController {
|
||||
@ApiOperation({summary: 'Get User WorkSpaces'})
|
||||
@ApiResponse({ status: 200, description: 'Got Workspaces successfully!' })
|
||||
@ApiResponse({ status: 404, description: 'Bad Request!' })
|
||||
findByUser(@UserDec('id') userId: string) {
|
||||
return this.workspaceService.findByUser(userId);
|
||||
findByUser(@UserDec() user: ITokenPayload) {
|
||||
return this.workspaceService.findByUser(user.id, user.permissions);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,36 @@
|
||||
import { Injectable, NotFoundException } from "@nestjs/common";
|
||||
import { AttachmentRepository } from "../repositories/attachment.repository";
|
||||
import { TaskRepository } from "../repositories/task.repository";
|
||||
import { TMAttachment } from "../entities/attachment.entity";
|
||||
import { CreateAttachmentDto } from "../dto/attachment/create-attachment.dto";
|
||||
import { UpdateAttachmentDto } from "../dto/attachment/update-attachment.dto";
|
||||
import { attachmentMessage } from "../../../common/enums/message.enum";
|
||||
import { TaskService } from "./task.service";
|
||||
|
||||
@Injectable()
|
||||
export class AttachmentService {
|
||||
constructor(
|
||||
private readonly attachmentRepository: AttachmentRepository,
|
||||
private readonly taskRepository: TaskRepository,
|
||||
private readonly taskService: TaskService,
|
||||
) {}
|
||||
|
||||
findAll(): Promise<TMAttachment[]> {
|
||||
return this.attachmentRepository.findAll();
|
||||
}
|
||||
|
||||
findByTask(taskId: string): Promise<TMAttachment[]> {
|
||||
return this.attachmentRepository.findByTask(taskId);
|
||||
}
|
||||
|
||||
async findOne(id: string): Promise<TMAttachment> {
|
||||
const attachment = await this.attachmentRepository.findOneById(id);
|
||||
if (!attachment) throw new NotFoundException(`Attachment #${id} not found`);
|
||||
async findOneOrFail(id: string): Promise<TMAttachment> {
|
||||
const attachment = await this.attachmentRepository.findOne({ where: { id }, relations: { task: true } });
|
||||
if (!attachment) throw new NotFoundException(attachmentMessage.ATTACHMENT_NOT_FOUND);
|
||||
return attachment;
|
||||
}
|
||||
|
||||
async create(dto: CreateAttachmentDto): Promise<TMAttachment> {
|
||||
const task = await this.taskRepository.findOneById(dto.taskId);
|
||||
if (!task) throw new NotFoundException(`Task #${dto.taskId} not found`);
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
|
||||
const attachment = this.attachmentRepository.create(dto);
|
||||
return this.attachmentRepository.save(attachment);
|
||||
}
|
||||
|
||||
async update(id: string, dto: UpdateAttachmentDto): Promise<TMAttachment> {
|
||||
const attachment = await this.findOne(id);
|
||||
const attachment = await this.findOneOrFail(id);
|
||||
|
||||
if (dto.taskId) {
|
||||
const task = await this.taskRepository.findOneById(dto.taskId);
|
||||
if (!task) throw new NotFoundException(`Task #${dto.taskId} not found`);
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
}
|
||||
|
||||
Object.assign(attachment, dto);
|
||||
@@ -47,7 +38,7 @@ export class AttachmentService {
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<void> {
|
||||
await this.findOne(id);
|
||||
await this.findOneOrFail(id);
|
||||
await this.attachmentRepository.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +1,36 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { CheckListItemRepository } from '../repositories/check-list-item.repository';
|
||||
import { TaskRepository } from '../repositories/task.repository';
|
||||
import { TMCheckListItem } from '../entities/check-list-item.entity';
|
||||
import { CreateCheckListItemDto } from '../dto/check-list-item/create-check-list-item.dto';
|
||||
import { UpdateCheckListItemDto } from '../dto/check-list-item/update-check-list-item.dto';
|
||||
import { CursorPaginationDto } from '../../../common/DTO/cursor-pagination.dto';
|
||||
import { CursorPaginatedResult } from '../../../common/interfaces/cursor-paginated-result.interface';
|
||||
import { buildCursorPageFormat } from '../../../common/helpers/cursor-paginated.helper';
|
||||
import { checkListItemMessage } from '../../../common/enums/message.enum';
|
||||
import { TaskService } from './task.service';
|
||||
|
||||
@Injectable()
|
||||
export class CheckListItemService {
|
||||
constructor(
|
||||
private readonly checkListItemRepository: CheckListItemRepository,
|
||||
private readonly taskRepository: TaskRepository,
|
||||
private readonly taskService: TaskService,
|
||||
) {}
|
||||
|
||||
async findAll(pagination: CursorPaginationDto): Promise<CursorPaginatedResult<TMCheckListItem>> {
|
||||
const limit = pagination.limit ?? 10;
|
||||
const cursorDate = pagination.cursor ? new Date(pagination.cursor) : undefined;
|
||||
|
||||
const [data] = await this.checkListItemRepository.findAll(limit, cursorDate);
|
||||
|
||||
return buildCursorPageFormat(data, limit, cursorDate);
|
||||
}
|
||||
|
||||
async findByTask(
|
||||
taskId: string,
|
||||
pagination: CursorPaginationDto,
|
||||
): Promise<CursorPaginatedResult<TMCheckListItem>> {
|
||||
const limit = pagination.limit ?? 10;
|
||||
const cursorDate = pagination.cursor ? new Date(pagination.cursor) : undefined;
|
||||
|
||||
const [data] = await this.checkListItemRepository.findByTask(taskId, limit, cursorDate);
|
||||
|
||||
return buildCursorPageFormat(data, limit, cursorDate);
|
||||
}
|
||||
|
||||
async findOne(id: string): Promise<TMCheckListItem> {
|
||||
async findOneOrFail(id: string): Promise<TMCheckListItem> {
|
||||
const checkListItem = await this.checkListItemRepository.findOneById(id);
|
||||
if (!checkListItem) throw new NotFoundException(`CheckListItem #${id} not found`);
|
||||
if (!checkListItem) throw new NotFoundException(checkListItemMessage.CHECKLISTITEM_NOT_FOUND);
|
||||
return checkListItem;
|
||||
}
|
||||
|
||||
async create(dto: CreateCheckListItemDto): Promise<TMCheckListItem> {
|
||||
const task = await this.taskRepository.findOneById(dto.taskId);
|
||||
if (!task) throw new NotFoundException(`Task #${dto.taskId} not found`);
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
|
||||
const checkListItem = this.checkListItemRepository.create(dto);
|
||||
return this.checkListItemRepository.save(checkListItem);
|
||||
}
|
||||
|
||||
async update(id: string, dto: UpdateCheckListItemDto): Promise<TMCheckListItem> {
|
||||
const checkListItem = await this.findOne(id);
|
||||
const checkListItem = await this.findOneOrFail(id);
|
||||
|
||||
if (dto.taskId) {
|
||||
const task = await this.taskRepository.findOneById(dto.taskId);
|
||||
if (!task) throw new NotFoundException(`Task #${dto.taskId} not found`);
|
||||
await this.taskService.findOneOrFail(dto.taskId);
|
||||
}
|
||||
|
||||
Object.assign(checkListItem, dto);
|
||||
@@ -63,8 +38,17 @@ export class CheckListItemService {
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<TMCheckListItem> {
|
||||
const checkListItem = await this.findOne(id);
|
||||
const checkListItem = await this.findOneOrFail(id);
|
||||
await this.checkListItemRepository.delete(id);
|
||||
return checkListItem;
|
||||
}
|
||||
|
||||
async toggleStatus(id: string) : Promise<TMCheckListItem> {
|
||||
const checkListItem = await this.findOneOrFail(id);
|
||||
const isDone = checkListItem.isDone;
|
||||
checkListItem.isDone = !isDone;
|
||||
await this.checkListItemRepository.save(checkListItem);
|
||||
|
||||
return checkListItem;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
||||
import { WorkspaceService } from "./workspace.service";
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
|
||||
@Injectable()
|
||||
export class ProjectService {
|
||||
@@ -19,29 +20,6 @@ export class ProjectService {
|
||||
private readonly userRepository: Repository<User>,
|
||||
) {}
|
||||
|
||||
async findAll(pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
const page = pagination.page ?? 1;
|
||||
const limit = pagination.limit ?? 10;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [projects, count] = await this.projectRepository.findAndCount({
|
||||
skip: skip,
|
||||
take: limit,
|
||||
relations: {
|
||||
users: true,
|
||||
},
|
||||
select: {
|
||||
users: {
|
||||
id: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return { projects, count, paginate: true };
|
||||
}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMProject> {
|
||||
const project = await this.projectRepository.findOne({ where: { id } });
|
||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||
@@ -124,21 +102,36 @@ export class ProjectService {
|
||||
return project;
|
||||
}
|
||||
|
||||
async findUserProjects(
|
||||
async findUserProjectsByWorkspace(
|
||||
userId: string,
|
||||
permissions: PermissionEnum[],
|
||||
wsId: string,
|
||||
pagination: PaginationDto,
|
||||
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||
const workspace = await this.workspaceService.findOneOrFail(wsId);
|
||||
|
||||
const page = pagination.page ?? 1;
|
||||
const limit = pagination.limit ?? 10;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const [projects, count] = await this.projectRepository.findUserProjects(userId, wsId, skip, limit);
|
||||
const isPermissionIncluded = permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS);
|
||||
const isUserMemeberOfWorkspace = workspace.users.some((user) => user.id === userId);
|
||||
|
||||
var res: [TMProject[], number];
|
||||
if (isUserMemeberOfWorkspace) {
|
||||
res = await this.projectRepository.findUserProjects(userId, wsId, skip, limit);
|
||||
} else if (isPermissionIncluded) {
|
||||
res = await this.projectRepository.findAndCount({ where: { workspaceId: wsId } });
|
||||
} else {
|
||||
throw new ForbiddenException(WorkSpaceMessage.FORBIDDEN);
|
||||
}
|
||||
|
||||
const [projects, count] = res;
|
||||
|
||||
return { projects, count, paginate: true };
|
||||
}
|
||||
|
||||
async getProjectDetail(projectId: string, userId: string): Promise<TMProject | null> {
|
||||
async getProjectDetail(projectId: string, userId: string, permissions: PermissionEnum[]): Promise<TMProject | null> {
|
||||
const project = await this.projectRepository.findOne({
|
||||
where: { id: projectId },
|
||||
relations: {
|
||||
@@ -147,8 +140,9 @@ export class ProjectService {
|
||||
});
|
||||
if (!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||
|
||||
const isUserMember = project.users.some(user => user.id === userId);
|
||||
if(!isUserMember) throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
||||
const isUserMember = project.users.some((user) => user.id === userId);
|
||||
if (!isUserMember && !permissions.includes(PermissionEnum.VIEW_ALL_PROJECTS))
|
||||
throw new ForbiddenException(ProjectMessage.NOT_MEMBER_OF_PROJECT);
|
||||
|
||||
const projectDetail = await this.projectRepository.getProjectDetail(projectId);
|
||||
|
||||
|
||||
@@ -13,19 +13,6 @@ export class RemarkService {
|
||||
private readonly taskService: TaskService,
|
||||
) {}
|
||||
|
||||
findAll(): Promise<TMRemark[]> {
|
||||
return this.remarkRepository.find({ relations: { task: true } });
|
||||
}
|
||||
|
||||
findByTask(taskId: string): Promise<TMRemark[]> {
|
||||
return this.remarkRepository.find({
|
||||
where: { taskId },
|
||||
relations: {
|
||||
task: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMRemark> {
|
||||
const remark = await this.remarkRepository.findOne({ where: { id } });
|
||||
if (!remark) throw new NotFoundException(remarkMessage.REMARK_NOT_FOUND);
|
||||
|
||||
@@ -13,16 +13,6 @@ export class TaskPhaseService {
|
||||
private readonly projectService: ProjectService
|
||||
) {}
|
||||
|
||||
findAll(): Promise<TMTaskPhase[]> {
|
||||
return this.taskPhaseRepository.find();
|
||||
}
|
||||
|
||||
findByProject(projectId: string): Promise<TMTaskPhase[]> {
|
||||
return this.taskPhaseRepository.find({
|
||||
where: {projectId}
|
||||
});
|
||||
}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMTaskPhase> {
|
||||
const taskPhase = await this.taskPhaseRepository.findOne({where: {id}});
|
||||
if (!taskPhase) throw new NotFoundException(TaskPhaseMessage.TASK_PHASE_NOT_FOUND);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { User } from "../../users/entities/user.entity";
|
||||
import { TaskMessage, TaskPhaseMessage } from "../../../common/enums/message.enum";
|
||||
import { TaskPhaseRepository } from "../repositories/task-phase.repository";
|
||||
import { TMTaskPhase } from "../entities/task-phase.entity";
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
|
||||
@Injectable()
|
||||
export class TaskService {
|
||||
@@ -20,22 +21,12 @@ export class TaskService {
|
||||
private readonly userRepository: Repository<User>,
|
||||
) {}
|
||||
|
||||
async findAll(): Promise<TMTask[]> {
|
||||
return this.taskRepository.find({
|
||||
relations: ["taskPhase", "remarks", "attachments", "checkListItems", "users"],
|
||||
});
|
||||
}
|
||||
|
||||
async findByPhase(taskPhaseId: string): Promise<TMTask[]> {
|
||||
return this.taskRepository.find({ where: { taskPhaseId } });
|
||||
}
|
||||
|
||||
async findOneOrFail(id: string): Promise<TMTask> {
|
||||
const task = await this.taskRepository.findOne({
|
||||
where: { id },
|
||||
relations: {
|
||||
taskPhase: true,
|
||||
users: true
|
||||
users: true,
|
||||
},
|
||||
});
|
||||
if (!task) throw new NotFoundException(TaskMessage.TASK_NOT_FOUND);
|
||||
@@ -125,11 +116,12 @@ export class TaskService {
|
||||
await this.taskRepository.delete(id);
|
||||
}
|
||||
|
||||
async getTaskDetail(userId: string, taskId: string): Promise<TMTask | null> {
|
||||
async getTaskDetail(userId: string, permissions: PermissionEnum[], taskId: string): Promise<TMTask | null> {
|
||||
const task = await this.findOneOrFail(taskId);
|
||||
|
||||
const isTaskMember = task.users.some((user) => user.id === userId);
|
||||
if(!isTaskMember) throw new ForbiddenException(TaskMessage.USER_NOT_TASK_MEMBER);
|
||||
const hasPermission = permissions.includes(PermissionEnum.TASK);
|
||||
if (!isTaskMember && !hasPermission) throw new ForbiddenException(TaskMessage.USER_NOT_TASK_MEMBER);
|
||||
|
||||
const taskDetail = await this.taskRepository.getTaskDetail(taskId);
|
||||
return taskDetail;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { CreateWorkspaceDto } from "../dto/workspace/create-workspace.dto";
|
||||
import { UpdateWorkspaceDto } from "../dto/workspace/update-workspace.dto";
|
||||
import { User } from "../../users/entities/user.entity";
|
||||
import { WorkSpaceMessage } from "../../../common/enums/message.enum";
|
||||
import { PermissionEnum } from "../../users/enums/permission.enum";
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceService {
|
||||
@@ -68,7 +69,10 @@ export class WorkspaceService {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async findByUser(userId: string): Promise<TMWorkspace[]> {
|
||||
async findByUser(userId: string, permissions: PermissionEnum[]): Promise<TMWorkspace[]> {
|
||||
if(permissions.includes(PermissionEnum.VIEW_ALL_WORKSPACES)) {
|
||||
return await this.workspaceRepository.find();
|
||||
}
|
||||
return await this.workspaceRepository.findByUser(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,44 +4,10 @@ import { Repository } from 'typeorm';
|
||||
import { TMAttachment } from '../entities/attachment.entity';
|
||||
|
||||
@Injectable()
|
||||
export class AttachmentRepository {
|
||||
export class AttachmentRepository extends Repository<TMAttachment>{
|
||||
constructor(
|
||||
@InjectRepository(TMAttachment)
|
||||
private readonly repository: Repository<TMAttachment>,
|
||||
) {}
|
||||
|
||||
findAll() {
|
||||
return this.repository.find({
|
||||
relations: ['task'],
|
||||
});
|
||||
}
|
||||
|
||||
findByTask(taskId: string) {
|
||||
return this.repository.find({
|
||||
where: { taskId },
|
||||
});
|
||||
}
|
||||
|
||||
findOneById(id: string) {
|
||||
return this.repository.findOne({
|
||||
where: { id },
|
||||
relations: ['task'],
|
||||
});
|
||||
}
|
||||
|
||||
create(data: Partial<TMAttachment>) {
|
||||
return this.repository.create(data);
|
||||
}
|
||||
|
||||
save(attachment: TMAttachment) {
|
||||
return this.repository.save(attachment);
|
||||
}
|
||||
|
||||
update(id: string, data: Partial<TMAttachment>) {
|
||||
return this.repository.update(id, data);
|
||||
}
|
||||
|
||||
delete(id: string) {
|
||||
return this.repository.delete(id);
|
||||
@InjectRepository(TMAttachment) attachmentRepository: Repository<TMAttachment>,
|
||||
) {
|
||||
super(attachmentRepository.target, attachmentRepository.manager, attachmentRepository.queryRunner);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,13 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository, MoreThan } from 'typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { TMCheckListItem } from '../entities/check-list-item.entity';
|
||||
|
||||
@Injectable()
|
||||
export class CheckListItemRepository {
|
||||
export class CheckListItemRepository extends Repository<TMCheckListItem>{
|
||||
constructor(
|
||||
@InjectRepository(TMCheckListItem)
|
||||
private readonly repository: Repository<TMCheckListItem>,
|
||||
) {}
|
||||
|
||||
findAll(limit: number, cursor?: Date) {
|
||||
return this.repository.findAndCount({
|
||||
where: cursor ? { createdAt: MoreThan(cursor) } : {},
|
||||
order: { createdAt: 'ASC' },
|
||||
take: limit + 1,
|
||||
relations: ['task'],
|
||||
});
|
||||
}
|
||||
|
||||
findByTask(taskId: string, limit: number, cursor?: Date) {
|
||||
return this.repository.findAndCount({
|
||||
where: cursor
|
||||
? { taskId, createdAt: MoreThan(cursor) }
|
||||
: { taskId },
|
||||
order: { createdAt: 'ASC' },
|
||||
take: limit + 1,
|
||||
relations: ['task'],
|
||||
});
|
||||
}
|
||||
|
||||
findOneById(id: string) {
|
||||
return this.repository.findOne({
|
||||
where: { id },
|
||||
relations: ['task'],
|
||||
});
|
||||
}
|
||||
|
||||
findOneByCreatedAt(createdAt: Date) {
|
||||
return this.repository.findOne({
|
||||
where: { createdAt },
|
||||
order: { createdAt: 'ASC' },
|
||||
});
|
||||
}
|
||||
|
||||
create(data: Partial<TMCheckListItem>) {
|
||||
return this.repository.create(data);
|
||||
}
|
||||
|
||||
save(checkListItem: TMCheckListItem) {
|
||||
return this.repository.save(checkListItem);
|
||||
}
|
||||
|
||||
update(id: string, data: Partial<TMCheckListItem>) {
|
||||
return this.repository.update(id, data);
|
||||
}
|
||||
|
||||
delete(id: string) {
|
||||
return this.repository.delete(id);
|
||||
@InjectRepository(TMCheckListItem) checkListItemRepository: Repository<TMCheckListItem>,
|
||||
) {
|
||||
super(checkListItemRepository.target, checkListItemRepository.manager, checkListItemRepository.queryRunner);
|
||||
}
|
||||
}
|
||||
@@ -22,21 +22,22 @@ export class TaskRepository extends Repository<TMTask> {
|
||||
qb.where("completedCheckListItems.isDone = :isDone", { isDone: true }),
|
||||
)
|
||||
|
||||
.select(["remark.id",
|
||||
"remark.title",
|
||||
"remark.color",
|
||||
"checkListItem.id",
|
||||
"checkListItem.title",
|
||||
"checkListItem.isDone",
|
||||
"attachment.id",
|
||||
"attachment.title",
|
||||
"attachment.type",
|
||||
"attachment.file",
|
||||
|
||||
"user.id",
|
||||
"user.firstName",
|
||||
"user.lastName"
|
||||
])
|
||||
.select([
|
||||
"remark.id",
|
||||
"remark.title",
|
||||
"remark.color",
|
||||
"checkListItem.id",
|
||||
"checkListItem.title",
|
||||
"checkListItem.isDone",
|
||||
"attachment.id",
|
||||
"attachment.title",
|
||||
"attachment.type",
|
||||
"attachment.file",
|
||||
|
||||
"user.id",
|
||||
"user.firstName",
|
||||
"user.lastName",
|
||||
])
|
||||
.where("task.id = :taskId", { taskId })
|
||||
.getOne();
|
||||
}
|
||||
|
||||
@@ -25,9 +25,10 @@ export enum PermissionEnum {
|
||||
DPAGE = "dpage",
|
||||
DMAIL = 'dmail',
|
||||
RESELLER="reseller",
|
||||
WORKSPACE="workspace",
|
||||
PROJECT="project",
|
||||
WORKSPACE="workspace", // create, update, remove
|
||||
VIEW_ALL_WORKSPACES="view_all_workspaces",
|
||||
PROJECT="project", // create, update, remove
|
||||
VIEW_ALL_PROJECTS="view_all_projects",
|
||||
TASK="task", // read, create, update, remove
|
||||
TASK_PHASE="task_phase",
|
||||
TASK="task",
|
||||
REMARK="remark"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user