@cat-factory/app 0.46.12 → 0.47.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/auth/AuthGate.vue +1 -1
- package/app/components/auth/LoginScreen.vue +131 -1
- package/app/components/layout/AccountDeploymentSettings.vue +232 -5
- package/app/components/providers/ApiKeysSection.vue +27 -3
- package/app/components/providers/PersonalSubscriptionSection.vue +17 -2
- package/app/components/providers/SignInRequiredNotice.vue +19 -0
- package/app/components/settings/AccountSettingsPanel.vue +9 -6
- package/app/components/settings/IssueTrackerPanel.vue +114 -53
- package/app/components/settings/LocalModeSettingsPanel.vue +60 -28
- package/app/components/settings/LocalModelEndpointsPanel.vue +72 -27
- package/app/components/settings/MergeThresholdsPanel.vue +93 -45
- package/app/components/settings/ModelConfigurationPanel.vue +62 -36
- package/app/components/settings/ObservabilityConnectionPanel.vue +65 -35
- package/app/components/settings/OpenRouterCatalogPanel.vue +70 -40
- package/app/components/settings/ProviderConnectionPanel.vue +115 -61
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +9 -12
- package/app/components/settings/UserSecretsSection.vue +37 -18
- package/app/components/settings/WorkspaceSettingsPanel.vue +114 -62
- package/app/composables/api/auth.ts +7 -0
- package/app/stores/auth.ts +25 -1
- package/app/types/accountSettings.ts +4 -0
- package/i18n/locales/en.json +496 -0
- package/i18n/locales/es.json +490 -0
- package/i18n/locales/fr.json +490 -0
- package/i18n/locales/pl.json +490 -0
- package/i18n/locales/uk.json +490 -0
- package/package.json +2 -2
|
@@ -17,6 +17,7 @@ import type { ModelPreset } from '~/types/model-presets'
|
|
|
17
17
|
import { MODEL_CONFIGURABLE_SYSTEM_KINDS } from '~/utils/catalog'
|
|
18
18
|
import { cachingLabel, contextLabel, costLabel, displayFlavor, isSelectable } from '~/stores/models'
|
|
19
19
|
|
|
20
|
+
const { t } = useI18n()
|
|
20
21
|
const ui = useUiStore()
|
|
21
22
|
const models = useModelsStore()
|
|
22
23
|
const presets = useModelPresetsStore()
|
|
@@ -83,7 +84,9 @@ const selectableModels = computed(() => {
|
|
|
83
84
|
.map((m) => {
|
|
84
85
|
const flavor = displayFlavor(m, configured)
|
|
85
86
|
const ctx = contextLabel(flavor.contextTokens)
|
|
86
|
-
const price =
|
|
87
|
+
const price =
|
|
88
|
+
costLabel(flavor) ??
|
|
89
|
+
(flavor.quotaBased ? t('settings.modelConfiguration.quota') : undefined)
|
|
87
90
|
// Surface caching in the suffix: a cache-less flavour (the Workers-AI hot path)
|
|
88
91
|
// re-bills its whole growing prompt every turn, which the user can act on.
|
|
89
92
|
const caching = cachingLabel(flavor)
|
|
@@ -134,7 +137,7 @@ async function setDefault(p: ModelPreset) {
|
|
|
134
137
|
try {
|
|
135
138
|
await presets.update(p.id, { isDefault: true })
|
|
136
139
|
} catch (e) {
|
|
137
|
-
fail('
|
|
140
|
+
fail(t('settings.modelConfiguration.toast.setDefaultFailed'), e)
|
|
138
141
|
} finally {
|
|
139
142
|
busy.value = false
|
|
140
143
|
}
|
|
@@ -145,7 +148,7 @@ async function remove(p: ModelPreset) {
|
|
|
145
148
|
try {
|
|
146
149
|
await presets.remove(p.id)
|
|
147
150
|
} catch (e) {
|
|
148
|
-
fail('
|
|
151
|
+
fail(t('settings.modelConfiguration.toast.deleteFailed'), e)
|
|
149
152
|
} finally {
|
|
150
153
|
busy.value = false
|
|
151
154
|
}
|
|
@@ -168,7 +171,7 @@ function overrideMenu(kind: AgentKind) {
|
|
|
168
171
|
return [
|
|
169
172
|
[
|
|
170
173
|
{
|
|
171
|
-
label: '
|
|
174
|
+
label: t('settings.modelConfiguration.editor.useBaseModel'),
|
|
172
175
|
icon: 'i-lucide-rotate-ccw',
|
|
173
176
|
onSelect: () => setOverride(kind, null),
|
|
174
177
|
},
|
|
@@ -190,14 +193,17 @@ function setOverride(kind: AgentKind, modelId: string | null) {
|
|
|
190
193
|
/** The label on a kind's override button: its override model, else "Base model". */
|
|
191
194
|
function overrideLabel(kind: AgentKind): string {
|
|
192
195
|
const id = editor.value?.overrides[kind]
|
|
193
|
-
return id ? modelLabel(id) : '
|
|
196
|
+
return id ? modelLabel(id) : t('settings.modelConfiguration.editor.baseModel')
|
|
194
197
|
}
|
|
195
198
|
|
|
196
199
|
async function save() {
|
|
197
200
|
const e = editor.value
|
|
198
201
|
if (!e) return
|
|
199
202
|
if (!e.name.trim()) {
|
|
200
|
-
fail(
|
|
203
|
+
fail(
|
|
204
|
+
t('settings.modelConfiguration.toast.nameRequiredTitle'),
|
|
205
|
+
new Error(t('settings.modelConfiguration.toast.nameRequiredBody')),
|
|
206
|
+
)
|
|
201
207
|
return
|
|
202
208
|
}
|
|
203
209
|
busy.value = true
|
|
@@ -219,7 +225,7 @@ async function save() {
|
|
|
219
225
|
}
|
|
220
226
|
editor.value = null
|
|
221
227
|
} catch (err) {
|
|
222
|
-
fail('
|
|
228
|
+
fail(t('settings.modelConfiguration.toast.saveFailed'), err)
|
|
223
229
|
} finally {
|
|
224
230
|
busy.value = false
|
|
225
231
|
}
|
|
@@ -251,10 +257,11 @@ function fail(title: string, e: unknown) {
|
|
|
251
257
|
<UIcon name="i-lucide-cpu" class="h-5 w-5 text-indigo-300" />
|
|
252
258
|
</div>
|
|
253
259
|
<div class="min-w-0">
|
|
254
|
-
<h1 class="truncate text-base font-semibold text-white">
|
|
260
|
+
<h1 class="truncate text-base font-semibold text-white">
|
|
261
|
+
{{ t('settings.modelConfiguration.title') }}
|
|
262
|
+
</h1>
|
|
255
263
|
<p class="truncate text-xs text-slate-500">
|
|
256
|
-
|
|
257
|
-
workspace default preset.
|
|
264
|
+
{{ t('settings.modelConfiguration.subtitle') }}
|
|
258
265
|
</p>
|
|
259
266
|
</div>
|
|
260
267
|
<UButton
|
|
@@ -266,7 +273,7 @@ function fail(title: string, e: unknown) {
|
|
|
266
273
|
class="ml-auto"
|
|
267
274
|
@click="editor = null"
|
|
268
275
|
>
|
|
269
|
-
|
|
276
|
+
{{ t('settings.modelConfiguration.back') }}
|
|
270
277
|
</UButton>
|
|
271
278
|
<UButton
|
|
272
279
|
icon="i-lucide-x"
|
|
@@ -274,7 +281,7 @@ function fail(title: string, e: unknown) {
|
|
|
274
281
|
variant="ghost"
|
|
275
282
|
size="sm"
|
|
276
283
|
:class="editor ? '' : 'ml-auto'"
|
|
277
|
-
title="
|
|
284
|
+
:title="t('settings.modelConfiguration.closeEsc')"
|
|
278
285
|
@click="open = false"
|
|
279
286
|
/>
|
|
280
287
|
</header>
|
|
@@ -285,9 +292,17 @@ function fail(title: string, e: unknown) {
|
|
|
285
292
|
<template v-if="!editor">
|
|
286
293
|
<div class="flex items-center justify-between">
|
|
287
294
|
<p class="text-sm leading-relaxed text-slate-400">
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
295
|
+
<i18n-t
|
|
296
|
+
keypath="settings.modelConfiguration.list.intro"
|
|
297
|
+
scope="global"
|
|
298
|
+
tag="span"
|
|
299
|
+
>
|
|
300
|
+
<template #baseModel>
|
|
301
|
+
<span class="text-slate-300">{{
|
|
302
|
+
t('settings.modelConfiguration.list.introBaseModel')
|
|
303
|
+
}}</span>
|
|
304
|
+
</template>
|
|
305
|
+
</i18n-t>
|
|
291
306
|
</p>
|
|
292
307
|
<UButton
|
|
293
308
|
icon="i-lucide-plus"
|
|
@@ -296,12 +311,12 @@ function fail(title: string, e: unknown) {
|
|
|
296
311
|
class="shrink-0"
|
|
297
312
|
@click="startCreate"
|
|
298
313
|
>
|
|
299
|
-
|
|
314
|
+
{{ t('settings.modelConfiguration.list.newPreset') }}
|
|
300
315
|
</UButton>
|
|
301
316
|
</div>
|
|
302
317
|
|
|
303
318
|
<p v-if="models.models.length === 0" class="py-4 text-center text-sm text-slate-500">
|
|
304
|
-
|
|
319
|
+
{{ t('settings.modelConfiguration.list.loadingCatalog') }}
|
|
305
320
|
</p>
|
|
306
321
|
|
|
307
322
|
<div v-else class="space-y-3">
|
|
@@ -313,7 +328,7 @@ function fail(title: string, e: unknown) {
|
|
|
313
328
|
<div class="flex items-center gap-2">
|
|
314
329
|
<span class="truncate text-sm font-semibold text-slate-100">{{ p.name }}</span>
|
|
315
330
|
<UBadge v-if="p.isDefault" color="primary" variant="subtle" size="xs">
|
|
316
|
-
|
|
331
|
+
{{ t('settings.modelConfiguration.list.default') }}
|
|
317
332
|
</UBadge>
|
|
318
333
|
<div class="ml-auto flex items-center gap-1">
|
|
319
334
|
<UButton
|
|
@@ -323,7 +338,7 @@ function fail(title: string, e: unknown) {
|
|
|
323
338
|
color="neutral"
|
|
324
339
|
icon="i-lucide-star"
|
|
325
340
|
:loading="busy"
|
|
326
|
-
title="
|
|
341
|
+
:title="t('settings.modelConfiguration.list.setDefaultTitle')"
|
|
327
342
|
@click="setDefault(p)"
|
|
328
343
|
/>
|
|
329
344
|
<UButton
|
|
@@ -331,7 +346,7 @@ function fail(title: string, e: unknown) {
|
|
|
331
346
|
variant="ghost"
|
|
332
347
|
color="neutral"
|
|
333
348
|
icon="i-lucide-pencil"
|
|
334
|
-
title="
|
|
349
|
+
:title="t('settings.modelConfiguration.list.editTitle')"
|
|
335
350
|
@click="startEdit(p)"
|
|
336
351
|
/>
|
|
337
352
|
<UButton
|
|
@@ -342,19 +357,26 @@ function fail(title: string, e: unknown) {
|
|
|
342
357
|
:disabled="p.isDefault"
|
|
343
358
|
:loading="busy"
|
|
344
359
|
:title="
|
|
345
|
-
p.isDefault
|
|
360
|
+
p.isDefault
|
|
361
|
+
? t('settings.modelConfiguration.list.deleteDisabledTitle')
|
|
362
|
+
: t('settings.modelConfiguration.list.deleteTitle')
|
|
346
363
|
"
|
|
347
364
|
@click="remove(p)"
|
|
348
365
|
/>
|
|
349
366
|
</div>
|
|
350
367
|
</div>
|
|
351
368
|
<div class="mt-1.5 text-[11px] text-slate-400">
|
|
352
|
-
|
|
369
|
+
{{ t('settings.modelConfiguration.list.basePrefix') }}
|
|
370
|
+
<span class="text-slate-300">{{ modelLabel(p.baseModelId) }}</span>
|
|
353
371
|
<span v-if="Object.keys(p.overrides).length">
|
|
354
|
-
·
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
372
|
+
·
|
|
373
|
+
{{
|
|
374
|
+
t(
|
|
375
|
+
'settings.modelConfiguration.list.overrideCount',
|
|
376
|
+
{ count: Object.keys(p.overrides).length },
|
|
377
|
+
Object.keys(p.overrides).length,
|
|
378
|
+
)
|
|
379
|
+
}}
|
|
358
380
|
</span>
|
|
359
381
|
</div>
|
|
360
382
|
</div>
|
|
@@ -362,7 +384,7 @@ function fail(title: string, e: unknown) {
|
|
|
362
384
|
v-if="sortedPresets.length === 0"
|
|
363
385
|
class="py-6 text-center text-sm text-slate-500"
|
|
364
386
|
>
|
|
365
|
-
|
|
387
|
+
{{ t('settings.modelConfiguration.list.empty') }}
|
|
366
388
|
</p>
|
|
367
389
|
</div>
|
|
368
390
|
</template>
|
|
@@ -374,11 +396,11 @@ function fail(title: string, e: unknown) {
|
|
|
374
396
|
<label
|
|
375
397
|
class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-slate-400"
|
|
376
398
|
>
|
|
377
|
-
|
|
399
|
+
{{ t('settings.modelConfiguration.editor.nameLabel') }}
|
|
378
400
|
</label>
|
|
379
401
|
<UInput
|
|
380
402
|
v-model="editor.name"
|
|
381
|
-
placeholder="
|
|
403
|
+
:placeholder="t('settings.modelConfiguration.editor.namePlaceholder')"
|
|
382
404
|
size="sm"
|
|
383
405
|
class="w-full"
|
|
384
406
|
/>
|
|
@@ -388,7 +410,7 @@ function fail(title: string, e: unknown) {
|
|
|
388
410
|
<label
|
|
389
411
|
class="mb-1 block text-[11px] font-semibold uppercase tracking-wide text-slate-400"
|
|
390
412
|
>
|
|
391
|
-
|
|
413
|
+
{{ t('settings.modelConfiguration.editor.baseModelLabel') }}
|
|
392
414
|
</label>
|
|
393
415
|
<UDropdownMenu
|
|
394
416
|
:items="baseMenu"
|
|
@@ -408,21 +430,21 @@ function fail(title: string, e: unknown) {
|
|
|
408
430
|
|
|
409
431
|
<label class="flex items-center gap-2 text-sm text-slate-300">
|
|
410
432
|
<UCheckbox v-model="editor.isDefault" />
|
|
411
|
-
|
|
433
|
+
{{ t('settings.modelConfiguration.editor.makeDefault') }}
|
|
412
434
|
</label>
|
|
413
435
|
</div>
|
|
414
436
|
|
|
415
437
|
<div>
|
|
416
438
|
<div class="mb-1 flex items-center justify-between">
|
|
417
439
|
<span class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
418
|
-
|
|
440
|
+
{{ t('settings.modelConfiguration.editor.perAgentOverrides') }}
|
|
419
441
|
</span>
|
|
420
442
|
</div>
|
|
421
443
|
<UInput
|
|
422
444
|
v-model="filter"
|
|
423
445
|
icon="i-lucide-search"
|
|
424
446
|
size="sm"
|
|
425
|
-
placeholder="
|
|
447
|
+
:placeholder="t('settings.modelConfiguration.editor.filterPlaceholder')"
|
|
426
448
|
class="mb-3 w-full"
|
|
427
449
|
/>
|
|
428
450
|
<div
|
|
@@ -461,17 +483,21 @@ function fail(title: string, e: unknown) {
|
|
|
461
483
|
v-if="filteredKinds.length === 0"
|
|
462
484
|
class="px-4 py-6 text-center text-sm text-slate-500"
|
|
463
485
|
>
|
|
464
|
-
|
|
486
|
+
{{ t('settings.modelConfiguration.editor.noAgentsMatch', { filter }) }}
|
|
465
487
|
</p>
|
|
466
488
|
</div>
|
|
467
489
|
</div>
|
|
468
490
|
|
|
469
491
|
<div class="flex items-center justify-end gap-2">
|
|
470
492
|
<UButton color="neutral" variant="ghost" size="sm" @click="editor = null">
|
|
471
|
-
|
|
493
|
+
{{ t('common.cancel') }}
|
|
472
494
|
</UButton>
|
|
473
495
|
<UButton color="primary" size="sm" :loading="busy" @click="save">
|
|
474
|
-
{{
|
|
496
|
+
{{
|
|
497
|
+
editor.id
|
|
498
|
+
? t('settings.modelConfiguration.editor.saveChanges')
|
|
499
|
+
: t('settings.modelConfiguration.editor.createPreset')
|
|
500
|
+
}}
|
|
475
501
|
</UButton>
|
|
476
502
|
</div>
|
|
477
503
|
</template>
|
|
@@ -8,6 +8,7 @@ import { computed, reactive, ref, watch } from 'vue'
|
|
|
8
8
|
import type { ObservabilityProviderKind } from '~/types/releaseHealth'
|
|
9
9
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
10
10
|
|
|
11
|
+
const { t } = useI18n()
|
|
11
12
|
const ui = useUiStore()
|
|
12
13
|
const store = useReleaseHealthStore()
|
|
13
14
|
const toast = useToast()
|
|
@@ -53,7 +54,7 @@ watch(
|
|
|
53
54
|
if (site) datadog.site = site
|
|
54
55
|
await store.loadIncident()
|
|
55
56
|
} catch (e) {
|
|
56
|
-
notifyError('
|
|
57
|
+
notifyError(t('settings.observabilityConnection.toast.loadFailed'), e)
|
|
57
58
|
}
|
|
58
59
|
},
|
|
59
60
|
{ immediate: true },
|
|
@@ -71,16 +72,23 @@ async function saveIncident() {
|
|
|
71
72
|
}
|
|
72
73
|
if (incidentIo.apiKey.trim()) input.incidentIo = { apiKey: incidentIo.apiKey.trim() }
|
|
73
74
|
if (!input.pagerDuty && !input.incidentIo) {
|
|
74
|
-
toast.add({
|
|
75
|
+
toast.add({
|
|
76
|
+
title: t('settings.observabilityConnection.toast.incidentCredsRequired'),
|
|
77
|
+
color: 'error',
|
|
78
|
+
})
|
|
75
79
|
return
|
|
76
80
|
}
|
|
77
81
|
await store.saveIncident(input)
|
|
78
82
|
pagerDuty.apiToken = ''
|
|
79
83
|
pagerDuty.fromEmail = ''
|
|
80
84
|
incidentIo.apiKey = ''
|
|
81
|
-
toast.add({
|
|
85
|
+
toast.add({
|
|
86
|
+
title: t('settings.observabilityConnection.toast.incidentSaved'),
|
|
87
|
+
icon: 'i-lucide-check',
|
|
88
|
+
color: 'success',
|
|
89
|
+
})
|
|
82
90
|
} catch (e) {
|
|
83
|
-
notifyError('
|
|
91
|
+
notifyError(t('settings.observabilityConnection.toast.incidentSaveFailed'), e)
|
|
84
92
|
} finally {
|
|
85
93
|
incidentBusy.value = false
|
|
86
94
|
}
|
|
@@ -91,7 +99,7 @@ async function disconnectIncident() {
|
|
|
91
99
|
try {
|
|
92
100
|
await store.removeIncident()
|
|
93
101
|
} catch (e) {
|
|
94
|
-
notifyError('
|
|
102
|
+
notifyError(t('settings.observabilityConnection.toast.incidentDisconnectFailed'), e)
|
|
95
103
|
} finally {
|
|
96
104
|
incidentBusy.value = false
|
|
97
105
|
}
|
|
@@ -106,9 +114,13 @@ async function saveConnection() {
|
|
|
106
114
|
})
|
|
107
115
|
datadog.apiKey = ''
|
|
108
116
|
datadog.appKey = ''
|
|
109
|
-
toast.add({
|
|
117
|
+
toast.add({
|
|
118
|
+
title: t('settings.observabilityConnection.toast.connected'),
|
|
119
|
+
icon: 'i-lucide-check',
|
|
120
|
+
color: 'success',
|
|
121
|
+
})
|
|
110
122
|
} catch (e) {
|
|
111
|
-
notifyError('
|
|
123
|
+
notifyError(t('settings.observabilityConnection.toast.connectFailed'), e)
|
|
112
124
|
} finally {
|
|
113
125
|
busy.value = false
|
|
114
126
|
}
|
|
@@ -119,50 +131,62 @@ async function disconnect() {
|
|
|
119
131
|
try {
|
|
120
132
|
await store.removeConnection()
|
|
121
133
|
} catch (e) {
|
|
122
|
-
notifyError('
|
|
134
|
+
notifyError(t('settings.observabilityConnection.toast.disconnectFailed'), e)
|
|
123
135
|
} finally {
|
|
124
136
|
busy.value = false
|
|
125
137
|
}
|
|
126
138
|
}
|
|
127
139
|
|
|
128
140
|
const connectedLabel = computed(() => {
|
|
129
|
-
if (!store.connection.connected) return '
|
|
141
|
+
if (!store.connection.connected) return t('settings.observabilityConnection.status.notConnected')
|
|
130
142
|
const site = store.connection.summary?.site
|
|
131
|
-
return site
|
|
143
|
+
return site
|
|
144
|
+
? t('settings.observabilityConnection.status.connectedWithSite', { site })
|
|
145
|
+
: t('settings.observabilityConnection.status.connected')
|
|
132
146
|
})
|
|
133
147
|
</script>
|
|
134
148
|
|
|
135
149
|
<template>
|
|
136
|
-
<UModal
|
|
150
|
+
<UModal
|
|
151
|
+
v-model:open="open"
|
|
152
|
+
:title="t('settings.observabilityConnection.title')"
|
|
153
|
+
:ui="{ content: 'max-w-lg' }"
|
|
154
|
+
>
|
|
137
155
|
<template #title>
|
|
138
|
-
<IntegrationBackTitle title="
|
|
156
|
+
<IntegrationBackTitle :title="t('settings.observabilityConnection.title')" @back="back" />
|
|
139
157
|
</template>
|
|
140
158
|
<template #body>
|
|
141
159
|
<div class="space-y-4">
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
160
|
+
<i18n-t
|
|
161
|
+
keypath="settings.observabilityConnection.intro"
|
|
162
|
+
tag="p"
|
|
163
|
+
class="text-sm text-slate-400"
|
|
164
|
+
scope="global"
|
|
165
|
+
>
|
|
166
|
+
<template #gate>
|
|
167
|
+
<code>post-release-health</code>
|
|
168
|
+
</template>
|
|
169
|
+
</i18n-t>
|
|
148
170
|
|
|
149
171
|
<section class="space-y-3 rounded-lg border border-slate-700 p-3">
|
|
150
172
|
<div class="flex items-center justify-between">
|
|
151
|
-
<h3 class="text-sm font-semibold">
|
|
173
|
+
<h3 class="text-sm font-semibold">
|
|
174
|
+
{{ t('settings.observabilityConnection.connection.heading') }}
|
|
175
|
+
</h3>
|
|
152
176
|
<UBadge :color="store.connection.connected ? 'success' : 'neutral'" variant="soft">
|
|
153
177
|
{{ connectedLabel }}
|
|
154
178
|
</UBadge>
|
|
155
179
|
</div>
|
|
156
180
|
|
|
157
|
-
<UFormField label="
|
|
181
|
+
<UFormField :label="t('settings.observabilityConnection.connection.provider')">
|
|
158
182
|
<USelect v-model="provider" :items="PROVIDERS" value-key="value" class="w-full" />
|
|
159
183
|
</UFormField>
|
|
160
184
|
|
|
161
185
|
<template v-if="provider === 'datadog'">
|
|
162
|
-
<UFormField label="
|
|
186
|
+
<UFormField :label="t('settings.observabilityConnection.datadog.site')">
|
|
163
187
|
<UInput v-model="datadog.site" placeholder="datadoghq.com" class="w-full" />
|
|
164
188
|
</UFormField>
|
|
165
|
-
<UFormField label="
|
|
189
|
+
<UFormField :label="t('settings.observabilityConnection.datadog.apiKey')">
|
|
166
190
|
<UInput
|
|
167
191
|
v-model="datadog.apiKey"
|
|
168
192
|
type="password"
|
|
@@ -170,7 +194,7 @@ const connectedLabel = computed(() => {
|
|
|
170
194
|
class="w-full"
|
|
171
195
|
/>
|
|
172
196
|
</UFormField>
|
|
173
|
-
<UFormField label="
|
|
197
|
+
<UFormField :label="t('settings.observabilityConnection.datadog.appKey')">
|
|
174
198
|
<UInput
|
|
175
199
|
v-model="datadog.appKey"
|
|
176
200
|
type="password"
|
|
@@ -186,7 +210,7 @@ const connectedLabel = computed(() => {
|
|
|
186
210
|
:disabled="!datadog.apiKey || !datadog.appKey"
|
|
187
211
|
@click="saveConnection"
|
|
188
212
|
>
|
|
189
|
-
|
|
213
|
+
{{ t('settings.observabilityConnection.saveConnection') }}
|
|
190
214
|
</UButton>
|
|
191
215
|
<UButton
|
|
192
216
|
v-if="store.connection.connected"
|
|
@@ -195,7 +219,7 @@ const connectedLabel = computed(() => {
|
|
|
195
219
|
:loading="busy"
|
|
196
220
|
@click="disconnect"
|
|
197
221
|
>
|
|
198
|
-
|
|
222
|
+
{{ t('settings.observabilityConnection.disconnect') }}
|
|
199
223
|
</UButton>
|
|
200
224
|
</div>
|
|
201
225
|
</section>
|
|
@@ -207,21 +231,25 @@ const connectedLabel = computed(() => {
|
|
|
207
231
|
class="space-y-3 rounded-lg border border-slate-700 p-3"
|
|
208
232
|
>
|
|
209
233
|
<div class="flex items-center justify-between">
|
|
210
|
-
<h3 class="text-sm font-semibold">
|
|
234
|
+
<h3 class="text-sm font-semibold">
|
|
235
|
+
{{ t('settings.observabilityConnection.incident.heading') }}
|
|
236
|
+
</h3>
|
|
211
237
|
<UBadge :color="store.incident.connected ? 'success' : 'neutral'" variant="soft">
|
|
212
|
-
{{
|
|
238
|
+
{{
|
|
239
|
+
store.incident.connected
|
|
240
|
+
? t('settings.observabilityConnection.incident.configured')
|
|
241
|
+
: t('settings.observabilityConnection.incident.notSet')
|
|
242
|
+
}}
|
|
213
243
|
</UBadge>
|
|
214
244
|
</div>
|
|
215
245
|
<p class="text-[11px] text-slate-400">
|
|
216
|
-
|
|
217
|
-
systems ALREADY opened from the same signals (annotate, never re-alert). Secrets are
|
|
218
|
-
write-only — blank leaves a stored value unchanged.
|
|
246
|
+
{{ t('settings.observabilityConnection.incident.description') }}
|
|
219
247
|
</p>
|
|
220
248
|
|
|
221
|
-
<UFormField label="
|
|
249
|
+
<UFormField :label="t('settings.observabilityConnection.incident.pagerDutyToken')">
|
|
222
250
|
<UInput v-model="pagerDuty.apiToken" type="password" class="w-full" />
|
|
223
251
|
</UFormField>
|
|
224
|
-
<UFormField label="
|
|
252
|
+
<UFormField :label="t('settings.observabilityConnection.incident.pagerDutyFromEmail')">
|
|
225
253
|
<UInput
|
|
226
254
|
v-model="pagerDuty.fromEmail"
|
|
227
255
|
type="email"
|
|
@@ -229,12 +257,14 @@ const connectedLabel = computed(() => {
|
|
|
229
257
|
class="w-full"
|
|
230
258
|
/>
|
|
231
259
|
</UFormField>
|
|
232
|
-
<UFormField label="incident.
|
|
260
|
+
<UFormField :label="t('settings.observabilityConnection.incident.incidentIoKey')">
|
|
233
261
|
<UInput v-model="incidentIo.apiKey" type="password" class="w-full" />
|
|
234
262
|
</UFormField>
|
|
235
263
|
|
|
236
264
|
<div class="flex gap-2">
|
|
237
|
-
<UButton :loading="incidentBusy" @click="saveIncident">
|
|
265
|
+
<UButton :loading="incidentBusy" @click="saveIncident">
|
|
266
|
+
{{ t('common.save') }}
|
|
267
|
+
</UButton>
|
|
238
268
|
<UButton
|
|
239
269
|
v-if="store.incident.connected"
|
|
240
270
|
color="error"
|
|
@@ -242,7 +272,7 @@ const connectedLabel = computed(() => {
|
|
|
242
272
|
:loading="incidentBusy"
|
|
243
273
|
@click="disconnectIncident"
|
|
244
274
|
>
|
|
245
|
-
|
|
275
|
+
{{ t('settings.observabilityConnection.incident.clear') }}
|
|
246
276
|
</UButton>
|
|
247
277
|
</div>
|
|
248
278
|
</section>
|