@emberai-engg/task-board 0.3.6 → 0.4.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 +132 -71
- package/dist/index.d.mts +561 -2
- package/dist/index.d.ts +561 -2
- package/dist/index.js +3458 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3400 -35
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +2450 -25
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @emberai-engg/task-board
|
|
2
2
|
|
|
3
|
-
Reusable Kanban task board component with built-in create/detail UI
|
|
3
|
+
Reusable Kanban task board component with built-in create/detail UI, threaded
|
|
4
|
+
discussions with highlight-to-comment, structured outstanding questions, file
|
|
5
|
+
attachments backed by Google Cloud Storage, and a WYSIWYG markdown editor.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -8,9 +10,21 @@ Reusable Kanban task board component with built-in create/detail UI.
|
|
|
8
10
|
npm install @emberai-engg/task-board
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Then import the bundled stylesheet once at app start (e.g. in `app/layout.tsx`):
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
```ts
|
|
16
|
+
import '@emberai-engg/task-board/styles.css';
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
That's it. The stylesheet is self-contained — Tailwind utilities used by the
|
|
20
|
+
package are pre-compiled into it, so you don't need to add anything to your own
|
|
21
|
+
Tailwind config or `@source` paths. The bundled CSS deliberately omits the
|
|
22
|
+
Tailwind preflight so it won't trample your app's own resets.
|
|
23
|
+
|
|
24
|
+
## Quick Start — list page only (slide-over detail)
|
|
25
|
+
|
|
26
|
+
The default `<TaskBoard>` ships with a built-in `<TaskDetailPanel>` slide-over
|
|
27
|
+
that opens when a task card is clicked.
|
|
14
28
|
|
|
15
29
|
```tsx
|
|
16
30
|
import { TaskBoardProvider, TaskBoard } from '@emberai-engg/task-board';
|
|
@@ -23,17 +37,8 @@ function App() {
|
|
|
23
37
|
return (
|
|
24
38
|
<TaskBoardProvider
|
|
25
39
|
apiClient={apiClient}
|
|
26
|
-
user={
|
|
27
|
-
|
|
28
|
-
name: user.name,
|
|
29
|
-
email: user.email,
|
|
30
|
-
apps: user.apps,
|
|
31
|
-
is_internal: user.is_internal,
|
|
32
|
-
is_reviewer: user.is_reviewer,
|
|
33
|
-
}}
|
|
34
|
-
projects={[
|
|
35
|
-
{ slug: 'my-project', name: 'My Project' },
|
|
36
|
-
]}
|
|
40
|
+
user={user}
|
|
41
|
+
projects={[{ slug: 'my-project', name: 'My Project' }]}
|
|
37
42
|
>
|
|
38
43
|
<TaskBoard onShareFeedback={() => router.push('/feedback')} />
|
|
39
44
|
</TaskBoardProvider>
|
|
@@ -41,14 +46,63 @@ function App() {
|
|
|
41
46
|
}
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
-
|
|
49
|
+
## Quick Start — list + dedicated detail route
|
|
50
|
+
|
|
51
|
+
For larger workflows (description sections, outstanding questions, attachments,
|
|
52
|
+
threads with highlight-to-comment), pair `<TaskBoard>` on the list route with
|
|
53
|
+
`<TaskDetailView>` on a separate detail route.
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
// app/task-board/page.tsx
|
|
57
|
+
function TaskBoardPage() {
|
|
58
|
+
const router = useRouter();
|
|
59
|
+
return (
|
|
60
|
+
<TaskBoardProvider apiClient={apiClient} user={user} projects={projects}>
|
|
61
|
+
<TaskBoard
|
|
62
|
+
onTaskOpen={(task) => router.push(`/task-board/${task.id}?project=${task.project_slug}`)}
|
|
63
|
+
/>
|
|
64
|
+
</TaskBoardProvider>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// app/task-board/[taskId]/page.tsx
|
|
69
|
+
function TaskDetailPage({ params }: { params: { taskId: string } }) {
|
|
70
|
+
const router = useRouter();
|
|
71
|
+
return (
|
|
72
|
+
<TaskBoardProvider apiClient={apiClient} user={user} projects={projects}>
|
|
73
|
+
<TaskDetailView
|
|
74
|
+
taskId={params.taskId}
|
|
75
|
+
onBack={() => router.push('/task-board')}
|
|
76
|
+
onNavigateToTask={(id, slug) => router.push(`/task-board/${id}?project=${slug}`)}
|
|
77
|
+
onDeleted={() => router.push('/task-board')}
|
|
78
|
+
/>
|
|
79
|
+
</TaskBoardProvider>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
When `onTaskOpen` is set, `<TaskBoard>` skips its built-in slide-over panel —
|
|
85
|
+
the consumer owns navigation.
|
|
86
|
+
|
|
87
|
+
## What the detail page gives you
|
|
88
|
+
|
|
89
|
+
- **Inline-editable title**, click-to-edit
|
|
90
|
+
- **Status / priority / share / delete** in the header
|
|
91
|
+
- **Four description sections** (Problem, User Story, Proposed Behavior,
|
|
92
|
+
Acceptance Criteria), each with a Draft/Approved toggle
|
|
93
|
+
- **WYSIWYG markdown editor** — bold/italic, H2, bullet/numbered lists with
|
|
94
|
+
multi-line support and auto-incrementing numbers, blockquote, inline code,
|
|
95
|
+
@mentions. Stores markdown on disk via `mdToHtml`/`htmlToMd` round-trip.
|
|
96
|
+
- **Outstanding Questions** — structured list with awaiting/answered status,
|
|
97
|
+
per-question replies, mark-answered/reopen, author-only delete
|
|
98
|
+
- **Attachments** — three groups (Images / Files / Links & recordings), GCS
|
|
99
|
+
upload, signed read URLs, hover-to-delete
|
|
100
|
+
- **Threads panel** — Threads + Activity tabs, collapse toggle (persisted),
|
|
101
|
+
active/completed filter, per-thread title and complete/reopen, thread
|
|
102
|
+
composer with attachments and public/internal toggle
|
|
103
|
+
- **Highlight-to-comment** — select text in a description section to attach a
|
|
104
|
+
thread anchor; clicking the anchor pill scrolls back to the section and
|
|
105
|
+
pulses it
|
|
52
106
|
|
|
53
107
|
## Props / Config Reference
|
|
54
108
|
|
|
@@ -63,6 +117,7 @@ This gives you:
|
|
|
63
117
|
| `priorities` | `PriorityConfig[]` | No | Priority levels |
|
|
64
118
|
| `tags` | `TagConfig[]` | No | Predefined tags |
|
|
65
119
|
| `apiBasePath` | `string` | No | API prefix (defaults to `/api/v1/taskboard`) |
|
|
120
|
+
| `internalLabel` | `string` | No | Label on internal-only comment chips. Defaults to `"Internal"`. |
|
|
66
121
|
| `features` | `object` | No | Feature flags for enabling/disabling features |
|
|
67
122
|
| `onTaskCreate` | `(task) => void` | No | Callback on task creation |
|
|
68
123
|
| `onTaskUpdate` | `(task) => void` | No | Callback on task update |
|
|
@@ -76,52 +131,32 @@ This gives you:
|
|
|
76
131
|
| `className` | `string` | CSS class for the outer container |
|
|
77
132
|
| `headerActions` | `ReactNode` | Additional buttons in the header |
|
|
78
133
|
| `onShareFeedback` | `() => void` | Callback for Share Feedback button. Hidden if omitted. |
|
|
79
|
-
| `onTaskOpen` | `(task) => void` |
|
|
80
|
-
| `renderTaskDetail` | `function` | Override for task detail panel (built-in used if omitted) |
|
|
134
|
+
| `onTaskOpen` | `(task) => void` | When provided, the built-in slide-over panel is suppressed and the consumer owns navigation. |
|
|
135
|
+
| `renderTaskDetail` | `function` | Override for task detail panel (built-in slide-over used if omitted) |
|
|
81
136
|
| `renderCreateTask` | `function` | Override for create task modal (built-in used if omitted) |
|
|
82
137
|
|
|
83
|
-
###
|
|
84
|
-
|
|
85
|
-
If you need custom create/detail UI, pass render props:
|
|
86
|
-
|
|
87
|
-
```tsx
|
|
88
|
-
<TaskBoard
|
|
89
|
-
renderCreateTask={({ projectSlug, defaultStatus, onClose, onCreate }) => (
|
|
90
|
-
<MyCustomCreateModal ... />
|
|
91
|
-
)}
|
|
92
|
-
renderTaskDetail={({ task, onClose, onUpdate }) => (
|
|
93
|
-
<MyCustomDetailPanel ... />
|
|
94
|
-
)}
|
|
95
|
-
/>
|
|
96
|
-
```
|
|
138
|
+
### `TaskDetailView`
|
|
97
139
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
// Use hooks independently
|
|
108
|
-
function MyCustomUI() {
|
|
109
|
-
const { createTask, moveTask } = useTaskActions(tasks, setTasks, fetchTasks);
|
|
110
|
-
// ...
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Use small components
|
|
114
|
-
<PriorityBadge priority="high" />
|
|
115
|
-
<UserAvatar name="John Smith" size="sm" showTooltip />
|
|
116
|
-
```
|
|
140
|
+
| Prop | Type | Description |
|
|
141
|
+
|------|------|-------------|
|
|
142
|
+
| `taskId` | `string` | Required. The task to show. |
|
|
143
|
+
| `onBack` | `() => void` | Callback for the back link. Use this for SPA routing. |
|
|
144
|
+
| `backHref` | `string` | href for the back link if `onBack` is omitted. |
|
|
145
|
+
| `breadcrumb` | `ReactNode` | Slot rendered above the main content (e.g. consumer breadcrumb bar). |
|
|
146
|
+
| `onDeleted` | `(task) => void` | Called after successful delete; consumer should navigate away. |
|
|
147
|
+
| `onNavigateToTask` | `(id, projectSlug) => void` | Provide to enable prev/next buttons. |
|
|
148
|
+
| `buildShareUrl` | `(task) => string` | Override the share URL. Defaults to `${origin}/task-board/${id}?project=${slug}`. |
|
|
117
149
|
|
|
118
150
|
## Hooks API
|
|
119
151
|
|
|
120
152
|
| Hook | Purpose |
|
|
121
153
|
|------|---------|
|
|
122
154
|
| `useTaskBoard()` | Board state: projects, tasks, loading, pagination |
|
|
123
|
-
| `useTaskActions(
|
|
155
|
+
| `useTaskActions(...)` | CRUD: create, update, delete, move tasks |
|
|
124
156
|
| `useTaskDetail(taskId)` | Single task: comments, activity, field updates |
|
|
157
|
+
| `useTaskQuestions(taskId, initial?)` | Outstanding Questions for a task: list + create / update / delete / reply |
|
|
158
|
+
| `useTaskAttachments(taskId, initial?)` | Attachments: list + uploadFile / addLink / remove |
|
|
159
|
+
| `useHighlightAnchor()` | Selection-driven anchor flow: bubble + pendingAnchor + focusAnchor |
|
|
125
160
|
| `useShareLink()` | Copy shareable task URLs |
|
|
126
161
|
|
|
127
162
|
## Feature Flags
|
|
@@ -129,19 +164,49 @@ function MyCustomUI() {
|
|
|
129
164
|
```tsx
|
|
130
165
|
<TaskBoardProvider
|
|
131
166
|
features={{
|
|
132
|
-
dragAndDrop: true,
|
|
133
|
-
comments: true,
|
|
134
|
-
mentions: true,
|
|
135
|
-
notifications: true,
|
|
136
|
-
internalComments: true,
|
|
137
|
-
tags: true,
|
|
138
|
-
sharing: true,
|
|
139
|
-
filters: true,
|
|
140
|
-
unreadIndicators: true,
|
|
167
|
+
dragAndDrop: true,
|
|
168
|
+
comments: true,
|
|
169
|
+
mentions: true,
|
|
170
|
+
notifications: true,
|
|
171
|
+
internalComments: true,
|
|
172
|
+
tags: true,
|
|
173
|
+
sharing: true,
|
|
174
|
+
filters: true,
|
|
175
|
+
unreadIndicators: true,
|
|
141
176
|
}}
|
|
142
177
|
/>
|
|
143
178
|
```
|
|
144
179
|
|
|
180
|
+
## Backwards-compatibility notes (v0.3 → v0.4)
|
|
181
|
+
|
|
182
|
+
- The `StructuredDescription.open_questions` field still exists and is preserved
|
|
183
|
+
on existing tasks, but is no longer rendered in the description editor — the
|
|
184
|
+
Outstanding Questions feature replaces it. Tasks created before v0.4 keep
|
|
185
|
+
their content; new tasks have an empty `open_questions` field.
|
|
186
|
+
- `Comment` gained optional `parent_id`, `title`, `thread_status`, `anchor`,
|
|
187
|
+
`attachment_ids`. Existing comments without these fields render the same as
|
|
188
|
+
before.
|
|
189
|
+
|
|
190
|
+
## Backend
|
|
191
|
+
|
|
192
|
+
The `backend-reference/` folder contains a Python FastAPI reference implementation:
|
|
193
|
+
|
|
194
|
+
- `models/taskboard.py` — Pydantic models (Tasks / Comments / Threads /
|
|
195
|
+
Questions / Attachments + the `ThreadAnchor` schema)
|
|
196
|
+
- `api/taskboard.py` — full FastAPI router covering all v0.4 endpoints,
|
|
197
|
+
including the threads, questions, and attachments routes
|
|
198
|
+
- `services/gcs_storage.py` — Google Cloud Storage helper for file uploads.
|
|
199
|
+
Supports inline service-account env vars, `GOOGLE_APPLICATION_CREDENTIALS`,
|
|
200
|
+
and Application Default Credentials
|
|
201
|
+
- `services/config_snippet.py` — settings fields and sample `.env` values
|
|
202
|
+
|
|
203
|
+
Add `google-cloud-storage>=2.18.0` to `requirements.txt`. Without
|
|
204
|
+
`GCP_STORAGE_BUCKET` set, link attachments still work but image/file uploads
|
|
205
|
+
return a clean 503.
|
|
206
|
+
|
|
207
|
+
See [`backend-reference/README.md`](backend-reference/README.md) for the
|
|
208
|
+
adaptation guide.
|
|
209
|
+
|
|
145
210
|
## Development
|
|
146
211
|
|
|
147
212
|
```bash
|
|
@@ -151,10 +216,6 @@ npm run build # Production build
|
|
|
151
216
|
npm test # Run tests
|
|
152
217
|
```
|
|
153
218
|
|
|
154
|
-
## Backend
|
|
155
|
-
|
|
156
|
-
The `backend-reference/` folder contains a Python FastAPI reference implementation for the task board API. Copy it into your app's backend and adapt the auth and database setup to match your app. See [`backend-reference/README.md`](backend-reference/README.md) for details.
|
|
157
|
-
|
|
158
219
|
## License
|
|
159
220
|
|
|
160
221
|
Private — internal use only.
|