@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
|
@@ -9,6 +9,7 @@ import { computed, ref, watch } from 'vue'
|
|
|
9
9
|
import { LOCAL_RUNNER_DEFAULTS, LOCAL_RUNNER_LABELS, type LocalRunner } from '~/types/localModels'
|
|
10
10
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
11
11
|
|
|
12
|
+
const { t } = useI18n()
|
|
12
13
|
const ui = useUiStore()
|
|
13
14
|
const store = useLocalModelsStore()
|
|
14
15
|
const toast = useToast()
|
|
@@ -95,7 +96,7 @@ async function test() {
|
|
|
95
96
|
selected.value = keep.length ? keep : [...result.models]
|
|
96
97
|
testError.value = null
|
|
97
98
|
} else {
|
|
98
|
-
testError.value = result.error ?? '
|
|
99
|
+
testError.value = result.error ?? t('settings.localModelEndpoints.unreachable')
|
|
99
100
|
}
|
|
100
101
|
} catch (e) {
|
|
101
102
|
testError.value = e instanceof Error ? e.message : String(e)
|
|
@@ -125,12 +126,14 @@ async function save() {
|
|
|
125
126
|
})
|
|
126
127
|
apiKey.value = ''
|
|
127
128
|
toast.add({
|
|
128
|
-
title:
|
|
129
|
+
title: t('settings.localModelEndpoints.toast.saved', {
|
|
130
|
+
name: LOCAL_RUNNER_LABELS[provider.value],
|
|
131
|
+
}),
|
|
129
132
|
icon: 'i-lucide-check',
|
|
130
133
|
color: 'success',
|
|
131
134
|
})
|
|
132
135
|
} catch (e) {
|
|
133
|
-
notifyError('
|
|
136
|
+
notifyError(t('settings.localModelEndpoints.toast.saveFailed'), e)
|
|
134
137
|
} finally {
|
|
135
138
|
busy.value = false
|
|
136
139
|
}
|
|
@@ -147,9 +150,9 @@ async function remove(p: LocalRunner) {
|
|
|
147
150
|
selected.value = []
|
|
148
151
|
tested.value = false
|
|
149
152
|
}
|
|
150
|
-
toast.add({ title: '
|
|
153
|
+
toast.add({ title: t('settings.localModelEndpoints.toast.removed'), icon: 'i-lucide-check' })
|
|
151
154
|
} catch (e) {
|
|
152
|
-
notifyError('
|
|
155
|
+
notifyError(t('settings.localModelEndpoints.toast.removeFailed'), e)
|
|
153
156
|
} finally {
|
|
154
157
|
busy.value = false
|
|
155
158
|
}
|
|
@@ -157,18 +160,27 @@ async function remove(p: LocalRunner) {
|
|
|
157
160
|
</script>
|
|
158
161
|
|
|
159
162
|
<template>
|
|
160
|
-
<UModal
|
|
163
|
+
<UModal
|
|
164
|
+
v-model:open="open"
|
|
165
|
+
:title="t('settings.localModelEndpoints.title')"
|
|
166
|
+
:ui="{ content: 'max-w-2xl' }"
|
|
167
|
+
>
|
|
161
168
|
<template #title>
|
|
162
|
-
<IntegrationBackTitle title="
|
|
169
|
+
<IntegrationBackTitle :title="t('settings.localModelEndpoints.title')" @back="back" />
|
|
163
170
|
</template>
|
|
164
171
|
<template #body>
|
|
165
172
|
<div class="space-y-4">
|
|
166
173
|
<p class="text-xs text-slate-400">
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
174
|
+
<i18n-t keypath="settings.localModelEndpoints.intro" tag="span" scope="global">
|
|
175
|
+
<template #ownMachine>
|
|
176
|
+
<strong>{{ t('settings.localModelEndpoints.introOwnMachine') }}</strong>
|
|
177
|
+
</template>
|
|
178
|
+
<template #justForYou>
|
|
179
|
+
<span class="text-slate-300">{{
|
|
180
|
+
t('settings.localModelEndpoints.introJustForYou')
|
|
181
|
+
}}</span>
|
|
182
|
+
</template>
|
|
183
|
+
</i18n-t>
|
|
172
184
|
</p>
|
|
173
185
|
|
|
174
186
|
<!-- connected endpoints -->
|
|
@@ -181,8 +193,17 @@ async function remove(p: LocalRunner) {
|
|
|
181
193
|
<span class="font-medium text-slate-200">{{ e.label }}</span>
|
|
182
194
|
<span class="ml-2 text-xs text-slate-500">{{ LOCAL_RUNNER_LABELS[e.provider] }}</span>
|
|
183
195
|
<div class="text-[11px] text-slate-500">
|
|
184
|
-
{{ e.baseUrl }} ·
|
|
185
|
-
|
|
196
|
+
{{ e.baseUrl }} ·
|
|
197
|
+
{{
|
|
198
|
+
t(
|
|
199
|
+
'settings.localModelEndpoints.modelCount',
|
|
200
|
+
{ count: e.models.length },
|
|
201
|
+
e.models.length,
|
|
202
|
+
)
|
|
203
|
+
}}
|
|
204
|
+
<template v-if="e.hasApiKey">
|
|
205
|
+
· {{ t('settings.localModelEndpoints.keySet') }}</template
|
|
206
|
+
>
|
|
186
207
|
</div>
|
|
187
208
|
</div>
|
|
188
209
|
<div class="flex items-center gap-1">
|
|
@@ -192,7 +213,7 @@ async function remove(p: LocalRunner) {
|
|
|
192
213
|
variant="ghost"
|
|
193
214
|
size="xs"
|
|
194
215
|
:disabled="busy"
|
|
195
|
-
title="
|
|
216
|
+
:title="t('settings.localModelEndpoints.edit')"
|
|
196
217
|
@click="provider = e.provider"
|
|
197
218
|
/>
|
|
198
219
|
<UButton
|
|
@@ -209,29 +230,45 @@ async function remove(p: LocalRunner) {
|
|
|
209
230
|
<!-- add / edit form -->
|
|
210
231
|
<div class="rounded-lg border border-dashed border-slate-700 p-3 space-y-3">
|
|
211
232
|
<p class="text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
212
|
-
{{
|
|
233
|
+
{{
|
|
234
|
+
existing
|
|
235
|
+
? t('settings.localModelEndpoints.editRunner')
|
|
236
|
+
: t('settings.localModelEndpoints.addRunner')
|
|
237
|
+
}}
|
|
213
238
|
</p>
|
|
214
239
|
|
|
215
240
|
<div class="flex flex-wrap items-end gap-3">
|
|
216
|
-
<UFormField label="
|
|
241
|
+
<UFormField :label="t('settings.localModelEndpoints.runnerType')">
|
|
217
242
|
<USelect v-model="provider" :items="RUNNERS" value-key="value" class="w-48" />
|
|
218
243
|
</UFormField>
|
|
219
|
-
<UFormField
|
|
220
|
-
|
|
244
|
+
<UFormField
|
|
245
|
+
:label="t('settings.localModelEndpoints.labelOptional')"
|
|
246
|
+
class="flex-1 min-w-40"
|
|
247
|
+
>
|
|
248
|
+
<UInput
|
|
249
|
+
v-model="label"
|
|
250
|
+
:placeholder="
|
|
251
|
+
t('settings.localModelEndpoints.labelPlaceholder', {
|
|
252
|
+
name: LOCAL_RUNNER_LABELS[provider],
|
|
253
|
+
})
|
|
254
|
+
"
|
|
255
|
+
/>
|
|
221
256
|
</UFormField>
|
|
222
257
|
</div>
|
|
223
258
|
|
|
224
|
-
<UFormField label="
|
|
259
|
+
<UFormField :label="t('settings.localModelEndpoints.baseUrl')">
|
|
225
260
|
<UInput v-model="baseUrl" class="font-mono" placeholder="http://localhost:11434/v1" />
|
|
226
261
|
</UFormField>
|
|
227
262
|
|
|
228
|
-
<UFormField label="
|
|
263
|
+
<UFormField :label="t('settings.localModelEndpoints.apiKeyOptional')">
|
|
229
264
|
<UInput
|
|
230
265
|
v-model="apiKey"
|
|
231
266
|
type="password"
|
|
232
267
|
class="font-mono"
|
|
233
268
|
:placeholder="
|
|
234
|
-
existing?.hasApiKey
|
|
269
|
+
existing?.hasApiKey
|
|
270
|
+
? t('settings.localModelEndpoints.apiKeyKeepPlaceholder')
|
|
271
|
+
: t('settings.localModelEndpoints.apiKeyIgnorePlaceholder')
|
|
235
272
|
"
|
|
236
273
|
/>
|
|
237
274
|
</UFormField>
|
|
@@ -246,19 +283,27 @@ async function remove(p: LocalRunner) {
|
|
|
246
283
|
:disabled="!baseUrl.trim()"
|
|
247
284
|
@click="test()"
|
|
248
285
|
>
|
|
249
|
-
|
|
286
|
+
{{ t('settings.localModelEndpoints.testConnection') }}
|
|
250
287
|
</UButton>
|
|
251
288
|
<span v-if="testError" class="text-xs text-rose-400">{{ testError }}</span>
|
|
252
289
|
<span v-else-if="tested && discovered.length" class="text-xs text-emerald-400">
|
|
253
|
-
|
|
290
|
+
{{
|
|
291
|
+
t(
|
|
292
|
+
'settings.localModelEndpoints.reachable',
|
|
293
|
+
{ count: discovered.length },
|
|
294
|
+
discovered.length,
|
|
295
|
+
)
|
|
296
|
+
}}
|
|
254
297
|
</span>
|
|
255
|
-
<span v-else-if="tested" class="text-xs text-slate-500">
|
|
298
|
+
<span v-else-if="tested" class="text-xs text-slate-500">{{
|
|
299
|
+
t('settings.localModelEndpoints.noModels')
|
|
300
|
+
}}</span>
|
|
256
301
|
</div>
|
|
257
302
|
|
|
258
303
|
<!-- discovered models multi-select -->
|
|
259
304
|
<div v-if="discovered.length" class="space-y-1.5">
|
|
260
305
|
<span class="block text-[10px] uppercase tracking-wide text-slate-500">
|
|
261
|
-
|
|
306
|
+
{{ t('settings.localModelEndpoints.enableModels') }}
|
|
262
307
|
</span>
|
|
263
308
|
<div class="grid grid-cols-1 gap-1.5 sm:grid-cols-2">
|
|
264
309
|
<label
|
|
@@ -285,7 +330,7 @@ async function remove(p: LocalRunner) {
|
|
|
285
330
|
:disabled="!baseUrl.trim() || !selected.length"
|
|
286
331
|
@click="save()"
|
|
287
332
|
>
|
|
288
|
-
{{ existing ? '
|
|
333
|
+
{{ existing ? t('common.save') : t('settings.localModelEndpoints.addRunner') }}
|
|
289
334
|
</UButton>
|
|
290
335
|
</div>
|
|
291
336
|
</div>
|
|
@@ -4,16 +4,28 @@
|
|
|
4
4
|
// resolved preset). Full CRUD over the mergePresets store — the same library the
|
|
5
5
|
// task inspector's "Merge policy" dropdown selects from. Exactly one preset is the
|
|
6
6
|
// default; it cannot be deleted or un-defaulted (the backend enforces this too).
|
|
7
|
-
import { reactive, ref, watch } from 'vue'
|
|
7
|
+
import { computed, reactive, ref, watch } from 'vue'
|
|
8
8
|
import type { MergeThresholdPreset, RequirementConcernLevel } from '~/types/merge'
|
|
9
9
|
|
|
10
|
+
const { t } = useI18n()
|
|
11
|
+
|
|
12
|
+
// Per-concern-level label. An exhaustive Record keyed off the union (a missing member fails
|
|
13
|
+
// the typecheck); each value is a LITERAL catalog key so the typed-message-keys check sees
|
|
14
|
+
// it. Leaf keys mirror the enum value verbatim.
|
|
15
|
+
const CONCERN_LABEL_KEYS: Record<RequirementConcernLevel, string> = {
|
|
16
|
+
none: 'settings.mergeThresholds.concern.none',
|
|
17
|
+
low: 'settings.mergeThresholds.concern.low',
|
|
18
|
+
medium: 'settings.mergeThresholds.concern.medium',
|
|
19
|
+
high: 'settings.mergeThresholds.concern.high',
|
|
20
|
+
}
|
|
21
|
+
|
|
10
22
|
// Concern-level options for the requirements auto-pass threshold (none < low < medium < high).
|
|
11
|
-
const CONCERN_LEVELS
|
|
12
|
-
{ value: 'none', label:
|
|
13
|
-
{ value: 'low', label:
|
|
14
|
-
{ value: 'medium', label:
|
|
15
|
-
{ value: 'high', label:
|
|
16
|
-
]
|
|
23
|
+
const CONCERN_LEVELS = computed<{ value: RequirementConcernLevel; label: string }[]>(() => [
|
|
24
|
+
{ value: 'none', label: t(CONCERN_LABEL_KEYS.none) },
|
|
25
|
+
{ value: 'low', label: t(CONCERN_LABEL_KEYS.low) },
|
|
26
|
+
{ value: 'medium', label: t(CONCERN_LABEL_KEYS.medium) },
|
|
27
|
+
{ value: 'high', label: t(CONCERN_LABEL_KEYS.high) },
|
|
28
|
+
])
|
|
17
29
|
|
|
18
30
|
const store = useMergePresetsStore()
|
|
19
31
|
const toast = useToast()
|
|
@@ -77,9 +89,13 @@ async function save(p: MergeThresholdPreset) {
|
|
|
77
89
|
maxRequirementIterations: d.maxRequirementIterations,
|
|
78
90
|
maxRequirementConcernAllowed: d.maxRequirementConcernAllowed,
|
|
79
91
|
})
|
|
80
|
-
toast.add({
|
|
92
|
+
toast.add({
|
|
93
|
+
title: t('settings.mergeThresholds.toast.saved'),
|
|
94
|
+
icon: 'i-lucide-check',
|
|
95
|
+
color: 'success',
|
|
96
|
+
})
|
|
81
97
|
} catch (e) {
|
|
82
|
-
notifyError('
|
|
98
|
+
notifyError(t('settings.mergeThresholds.toast.saveFailed'), e)
|
|
83
99
|
} finally {
|
|
84
100
|
busy.value = null
|
|
85
101
|
}
|
|
@@ -90,7 +106,7 @@ async function makeDefault(p: MergeThresholdPreset) {
|
|
|
90
106
|
try {
|
|
91
107
|
await store.update(p.id, { isDefault: true })
|
|
92
108
|
} catch (e) {
|
|
93
|
-
notifyError('
|
|
109
|
+
notifyError(t('settings.mergeThresholds.toast.defaultFailed'), e)
|
|
94
110
|
} finally {
|
|
95
111
|
busy.value = null
|
|
96
112
|
}
|
|
@@ -101,7 +117,7 @@ async function remove(p: MergeThresholdPreset) {
|
|
|
101
117
|
try {
|
|
102
118
|
await store.remove(p.id)
|
|
103
119
|
} catch (e) {
|
|
104
|
-
notifyError('
|
|
120
|
+
notifyError(t('settings.mergeThresholds.toast.deleteFailed'), e)
|
|
105
121
|
} finally {
|
|
106
122
|
busy.value = null
|
|
107
123
|
}
|
|
@@ -133,9 +149,13 @@ async function create() {
|
|
|
133
149
|
maxRequirementConcernAllowed: draft.maxRequirementConcernAllowed,
|
|
134
150
|
})
|
|
135
151
|
draft.name = ''
|
|
136
|
-
toast.add({
|
|
152
|
+
toast.add({
|
|
153
|
+
title: t('settings.mergeThresholds.toast.created'),
|
|
154
|
+
icon: 'i-lucide-check',
|
|
155
|
+
color: 'success',
|
|
156
|
+
})
|
|
137
157
|
} catch (e) {
|
|
138
|
-
notifyError('
|
|
158
|
+
notifyError(t('settings.mergeThresholds.toast.createFailed'), e)
|
|
139
159
|
} finally {
|
|
140
160
|
creating.value = false
|
|
141
161
|
}
|
|
@@ -144,13 +164,16 @@ async function create() {
|
|
|
144
164
|
|
|
145
165
|
<template>
|
|
146
166
|
<div class="space-y-4">
|
|
147
|
-
<
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
167
|
+
<i18n-t
|
|
168
|
+
keypath="settings.mergeThresholds.intro"
|
|
169
|
+
tag="p"
|
|
170
|
+
class="text-xs text-slate-400"
|
|
171
|
+
scope="global"
|
|
172
|
+
>
|
|
173
|
+
<template #merger>
|
|
174
|
+
<span class="text-slate-300">{{ t('settings.mergeThresholds.mergerAgent') }}</span>
|
|
175
|
+
</template>
|
|
176
|
+
</i18n-t>
|
|
154
177
|
|
|
155
178
|
<div
|
|
156
179
|
v-for="p in store.presets"
|
|
@@ -158,8 +181,15 @@ async function create() {
|
|
|
158
181
|
class="rounded-lg border border-slate-700 bg-slate-800/40 p-3"
|
|
159
182
|
>
|
|
160
183
|
<div class="mb-3 flex items-center gap-2">
|
|
161
|
-
<UInput
|
|
162
|
-
|
|
184
|
+
<UInput
|
|
185
|
+
v-model="drafts[p.id]!.name"
|
|
186
|
+
size="sm"
|
|
187
|
+
class="flex-1"
|
|
188
|
+
:placeholder="t('settings.mergeThresholds.presetNamePlaceholder')"
|
|
189
|
+
/>
|
|
190
|
+
<UBadge v-if="p.isDefault" color="primary" variant="subtle" size="sm">
|
|
191
|
+
{{ t('settings.mergeThresholds.default') }}
|
|
192
|
+
</UBadge>
|
|
163
193
|
<UButton
|
|
164
194
|
v-else
|
|
165
195
|
color="neutral"
|
|
@@ -169,7 +199,7 @@ async function create() {
|
|
|
169
199
|
:loading="busy === p.id"
|
|
170
200
|
@click="makeDefault(p)"
|
|
171
201
|
>
|
|
172
|
-
|
|
202
|
+
{{ t('settings.mergeThresholds.makeDefault') }}
|
|
173
203
|
</UButton>
|
|
174
204
|
<UButton
|
|
175
205
|
color="error"
|
|
@@ -177,7 +207,11 @@ async function create() {
|
|
|
177
207
|
size="xs"
|
|
178
208
|
icon="i-lucide-trash-2"
|
|
179
209
|
:disabled="p.isDefault || busy === p.id"
|
|
180
|
-
:title="
|
|
210
|
+
:title="
|
|
211
|
+
p.isDefault
|
|
212
|
+
? t('settings.mergeThresholds.deleteDefaultBlocked')
|
|
213
|
+
: t('settings.mergeThresholds.deletePreset')
|
|
214
|
+
"
|
|
181
215
|
@click="remove(p)"
|
|
182
216
|
/>
|
|
183
217
|
</div>
|
|
@@ -185,7 +219,7 @@ async function create() {
|
|
|
185
219
|
<div class="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
|
186
220
|
<label class="block">
|
|
187
221
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
188
|
-
|
|
222
|
+
{{ t('settings.mergeThresholds.field.maxComplexity') }}
|
|
189
223
|
</span>
|
|
190
224
|
<UInput
|
|
191
225
|
v-model.number="drafts[p.id]!.maxComplexity"
|
|
@@ -197,7 +231,7 @@ async function create() {
|
|
|
197
231
|
</label>
|
|
198
232
|
<label class="block">
|
|
199
233
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
200
|
-
|
|
234
|
+
{{ t('settings.mergeThresholds.field.maxRisk') }}
|
|
201
235
|
</span>
|
|
202
236
|
<UInput
|
|
203
237
|
v-model.number="drafts[p.id]!.maxRisk"
|
|
@@ -209,7 +243,7 @@ async function create() {
|
|
|
209
243
|
</label>
|
|
210
244
|
<label class="block">
|
|
211
245
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
212
|
-
|
|
246
|
+
{{ t('settings.mergeThresholds.field.maxImpact') }}
|
|
213
247
|
</span>
|
|
214
248
|
<UInput
|
|
215
249
|
v-model.number="drafts[p.id]!.maxImpact"
|
|
@@ -221,7 +255,7 @@ async function create() {
|
|
|
221
255
|
</label>
|
|
222
256
|
<label class="block">
|
|
223
257
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
224
|
-
|
|
258
|
+
{{ t('settings.mergeThresholds.field.ciMaxAttempts') }}
|
|
225
259
|
</span>
|
|
226
260
|
<UInput
|
|
227
261
|
v-model.number="drafts[p.id]!.ciMaxAttempts"
|
|
@@ -233,7 +267,7 @@ async function create() {
|
|
|
233
267
|
</label>
|
|
234
268
|
<label class="block">
|
|
235
269
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
236
|
-
|
|
270
|
+
{{ t('settings.mergeThresholds.field.maxRequirementIterations') }}
|
|
237
271
|
</span>
|
|
238
272
|
<UInput
|
|
239
273
|
v-model.number="drafts[p.id]!.maxRequirementIterations"
|
|
@@ -245,7 +279,7 @@ async function create() {
|
|
|
245
279
|
</label>
|
|
246
280
|
<label class="block">
|
|
247
281
|
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
248
|
-
|
|
282
|
+
{{ t('settings.mergeThresholds.field.maxRequirementConcernAllowed') }}
|
|
249
283
|
</span>
|
|
250
284
|
<USelect
|
|
251
285
|
v-model="drafts[p.id]!.maxRequirementConcernAllowed"
|
|
@@ -265,7 +299,7 @@ async function create() {
|
|
|
265
299
|
:loading="busy === p.id"
|
|
266
300
|
@click="save(p)"
|
|
267
301
|
>
|
|
268
|
-
|
|
302
|
+
{{ t('common.save') }}
|
|
269
303
|
</UButton>
|
|
270
304
|
</div>
|
|
271
305
|
</div>
|
|
@@ -273,15 +307,23 @@ async function create() {
|
|
|
273
307
|
<!-- create -->
|
|
274
308
|
<div class="rounded-lg border border-dashed border-slate-700 p-3">
|
|
275
309
|
<p class="mb-2 text-[11px] font-semibold uppercase tracking-wide text-slate-400">
|
|
276
|
-
|
|
310
|
+
{{ t('settings.mergeThresholds.newPreset') }}
|
|
277
311
|
</p>
|
|
278
312
|
<div class="flex flex-wrap items-end gap-3">
|
|
279
313
|
<label class="block min-w-40 flex-1">
|
|
280
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
281
|
-
|
|
314
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
315
|
+
{{ t('settings.mergeThresholds.create.name') }}
|
|
316
|
+
</span>
|
|
317
|
+
<UInput
|
|
318
|
+
v-model="draft.name"
|
|
319
|
+
size="sm"
|
|
320
|
+
:placeholder="t('settings.mergeThresholds.create.namePlaceholder')"
|
|
321
|
+
/>
|
|
282
322
|
</label>
|
|
283
323
|
<label class="block w-20">
|
|
284
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
324
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
325
|
+
{{ t('settings.mergeThresholds.create.complexity') }}
|
|
326
|
+
</span>
|
|
285
327
|
<UInput
|
|
286
328
|
v-model.number="draft.maxComplexity"
|
|
287
329
|
type="number"
|
|
@@ -291,21 +333,27 @@ async function create() {
|
|
|
291
333
|
/>
|
|
292
334
|
</label>
|
|
293
335
|
<label class="block w-20">
|
|
294
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
336
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
337
|
+
{{ t('settings.mergeThresholds.create.risk') }}
|
|
338
|
+
</span>
|
|
295
339
|
<UInput v-model.number="draft.maxRisk" type="number" :min="0" :max="100" size="sm" />
|
|
296
340
|
</label>
|
|
297
341
|
<label class="block w-20">
|
|
298
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
342
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
343
|
+
{{ t('settings.mergeThresholds.create.impact') }}
|
|
344
|
+
</span>
|
|
299
345
|
<UInput v-model.number="draft.maxImpact" type="number" :min="0" :max="100" size="sm" />
|
|
300
346
|
</label>
|
|
301
347
|
<label class="block w-20">
|
|
302
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
348
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
349
|
+
{{ t('settings.mergeThresholds.create.ciFix') }}
|
|
350
|
+
</span>
|
|
303
351
|
<UInput v-model.number="draft.ciMaxAttempts" type="number" :min="0" :max="50" size="sm" />
|
|
304
352
|
</label>
|
|
305
353
|
<label class="block w-20">
|
|
306
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500"
|
|
307
|
-
|
|
308
|
-
>
|
|
354
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
355
|
+
{{ t('settings.mergeThresholds.create.reqIter') }}
|
|
356
|
+
</span>
|
|
309
357
|
<UInput
|
|
310
358
|
v-model.number="draft.maxRequirementIterations"
|
|
311
359
|
type="number"
|
|
@@ -315,9 +363,9 @@ async function create() {
|
|
|
315
363
|
/>
|
|
316
364
|
</label>
|
|
317
365
|
<label class="block w-32">
|
|
318
|
-
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500"
|
|
319
|
-
|
|
320
|
-
>
|
|
366
|
+
<span class="mb-1 block text-[10px] uppercase tracking-wide text-slate-500">
|
|
367
|
+
{{ t('settings.mergeThresholds.create.autoPass') }}
|
|
368
|
+
</span>
|
|
321
369
|
<USelect
|
|
322
370
|
v-model="draft.maxRequirementConcernAllowed"
|
|
323
371
|
:items="CONCERN_LEVELS"
|
|
@@ -333,7 +381,7 @@ async function create() {
|
|
|
333
381
|
:disabled="!draft.name.trim()"
|
|
334
382
|
@click="create"
|
|
335
383
|
>
|
|
336
|
-
|
|
384
|
+
{{ t('settings.mergeThresholds.add') }}
|
|
337
385
|
</UButton>
|
|
338
386
|
</div>
|
|
339
387
|
</div>
|