@flusys/ng-task-manager 1.2.0-rc.1

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/README.md ADDED
@@ -0,0 +1,276 @@
1
+ # @flusys/ng-task-manager
2
+
3
+ Task management UI for FLUSYS Angular applications — dynamic kanban boards, drag-and-drop list reordering, real-time collaboration via Socket.IO, board-scoped member assignment, and a signal-based reactive state layer.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@flusys/ng-task-manager.svg)](https://www.npmjs.com/package/@flusys/ng-task-manager)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ---
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ npm install @flusys/ng-task-manager @angular/cdk socket.io-client
14
+ ```
15
+
16
+ ---
17
+
18
+ ## 1. Add Routes
19
+
20
+ ```typescript
21
+ // app.routes.ts
22
+ import { TASK_MANAGER_ROUTES } from '@flusys/ng-task-manager';
23
+
24
+ export const routes: Routes = [
25
+ {
26
+ path: 'task-manager',
27
+ children: TASK_MANAGER_ROUTES,
28
+ },
29
+ ];
30
+ ```
31
+
32
+ | Path | Page |
33
+ |---|---|
34
+ | `/task-manager` | `BoardListPage` — grid of all boards |
35
+ | `/task-manager/board/:boardId` | `BoardViewPage` — kanban board with drag-drop |
36
+
37
+ Both pages are lazy-loaded via `loadComponent`.
38
+
39
+ ---
40
+
41
+ ## 2. Add Menu Item
42
+
43
+ ```typescript
44
+ // app-menu.config.ts
45
+ {
46
+ id: 'task-manager',
47
+ labelKey: 'menu.task.manager',
48
+ icon: 'check-square',
49
+ iconType: 1,
50
+ routerLink: ['/task-manager'],
51
+ }
52
+ ```
53
+
54
+ ---
55
+
56
+ ## 3. State Service
57
+
58
+ `TaskBoardStateService` is the single source of truth for an open board. It manages all signal state and handles real-time events from the WebSocket.
59
+
60
+ ```typescript
61
+ import { TaskBoardStateService } from '@flusys/ng-task-manager';
62
+
63
+ @Component({ ... })
64
+ export class MyComponent {
65
+ private readonly state = inject(TaskBoardStateService);
66
+
67
+ // Open a board (loads lists, tasks, labels, members; joins socket room)
68
+ ngOnInit(): void {
69
+ this.state.openBoard(this.boardId);
70
+ }
71
+
72
+ // Close a board (leaves socket room, clears state)
73
+ ngOnDestroy(): void {
74
+ this.state.closeBoard();
75
+ }
76
+
77
+ // Reactive signals
78
+ readonly board = this.state.board; // Signal<ITaskBoard | null>
79
+ readonly lists = this.state.lists; // Signal<ITaskList[]>
80
+ readonly tasks = this.state.tasks; // Signal<ITask[]>
81
+ readonly labels = this.state.labels; // Signal<ITaskLabel[]>
82
+ readonly members = this.state.members; // Signal<ITaskBoardMember[]>
83
+ readonly isLoading = this.state.isLoading; // Signal<boolean>
84
+
85
+ // Computed helpers
86
+ readonly tasksByList = this.state.tasksByList; // Signal<Map<listId, ITask[]>>
87
+ readonly listsWithTasks = this.state.listsWithTasks; // Signal<Array<ITaskList & { tasks: ITask[] }>>
88
+ }
89
+ ```
90
+
91
+ ### Real-time event handling
92
+
93
+ `TaskBoardStateService` subscribes to `board:event` socket events automatically when `openBoard()` is called. All 8 event types update signal state in-place without a full reload:
94
+
95
+ | Event type | Effect |
96
+ |---|---|
97
+ | `task:created` | Appended to `tasks` signal |
98
+ | `task:updated` | Replaced in `tasks` by id |
99
+ | `task:moved` | `listId` and `position` updated in-place |
100
+ | `task:deleted` | Removed from `tasks` |
101
+ | `list:created` | Appended to `lists` signal |
102
+ | `list:updated` | Replaced in `lists` by id |
103
+ | `list:deleted` | Removed from `lists` |
104
+ | `list:reordered` | Lists re-sorted by new position values |
105
+
106
+ ---
107
+
108
+ ## 4. Socket Service
109
+
110
+ `TaskBoardSocketService` manages the Socket.IO connection to the `/task-boards` namespace.
111
+
112
+ ```typescript
113
+ import { TaskBoardSocketService } from '@flusys/ng-task-manager';
114
+
115
+ @Injectable({ providedIn: 'root' })
116
+ export class MyService {
117
+ private readonly socket = inject(TaskBoardSocketService);
118
+
119
+ connect(accessToken: string): void {
120
+ this.socket.connect(accessToken); // connects with JWT auth
121
+ }
122
+
123
+ joinBoard(boardId: string): void {
124
+ this.socket.joinBoard(boardId); // emits board:join
125
+ }
126
+
127
+ leaveBoard(boardId: string): void {
128
+ this.socket.leaveBoard(boardId); // emits board:leave
129
+ }
130
+
131
+ // Observable<IBoardSocketEvent>
132
+ readonly events$ = this.socket.onBoardEvent;
133
+
134
+ // Signal<boolean>
135
+ readonly connected = this.socket.isConnected;
136
+ }
137
+ ```
138
+
139
+ ---
140
+
141
+ ## 5. API Services
142
+
143
+ | Service | Base path | Key methods |
144
+ |---|---|---|
145
+ | `TaskBoardApiService` | `/board` | `getAll()`, `insert()`, `update()`, `delete()`, `getMembers()`, `addMember()`, `removeMember()` |
146
+ | `TaskApiService` | `/task` | `getBoardTasks()`, `insert()`, `update()`, `delete()`, `moveTask()`, `assignTask()` |
147
+ | `TaskListApiService` | `/task-list` | `getBoardLists()`, `insert()`, `update()`, `delete()`, `reorder()` |
148
+ | `TaskLabelApiService` | `/task-label` | `getBoardLabels()`, `insert()`, `update()`, `delete()` |
149
+ | `TaskCommentApiService` | `/task-comment` | `getTaskComments()`, `insert()`, `update()`, `delete()` |
150
+
151
+ All services extend `ApiResourceService` and use the POST-only RPC convention.
152
+
153
+ ---
154
+
155
+ ## 6. Components
156
+
157
+ ### `TaskCardComponent`
158
+
159
+ Kanban card displayed inside each list column.
160
+
161
+ ```html
162
+ <task-card [task]="task" (cardClick)="openDetail($event)" />
163
+ ```
164
+
165
+ | Input | Type | Description |
166
+ |---|---|---|
167
+ | `task` | `ITask` | Task data to render |
168
+
169
+ | Output | Type | Description |
170
+ |---|---|---|
171
+ | `cardClick` | `ITask` | Emitted when the card is clicked |
172
+
173
+ Displays: label color bars, priority badge, due date, assignee avatar placeholder.
174
+
175
+ ---
176
+
177
+ ### `TaskFormDialogComponent`
178
+
179
+ Custom Dialog for creating and editing tasks.
180
+
181
+ ```html
182
+ <task-form-dialog
183
+ [(visible)]="showForm"
184
+ [boardId]="boardId"
185
+ [listId]="selectedListId"
186
+ [members]="state.members()"
187
+ [labels]="state.labels()"
188
+ (saved)="onTaskSaved($event)"
189
+ />
190
+ ```
191
+
192
+ | Input | Type | Description |
193
+ |---|---|---|
194
+ | `visible` | `boolean` (model) | Controls dialog open/close |
195
+ | `task` | `ITask \| null` | Pass existing task to edit; omit to create |
196
+ | `boardId` | `string` | Board context |
197
+ | `listId` | `string` | Default list for new tasks |
198
+ | `members` | `ITaskBoardMember[]` | Assignee dropdown — board members only |
199
+ | `labels` | `ITaskLabel[]` | Multi-select label options |
200
+
201
+ | Output | Type | Description |
202
+ |---|---|---|
203
+ | `saved` | `ITask` | Emitted after successful create or update |
204
+
205
+ ---
206
+
207
+ ### `TaskDetailPanelComponent`
208
+
209
+ Custom Drawer (right panel, 480 px) showing full task details and threaded comments.
210
+
211
+ ```html
212
+ <task-detail-panel
213
+ [(visible)]="showDetail"
214
+ [task]="selectedTask"
215
+ [boardId]="boardId"
216
+ />
217
+ ```
218
+
219
+ | Input | Type | Description |
220
+ |---|---|---|
221
+ | `visible` | `boolean` (model) | Controls panel open/close |
222
+ | `task` | `ITask \| null` | Task to display |
223
+ | `boardId` | `string` | Used to load comments |
224
+
225
+ ---
226
+
227
+ ## 7. Pages
228
+
229
+ ### `BoardListPage`
230
+
231
+ Grid view of all boards the user has access to. Provides a "Create Board" action that opens an inline dialog.
232
+
233
+ Route: `/task-manager`
234
+
235
+ ### `BoardViewPage`
236
+
237
+ Full kanban board. Receives `boardId` via route input binding (`withComponentInputBinding()`).
238
+
239
+ - Lists rendered as columns, tasks as draggable cards (Angular CDK DragDrop)
240
+ - Dragging a card between columns calls `TaskApiService.moveTask()`
241
+ - Real-time updates applied by `TaskBoardStateService.handleBoardEvent()`
242
+ - "Add List" creates a new dynamic list column
243
+ - Clicking a card opens `TaskDetailPanelComponent`
244
+ - "Add Task" opens `TaskFormDialogComponent`
245
+
246
+ Route: `/task-manager/board/:boardId`
247
+
248
+ ---
249
+
250
+ ## 8. Interfaces
251
+
252
+ ```typescript
253
+ import type {
254
+ ITaskBoard,
255
+ ITaskBoardMember,
256
+ ITaskList,
257
+ ITask,
258
+ ITaskLabel,
259
+ ITaskComment,
260
+ ITaskActivity,
261
+ IBoardSocketEvent,
262
+ BoardMemberRole,
263
+ TaskPriority,
264
+ } from '@flusys/ng-task-manager';
265
+ ```
266
+
267
+ | Type | Values |
268
+ |---|---|
269
+ | `BoardMemberRole` | `'OWNER' \| 'ADMIN' \| 'MEMBER' \| 'VIEWER'` |
270
+ | `TaskPriority` | `'LOW' \| 'MEDIUM' \| 'HIGH' \| 'URGENT'` |
271
+
272
+ ---
273
+
274
+ ## License
275
+
276
+ MIT © FLUSYS