@cat-factory/app 0.26.3 → 0.26.5
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.
|
@@ -343,8 +343,11 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
343
343
|
<div class="space-y-3 p-4">
|
|
344
344
|
<!-- frame header (doubles as the drag handle for the expanded frame) -->
|
|
345
345
|
<div class="flex items-start justify-between gap-2">
|
|
346
|
+
<!-- `nopan` stops Vue Flow's pane from panning on a left-drag that starts on
|
|
347
|
+
this handle (it pans via d3-zoom's mousedown, which our pointerdown
|
|
348
|
+
stopPropagation can't intercept), so the grab drives the frame move. -->
|
|
346
349
|
<div
|
|
347
|
-
class="flex cursor-grab items-center gap-2 active:cursor-grabbing"
|
|
350
|
+
class="nopan flex cursor-grab items-center gap-2 active:cursor-grabbing"
|
|
348
351
|
title="Drag service"
|
|
349
352
|
@pointerdown="onFrameHandle"
|
|
350
353
|
>
|
|
@@ -428,19 +431,21 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
428
431
|
<UIcon name="i-lucide-plus" class="h-3.5 w-3.5" /> Add the first task
|
|
429
432
|
</button>
|
|
430
433
|
|
|
431
|
-
<!-- resize handles (drag the borders to resize the service, Miro-style)
|
|
434
|
+
<!-- resize handles (drag the borders to resize the service, Miro-style).
|
|
435
|
+
`nopan` (alongside `nodrag`) so the pane doesn't pan while resizing —
|
|
436
|
+
same reason as the header handle above. -->
|
|
432
437
|
<div
|
|
433
|
-
class="nodrag absolute right-0 top-0 h-full w-2 cursor-ew-resize hover:bg-sky-400/20"
|
|
438
|
+
class="nodrag nopan absolute right-0 top-0 h-full w-2 cursor-ew-resize hover:bg-sky-400/20"
|
|
434
439
|
title="Drag to resize"
|
|
435
440
|
@pointerdown="onResize($event, 'e')"
|
|
436
441
|
/>
|
|
437
442
|
<div
|
|
438
|
-
class="nodrag absolute bottom-0 left-0 h-2 w-full cursor-ns-resize hover:bg-sky-400/20"
|
|
443
|
+
class="nodrag nopan absolute bottom-0 left-0 h-2 w-full cursor-ns-resize hover:bg-sky-400/20"
|
|
439
444
|
title="Drag to resize"
|
|
440
445
|
@pointerdown="onResize($event, 's')"
|
|
441
446
|
/>
|
|
442
447
|
<div
|
|
443
|
-
class="nodrag absolute bottom-0 right-0 h-4 w-4 cursor-nwse-resize"
|
|
448
|
+
class="nodrag nopan absolute bottom-0 right-0 h-4 w-4 cursor-nwse-resize"
|
|
444
449
|
title="Drag to resize"
|
|
445
450
|
@pointerdown="onResize($event, 'se')"
|
|
446
451
|
>
|
|
@@ -34,9 +34,9 @@ function onHandle(e: PointerEvent) {
|
|
|
34
34
|
pointerEvents: draggingId === taskId ? 'none' : undefined,
|
|
35
35
|
}"
|
|
36
36
|
>
|
|
37
|
-
<!-- drag handle -->
|
|
37
|
+
<!-- drag handle (`nopan` so the pane doesn't pan on a left-drag from here) -->
|
|
38
38
|
<div
|
|
39
|
-
class="nodrag flex cursor-grab items-center justify-center rounded-t-lg border border-b-0 border-slate-700 bg-slate-800/80 py-px active:cursor-grabbing"
|
|
39
|
+
class="nodrag nopan flex cursor-grab items-center justify-center rounded-t-lg border border-b-0 border-slate-700 bg-slate-800/80 py-px active:cursor-grabbing"
|
|
40
40
|
title="Drag task"
|
|
41
41
|
@pointerdown="onHandle"
|
|
42
42
|
>
|
|
@@ -48,9 +48,9 @@ function onResize(e: PointerEvent, edge: 'e' | 's' | 'se') {
|
|
|
48
48
|
zIndex: draggingId === moduleId ? 50 : 5,
|
|
49
49
|
}"
|
|
50
50
|
>
|
|
51
|
-
<!-- module header / drag handle -->
|
|
51
|
+
<!-- module header / drag handle (`nopan` so a left-drag moves it, not the pane) -->
|
|
52
52
|
<div
|
|
53
|
-
class="nodrag flex h-[30px] cursor-grab items-center gap-1 rounded-t-xl bg-violet-500/15 px-2 active:cursor-grabbing"
|
|
53
|
+
class="nodrag nopan flex h-[30px] cursor-grab items-center gap-1 rounded-t-xl bg-violet-500/15 px-2 active:cursor-grabbing"
|
|
54
54
|
@pointerdown="onHandle"
|
|
55
55
|
@click.stop="ui.select(moduleId)"
|
|
56
56
|
>
|
|
@@ -73,19 +73,20 @@ function onResize(e: PointerEvent, edge: 'e' | 's' | 'se') {
|
|
|
73
73
|
<DraggableTask v-for="t in tasks" :key="t.id" :task-id="t.id" />
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
|
-
<!-- resize handles (drag the borders to resize the module, Miro-style)
|
|
76
|
+
<!-- resize handles (drag the borders to resize the module, Miro-style).
|
|
77
|
+
`nopan` (with `nodrag`) so resizing doesn't pan the pane. -->
|
|
77
78
|
<div
|
|
78
|
-
class="nodrag absolute right-0 top-0 h-full w-2 cursor-ew-resize hover:bg-violet-400/20"
|
|
79
|
+
class="nodrag nopan absolute right-0 top-0 h-full w-2 cursor-ew-resize hover:bg-violet-400/20"
|
|
79
80
|
title="Drag to resize"
|
|
80
81
|
@pointerdown="onResize($event, 'e')"
|
|
81
82
|
/>
|
|
82
83
|
<div
|
|
83
|
-
class="nodrag absolute bottom-0 left-0 h-2 w-full cursor-ns-resize hover:bg-violet-400/20"
|
|
84
|
+
class="nodrag nopan absolute bottom-0 left-0 h-2 w-full cursor-ns-resize hover:bg-violet-400/20"
|
|
84
85
|
title="Drag to resize"
|
|
85
86
|
@pointerdown="onResize($event, 's')"
|
|
86
87
|
/>
|
|
87
88
|
<div
|
|
88
|
-
class="nodrag absolute bottom-0 right-0 h-4 w-4 cursor-nwse-resize"
|
|
89
|
+
class="nodrag nopan absolute bottom-0 right-0 h-4 w-4 cursor-nwse-resize"
|
|
89
90
|
title="Drag to resize"
|
|
90
91
|
@pointerdown="onResize($event, 'se')"
|
|
91
92
|
>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
// Import an issue from a connected task source (by key or URL)
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
2
|
+
// Import an issue from a connected task source (by key or URL). An imported issue
|
|
3
|
+
// can be attached to an existing task for context from the inspector (see
|
|
4
|
+
// TaskContextIssues.vue), or turned into a new board task here: pick a container
|
|
5
|
+
// (service frame or module), then click a search hit to open the prefilled
|
|
6
|
+
// add-task form (title seeded, issue staged as linked context) where the user
|
|
7
|
+
// confirms the pipeline / presets before creating it. A separate icon button on
|
|
8
|
+
// each row opens the issue on GitHub.
|
|
9
9
|
import type { TaskSearchResult, TaskSourceKind } from '~/types/domain'
|
|
10
10
|
import type { AddTaskPrefill } from '~/stores/ui'
|
|
11
11
|
|
|
@@ -85,10 +85,6 @@ const freshHits = computed(() =>
|
|
|
85
85
|
searchResults.value.filter((r) => !importedIds.value.has(r.externalId)),
|
|
86
86
|
)
|
|
87
87
|
|
|
88
|
-
const sourceTasks = computed(() =>
|
|
89
|
-
source.value ? tasks.tasks.filter((t) => t.source === source.value) : [],
|
|
90
|
-
)
|
|
91
|
-
|
|
92
88
|
// Containers a new task can be created in: every service frame and module on the
|
|
93
89
|
// board. Modules are labelled with their parent frame so the choice is unambiguous.
|
|
94
90
|
const containerItems = computed(() =>
|
|
@@ -262,7 +258,7 @@ async function doSpawnEpic() {
|
|
|
262
258
|
<!-- Container for epic children when spawning from a pasted ref (the shared
|
|
263
259
|
"Create tasks in" selector below covers the search-results case). -->
|
|
264
260
|
<UFormField
|
|
265
|
-
v-if="containerItems.length && !freshHits.length
|
|
261
|
+
v-if="containerItems.length && !freshHits.length"
|
|
266
262
|
label="Epic children container"
|
|
267
263
|
class="w-72"
|
|
268
264
|
>
|
|
@@ -288,7 +284,7 @@ async function doSpawnEpic() {
|
|
|
288
284
|
|
|
289
285
|
<!-- Shared target container for every "Create task" action below. -->
|
|
290
286
|
<UFormField
|
|
291
|
-
v-if="containerItems.length &&
|
|
287
|
+
v-if="containerItems.length && freshHits.length"
|
|
292
288
|
label="Create tasks in"
|
|
293
289
|
class="w-72"
|
|
294
290
|
>
|
|
@@ -300,7 +296,7 @@ async function doSpawnEpic() {
|
|
|
300
296
|
/>
|
|
301
297
|
</UFormField>
|
|
302
298
|
<p
|
|
303
|
-
v-else-if="!containerItems.length &&
|
|
299
|
+
v-else-if="!containerItems.length && freshHits.length"
|
|
304
300
|
class="text-[11px] text-slate-500"
|
|
305
301
|
>
|
|
306
302
|
Add a service frame to the board first to create tasks from issues.
|
|
@@ -352,52 +348,11 @@ async function doSpawnEpic() {
|
|
|
352
348
|
</div>
|
|
353
349
|
</div>
|
|
354
350
|
|
|
355
|
-
<!-- List of already-imported issues -->
|
|
356
|
-
<div v-if="sourceTasks.length" class="space-y-2">
|
|
357
|
-
<h3 class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
358
|
-
Imported issues
|
|
359
|
-
</h3>
|
|
360
|
-
<div
|
|
361
|
-
v-for="task in sourceTasks"
|
|
362
|
-
:key="`${task.source}:${task.externalId}`"
|
|
363
|
-
class="flex items-start justify-between gap-2 rounded-lg border border-slate-800 bg-slate-900/60 p-3 transition-colors hover:border-primary-500/60 hover:bg-slate-900"
|
|
364
|
-
>
|
|
365
|
-
<button
|
|
366
|
-
type="button"
|
|
367
|
-
class="min-w-0 flex-1 text-left disabled:cursor-not-allowed disabled:opacity-60"
|
|
368
|
-
:disabled="!containerId"
|
|
369
|
-
:title="containerId ? 'Create a task from this issue' : 'Pick a container first'"
|
|
370
|
-
@click="selectIssue(task, false)"
|
|
371
|
-
>
|
|
372
|
-
<span class="block truncate text-sm font-medium text-white">
|
|
373
|
-
{{ task.externalId }} · {{ task.title }}
|
|
374
|
-
</span>
|
|
375
|
-
<span class="mt-0.5 line-clamp-2 block text-xs text-slate-500">{{
|
|
376
|
-
task.excerpt
|
|
377
|
-
}}</span>
|
|
378
|
-
</button>
|
|
379
|
-
<div class="flex shrink-0 items-center gap-2">
|
|
380
|
-
<UBadge color="neutral" variant="soft" size="xs">
|
|
381
|
-
{{ task.status }}
|
|
382
|
-
</UBadge>
|
|
383
|
-
<UButton
|
|
384
|
-
color="neutral"
|
|
385
|
-
variant="ghost"
|
|
386
|
-
size="xs"
|
|
387
|
-
icon="i-lucide-external-link"
|
|
388
|
-
:to="task.url"
|
|
389
|
-
target="_blank"
|
|
390
|
-
rel="noopener"
|
|
391
|
-
:aria-label="`View ${task.externalId} on GitHub`"
|
|
392
|
-
/>
|
|
393
|
-
</div>
|
|
394
|
-
</div>
|
|
395
|
-
</div>
|
|
396
351
|
<p
|
|
397
|
-
v-
|
|
352
|
+
v-if="!freshHits.length && !searchQuery.trim()"
|
|
398
353
|
class="text-center text-xs text-slate-500"
|
|
399
354
|
>
|
|
400
|
-
|
|
355
|
+
Search above, or paste an issue URL/key to create a task from it.
|
|
401
356
|
</p>
|
|
402
357
|
</div>
|
|
403
358
|
</template>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.5",
|
|
4
4
|
"description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|