@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 +276 -0
- package/fesm2022/flusys-ng-task-manager.mjs +4025 -0
- package/fesm2022/flusys-ng-task-manager.mjs.map +1 -0
- package/package.json +34 -0
- package/types/flusys-ng-task-manager.d.ts +580 -0
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
|
+
[](https://www.npmjs.com/package/@flusys/ng-task-manager)
|
|
6
|
+
[](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
|