@cat-factory/app 0.315.3 → 0.315.6
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/README.md +25 -4
- package/app/components/assistant/AssistantModal.vue +3 -2
- package/app/components/board/AddTaskModal.vue +3 -2
- package/app/components/board/CreateInitiativeModal.vue +3 -2
- package/app/components/board/RecurringPipelineModal.vue +3 -2
- package/app/components/board/ReviewFrictionDialog.vue +4 -3
- package/app/components/bootstrap/AdoptionReviewModal.vue +2 -0
- package/app/components/bootstrap/BootstrapModal.vue +4 -3
- package/app/components/common/AppModal.vue +50 -0
- package/app/components/common/ConfirmDialog.vue +5 -3
- package/app/components/common/KeyboardShortcutsHelp.vue +6 -4
- package/app/components/documents/DocumentImportModal.vue +3 -2
- package/app/components/documents/DocumentSourceConnectModal.vue +7 -2
- package/app/components/documents/DocumentTemplatesModal.vue +3 -2
- package/app/components/documents/SpawnPreviewModal.vue +3 -2
- package/app/components/documents/StartFromDesignModal.vue +3 -2
- package/app/components/environments/EnvironmentSetupWizard.vue +2 -0
- package/app/components/foundational/FoundationalServicePanel.vue +2 -0
- package/app/components/fragments/FragmentLibraryPanel.vue +2 -0
- package/app/components/github/AddServiceFromRepoModal.vue +5 -4
- package/app/components/github/GitHubPanel.vue +4 -3
- package/app/components/layout/BoardSwitcher.vue +7 -2
- package/app/components/layout/CommandBar.vue +3 -2
- package/app/components/layout/IntegrationsHub.vue +3 -6
- package/app/components/layout/ModelProvidersHub.vue +3 -6
- package/app/components/layout/PersonalSetupModal.vue +3 -6
- package/app/components/layout/RolePrompt.vue +3 -2
- package/app/components/notifications/NotificationSettingsPanel.vue +3 -6
- package/app/components/panels/DecisionModal.vue +3 -2
- package/app/components/panels/InspectorPanel.vue +6 -1
- package/app/components/panels/inspector/ServiceTestConfig.vue +6 -4
- package/app/components/pipeline/AgentPromptEditor.vue +2 -0
- package/app/components/pipeline/PipelineBuilder.vue +11 -2
- package/app/components/pipeline/PipelineHealthModal.vue +3 -2
- package/app/components/providers/AiPresetMismatchDialog.vue +3 -6
- package/app/components/providers/AiProviderOnboardingModal.vue +3 -6
- package/app/components/providers/PersonalCredentialModal.vue +3 -2
- package/app/components/providers/VendorCredentialsModal.vue +3 -6
- package/app/components/queue/DescribeWorkModal.vue +3 -2
- package/app/components/sandbox/SandboxPanel.vue +2 -0
- package/app/components/settings/AccountSettingsPanel.vue +1 -0
- package/app/components/settings/ApiTokensPanel.vue +3 -2
- package/app/components/settings/InfrastructureWindow.vue +3 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +3 -6
- package/app/components/settings/ModelConfigurationPanel.vue +9 -1
- package/app/components/settings/ModelPresetHealthModal.vue +3 -2
- package/app/components/settings/ObservabilityConnectionPanel.vue +3 -6
- package/app/components/settings/OpenRouterCatalogPanel.vue +3 -2
- package/app/components/settings/RiskPolicyHealthModal.vue +3 -2
- package/app/components/settings/UserSecretsSection.vue +3 -6
- package/app/components/settings/WorkspaceSettingsPanel.vue +1 -0
- package/app/components/setup/SetupChecklistPanel.vue +3 -2
- package/app/components/slack/SlackPanel.vue +3 -2
- package/app/components/tasks/BugHuntModal.vue +2 -0
- package/app/components/tasks/TaskImportModal.vue +3 -2
- package/app/components/tasks/TaskSourceConnectModal.vue +3 -2
- package/app/components/theme/ThemeImportModal.vue +4 -2
- package/app/components/tutorial/TutorialCatalogue.vue +4 -3
- package/app/components/tutorial/TutorialPrompt.vue +3 -2
- package/app/stores/github/connection.ts +2 -4
- package/app/stores/github/context.ts +5 -1
- package/app/stores/github/projectionLoad.ts +127 -0
- package/app/stores/github/repoActions.ts +7 -2
- package/app/stores/github.spec.ts +355 -1
- package/app/stores/github.ts +21 -22
- package/app/stores/ui/builderModelConfigHandoff.spec.ts +88 -0
- package/app/stores/ui/modals.ts +78 -12
- package/app/utils/overlaySize.ts +22 -0
- package/i18n/locales/de.json +1 -0
- package/i18n/locales/en.json +1 -0
- package/i18n/locales/es.json +1 -0
- package/i18n/locales/fr.json +1 -0
- package/i18n/locales/he.json +1 -0
- package/i18n/locales/it.json +1 -0
- package/i18n/locales/ja.json +1 -0
- package/i18n/locales/pl.json +1 -0
- package/i18n/locales/tr.json +1 -0
- package/i18n/locales/uk.json +1 -0
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { showOverrideField } from '~/utils/uiMode'
|
|
3
3
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
4
4
|
import EmptyState from '~/components/common/EmptyState.vue'
|
|
5
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
5
6
|
|
|
6
7
|
// The Integrations hub: a single modal that lists the OPTIONAL external systems the WORKSPACE
|
|
7
8
|
// can enable or link in — the ones that feed a run its context (source control, documents,
|
|
@@ -370,11 +371,7 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
370
371
|
</script>
|
|
371
372
|
|
|
372
373
|
<template>
|
|
373
|
-
<
|
|
374
|
-
v-model:open="open"
|
|
375
|
-
:title="t('layout.integrationsHub.title')"
|
|
376
|
-
:ui="{ content: 'max-w-xl' }"
|
|
377
|
-
>
|
|
374
|
+
<AppModal size="form" v-model:open="open" :title="t('layout.integrationsHub.title')">
|
|
378
375
|
<template #body>
|
|
379
376
|
<!-- Named for the same reason `model-providers-hub` is: the tutorial tour that explains
|
|
380
377
|
what a connection adds to a run points at this list. -->
|
|
@@ -489,5 +486,5 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
489
486
|
</section>
|
|
490
487
|
</div>
|
|
491
488
|
</template>
|
|
492
|
-
</
|
|
489
|
+
</AppModal>
|
|
493
490
|
</template>
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// hub row-for-row so the two read as siblings.
|
|
15
15
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
16
16
|
import EmptyState from '~/components/common/EmptyState.vue'
|
|
17
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
17
18
|
|
|
18
19
|
const { t } = useI18n()
|
|
19
20
|
const ui = useUiStore()
|
|
@@ -167,11 +168,7 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
167
168
|
</script>
|
|
168
169
|
|
|
169
170
|
<template>
|
|
170
|
-
<
|
|
171
|
-
v-model:open="open"
|
|
172
|
-
:title="t('layout.modelProvidersHub.title')"
|
|
173
|
-
:ui="{ content: 'max-w-xl' }"
|
|
174
|
-
>
|
|
171
|
+
<AppModal size="form" v-model:open="open" :title="t('layout.modelProvidersHub.title')">
|
|
175
172
|
<template #body>
|
|
176
173
|
<div class="space-y-5" data-testid="model-providers-hub">
|
|
177
174
|
<p class="text-xs text-muted">
|
|
@@ -245,5 +242,5 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
245
242
|
</section>
|
|
246
243
|
</div>
|
|
247
244
|
</template>
|
|
248
|
-
</
|
|
245
|
+
</AppModal>
|
|
249
246
|
</template>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// existing per-panel handlers via `ui.openFromPersonal(...)`, so opening one closes this
|
|
7
7
|
// hub, reveals that panel, and gives it a "Back to My setup" control (IntegrationBackTitle).
|
|
8
8
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
const ui = useUiStore()
|
|
@@ -107,11 +108,7 @@ const groups = computed<PersonalGroup[]>(() => {
|
|
|
107
108
|
</script>
|
|
108
109
|
|
|
109
110
|
<template>
|
|
110
|
-
<
|
|
111
|
-
v-model:open="open"
|
|
112
|
-
:title="t('layout.personalSetup.title')"
|
|
113
|
-
:ui="{ content: 'max-w-xl' }"
|
|
114
|
-
>
|
|
111
|
+
<AppModal size="form" v-model:open="open" :title="t('layout.personalSetup.title')">
|
|
115
112
|
<template #body>
|
|
116
113
|
<div class="space-y-5">
|
|
117
114
|
<p class="text-xs text-muted">
|
|
@@ -153,5 +150,5 @@ const groups = computed<PersonalGroup[]>(() => {
|
|
|
153
150
|
</section>
|
|
154
151
|
</div>
|
|
155
152
|
</template>
|
|
156
|
-
</
|
|
153
|
+
</AppModal>
|
|
157
154
|
</template>
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// next launch asks again. There is deliberately no "don't ask me again": an unanswered question
|
|
12
12
|
// costs nothing here, where a wrongly-recorded answer costs a person destinations they need.
|
|
13
13
|
import { ROLE_PRESENTATION, UI_ROLES, type UiRole } from '~/utils/uiRole'
|
|
14
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
14
15
|
|
|
15
16
|
const { t } = useI18n()
|
|
16
17
|
const uiRole = useUiRoleStore()
|
|
@@ -26,7 +27,7 @@ function pick(role: UiRole) {
|
|
|
26
27
|
</script>
|
|
27
28
|
|
|
28
29
|
<template>
|
|
29
|
-
<
|
|
30
|
+
<AppModal size="prompt" v-model:open="open" :title="t('uiRole.prompt.title')">
|
|
30
31
|
<template #body>
|
|
31
32
|
<div class="space-y-4" data-testid="role-prompt">
|
|
32
33
|
<p class="text-sm text-toned">{{ t('uiRole.prompt.intro') }}</p>
|
|
@@ -72,5 +73,5 @@ function pick(role: UiRole) {
|
|
|
72
73
|
</UButton>
|
|
73
74
|
</div>
|
|
74
75
|
</template>
|
|
75
|
-
</
|
|
76
|
+
</AppModal>
|
|
76
77
|
</template>
|
|
@@ -26,6 +26,7 @@ import type {
|
|
|
26
26
|
} from '~/types/notifications'
|
|
27
27
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
28
28
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
29
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
29
30
|
|
|
30
31
|
const ui = useUiStore()
|
|
31
32
|
const notifications = useNotificationsStore()
|
|
@@ -134,11 +135,7 @@ function resetToDefaults() {
|
|
|
134
135
|
</script>
|
|
135
136
|
|
|
136
137
|
<template>
|
|
137
|
-
<
|
|
138
|
-
v-model:open="open"
|
|
139
|
-
:title="t('notificationSettings.panel.title')"
|
|
140
|
-
:ui="{ content: 'max-w-2xl' }"
|
|
141
|
-
>
|
|
138
|
+
<AppModal size="form" v-model:open="open" :title="t('notificationSettings.panel.title')">
|
|
142
139
|
<template #title>
|
|
143
140
|
<IntegrationBackTitle :title="t('notificationSettings.panel.title')" @back="back" />
|
|
144
141
|
</template>
|
|
@@ -235,5 +232,5 @@ function resetToDefaults() {
|
|
|
235
232
|
</template>
|
|
236
233
|
</div>
|
|
237
234
|
</template>
|
|
238
|
-
</
|
|
235
|
+
</AppModal>
|
|
239
236
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { agentKindMeta } from '~/utils/catalog'
|
|
3
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
3
4
|
|
|
4
5
|
const execution = useExecutionStore()
|
|
5
6
|
const board = useBoardStore()
|
|
@@ -52,7 +53,7 @@ async function choose(option: string) {
|
|
|
52
53
|
</script>
|
|
53
54
|
|
|
54
55
|
<template>
|
|
55
|
-
<
|
|
56
|
+
<AppModal size="prompt" v-model:open="open" :title="t('panels.decision.title')">
|
|
56
57
|
<template #body>
|
|
57
58
|
<div v-if="decision && agent" class="space-y-4" data-testid="decision-modal">
|
|
58
59
|
<div class="flex items-center gap-2 text-sm text-muted">
|
|
@@ -97,5 +98,5 @@ async function choose(option: string) {
|
|
|
97
98
|
</p>
|
|
98
99
|
</div>
|
|
99
100
|
</template>
|
|
100
|
-
</
|
|
101
|
+
</AppModal>
|
|
101
102
|
</template>
|
|
@@ -24,10 +24,15 @@ const recurring = useRecurringPipelinesStore()
|
|
|
24
24
|
const requirements = useRequirementsStore()
|
|
25
25
|
const access = useWorkspaceAccess()
|
|
26
26
|
const { t } = useI18n()
|
|
27
|
+
const { present } = usePipelineErrorToast()
|
|
27
28
|
|
|
28
29
|
onMounted(() => {
|
|
29
30
|
fragments.ensureLoaded()
|
|
30
|
-
|
|
31
|
+
// The repo list behind the inspector's repo link and the service config's detect-from-repo
|
|
32
|
+
// lookup. Both read the store, so this one call serves them.
|
|
33
|
+
github.ensureLoaded().catch((error: unknown) => {
|
|
34
|
+
present(error, 'github.connect.errors.loadProjection')
|
|
35
|
+
})
|
|
31
36
|
})
|
|
32
37
|
|
|
33
38
|
const block = computed<Block | undefined>(() =>
|
|
@@ -21,6 +21,7 @@ import InspectorSection from '~/components/panels/inspector/InspectorSection.vue
|
|
|
21
21
|
import ServiceSelfTests from '~/components/panels/inspector/ServiceSelfTests.vue'
|
|
22
22
|
import IconButton from '~/components/common/IconButton.vue'
|
|
23
23
|
import { apiErrorEnvelope } from '~/composables/api/errors'
|
|
24
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
24
25
|
|
|
25
26
|
// Service-level (frame) configuration: the service-owned PROVISIONING — the provision
|
|
26
27
|
// TYPE this service produces (`infraless` / `docker-compose` / `kubernetes` / `custom`)
|
|
@@ -49,10 +50,10 @@ const ui = useUiStore()
|
|
|
49
50
|
const { t, te } = useI18n()
|
|
50
51
|
|
|
51
52
|
// The custom-manifest-type catalog feeds the `custom` picker. Cheap + shared (coalesced).
|
|
52
|
-
// The repo list
|
|
53
|
+
// The repo list behind the detect-from-repo affordance (owner/name lookup) is loaded by the
|
|
54
|
+
// surface that hosts this section: the inspector panel, or the add-service modal on open.
|
|
53
55
|
onMounted(() => {
|
|
54
56
|
void infra.ensureLoaded()
|
|
55
|
-
void github.ensureLoaded()
|
|
56
57
|
})
|
|
57
58
|
|
|
58
59
|
// The service's declared provision type (absent ⇒ treated as `infraless`: no environment
|
|
@@ -840,7 +841,8 @@ function setSize(value: InstanceSize) {
|
|
|
840
841
|
</div>
|
|
841
842
|
</div>
|
|
842
843
|
|
|
843
|
-
<
|
|
844
|
+
<AppModal
|
|
845
|
+
size="form"
|
|
844
846
|
v-model:open="browseOpen"
|
|
845
847
|
:title="
|
|
846
848
|
browseTarget === 'compose'
|
|
@@ -880,7 +882,7 @@ function setSize(value: InstanceSize) {
|
|
|
880
882
|
</div>
|
|
881
883
|
</div>
|
|
882
884
|
</template>
|
|
883
|
-
</
|
|
885
|
+
</AppModal>
|
|
884
886
|
|
|
885
887
|
<!-- Provisioning hints: advisory inputs to the ephemeral-environment provisioner.
|
|
886
888
|
Collapsed by default — most services never tune them. -->
|
|
@@ -170,6 +170,8 @@ function revisionLabel(revision: AgentPromptRevision): string {
|
|
|
170
170
|
</script>
|
|
171
171
|
|
|
172
172
|
<template>
|
|
173
|
+
<!-- workbench-width-ok: a prompt editor, up to 1024px on a large screen. Its shell waits on
|
|
174
|
+
#2359. -->
|
|
173
175
|
<UModal
|
|
174
176
|
v-model:open="open"
|
|
175
177
|
:title="t('agentPrompt.title', { agent: label })"
|
|
@@ -31,6 +31,7 @@ import type { ConsensusStrategy } from '~/types/consensus'
|
|
|
31
31
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
32
32
|
import IconButton from '~/components/common/IconButton.vue'
|
|
33
33
|
import EmptyState from '~/components/common/EmptyState.vue'
|
|
34
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
34
35
|
|
|
35
36
|
type DraftUnit = { index: number; kind: AgentKind; companionIndex: number | null }
|
|
36
37
|
|
|
@@ -251,6 +252,8 @@ const open = computed({
|
|
|
251
252
|
// knows whether to offer the post-release-health gate (it's loaded on demand, not from
|
|
252
253
|
// the snapshot). Best-effort: a failure just leaves the gate hidden.
|
|
253
254
|
onModalOpen(open, () => {
|
|
255
|
+
// Coming back from the model configuration, where none of this changed.
|
|
256
|
+
if (ui.consumeBuilderReturn()) return
|
|
254
257
|
releaseHealth.load().catch(() => {})
|
|
255
258
|
// The prompt-override index badges the steps whose agent no longer runs the shipped prompt.
|
|
256
259
|
// Best-effort: the builder is fully usable without it, and a deployment that wires no
|
|
@@ -403,6 +406,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
403
406
|
:title="t('pipeline.builder.title')"
|
|
404
407
|
side="left"
|
|
405
408
|
:ui="{ content: 'max-w-[90vw] sm:max-w-2xl lg:max-w-5xl xl:max-w-6xl' }"
|
|
409
|
+
@after:leave="ui.builderLeft()"
|
|
406
410
|
>
|
|
407
411
|
<template #body>
|
|
408
412
|
<!-- On compact viewports the three sections stack and the slideover body
|
|
@@ -442,6 +446,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
442
446
|
size="xs"
|
|
443
447
|
icon="i-lucide-cpu"
|
|
444
448
|
:title="t('pipeline.builder.configureModelsTooltip')"
|
|
449
|
+
data-testid="pipeline-builder-configure-models"
|
|
445
450
|
@click="ui.openModelConfig()"
|
|
446
451
|
>
|
|
447
452
|
{{ t('pipeline.builder.configureModels') }}
|
|
@@ -1392,7 +1397,11 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1392
1397
|
</USlideover>
|
|
1393
1398
|
|
|
1394
1399
|
<!-- Add-agent form -->
|
|
1395
|
-
<
|
|
1400
|
+
<AppModal
|
|
1401
|
+
size="prompt"
|
|
1402
|
+
v-model:open="addAgentOpen"
|
|
1403
|
+
:title="t('pipeline.builder.addAgentModal.title')"
|
|
1404
|
+
>
|
|
1396
1405
|
<template #body>
|
|
1397
1406
|
<div class="space-y-3">
|
|
1398
1407
|
<div>
|
|
@@ -1456,7 +1465,7 @@ const { toggleArchive, toggleDefault, edit, removePipeline, clone } = usePipelin
|
|
|
1456
1465
|
</UButton>
|
|
1457
1466
|
</div>
|
|
1458
1467
|
</template>
|
|
1459
|
-
</
|
|
1468
|
+
</AppModal>
|
|
1460
1469
|
|
|
1461
1470
|
<!-- The per-workspace system-prompt editor for one agent kind. Mounted alongside the builder
|
|
1462
1471
|
(not inside its slideover body) so its own modal isn't nested inside the scrolling column. -->
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
2
3
|
// Startup advisory for unhealthy pipelines. Opened once per session from the board page when
|
|
3
4
|
// `usePipelineHealth` reports any issue. Lists:
|
|
4
5
|
// • new built-in pipelines the workspace doesn't have yet (ADD them);
|
|
@@ -121,7 +122,7 @@ const reseedableCount = computed(
|
|
|
121
122
|
</script>
|
|
122
123
|
|
|
123
124
|
<template>
|
|
124
|
-
<
|
|
125
|
+
<AppModal size="form" v-model:open="open" :title="t('pipeline.health.title')">
|
|
125
126
|
<template #body>
|
|
126
127
|
<div v-if="!hasIssues" class="py-6 text-center text-sm text-muted">
|
|
127
128
|
<UIcon name="i-lucide-check-circle-2" class="mx-auto mb-2 h-8 w-8 text-app-success-400" />
|
|
@@ -331,5 +332,5 @@ const reseedableCount = computed(
|
|
|
331
332
|
</UButton>
|
|
332
333
|
</div>
|
|
333
334
|
</template>
|
|
334
|
-
</
|
|
335
|
+
</AppModal>
|
|
335
336
|
</template>
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// fixed (or all its models become available).
|
|
9
9
|
import { computed } from 'vue'
|
|
10
10
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
11
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
11
12
|
|
|
12
13
|
const { t } = useI18n()
|
|
13
14
|
const ui = useUiStore()
|
|
@@ -36,11 +37,7 @@ function go(action: () => void) {
|
|
|
36
37
|
</script>
|
|
37
38
|
|
|
38
39
|
<template>
|
|
39
|
-
<
|
|
40
|
-
v-model:open="open"
|
|
41
|
-
:title="t('providers.presetMismatch.title')"
|
|
42
|
-
:ui="{ content: 'max-w-xl' }"
|
|
43
|
-
>
|
|
40
|
+
<AppModal size="prompt" v-model:open="open" :title="t('providers.presetMismatch.title')">
|
|
44
41
|
<template #body>
|
|
45
42
|
<div class="space-y-5">
|
|
46
43
|
<i18n-t
|
|
@@ -103,5 +100,5 @@ function go(action: () => void) {
|
|
|
103
100
|
</div>
|
|
104
101
|
</div>
|
|
105
102
|
</template>
|
|
106
|
-
</
|
|
103
|
+
</AppModal>
|
|
107
104
|
</template>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// duplicating them). It auto-opens once per session (driven from pages/index.vue) and, like
|
|
7
7
|
// the banner, disappears automatically the moment a usable source exists.
|
|
8
8
|
import { computed } from 'vue'
|
|
9
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
const ui = useUiStore()
|
|
@@ -75,11 +76,7 @@ const routes = computed<Route[]>(() => [
|
|
|
75
76
|
</script>
|
|
76
77
|
|
|
77
78
|
<template>
|
|
78
|
-
<
|
|
79
|
-
v-model:open="open"
|
|
80
|
-
:title="t('providers.onboarding.title')"
|
|
81
|
-
:ui="{ content: 'max-w-2xl' }"
|
|
82
|
-
>
|
|
79
|
+
<AppModal size="wide" v-model:open="open" :title="t('providers.onboarding.title')">
|
|
83
80
|
<template #body>
|
|
84
81
|
<div class="space-y-5">
|
|
85
82
|
<div
|
|
@@ -123,5 +120,5 @@ const routes = computed<Route[]>(() => [
|
|
|
123
120
|
</p>
|
|
124
121
|
</div>
|
|
125
122
|
</template>
|
|
126
|
-
</
|
|
123
|
+
</AppModal>
|
|
127
124
|
</template>
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// password. The copy follows the pending vendor (Claude / GLM / ChatGPT-Codex).
|
|
7
7
|
import { computed, ref } from 'vue'
|
|
8
8
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
9
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
const personal = usePersonalSubscriptionsStore()
|
|
@@ -85,7 +86,7 @@ function goConnect() {
|
|
|
85
86
|
</script>
|
|
86
87
|
|
|
87
88
|
<template>
|
|
88
|
-
<
|
|
89
|
+
<AppModal size="prompt" v-model:open="open" :title="title">
|
|
89
90
|
<template #body>
|
|
90
91
|
<div class="space-y-4">
|
|
91
92
|
<template v-if="needsConnect">
|
|
@@ -141,5 +142,5 @@ function goConnect() {
|
|
|
141
142
|
</template>
|
|
142
143
|
</div>
|
|
143
144
|
</template>
|
|
144
|
-
</
|
|
145
|
+
</AppModal>
|
|
145
146
|
</template>
|
|
@@ -10,6 +10,7 @@ import type { SubscriptionVendor } from '~/types/domain'
|
|
|
10
10
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
11
11
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
12
12
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
13
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
13
14
|
|
|
14
15
|
const { t, n } = useI18n()
|
|
15
16
|
const ui = useUiStore()
|
|
@@ -173,11 +174,7 @@ function vendorLabel(v: SubscriptionVendor): string {
|
|
|
173
174
|
</script>
|
|
174
175
|
|
|
175
176
|
<template>
|
|
176
|
-
<
|
|
177
|
-
v-model:open="open"
|
|
178
|
-
:title="t('providers.vendorCredentials.title')"
|
|
179
|
-
:ui="{ content: 'max-w-2xl' }"
|
|
180
|
-
>
|
|
177
|
+
<AppModal size="wide" v-model:open="open" :title="t('providers.vendorCredentials.title')">
|
|
181
178
|
<template #title>
|
|
182
179
|
<IntegrationBackTitle :title="t('providers.vendorCredentials.title')" @back="back" />
|
|
183
180
|
</template>
|
|
@@ -337,5 +334,5 @@ function vendorLabel(v: SubscriptionVendor): string {
|
|
|
337
334
|
</template>
|
|
338
335
|
</UTabs>
|
|
339
336
|
</template>
|
|
340
|
-
</
|
|
337
|
+
</AppModal>
|
|
341
338
|
</template>
|
|
@@ -6,6 +6,7 @@ import { splitDescribedWork } from '~/utils/describeWork'
|
|
|
6
6
|
import { isReviewDebtConflict, reviewFrictionContext } from '~/utils/reviewFriction'
|
|
7
7
|
import { pipelineAllowedForManualStart } from '~/utils/pipeline'
|
|
8
8
|
import { showOverrideField } from '~/utils/uiMode'
|
|
9
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* The one-sentence intake (issue #2258): what needs doing, which service, feature or bug. Nothing else on the
|
|
@@ -220,7 +221,7 @@ async function submit(startNow: boolean, acknowledgeReviewDebt = false) {
|
|
|
220
221
|
</script>
|
|
221
222
|
|
|
222
223
|
<template>
|
|
223
|
-
<
|
|
224
|
+
<AppModal size="wide" v-model:open="open" :title="t('describeWork.title')">
|
|
224
225
|
<template #body>
|
|
225
226
|
<div class="space-y-4" data-testid="describe-work-modal">
|
|
226
227
|
<UFormField :label="t('describeWork.textLabel')" :description="t('describeWork.textHint')">
|
|
@@ -363,5 +364,5 @@ async function submit(startNow: boolean, acknowledgeReviewDebt = false) {
|
|
|
363
364
|
</UButton>
|
|
364
365
|
</div>
|
|
365
366
|
</template>
|
|
366
|
-
</
|
|
367
|
+
</AppModal>
|
|
367
368
|
</template>
|
|
@@ -272,6 +272,8 @@ async function archive(prompt: SandboxPromptVersion) {
|
|
|
272
272
|
</script>
|
|
273
273
|
|
|
274
274
|
<template>
|
|
275
|
+
<!-- workbench-width-ok: experiments, prompts and fixtures with a graded grid (1024px). Its
|
|
276
|
+
shell waits on #2359. -->
|
|
275
277
|
<UModal
|
|
276
278
|
v-model:open="open"
|
|
277
279
|
:title="t('sandbox.title')"
|
|
@@ -59,6 +59,7 @@ const tabs = computed(() => [
|
|
|
59
59
|
</script>
|
|
60
60
|
|
|
61
61
|
<template>
|
|
62
|
+
<!-- workbench-width-ok: tabbed account settings (768px). Its shell waits on #2359. -->
|
|
62
63
|
<UModal v-model:open="open" :title="t('settings.account.title')" :ui="{ content: 'max-w-3xl' }">
|
|
63
64
|
<template #body>
|
|
64
65
|
<EmptyState
|
|
@@ -9,6 +9,7 @@ import { showOverrideField } from '~/utils/uiMode'
|
|
|
9
9
|
import type { PublicApiKey, PublicApiScope } from '~/types/publicApiKeys'
|
|
10
10
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
11
11
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
12
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
12
13
|
|
|
13
14
|
const { t, d } = useI18n()
|
|
14
15
|
|
|
@@ -227,7 +228,7 @@ async function revokeToken(key: PublicApiKey) {
|
|
|
227
228
|
</script>
|
|
228
229
|
|
|
229
230
|
<template>
|
|
230
|
-
<
|
|
231
|
+
<AppModal size="form" v-model:open="open" :title="t('settings.apiTokens.title')">
|
|
231
232
|
<template #title>
|
|
232
233
|
<IntegrationBackTitle :title="t('settings.apiTokens.title')" @back="back" />
|
|
233
234
|
</template>
|
|
@@ -416,5 +417,5 @@ async function revokeToken(key: PublicApiKey) {
|
|
|
416
417
|
</section>
|
|
417
418
|
</div>
|
|
418
419
|
</template>
|
|
419
|
-
</
|
|
420
|
+
</AppModal>
|
|
420
421
|
</template>
|
|
@@ -37,6 +37,7 @@ import SharedStacksPanel from '~/components/settings/SharedStacksPanel.vue'
|
|
|
37
37
|
import ComposeEnvironmentSetupSection from '~/components/settings/ComposeEnvironmentSetupSection.vue'
|
|
38
38
|
import PackageRegistriesPanel from '~/components/settings/PackageRegistriesPanel.vue'
|
|
39
39
|
import CapabilityCredentialsPanel from '~/components/settings/CapabilityCredentialsPanel.vue'
|
|
40
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
40
41
|
|
|
41
42
|
const { t } = useI18n()
|
|
42
43
|
const ui = useUiStore()
|
|
@@ -152,11 +153,7 @@ watch([tabs, () => store.loaded], () => {
|
|
|
152
153
|
</script>
|
|
153
154
|
|
|
154
155
|
<template>
|
|
155
|
-
<
|
|
156
|
-
v-model:open="open"
|
|
157
|
-
:title="t('settings.providerConnection.windowTitle')"
|
|
158
|
-
:ui="{ content: 'max-w-xl' }"
|
|
159
|
-
>
|
|
156
|
+
<AppModal size="form" v-model:open="open" :title="t('settings.providerConnection.windowTitle')">
|
|
160
157
|
<template #body>
|
|
161
158
|
<div class="space-y-4">
|
|
162
159
|
<UTabs
|
|
@@ -218,5 +215,5 @@ watch([tabs, () => store.loaded], () => {
|
|
|
218
215
|
</p>
|
|
219
216
|
</div>
|
|
220
217
|
</template>
|
|
221
|
-
</
|
|
218
|
+
</AppModal>
|
|
222
219
|
</template>
|
|
@@ -19,6 +19,7 @@ import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
|
19
19
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
20
20
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
21
21
|
import IconButton from '~/components/common/IconButton.vue'
|
|
22
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
22
23
|
|
|
23
24
|
const { t } = useI18n()
|
|
24
25
|
const ui = useUiStore()
|
|
@@ -269,11 +270,7 @@ async function remove(p: LocalRunner) {
|
|
|
269
270
|
</script>
|
|
270
271
|
|
|
271
272
|
<template>
|
|
272
|
-
<
|
|
273
|
-
v-model:open="open"
|
|
274
|
-
:title="t('settings.localModelEndpoints.title')"
|
|
275
|
-
:ui="{ content: 'max-w-2xl' }"
|
|
276
|
-
>
|
|
273
|
+
<AppModal size="form" v-model:open="open" :title="t('settings.localModelEndpoints.title')">
|
|
277
274
|
<template #title>
|
|
278
275
|
<IntegrationBackTitle :title="t('settings.localModelEndpoints.title')" @back="back" />
|
|
279
276
|
</template>
|
|
@@ -483,5 +480,5 @@ async function remove(p: LocalRunner) {
|
|
|
483
480
|
</div>
|
|
484
481
|
</div>
|
|
485
482
|
</template>
|
|
486
|
-
</
|
|
483
|
+
</AppModal>
|
|
487
484
|
</template>
|
|
@@ -311,6 +311,7 @@ async function save() {
|
|
|
311
311
|
<Transition name="reader-fade">
|
|
312
312
|
<div
|
|
313
313
|
v-if="open"
|
|
314
|
+
data-testid="model-configuration-panel"
|
|
314
315
|
class="z-50 flex-col bg-app-950/96 backdrop-blur-sm"
|
|
315
316
|
:class="FULL_BLEED_TAKEOVER_CLASS"
|
|
316
317
|
role="dialog"
|
|
@@ -377,7 +378,13 @@ async function save() {
|
|
|
377
378
|
</template>
|
|
378
379
|
</i18n-t>
|
|
379
380
|
</p>
|
|
380
|
-
<UButton
|
|
381
|
+
<UButton
|
|
382
|
+
icon="i-lucide-plus"
|
|
383
|
+
size="sm"
|
|
384
|
+
class="shrink-0"
|
|
385
|
+
data-testid="model-preset-new"
|
|
386
|
+
@click="startCreate"
|
|
387
|
+
>
|
|
381
388
|
{{ t('settings.modelConfiguration.list.newPreset') }}
|
|
382
389
|
</UButton>
|
|
383
390
|
</div>
|
|
@@ -491,6 +498,7 @@ async function save() {
|
|
|
491
498
|
</SectionLabel>
|
|
492
499
|
<UInput
|
|
493
500
|
v-model="editor.name"
|
|
501
|
+
data-testid="model-preset-name"
|
|
494
502
|
:placeholder="t('settings.modelConfiguration.editor.namePlaceholder')"
|
|
495
503
|
size="sm"
|
|
496
504
|
class="w-full"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
2
3
|
// Startup advisory for built-in model presets that drifted from the catalog. Opened once per
|
|
3
4
|
// session from the board page when `useModelPresetHealth` reports any issue. Lists:
|
|
4
5
|
// • new built-in presets the workspace doesn't have yet (ADD them);
|
|
@@ -57,7 +58,7 @@ const reseedableCount = computed(
|
|
|
57
58
|
</script>
|
|
58
59
|
|
|
59
60
|
<template>
|
|
60
|
-
<
|
|
61
|
+
<AppModal size="form" v-model:open="open" :title="t('modelPreset.health.title')">
|
|
61
62
|
<template #body>
|
|
62
63
|
<div v-if="!hasIssues" class="py-6 text-center text-sm text-muted">
|
|
63
64
|
<UIcon name="i-lucide-check-circle-2" class="mx-auto mb-2 h-8 w-8 text-app-success-400" />
|
|
@@ -165,5 +166,5 @@ const reseedableCount = computed(
|
|
|
165
166
|
</UButton>
|
|
166
167
|
</div>
|
|
167
168
|
</template>
|
|
168
|
-
</
|
|
169
|
+
</AppModal>
|
|
169
170
|
</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
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
11
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
11
12
|
|
|
12
13
|
const { t } = useI18n()
|
|
13
14
|
const ui = useUiStore()
|
|
@@ -136,11 +137,7 @@ const connectedLabel = computed(() => {
|
|
|
136
137
|
</script>
|
|
137
138
|
|
|
138
139
|
<template>
|
|
139
|
-
<
|
|
140
|
-
v-model:open="open"
|
|
141
|
-
:title="t('settings.observabilityConnection.title')"
|
|
142
|
-
:ui="{ content: 'max-w-lg' }"
|
|
143
|
-
>
|
|
140
|
+
<AppModal size="form" v-model:open="open" :title="t('settings.observabilityConnection.title')">
|
|
144
141
|
<template #title>
|
|
145
142
|
<IntegrationBackTitle :title="t('settings.observabilityConnection.title')" @back="back" />
|
|
146
143
|
</template>
|
|
@@ -261,5 +258,5 @@ const connectedLabel = computed(() => {
|
|
|
261
258
|
</section>
|
|
262
259
|
</div>
|
|
263
260
|
</template>
|
|
264
|
-
</
|
|
261
|
+
</AppModal>
|
|
265
262
|
</template>
|
|
@@ -12,6 +12,7 @@ import type { OpenRouterModelMeta } from '~/types/openrouter'
|
|
|
12
12
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
13
13
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
14
14
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
|
+
import AppModal from '~/components/common/AppModal.vue'
|
|
15
16
|
|
|
16
17
|
const { t } = useI18n()
|
|
17
18
|
const ui = useUiStore()
|
|
@@ -205,7 +206,7 @@ function manageKeys() {
|
|
|
205
206
|
</script>
|
|
206
207
|
|
|
207
208
|
<template>
|
|
208
|
-
<
|
|
209
|
+
<AppModal size="form" v-model:open="open" title="OpenRouter">
|
|
209
210
|
<template #title>
|
|
210
211
|
<IntegrationBackTitle title="OpenRouter" @back="back" />
|
|
211
212
|
</template>
|
|
@@ -387,5 +388,5 @@ function manageKeys() {
|
|
|
387
388
|
</template>
|
|
388
389
|
</div>
|
|
389
390
|
</template>
|
|
390
|
-
</
|
|
391
|
+
</AppModal>
|
|
391
392
|
</template>
|