@flusys/nestjs-task-manager 7.1.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/index.d.ts +3 -3
- package/controllers/index.d.ts +5 -5
- package/controllers/task-board.controller.d.ts +3 -3
- package/controllers/task-comment.controller.d.ts +2 -2
- package/controllers/task-label.controller.d.ts +2 -2
- package/controllers/task-list.controller.d.ts +3 -3
- package/controllers/task.controller.d.ts +4 -4
- package/docs/index.d.ts +1 -1
- package/docs/task-manager-swagger.config.d.ts +1 -1
- package/dtos/index.d.ts +5 -5
- package/dtos/task-board.dto.d.ts +1 -1
- package/dtos/task.dto.d.ts +2 -2
- package/entities/index.d.ts +19 -19
- package/entities/task-board-with-company.entity.d.ts +1 -1
- package/fesm/234.js +1393 -0
- package/fesm/431.js +981 -0
- package/fesm/827.js +1054 -0
- package/fesm/988.js +881 -0
- package/fesm/config/index.js +156 -3
- package/fesm/controllers/index.js +21 -5
- package/fesm/docs/index.js +58 -1
- package/fesm/dtos/index.js +280 -5
- package/fesm/entities/index.js +26 -46
- package/fesm/gateways/index.js +288 -1
- package/fesm/index.js +440 -9
- package/fesm/interfaces/index.js +16 -2
- package/fesm/modules/index.js +210 -1
- package/fesm/runtime.js +85 -0
- package/fesm/services/index.js +53 -8
- package/gateways/index.d.ts +1 -1
- package/gateways/task-board.gateway.d.ts +3 -3
- package/index.d.ts +9 -9
- package/interfaces/index.d.ts +2 -2
- package/interfaces/task-manager-module.interface.d.ts +3 -3
- package/interfaces/task.interface.d.ts +2 -2
- package/modules/index.d.ts +1 -1
- package/modules/task-manager.module.d.ts +2 -2
- package/package.json +26 -36
- package/services/index.d.ts +8 -8
- package/services/task-activity.service.d.ts +1 -1
- package/services/task-board.service.d.ts +5 -5
- package/services/task-comment.service.d.ts +4 -4
- package/services/task-label.service.d.ts +4 -4
- package/services/task-list.service.d.ts +4 -4
- package/services/task-manager-config.service.d.ts +3 -3
- package/services/task-manager-datasource.provider.d.ts +3 -3
- package/services/task.service.d.ts +7 -7
- package/cjs/config/event-actions.js +0 -37
- package/cjs/config/index.js +0 -20
- package/cjs/config/message-keys.js +0 -92
- package/cjs/config/task-manager.constants.js +0 -11
- package/cjs/controllers/index.js +0 -22
- package/cjs/controllers/task-board.controller.js +0 -219
- package/cjs/controllers/task-board.controller.spec.js +0 -132
- package/cjs/controllers/task-comment.controller.js +0 -103
- package/cjs/controllers/task-comment.controller.spec.js +0 -86
- package/cjs/controllers/task-label.controller.js +0 -112
- package/cjs/controllers/task-label.controller.spec.js +0 -88
- package/cjs/controllers/task-list.controller.js +0 -158
- package/cjs/controllers/task-list.controller.spec.js +0 -112
- package/cjs/controllers/task.controller.js +0 -199
- package/cjs/controllers/task.controller.spec.js +0 -131
- package/cjs/docs/index.js +0 -18
- package/cjs/docs/task-manager-swagger.config.js +0 -43
- package/cjs/docs/task-manager-swagger.config.spec.js +0 -28
- package/cjs/dtos/index.js +0 -22
- package/cjs/dtos/task-board.dto.js +0 -310
- package/cjs/dtos/task-comment.dto.js +0 -131
- package/cjs/dtos/task-label.dto.js +0 -120
- package/cjs/dtos/task-list.dto.js +0 -198
- package/cjs/dtos/task.dto.js +0 -367
- package/cjs/entities/index.js +0 -72
- package/cjs/entities/index.spec.js +0 -30
- package/cjs/entities/task-activity.entity.js +0 -98
- package/cjs/entities/task-assignee.entity.js +0 -67
- package/cjs/entities/task-board-member.entity.js +0 -94
- package/cjs/entities/task-board-with-company.entity.js +0 -57
- package/cjs/entities/task-board.entity.js +0 -88
- package/cjs/entities/task-comment.entity.js +0 -80
- package/cjs/entities/task-label.entity.js +0 -72
- package/cjs/entities/task-list.entity.js +0 -104
- package/cjs/entities/task-task-label.entity.js +0 -67
- package/cjs/entities/task.entity.js +0 -151
- package/cjs/gateways/index.js +0 -18
- package/cjs/gateways/task-board.gateway.js +0 -167
- package/cjs/gateways/task-board.gateway.spec.js +0 -243
- package/cjs/index.js +0 -26
- package/cjs/interfaces/index.js +0 -19
- package/cjs/interfaces/task-manager-module.interface.js +0 -4
- package/cjs/interfaces/task.interface.js +0 -4
- package/cjs/modules/index.js +0 -18
- package/cjs/modules/task-manager.module.js +0 -135
- package/cjs/modules/task-manager.module.spec.js +0 -144
- package/cjs/services/index.js +0 -25
- package/cjs/services/task-activity.service.js +0 -76
- package/cjs/services/task-activity.service.spec.js +0 -125
- package/cjs/services/task-board.service.js +0 -247
- package/cjs/services/task-board.service.spec.js +0 -465
- package/cjs/services/task-comment.service.js +0 -103
- package/cjs/services/task-comment.service.spec.js +0 -160
- package/cjs/services/task-label.service.js +0 -97
- package/cjs/services/task-label.service.spec.js +0 -138
- package/cjs/services/task-list.service.js +0 -130
- package/cjs/services/task-list.service.spec.js +0 -284
- package/cjs/services/task-manager-config.service.js +0 -69
- package/cjs/services/task-manager-config.service.spec.js +0 -98
- package/cjs/services/task-manager-datasource.provider.js +0 -84
- package/cjs/services/task-manager-datasource.provider.spec.js +0 -131
- package/cjs/services/task.service.js +0 -398
- package/cjs/services/task.service.spec.js +0 -700
- package/fesm/config/event-actions.js +0 -16
- package/fesm/config/message-keys.js +0 -65
- package/fesm/config/task-manager.constants.js +0 -1
- package/fesm/controllers/task-board.controller.js +0 -209
- package/fesm/controllers/task-board.controller.spec.js +0 -128
- package/fesm/controllers/task-comment.controller.js +0 -93
- package/fesm/controllers/task-comment.controller.spec.js +0 -82
- package/fesm/controllers/task-label.controller.js +0 -102
- package/fesm/controllers/task-label.controller.spec.js +0 -84
- package/fesm/controllers/task-list.controller.js +0 -148
- package/fesm/controllers/task-list.controller.spec.js +0 -108
- package/fesm/controllers/task.controller.js +0 -189
- package/fesm/controllers/task.controller.spec.js +0 -127
- package/fesm/docs/task-manager-swagger.config.js +0 -33
- package/fesm/docs/task-manager-swagger.config.spec.js +0 -24
- package/fesm/dtos/task-board.dto.js +0 -277
- package/fesm/dtos/task-comment.dto.js +0 -110
- package/fesm/dtos/task-label.dto.js +0 -99
- package/fesm/dtos/task-list.dto.js +0 -174
- package/fesm/dtos/task.dto.js +0 -337
- package/fesm/entities/index.spec.js +0 -26
- package/fesm/entities/task-activity.entity.js +0 -88
- package/fesm/entities/task-assignee.entity.js +0 -57
- package/fesm/entities/task-board-member.entity.js +0 -76
- package/fesm/entities/task-board-with-company.entity.js +0 -47
- package/fesm/entities/task-board.entity.js +0 -78
- package/fesm/entities/task-comment.entity.js +0 -70
- package/fesm/entities/task-label.entity.js +0 -62
- package/fesm/entities/task-list.entity.js +0 -94
- package/fesm/entities/task-task-label.entity.js +0 -57
- package/fesm/entities/task.entity.js +0 -133
- package/fesm/gateways/task-board.gateway.js +0 -157
- package/fesm/gateways/task-board.gateway.spec.js +0 -239
- package/fesm/interfaces/task-manager-module.interface.js +0 -1
- package/fesm/interfaces/task.interface.js +0 -1
- package/fesm/modules/task-manager.module.js +0 -125
- package/fesm/modules/task-manager.module.spec.js +0 -140
- package/fesm/services/task-activity.service.js +0 -66
- package/fesm/services/task-activity.service.spec.js +0 -121
- package/fesm/services/task-board.service.js +0 -237
- package/fesm/services/task-board.service.spec.js +0 -461
- package/fesm/services/task-comment.service.js +0 -93
- package/fesm/services/task-comment.service.spec.js +0 -156
- package/fesm/services/task-label.service.js +0 -87
- package/fesm/services/task-label.service.spec.js +0 -134
- package/fesm/services/task-list.service.js +0 -120
- package/fesm/services/task-list.service.spec.js +0 -280
- package/fesm/services/task-manager-config.service.js +0 -59
- package/fesm/services/task-manager-config.service.spec.js +0 -94
- package/fesm/services/task-manager-datasource.provider.js +0 -74
- package/fesm/services/task-manager-datasource.provider.spec.js +0 -127
- package/fesm/services/task.service.js +0 -388
- package/fesm/services/task.service.spec.js +0 -696
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
function _ts_metadata(k, v) {
|
|
21
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
-
}
|
|
23
|
-
function _ts_param(paramIndex, decorator) {
|
|
24
|
-
return function(target, key) {
|
|
25
|
-
decorator(target, key, paramIndex);
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
import { Inject, Injectable, Scope } from '@nestjs/common';
|
|
29
|
-
import { TaskActivity } from '../entities';
|
|
30
|
-
import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
|
|
31
|
-
export class TaskActivityService {
|
|
32
|
-
async log(taskId, boardId, userId, action, oldValue, newValue) {
|
|
33
|
-
const repo = await this.ensureRepository();
|
|
34
|
-
const activity = repo.create({
|
|
35
|
-
taskId,
|
|
36
|
-
boardId,
|
|
37
|
-
userId,
|
|
38
|
-
action,
|
|
39
|
-
oldValue,
|
|
40
|
-
newValue
|
|
41
|
-
});
|
|
42
|
-
await repo.save(activity);
|
|
43
|
-
}
|
|
44
|
-
async ensureRepository() {
|
|
45
|
-
if (!this.repository) {
|
|
46
|
-
this.repository = await this.dataSourceProvider.getRepository(TaskActivity);
|
|
47
|
-
}
|
|
48
|
-
return this.repository;
|
|
49
|
-
}
|
|
50
|
-
constructor(dataSourceProvider){
|
|
51
|
-
_define_property(this, "dataSourceProvider", void 0);
|
|
52
|
-
_define_property(this, "repository", void 0);
|
|
53
|
-
this.dataSourceProvider = dataSourceProvider;
|
|
54
|
-
this.repository = null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
TaskActivityService = _ts_decorate([
|
|
58
|
-
Injectable({
|
|
59
|
-
scope: Scope.REQUEST
|
|
60
|
-
}),
|
|
61
|
-
_ts_param(0, Inject(TaskManagerDataSourceProvider)),
|
|
62
|
-
_ts_metadata("design:type", Function),
|
|
63
|
-
_ts_metadata("design:paramtypes", [
|
|
64
|
-
typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
|
|
65
|
-
])
|
|
66
|
-
], TaskActivityService);
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { Test } from '@nestjs/testing';
|
|
2
|
-
import { TaskActivity } from '../entities';
|
|
3
|
-
import { TaskActivityService } from './task-activity.service';
|
|
4
|
-
import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
|
|
5
|
-
describe('TaskActivityService', ()=>{
|
|
6
|
-
let service;
|
|
7
|
-
let mockRepo;
|
|
8
|
-
let mockDataSourceProvider;
|
|
9
|
-
beforeEach(async ()=>{
|
|
10
|
-
mockRepo = {
|
|
11
|
-
create: jest.fn((data)=>({
|
|
12
|
-
id: 'activity-uuid-1',
|
|
13
|
-
...data
|
|
14
|
-
})),
|
|
15
|
-
save: jest.fn().mockResolvedValue(undefined)
|
|
16
|
-
};
|
|
17
|
-
mockDataSourceProvider = {
|
|
18
|
-
getRepository: jest.fn().mockResolvedValue(mockRepo)
|
|
19
|
-
};
|
|
20
|
-
const module = await Test.createTestingModule({
|
|
21
|
-
providers: [
|
|
22
|
-
TaskActivityService,
|
|
23
|
-
{
|
|
24
|
-
provide: TaskManagerDataSourceProvider,
|
|
25
|
-
useValue: mockDataSourceProvider
|
|
26
|
-
}
|
|
27
|
-
]
|
|
28
|
-
}).compile();
|
|
29
|
-
service = await module.resolve(TaskActivityService);
|
|
30
|
-
});
|
|
31
|
-
it('lazily resolves the TaskActivity repository from the DataSource provider', async ()=>{
|
|
32
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.created', null, {
|
|
33
|
-
title: 'New task'
|
|
34
|
-
});
|
|
35
|
-
expect(mockDataSourceProvider.getRepository).toHaveBeenCalledWith(TaskActivity);
|
|
36
|
-
expect(mockDataSourceProvider.getRepository).toHaveBeenCalledTimes(1);
|
|
37
|
-
});
|
|
38
|
-
it('caches the repository across multiple log calls (only resolved once)', async ()=>{
|
|
39
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.created', null, {
|
|
40
|
-
title: 'New task'
|
|
41
|
-
});
|
|
42
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.moved', {
|
|
43
|
-
listId: 'a'
|
|
44
|
-
}, {
|
|
45
|
-
listId: 'b'
|
|
46
|
-
});
|
|
47
|
-
expect(mockDataSourceProvider.getRepository).toHaveBeenCalledTimes(1);
|
|
48
|
-
expect(mockRepo.save).toHaveBeenCalledTimes(2);
|
|
49
|
-
});
|
|
50
|
-
it('records "task.created" activity with title in newValue and null oldValue', async ()=>{
|
|
51
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.created', null, {
|
|
52
|
-
title: 'New task'
|
|
53
|
-
});
|
|
54
|
-
expect(mockRepo.create).toHaveBeenCalledWith({
|
|
55
|
-
taskId: 'task-1',
|
|
56
|
-
boardId: 'board-1',
|
|
57
|
-
userId: 'user-1',
|
|
58
|
-
action: 'task.created',
|
|
59
|
-
oldValue: null,
|
|
60
|
-
newValue: {
|
|
61
|
-
title: 'New task'
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
expect(mockRepo.save).toHaveBeenCalledWith(expect.objectContaining({
|
|
65
|
-
action: 'task.created',
|
|
66
|
-
newValue: {
|
|
67
|
-
title: 'New task'
|
|
68
|
-
}
|
|
69
|
-
}));
|
|
70
|
-
});
|
|
71
|
-
it('records "task.moved" activity with old and new listId', async ()=>{
|
|
72
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.moved', {
|
|
73
|
-
listId: 'list-old'
|
|
74
|
-
}, {
|
|
75
|
-
listId: 'list-new'
|
|
76
|
-
});
|
|
77
|
-
expect(mockRepo.create).toHaveBeenCalledWith(expect.objectContaining({
|
|
78
|
-
action: 'task.moved',
|
|
79
|
-
oldValue: {
|
|
80
|
-
listId: 'list-old'
|
|
81
|
-
},
|
|
82
|
-
newValue: {
|
|
83
|
-
listId: 'list-new'
|
|
84
|
-
}
|
|
85
|
-
}));
|
|
86
|
-
});
|
|
87
|
-
it('records "task.assigned" activity with old and new assigneeIds', async ()=>{
|
|
88
|
-
await service.log('task-1', 'board-1', 'user-1', 'task.assigned', {
|
|
89
|
-
assigneeIds: [
|
|
90
|
-
'u1'
|
|
91
|
-
]
|
|
92
|
-
}, {
|
|
93
|
-
assigneeIds: [
|
|
94
|
-
'u1',
|
|
95
|
-
'u2'
|
|
96
|
-
]
|
|
97
|
-
});
|
|
98
|
-
expect(mockRepo.create).toHaveBeenCalledWith(expect.objectContaining({
|
|
99
|
-
action: 'task.assigned',
|
|
100
|
-
oldValue: {
|
|
101
|
-
assigneeIds: [
|
|
102
|
-
'u1'
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
|
-
newValue: {
|
|
106
|
-
assigneeIds: [
|
|
107
|
-
'u1',
|
|
108
|
-
'u2'
|
|
109
|
-
]
|
|
110
|
-
}
|
|
111
|
-
}));
|
|
112
|
-
});
|
|
113
|
-
it('records an activity with a null userId (system-initiated action)', async ()=>{
|
|
114
|
-
await service.log('task-1', 'board-1', null, 'task.created', null, {
|
|
115
|
-
title: 'System task'
|
|
116
|
-
});
|
|
117
|
-
expect(mockRepo.create).toHaveBeenCalledWith(expect.objectContaining({
|
|
118
|
-
userId: null
|
|
119
|
-
}));
|
|
120
|
-
});
|
|
121
|
-
});
|
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
function _ts_metadata(k, v) {
|
|
21
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
-
}
|
|
23
|
-
function _ts_param(paramIndex, decorator) {
|
|
24
|
-
return function(target, key) {
|
|
25
|
-
decorator(target, key, paramIndex);
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
import { ApiService, getCastIntType, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
29
|
-
import { UtilsService } from '@flusys/nestjs-shared/modules';
|
|
30
|
-
import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
|
|
31
|
-
import { BadRequestException, Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
|
|
32
|
-
import { IsNull } from 'typeorm';
|
|
33
|
-
import { TASK_BOARD_MESSAGES, TASK_MANAGER_EVENT_ENTITIES, TASK_MANAGER_EVENT_MODULE } from '../config';
|
|
34
|
-
import { BoardMemberRole, TaskBoard, TaskBoardMember, TaskBoardWithCompany } from '../entities';
|
|
35
|
-
import { TaskManagerConfigService } from './task-manager-config.service';
|
|
36
|
-
import { TaskManagerDataSourceProvider } from './task-manager-datasource.provider';
|
|
37
|
-
export class TaskBoardService extends ApiService {
|
|
38
|
-
async convertSingleDtoToEntity(dto, user) {
|
|
39
|
-
await this.ensureDataSourceRepository();
|
|
40
|
-
let entity = {};
|
|
41
|
-
if ('id' in dto && dto.id) {
|
|
42
|
-
const existing = await this.repository.findOne({
|
|
43
|
-
where: {
|
|
44
|
-
id: dto.id
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
if (!existing) throw new NotFoundException({
|
|
48
|
-
message: 'Board not found',
|
|
49
|
-
messageKey: TASK_BOARD_MESSAGES.NOT_FOUND
|
|
50
|
-
});
|
|
51
|
-
entity = existing;
|
|
52
|
-
}
|
|
53
|
-
const merged = {
|
|
54
|
-
...entity,
|
|
55
|
-
name: dto.name ?? entity.name,
|
|
56
|
-
description: dto.description !== undefined ? dto.description ?? null : entity.description ?? null,
|
|
57
|
-
color: dto.color ?? entity.color ?? '#3B82F6',
|
|
58
|
-
isActive: ('isActive' in dto ? dto.isActive : undefined) ?? entity.isActive ?? true
|
|
59
|
-
};
|
|
60
|
-
if (this.config.isCompanyFeatureEnabled()) {
|
|
61
|
-
merged.companyId = user?.companyId ?? null;
|
|
62
|
-
}
|
|
63
|
-
return merged;
|
|
64
|
-
}
|
|
65
|
-
async getExtraManipulateQuery(query, filterDto, user) {
|
|
66
|
-
await super.getExtraManipulateQuery(query, filterDto, user);
|
|
67
|
-
applyCompanyFilter(query, {
|
|
68
|
-
isCompanyFeatureEnabled: this.config.isCompanyFeatureEnabled(),
|
|
69
|
-
entityAlias: 'task_board'
|
|
70
|
-
}, user);
|
|
71
|
-
if (user?.id) {
|
|
72
|
-
query.innerJoin('task_board_member', 'tbm_filter', 'tbm_filter.board_id = task_board.id AND tbm_filter.user_id = :currentUserId AND tbm_filter.deleted_at IS NULL', {
|
|
73
|
-
currentUserId: user.id
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
query.addSelect('task_board.createdAt').addSelect('task_board.updatedAt').addSelect(`(SELECT CAST(COUNT(*) AS ${getCastIntType()}) FROM task_board_member tbm WHERE tbm.board_id = task_board.id AND tbm.deleted_at IS NULL)`, 'total_members').addSelect(`(SELECT CAST(COUNT(*) AS ${getCastIntType()}) FROM task_list tl WHERE tl.board_id = task_board.id AND tl.is_active = true AND tl.deleted_at IS NULL)`, 'total_lists').addSelect(`(SELECT CAST(COUNT(*) AS ${getCastIntType()}) FROM task t WHERE t.board_id = task_board.id AND t.deleted_at IS NULL)`, 'total_tasks');
|
|
77
|
-
return {
|
|
78
|
-
query,
|
|
79
|
-
isRaw: true
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
convertEntityToResponseDto(entity, isRaw) {
|
|
83
|
-
if (!isRaw) return super.convertEntityToResponseDto(entity, isRaw);
|
|
84
|
-
const prefix = `${this.entityName}_`;
|
|
85
|
-
const mapped = {};
|
|
86
|
-
for (const [key, value] of Object.entries(entity)){
|
|
87
|
-
const rawKey = key.startsWith(prefix) ? key.slice(prefix.length) : key;
|
|
88
|
-
const camelKey = rawKey.replace(/_([a-z])/g, (_, c)=>c.toUpperCase());
|
|
89
|
-
mapped[camelKey] = typeof value === 'string' && value !== '' && !isNaN(Number(value)) ? Number(value) : value;
|
|
90
|
-
}
|
|
91
|
-
return mapped;
|
|
92
|
-
}
|
|
93
|
-
async addMember(dto, user) {
|
|
94
|
-
await this.ensureDataSourceRepository();
|
|
95
|
-
const memberRepo = await this.ensureMemberRepository();
|
|
96
|
-
const board = await this.repository.findOne({
|
|
97
|
-
where: {
|
|
98
|
-
id: dto.boardId
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
if (!board) throw new NotFoundException({
|
|
102
|
-
message: 'Board not found',
|
|
103
|
-
messageKey: TASK_BOARD_MESSAGES.NOT_FOUND
|
|
104
|
-
});
|
|
105
|
-
const existing = await memberRepo.findOne({
|
|
106
|
-
where: {
|
|
107
|
-
boardId: dto.boardId,
|
|
108
|
-
userId: dto.userId,
|
|
109
|
-
deletedAt: IsNull()
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
if (existing) throw new BadRequestException({
|
|
113
|
-
message: 'User is already a board member',
|
|
114
|
-
messageKey: TASK_BOARD_MESSAGES.MEMBER_ALREADY_EXISTS
|
|
115
|
-
});
|
|
116
|
-
const softDeleted = await memberRepo.findOne({
|
|
117
|
-
where: {
|
|
118
|
-
boardId: dto.boardId,
|
|
119
|
-
userId: dto.userId
|
|
120
|
-
},
|
|
121
|
-
withDeleted: true
|
|
122
|
-
});
|
|
123
|
-
if (softDeleted) {
|
|
124
|
-
await memberRepo.restore({
|
|
125
|
-
id: softDeleted.id
|
|
126
|
-
});
|
|
127
|
-
await memberRepo.update({
|
|
128
|
-
id: softDeleted.id
|
|
129
|
-
}, {
|
|
130
|
-
role: dto.role ?? BoardMemberRole.MEMBER
|
|
131
|
-
});
|
|
132
|
-
const restored = await memberRepo.findOne({
|
|
133
|
-
where: {
|
|
134
|
-
id: softDeleted.id
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
await this.invalidateBoardCache(dto.boardId);
|
|
138
|
-
return restored;
|
|
139
|
-
}
|
|
140
|
-
const member = memberRepo.create({
|
|
141
|
-
boardId: dto.boardId,
|
|
142
|
-
userId: dto.userId,
|
|
143
|
-
role: dto.role ?? BoardMemberRole.MEMBER,
|
|
144
|
-
createdById: user.id
|
|
145
|
-
});
|
|
146
|
-
const saved = await memberRepo.save(member);
|
|
147
|
-
await this.invalidateBoardCache(dto.boardId);
|
|
148
|
-
return saved;
|
|
149
|
-
}
|
|
150
|
-
async removeMember(dto) {
|
|
151
|
-
const memberRepo = await this.ensureMemberRepository();
|
|
152
|
-
const member = await memberRepo.findOne({
|
|
153
|
-
where: {
|
|
154
|
-
boardId: dto.boardId,
|
|
155
|
-
userId: dto.userId,
|
|
156
|
-
deletedAt: IsNull()
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
if (!member) throw new NotFoundException({
|
|
160
|
-
message: 'Member not found',
|
|
161
|
-
messageKey: TASK_BOARD_MESSAGES.MEMBER_NOT_FOUND
|
|
162
|
-
});
|
|
163
|
-
await memberRepo.update({
|
|
164
|
-
id: member.id
|
|
165
|
-
}, {
|
|
166
|
-
deletedAt: new Date()
|
|
167
|
-
});
|
|
168
|
-
await this.invalidateBoardCache(dto.boardId);
|
|
169
|
-
}
|
|
170
|
-
async getMembers(boardId) {
|
|
171
|
-
const memberRepo = await this.ensureMemberRepository();
|
|
172
|
-
const { entities, raw } = await memberRepo.createQueryBuilder('tbm').leftJoin('app_user', 'u', 'u.id = tbm.user_id').addSelect('u.name', 'userName').addSelect('u.email', 'userEmail').where('tbm.board_id = :boardId', {
|
|
173
|
-
boardId
|
|
174
|
-
}).andWhere('tbm.deleted_at IS NULL').orderBy('tbm.created_at', 'ASC').getRawAndEntities();
|
|
175
|
-
return entities.map((entity, i)=>({
|
|
176
|
-
...entity,
|
|
177
|
-
userName: raw[i]?.userName ?? null,
|
|
178
|
-
userEmail: raw[i]?.userEmail ?? null
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
async isBoardMember(boardId, userId) {
|
|
182
|
-
const memberRepo = await this.ensureMemberRepository();
|
|
183
|
-
const count = await memberRepo.count({
|
|
184
|
-
where: {
|
|
185
|
-
boardId,
|
|
186
|
-
userId,
|
|
187
|
-
deletedAt: IsNull()
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
return count > 0;
|
|
191
|
-
}
|
|
192
|
-
async afterInsertOperation(entities, _dto, user, _qr) {
|
|
193
|
-
if (!user?.id) return;
|
|
194
|
-
const memberRepo = await this.ensureMemberRepository();
|
|
195
|
-
await memberRepo.save(entities.map((board)=>memberRepo.create({
|
|
196
|
-
boardId: board.id,
|
|
197
|
-
userId: user.id,
|
|
198
|
-
role: BoardMemberRole.OWNER,
|
|
199
|
-
createdById: user.id
|
|
200
|
-
})));
|
|
201
|
-
}
|
|
202
|
-
async invalidateBoardCache(boardId) {
|
|
203
|
-
await Promise.all([
|
|
204
|
-
this.clearCacheForAll(),
|
|
205
|
-
this.clearCacheForId([
|
|
206
|
-
{
|
|
207
|
-
id: boardId
|
|
208
|
-
}
|
|
209
|
-
])
|
|
210
|
-
]);
|
|
211
|
-
}
|
|
212
|
-
async ensureMemberRepository() {
|
|
213
|
-
if (!this.memberRepository) {
|
|
214
|
-
this.memberRepository = await this.dataSourceProvider.getRepository(TaskBoardMember);
|
|
215
|
-
}
|
|
216
|
-
return this.memberRepository;
|
|
217
|
-
}
|
|
218
|
-
constructor(cacheManager, utilsService, config, dataSourceProvider){
|
|
219
|
-
super(TASK_MANAGER_EVENT_ENTITIES.TASK_BOARD, cacheManager, utilsService, TaskBoardService.name, true, TASK_MANAGER_EVENT_MODULE, dataSourceProvider, config.isCompanyFeatureEnabled() ? TaskBoardWithCompany : TaskBoard), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "config", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "memberRepository", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.config = config, this.dataSourceProvider = dataSourceProvider, this.memberRepository = null;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
TaskBoardService = _ts_decorate([
|
|
223
|
-
Injectable({
|
|
224
|
-
scope: Scope.REQUEST
|
|
225
|
-
}),
|
|
226
|
-
_ts_param(0, Inject('CACHE_INSTANCE')),
|
|
227
|
-
_ts_param(1, Inject(UtilsService)),
|
|
228
|
-
_ts_param(2, Inject(TaskManagerConfigService)),
|
|
229
|
-
_ts_param(3, Inject(TaskManagerDataSourceProvider)),
|
|
230
|
-
_ts_metadata("design:type", Function),
|
|
231
|
-
_ts_metadata("design:paramtypes", [
|
|
232
|
-
typeof HybridCache === "undefined" ? Object : HybridCache,
|
|
233
|
-
typeof UtilsService === "undefined" ? Object : UtilsService,
|
|
234
|
-
typeof TaskManagerConfigService === "undefined" ? Object : TaskManagerConfigService,
|
|
235
|
-
typeof TaskManagerDataSourceProvider === "undefined" ? Object : TaskManagerDataSourceProvider
|
|
236
|
-
])
|
|
237
|
-
], TaskBoardService);
|