@cat-factory/app 0.308.0 → 0.310.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/README.md +32 -2
- package/app/assets/css/main.css +22 -0
- package/app/assets/css/prose.css +4 -4
- package/app/assets/css/type.css +24 -0
- package/app/components/assistant/AssistantModal.vue +8 -6
- package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
- package/app/components/auth/LoginScreen.vue +40 -26
- package/app/components/auth/ResetPasswordScreen.vue +9 -4
- package/app/components/auth/UserMenu.vue +5 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
- package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
- package/app/components/binaryOutput/StoredAssetView.vue +13 -11
- package/app/components/board/AddTaskModal.vue +30 -27
- package/app/components/board/AgentFailureCard.vue +21 -18
- package/app/components/board/AgentFailureHistory.vue +18 -9
- package/app/components/board/CreateInitiativeModal.vue +7 -6
- package/app/components/board/FailureDetail.vue +22 -12
- package/app/components/board/FailureHistoryList.vue +5 -5
- package/app/components/board/RecurringPipelineModal.vue +12 -11
- package/app/components/board/ReviewFrictionDialog.vue +8 -6
- package/app/components/board/StepExecutionHistory.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +1 -1
- package/app/components/board/nodes/BlockNode.vue +25 -24
- package/app/components/board/nodes/DecisionBadge.vue +4 -3
- package/app/components/board/nodes/EpicNode.vue +4 -4
- package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
- package/app/components/board/nodes/InitiativeCard.vue +4 -4
- package/app/components/board/nodes/LaneGroup.vue +3 -5
- package/app/components/board/nodes/TaskCard.vue +20 -15
- package/app/components/board/nodes/TaskLane.vue +3 -3
- package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
- package/app/components/bootstrap/BootstrapModal.vue +14 -13
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +13 -10
- package/app/components/bugFishing/BugFishingWindow.vue +81 -58
- package/app/components/clarity/ClarityReviewWindow.vue +13 -10
- package/app/components/common/AsyncViewError.vue +1 -1
- package/app/components/common/ClarificationItem.vue +6 -6
- package/app/components/common/CopyButton.vue +12 -11
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +1 -1
- package/app/components/common/IconButton.vue +34 -9
- package/app/components/common/InterviewGateNotice.vue +4 -4
- package/app/components/common/MarkdownProse.vue +8 -2
- package/app/components/common/SectionLabel.vue +38 -0
- package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
- package/app/components/context/ContextAttachmentFields.vue +32 -20
- package/app/components/docs/DocInterviewWindow.vue +10 -9
- package/app/components/documents/ContextDocumentPicker.vue +22 -21
- package/app/components/documents/DocumentImportModal.vue +7 -5
- package/app/components/documents/DocumentOriginLink.vue +12 -9
- package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
- package/app/components/documents/DocumentSyncState.vue +4 -4
- package/app/components/documents/DocumentTemplatesModal.vue +5 -4
- package/app/components/documents/RepoContextDocPicker.vue +7 -9
- package/app/components/documents/StartFromDesignModal.vue +4 -4
- package/app/components/documents/TaskContextDocs.vue +1 -1
- package/app/components/environments/EnvSetupStepper.vue +3 -3
- package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
- package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
- package/app/components/environments/steps/EnvReviewStep.vue +23 -22
- package/app/components/environments/steps/EnvSaveStep.vue +5 -5
- package/app/components/focus/BlockFocusView.vue +11 -10
- package/app/components/followUp/FollowUpWindow.vue +18 -15
- package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
- package/app/components/foundational/FoundationalContractSummary.vue +2 -2
- package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
- package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
- package/app/components/foundational/FoundationalServiceSources.vue +7 -6
- package/app/components/foundational/FoundationalSuppressions.vue +2 -2
- package/app/components/fragments/FragmentLibraryManager.vue +8 -7
- package/app/components/fragments/FragmentSelector.vue +22 -20
- package/app/components/gates/GateFailingCheckList.vue +7 -6
- package/app/components/gates/GateResultView.vue +55 -49
- package/app/components/github/AddServiceFromRepoModal.vue +16 -11
- package/app/components/github/BranchProtectionPreflight.vue +5 -5
- package/app/components/github/GitHubConnect.vue +5 -3
- package/app/components/github/GitHubOnboarding.vue +7 -2
- package/app/components/github/GitHubPanel.vue +23 -19
- package/app/components/github/RepoTreeBrowser.vue +16 -13
- package/app/components/humanTest/HumanTestWindow.vue +29 -24
- package/app/components/initiative/InitiativePlanNotice.vue +3 -3
- package/app/components/initiative/InitiativePlanReview.vue +46 -38
- package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
- package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
- package/app/components/judge/JudgeResultView.vue +28 -27
- package/app/components/kaizen/KaizenPanel.vue +70 -56
- package/app/components/kaizen/KaizenStepStatus.vue +7 -6
- package/app/components/layout/AccountAuditLog.vue +1 -1
- package/app/components/layout/AccountDeploymentSettings.vue +10 -10
- package/app/components/layout/AccountFailureKindRules.vue +13 -13
- package/app/components/layout/AccountFoundationalSettings.vue +1 -1
- package/app/components/layout/AccountFragmentSettings.vue +1 -1
- package/app/components/layout/AccountModelPolicySettings.vue +7 -7
- package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +13 -9
- package/app/components/layout/AiProvidersBanner.vue +1 -1
- package/app/components/layout/AppearanceSwitcher.vue +5 -4
- package/app/components/layout/BoardSwitcher.vue +13 -10
- package/app/components/layout/BoardToolbar.vue +10 -5
- package/app/components/layout/CommandBar.vue +8 -5
- package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
- package/app/components/layout/IntegrationsHub.vue +12 -9
- package/app/components/layout/LanguageSwitcher.vue +5 -4
- package/app/components/layout/ModelProvidersHub.vue +10 -7
- package/app/components/layout/NotificationsInbox.vue +47 -36
- package/app/components/layout/PersonalSetupModal.vue +9 -6
- package/app/components/layout/RolePrompt.vue +5 -4
- package/app/components/layout/SideBar.vue +7 -8
- package/app/components/layout/SpendWarningBanner.vue +3 -3
- package/app/components/layout/TranslationWarningBanner.vue +5 -4
- package/app/components/layout/UiModeSwitcher.vue +15 -12
- package/app/components/layout/UiRoleSwitcher.vue +10 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
- package/app/components/media/ArtifactLightbox.vue +74 -44
- package/app/components/media/ImageCompare.vue +80 -85
- package/app/components/merge/MergeEffortChips.vue +4 -6
- package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
- package/app/components/observability/OutcomeFilterChips.vue +6 -5
- package/app/components/observability/RunFailureSummary.vue +22 -23
- package/app/components/observability/StepMetricsBar.vue +9 -8
- package/app/components/observability/StepModelActivity.vue +8 -5
- package/app/components/observability/ToolCallList.vue +19 -20
- package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
- package/app/components/palettes/AgentPalette.vue +21 -15
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +57 -49
- package/app/components/panels/AttemptEntryHeader.vue +2 -2
- package/app/components/panels/DecisionModal.vue +1 -1
- package/app/components/panels/GenericStructuredResultView.vue +6 -5
- package/app/components/panels/InspectorPanel.vue +15 -13
- package/app/components/panels/MergerResultView.vue +10 -9
- package/app/components/panels/ObservabilityPanel.vue +211 -186
- package/app/components/panels/OperatorDashboardPanel.vue +124 -115
- package/app/components/panels/ReportsPanel.vue +87 -83
- package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
- package/app/components/panels/ResultWindowShell.vue +152 -137
- package/app/components/panels/RunDetailLoadState.vue +1 -1
- package/app/components/panels/StepContainerStatus.vue +17 -16
- package/app/components/panels/StepDelegatedStatus.vue +24 -21
- package/app/components/panels/StepEffortReport.vue +12 -17
- package/app/components/panels/StepFragmentAdherence.vue +9 -10
- package/app/components/panels/StepMetadataCard.vue +41 -43
- package/app/components/panels/StepReproductionReport.vue +18 -20
- package/app/components/panels/StepRestartControl.vue +3 -2
- package/app/components/panels/StepRunMeta.vue +27 -26
- package/app/components/panels/StepTestReport.vue +16 -15
- package/app/components/panels/StepToolServers.vue +7 -8
- package/app/components/panels/StepValidationReport.vue +5 -5
- package/app/components/panels/inspector/ContainerSummary.vue +4 -4
- package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
- package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
- package/app/components/panels/inspector/EpicChildren.vue +12 -10
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
- package/app/components/panels/inspector/FrontendConfig.vue +29 -36
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +25 -17
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
- package/app/components/panels/inspector/ServiceConnections.vue +5 -4
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
- package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
- package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
- package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
- package/app/components/panels/inspector/TaskExecution.vue +18 -16
- package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
- package/app/components/panels/inspector/TaskStructure.vue +5 -4
- package/app/components/pipeline/AgentPromptEditor.vue +15 -14
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
- package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
- package/app/components/pipeline/GateConfigFields.vue +19 -23
- package/app/components/pipeline/IterationCapPrompt.vue +1 -1
- package/app/components/pipeline/PipelineBuilder.vue +113 -99
- package/app/components/pipeline/PipelineHealthModal.vue +7 -7
- package/app/components/pipeline/PipelinePicker.vue +11 -9
- package/app/components/pipeline/PipelinePreview.vue +6 -7
- package/app/components/pipeline/PipelineProgress.vue +49 -45
- package/app/components/prReview/PrReviewWindow.vue +87 -65
- package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
- package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
- package/app/components/providers/ApiKeysSection.vue +11 -9
- package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
- package/app/components/providers/VendorCredentialsModal.vue +5 -4
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
- package/app/components/ralph/RalphLoopResultView.vue +29 -29
- package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
- package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
- package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
- package/app/components/sandbox/SandboxPanel.vue +93 -73
- package/app/components/settings/ApiTokensPanel.vue +1 -1
- package/app/components/settings/BudgetSettings.vue +18 -17
- package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
- package/app/components/settings/CloudflareHandlerSection.vue +44 -41
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
- package/app/components/settings/ConnectionTestVerdict.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +58 -47
- package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
- package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
- package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
- package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
- package/app/components/settings/IssueTrackerPanel.vue +30 -21
- package/app/components/settings/KubernetesEngineForm.vue +9 -8
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
- package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
- package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
- package/app/components/settings/MergeClassRulesEditor.vue +6 -5
- package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
- package/app/components/settings/ModelConfigurationPanel.vue +17 -19
- package/app/components/settings/ModelPresetHealthModal.vue +3 -3
- package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
- package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
- package/app/components/settings/PackageRegistriesPanel.vue +4 -4
- package/app/components/settings/ProviderConnectionTab.vue +5 -4
- package/app/components/settings/ProviderManifestEditor.vue +9 -8
- package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
- package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
- package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
- package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
- package/app/components/settings/RiskPolicyPanel.vue +11 -13
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
- package/app/components/settings/SharedStacksPanel.vue +5 -5
- package/app/components/settings/TaskSourceCard.vue +2 -2
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
- package/app/components/settings/ToolServerChecklist.vue +22 -22
- package/app/components/settings/UsageSettings.vue +13 -13
- package/app/components/settings/UserSecretsSection.vue +4 -3
- package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
- package/app/components/skills/ReviewSkillQueue.vue +12 -10
- package/app/components/skills/SkillLibraryManager.vue +9 -8
- package/app/components/slack/SlackPanel.vue +17 -12
- package/app/components/spec/ServiceSpecWindow.vue +19 -19
- package/app/components/tasks/BugHuntModal.vue +1 -1
- package/app/components/tasks/ContextIssuePicker.vue +16 -15
- package/app/components/tasks/TaskContextIssues.vue +5 -4
- package/app/components/tasks/TaskImportModal.vue +3 -2
- package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
- package/app/components/testing/TestReportWindow.vue +67 -60
- package/app/components/theme/ThemeImportModal.vue +2 -2
- package/app/components/tutorial/TutorialNudge.vue +3 -2
- package/app/components/tutorial/TutorialOverlay.vue +3 -2
- package/app/components/vcs/GitLabConnect.vue +1 -1
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
- package/app/utils/theme/builtins.ts +7 -1
- package/i18n/locales/de.json +7 -3
- package/i18n/locales/en.json +7 -3
- package/i18n/locales/es.json +7 -3
- package/i18n/locales/fr.json +7 -3
- package/i18n/locales/he.json +7 -3
- package/i18n/locales/it.json +7 -3
- package/i18n/locales/ja.json +7 -3
- package/i18n/locales/pl.json +7 -3
- package/i18n/locales/tr.json +7 -3
- package/i18n/locales/uk.json +7 -3
- package/package.json +1 -1
|
@@ -549,7 +549,7 @@ const STATUS_KEYS: Record<BugHuntAnalysisStatus, string> = {
|
|
|
549
549
|
<p v-if="candidate.analysis?.rationale" class="text-xs text-toned">
|
|
550
550
|
{{ candidate.analysis.rationale }}
|
|
551
551
|
</p>
|
|
552
|
-
<div class="flex flex-wrap items-center gap-2 text-
|
|
552
|
+
<div class="flex flex-wrap items-center gap-2 text-2xs text-dimmed">
|
|
553
553
|
<span v-if="candidate.priority">{{ candidate.priority }}</span>
|
|
554
554
|
<span v-for="label in candidate.labels" :key="label">{{ label }}</span>
|
|
555
555
|
<span v-if="createdAtDate(candidate.createdAt)">
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
reconcileSource,
|
|
29
29
|
sourceMenuItems,
|
|
30
30
|
} from '~/utils/sourcePicker'
|
|
31
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
31
32
|
|
|
32
33
|
const props = defineProps<{
|
|
33
34
|
/** contextKeys already staged by the caller, so they're filtered out / not re-offered. */
|
|
@@ -291,12 +292,9 @@ onMounted(() => {
|
|
|
291
292
|
promises a choice that isn't there. `id` labels the trigger, whose own content is the
|
|
292
293
|
tracker name rather than what that name means. -->
|
|
293
294
|
<div class="flex items-center gap-1.5">
|
|
294
|
-
<span
|
|
295
|
-
:id="sourceLabelId"
|
|
296
|
-
class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
|
|
297
|
-
>
|
|
295
|
+
<SectionLabel as="span" :id="sourceLabelId" class="shrink-0">
|
|
298
296
|
{{ t('tasks.picker.sourceLabel') }}
|
|
299
|
-
</
|
|
297
|
+
</SectionLabel>
|
|
300
298
|
<UDropdownMenu
|
|
301
299
|
v-if="sourcePickable"
|
|
302
300
|
:items="sourceMenu"
|
|
@@ -335,16 +333,17 @@ onMounted(() => {
|
|
|
335
333
|
@keydown.enter="refRow && pickRef(refRow)"
|
|
336
334
|
/>
|
|
337
335
|
|
|
338
|
-
<p v-if="searchError" class="px-1 text-
|
|
336
|
+
<p v-if="searchError" class="px-1 text-2xs text-app-warning-400">
|
|
339
337
|
{{ searchError }}
|
|
340
338
|
</p>
|
|
341
339
|
|
|
342
340
|
<div class="max-h-56 space-y-0.5 overflow-y-auto">
|
|
343
341
|
<!-- Already-imported issues (linked directly, no re-fetch). -->
|
|
344
|
-
<
|
|
342
|
+
<UButton
|
|
343
|
+
color="neutral"
|
|
344
|
+
variant="ghost"
|
|
345
345
|
v-for="row in importedRows"
|
|
346
346
|
:key="`imp:${row.externalId}`"
|
|
347
|
-
type="button"
|
|
348
347
|
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
349
348
|
@click="pickImported(row)"
|
|
350
349
|
>
|
|
@@ -353,13 +352,14 @@ onMounted(() => {
|
|
|
353
352
|
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
|
|
354
353
|
t('tasks.picker.imported')
|
|
355
354
|
}}</UBadge>
|
|
356
|
-
</
|
|
355
|
+
</UButton>
|
|
357
356
|
|
|
358
357
|
<!-- Tracker search hits (imported on add). -->
|
|
359
|
-
<
|
|
358
|
+
<UButton
|
|
359
|
+
color="neutral"
|
|
360
|
+
variant="ghost"
|
|
360
361
|
v-for="r in searchRows"
|
|
361
362
|
:key="`hit:${r.externalId}`"
|
|
362
|
-
type="button"
|
|
363
363
|
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
364
364
|
@click="pickSearch(r)"
|
|
365
365
|
>
|
|
@@ -368,12 +368,13 @@ onMounted(() => {
|
|
|
368
368
|
<UBadge v-if="r.status" color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
369
369
|
{{ r.status }}
|
|
370
370
|
</UBadge>
|
|
371
|
-
</
|
|
371
|
+
</UButton>
|
|
372
372
|
|
|
373
373
|
<!-- Explicit URL/key reference (imported on add). -->
|
|
374
|
-
<
|
|
374
|
+
<UButton
|
|
375
|
+
color="neutral"
|
|
376
|
+
variant="ghost"
|
|
375
377
|
v-if="refRow"
|
|
376
|
-
type="button"
|
|
377
378
|
class="flex w-full items-center gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
378
379
|
@click="pickRef(refRow)"
|
|
379
380
|
>
|
|
@@ -385,7 +386,7 @@ onMounted(() => {
|
|
|
385
386
|
</template>
|
|
386
387
|
</i18n-t>
|
|
387
388
|
</span>
|
|
388
|
-
</
|
|
389
|
+
</UButton>
|
|
389
390
|
|
|
390
391
|
<EmptyState
|
|
391
392
|
v-if="empty"
|
|
@@ -132,10 +132,11 @@ async function attach(item: PendingContext) {
|
|
|
132
132
|
/>
|
|
133
133
|
|
|
134
134
|
<div v-if="linked.length" class="space-y-1">
|
|
135
|
-
<
|
|
135
|
+
<ULink
|
|
136
|
+
raw
|
|
136
137
|
v-for="issue in linked"
|
|
137
138
|
:key="`${issue.source}:${issue.externalId}`"
|
|
138
|
-
:
|
|
139
|
+
:to="issue.url"
|
|
139
140
|
target="_blank"
|
|
140
141
|
rel="noopener"
|
|
141
142
|
class="flex items-center gap-1.5 rounded-md border border-default bg-default/60 px-2 py-1.5 text-xs text-toned hover:bg-elevated/60"
|
|
@@ -148,9 +149,9 @@ async function attach(item: PendingContext) {
|
|
|
148
149
|
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">
|
|
149
150
|
{{ issue.status }}
|
|
150
151
|
</UBadge>
|
|
151
|
-
</
|
|
152
|
+
</ULink>
|
|
152
153
|
</div>
|
|
153
|
-
<p v-else class="text-
|
|
154
|
+
<p v-else class="text-2xs text-dimmed">
|
|
154
155
|
{{ emptyHint }}
|
|
155
156
|
</p>
|
|
156
157
|
</InspectorSection>
|
|
@@ -17,6 +17,7 @@ import type { PendingContext } from '~/composables/useContextLinking'
|
|
|
17
17
|
import { type AddSourceLabels, addChoicesOf, buildSourceChoices } from '~/utils/sourcePicker'
|
|
18
18
|
import ContextIssuePicker from '~/components/tasks/ContextIssuePicker.vue'
|
|
19
19
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
20
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
20
21
|
|
|
21
22
|
const { t } = useI18n()
|
|
22
23
|
const ui = useUiStore()
|
|
@@ -183,9 +184,9 @@ async function doSpawnEpic() {
|
|
|
183
184
|
|
|
184
185
|
<!-- Secondary: spawn a parent/epic issue as a whole linked task group. -->
|
|
185
186
|
<div class="space-y-2 border-t border-default pt-3">
|
|
186
|
-
<
|
|
187
|
+
<SectionLabel as="span">
|
|
187
188
|
{{ t('tasks.import.asEpic') }}
|
|
188
|
-
</
|
|
189
|
+
</SectionLabel>
|
|
189
190
|
<div class="flex items-end gap-2">
|
|
190
191
|
<UFormField :label="descriptor?.refLabel ?? t('tasks.import.refLabel')" class="flex-1">
|
|
191
192
|
<UInput
|
|
@@ -128,10 +128,10 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
128
128
|
|
|
129
129
|
<!-- Credentialless source (GitHub Issues): no form, just the on/off toggle. -->
|
|
130
130
|
<template v-if="credentialless">
|
|
131
|
-
<p class="text-
|
|
131
|
+
<p class="text-2xs text-dimmed">
|
|
132
132
|
{{ t('tasks.connect.credentialless') }}
|
|
133
133
|
</p>
|
|
134
|
-
<p v-if="!available" class="text-
|
|
134
|
+
<p v-if="!available" class="text-2xs text-app-warning-400">
|
|
135
135
|
{{ t('tasks.connect.installAppHint', { label: descriptor.label }) }}
|
|
136
136
|
</p>
|
|
137
137
|
</template>
|
|
@@ -149,7 +149,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
149
149
|
>
|
|
150
150
|
{{ t('tasks.connect.oauthButton', { label: descriptor.label }) }}
|
|
151
151
|
</UButton>
|
|
152
|
-
<p class="text-center text-
|
|
152
|
+
<p class="text-center text-2xs text-dimmed">
|
|
153
153
|
{{ t('tasks.connect.oauthOr') }}
|
|
154
154
|
</p>
|
|
155
155
|
</template>
|
|
@@ -167,7 +167,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
167
167
|
/>
|
|
168
168
|
</UFormField>
|
|
169
169
|
</div>
|
|
170
|
-
<p v-else class="text-
|
|
170
|
+
<p v-else class="text-2xs text-dimmed">
|
|
171
171
|
{{
|
|
172
172
|
connection?.label
|
|
173
173
|
? t('tasks.connect.connectedTo', { label: connection.label })
|
|
@@ -184,7 +184,7 @@ async function toggleEnabled(enabled: boolean) {
|
|
|
184
184
|
<div class="font-medium text-default">
|
|
185
185
|
{{ t('tasks.connect.offerToWorkspace') }}
|
|
186
186
|
</div>
|
|
187
|
-
<div class="text-
|
|
187
|
+
<div class="text-2xs text-dimmed">
|
|
188
188
|
{{ t('tasks.connect.offerHint', { label: descriptor.label }) }}
|
|
189
189
|
</div>
|
|
190
190
|
</div>
|
|
@@ -22,6 +22,7 @@ import EnvironmentStatusPanel from '~/components/environments/EnvironmentStatusP
|
|
|
22
22
|
import ProvisioningLogsDrawer from '~/components/provisioning/ProvisioningLogsDrawer.vue'
|
|
23
23
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
24
24
|
import { runIsActive } from '~/utils/pipelineRender'
|
|
25
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
25
26
|
|
|
26
27
|
const board = useBoardStore()
|
|
27
28
|
const execution = useExecutionStore()
|
|
@@ -361,7 +362,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
361
362
|
</UBadge>
|
|
362
363
|
<span
|
|
363
364
|
v-if="testState && testState.attempts > 0"
|
|
364
|
-
class="text-
|
|
365
|
+
class="text-2xs text-muted"
|
|
365
366
|
:title="t('testing.fixerAttempts')"
|
|
366
367
|
>
|
|
367
368
|
{{ t('testing.fixCount', { attempts: testState.attempts, max: testState.maxAttempts }) }}
|
|
@@ -384,9 +385,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
384
385
|
data-testid="tester-infrastructure"
|
|
385
386
|
class="space-y-3"
|
|
386
387
|
>
|
|
387
|
-
<
|
|
388
|
+
<SectionLabel as="h3">
|
|
388
389
|
{{ t('testing.infrastructure') }}
|
|
389
|
-
</
|
|
390
|
+
</SectionLabel>
|
|
390
391
|
<StepContainerStatus :step="step" :run-failed="runFailed" :run-active="runActive" />
|
|
391
392
|
<EnvironmentStatusPanel
|
|
392
393
|
v-if="stepEnvironment"
|
|
@@ -414,10 +415,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
414
415
|
class="h-3.5 w-3.5 shrink-0"
|
|
415
416
|
:class="infraSetup.started ? 'text-app-success-400' : 'text-app-error-400'"
|
|
416
417
|
/>
|
|
417
|
-
<span class="text-
|
|
418
|
+
<span class="text-sm font-medium text-default">
|
|
418
419
|
{{ standupHeadline }}
|
|
419
420
|
</span>
|
|
420
|
-
<span v-if="infraSetup.durationMs != null" class="ms-auto text-
|
|
421
|
+
<span v-if="infraSetup.durationMs != null" class="ms-auto text-2xs text-dimmed">
|
|
421
422
|
{{
|
|
422
423
|
t('testing.standup.took', {
|
|
423
424
|
seconds: n(infraSetup.durationMs / 1000, 'decimal'),
|
|
@@ -425,12 +426,12 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
425
426
|
}}
|
|
426
427
|
</span>
|
|
427
428
|
</div>
|
|
428
|
-
<p v-if="infraSetup.composePath" class="mt-1 font-mono text-
|
|
429
|
+
<p v-if="infraSetup.composePath" class="mt-1 font-mono text-2xs text-dimmed">
|
|
429
430
|
{{ infraSetup.composePath }}
|
|
430
431
|
</p>
|
|
431
432
|
<p
|
|
432
433
|
v-if="infraSetup.error"
|
|
433
|
-
class="mt-1 text-
|
|
434
|
+
class="mt-1 text-xs leading-snug text-app-error-300"
|
|
434
435
|
data-testid="tester-infra-setup-error"
|
|
435
436
|
>
|
|
436
437
|
{{ infraSetup.error }}
|
|
@@ -455,7 +456,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
455
456
|
<pre
|
|
456
457
|
v-if="showInfraSetupLogs"
|
|
457
458
|
data-testid="tester-infra-setup-logs"
|
|
458
|
-
class="mt-2 max-h-64 overflow-auto rounded bg-app-950/70 p-2 font-mono text-
|
|
459
|
+
class="mt-2 max-h-64 overflow-auto rounded-sm bg-app-950/70 p-2 font-mono text-2xs leading-relaxed text-toned"
|
|
459
460
|
>{{ infraSetup.logs }}</pre>
|
|
460
461
|
</template>
|
|
461
462
|
</div>
|
|
@@ -467,7 +468,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
467
468
|
<div
|
|
468
469
|
v-if="infraReady"
|
|
469
470
|
data-testid="tester-env-ready"
|
|
470
|
-
class="flex items-center gap-2 rounded-lg border border-app-success-500/30 bg-app-success-500/10 px-3 py-2 text-
|
|
471
|
+
class="flex items-center gap-2 rounded-lg border border-app-success-500/30 bg-app-success-500/10 px-3 py-2 text-sm text-app-success-200"
|
|
471
472
|
>
|
|
472
473
|
<UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0 text-app-success-400" />
|
|
473
474
|
<span>{{ t('testing.readyBanner') }}</span>
|
|
@@ -504,9 +505,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
504
505
|
how it ended), so the otherwise-opaque fixer sub-jobs have a surface — the
|
|
505
506
|
analogue of the polling gate's attempt history. -->
|
|
506
507
|
<section v-if="fixerAttempts.length" data-testid="tester-fixer-attempts" class="space-y-2">
|
|
507
|
-
<
|
|
508
|
+
<SectionLabel as="h3">
|
|
508
509
|
{{ t('testing.fixerAttempts') }}
|
|
509
|
-
</
|
|
510
|
+
</SectionLabel>
|
|
510
511
|
<ol class="space-y-2">
|
|
511
512
|
<li
|
|
512
513
|
v-for="a in fixerAttempts"
|
|
@@ -531,20 +532,20 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
531
532
|
<MarkdownProse
|
|
532
533
|
v-if="a.summary"
|
|
533
534
|
:text="a.summary"
|
|
534
|
-
class="mt-1 max-w-3xl text-
|
|
535
|
+
class="mt-1 max-w-3xl text-xs leading-snug text-muted"
|
|
535
536
|
/>
|
|
536
537
|
<div v-if="a.concerns && a.concerns.length" class="mt-1.5">
|
|
537
|
-
<p class="text-
|
|
538
|
+
<p class="text-2xs text-dimmed">
|
|
538
539
|
{{ t('testing.fixerTimeline.addressed') }}
|
|
539
540
|
</p>
|
|
540
541
|
<ul class="mt-1 space-y-0.5">
|
|
541
542
|
<li
|
|
542
543
|
v-for="(c, ci) in a.concerns"
|
|
543
544
|
:key="`fa${a.attempt}-c${ci}`"
|
|
544
|
-
class="flex items-center gap-1.5 text-
|
|
545
|
+
class="flex items-center gap-1.5 text-xs text-toned"
|
|
545
546
|
>
|
|
546
547
|
<span
|
|
547
|
-
class="rounded px-1 text-
|
|
548
|
+
class="rounded-sm px-1 text-3xs uppercase"
|
|
548
549
|
:class="SEVERITY_META[c.severity].chip"
|
|
549
550
|
>{{ SEVERITY_LABELS[c.severity] }}</span
|
|
550
551
|
>
|
|
@@ -566,12 +567,12 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
566
567
|
class="space-y-2"
|
|
567
568
|
>
|
|
568
569
|
<div class="flex items-center gap-2">
|
|
569
|
-
<
|
|
570
|
+
<SectionLabel as="h3">
|
|
570
571
|
{{ t('testing.quality.heading') }}
|
|
571
|
-
</
|
|
572
|
+
</SectionLabel>
|
|
572
573
|
<span
|
|
573
574
|
v-if="quality.attempts"
|
|
574
|
-
class="text-
|
|
575
|
+
class="text-2xs text-muted"
|
|
575
576
|
:title="t('testing.quality.reruns')"
|
|
576
577
|
>
|
|
577
578
|
{{
|
|
@@ -604,30 +605,30 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
604
605
|
class="h-3.5 w-3.5 shrink-0"
|
|
605
606
|
:class="vd.adequate ? 'text-app-success-400' : 'text-app-warning-300'"
|
|
606
607
|
/>
|
|
607
|
-
<span class="text-
|
|
608
|
+
<span class="text-sm font-medium text-default">
|
|
608
609
|
{{
|
|
609
610
|
vd.adequate ? t('testing.quality.adequate') : t('testing.quality.inadequate')
|
|
610
611
|
}}
|
|
611
612
|
</span>
|
|
612
|
-
<span v-if="vd.model" class="ms-auto font-mono text-
|
|
613
|
+
<span v-if="vd.model" class="ms-auto font-mono text-3xs text-dimmed">{{
|
|
613
614
|
vd.model
|
|
614
615
|
}}</span>
|
|
615
|
-
<span class="text-
|
|
616
|
+
<span class="text-2xs text-dimmed" :class="{ 'ms-auto': !vd.model }">{{
|
|
616
617
|
d(new Date(vd.at), 'short')
|
|
617
618
|
}}</span>
|
|
618
619
|
</div>
|
|
619
620
|
<MarkdownProse
|
|
620
621
|
v-if="vd.feedback"
|
|
621
622
|
:text="vd.feedback"
|
|
622
|
-
class="mt-1 text-
|
|
623
|
+
class="mt-1 text-xs leading-snug text-muted"
|
|
623
624
|
/>
|
|
624
625
|
<div v-if="vd.gaps.length" class="mt-1.5">
|
|
625
|
-
<p class="text-
|
|
626
|
+
<p class="text-2xs text-dimmed">{{ t('testing.quality.gaps') }}</p>
|
|
626
627
|
<ul class="mt-1 space-y-0.5">
|
|
627
628
|
<li
|
|
628
629
|
v-for="(gap, gi) in vd.gaps"
|
|
629
630
|
:key="`qc${vi}-g${gi}`"
|
|
630
|
-
class="flex items-start gap-1.5 text-
|
|
631
|
+
class="flex items-start gap-1.5 text-xs text-toned"
|
|
631
632
|
>
|
|
632
633
|
<UIcon
|
|
633
634
|
name="i-lucide-dot"
|
|
@@ -647,7 +648,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
647
648
|
>
|
|
648
649
|
<UIcon name="i-lucide-flask-conical" class="h-8 w-8 opacity-40" />
|
|
649
650
|
<p class="text-sm">{{ t('testing.empty.title') }}</p>
|
|
650
|
-
<p class="max-w-sm text-
|
|
651
|
+
<p class="max-w-sm text-2xs text-dimmed">
|
|
651
652
|
{{ t('testing.empty.hint') }}
|
|
652
653
|
</p>
|
|
653
654
|
</div>
|
|
@@ -659,19 +660,21 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
659
660
|
<MarkdownProse
|
|
660
661
|
v-if="report.summary"
|
|
661
662
|
:text="report.summary"
|
|
662
|
-
class="mb-4 max-w-3xl text-
|
|
663
|
+
class="mb-4 max-w-3xl text-sm leading-relaxed text-toned"
|
|
663
664
|
/>
|
|
664
665
|
|
|
665
|
-
<h3 class="mb-2
|
|
666
|
+
<SectionLabel as="h3" class="mb-2">
|
|
666
667
|
{{ t('testing.scenariosOutcomes') }}
|
|
667
|
-
</
|
|
668
|
+
</SectionLabel>
|
|
668
669
|
<ul class="space-y-2">
|
|
669
670
|
<li
|
|
670
671
|
v-for="g in groups"
|
|
671
672
|
:key="g.key"
|
|
672
673
|
class="overflow-hidden rounded-lg border border-default bg-default/60"
|
|
673
674
|
>
|
|
674
|
-
<
|
|
675
|
+
<UButton
|
|
676
|
+
color="neutral"
|
|
677
|
+
variant="ghost"
|
|
675
678
|
class="flex w-full items-center gap-2 px-3 py-2 text-start hover:bg-elevated/40"
|
|
676
679
|
@click="toggle(g.key)"
|
|
677
680
|
>
|
|
@@ -685,7 +688,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
685
688
|
:class="GROUP_STATUS_META[g.status].text"
|
|
686
689
|
/>
|
|
687
690
|
<span
|
|
688
|
-
class="min-w-0 flex-1 truncate text-
|
|
691
|
+
class="min-w-0 flex-1 truncate text-sm"
|
|
689
692
|
:class="g.other ? 'text-muted' : 'font-medium text-default'"
|
|
690
693
|
>
|
|
691
694
|
{{ g.title }}
|
|
@@ -702,14 +705,14 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
702
705
|
)
|
|
703
706
|
"
|
|
704
707
|
/>
|
|
705
|
-
<span class="shrink-0 text-
|
|
708
|
+
<span class="shrink-0 text-2xs text-dimmed">
|
|
706
709
|
{{ t('testing.checkCount', { count: g.outcomes.length }, g.outcomes.length) }}
|
|
707
710
|
<template v-if="g.concerns.length">
|
|
708
711
|
·
|
|
709
712
|
{{ t('testing.concernCount', { count: g.concerns.length }, g.concerns.length) }}
|
|
710
713
|
</template>
|
|
711
714
|
</span>
|
|
712
|
-
</
|
|
715
|
+
</UButton>
|
|
713
716
|
|
|
714
717
|
<div v-if="!collapsed.has(g.key)" class="space-y-1 px-3 pb-3 ps-9">
|
|
715
718
|
<!-- Outcomes -->
|
|
@@ -724,15 +727,15 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
724
727
|
:class="STATUS_META[o.status].text"
|
|
725
728
|
/>
|
|
726
729
|
<div class="min-w-0">
|
|
727
|
-
<span class="text-
|
|
730
|
+
<span class="text-sm text-default">{{ o.name }}</span>
|
|
728
731
|
<MarkdownProse
|
|
729
732
|
v-if="o.detail"
|
|
730
733
|
:text="o.detail"
|
|
731
|
-
class="max-w-3xl text-
|
|
734
|
+
class="max-w-3xl text-xs leading-snug text-muted"
|
|
732
735
|
/>
|
|
733
736
|
</div>
|
|
734
737
|
</div>
|
|
735
|
-
<p v-if="!g.outcomes.length" class="py-0.5 text-
|
|
738
|
+
<p v-if="!g.outcomes.length" class="py-0.5 text-xs italic text-dimmed">
|
|
736
739
|
{{ t('testing.noDiscreteCheck') }}
|
|
737
740
|
</p>
|
|
738
741
|
|
|
@@ -749,9 +752,9 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
749
752
|
/>
|
|
750
753
|
<div class="min-w-0">
|
|
751
754
|
<div class="flex items-center gap-1.5">
|
|
752
|
-
<span class="text-
|
|
755
|
+
<span class="text-xs font-medium text-default">{{ c.title }}</span>
|
|
753
756
|
<span
|
|
754
|
-
class="rounded px-1 text-
|
|
757
|
+
class="rounded-sm px-1 text-3xs uppercase"
|
|
755
758
|
:class="SEVERITY_META[c.severity].chip"
|
|
756
759
|
>
|
|
757
760
|
{{ SEVERITY_LABELS[c.severity] }}
|
|
@@ -760,18 +763,20 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
760
763
|
<MarkdownProse
|
|
761
764
|
v-if="c.detail"
|
|
762
765
|
:text="c.detail"
|
|
763
|
-
class="max-w-3xl text-
|
|
766
|
+
class="max-w-3xl text-xs leading-snug text-muted"
|
|
764
767
|
/>
|
|
765
768
|
</div>
|
|
766
769
|
</div>
|
|
767
770
|
|
|
768
771
|
<!-- Screenshots captured for this scenario -->
|
|
769
772
|
<div v-if="g.screenshots.length" class="mt-2 flex flex-wrap gap-2">
|
|
770
|
-
<
|
|
773
|
+
<UButton
|
|
774
|
+
color="neutral"
|
|
775
|
+
variant="ghost"
|
|
771
776
|
v-for="(s, si) in g.screenshots"
|
|
772
777
|
:key="`shot${si}`"
|
|
773
778
|
data-testid="tester-screenshot"
|
|
774
|
-
class="group relative h-20 w-28 shrink-0 overflow-hidden rounded border border-default bg-app-950/60 hover:border-app-600"
|
|
779
|
+
class="group relative block h-20 w-28 shrink-0 overflow-hidden rounded-sm border border-default bg-app-950/60 hover:bg-app-950/60 focus-visible:bg-app-950/60 disabled:bg-app-950/60 p-0 hover:border-app-600"
|
|
775
780
|
:title="s.view"
|
|
776
781
|
@click="openShot(s.artifactId)"
|
|
777
782
|
>
|
|
@@ -783,7 +788,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
783
788
|
/>
|
|
784
789
|
<span
|
|
785
790
|
v-else
|
|
786
|
-
class="flex h-full w-full items-center justify-center text-
|
|
791
|
+
class="flex h-full w-full items-center justify-center text-3xs text-app-600"
|
|
787
792
|
>
|
|
788
793
|
{{
|
|
789
794
|
blobs.statusFor(s.artifactId) === 'error'
|
|
@@ -792,10 +797,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
792
797
|
}}
|
|
793
798
|
</span>
|
|
794
799
|
<span
|
|
795
|
-
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1 py-0.5 text-
|
|
800
|
+
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1 py-0.5 text-3xs text-toned"
|
|
796
801
|
>{{ s.view }}</span
|
|
797
802
|
>
|
|
798
|
-
</
|
|
803
|
+
</UButton>
|
|
799
804
|
</div>
|
|
800
805
|
</div>
|
|
801
806
|
</li>
|
|
@@ -803,14 +808,16 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
803
808
|
|
|
804
809
|
<!-- Standalone gallery: any captures not mapped to a scenario above -->
|
|
805
810
|
<section v-if="ungroupedScreenshots.length" class="mt-5">
|
|
806
|
-
<h3 class="mb-2
|
|
811
|
+
<SectionLabel as="h3" class="mb-2">
|
|
807
812
|
{{ t('testing.screenshots') }}
|
|
808
|
-
</
|
|
813
|
+
</SectionLabel>
|
|
809
814
|
<div class="grid grid-cols-2 gap-3 sm:grid-cols-3">
|
|
810
|
-
<
|
|
815
|
+
<UButton
|
|
816
|
+
color="neutral"
|
|
817
|
+
variant="ghost"
|
|
811
818
|
v-for="(s, si) in ungroupedScreenshots"
|
|
812
819
|
:key="`gal${si}`"
|
|
813
|
-
class="group relative aspect-video overflow-hidden rounded-lg border border-default bg-app-950/60 hover:border-app-600"
|
|
820
|
+
class="group relative block aspect-video overflow-hidden rounded-lg border border-default bg-app-950/60 hover:bg-app-950/60 focus-visible:bg-app-950/60 disabled:bg-app-950/60 p-0 hover:border-app-600"
|
|
814
821
|
:title="s.view"
|
|
815
822
|
@click="openShot(s.artifactId)"
|
|
816
823
|
>
|
|
@@ -822,7 +829,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
822
829
|
/>
|
|
823
830
|
<span
|
|
824
831
|
v-else
|
|
825
|
-
class="flex h-full w-full items-center justify-center text-
|
|
832
|
+
class="flex h-full w-full items-center justify-center text-2xs text-app-600"
|
|
826
833
|
>
|
|
827
834
|
{{
|
|
828
835
|
blobs.statusFor(s.artifactId) === 'error'
|
|
@@ -831,10 +838,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
831
838
|
}}
|
|
832
839
|
</span>
|
|
833
840
|
<span
|
|
834
|
-
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1.5 py-0.5 text-
|
|
841
|
+
class="absolute inset-x-0 bottom-0 truncate bg-app-950/80 px-1.5 py-0.5 text-3xs text-toned"
|
|
835
842
|
>{{ s.view }}</span
|
|
836
843
|
>
|
|
837
|
-
</
|
|
844
|
+
</UButton>
|
|
838
845
|
</div>
|
|
839
846
|
</section>
|
|
840
847
|
</template>
|
|
@@ -845,10 +852,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
845
852
|
class="hidden w-60 shrink-0 flex-col gap-4 border-s border-default bg-default/50 px-4 py-4 lg:flex"
|
|
846
853
|
>
|
|
847
854
|
<div v-if="report">
|
|
848
|
-
<h4 class="mb-2
|
|
855
|
+
<SectionLabel as="h4" class="mb-2">
|
|
849
856
|
{{ t('testing.verdict.heading') }}
|
|
850
|
-
</
|
|
851
|
-
<div class="flex items-center gap-2 text-
|
|
857
|
+
</SectionLabel>
|
|
858
|
+
<div class="flex items-center gap-2 text-sm">
|
|
852
859
|
<UIcon
|
|
853
860
|
:name="report.greenlight ? 'i-lucide-circle-check' : 'i-lucide-circle-x'"
|
|
854
861
|
class="h-4 w-4"
|
|
@@ -861,10 +868,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
861
868
|
</div>
|
|
862
869
|
|
|
863
870
|
<div v-if="report">
|
|
864
|
-
<h4 class="mb-2
|
|
871
|
+
<SectionLabel as="h4" class="mb-2">
|
|
865
872
|
{{ t('testing.outcomes.heading') }}
|
|
866
|
-
</
|
|
867
|
-
<dl class="space-y-1 text-
|
|
873
|
+
</SectionLabel>
|
|
874
|
+
<dl class="space-y-1 text-xs">
|
|
868
875
|
<div class="flex items-center justify-between">
|
|
869
876
|
<dt class="text-muted">{{ t('testing.outcomes.passed') }}</dt>
|
|
870
877
|
<dd class="text-app-success-300">{{ counts.passed }}</dd>
|
|
@@ -892,10 +899,10 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
892
899
|
</div>
|
|
893
900
|
|
|
894
901
|
<div v-if="report?.environment">
|
|
895
|
-
<h4 class="mb-1
|
|
902
|
+
<SectionLabel as="h4" class="mb-1">
|
|
896
903
|
{{ t('testing.environment') }}
|
|
897
|
-
</
|
|
898
|
-
<p class="text-
|
|
904
|
+
</SectionLabel>
|
|
905
|
+
<p class="text-xs capitalize text-toned">{{ report.environment }}</p>
|
|
899
906
|
</div>
|
|
900
907
|
|
|
901
908
|
<!-- Shared run metadata + embedded observability (model, run id, timing,
|
|
@@ -910,7 +917,7 @@ const GROUP_STATUS_META: Record<ScenarioGroup['status'], { icon: string; text: s
|
|
|
910
917
|
:failure-at="instance?.failure?.occurredAt"
|
|
911
918
|
/>
|
|
912
919
|
|
|
913
|
-
<p class="mt-auto text-
|
|
920
|
+
<p class="mt-auto text-3xs leading-relaxed text-app-600">
|
|
914
921
|
{{ t('testing.footer') }}
|
|
915
922
|
</p>
|
|
916
923
|
</aside>
|
|
@@ -66,7 +66,7 @@ async function submit() {
|
|
|
66
66
|
:description="t('appearance.import.description')"
|
|
67
67
|
>
|
|
68
68
|
<template #body>
|
|
69
|
-
<
|
|
69
|
+
<UForm class="space-y-4" data-testid="theme-import-form" @submit="submit">
|
|
70
70
|
<UFormField
|
|
71
71
|
:label="t('appearance.import.linkLabel')"
|
|
72
72
|
:error="error ? t(ERROR_KEYS[error]) : undefined"
|
|
@@ -109,7 +109,7 @@ async function submit() {
|
|
|
109
109
|
{{ t('appearance.import.submit') }}
|
|
110
110
|
</UButton>
|
|
111
111
|
</div>
|
|
112
|
-
</
|
|
112
|
+
</UForm>
|
|
113
113
|
</template>
|
|
114
114
|
</UModal>
|
|
115
115
|
</template>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
3
4
|
|
|
4
5
|
// The contextual offer's surface: one walkthrough, offered beside the work that just made it
|
|
5
6
|
// relevant. Deliberately NOT a modal — the whole point is the moment, and a modal would
|
|
@@ -75,9 +76,9 @@ function take(tourId: string) {
|
|
|
75
76
|
class="text-primary mt-0.5 h-4 w-4 shrink-0"
|
|
76
77
|
/>
|
|
77
78
|
<div class="min-w-0 flex-1">
|
|
78
|
-
<
|
|
79
|
+
<SectionLabel as="p">
|
|
79
80
|
{{ t('tutorial.nudge.label') }}
|
|
80
|
-
</
|
|
81
|
+
</SectionLabel>
|
|
81
82
|
<p class="mt-0.5 text-sm font-medium text-app-100">{{ t(offered.titleKey) }}</p>
|
|
82
83
|
<p class="mt-0.5 text-xs text-muted">{{ t(offered.descriptionKey) }}</p>
|
|
83
84
|
</div>
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
waitBudgetMs,
|
|
21
21
|
} from './TutorialOverlay.logic'
|
|
22
22
|
import type { TutorialAdvanceCause, TutorialDirection } from './TutorialOverlay.logic'
|
|
23
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
23
24
|
|
|
24
25
|
// The one shared tour runtime: resolves the running tour from the `tutorialTours` slot,
|
|
25
26
|
// anchors a highlight ring + tooltip to the current step's `data-testid`, and advances
|
|
@@ -628,9 +629,9 @@ onUnmounted(() => {
|
|
|
628
629
|
class="mt-3 rounded-lg border border-muted/70 bg-elevated/40 p-2.5"
|
|
629
630
|
data-testid="tutorial-next-tour"
|
|
630
631
|
>
|
|
631
|
-
<
|
|
632
|
+
<SectionLabel as="p">
|
|
632
633
|
{{ t('tutorial.overlay.nextUp') }}
|
|
633
|
-
</
|
|
634
|
+
</SectionLabel>
|
|
634
635
|
<p class="mt-0.5 text-sm font-medium text-app-100">{{ t(nextTour.titleKey) }}</p>
|
|
635
636
|
<p class="mt-0.5 text-xs text-muted">{{ t(nextTour.descriptionKey) }}</p>
|
|
636
637
|
<UButton
|
|
@@ -67,7 +67,7 @@ async function connect() {
|
|
|
67
67
|
/>
|
|
68
68
|
</UFormField>
|
|
69
69
|
|
|
70
|
-
<p class="text-
|
|
70
|
+
<p class="text-2xs text-dimmed">
|
|
71
71
|
<ULink :to="tokenUrl" target="_blank" class="text-primary hover:underline">
|
|
72
72
|
{{ t('vcs.connect.gitlab.createToken') }}
|
|
73
73
|
</ULink>
|