@cat-factory/app 0.311.1 → 0.311.3
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 +70 -5
- package/app/app.config.ts +6 -18
- package/app/components/assistant/AssistantModal.vue +2 -5
- package/app/components/auth/AuthGate.vue +2 -1
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +14 -15
- package/app/components/binaryOutput/StoredAssetView.vue +1 -3
- package/app/components/board/AddTaskModal.vue +3 -10
- package/app/components/board/AgentFailureCard.vue +4 -5
- package/app/components/board/AgentStopButton.vue +5 -7
- package/app/components/board/BoardCanvas.vue +31 -30
- package/app/components/board/CreateInitiativeModal.vue +2 -4
- package/app/components/board/RecurringPipelineModal.vue +2 -7
- package/app/components/board/nodes/AgentChip.vue +3 -2
- package/app/components/board/nodes/BlockNode.vue +14 -11
- package/app/components/board/nodes/InitiativeCard.vue +6 -3
- package/app/components/bootstrap/AdoptionReviewModal.vue +4 -7
- package/app/components/bootstrap/BootstrapModal.vue +6 -15
- package/app/components/bootstrap/BootstrapRunSteps.vue +3 -1
- package/app/components/brainstorm/BrainstormWindow.vue +32 -26
- package/app/components/bugFishing/BugFishingWindow.vue +15 -13
- package/app/components/clarity/ClarityReviewWindow.vue +31 -26
- package/app/components/common/AsyncViewError.vue +1 -1
- package/app/components/common/ClarificationItem.vue +3 -1
- package/app/components/common/EmptyState.vue +41 -19
- package/app/components/common/InterviewGateNotice.vue +3 -1
- package/app/components/common/Spinner.vue +28 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +5 -5
- package/app/components/docs/DocInterviewWindow.vue +6 -6
- package/app/components/documents/ContextDocumentPicker.vue +2 -2
- package/app/components/documents/DocumentImportModal.vue +9 -8
- package/app/components/documents/DocumentSourceConnectModal.vue +10 -10
- package/app/components/documents/DocumentTemplatesModal.vue +15 -9
- package/app/components/documents/RepoContextDocPicker.vue +2 -2
- package/app/components/documents/SpawnPreviewModal.vue +4 -6
- package/app/components/documents/StartFromDesignModal.vue +2 -1
- package/app/components/documents/TaskContextDocs.vue +4 -5
- package/app/components/environments/EnvironmentStatusPanel.vue +11 -8
- package/app/components/environments/steps/EnvPickStep.vue +7 -3
- package/app/components/environments/steps/EnvPreflightStep.vue +6 -5
- package/app/components/focus/BlockFocusView.vue +6 -5
- package/app/components/followUp/FollowUpWindow.vue +7 -9
- package/app/components/forkDecision/ForkDecisionWindow.vue +9 -8
- package/app/components/foundational/FoundationalServiceCatalogList.vue +9 -5
- package/app/components/foundational/FoundationalServiceRegistry.vue +11 -7
- package/app/components/foundational/FoundationalServiceSources.vue +20 -22
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/foundational/ServiceCatalogConnection.vue +15 -15
- package/app/components/fragments/FragmentLibraryManager.vue +36 -34
- package/app/components/fragments/FragmentSelector.vue +7 -3
- package/app/components/gates/GateResultView.vue +6 -9
- package/app/components/github/AddServiceFromRepoModal.vue +6 -10
- package/app/components/github/GitHubConnect.vue +10 -17
- package/app/components/github/GitHubPanel.vue +44 -47
- package/app/components/github/RepoTreeBrowser.vue +9 -5
- package/app/components/guidedReview/GuidedReviewModal.vue +16 -6
- package/app/components/guidedReview/GuidedReviewOverview.vue +2 -1
- package/app/components/guidedReview/GuidedReviewPicker.vue +10 -7
- package/app/components/guidedReview/GuidedReviewThread.vue +9 -4
- package/app/components/humanTest/HumanTestWindow.vue +2 -1
- package/app/components/initiative/InitiativePlanningWindow.vue +6 -6
- package/app/components/initiative/InitiativeTrackerWindow.vue +11 -11
- package/app/components/judge/JudgeResultView.vue +2 -7
- package/app/components/kaizen/KaizenPanel.vue +20 -5
- package/app/components/kaizen/KaizenStepStatus.vue +2 -1
- package/app/components/layout/AccountAuditLog.vue +11 -3
- package/app/components/layout/AccountDeploymentSettings.vue +17 -62
- package/app/components/layout/AccountFailureKindRules.vue +6 -5
- package/app/components/layout/AccountModelPolicySettings.vue +2 -6
- package/app/components/layout/AccountPlatformAlertSettings.vue +5 -13
- package/app/components/layout/AccountRiskPolicySettings.vue +13 -14
- package/app/components/layout/AccountRunCredentialSettings.vue +2 -2
- package/app/components/layout/AccountTeamSettings.vue +12 -9
- package/app/components/layout/BoardSwitcher.vue +2 -2
- package/app/components/layout/BoardToolbar.vue +3 -11
- package/app/components/layout/CommandBar.vue +7 -3
- package/app/components/layout/ConnectionStatusBanner.vue +2 -1
- package/app/components/layout/IntegrationsHub.vue +7 -3
- package/app/components/layout/ModelProvidersHub.vue +7 -3
- package/app/components/layout/NotificationsInbox.vue +3 -11
- package/app/components/layout/SideBar.vue +1 -1
- package/app/components/layout/WorkspaceMembersSettings.vue +12 -5
- package/app/components/media/ArtifactLightbox.vue +4 -3
- package/app/components/notifications/NotificationSettingsPanel.vue +4 -11
- package/app/components/observability/ToolCallList.vue +12 -17
- package/app/components/panels/AgentStepDetail.vue +5 -5
- package/app/components/panels/GenericStructuredResultView.vue +6 -9
- package/app/components/panels/InspectorPanel.vue +2 -1
- package/app/components/panels/MergerResultView.vue +5 -6
- package/app/components/panels/ObservabilityPanel.vue +26 -41
- package/app/components/panels/OperatorDashboardPanel.vue +29 -17
- package/app/components/panels/ReportsPanel.vue +17 -11
- package/app/components/panels/ReportsSpendBreakdown.vue +7 -3
- package/app/components/panels/ResultWindowShell.vue +1 -1
- package/app/components/panels/RunDetailLoadState.vue +4 -3
- package/app/components/panels/StepContainerStatus.vue +4 -3
- package/app/components/panels/StepDelegatedStatus.vue +3 -2
- package/app/components/panels/StepMetadataCard.vue +6 -8
- package/app/components/panels/StepRunMeta.vue +2 -5
- package/app/components/panels/inspector/ContainerSummary.vue +7 -1
- package/app/components/panels/inspector/EpicChildren.vue +7 -3
- package/app/components/panels/inspector/FrontendConfig.vue +7 -3
- package/app/components/panels/inspector/InitiativeInspector.vue +5 -2
- package/app/components/panels/inspector/ServiceConnections.vue +7 -3
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -6
- package/app/components/panels/inspector/ServiceTestSecrets.vue +2 -6
- package/app/components/panels/inspector/ServiceTestingContext.vue +2 -6
- package/app/components/panels/inspector/ServiceValidationConfig.vue +38 -39
- package/app/components/panels/inspector/TaskExecution.vue +5 -6
- package/app/components/panels/inspector/TaskRunSettings.vue +7 -3
- package/app/components/panels/inspector/TaskStructure.vue +0 -1
- package/app/components/pipeline/AgentPromptEditor.vue +25 -18
- package/app/components/pipeline/PipelineBuilder.vue +14 -24
- package/app/components/pipeline/PipelineProgress.vue +16 -17
- package/app/components/prReview/PrReviewPhaseBadge.vue +3 -2
- package/app/components/prReview/PrReviewWindow.vue +16 -20
- package/app/components/providers/ApiKeysSection.vue +2 -6
- package/app/components/providers/PersonalCredentialModal.vue +2 -6
- package/app/components/providers/PersonalSubscriptionSection.vue +3 -7
- package/app/components/providers/VendorCredentialsModal.vue +2 -6
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -6
- package/app/components/ralph/RalphLoopResultView.vue +2 -7
- package/app/components/requirements/RequirementsReviewWindow.vue +44 -39
- package/app/components/sandbox/SandboxPanel.vue +37 -25
- package/app/components/settings/AccountSettingsPanel.vue +6 -3
- package/app/components/settings/ApiTokensPanel.vue +2 -6
- package/app/components/settings/BudgetSettings.vue +2 -2
- package/app/components/settings/CapabilityCredentialsPanel.vue +2 -6
- package/app/components/settings/CloudflareHandlerSection.vue +3 -7
- package/app/components/settings/ConsensusGroupsSection.vue +7 -3
- package/app/components/settings/CustomManifestTypeEditor.vue +7 -3
- package/app/components/settings/DefaultProvisionTypeSection.vue +2 -2
- package/app/components/settings/InfraHandlersConfigurator.vue +8 -11
- package/app/components/settings/IssueTrackerPanel.vue +9 -9
- package/app/components/settings/LocalContainerPoolSettings.vue +2 -6
- package/app/components/settings/LocalModelEndpointsPanel.vue +5 -7
- package/app/components/settings/McpAuthorizeScreen.vue +8 -3
- package/app/components/settings/McpOAuthCallbackScreen.vue +2 -1
- package/app/components/settings/ModelConfigurationPanel.vue +45 -17
- package/app/components/settings/ObservabilityConnectionPanel.vue +4 -15
- package/app/components/settings/OpenRouterCatalogPanel.vue +8 -24
- package/app/components/settings/PackageRegistriesPanel.vue +2 -6
- package/app/components/settings/ProviderConnectionTab.vue +3 -7
- package/app/components/settings/RiskPolicyPanel.vue +4 -16
- package/app/components/settings/SharedStacksPanel.vue +8 -18
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +10 -6
- package/app/components/settings/UsageSettings.vue +11 -2
- package/app/components/settings/UserSecretsSection.vue +5 -7
- package/app/components/settings/WorkspaceMetadataSettings.vue +9 -9
- package/app/components/settings/WorkspaceSettingsPanel.vue +3 -11
- package/app/components/skills/ReviewSkillQueue.vue +7 -3
- package/app/components/skills/SkillLibraryManager.vue +20 -18
- package/app/components/slack/SlackPanel.vue +5 -8
- package/app/components/spec/ServiceSpecWindow.vue +32 -29
- package/app/components/tasks/BugHuntModal.vue +23 -19
- package/app/components/tasks/ContextIssuePicker.vue +2 -2
- package/app/components/tasks/TaskContextIssues.vue +4 -5
- package/app/components/tasks/TaskImportModal.vue +10 -8
- package/app/components/tasks/TaskSourceConnectModal.vue +11 -11
- package/app/components/testing/TestReportWindow.vue +6 -12
- package/app/components/tutorial/TutorialCatalogue.vue +7 -3
- package/app/components/tutorial/TutorialOverlay.vue +2 -1
- package/app/components/tutorial/TutorialPrompt.vue +7 -3
- package/app/components/vcs/GitLabConnect.vue +2 -6
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +9 -4
- package/app/composables/toastTitleKeys.spec.ts +143 -0
- package/app/composables/useActionToast.spec.ts +71 -0
- package/app/composables/useActionToast.ts +101 -0
- package/app/composables/useBlockDeletion.ts +3 -6
- package/app/composables/useConfirmAction.ts +5 -3
- package/app/composables/useContextLinking.spec.ts +3 -0
- package/app/composables/useContextLinking.ts +11 -16
- package/app/composables/useCopyToClipboard.ts +4 -3
- package/app/composables/useNavContributions.ts +4 -5
- package/app/composables/usePipelineErrorToast.spec.ts +24 -0
- package/app/composables/usePipelineErrorToast.ts +26 -2
- package/app/composables/usePipelineLibraryActions.ts +8 -9
- package/app/pages/index.vue +3 -2
- package/app/stores/board/context.ts +4 -3
- package/app/stores/board/placement.ts +8 -20
- package/app/stores/board/removal.ts +4 -13
- package/app/stores/board.spec.ts +10 -1
- package/app/stores/board.ts +3 -2
- package/app/utils/bootstrapSteps.ts +11 -2
- package/app/utils/pipelineRender.ts +21 -8
- package/i18n/locales/de.json +12 -30
- package/i18n/locales/en.json +12 -30
- package/i18n/locales/es.json +12 -30
- package/i18n/locales/fr.json +12 -30
- package/i18n/locales/he.json +12 -30
- package/i18n/locales/it.json +12 -30
- package/i18n/locales/ja.json +12 -30
- package/i18n/locales/pl.json +12 -30
- package/i18n/locales/tr.json +12 -30
- package/i18n/locales/uk.json +12 -30
- package/package.json +1 -1
|
@@ -14,12 +14,13 @@ import type {
|
|
|
14
14
|
} from '~/types/merge'
|
|
15
15
|
import RiskPolicyCreateForm from '~/components/settings/RiskPolicyCreateForm.vue'
|
|
16
16
|
import RiskPolicyEditorRow from '~/components/settings/RiskPolicyEditorRow.vue'
|
|
17
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
17
18
|
|
|
18
19
|
const props = defineProps<{ accountId: string }>()
|
|
19
20
|
|
|
20
21
|
const { t } = useI18n()
|
|
21
22
|
const store = useAccountRiskPoliciesStore()
|
|
22
|
-
const
|
|
23
|
+
const actionToast = useActionToast()
|
|
23
24
|
const { present } = usePipelineErrorToast()
|
|
24
25
|
const { confirm } = useConfirm()
|
|
25
26
|
|
|
@@ -47,11 +48,7 @@ async function save(policy: RiskPolicyLibraryEntry, patch: UpdateRiskPolicyInput
|
|
|
47
48
|
busy.value = policy.id
|
|
48
49
|
try {
|
|
49
50
|
await store.update(props.accountId, policy.id, patch)
|
|
50
|
-
toast.
|
|
51
|
-
title: t('settings.riskPolicy.toast.saved'),
|
|
52
|
-
icon: 'i-lucide-check',
|
|
53
|
-
color: 'success',
|
|
54
|
-
})
|
|
51
|
+
actionToast.success('settings.riskPolicy.toast.saved')
|
|
55
52
|
} catch (e) {
|
|
56
53
|
present(e, 'settings.riskPolicy.toast.saveFailed')
|
|
57
54
|
} finally {
|
|
@@ -84,11 +81,7 @@ async function create(input: CreateRiskPolicyInput) {
|
|
|
84
81
|
creating.value = true
|
|
85
82
|
try {
|
|
86
83
|
await store.create(props.accountId, input)
|
|
87
|
-
toast.
|
|
88
|
-
title: t('settings.riskPolicy.toast.created'),
|
|
89
|
-
icon: 'i-lucide-check',
|
|
90
|
-
color: 'success',
|
|
91
|
-
})
|
|
84
|
+
actionToast.success('settings.riskPolicy.toast.created')
|
|
92
85
|
} catch (e) {
|
|
93
86
|
present(e, 'settings.riskPolicy.toast.createFailed')
|
|
94
87
|
} finally {
|
|
@@ -101,9 +94,15 @@ async function create(input: CreateRiskPolicyInput) {
|
|
|
101
94
|
<div class="space-y-4 text-sm" data-testid="account-risk-policy-panel">
|
|
102
95
|
<p class="text-2xs text-muted">{{ t('layout.accountRiskPolicies.intro') }}</p>
|
|
103
96
|
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
</
|
|
97
|
+
<div v-if="store.loading && policies.length === 0" class="space-y-2">
|
|
98
|
+
<USkeleton v-for="i in 2" :key="i" class="h-20 w-full" />
|
|
99
|
+
</div>
|
|
100
|
+
<EmptyState
|
|
101
|
+
v-else-if="policies.length === 0"
|
|
102
|
+
compact
|
|
103
|
+
icon="i-lucide-shield"
|
|
104
|
+
:title="t('layout.accountRiskPolicies.empty')"
|
|
105
|
+
/>
|
|
107
106
|
|
|
108
107
|
<RiskPolicyEditorRow
|
|
109
108
|
v-for="policy in policies"
|
|
@@ -16,7 +16,7 @@ import { onMounted, ref, watch } from 'vue'
|
|
|
16
16
|
const props = defineProps<{ accountId: string }>()
|
|
17
17
|
|
|
18
18
|
const store = useAccountSettingsStore()
|
|
19
|
-
const
|
|
19
|
+
const actionToast = useActionToast()
|
|
20
20
|
const { present } = usePipelineErrorToast()
|
|
21
21
|
const { t } = useI18n()
|
|
22
22
|
|
|
@@ -48,7 +48,7 @@ async function save() {
|
|
|
48
48
|
...(forbid.value ? { allowInitiatorPat: false } : { allowInitiatorPat: undefined }),
|
|
49
49
|
},
|
|
50
50
|
})
|
|
51
|
-
|
|
51
|
+
actionToast.success('settings.runCredentialPolicy.saved')
|
|
52
52
|
} catch (e) {
|
|
53
53
|
present(e, 'settings.runCredentialPolicy.saveFailed')
|
|
54
54
|
} finally {
|
|
@@ -9,6 +9,7 @@ import AccountPlatformAlertSettings from '~/components/layout/AccountPlatformAle
|
|
|
9
9
|
import AccountRunCredentialSettings from '~/components/layout/AccountRunCredentialSettings.vue'
|
|
10
10
|
import SecretInput from '~/components/common/SecretInput.vue'
|
|
11
11
|
import IconButton from '~/components/common/IconButton.vue'
|
|
12
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
12
13
|
|
|
13
14
|
// Team settings for an org account: the member roster (with combinable admin /
|
|
14
15
|
// developer / product roles), pending email invitations, and the per-account
|
|
@@ -19,7 +20,7 @@ const props = defineProps<{ accountId: string }>()
|
|
|
19
20
|
const accounts = useAccountsStore()
|
|
20
21
|
const uiMode = useUiModeStore()
|
|
21
22
|
const auth = useAuthStore()
|
|
22
|
-
const
|
|
23
|
+
const actionToast = useActionToast()
|
|
23
24
|
const { present } = usePipelineErrorToast()
|
|
24
25
|
const { t, te } = useI18n()
|
|
25
26
|
const { confirmAction, toastDone } = useConfirmAction()
|
|
@@ -77,7 +78,7 @@ async function revokeSessions(userId: string, label: string) {
|
|
|
77
78
|
if (!(await confirmAction('revoke', label))) return
|
|
78
79
|
try {
|
|
79
80
|
await accounts.revokeMemberSessions(props.accountId, userId)
|
|
80
|
-
|
|
81
|
+
actionToast.success('layout.accountTeam.members.sessionsRevoked')
|
|
81
82
|
} catch (e) {
|
|
82
83
|
present(e, 'layout.accountTeam.errors.revokeSessions')
|
|
83
84
|
}
|
|
@@ -114,7 +115,7 @@ async function createOrganization() {
|
|
|
114
115
|
try {
|
|
115
116
|
await accounts.createOrg(name)
|
|
116
117
|
newOrgName.value = ''
|
|
117
|
-
|
|
118
|
+
actionToast.success('layout.accountTeam.org.created')
|
|
118
119
|
} catch (e) {
|
|
119
120
|
present(e, 'layout.accountTeam.errors.createOrg')
|
|
120
121
|
} finally {
|
|
@@ -136,12 +137,10 @@ async function sendInvite() {
|
|
|
136
137
|
inviteRoles.value.length ? inviteRoles.value : ['developer'],
|
|
137
138
|
)
|
|
138
139
|
inviteEmail.value = ''
|
|
139
|
-
|
|
140
|
-
title: t('layout.accountTeam.invite.created'),
|
|
140
|
+
actionToast.success('layout.accountTeam.invite.created', {
|
|
141
141
|
description: acceptUrl
|
|
142
142
|
? t('layout.accountTeam.invite.createdEmailed')
|
|
143
143
|
: t('layout.accountTeam.invite.createdShareLink'),
|
|
144
|
-
icon: 'i-lucide-mail-check',
|
|
145
144
|
})
|
|
146
145
|
} catch (e) {
|
|
147
146
|
present(e, 'layout.accountTeam.errors.sendInvite')
|
|
@@ -175,7 +174,7 @@ async function connectEmail() {
|
|
|
175
174
|
fromAddress: emailFrom.value.trim(),
|
|
176
175
|
})
|
|
177
176
|
emailApiKey.value = ''
|
|
178
|
-
|
|
177
|
+
actionToast.success('layout.accountTeam.email.connected')
|
|
179
178
|
} catch (e) {
|
|
180
179
|
present(e, 'layout.accountTeam.errors.connectEmail')
|
|
181
180
|
} finally {
|
|
@@ -261,8 +260,12 @@ async function disconnectEmail() {
|
|
|
261
260
|
@click="revokeSessions(m.userId, m.name || m.email || m.userId)"
|
|
262
261
|
/>
|
|
263
262
|
</li>
|
|
264
|
-
<li v-if="accounts.members.length === 0"
|
|
265
|
-
|
|
263
|
+
<li v-if="accounts.members.length === 0">
|
|
264
|
+
<EmptyState
|
|
265
|
+
compact
|
|
266
|
+
icon="i-lucide-users"
|
|
267
|
+
:title="t('layout.accountTeam.members.empty')"
|
|
268
|
+
/>
|
|
266
269
|
</li>
|
|
267
270
|
</ul>
|
|
268
271
|
</section>
|
|
@@ -28,7 +28,7 @@ const { t } = useI18n()
|
|
|
28
28
|
const accounts = useAccountsStore()
|
|
29
29
|
const workspace = useWorkspaceStore()
|
|
30
30
|
const ui = useUiStore()
|
|
31
|
-
const
|
|
31
|
+
const actionToast = useActionToast()
|
|
32
32
|
const { present } = usePipelineErrorToast()
|
|
33
33
|
const access = useWorkspaceAccess()
|
|
34
34
|
const { confirm } = useConfirm()
|
|
@@ -191,7 +191,7 @@ async function removeBoard() {
|
|
|
191
191
|
busy.value = true
|
|
192
192
|
try {
|
|
193
193
|
await workspace.remove(id)
|
|
194
|
-
|
|
194
|
+
actionToast.success('layout.boardSwitcher.toast.boardDeleted')
|
|
195
195
|
} catch (e) {
|
|
196
196
|
present(e, 'layout.boardSwitcher.toast.deleteBoardFailed')
|
|
197
197
|
} finally {
|
|
@@ -15,7 +15,7 @@ const execution = useExecutionStore()
|
|
|
15
15
|
const workspace = useWorkspaceStore()
|
|
16
16
|
const workspaceSettings = useWorkspaceSettingsStore()
|
|
17
17
|
const services = useServicesStore()
|
|
18
|
-
const
|
|
18
|
+
const actionToast = useActionToast()
|
|
19
19
|
const { present } = usePipelineErrorToast()
|
|
20
20
|
const access = useWorkspaceAccess()
|
|
21
21
|
const { t, n } = useI18n()
|
|
@@ -24,11 +24,7 @@ const { fitView, zoomIn, zoomOut, resetZoom } = useBoardFlow()
|
|
|
24
24
|
async function mountService(serviceId: string, title: string) {
|
|
25
25
|
try {
|
|
26
26
|
await services.mount(serviceId)
|
|
27
|
-
|
|
28
|
-
title: t('board.toolbar.serviceAdded', { title }),
|
|
29
|
-
icon: 'i-lucide-box',
|
|
30
|
-
color: 'success',
|
|
31
|
-
})
|
|
27
|
+
actionToast.success('board.toolbar.serviceAdded', { params: { title } })
|
|
32
28
|
} catch (e) {
|
|
33
29
|
present(e, 'board.toolbar.serviceAddFailed')
|
|
34
30
|
}
|
|
@@ -51,11 +47,7 @@ const mountableItems = computed(() =>
|
|
|
51
47
|
async function restoreService(id: string, title: string) {
|
|
52
48
|
try {
|
|
53
49
|
await board.restoreService(id)
|
|
54
|
-
toast.
|
|
55
|
-
title: t('board.toast.restored', { name: title }),
|
|
56
|
-
icon: 'i-lucide-archive-restore',
|
|
57
|
-
color: 'neutral',
|
|
58
|
-
})
|
|
50
|
+
actionToast.success('board.toast.restored', { params: { name: title } })
|
|
59
51
|
} catch (e) {
|
|
60
52
|
present(e, 'board.toast.restoreFailed')
|
|
61
53
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
// available actions (connected integrations, etc.) show.
|
|
8
8
|
|
|
9
9
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
10
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
10
11
|
|
|
11
12
|
interface Command {
|
|
12
13
|
id: string
|
|
@@ -273,9 +274,12 @@ function indexOf(cmd: Command) {
|
|
|
273
274
|
</div>
|
|
274
275
|
|
|
275
276
|
<div class="max-h-80 overflow-y-auto p-1.5">
|
|
276
|
-
<
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
<EmptyState
|
|
278
|
+
v-if="filtered.length === 0"
|
|
279
|
+
compact
|
|
280
|
+
icon="i-lucide-search-x"
|
|
281
|
+
:title="t('layout.commandBar.noMatches')"
|
|
282
|
+
/>
|
|
279
283
|
|
|
280
284
|
<div v-for="group in groups" :key="group.name" class="mb-1">
|
|
281
285
|
<SectionLabel as="p" class="px-2 pb-1 pt-2">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, onBeforeUnmount, ref, watch } from 'vue'
|
|
3
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
3
4
|
|
|
4
5
|
// A slim top strip shown when the real-time WebSocket isn't delivering events, so a
|
|
5
6
|
// silently-frozen board (events stop arriving, nothing updates) is no longer indistinguishable
|
|
@@ -70,7 +71,7 @@ onBeforeUnmount(clearTimer)
|
|
|
70
71
|
aria-live="polite"
|
|
71
72
|
data-testid="stream-reconnecting"
|
|
72
73
|
>
|
|
73
|
-
<
|
|
74
|
+
<Spinner class="h-3.5 w-3.5" />
|
|
74
75
|
<span>{{ t('app.reconnecting') }}</span>
|
|
75
76
|
</div>
|
|
76
77
|
<div
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { showOverrideField } from '~/utils/uiMode'
|
|
3
3
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
4
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
4
5
|
|
|
5
6
|
// The Integrations hub: a single modal that lists the OPTIONAL external systems the WORKSPACE
|
|
6
7
|
// can enable or link in — the ones that feed a run its context (source control, documents,
|
|
@@ -417,9 +418,12 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
417
418
|
class="w-full"
|
|
418
419
|
/>
|
|
419
420
|
|
|
420
|
-
<
|
|
421
|
-
|
|
422
|
-
|
|
421
|
+
<EmptyState
|
|
422
|
+
v-if="!filteredGroups.length"
|
|
423
|
+
compact
|
|
424
|
+
icon="i-lucide-search-x"
|
|
425
|
+
:title="t('layout.integrationsHub.noMatches', { query })"
|
|
426
|
+
/>
|
|
423
427
|
|
|
424
428
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
425
429
|
<SectionLabel as="h3" class="mb-2 px-1">
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// "Back to Model providers" control (IntegrationBackTitle). Layout mirrors the Integrations
|
|
14
14
|
// hub row-for-row so the two read as siblings.
|
|
15
15
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
16
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
16
17
|
|
|
17
18
|
const { t } = useI18n()
|
|
18
19
|
const ui = useUiStore()
|
|
@@ -197,9 +198,12 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
197
198
|
class="w-full"
|
|
198
199
|
/>
|
|
199
200
|
|
|
200
|
-
<
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
<EmptyState
|
|
202
|
+
v-if="!filteredGroups.length"
|
|
203
|
+
compact
|
|
204
|
+
icon="i-lucide-search-x"
|
|
205
|
+
:title="t('layout.modelProvidersHub.noMatches', { query })"
|
|
206
|
+
/>
|
|
203
207
|
|
|
204
208
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
205
209
|
<SectionLabel as="h3" class="mb-2 px-1">
|
|
@@ -16,7 +16,7 @@ const ui = useUiStore()
|
|
|
16
16
|
const access = useWorkspaceAccess()
|
|
17
17
|
const execution = useExecutionStore()
|
|
18
18
|
const trackRecords = useMergeTrackRecordsStore()
|
|
19
|
-
const
|
|
19
|
+
const actionToast = useActionToast()
|
|
20
20
|
const { present } = usePipelineErrorToast()
|
|
21
21
|
|
|
22
22
|
const busy = ref<string | null>(null)
|
|
@@ -197,11 +197,7 @@ async function act(n: Notification) {
|
|
|
197
197
|
// Only the merge cards carry a tag; passing `undefined` elsewhere keeps the historical
|
|
198
198
|
// no-body act, so a non-merge card's action is completely unchanged.
|
|
199
199
|
await notifications.act(n.id, collectsEffort(n) ? effortFor(n) : undefined)
|
|
200
|
-
toast.
|
|
201
|
-
title: t('layout.notifications.toast.acted'),
|
|
202
|
-
color: 'success',
|
|
203
|
-
icon: 'i-lucide-check',
|
|
204
|
-
})
|
|
200
|
+
actionToast.success('layout.notifications.toast.acted')
|
|
205
201
|
} catch (e) {
|
|
206
202
|
present(e, 'layout.notifications.toast.actFailed')
|
|
207
203
|
} finally {
|
|
@@ -213,11 +209,7 @@ async function dismiss(n: Notification) {
|
|
|
213
209
|
busy.value = n.id
|
|
214
210
|
try {
|
|
215
211
|
await notifications.dismiss(n.id)
|
|
216
|
-
toast.
|
|
217
|
-
title: t('layout.notifications.toast.dismissed'),
|
|
218
|
-
color: 'neutral',
|
|
219
|
-
icon: 'i-lucide-check',
|
|
220
|
-
})
|
|
212
|
+
actionToast.success('layout.notifications.toast.dismissed')
|
|
221
213
|
} catch (e) {
|
|
222
214
|
present(e, 'layout.notifications.toast.dismissFailed')
|
|
223
215
|
} finally {
|
|
@@ -157,7 +157,7 @@ watch(
|
|
|
157
157
|
<!-- safe-area-ok: a scrim with no content; the drawer below pads its own edges -->
|
|
158
158
|
<div
|
|
159
159
|
v-if="ui.mobileNavOpen"
|
|
160
|
-
class="fixed inset-0 z-30 bg-
|
|
160
|
+
class="fixed inset-0 z-30 bg-elevated/75 backdrop-blur-sm lg:hidden"
|
|
161
161
|
data-testid="sidebar-backdrop"
|
|
162
162
|
role="button"
|
|
163
163
|
tabindex="-1"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
3
3
|
import type { WorkspaceAccessMode, WorkspaceRole } from '~/types/domain'
|
|
4
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
4
5
|
|
|
5
6
|
// Workspace-membership management (workspace-rbac initiative, slice 9). The tier BELOW
|
|
6
7
|
// account tenancy: an account admin restricts a board to an explicit member list (with
|
|
@@ -16,7 +17,7 @@ const workspace = useWorkspaceStore()
|
|
|
16
17
|
const members = useWorkspaceMembersStore()
|
|
17
18
|
const accounts = useAccountsStore()
|
|
18
19
|
const auth = useAuthStore()
|
|
19
|
-
const
|
|
20
|
+
const actionToast = useActionToast()
|
|
20
21
|
const { present } = usePipelineErrorToast()
|
|
21
22
|
const { t } = useI18n()
|
|
22
23
|
const { confirmAction, toastDone } = useConfirmAction()
|
|
@@ -108,7 +109,7 @@ async function addMember() {
|
|
|
108
109
|
await members.add(props.workspaceId, userId, addRole.value)
|
|
109
110
|
addUserId.value = undefined
|
|
110
111
|
addRole.value = 'member'
|
|
111
|
-
|
|
112
|
+
actionToast.success('layout.workspaceMembers.add.added')
|
|
112
113
|
} catch (e) {
|
|
113
114
|
present(e, 'layout.workspaceMembers.errors.add')
|
|
114
115
|
} finally {
|
|
@@ -173,7 +174,9 @@ function memberLabel(userId: string, name?: string | null, email?: string | null
|
|
|
173
174
|
<h3 class="mb-2 font-semibold text-highlighted">
|
|
174
175
|
{{ t('layout.workspaceMembers.roster.title') }}
|
|
175
176
|
</h3>
|
|
176
|
-
<
|
|
177
|
+
<div v-if="!rosterReady" class="space-y-1">
|
|
178
|
+
<USkeleton v-for="i in 3" :key="i" class="h-8 w-full" />
|
|
179
|
+
</div>
|
|
177
180
|
<ul v-else class="space-y-1" data-testid="workspace-members-roster">
|
|
178
181
|
<li
|
|
179
182
|
v-for="m in members.members"
|
|
@@ -206,8 +209,12 @@ function memberLabel(userId: string, name?: string | null, email?: string | null
|
|
|
206
209
|
/>
|
|
207
210
|
</span>
|
|
208
211
|
</li>
|
|
209
|
-
<li v-if="members.members.length === 0"
|
|
210
|
-
|
|
212
|
+
<li v-if="members.members.length === 0">
|
|
213
|
+
<EmptyState
|
|
214
|
+
compact
|
|
215
|
+
icon="i-lucide-users"
|
|
216
|
+
:title="t('layout.workspaceMembers.roster.empty')"
|
|
217
|
+
/>
|
|
211
218
|
</li>
|
|
212
219
|
</ul>
|
|
213
220
|
</section>
|
|
@@ -10,6 +10,7 @@ import { computed, ref, watch } from 'vue'
|
|
|
10
10
|
import { useModalBehavior } from '@modular-vue/core'
|
|
11
11
|
import type { ArtifactBlobs } from '~/composables/useArtifactBlobs'
|
|
12
12
|
import IconButton from '~/components/common/IconButton.vue'
|
|
13
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
13
14
|
import { FULL_BLEED_TAKEOVER_CLASS } from '~/utils/safeArea'
|
|
14
15
|
|
|
15
16
|
interface LightboxItem {
|
|
@@ -273,10 +274,10 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKey, true))
|
|
|
273
274
|
@pointercancel="onPointerUp"
|
|
274
275
|
/>
|
|
275
276
|
<div v-else class="flex flex-col items-center gap-2 text-dimmed">
|
|
276
|
-
<
|
|
277
|
-
:name="state === 'error' ? 'i-lucide-image-off' :
|
|
277
|
+
<Spinner
|
|
278
|
+
:name="state === 'error' ? 'i-lucide-image-off' : undefined"
|
|
279
|
+
:spinning="state !== 'error'"
|
|
278
280
|
class="h-8 w-8"
|
|
279
|
-
:class="state === 'error' ? '' : 'animate-spin'"
|
|
280
281
|
/>
|
|
281
282
|
<p class="text-xs">
|
|
282
283
|
{{ state === 'error' ? t('media.lightbox.failed') : t('media.lightbox.loading') }}
|
|
@@ -30,7 +30,7 @@ import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
|
30
30
|
const ui = useUiStore()
|
|
31
31
|
const notifications = useNotificationsStore()
|
|
32
32
|
const slack = useSlackStore()
|
|
33
|
-
const
|
|
33
|
+
const actionToast = useActionToast()
|
|
34
34
|
const { present } = usePipelineErrorToast()
|
|
35
35
|
const { t } = useI18n()
|
|
36
36
|
|
|
@@ -119,11 +119,7 @@ async function save() {
|
|
|
119
119
|
busy.value = true
|
|
120
120
|
try {
|
|
121
121
|
await notifications.updateSettings(matrix)
|
|
122
|
-
toast.
|
|
123
|
-
title: t('notificationSettings.toast.saved'),
|
|
124
|
-
icon: 'i-lucide-check',
|
|
125
|
-
color: 'success',
|
|
126
|
-
})
|
|
122
|
+
actionToast.success('notificationSettings.toast.saved')
|
|
127
123
|
} catch (e) {
|
|
128
124
|
present(e, 'notificationSettings.error.save')
|
|
129
125
|
} finally {
|
|
@@ -167,11 +163,8 @@ function resetToDefaults() {
|
|
|
167
163
|
</UButton>
|
|
168
164
|
</div>
|
|
169
165
|
|
|
170
|
-
<div
|
|
171
|
-
v-
|
|
172
|
-
class="rounded-lg border border-muted bg-elevated/40 p-3 text-xs text-muted"
|
|
173
|
-
>
|
|
174
|
-
{{ t('common.loading') }}
|
|
166
|
+
<div v-else-if="!editable" class="space-y-1">
|
|
167
|
+
<USkeleton v-for="n in 4" :key="n" class="h-10 w-full" />
|
|
175
168
|
</div>
|
|
176
169
|
|
|
177
170
|
<template v-else>
|
|
@@ -6,6 +6,7 @@ import { filterToolCallsByOutcome, formatMs } from '~/utils/observability'
|
|
|
6
6
|
import { agentKindMeta } from '~/utils/catalog'
|
|
7
7
|
import OutcomeFilterChips from '~/components/observability/OutcomeFilterChips.vue'
|
|
8
8
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
9
10
|
|
|
10
11
|
// The tool-call TRAJECTORY drill-down: what the run's agents DID, oldest first, in the order
|
|
11
12
|
// they did it. The sibling of the model-call list, and the one that holds the failures no LLM
|
|
@@ -153,13 +154,9 @@ function prettyArgs(raw: string): string {
|
|
|
153
154
|
|
|
154
155
|
<!-- Every state below is gated on having NOTHING to show: rows already in hand outrank a
|
|
155
156
|
read still in flight behind them, and outrank one that failed. -->
|
|
156
|
-
<
|
|
157
|
-
v-
|
|
158
|
-
|
|
159
|
-
>
|
|
160
|
-
<UIcon name="i-lucide-loader-circle" class="h-4 w-4 animate-spin" />
|
|
161
|
-
{{ t('observability.toolCalls.loading') }}
|
|
162
|
-
</p>
|
|
157
|
+
<div v-if="source.loading && !visible.length" class="space-y-2">
|
|
158
|
+
<USkeleton v-for="n in 3" :key="n" class="h-10 w-full rounded-xl" />
|
|
159
|
+
</div>
|
|
163
160
|
<div
|
|
164
161
|
v-else-if="source.error && !visible.length"
|
|
165
162
|
class="flex flex-col items-center gap-3 rounded-lg border border-dashed border-app-error-900/60 py-6 text-center text-sm text-app-error-400"
|
|
@@ -178,20 +175,18 @@ function prettyArgs(raw: string): string {
|
|
|
178
175
|
</div>
|
|
179
176
|
<!-- "The run made no tool calls" is a claim about the RUN, so it comes off the aggregate,
|
|
180
177
|
never off an empty prefix that may simply not have loaded. -->
|
|
181
|
-
<
|
|
178
|
+
<EmptyState
|
|
182
179
|
v-else-if="!counts.all"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
</p>
|
|
180
|
+
icon="i-lucide-wrench"
|
|
181
|
+
:title="t('observability.toolCalls.none')"
|
|
182
|
+
/>
|
|
187
183
|
<!-- Narrowed to nothing is a different statement from recorded nothing, and it is the more
|
|
188
184
|
reassuring of the two: the operator asked for the failures and there are none. -->
|
|
189
|
-
<
|
|
185
|
+
<EmptyState
|
|
190
186
|
v-else-if="!visible.length"
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
</p>
|
|
187
|
+
icon="i-lucide-list-filter"
|
|
188
|
+
:title="t('observability.toolCalls.noneMatching')"
|
|
189
|
+
/>
|
|
195
190
|
|
|
196
191
|
<template v-else>
|
|
197
192
|
<!-- What this view is bounded by, when it is. A cap nobody can see is a prefix read as a
|
|
@@ -31,6 +31,7 @@ import InputGateNotice from '~/components/inputGate/InputGateNotice.vue'
|
|
|
31
31
|
import RunDetailLoadState from '~/components/panels/RunDetailLoadState.vue'
|
|
32
32
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
33
33
|
import IconButton from '~/components/common/IconButton.vue'
|
|
34
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
34
35
|
import { FULL_BLEED_TAKEOVER_CLASS } from '~/utils/safeArea'
|
|
35
36
|
|
|
36
37
|
// Detail overlay for a single pipeline step. Opened by clicking an agent in the
|
|
@@ -822,12 +823,11 @@ async function copyOutput() {
|
|
|
822
823
|
</section>
|
|
823
824
|
</template>
|
|
824
825
|
|
|
825
|
-
<
|
|
826
|
+
<EmptyState
|
|
826
827
|
v-else
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
</p>
|
|
828
|
+
icon="i-lucide-file-text"
|
|
829
|
+
:title="t('panels.stepDetail.noProseOutput')"
|
|
830
|
+
/>
|
|
831
831
|
</div>
|
|
832
832
|
</div>
|
|
833
833
|
</div>
|
|
@@ -12,6 +12,7 @@ import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
|
12
12
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
13
13
|
import CopyButton from '~/components/common/CopyButton.vue'
|
|
14
14
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
15
16
|
|
|
16
17
|
const board = useBoardStore()
|
|
17
18
|
const execution = useExecutionStore()
|
|
@@ -87,16 +88,12 @@ const customJson = computed<string | null>(() => {
|
|
|
87
88
|
><code>{{ customJson }}</code></pre>
|
|
88
89
|
</template>
|
|
89
90
|
|
|
90
|
-
<
|
|
91
|
+
<EmptyState
|
|
91
92
|
v-else-if="!step?.output"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
<p class="max-w-sm text-2xs text-dimmed">
|
|
97
|
-
{{ t('panels.structuredResult.noResultHint') }}
|
|
98
|
-
</p>
|
|
99
|
-
</div>
|
|
93
|
+
icon="i-lucide-braces"
|
|
94
|
+
:title="t('panels.structuredResult.noResult')"
|
|
95
|
+
:description="t('panels.structuredResult.noResultHint')"
|
|
96
|
+
/>
|
|
100
97
|
</div>
|
|
101
98
|
|
|
102
99
|
<!-- Sidebar: shared run metadata + observability rollup -->
|
|
@@ -11,6 +11,7 @@ import BootstrapRunSteps from '~/components/bootstrap/BootstrapRunSteps.vue'
|
|
|
11
11
|
import { BLUEPRINT_AGENT_KIND } from '@cat-factory/contracts'
|
|
12
12
|
import { VCS_PROVIDER_ICONS } from '~/utils/vcs'
|
|
13
13
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
14
|
+
import Spinner from '~/components/common/Spinner.vue'
|
|
14
15
|
|
|
15
16
|
const board = useBoardStore()
|
|
16
17
|
const pipelines = usePipelinesStore()
|
|
@@ -500,7 +501,7 @@ const showOriginalDescription = ref(false)
|
|
|
500
501
|
>
|
|
501
502
|
<div class="flex items-center justify-between gap-2">
|
|
502
503
|
<span class="flex items-center gap-1.5 text-xs text-app-warning-300">
|
|
503
|
-
<
|
|
504
|
+
<Spinner class="h-3.5 w-3.5" />
|
|
504
505
|
{{ t('panels.inspector.bootstrapping') }}
|
|
505
506
|
</span>
|
|
506
507
|
<div class="flex items-center gap-1.5">
|
|
@@ -12,6 +12,7 @@ import StepRunMeta from '~/components/panels/StepRunMeta.vue'
|
|
|
12
12
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
13
13
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
14
14
|
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
|
+
import EmptyState from '~/components/common/EmptyState.vue'
|
|
15
16
|
|
|
16
17
|
const board = useBoardStore()
|
|
17
18
|
const execution = useExecutionStore()
|
|
@@ -275,13 +276,11 @@ const reasonText = computed(() => {
|
|
|
275
276
|
:text="step.output"
|
|
276
277
|
class="text-sm leading-relaxed text-toned"
|
|
277
278
|
/>
|
|
278
|
-
<
|
|
279
|
+
<EmptyState
|
|
279
280
|
v-else
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<p class="text-sm">{{ t('panels.mergerResult.noResult') }}</p>
|
|
284
|
-
</div>
|
|
281
|
+
icon="i-lucide-git-pull-request"
|
|
282
|
+
:title="t('panels.mergerResult.noResult')"
|
|
283
|
+
/>
|
|
285
284
|
</div>
|
|
286
285
|
|
|
287
286
|
<!-- Sidebar: shared run metadata. -->
|