@cat-factory/app 0.110.2 → 0.110.3
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/app/components/github/AddServiceFromRepoModal.vue +11 -5
- package/app/components/layout/BoardToolbar.vue +43 -0
- package/app/components/panels/InspectorPanel.vue +22 -2
- package/app/composables/api/board.ts +9 -0
- package/app/composables/useBlockDeletion.ts +49 -1
- package/app/stores/board.ts +42 -1
- package/app/stores/services.ts +18 -0
- package/app/stores/workspace.ts +1 -0
- package/i18n/locales/de.json +13 -3
- package/i18n/locales/en.json +13 -3
- package/i18n/locales/es.json +12 -2
- package/i18n/locales/fr.json +12 -2
- package/i18n/locales/he.json +12 -2
- package/i18n/locales/it.json +13 -3
- package/i18n/locales/ja.json +12 -2
- package/i18n/locales/pl.json +12 -2
- package/i18n/locales/tr.json +12 -2
- package/i18n/locales/uk.json +12 -2
- package/package.json +2 -2
|
@@ -65,13 +65,19 @@ watch(
|
|
|
65
65
|
// The integration is on but this workspace isn't bound yet — connect first.
|
|
66
66
|
const needsGitHub = computed(() => github.available === true && !github.connected)
|
|
67
67
|
|
|
68
|
-
// Repos
|
|
69
|
-
//
|
|
70
|
-
// the
|
|
71
|
-
//
|
|
68
|
+
// Repos whose service is ALREADY mounted on THIS board can't be added again — adding here would
|
|
69
|
+
// be a no-op. A repo whose service lives on ANOTHER board in the org stays addable: adding it
|
|
70
|
+
// MOUNTS the shared service onto this board (backend `addServiceFromRepo`). Monorepos are exempt
|
|
71
|
+
// (each subdirectory is its own service). Derived from the account's catalog cross-referenced with
|
|
72
|
+
// this board's mounts (`byServiceId`), since the repo projection carries no repo→block link.
|
|
72
73
|
const onBoardIds = computed(
|
|
73
74
|
() =>
|
|
74
|
-
new Set(
|
|
75
|
+
new Set(
|
|
76
|
+
services.catalog
|
|
77
|
+
.filter((s) => services.byServiceId[s.id])
|
|
78
|
+
.map((s) => s.repoGithubId)
|
|
79
|
+
.filter((id): id is number => id != null),
|
|
80
|
+
),
|
|
75
81
|
)
|
|
76
82
|
|
|
77
83
|
// Map an available repo to a combobox item. The label carries the private/monorepo/
|
|
@@ -44,6 +44,34 @@ const mountableItems = computed(() =>
|
|
|
44
44
|
}),
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
+
async function restoreService(id: string, title: string) {
|
|
48
|
+
try {
|
|
49
|
+
await board.restoreService(id)
|
|
50
|
+
toast.add({
|
|
51
|
+
title: t('board.toast.restored', { name: title }),
|
|
52
|
+
icon: 'i-lucide-archive-restore',
|
|
53
|
+
color: 'neutral',
|
|
54
|
+
})
|
|
55
|
+
} catch (e) {
|
|
56
|
+
toast.add({
|
|
57
|
+
title: t('board.toast.restoreFailed'),
|
|
58
|
+
description: e instanceof Error ? e.message : String(e),
|
|
59
|
+
color: 'error',
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Archived services — hidden from the board but restorable here with no expiry.
|
|
65
|
+
const archivedItems = computed(() =>
|
|
66
|
+
board.archived.map((b) => ({
|
|
67
|
+
label: b.title,
|
|
68
|
+
icon: 'i-lucide-box',
|
|
69
|
+
onSelect: () => {
|
|
70
|
+
void restoreService(b.id, b.title)
|
|
71
|
+
},
|
|
72
|
+
})),
|
|
73
|
+
)
|
|
74
|
+
|
|
47
75
|
const zoomPct = computed(() => Math.round(ui.zoom * 100))
|
|
48
76
|
// Disable the zoom buttons once the camera hits a clamp (Vue Flow pins the zoom exactly
|
|
49
77
|
// at the limit, so a small epsilon guards against float drift). UX-16.
|
|
@@ -186,6 +214,21 @@ const decisionItems = computed(() =>
|
|
|
186
214
|
</UButton>
|
|
187
215
|
</UDropdownMenu>
|
|
188
216
|
|
|
217
|
+
<!-- archived services: hidden from the board, restorable with no expiry -->
|
|
218
|
+
<UDropdownMenu v-if="archivedItems.length" :items="archivedItems">
|
|
219
|
+
<UButton
|
|
220
|
+
color="neutral"
|
|
221
|
+
variant="ghost"
|
|
222
|
+
size="sm"
|
|
223
|
+
icon="i-lucide-archive"
|
|
224
|
+
:title="t('board.toolbar.archivedServices')"
|
|
225
|
+
data-testid="board-archived-services"
|
|
226
|
+
>
|
|
227
|
+
<span class="hidden sm:inline">{{ t('board.toolbar.archivedServices') }}</span>
|
|
228
|
+
<span>{{ n(archivedItems.length) }}</span>
|
|
229
|
+
</UButton>
|
|
230
|
+
</UDropdownMenu>
|
|
231
|
+
|
|
189
232
|
<!-- human-actionable notifications (merge review, pipeline complete, CI failed) -->
|
|
190
233
|
<NotificationsInbox />
|
|
191
234
|
|
|
@@ -186,10 +186,17 @@ const runMenu = computed(() => {
|
|
|
186
186
|
|
|
187
187
|
// Delegate to the shared confirm-gated deletion so the button and the keyboard shortcut
|
|
188
188
|
// (Delete/Backspace) follow the exact same prompt + optimistic-delete + rollback path.
|
|
189
|
-
const { deleteBlock } = useBlockDeletion()
|
|
189
|
+
const { deleteBlock, archiveBlock } = useBlockDeletion()
|
|
190
190
|
function remove() {
|
|
191
191
|
void deleteBlock(block.value)
|
|
192
192
|
}
|
|
193
|
+
function archive() {
|
|
194
|
+
void archiveBlock(block.value)
|
|
195
|
+
}
|
|
196
|
+
// A service (top-level frame) can be archived — hidden but restorable with no expiry.
|
|
197
|
+
const isServiceFrame = computed(
|
|
198
|
+
() => block.value?.level === 'frame' && block.value?.parentId === null,
|
|
199
|
+
)
|
|
193
200
|
|
|
194
201
|
// ---- failed agent run (bootstrap or execution) ------------------------------
|
|
195
202
|
// A block whose current run failed surfaces the shared failure banner + retry,
|
|
@@ -545,12 +552,25 @@ const showOriginalDescription = ref(false)
|
|
|
545
552
|
>
|
|
546
553
|
{{ t('panels.inspector.focus') }}
|
|
547
554
|
</UButton>
|
|
555
|
+
<UButton
|
|
556
|
+
v-if="isServiceFrame"
|
|
557
|
+
color="neutral"
|
|
558
|
+
variant="ghost"
|
|
559
|
+
size="sm"
|
|
560
|
+
icon="i-lucide-archive"
|
|
561
|
+
:class="isServiceFrame ? 'ms-auto' : ''"
|
|
562
|
+
data-testid="inspector-archive"
|
|
563
|
+
:title="t('panels.inspector.archiveService')"
|
|
564
|
+
@click="archive"
|
|
565
|
+
>
|
|
566
|
+
{{ t('panels.inspector.archiveService') }}
|
|
567
|
+
</UButton>
|
|
548
568
|
<UButton
|
|
549
569
|
color="error"
|
|
550
570
|
variant="ghost"
|
|
551
571
|
size="sm"
|
|
552
572
|
icon="i-lucide-trash-2"
|
|
553
|
-
class="ms-auto"
|
|
573
|
+
:class="isServiceFrame ? '' : 'ms-auto'"
|
|
554
574
|
data-testid="inspector-delete"
|
|
555
575
|
:title="deleteLabel"
|
|
556
576
|
@click="remove"
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
addModuleContract,
|
|
5
5
|
addServiceFromRepoContract,
|
|
6
6
|
addTaskContract,
|
|
7
|
+
archiveBlockContract,
|
|
7
8
|
assignEpicContract,
|
|
8
9
|
clonePipelineContract,
|
|
9
10
|
createPipelineContract,
|
|
@@ -14,6 +15,7 @@ import {
|
|
|
14
15
|
removeBlockContract,
|
|
15
16
|
reparentBlockContract,
|
|
16
17
|
reseedPipelineContract,
|
|
18
|
+
restoreBlockContract,
|
|
17
19
|
toggleDependencyContract,
|
|
18
20
|
updateBlockContract,
|
|
19
21
|
updatePipelineContract,
|
|
@@ -87,6 +89,13 @@ export function boardApi({ send, ws }: ApiContext) {
|
|
|
87
89
|
removeBlock: (workspaceId: string, blockId: string) =>
|
|
88
90
|
send(removeBlockContract, { pathPrefix: ws(workspaceId), pathParams: { blockId } }),
|
|
89
91
|
|
|
92
|
+
// Archive a service (hide it + its subtree, restorable with no expiry) instead of deleting.
|
|
93
|
+
archiveBlock: (workspaceId: string, blockId: string) =>
|
|
94
|
+
send(archiveBlockContract, { pathPrefix: ws(workspaceId), pathParams: { blockId } }),
|
|
95
|
+
|
|
96
|
+
restoreBlock: (workspaceId: string, blockId: string) =>
|
|
97
|
+
send(restoreBlockContract, { pathPrefix: ws(workspaceId), pathParams: { blockId } }),
|
|
98
|
+
|
|
90
99
|
toggleDependency: (workspaceId: string, blockId: string, body: { sourceId: string }) =>
|
|
91
100
|
send(toggleDependencyContract, {
|
|
92
101
|
pathPrefix: ws(workspaceId),
|
|
@@ -15,9 +15,54 @@ export function useBlockDeletion() {
|
|
|
15
15
|
const execution = useExecutionStore()
|
|
16
16
|
const ui = useUiStore()
|
|
17
17
|
const recurring = useRecurringPipelinesStore()
|
|
18
|
+
const toast = useToast()
|
|
18
19
|
const { confirm } = useConfirm()
|
|
19
20
|
const { t } = useI18n()
|
|
20
21
|
|
|
22
|
+
/** A service is any top-level frame; only services are archivable. */
|
|
23
|
+
function isService(block: Block): boolean {
|
|
24
|
+
return block.level === 'frame' && block.parentId === null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Unfinished (`status !== 'done'`) task descendants of a service — the delete blocker. */
|
|
28
|
+
function unfinishedTaskCount(block: Block): number {
|
|
29
|
+
return board.descendantsOf(block.id).filter((b) => b.level === 'task' && b.status !== 'done')
|
|
30
|
+
.length
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Archive a service: hide it (restorable with no expiry) instead of deleting. Used both as the
|
|
35
|
+
* explicit inspector action and as the automatic fallback when a service that still has
|
|
36
|
+
* unfinished work can't be deleted.
|
|
37
|
+
*/
|
|
38
|
+
async function archiveBlock(block: Block | undefined | null): Promise<boolean> {
|
|
39
|
+
if (!block || !isService(block)) return false
|
|
40
|
+
const ok = await confirm({
|
|
41
|
+
title: t('panels.inspector.confirmArchive.title'),
|
|
42
|
+
description: t('panels.inspector.confirmArchive.body', { name: block.title }),
|
|
43
|
+
confirmLabel: t('panels.inspector.archiveService'),
|
|
44
|
+
icon: 'i-lucide-archive',
|
|
45
|
+
})
|
|
46
|
+
if (!ok) return false
|
|
47
|
+
ui.select(null)
|
|
48
|
+
try {
|
|
49
|
+
await board.archiveService(block.id)
|
|
50
|
+
toast.add({
|
|
51
|
+
title: t('board.toast.archived', { name: block.title }),
|
|
52
|
+
icon: 'i-lucide-archive',
|
|
53
|
+
color: 'neutral',
|
|
54
|
+
})
|
|
55
|
+
} catch (e) {
|
|
56
|
+
toast.add({
|
|
57
|
+
title: t('board.toast.archiveFailed'),
|
|
58
|
+
description: e instanceof Error ? e.message : String(e),
|
|
59
|
+
icon: 'i-lucide-triangle-alert',
|
|
60
|
+
color: 'error',
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
21
66
|
/** Resolve the confirm title/body for a block, matching the inspector's delete-label kinds. */
|
|
22
67
|
function copyFor(block: Block): { title: string; body: string } {
|
|
23
68
|
const schedule = recurring.byBlock(block.id)
|
|
@@ -49,6 +94,9 @@ export function useBlockDeletion() {
|
|
|
49
94
|
|
|
50
95
|
async function deleteBlock(block: Block | undefined | null): Promise<boolean> {
|
|
51
96
|
if (!block) return false
|
|
97
|
+
// A service with unfinished work can't be deleted (the backend rejects it) — archive it
|
|
98
|
+
// instead. Route straight to the archive flow so the user is never handed a dead-end error.
|
|
99
|
+
if (isService(block) && unfinishedTaskCount(block) > 0) return archiveBlock(block)
|
|
52
100
|
const { title, body } = copyFor(block)
|
|
53
101
|
const ok = await confirm({
|
|
54
102
|
title,
|
|
@@ -75,5 +123,5 @@ export function useBlockDeletion() {
|
|
|
75
123
|
return true
|
|
76
124
|
}
|
|
77
125
|
|
|
78
|
-
return { deleteBlock }
|
|
126
|
+
return { deleteBlock, archiveBlock }
|
|
79
127
|
}
|
package/app/stores/board.ts
CHANGED
|
@@ -42,6 +42,10 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
42
42
|
params ?? {},
|
|
43
43
|
)
|
|
44
44
|
const blocks = ref<Block[]>([])
|
|
45
|
+
// Archived service frames (`archived === true`): hidden from the board but preserved and
|
|
46
|
+
// restorable with no expiry. Hydrated from the snapshot's `archivedServices`; the frames
|
|
47
|
+
// themselves are NOT in `blocks` (the snapshot filters an archived frame + its subtree out).
|
|
48
|
+
const archived = ref<Block[]>([])
|
|
45
49
|
|
|
46
50
|
// Pure derivations (hierarchy, status/progress, sizing) live in the composable.
|
|
47
51
|
const queries = useBlockQueries(blocks)
|
|
@@ -117,6 +121,28 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
117
121
|
blocks.value = applyPendingRemovals(reconciled)
|
|
118
122
|
}
|
|
119
123
|
|
|
124
|
+
/** Replace the archived-services list from the snapshot (absent ⇒ none). */
|
|
125
|
+
function hydrateArchived(next: Block[] = []) {
|
|
126
|
+
archived.value = [...next]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Archive a service (hide it + its subtree, restorable with no expiry) — the non-destructive
|
|
131
|
+
* alternative to deleting a service that still has unfinished tasks. The acting tab isn't
|
|
132
|
+
* echoed its own coarse board event, so re-hydrate explicitly to drop the frame from the board
|
|
133
|
+
* and surface it under the archived list.
|
|
134
|
+
*/
|
|
135
|
+
async function archiveService(id: string) {
|
|
136
|
+
await api.archiveBlock(useWorkspaceStore().requireId(), id)
|
|
137
|
+
await useWorkspaceStore().refresh()
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Restore an archived service back onto the board. Re-hydrates to pull its subtree back in. */
|
|
141
|
+
async function restoreService(id: string) {
|
|
142
|
+
await api.restoreBlock(useWorkspaceStore().requireId(), id)
|
|
143
|
+
await useWorkspaceStore().refresh()
|
|
144
|
+
}
|
|
145
|
+
|
|
120
146
|
/** Insert or replace a block returned by the backend. */
|
|
121
147
|
function upsert(block: Block) {
|
|
122
148
|
// A live event for a block awaiting its deferred delete must not resurrect it.
|
|
@@ -135,7 +161,10 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
135
161
|
/**
|
|
136
162
|
* Import an existing GitHub repo (the App is installed + it's projected) as a
|
|
137
163
|
* service frame, with no bootstrap run. The backend links the repo to the new
|
|
138
|
-
* frame and returns it `ready`; we upsert it onto the board.
|
|
164
|
+
* frame and returns it `ready`; we upsert it onto the board. When the repo already
|
|
165
|
+
* backs an org service, the backend MOUNTS that shared service here instead of
|
|
166
|
+
* minting a rival — so refresh the snapshot to pull in the shared frame's subtree
|
|
167
|
+
* + its mount layout (a fresh import has no subtree, but the reconcile is harmless).
|
|
139
168
|
*/
|
|
140
169
|
async function addServiceFromRepo(
|
|
141
170
|
repoGithubId: number,
|
|
@@ -154,6 +183,7 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
154
183
|
...(opts?.position ? { position: opts.position } : {}),
|
|
155
184
|
})
|
|
156
185
|
upsert(block)
|
|
186
|
+
await useWorkspaceStore().refresh()
|
|
157
187
|
return block
|
|
158
188
|
}
|
|
159
189
|
|
|
@@ -408,6 +438,13 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
408
438
|
// the window then leaves the run untouched instead of restoring an already-cancelled one.
|
|
409
439
|
await opts.onCommit?.(pending.wsId)
|
|
410
440
|
await api.removeBlock(pending.wsId, id)
|
|
441
|
+
// A service frame's delete also reclaims its account-owned service server-side, but this
|
|
442
|
+
// tab is not echoed its own coarse `board` event, so nothing re-hydrates the service
|
|
443
|
+
// catalog here — drop the deleted service locally so the add-service picker stops flagging
|
|
444
|
+
// its repo as "already on board" (a no-op for a task/module). Only after the commit, so a
|
|
445
|
+
// still-linked repo is never briefly presented as addable.
|
|
446
|
+
if (useWorkspaceStore().workspaceId === pending.wsId)
|
|
447
|
+
useServicesStore().dropByFrameBlock(id)
|
|
411
448
|
// Stop filtering the subtree only after the server has actually dropped it, so a
|
|
412
449
|
// snapshot that raced the in-flight delete can't briefly resurrect it.
|
|
413
450
|
for (const b of pending.snap.removed) pendingDoomed.delete(b.id)
|
|
@@ -573,7 +610,9 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
573
610
|
|
|
574
611
|
return {
|
|
575
612
|
blocks,
|
|
613
|
+
archived,
|
|
576
614
|
hydrate,
|
|
615
|
+
hydrateArchived,
|
|
577
616
|
upsert,
|
|
578
617
|
...queries,
|
|
579
618
|
addBlock,
|
|
@@ -586,6 +625,8 @@ export const useBoardStore = defineStore('board', () => {
|
|
|
586
625
|
detach,
|
|
587
626
|
reattach,
|
|
588
627
|
removeBlock,
|
|
628
|
+
archiveService,
|
|
629
|
+
restoreService,
|
|
589
630
|
previewMove,
|
|
590
631
|
moveBlock,
|
|
591
632
|
updateBlock,
|
package/app/stores/services.ts
CHANGED
|
@@ -46,6 +46,23 @@ export const useServicesStore = defineStore('services', () => {
|
|
|
46
46
|
return (serviceByFrameBlock.value[frameBlockId]?.mountCount ?? 0) > 1
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Drop the account-owned service (and this board's mount) backing a just-deleted frame.
|
|
51
|
+
* The acting tab is deliberately NOT echoed its own coarse `board` event (see
|
|
52
|
+
* `useWorkspaceStream`), so a service-frame delete never triggers a snapshot re-hydrate
|
|
53
|
+
* here — without this the deleted service lingers in `catalog`, which the add-service
|
|
54
|
+
* picker reads to flag a repo as "already on board", so the repo can't be re-added until
|
|
55
|
+
* a full refresh. Called once the delete has COMMITTED server-side (the service is gone),
|
|
56
|
+
* so it can never briefly present a still-linked repo as addable. A no-op for a task/module
|
|
57
|
+
* id (nothing in the catalog matches its frame).
|
|
58
|
+
*/
|
|
59
|
+
function dropByFrameBlock(frameBlockId: string) {
|
|
60
|
+
const service = catalog.value.find((s) => s.frameBlockId === frameBlockId)
|
|
61
|
+
if (!service) return
|
|
62
|
+
catalog.value = catalog.value.filter((s) => s.id !== service.id)
|
|
63
|
+
mounts.value = mounts.value.filter((m) => m.serviceId !== service.id)
|
|
64
|
+
}
|
|
65
|
+
|
|
49
66
|
async function mount(serviceId: string, position?: { x: number; y: number }) {
|
|
50
67
|
const ws = useWorkspaceStore()
|
|
51
68
|
const created = await api.mountService(ws.requireId(), serviceId, position ? { position } : {})
|
|
@@ -79,6 +96,7 @@ export const useServicesStore = defineStore('services', () => {
|
|
|
79
96
|
serviceByFrameBlock,
|
|
80
97
|
mountable,
|
|
81
98
|
isSharedFrame,
|
|
99
|
+
dropByFrameBlock,
|
|
82
100
|
hydrate,
|
|
83
101
|
mount,
|
|
84
102
|
unmount,
|
package/app/stores/workspace.ts
CHANGED
|
@@ -115,6 +115,7 @@ export const useWorkspaceStore = defineStore(
|
|
|
115
115
|
if (i >= 0) workspaces.value[i] = snapshot.workspace
|
|
116
116
|
else workspaces.value.unshift(snapshot.workspace)
|
|
117
117
|
useBoardStore().hydrate(snapshot.blocks)
|
|
118
|
+
useBoardStore().hydrateArchived(snapshot.archivedServices ?? [])
|
|
118
119
|
usePipelinesStore().hydrate(snapshot.pipelines, snapshot.pipelineCatalogVersions)
|
|
119
120
|
useExecutionStore().hydrate(snapshot.executions, snapshot.workspace.id)
|
|
120
121
|
useAgentRunsStore().hydrate(snapshot.bootstrapJobs ?? [], snapshot.workspace.id)
|
package/i18n/locales/de.json
CHANGED
|
@@ -1412,7 +1412,12 @@
|
|
|
1412
1412
|
"viewRequirements": "Anforderungen anzeigen",
|
|
1413
1413
|
"reRun": "Erneut ausführen",
|
|
1414
1414
|
"run": "Ausführen",
|
|
1415
|
-
"focus": "Fokussieren"
|
|
1415
|
+
"focus": "Fokussieren",
|
|
1416
|
+
"archiveService": "Dienst archivieren",
|
|
1417
|
+
"confirmArchive": {
|
|
1418
|
+
"title": "Diesen Dienst archivieren?",
|
|
1419
|
+
"body": "„{name}“ und seine Aufgaben werden vom Board ausgeblendet. Du kannst den Dienst jederzeit wiederherstellen."
|
|
1420
|
+
}
|
|
1416
1421
|
}
|
|
1417
1422
|
},
|
|
1418
1423
|
"layout": {
|
|
@@ -1864,7 +1869,11 @@
|
|
|
1864
1869
|
"unlinkFailed": "Abhängigkeit konnte nicht entfernt werden",
|
|
1865
1870
|
"recurringDeleteFailed": "Wiederkehrende Pipeline konnte nicht gelöscht werden",
|
|
1866
1871
|
"deleted": "\"{name}\" gelöscht",
|
|
1867
|
-
"moved": "\"{name}\" verschoben"
|
|
1872
|
+
"moved": "\"{name}\" verschoben",
|
|
1873
|
+
"archived": "Archiviert: „{name}“",
|
|
1874
|
+
"restored": "Wiederhergestellt: „{name}“",
|
|
1875
|
+
"archiveFailed": "Dienst konnte nicht archiviert werden",
|
|
1876
|
+
"restoreFailed": "Dienst konnte nicht wiederhergestellt werden"
|
|
1868
1877
|
},
|
|
1869
1878
|
"repoTypes": {
|
|
1870
1879
|
"service": "Service",
|
|
@@ -1889,7 +1898,8 @@
|
|
|
1889
1898
|
"zoomOut": "Verkleinern",
|
|
1890
1899
|
"zoomIn": "Vergrößern",
|
|
1891
1900
|
"fitView": "Board an Inhalt anpassen",
|
|
1892
|
-
"resetZoom": "Zoom auf 100 % zurücksetzen"
|
|
1901
|
+
"resetZoom": "Zoom auf 100 % zurücksetzen",
|
|
1902
|
+
"archivedServices": "Archivierte Dienste"
|
|
1893
1903
|
},
|
|
1894
1904
|
"canvas": {
|
|
1895
1905
|
"emptyTitle": "Ihr Board ist leer",
|
package/i18n/locales/en.json
CHANGED
|
@@ -124,7 +124,11 @@
|
|
|
124
124
|
"unlinkFailed": "Could not remove dependency",
|
|
125
125
|
"recurringDeleteFailed": "Could not delete recurring pipeline",
|
|
126
126
|
"deleted": "Deleted \"{name}\"",
|
|
127
|
-
"moved": "Moved \"{name}\""
|
|
127
|
+
"moved": "Moved \"{name}\"",
|
|
128
|
+
"archived": "Archived \"{name}\"",
|
|
129
|
+
"restored": "Restored \"{name}\"",
|
|
130
|
+
"archiveFailed": "Couldn't archive the service",
|
|
131
|
+
"restoreFailed": "Couldn't restore the service"
|
|
128
132
|
},
|
|
129
133
|
"repoTypes": {
|
|
130
134
|
"service": "Service",
|
|
@@ -152,7 +156,8 @@
|
|
|
152
156
|
"zoomOut": "Zoom out",
|
|
153
157
|
"zoomIn": "Zoom in",
|
|
154
158
|
"fitView": "Fit board to content",
|
|
155
|
-
"resetZoom": "Reset zoom to 100%"
|
|
159
|
+
"resetZoom": "Reset zoom to 100%",
|
|
160
|
+
"archivedServices": "Archived services"
|
|
156
161
|
},
|
|
157
162
|
"canvas": {
|
|
158
163
|
"emptyTitle": "Your board is empty",
|
|
@@ -1151,7 +1156,12 @@
|
|
|
1151
1156
|
"viewRequirements": "View Requirements",
|
|
1152
1157
|
"reRun": "Re-run",
|
|
1153
1158
|
"run": "Run",
|
|
1154
|
-
"focus": "Focus"
|
|
1159
|
+
"focus": "Focus",
|
|
1160
|
+
"archiveService": "Archive service",
|
|
1161
|
+
"confirmArchive": {
|
|
1162
|
+
"title": "Archive this service?",
|
|
1163
|
+
"body": "\"{name}\" and its tasks will be hidden from the board. You can restore it at any time."
|
|
1164
|
+
}
|
|
1155
1165
|
}
|
|
1156
1166
|
},
|
|
1157
1167
|
"observability": {
|
package/i18n/locales/es.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "No se pudo eliminar la dependencia",
|
|
110
110
|
"recurringDeleteFailed": "No se pudo eliminar el pipeline recurrente",
|
|
111
111
|
"deleted": "\"{name}\" eliminado",
|
|
112
|
-
"moved": "\"{name}\" movido"
|
|
112
|
+
"moved": "\"{name}\" movido",
|
|
113
|
+
"archived": "Archivado «{name}»",
|
|
114
|
+
"restored": "Restaurado «{name}»",
|
|
115
|
+
"archiveFailed": "No se pudo archivar el servicio",
|
|
116
|
+
"restoreFailed": "No se pudo restaurar el servicio"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "Servicio",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "Alejar",
|
|
135
139
|
"zoomIn": "Acercar",
|
|
136
140
|
"fitView": "Ajustar al contenido",
|
|
137
|
-
"resetZoom": "Restablecer zoom al 100%"
|
|
141
|
+
"resetZoom": "Restablecer zoom al 100%",
|
|
142
|
+
"archivedServices": "Servicios archivados"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "Tu tablero está vacío",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "Se eliminarán \"{name}\", su programación y su historial de ejecución. Esta acción no se puede deshacer."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "Se eliminará \"{name}\" y el {count} elemento que contiene. Esta acción no se puede deshacer. | Se eliminará \"{name}\" y los {count} elementos que contiene. Esta acción no se puede deshacer."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "Archivar servicio",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "¿Archivar este servicio?",
|
|
1109
|
+
"body": "«{name}» y sus tareas se ocultarán del tablero. Puedes restaurarlo en cualquier momento."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/fr.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "Impossible de supprimer la dépendance",
|
|
110
110
|
"recurringDeleteFailed": "Impossible de supprimer le pipeline récurrent",
|
|
111
111
|
"deleted": "\"{name}\" supprimé",
|
|
112
|
-
"moved": "\"{name}\" déplacé"
|
|
112
|
+
"moved": "\"{name}\" déplacé",
|
|
113
|
+
"archived": "Archivé « {name} »",
|
|
114
|
+
"restored": "Restauré « {name} »",
|
|
115
|
+
"archiveFailed": "Impossible d'archiver le service",
|
|
116
|
+
"restoreFailed": "Impossible de restaurer le service"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "Service",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "Dézoomer",
|
|
135
139
|
"zoomIn": "Zoomer",
|
|
136
140
|
"fitView": "Ajuster au contenu",
|
|
137
|
-
"resetZoom": "Réinitialiser le zoom à 100 %"
|
|
141
|
+
"resetZoom": "Réinitialiser le zoom à 100 %",
|
|
142
|
+
"archivedServices": "Services archivés"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "Votre tableau est vide",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "\"{name}\", sa planification et son historique d'exécution seront supprimés. Cette action est irréversible."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "\"{name}\" et le {count} élément qu'il contient seront supprimés. Cette action est irréversible. | \"{name}\" et les {count} éléments qu'il contient seront supprimés. Cette action est irréversible."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "Archiver le service",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "Archiver ce service ?",
|
|
1109
|
+
"body": "« {name} » et ses tâches seront masqués du tableau. Vous pouvez le restaurer à tout moment."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/he.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "לא ניתן להסיר את התלות",
|
|
110
110
|
"recurringDeleteFailed": "לא ניתן היה למחוק את הצינור החוזר",
|
|
111
111
|
"deleted": "\"{name}\" נמחק",
|
|
112
|
-
"moved": "\"{name}\" הועבר"
|
|
112
|
+
"moved": "\"{name}\" הועבר",
|
|
113
|
+
"archived": "הועבר לארכיון: \"{name}\"",
|
|
114
|
+
"restored": "שוחזר: \"{name}\"",
|
|
115
|
+
"archiveFailed": "לא ניתן להעביר את השירות לארכיון",
|
|
116
|
+
"restoreFailed": "לא ניתן לשחזר את השירות"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "שירות",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "הקטנה",
|
|
135
139
|
"zoomIn": "הגדלה",
|
|
136
140
|
"fitView": "התאמה לתוכן",
|
|
137
|
-
"resetZoom": "איפוס התקריב ל-100%"
|
|
141
|
+
"resetZoom": "איפוס התקריב ל-100%",
|
|
142
|
+
"archivedServices": "שירותים בארכיון"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "הלוח שלך ריק",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "\"{name}\", התזמון שלו והיסטוריית ההרצות יימחקו. לא ניתן לבטל פעולה זו."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "\"{name}\" ו-{count} פריט שבתוכו יימחקו. לא ניתן לבטל פעולה זו. | \"{name}\" ו-{count} פריטים שבתוכו יימחקו. לא ניתן לבטל פעולה זו."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "העברת שירות לארכיון",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "להעביר שירות זה לארכיון?",
|
|
1109
|
+
"body": "\"{name}\" והמשימות שלו יוסתרו מהלוח. אפשר לשחזר אותו בכל עת."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/it.json
CHANGED
|
@@ -1412,7 +1412,12 @@
|
|
|
1412
1412
|
"viewRequirements": "Visualizza requisiti",
|
|
1413
1413
|
"reRun": "Riesegui",
|
|
1414
1414
|
"run": "Esegui",
|
|
1415
|
-
"focus": "Metti a fuoco"
|
|
1415
|
+
"focus": "Metti a fuoco",
|
|
1416
|
+
"archiveService": "Archivia servizio",
|
|
1417
|
+
"confirmArchive": {
|
|
1418
|
+
"title": "Archiviare questo servizio?",
|
|
1419
|
+
"body": "\"{name}\" e le sue attività verranno nascosti dalla board. Puoi ripristinarlo in qualsiasi momento."
|
|
1420
|
+
}
|
|
1416
1421
|
}
|
|
1417
1422
|
},
|
|
1418
1423
|
"layout": {
|
|
@@ -1864,7 +1869,11 @@
|
|
|
1864
1869
|
"unlinkFailed": "Impossibile rimuovere la dipendenza",
|
|
1865
1870
|
"recurringDeleteFailed": "Impossibile eliminare la pipeline ricorrente",
|
|
1866
1871
|
"deleted": "Eliminato \"{name}\"",
|
|
1867
|
-
"moved": "Spostato \"{name}\""
|
|
1872
|
+
"moved": "Spostato \"{name}\"",
|
|
1873
|
+
"archived": "Archiviato \"{name}\"",
|
|
1874
|
+
"restored": "Ripristinato \"{name}\"",
|
|
1875
|
+
"archiveFailed": "Impossibile archiviare il servizio",
|
|
1876
|
+
"restoreFailed": "Impossibile ripristinare il servizio"
|
|
1868
1877
|
},
|
|
1869
1878
|
"repoTypes": {
|
|
1870
1879
|
"service": "Servizio",
|
|
@@ -1889,7 +1898,8 @@
|
|
|
1889
1898
|
"zoomOut": "Riduci lo zoom",
|
|
1890
1899
|
"zoomIn": "Aumenta lo zoom",
|
|
1891
1900
|
"fitView": "Adatta la board al contenuto",
|
|
1892
|
-
"resetZoom": "Reimposta lo zoom al 100%"
|
|
1901
|
+
"resetZoom": "Reimposta lo zoom al 100%",
|
|
1902
|
+
"archivedServices": "Servizi archiviati"
|
|
1893
1903
|
},
|
|
1894
1904
|
"canvas": {
|
|
1895
1905
|
"emptyTitle": "La tua board è vuota",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "依存関係を削除できませんでした",
|
|
110
110
|
"recurringDeleteFailed": "定期パイプラインを削除できませんでした",
|
|
111
111
|
"deleted": "\"{name}\" を削除しました",
|
|
112
|
-
"moved": "\"{name}\" を移動しました"
|
|
112
|
+
"moved": "\"{name}\" を移動しました",
|
|
113
|
+
"archived": "「{name}」をアーカイブしました",
|
|
114
|
+
"restored": "「{name}」を復元しました",
|
|
115
|
+
"archiveFailed": "サービスをアーカイブできませんでした",
|
|
116
|
+
"restoreFailed": "サービスを復元できませんでした"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "サービス",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "縮小",
|
|
135
139
|
"zoomIn": "拡大",
|
|
136
140
|
"fitView": "内容に合わせる",
|
|
137
|
-
"resetZoom": "ズームを100%にリセット"
|
|
141
|
+
"resetZoom": "ズームを100%にリセット",
|
|
142
|
+
"archivedServices": "アーカイブ済みサービス"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "ボードが空です",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "「{name}」、そのスケジュール、実行履歴が削除されます。この操作は取り消せません。"
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "「{name}」とその中の {count} 件の項目が削除されます。この操作は取り消せません。 | 「{name}」とその中の {count} 件の項目が削除されます。この操作は取り消せません。"
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "サービスをアーカイブ",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "このサービスをアーカイブしますか?",
|
|
1109
|
+
"body": "「{name}」とそのタスクはボードから非表示になります。いつでも復元できます。"
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/pl.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "Nie udało się usunąć zależności",
|
|
110
110
|
"recurringDeleteFailed": "Nie udało się usunąć cyklicznego pipeline'u",
|
|
111
111
|
"deleted": "Usunięto \"{name}\"",
|
|
112
|
-
"moved": "Przeniesiono \"{name}\""
|
|
112
|
+
"moved": "Przeniesiono \"{name}\"",
|
|
113
|
+
"archived": "Zarchiwizowano „{name}”",
|
|
114
|
+
"restored": "Przywrócono „{name}”",
|
|
115
|
+
"archiveFailed": "Nie udało się zarchiwizować usługi",
|
|
116
|
+
"restoreFailed": "Nie udało się przywrócić usługi"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "Usługa",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "Pomniejsz",
|
|
135
139
|
"zoomIn": "Powiększ",
|
|
136
140
|
"fitView": "Dopasuj do zawartości",
|
|
137
|
-
"resetZoom": "Zresetuj powiększenie do 100%"
|
|
141
|
+
"resetZoom": "Zresetuj powiększenie do 100%",
|
|
142
|
+
"archivedServices": "Zarchiwizowane usługi"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "Twoja tablica jest pusta",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "\"{name}\", jego harmonogram i historia uruchomień zostaną usunięte. Tej operacji nie można cofnąć."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "\"{name}\" i {count} element w środku zostaną usunięte. Tej operacji nie można cofnąć. | \"{name}\" i {count} elementy w środku zostaną usunięte. Tej operacji nie można cofnąć. | \"{name}\" i {count} elementów w środku zostanie usuniętych. Tej operacji nie można cofnąć."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "Archiwizuj usługę",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "Zarchiwizować tę usługę?",
|
|
1109
|
+
"body": "„{name}” i jej zadania zostaną ukryte z tablicy. Możesz przywrócić usługę w dowolnej chwili."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/tr.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "Bağımlılık kaldırılamadı",
|
|
110
110
|
"recurringDeleteFailed": "Yinelenen pipeline silinemedi",
|
|
111
111
|
"deleted": "\"{name}\" silindi",
|
|
112
|
-
"moved": "\"{name}\" taşındı"
|
|
112
|
+
"moved": "\"{name}\" taşındı",
|
|
113
|
+
"archived": "\"{name}\" arşivlendi",
|
|
114
|
+
"restored": "\"{name}\" geri yüklendi",
|
|
115
|
+
"archiveFailed": "Hizmet arşivlenemedi",
|
|
116
|
+
"restoreFailed": "Hizmet geri yüklenemedi"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "Servis",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "Uzaklaştır",
|
|
135
139
|
"zoomIn": "Yakınlaştır",
|
|
136
140
|
"fitView": "İçeriğe sığdır",
|
|
137
|
-
"resetZoom": "Yakınlaştırmayı %100'e sıfırla"
|
|
141
|
+
"resetZoom": "Yakınlaştırmayı %100'e sıfırla",
|
|
142
|
+
"archivedServices": "Arşivlenen hizmetler"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "Panonuz boş",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "\"{name}\", zamanlaması ve çalıştırma geçmişi kaldırılacak. Bu işlem geri alınamaz."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "\"{name}\" ve içindeki {count} öğe kaldırılacak. Bu işlem geri alınamaz. | \"{name}\" ve içindeki {count} öğe kaldırılacak. Bu işlem geri alınamaz."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "Hizmeti arşivle",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "Bu hizmet arşivlensin mi?",
|
|
1109
|
+
"body": "\"{name}\" ve görevleri panodan gizlenecek. İstediğin zaman geri yükleyebilirsin."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/i18n/locales/uk.json
CHANGED
|
@@ -109,7 +109,11 @@
|
|
|
109
109
|
"unlinkFailed": "Не вдалося видалити залежність",
|
|
110
110
|
"recurringDeleteFailed": "Не вдалося видалити повторюваний пайплайн",
|
|
111
111
|
"deleted": "\"{name}\" видалено",
|
|
112
|
-
"moved": "\"{name}\" переміщено"
|
|
112
|
+
"moved": "\"{name}\" переміщено",
|
|
113
|
+
"archived": "Заархівовано «{name}»",
|
|
114
|
+
"restored": "Відновлено «{name}»",
|
|
115
|
+
"archiveFailed": "Не вдалося заархівувати сервіс",
|
|
116
|
+
"restoreFailed": "Не вдалося відновити сервіс"
|
|
113
117
|
},
|
|
114
118
|
"repoTypes": {
|
|
115
119
|
"service": "Сервіс",
|
|
@@ -134,7 +138,8 @@
|
|
|
134
138
|
"zoomOut": "Зменшити",
|
|
135
139
|
"zoomIn": "Збільшити",
|
|
136
140
|
"fitView": "Вписати в область",
|
|
137
|
-
"resetZoom": "Скинути масштаб до 100%"
|
|
141
|
+
"resetZoom": "Скинути масштаб до 100%",
|
|
142
|
+
"archivedServices": "Архівовані сервіси"
|
|
138
143
|
},
|
|
139
144
|
"canvas": {
|
|
140
145
|
"emptyTitle": "Ваша дошка порожня",
|
|
@@ -1097,6 +1102,11 @@
|
|
|
1097
1102
|
"body": "\"{name}\", його розклад та історію запусків буде видалено. Цю дію не можна скасувати."
|
|
1098
1103
|
},
|
|
1099
1104
|
"containerBodyWithCount": "\"{name}\" і {count} елемент усередині буде видалено. Цю дію не можна скасувати. | \"{name}\" і {count} елементи всередині буде видалено. Цю дію не можна скасувати. | \"{name}\" і {count} елементів усередині буде видалено. Цю дію не можна скасувати."
|
|
1105
|
+
},
|
|
1106
|
+
"archiveService": "Архівувати сервіс",
|
|
1107
|
+
"confirmArchive": {
|
|
1108
|
+
"title": "Заархівувати цей сервіс?",
|
|
1109
|
+
"body": "«{name}» та його завдання буде приховано з дошки. Ви можете відновити його будь-коли."
|
|
1100
1110
|
}
|
|
1101
1111
|
}
|
|
1102
1112
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.110.
|
|
3
|
+
"version": "0.110.3",
|
|
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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"valibot": "^1.4.2",
|
|
35
35
|
"vue": "3.5.39",
|
|
36
36
|
"wretch": "^3.0.9",
|
|
37
|
-
"@cat-factory/contracts": "0.123.
|
|
37
|
+
"@cat-factory/contracts": "0.123.1"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|