@cat-factory/app 0.250.0 → 0.251.0
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/documents/DocumentSyncState.logic.spec.ts +16 -2
- package/app/components/documents/DocumentSyncState.logic.ts +27 -1
- package/app/components/documents/DocumentSyncState.vue +23 -1
- package/app/stores/documents.spec.ts +1 -0
- package/app/types/documents.ts +1 -0
- package/i18n/locales/de.json +5 -0
- package/i18n/locales/en.json +5 -0
- package/i18n/locales/es.json +5 -0
- package/i18n/locales/fr.json +5 -0
- package/i18n/locales/he.json +5 -0
- package/i18n/locales/it.json +5 -0
- package/i18n/locales/ja.json +5 -0
- package/i18n/locales/pl.json +5 -0
- package/i18n/locales/tr.json +5 -0
- package/i18n/locales/uk.json +5 -0
- package/package.json +2 -2
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
documentFreshnessChangeSchema,
|
|
4
|
+
documentFreshnessGapSchema,
|
|
5
|
+
documentRenderStatusSchema,
|
|
6
|
+
} from '@cat-factory/contracts'
|
|
3
7
|
import { missingI18nKeys } from '../../../test/i18nKeys'
|
|
4
|
-
import { CHANGE_KEYS, GAP_KEYS } from './DocumentSyncState.logic'
|
|
8
|
+
import { CHANGE_KEYS, GAP_KEYS, RENDER_STATUS_KEYS } from './DocumentSyncState.logic'
|
|
5
9
|
|
|
6
10
|
/**
|
|
7
11
|
* The half of these tables' correctness that no guard can see.
|
|
@@ -24,10 +28,20 @@ describe('DocumentSyncState freshness tables', () => {
|
|
|
24
28
|
expect(missingI18nKeys(Object.values(CHANGE_KEYS))).toEqual([])
|
|
25
29
|
})
|
|
26
30
|
|
|
31
|
+
it('names a key the base catalog holds for every render status that states one', () => {
|
|
32
|
+
// The `null` half is deliberate (see the table): only the statuses that name a FIX render.
|
|
33
|
+
expect(missingI18nKeys(Object.values(RENDER_STATUS_KEYS).filter((k) => k !== null))).toEqual([])
|
|
34
|
+
})
|
|
35
|
+
|
|
27
36
|
it('covers exactly the contracts vocabularies, with no entry for a member that is gone', () => {
|
|
28
37
|
expect(Object.keys(GAP_KEYS).sort()).toEqual([...documentFreshnessGapSchema.options].sort())
|
|
29
38
|
expect(Object.keys(CHANGE_KEYS).sort()).toEqual(
|
|
30
39
|
[...documentFreshnessChangeSchema.options].sort(),
|
|
31
40
|
)
|
|
41
|
+
// A new render status has to be CLASSIFIED (a key or an explicit null), never omitted into
|
|
42
|
+
// silence: an unclassified one would render nothing and read as "the images are fine".
|
|
43
|
+
expect(Object.keys(RENDER_STATUS_KEYS).sort()).toEqual(
|
|
44
|
+
[...documentRenderStatusSchema.options].sort(),
|
|
45
|
+
)
|
|
32
46
|
})
|
|
33
47
|
})
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
DocumentFreshnessChange,
|
|
3
|
+
DocumentFreshnessGap,
|
|
4
|
+
DocumentRenderStatus,
|
|
5
|
+
} from '~/types/domain'
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
8
|
* The i18n keys `DocumentSyncState` renders a freshness verdict through, in their own module so a
|
|
@@ -36,3 +40,25 @@ export const CHANGE_KEYS = {
|
|
|
36
40
|
reimported: 'documents.freshness.change.reimported',
|
|
37
41
|
revision_only: 'documents.freshness.change.revision_only',
|
|
38
42
|
} as const satisfies Record<DocumentFreshnessChange, string>
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* What became of a design document's rendered images, for the three statuses that ask something of
|
|
46
|
+
* a person, and `null` for the two that do not.
|
|
47
|
+
*
|
|
48
|
+
* A design import retains its frames as reference images, and every way of failing to renders as
|
|
49
|
+
* the same absence: no picture. `stored` and `none` are the states nothing can be done about
|
|
50
|
+
* ("they are there" and "the design had none"), so they say nothing on an eleven-pixel line already
|
|
51
|
+
* carrying a stamp, a verdict and a button. The other three each name a DIFFERENT fix, which is
|
|
52
|
+
* exactly why they are worth the room: configure image storage, or retry a source that would not
|
|
53
|
+
* render.
|
|
54
|
+
*
|
|
55
|
+
* `null` here rather than an omitted key so the `satisfies` still spans the whole vocabulary: a new
|
|
56
|
+
* status has to be classified rather than falling silently into the unremarkable half.
|
|
57
|
+
*/
|
|
58
|
+
export const RENDER_STATUS_KEYS = {
|
|
59
|
+
stored: null,
|
|
60
|
+
none: null,
|
|
61
|
+
partial: 'documents.renders.partial',
|
|
62
|
+
failed: 'documents.renders.failed',
|
|
63
|
+
storage_unavailable: 'documents.renders.storage_unavailable',
|
|
64
|
+
} as const satisfies Record<DocumentRenderStatus, string | null>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { isConnectableSource } from '@cat-factory/contracts'
|
|
3
3
|
import type { SourceDocument } from '~/types/domain'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CHANGE_KEYS,
|
|
6
|
+
GAP_KEYS,
|
|
7
|
+
RENDER_STATUS_KEYS,
|
|
8
|
+
} from '~/components/documents/DocumentSyncState.logic'
|
|
5
9
|
|
|
6
10
|
// When a stored document was last written, and a way to ask its source whether that is still the
|
|
7
11
|
// current revision.
|
|
@@ -129,6 +133,20 @@ const detail = computed(() =>
|
|
|
129
133
|
.join(' · '),
|
|
130
134
|
)
|
|
131
135
|
|
|
136
|
+
/**
|
|
137
|
+
* What became of the design's rendered images, when that is something a person can act on.
|
|
138
|
+
*
|
|
139
|
+
* A THIRD fact beside the two above, and separate for the same reason they are separate from each
|
|
140
|
+
* other: it is about the pictures rather than the text, it is written by the import rather than by
|
|
141
|
+
* a click, and folding it into either would make an absent image read as a stale body. It renders
|
|
142
|
+
* only for the statuses that name a fix, so the common case adds nothing to the line.
|
|
143
|
+
*/
|
|
144
|
+
const renders = computed(() => {
|
|
145
|
+
const status = props.doc.renderStatus
|
|
146
|
+
const key = status ? RENDER_STATUS_KEYS[status] : null
|
|
147
|
+
return key ? t(key) : ''
|
|
148
|
+
})
|
|
149
|
+
|
|
132
150
|
const TONE_CLASS: Record<Stated['tone'], string> = {
|
|
133
151
|
ok: 'text-emerald-400',
|
|
134
152
|
warn: 'text-amber-400',
|
|
@@ -165,6 +183,10 @@ async function refresh() {
|
|
|
165
183
|
<UIcon :name="stated.icon" class="h-3 w-3 shrink-0" />
|
|
166
184
|
<span class="truncate">{{ stated.text }}</span>
|
|
167
185
|
</span>
|
|
186
|
+
<span v-if="renders" class="flex min-w-0 items-center gap-1 text-slate-500" :title="renders">
|
|
187
|
+
<UIcon name="i-lucide-image-off" class="h-3 w-3 shrink-0" />
|
|
188
|
+
<span class="truncate">{{ renders }}</span>
|
|
189
|
+
</span>
|
|
168
190
|
<UButton
|
|
169
191
|
v-if="askable"
|
|
170
192
|
color="neutral"
|
package/app/types/documents.ts
CHANGED
package/i18n/locales/de.json
CHANGED
|
@@ -3925,6 +3925,11 @@
|
|
|
3925
3925
|
},
|
|
3926
3926
|
"refreshFailed": "Prüfung auf Änderungen fehlgeschlagen"
|
|
3927
3927
|
},
|
|
3928
|
+
"renders": {
|
|
3929
|
+
"partial": "Einige Design-Frames konnten nicht als Bilder gespeichert werden.",
|
|
3930
|
+
"failed": "Die Design-Bilder konnten nicht von der Quelle abgerufen werden.",
|
|
3931
|
+
"storage_unavailable": "Design-Bilder wurden nicht gespeichert: für diese Installation ist kein Bildspeicher konfiguriert."
|
|
3932
|
+
},
|
|
3928
3933
|
"connect": {
|
|
3929
3934
|
"title": "Quelle verbinden",
|
|
3930
3935
|
"sourceFallback": "Quelle",
|
package/i18n/locales/en.json
CHANGED
|
@@ -4448,6 +4448,11 @@
|
|
|
4448
4448
|
},
|
|
4449
4449
|
"refreshFailed": "Could not check for changes"
|
|
4450
4450
|
},
|
|
4451
|
+
"renders": {
|
|
4452
|
+
"partial": "Some design frames could not be saved as images.",
|
|
4453
|
+
"failed": "The design images could not be retrieved from the source.",
|
|
4454
|
+
"storage_unavailable": "Design images were not saved: this deployment has no image storage configured."
|
|
4455
|
+
},
|
|
4451
4456
|
"connect": {
|
|
4452
4457
|
"title": "Connect source",
|
|
4453
4458
|
"sourceFallback": "Source",
|
package/i18n/locales/es.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "No se han podido buscar cambios"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "Algunos marcos del diseño no se pudieron guardar como imágenes.",
|
|
4316
|
+
"failed": "No se pudieron obtener las imágenes del diseño desde el origen.",
|
|
4317
|
+
"storage_unavailable": "Las imágenes del diseño no se guardaron: esta instalación no tiene almacenamiento de imágenes configurado."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "Conectar fuente",
|
|
4316
4321
|
"sourceFallback": "Fuente",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "Impossible de vérifier les changements"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "Certains cadres de la maquette n'ont pas pu être enregistrés en images.",
|
|
4316
|
+
"failed": "Les images de la maquette n'ont pas pu être récupérées depuis la source.",
|
|
4317
|
+
"storage_unavailable": "Les images de la maquette n'ont pas été enregistrées : aucun stockage d'images n'est configuré pour ce déploiement."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "Connecter une source",
|
|
4316
4321
|
"sourceFallback": "Source",
|
package/i18n/locales/he.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "לא ניתן היה לבדוק שינויים"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "חלק ממסגרות העיצוב לא נשמרו כתמונות.",
|
|
4316
|
+
"failed": "לא ניתן היה לאחזר את תמונות העיצוב מהמקור.",
|
|
4317
|
+
"storage_unavailable": "תמונות העיצוב לא נשמרו: לפריסה הזו לא מוגדר אחסון תמונות."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "חבר מקור",
|
|
4316
4321
|
"sourceFallback": "מקור",
|
package/i18n/locales/it.json
CHANGED
|
@@ -3925,6 +3925,11 @@
|
|
|
3925
3925
|
},
|
|
3926
3926
|
"refreshFailed": "Impossibile verificare le modifiche"
|
|
3927
3927
|
},
|
|
3928
|
+
"renders": {
|
|
3929
|
+
"partial": "Alcuni frame del design non è stato possibile salvarli come immagini.",
|
|
3930
|
+
"failed": "Non è stato possibile recuperare le immagini del design dalla sorgente.",
|
|
3931
|
+
"storage_unavailable": "Le immagini del design non sono state salvate: questa installazione non ha uno spazio di archiviazione per le immagini configurato."
|
|
3932
|
+
},
|
|
3928
3933
|
"connect": {
|
|
3929
3934
|
"title": "Collega sorgente",
|
|
3930
3935
|
"sourceFallback": "Sorgente",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "変更を確認できませんでした"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "一部のデザインフレームを画像として保存できませんでした。",
|
|
4316
|
+
"failed": "ソースからデザイン画像を取得できませんでした。",
|
|
4317
|
+
"storage_unavailable": "デザイン画像は保存されていません。このデプロイには画像ストレージが設定されていません。"
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "ソースを接続",
|
|
4316
4321
|
"sourceFallback": "ソース",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "Nie udało się sprawdzić zmian"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "Niektórych ramek projektu nie udało się zapisać jako obrazy.",
|
|
4316
|
+
"failed": "Nie udało się pobrać obrazów projektu ze źródła.",
|
|
4317
|
+
"storage_unavailable": "Obrazy projektu nie zostały zapisane: to wdrożenie nie ma skonfigurowanego magazynu obrazów."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "Połącz źródło",
|
|
4316
4321
|
"sourceFallback": "Źródło",
|
package/i18n/locales/tr.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "Değişiklikler denetlenemedi"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "Bazı tasarım çerçeveleri görsel olarak kaydedilemedi.",
|
|
4316
|
+
"failed": "Tasarım görselleri kaynaktan alınamadı.",
|
|
4317
|
+
"storage_unavailable": "Tasarım görselleri kaydedilmedi: bu kurulumda yapılandırılmış bir görsel deposu yok."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "Kaynak bağla",
|
|
4316
4321
|
"sourceFallback": "Kaynak",
|
package/i18n/locales/uk.json
CHANGED
|
@@ -4311,6 +4311,11 @@
|
|
|
4311
4311
|
},
|
|
4312
4312
|
"refreshFailed": "Не вдалося перевірити зміни"
|
|
4313
4313
|
},
|
|
4314
|
+
"renders": {
|
|
4315
|
+
"partial": "Деякі кадри дизайну не вдалося зберегти як зображення.",
|
|
4316
|
+
"failed": "Не вдалося отримати зображення дизайну з джерела.",
|
|
4317
|
+
"storage_unavailable": "Зображення дизайну не збережено: у цьому розгортанні не налаштовано сховище зображень."
|
|
4318
|
+
},
|
|
4314
4319
|
"connect": {
|
|
4315
4320
|
"title": "Підключити джерело",
|
|
4316
4321
|
"sourceFallback": "Джерело",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.251.0",
|
|
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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"valibot": "^1.4.2",
|
|
41
41
|
"vue": "3.5.40",
|
|
42
42
|
"wretch": "^3.0.9",
|
|
43
|
-
"@cat-factory/contracts": "0.
|
|
43
|
+
"@cat-factory/contracts": "0.273.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@toad-contracts/testing": "0.3.2",
|