@cat-factory/app 0.47.11 → 0.48.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/layout/AccountDeploymentSettings.vue +119 -0
- package/app/components/settings/IssueTrackerPanel.vue +48 -1
- package/app/components/tasks/TaskSourceConnectModal.vue +36 -1
- package/app/composables/api/tasks.ts +11 -0
- package/app/stores/tasks.ts +12 -0
- package/app/stores/tracker.ts +12 -1
- package/app/types/tasks.ts +1 -0
- package/i18n/locales/en.json +17 -2
- package/i18n/locales/es.json +17 -2
- package/i18n/locales/fr.json +17 -2
- package/i18n/locales/pl.json +17 -2
- package/i18n/locales/uk.json +17 -2
- package/package.json +2 -2
|
@@ -15,8 +15,10 @@ const toast = useToast()
|
|
|
15
15
|
const { t } = useI18n()
|
|
16
16
|
|
|
17
17
|
const slack = reactive({ clientId: '', clientSecret: '', redirectUrl: '' })
|
|
18
|
+
const linear = reactive({ clientId: '', clientSecret: '', redirectUrl: '' })
|
|
18
19
|
const web = reactive({ braveApiKey: '', searxngUrl: '', searxngApiKey: '' })
|
|
19
20
|
const savingSlack = ref(false)
|
|
21
|
+
const savingLinear = ref(false)
|
|
20
22
|
const savingWeb = ref(false)
|
|
21
23
|
|
|
22
24
|
const summary = computed(() => store.view?.summary ?? null)
|
|
@@ -200,6 +202,61 @@ async function clearSlack() {
|
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
204
|
|
|
205
|
+
async function saveLinear() {
|
|
206
|
+
if (!linear.clientId.trim() || !linear.clientSecret.trim() || !linear.redirectUrl.trim()) {
|
|
207
|
+
toast.add({ title: t('layout.accountDeployment.linear.validation'), color: 'error' })
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
savingLinear.value = true
|
|
211
|
+
try {
|
|
212
|
+
await store.save(props.accountId, {
|
|
213
|
+
secrets: {
|
|
214
|
+
linearOAuth: {
|
|
215
|
+
clientId: linear.clientId.trim(),
|
|
216
|
+
clientSecret: linear.clientSecret.trim(),
|
|
217
|
+
redirectUrl: linear.redirectUrl.trim(),
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
})
|
|
221
|
+
linear.clientId = ''
|
|
222
|
+
linear.clientSecret = ''
|
|
223
|
+
linear.redirectUrl = ''
|
|
224
|
+
toast.add({
|
|
225
|
+
title: t('layout.accountDeployment.linear.saved'),
|
|
226
|
+
icon: 'i-lucide-check',
|
|
227
|
+
color: 'success',
|
|
228
|
+
})
|
|
229
|
+
} catch (e) {
|
|
230
|
+
toast.add({
|
|
231
|
+
title: t('layout.accountDeployment.linear.saveFailed'),
|
|
232
|
+
description: e instanceof Error ? e.message : String(e),
|
|
233
|
+
color: 'error',
|
|
234
|
+
})
|
|
235
|
+
} finally {
|
|
236
|
+
savingLinear.value = false
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
async function clearLinear() {
|
|
241
|
+
savingLinear.value = true
|
|
242
|
+
try {
|
|
243
|
+
await store.save(props.accountId, { secrets: { linearOAuth: null } })
|
|
244
|
+
toast.add({
|
|
245
|
+
title: t('layout.accountDeployment.linear.cleared'),
|
|
246
|
+
icon: 'i-lucide-check',
|
|
247
|
+
color: 'success',
|
|
248
|
+
})
|
|
249
|
+
} catch (e) {
|
|
250
|
+
toast.add({
|
|
251
|
+
title: t('layout.accountDeployment.linear.clearFailed'),
|
|
252
|
+
description: e instanceof Error ? e.message : String(e),
|
|
253
|
+
color: 'error',
|
|
254
|
+
})
|
|
255
|
+
} finally {
|
|
256
|
+
savingLinear.value = false
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
203
260
|
async function saveWeb() {
|
|
204
261
|
const brave = web.braveApiKey.trim()
|
|
205
262
|
const searxng = web.searxngUrl.trim()
|
|
@@ -329,6 +386,68 @@ async function clearWeb() {
|
|
|
329
386
|
</div>
|
|
330
387
|
</section>
|
|
331
388
|
|
|
389
|
+
<!-- Linear app OAuth -->
|
|
390
|
+
<section class="space-y-2 border-t border-slate-800 pt-6">
|
|
391
|
+
<div class="flex items-center gap-2">
|
|
392
|
+
<h4 class="text-sm font-semibold text-slate-200">
|
|
393
|
+
{{ t('layout.accountDeployment.linear.title') }}
|
|
394
|
+
</h4>
|
|
395
|
+
<UBadge
|
|
396
|
+
:color="summary?.linearOAuthConfigured ? 'success' : 'neutral'"
|
|
397
|
+
variant="subtle"
|
|
398
|
+
size="xs"
|
|
399
|
+
>
|
|
400
|
+
{{
|
|
401
|
+
summary?.linearOAuthConfigured
|
|
402
|
+
? t('layout.accountDeployment.configured')
|
|
403
|
+
: t('layout.accountDeployment.notSet')
|
|
404
|
+
}}
|
|
405
|
+
</UBadge>
|
|
406
|
+
</div>
|
|
407
|
+
<p class="text-[11px] text-slate-400">
|
|
408
|
+
{{ t('layout.accountDeployment.linear.description') }}
|
|
409
|
+
</p>
|
|
410
|
+
<div class="grid grid-cols-1 gap-2 sm:grid-cols-3">
|
|
411
|
+
<UInput
|
|
412
|
+
v-model="linear.clientId"
|
|
413
|
+
:placeholder="t('layout.accountDeployment.linear.clientId')"
|
|
414
|
+
size="sm"
|
|
415
|
+
/>
|
|
416
|
+
<UInput
|
|
417
|
+
v-model="linear.clientSecret"
|
|
418
|
+
type="password"
|
|
419
|
+
:placeholder="t('layout.accountDeployment.linear.clientSecret')"
|
|
420
|
+
size="sm"
|
|
421
|
+
/>
|
|
422
|
+
<UInput
|
|
423
|
+
v-model="linear.redirectUrl"
|
|
424
|
+
:placeholder="t('layout.accountDeployment.linear.redirectUrl')"
|
|
425
|
+
size="sm"
|
|
426
|
+
/>
|
|
427
|
+
</div>
|
|
428
|
+
<div class="flex gap-2">
|
|
429
|
+
<UButton
|
|
430
|
+
color="primary"
|
|
431
|
+
size="xs"
|
|
432
|
+
icon="i-lucide-save"
|
|
433
|
+
:loading="savingLinear"
|
|
434
|
+
@click="saveLinear"
|
|
435
|
+
>
|
|
436
|
+
{{ t('common.save') }}
|
|
437
|
+
</UButton>
|
|
438
|
+
<UButton
|
|
439
|
+
v-if="summary?.linearOAuthConfigured"
|
|
440
|
+
color="neutral"
|
|
441
|
+
variant="ghost"
|
|
442
|
+
size="xs"
|
|
443
|
+
:loading="savingLinear"
|
|
444
|
+
@click="clearLinear"
|
|
445
|
+
>
|
|
446
|
+
{{ t('layout.accountDeployment.clear') }}
|
|
447
|
+
</UButton>
|
|
448
|
+
</div>
|
|
449
|
+
</section>
|
|
450
|
+
|
|
332
451
|
<!-- Web search keys -->
|
|
333
452
|
<section class="space-y-2 border-t border-slate-800 pt-6">
|
|
334
453
|
<div class="flex items-center gap-2">
|
|
@@ -68,6 +68,39 @@ const canSave = computed(() => {
|
|
|
68
68
|
return true
|
|
69
69
|
})
|
|
70
70
|
|
|
71
|
+
// Linear team picker: load the connected workspace's teams so filing offers a
|
|
72
|
+
// dropdown instead of a raw team-id paste. Falls back to the text input if the
|
|
73
|
+
// teams can't be loaded (a broken connection shouldn't block configuration).
|
|
74
|
+
const teamsLoading = ref(false)
|
|
75
|
+
const teamsError = ref(false)
|
|
76
|
+
const teamOptions = computed(() =>
|
|
77
|
+
tracker.linearTeams.map((tm) => ({
|
|
78
|
+
label: tm.key ? `${tm.name} (${tm.key})` : tm.name,
|
|
79
|
+
value: tm.id,
|
|
80
|
+
})),
|
|
81
|
+
)
|
|
82
|
+
async function loadLinearTeams() {
|
|
83
|
+
if (!linearConnected.value) return
|
|
84
|
+
teamsLoading.value = true
|
|
85
|
+
teamsError.value = false
|
|
86
|
+
try {
|
|
87
|
+
await tracker.loadLinearTeams()
|
|
88
|
+
} catch {
|
|
89
|
+
teamsError.value = true
|
|
90
|
+
} finally {
|
|
91
|
+
teamsLoading.value = false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
watch(
|
|
95
|
+
() => [trackerKind.value, linearConnected.value] as const,
|
|
96
|
+
([kind, connected]) => {
|
|
97
|
+
if (kind === 'linear' && connected && tracker.linearTeams.length === 0 && !teamsError.value) {
|
|
98
|
+
void loadLinearTeams()
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{ immediate: true },
|
|
102
|
+
)
|
|
103
|
+
|
|
71
104
|
async function save() {
|
|
72
105
|
if (!canSave.value) return
|
|
73
106
|
saving.value = true
|
|
@@ -284,7 +317,21 @@ const STATUS_UI: Record<
|
|
|
284
317
|
:label="t('settings.issueTracker.filing.linearTeamId')"
|
|
285
318
|
class="w-64"
|
|
286
319
|
>
|
|
287
|
-
|
|
320
|
+
<!-- Typeahead combobox when the connection's teams loaded (built-in client-side
|
|
321
|
+
filter over the option labels — a large org's team list is too long for a
|
|
322
|
+
plain dropdown); raw-id fallback otherwise. Mirrors the repo picker. -->
|
|
323
|
+
<UInputMenu
|
|
324
|
+
v-if="linearConnected && !teamsError && teamOptions.length > 0"
|
|
325
|
+
v-model="linearTeamId"
|
|
326
|
+
:items="teamOptions"
|
|
327
|
+
value-key="value"
|
|
328
|
+
:loading="teamsLoading"
|
|
329
|
+
icon="i-lucide-search"
|
|
330
|
+
:placeholder="t('settings.issueTracker.filing.linearTeamSearchPlaceholder')"
|
|
331
|
+
size="sm"
|
|
332
|
+
class="w-full"
|
|
333
|
+
/>
|
|
334
|
+
<UInput v-else v-model="linearTeamId" placeholder="team_…" size="sm" class="w-full" />
|
|
288
335
|
<template #help>
|
|
289
336
|
<span class="text-[11px] text-slate-500">
|
|
290
337
|
{{ t('settings.issueTracker.filing.linearTeamIdHelp') }}
|
|
@@ -24,6 +24,9 @@ const connection = computed(() => (source.value ? tasks.connectionFor(source.val
|
|
|
24
24
|
const connected = computed(() => connection.value !== undefined)
|
|
25
25
|
// A credentialless source (GitHub Issues) reuses the installed GitHub App: no form.
|
|
26
26
|
const credentialless = computed(() => (descriptor.value?.credentialFields.length ?? 0) === 0)
|
|
27
|
+
// An OAuth source (Linear) offers a "Connect with X" button alongside the manual fields.
|
|
28
|
+
const oauth = computed(() => descriptor.value?.oauth ?? false)
|
|
29
|
+
const oauthStarting = ref(false)
|
|
27
30
|
// Usable right now: a credentialed source is connected; GitHub Issues' App is installed.
|
|
28
31
|
const available = computed(() => descriptor.value?.available ?? false)
|
|
29
32
|
|
|
@@ -77,6 +80,23 @@ async function submit() {
|
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
82
|
|
|
83
|
+
async function startOAuth() {
|
|
84
|
+
if (!source.value) return
|
|
85
|
+
oauthStarting.value = true
|
|
86
|
+
try {
|
|
87
|
+
// Only Linear wires an OAuth flow today; the browser navigates away on success.
|
|
88
|
+
if (source.value === 'linear') await tasks.startLinearOAuth()
|
|
89
|
+
} catch (e) {
|
|
90
|
+
toast.add({
|
|
91
|
+
title: t('tasks.connect.connectFailed'),
|
|
92
|
+
description: e instanceof Error ? e.message : String(e),
|
|
93
|
+
icon: 'i-lucide-triangle-alert',
|
|
94
|
+
color: 'error',
|
|
95
|
+
})
|
|
96
|
+
oauthStarting.value = false
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
80
100
|
async function disconnect() {
|
|
81
101
|
if (!source.value) return
|
|
82
102
|
await tasks.disconnect(source.value)
|
|
@@ -129,8 +149,23 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
129
149
|
</p>
|
|
130
150
|
</template>
|
|
131
151
|
|
|
132
|
-
<!-- Credentialed source (Jira): the connect form, shown until connected. -->
|
|
152
|
+
<!-- Credentialed source (Jira/Linear): the connect form, shown until connected. -->
|
|
133
153
|
<div v-else-if="!connected" class="space-y-3">
|
|
154
|
+
<!-- OAuth source (Linear): the redirect button, with the manual key form below. -->
|
|
155
|
+
<template v-if="oauth">
|
|
156
|
+
<UButton
|
|
157
|
+
block
|
|
158
|
+
color="primary"
|
|
159
|
+
icon="i-lucide-plug"
|
|
160
|
+
:loading="oauthStarting"
|
|
161
|
+
@click="startOAuth"
|
|
162
|
+
>
|
|
163
|
+
{{ t('tasks.connect.oauthButton', { label: descriptor.label }) }}
|
|
164
|
+
</UButton>
|
|
165
|
+
<p class="text-center text-[11px] text-slate-500">
|
|
166
|
+
{{ t('tasks.connect.oauthOr') }}
|
|
167
|
+
</p>
|
|
168
|
+
</template>
|
|
134
169
|
<UFormField
|
|
135
170
|
v-for="field in descriptor.credentialFields"
|
|
136
171
|
:key="field.key"
|
|
@@ -3,9 +3,11 @@ import {
|
|
|
3
3
|
createTaskFromIssueContract,
|
|
4
4
|
diagnoseTaskSourceContract,
|
|
5
5
|
disconnectTaskSourceContract,
|
|
6
|
+
getLinearInstallUrlContract,
|
|
6
7
|
getTrackerSettingsContract,
|
|
7
8
|
importTaskContract,
|
|
8
9
|
linkTaskContract,
|
|
10
|
+
listLinearTeamsContract,
|
|
9
11
|
listTaskConnectionsContract,
|
|
10
12
|
listTaskSourcesContract,
|
|
11
13
|
listTasksContract,
|
|
@@ -95,6 +97,15 @@ export function tasksApi({ send, ws }: ApiContext) {
|
|
|
95
97
|
body: { ref: string; containerId: string; position?: { x: number; y: number } },
|
|
96
98
|
) => send(spawnEpicContract, { pathPrefix: ws(workspaceId), pathParams: { source }, body }),
|
|
97
99
|
|
|
100
|
+
// ---- Linear-specific --------------------------------------------------
|
|
101
|
+
// The connection's Linear teams, for the ticket-filing team picker.
|
|
102
|
+
listLinearTeams: (workspaceId: string) =>
|
|
103
|
+
send(listLinearTeamsContract, { pathPrefix: ws(workspaceId) }),
|
|
104
|
+
|
|
105
|
+
// The "Connect with Linear" OAuth authorize URL (the browser is redirected to it).
|
|
106
|
+
getLinearInstallUrl: (workspaceId: string) =>
|
|
107
|
+
send(getLinearInstallUrlContract, { pathPrefix: ws(workspaceId) }),
|
|
108
|
+
|
|
98
109
|
// ---- issue-tracker selection (workspace-level) ------------------------
|
|
99
110
|
getTrackerSettings: (workspaceId: string) =>
|
|
100
111
|
send(getTrackerSettingsContract, { pathPrefix: ws(workspaceId) }),
|
package/app/stores/tasks.ts
CHANGED
|
@@ -90,6 +90,17 @@ export const useTasksStore = defineStore('tasks', () => {
|
|
|
90
90
|
available.value = true
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Start the "Connect with Linear" OAuth flow by navigating the browser to the
|
|
95
|
+
* authorize URL the backend mints (carrying a signed `state`). Linear redirects
|
|
96
|
+
* back to the public callback, which stores the token; the settings panel's
|
|
97
|
+
* `probe()` on return then reflects the new connection.
|
|
98
|
+
*/
|
|
99
|
+
async function startLinearOAuth() {
|
|
100
|
+
const { url } = await api.getLinearInstallUrl(workspace.requireId())
|
|
101
|
+
window.location.href = url
|
|
102
|
+
}
|
|
103
|
+
|
|
93
104
|
/** Disconnect the workspace from a source. */
|
|
94
105
|
async function disconnect(source: TaskSourceKind) {
|
|
95
106
|
await api.disconnectTaskSource(workspace.requireId(), source)
|
|
@@ -203,6 +214,7 @@ export const useTasksStore = defineStore('tasks', () => {
|
|
|
203
214
|
probe,
|
|
204
215
|
checkSetup,
|
|
205
216
|
connect,
|
|
217
|
+
startLinearOAuth,
|
|
206
218
|
disconnect,
|
|
207
219
|
setEnabled,
|
|
208
220
|
loadTasks,
|
package/app/stores/tracker.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
2
|
import { ref } from 'vue'
|
|
3
|
+
import type { LinearTeam } from '~/types/domain'
|
|
3
4
|
import type { PutTrackerSettingsInput, TrackerSettings } from '~/types/tracker'
|
|
4
5
|
import { useWorkspaceStore } from '~/stores/workspace'
|
|
5
6
|
|
|
@@ -20,6 +21,9 @@ export const useTrackerStore = defineStore('tracker', () => {
|
|
|
20
21
|
updatedAt: 0,
|
|
21
22
|
})
|
|
22
23
|
|
|
24
|
+
/** The connected Linear workspace's teams, for the filing team picker (lazily loaded). */
|
|
25
|
+
const linearTeams = ref<LinearTeam[]>([])
|
|
26
|
+
|
|
23
27
|
function hydrate(value: TrackerSettings | undefined) {
|
|
24
28
|
settings.value = value ?? {
|
|
25
29
|
tracker: null,
|
|
@@ -37,5 +41,12 @@ export const useTrackerStore = defineStore('tracker', () => {
|
|
|
37
41
|
return settings.value
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
|
|
44
|
+
/** Load the connected Linear workspace's teams for the filing team picker. */
|
|
45
|
+
async function loadLinearTeams() {
|
|
46
|
+
const ws = useWorkspaceStore()
|
|
47
|
+
const { teams } = await api.listLinearTeams(ws.requireId())
|
|
48
|
+
linearTeams.value = teams
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { settings, linearTeams, hydrate, save, loadLinearTeams }
|
|
41
52
|
})
|
package/app/types/tasks.ts
CHANGED
package/i18n/locales/en.json
CHANGED
|
@@ -828,6 +828,18 @@
|
|
|
828
828
|
"cleared": "Slack OAuth cleared",
|
|
829
829
|
"clearFailed": "Could not clear Slack OAuth"
|
|
830
830
|
},
|
|
831
|
+
"linear": {
|
|
832
|
+
"title": "Linear app (OAuth)",
|
|
833
|
+
"description": "Enables the \"Connect with Linear\" OAuth flow. Without it, workspaces can still connect Linear by pasting a personal API key.",
|
|
834
|
+
"clientId": "Client ID",
|
|
835
|
+
"clientSecret": "Client secret",
|
|
836
|
+
"redirectUrl": "Redirect URL",
|
|
837
|
+
"validation": "Enter the client id, secret and redirect URL",
|
|
838
|
+
"saved": "Linear OAuth saved",
|
|
839
|
+
"saveFailed": "Could not save Linear OAuth",
|
|
840
|
+
"cleared": "Linear OAuth cleared",
|
|
841
|
+
"clearFailed": "Could not clear Linear OAuth"
|
|
842
|
+
},
|
|
831
843
|
"web": {
|
|
832
844
|
"title": "Container web search",
|
|
833
845
|
"description": "The search upstream container agents reach through the backend proxy. Set a Brave key (recommended), or a self-hosted SearXNG URL (with an optional bearer key).",
|
|
@@ -1340,7 +1352,8 @@
|
|
|
1340
1352
|
"jiraProjectKey": "Jira project key",
|
|
1341
1353
|
"jiraProjectKeyHelp": "New tickets are filed under this project.",
|
|
1342
1354
|
"linearTeamId": "Linear team id",
|
|
1343
|
-
"linearTeamIdHelp": "New issues are created under this team (Linear requires a team to create an issue)."
|
|
1355
|
+
"linearTeamIdHelp": "New issues are created under this team (Linear requires a team to create an issue).",
|
|
1356
|
+
"linearTeamSearchPlaceholder": "Search teams…"
|
|
1344
1357
|
},
|
|
1345
1358
|
"vendor": {
|
|
1346
1359
|
"github": "GitHub Issues",
|
|
@@ -2168,7 +2181,9 @@
|
|
|
2168
2181
|
"offerHint": "When off, {label} is hidden from import and linking.",
|
|
2169
2182
|
"disconnect": "Disconnect",
|
|
2170
2183
|
"updateConnection": "Update connection",
|
|
2171
|
-
"connect": "Connect"
|
|
2184
|
+
"connect": "Connect",
|
|
2185
|
+
"oauthButton": "Connect with {label}",
|
|
2186
|
+
"oauthOr": "or connect with an API key"
|
|
2172
2187
|
}
|
|
2173
2188
|
},
|
|
2174
2189
|
"pipeline": {
|
package/i18n/locales/es.json
CHANGED
|
@@ -789,6 +789,18 @@
|
|
|
789
789
|
"cleared": "OAuth de Slack borrado",
|
|
790
790
|
"clearFailed": "No se pudo borrar el OAuth de Slack"
|
|
791
791
|
},
|
|
792
|
+
"linear": {
|
|
793
|
+
"title": "Aplicación de Linear (OAuth)",
|
|
794
|
+
"description": "Habilita el flujo de OAuth \"Conectar con Linear\". Sin ello, los espacios de trabajo aún pueden conectar Linear pegando una clave de API personal.",
|
|
795
|
+
"clientId": "ID de cliente",
|
|
796
|
+
"clientSecret": "Secreto de cliente",
|
|
797
|
+
"redirectUrl": "URL de redirección",
|
|
798
|
+
"validation": "Introduce el id de cliente, el secreto y la URL de redirección",
|
|
799
|
+
"saved": "OAuth de Linear guardado",
|
|
800
|
+
"saveFailed": "No se pudo guardar OAuth de Linear",
|
|
801
|
+
"cleared": "OAuth de Linear borrado",
|
|
802
|
+
"clearFailed": "No se pudo borrar OAuth de Linear"
|
|
803
|
+
},
|
|
792
804
|
"web": {
|
|
793
805
|
"title": "Búsqueda web del contenedor",
|
|
794
806
|
"description": "El proveedor de búsqueda al que los agentes del contenedor acceden a través del proxy del backend. Define una clave de Brave (recomendado) o una URL de SearXNG autoalojada (con una clave bearer opcional).",
|
|
@@ -1298,7 +1310,8 @@
|
|
|
1298
1310
|
"jiraProjectKey": "Clave de proyecto de Jira",
|
|
1299
1311
|
"jiraProjectKeyHelp": "Los nuevos tickets se registran en este proyecto.",
|
|
1300
1312
|
"linearTeamId": "Id de equipo de Linear",
|
|
1301
|
-
"linearTeamIdHelp": "Las nuevas incidencias se crean en este equipo (Linear requiere un equipo para crear una incidencia)."
|
|
1313
|
+
"linearTeamIdHelp": "Las nuevas incidencias se crean en este equipo (Linear requiere un equipo para crear una incidencia).",
|
|
1314
|
+
"linearTeamSearchPlaceholder": "Buscar equipos…"
|
|
1302
1315
|
},
|
|
1303
1316
|
"vendor": {
|
|
1304
1317
|
"github": "GitHub Issues",
|
|
@@ -2111,7 +2124,9 @@
|
|
|
2111
2124
|
"offerHint": "Cuando está desactivada, {label} se oculta de la importación y la vinculación.",
|
|
2112
2125
|
"disconnect": "Desconectar",
|
|
2113
2126
|
"updateConnection": "Actualizar conexión",
|
|
2114
|
-
"connect": "Conectar"
|
|
2127
|
+
"connect": "Conectar",
|
|
2128
|
+
"oauthButton": "Conectar con {label}",
|
|
2129
|
+
"oauthOr": "o conecta con una clave API"
|
|
2115
2130
|
}
|
|
2116
2131
|
},
|
|
2117
2132
|
"pipeline": {
|
package/i18n/locales/fr.json
CHANGED
|
@@ -789,6 +789,18 @@
|
|
|
789
789
|
"cleared": "OAuth Slack effacé",
|
|
790
790
|
"clearFailed": "Impossible d'effacer l'OAuth Slack"
|
|
791
791
|
},
|
|
792
|
+
"linear": {
|
|
793
|
+
"title": "Application Linear (OAuth)",
|
|
794
|
+
"description": "Active le flux OAuth « Se connecter avec Linear ». Sans cela, les espaces de travail peuvent toujours connecter Linear en collant une clé API personnelle.",
|
|
795
|
+
"clientId": "ID client",
|
|
796
|
+
"clientSecret": "Secret client",
|
|
797
|
+
"redirectUrl": "URL de redirection",
|
|
798
|
+
"validation": "Saisissez l'id client, le secret et l'URL de redirection",
|
|
799
|
+
"saved": "OAuth Linear enregistré",
|
|
800
|
+
"saveFailed": "Impossible d'enregistrer OAuth Linear",
|
|
801
|
+
"cleared": "OAuth Linear effacé",
|
|
802
|
+
"clearFailed": "Impossible d'effacer OAuth Linear"
|
|
803
|
+
},
|
|
792
804
|
"web": {
|
|
793
805
|
"title": "Recherche web du conteneur",
|
|
794
806
|
"description": "Le fournisseur de recherche que les agents en conteneur atteignent via le proxy du backend. Définissez une clé Brave (recommandé) ou une URL SearXNG auto-hébergée (avec une clé bearer facultative).",
|
|
@@ -1298,7 +1310,8 @@
|
|
|
1298
1310
|
"jiraProjectKey": "Clé de projet Jira",
|
|
1299
1311
|
"jiraProjectKeyHelp": "Les nouveaux tickets sont créés dans ce projet.",
|
|
1300
1312
|
"linearTeamId": "Id d'équipe Linear",
|
|
1301
|
-
"linearTeamIdHelp": "Les nouveaux tickets sont créés dans cette équipe (Linear exige une équipe pour créer un ticket)."
|
|
1313
|
+
"linearTeamIdHelp": "Les nouveaux tickets sont créés dans cette équipe (Linear exige une équipe pour créer un ticket).",
|
|
1314
|
+
"linearTeamSearchPlaceholder": "Rechercher des équipes…"
|
|
1302
1315
|
},
|
|
1303
1316
|
"vendor": {
|
|
1304
1317
|
"github": "GitHub Issues",
|
|
@@ -2111,7 +2124,9 @@
|
|
|
2111
2124
|
"offerHint": "Lorsqu'elle est désactivée, {label} est masquée de l'importation et de la liaison.",
|
|
2112
2125
|
"disconnect": "Déconnecter",
|
|
2113
2126
|
"updateConnection": "Mettre à jour la connexion",
|
|
2114
|
-
"connect": "Connecter"
|
|
2127
|
+
"connect": "Connecter",
|
|
2128
|
+
"oauthButton": "Se connecter avec {label}",
|
|
2129
|
+
"oauthOr": "ou connectez-vous avec une clé API"
|
|
2115
2130
|
}
|
|
2116
2131
|
},
|
|
2117
2132
|
"pipeline": {
|
package/i18n/locales/pl.json
CHANGED
|
@@ -789,6 +789,18 @@
|
|
|
789
789
|
"cleared": "Wyczyszczono OAuth Slacka",
|
|
790
790
|
"clearFailed": "Nie udało się wyczyścić OAuth Slacka"
|
|
791
791
|
},
|
|
792
|
+
"linear": {
|
|
793
|
+
"title": "Aplikacja Linear (OAuth)",
|
|
794
|
+
"description": "Włącza przepływ OAuth „Połącz z Linear”. Bez niego przestrzenie robocze nadal mogą połączyć Linear, wklejając osobisty klucz API.",
|
|
795
|
+
"clientId": "Identyfikator klienta",
|
|
796
|
+
"clientSecret": "Sekret klienta",
|
|
797
|
+
"redirectUrl": "Adres URL przekierowania",
|
|
798
|
+
"validation": "Podaj identyfikator klienta, sekret i adres URL przekierowania",
|
|
799
|
+
"saved": "Zapisano OAuth Linear",
|
|
800
|
+
"saveFailed": "Nie udało się zapisać OAuth Linear",
|
|
801
|
+
"cleared": "Wyczyszczono OAuth Linear",
|
|
802
|
+
"clearFailed": "Nie udało się wyczyścić OAuth Linear"
|
|
803
|
+
},
|
|
792
804
|
"web": {
|
|
793
805
|
"title": "Wyszukiwanie w sieci w kontenerze",
|
|
794
806
|
"description": "Dostawca wyszukiwania, do którego agenci w kontenerze sięgają przez proxy backendu. Ustaw klucz Brave (zalecane) lub własny adres URL SearXNG (z opcjonalnym kluczem bearer).",
|
|
@@ -1298,7 +1310,8 @@
|
|
|
1298
1310
|
"jiraProjectKey": "Klucz projektu Jira",
|
|
1299
1311
|
"jiraProjectKeyHelp": "Nowe zgłoszenia są rejestrowane w tym projekcie.",
|
|
1300
1312
|
"linearTeamId": "Identyfikator zespołu Linear",
|
|
1301
|
-
"linearTeamIdHelp": "Nowe zgłoszenia są tworzone w tym zespole (Linear wymaga zespołu do utworzenia zgłoszenia)."
|
|
1313
|
+
"linearTeamIdHelp": "Nowe zgłoszenia są tworzone w tym zespole (Linear wymaga zespołu do utworzenia zgłoszenia).",
|
|
1314
|
+
"linearTeamSearchPlaceholder": "Szukaj zespołów…"
|
|
1302
1315
|
},
|
|
1303
1316
|
"vendor": {
|
|
1304
1317
|
"github": "GitHub Issues",
|
|
@@ -2111,7 +2124,9 @@
|
|
|
2111
2124
|
"offerHint": "Po wyłączeniu {label} jest ukryte przed importem i powiązywaniem.",
|
|
2112
2125
|
"disconnect": "Rozłącz",
|
|
2113
2126
|
"updateConnection": "Zaktualizuj połączenie",
|
|
2114
|
-
"connect": "Połącz"
|
|
2127
|
+
"connect": "Połącz",
|
|
2128
|
+
"oauthButton": "Połącz z {label}",
|
|
2129
|
+
"oauthOr": "lub połącz za pomocą klucza API"
|
|
2115
2130
|
}
|
|
2116
2131
|
},
|
|
2117
2132
|
"pipeline": {
|
package/i18n/locales/uk.json
CHANGED
|
@@ -789,6 +789,18 @@
|
|
|
789
789
|
"cleared": "OAuth Slack очищено",
|
|
790
790
|
"clearFailed": "Не вдалося очистити OAuth Slack"
|
|
791
791
|
},
|
|
792
|
+
"linear": {
|
|
793
|
+
"title": "Застосунок Linear (OAuth)",
|
|
794
|
+
"description": "Вмикає потік OAuth «Підключити через Linear». Без нього робочі простори все одно можуть підключити Linear, вставивши особистий ключ API.",
|
|
795
|
+
"clientId": "ID клієнта",
|
|
796
|
+
"clientSecret": "Секрет клієнта",
|
|
797
|
+
"redirectUrl": "URL перенаправлення",
|
|
798
|
+
"validation": "Введіть ID клієнта, секрет і URL перенаправлення",
|
|
799
|
+
"saved": "OAuth Linear збережено",
|
|
800
|
+
"saveFailed": "Не вдалося зберегти OAuth Linear",
|
|
801
|
+
"cleared": "OAuth Linear очищено",
|
|
802
|
+
"clearFailed": "Не вдалося очистити OAuth Linear"
|
|
803
|
+
},
|
|
792
804
|
"web": {
|
|
793
805
|
"title": "Вебпошук контейнера",
|
|
794
806
|
"description": "Постачальник пошуку, до якого агенти в контейнері звертаються через проксі бекенду. Задайте ключ Brave (рекомендовано) або власний URL SearXNG (з необов'язковим ключем bearer).",
|
|
@@ -1298,7 +1310,8 @@
|
|
|
1298
1310
|
"jiraProjectKey": "Ключ проєкту Jira",
|
|
1299
1311
|
"jiraProjectKeyHelp": "Нові тикети реєструються в цьому проєкті.",
|
|
1300
1312
|
"linearTeamId": "Ідентифікатор команди Linear",
|
|
1301
|
-
"linearTeamIdHelp": "Нові тикети створюються в цій команді (Linear вимагає команду для створення тикета)."
|
|
1313
|
+
"linearTeamIdHelp": "Нові тикети створюються в цій команді (Linear вимагає команду для створення тикета).",
|
|
1314
|
+
"linearTeamSearchPlaceholder": "Пошук команд…"
|
|
1302
1315
|
},
|
|
1303
1316
|
"vendor": {
|
|
1304
1317
|
"github": "GitHub Issues",
|
|
@@ -2111,7 +2124,9 @@
|
|
|
2111
2124
|
"offerHint": "Коли вимкнено, {label} приховано з імпорту та прив'язування.",
|
|
2112
2125
|
"disconnect": "Відключити",
|
|
2113
2126
|
"updateConnection": "Оновити підключення",
|
|
2114
|
-
"connect": "Підключити"
|
|
2127
|
+
"connect": "Підключити",
|
|
2128
|
+
"oauthButton": "Підключити через {label}",
|
|
2129
|
+
"oauthOr": "або підключіться за допомогою ключа API"
|
|
2115
2130
|
}
|
|
2116
2131
|
},
|
|
2117
2132
|
"pipeline": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.48.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",
|
|
@@ -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.
|
|
37
|
+
"@cat-factory/contracts": "0.46.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@toad-contracts/testing": "0.3.2",
|