@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
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// flag); the hard `blocked` tier does not. Driven by `ui.reviewFrictionContext`, mounted in
|
|
7
7
|
// pages/index.vue. See backend/docs/review-debt-friction.md.
|
|
8
8
|
import { computed } from 'vue'
|
|
9
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
10
|
|
|
10
11
|
const { t } = useI18n()
|
|
11
12
|
const ui = useUiStore()
|
|
@@ -84,13 +85,14 @@ function createAnyway() {
|
|
|
84
85
|
<p class="text-sm text-toned">{{ body }}</p>
|
|
85
86
|
|
|
86
87
|
<div class="rounded-lg border border-muted bg-default/50 p-2">
|
|
87
|
-
<p class="mb-1.5 px-1
|
|
88
|
+
<SectionLabel as="p" class="mb-1.5 px-1">
|
|
88
89
|
{{ t('errors.reviewFriction.waitingHeading') }}
|
|
89
|
-
</
|
|
90
|
+
</SectionLabel>
|
|
90
91
|
<ul class="space-y-1">
|
|
91
92
|
<li v-for="item in ctx.debt" :key="item.blockId">
|
|
92
|
-
<
|
|
93
|
-
|
|
93
|
+
<UButton
|
|
94
|
+
color="neutral"
|
|
95
|
+
variant="ghost"
|
|
94
96
|
class="flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-left text-sm hover:bg-elevated/60 disabled:opacity-50"
|
|
95
97
|
:disabled="pending"
|
|
96
98
|
@click="goToBlock(item.blockId)"
|
|
@@ -98,10 +100,10 @@ function createAnyway() {
|
|
|
98
100
|
<span class="truncate text-default">
|
|
99
101
|
{{ item.title || t('errors.reviewFriction.untitled') }}
|
|
100
102
|
</span>
|
|
101
|
-
<span class="shrink-0 text-
|
|
103
|
+
<span class="shrink-0 text-xs text-dimmed">
|
|
102
104
|
{{ t('errors.reviewFriction.waiting', { minutes: item.waitingMinutes }) }}
|
|
103
105
|
</span>
|
|
104
|
-
</
|
|
106
|
+
</UButton>
|
|
105
107
|
</li>
|
|
106
108
|
</ul>
|
|
107
109
|
</div>
|
|
@@ -55,7 +55,7 @@ const entries = computed<Entry[]>(() =>
|
|
|
55
55
|
>
|
|
56
56
|
<!-- a superseded SUCCESSFUL attempt: its output, collapsible + copyable -->
|
|
57
57
|
<template v-if="entry.kind === 'success'">
|
|
58
|
-
<div class="flex items-center gap-1.5 text-
|
|
58
|
+
<div class="flex items-center gap-1.5 text-3xs text-dimmed">
|
|
59
59
|
<UIcon name="i-lucide-check-circle-2" class="h-3 w-3 shrink-0 text-app-success-400/70" />
|
|
60
60
|
<time>{{ d(new Date(entry.occurredAt), 'long') }}</time>
|
|
61
61
|
<span class="text-app-success-400/80">{{ t('panels.stepDetail.attemptSucceeded') }}</span>
|
|
@@ -63,31 +63,31 @@ const entries = computed<Entry[]>(() =>
|
|
|
63
63
|
<div class="relative mt-1">
|
|
64
64
|
<CopyButton :text="entry.output.output" class="absolute end-1 top-1 z-10" />
|
|
65
65
|
<pre
|
|
66
|
-
class="max-h-40 overflow-auto whitespace-pre-wrap rounded bg-app-950/80 p-1.5 pe-9 text-
|
|
66
|
+
class="max-h-40 overflow-auto whitespace-pre-wrap rounded-sm bg-app-950/80 p-1.5 pe-9 text-3xs leading-snug text-toned"
|
|
67
67
|
>{{ entry.output.output }}</pre>
|
|
68
68
|
</div>
|
|
69
|
-
<p v-if="entry.output.truncated" class="mt-1 text-
|
|
69
|
+
<p v-if="entry.output.truncated" class="mt-1 text-3xs text-dimmed">
|
|
70
70
|
{{ t('panels.stepDetail.outputTruncated') }}
|
|
71
71
|
</p>
|
|
72
72
|
</template>
|
|
73
73
|
|
|
74
74
|
<!-- a FAILED attempt: mirrors FailureHistoryList's entry markup -->
|
|
75
75
|
<template v-else>
|
|
76
|
-
<div class="flex items-center gap-1.5 text-
|
|
76
|
+
<div class="flex items-center gap-1.5 text-3xs text-dimmed">
|
|
77
77
|
<UIcon name="i-lucide-alert-triangle" class="h-3 w-3 shrink-0 text-app-error-400/70" />
|
|
78
78
|
<time>{{ d(new Date(entry.occurredAt), 'long') }}</time>
|
|
79
79
|
</div>
|
|
80
|
-
<p class="mt-1 text-
|
|
80
|
+
<p class="mt-1 text-2xs leading-snug text-toned" :title="entry.failure.message">
|
|
81
81
|
{{ entry.failure.message }}
|
|
82
82
|
</p>
|
|
83
|
-
<p v-if="entry.failure.hint" class="mt-1 text-
|
|
83
|
+
<p v-if="entry.failure.hint" class="mt-1 text-3xs leading-snug text-dimmed">
|
|
84
84
|
{{ entry.failure.hint }}
|
|
85
85
|
</p>
|
|
86
86
|
<FailureDetail
|
|
87
87
|
:detail="entry.failure.detail"
|
|
88
88
|
:message="entry.failure.message"
|
|
89
|
-
summary-class="text-
|
|
90
|
-
pre-class="bg-app-950/80 text-
|
|
89
|
+
summary-class="text-3xs text-dimmed hover:text-toned"
|
|
90
|
+
pre-class="bg-app-950/80 text-3xs text-muted"
|
|
91
91
|
/>
|
|
92
92
|
</template>
|
|
93
93
|
</li>
|
|
@@ -52,7 +52,7 @@ const dim = computed(() => (props.size === 'sm' ? 'h-7 w-7' : 'h-9 w-9'))
|
|
|
52
52
|
/>
|
|
53
53
|
</span>
|
|
54
54
|
</div>
|
|
55
|
-
<span v-if="size !== 'sm'" class="text-
|
|
55
|
+
<span v-if="size !== 'sm'" class="text-3xs leading-none text-toned">
|
|
56
56
|
{{ archetype.label }}
|
|
57
57
|
</span>
|
|
58
58
|
</div>
|
|
@@ -9,11 +9,11 @@ import AgentFailureCard from '~/components/board/AgentFailureCard.vue'
|
|
|
9
9
|
import AgentStopButton from '~/components/board/AgentStopButton.vue'
|
|
10
10
|
import AdoptionReviewModal from '~/components/bootstrap/AdoptionReviewModal.vue'
|
|
11
11
|
import BootstrapRunSteps from '~/components/bootstrap/BootstrapRunSteps.vue'
|
|
12
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
12
13
|
import { useBlockDrag } from '~/composables/useBlockDrag'
|
|
13
14
|
import { useFrameStacking } from '~/composables/useFrameStacking'
|
|
14
15
|
import { useViewport } from '~/composables/useViewport'
|
|
15
16
|
import { laneBodyHeightIn } from '~/utils/laneGeometry'
|
|
16
|
-
|
|
17
17
|
// Vue Flow passes the node's `id` and `data` as props to custom node components.
|
|
18
18
|
// Only frames are rendered as board nodes; their tasks live inside the card.
|
|
19
19
|
const props = defineProps<{ id: string }>()
|
|
@@ -249,10 +249,10 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
249
249
|
}}</span>
|
|
250
250
|
</div>
|
|
251
251
|
<div class="px-3 py-3">
|
|
252
|
-
<p class="text-
|
|
252
|
+
<p class="text-2xs leading-snug text-muted">
|
|
253
253
|
{{ t('board.frame.accessDenied.hint') }}
|
|
254
254
|
</p>
|
|
255
|
-
<code class="mt-2 block truncate font-mono text-
|
|
255
|
+
<code class="mt-2 block truncate font-mono text-2xs text-dimmed">{{ block.id }}</code>
|
|
256
256
|
</div>
|
|
257
257
|
</div>
|
|
258
258
|
|
|
@@ -316,9 +316,9 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
316
316
|
}}
|
|
317
317
|
</span>
|
|
318
318
|
</div>
|
|
319
|
-
<div class="mt-1.5 h-1 w-full overflow-hidden rounded bg-app-warning-900/40">
|
|
319
|
+
<div class="mt-1.5 h-1 w-full overflow-hidden rounded-sm bg-app-warning-900/40">
|
|
320
320
|
<div
|
|
321
|
-
class="h-full rounded bg-app-warning-400 transition-all"
|
|
321
|
+
class="h-full rounded-sm bg-app-warning-400 transition-all"
|
|
322
322
|
:style="{ width: bootstrapPct + '%' }"
|
|
323
323
|
/>
|
|
324
324
|
</div>
|
|
@@ -327,7 +327,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
327
327
|
<li
|
|
328
328
|
v-for="(item, i) in bootstrapItems"
|
|
329
329
|
:key="i"
|
|
330
|
-
class="flex items-start gap-1.5 text-
|
|
330
|
+
class="flex items-start gap-1.5 text-2xs"
|
|
331
331
|
:class="
|
|
332
332
|
item.status === 'completed'
|
|
333
333
|
? 'text-app-warning-200/60 line-through'
|
|
@@ -430,7 +430,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
430
430
|
{{ t('board.frame.shared') }}
|
|
431
431
|
</UBadge>
|
|
432
432
|
</div>
|
|
433
|
-
<div class="text-
|
|
433
|
+
<div class="text-2xs text-muted">{{ typeMeta!.label }}</div>
|
|
434
434
|
</div>
|
|
435
435
|
</div>
|
|
436
436
|
<div class="flex items-center gap-1">
|
|
@@ -441,27 +441,27 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
441
441
|
are `board.write`, hidden for a read-only viewer, who keeps the status badge
|
|
442
442
|
(the one view-only affordance here). -->
|
|
443
443
|
<template v-if="access.canWriteBoard.value">
|
|
444
|
-
<
|
|
444
|
+
<IconButton
|
|
445
445
|
class="nodrag"
|
|
446
446
|
data-testid="frame-add-task"
|
|
447
447
|
:size="isTouch ? 'sm' : 'xs'"
|
|
448
448
|
variant="ghost"
|
|
449
449
|
color="neutral"
|
|
450
450
|
icon="i-lucide-plus"
|
|
451
|
-
:
|
|
451
|
+
:label="t('board.frame.addTaskTitle')"
|
|
452
452
|
@click.stop="addTask"
|
|
453
453
|
/>
|
|
454
|
-
<
|
|
454
|
+
<IconButton
|
|
455
455
|
v-if="tasks.anyOffered"
|
|
456
456
|
class="nodrag"
|
|
457
457
|
:size="isTouch ? 'sm' : 'xs'"
|
|
458
458
|
variant="ghost"
|
|
459
459
|
color="neutral"
|
|
460
460
|
icon="i-lucide-ticket"
|
|
461
|
-
:
|
|
461
|
+
:label="t('board.frame.createTaskFromIssueTitle')"
|
|
462
462
|
@click.stop="createTaskFromIssue"
|
|
463
463
|
/>
|
|
464
|
-
<
|
|
464
|
+
<IconButton
|
|
465
465
|
v-if="documents.connectedDesignSources.length > 0"
|
|
466
466
|
class="nodrag"
|
|
467
467
|
data-testid="frame-start-from-design"
|
|
@@ -469,7 +469,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
469
469
|
variant="ghost"
|
|
470
470
|
color="neutral"
|
|
471
471
|
icon="i-lucide-frame"
|
|
472
|
-
:
|
|
472
|
+
:label="t('board.frame.startFromDesignTitle')"
|
|
473
473
|
@click.stop="startFromDesign"
|
|
474
474
|
/>
|
|
475
475
|
<!-- Recurring pipelines + initiatives are ADVANCED-tier authoring: both plan
|
|
@@ -480,7 +480,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
480
480
|
badges its task card and opens its inspector panel, and an initiative is
|
|
481
481
|
still a block on the board with its own inspector — so what a basic-mode
|
|
482
482
|
user loses is the ability to author a new one, not sight of one. -->
|
|
483
|
-
<
|
|
483
|
+
<IconButton
|
|
484
484
|
v-if="uiMode.isAdvanced"
|
|
485
485
|
class="nodrag"
|
|
486
486
|
data-testid="frame-add-recurring"
|
|
@@ -488,10 +488,10 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
488
488
|
variant="ghost"
|
|
489
489
|
color="neutral"
|
|
490
490
|
icon="i-lucide-repeat"
|
|
491
|
-
:
|
|
491
|
+
:label="t('board.frame.addRecurringTitle')"
|
|
492
492
|
@click.stop="addRecurring"
|
|
493
493
|
/>
|
|
494
|
-
<
|
|
494
|
+
<IconButton
|
|
495
495
|
v-if="uiMode.isAdvanced"
|
|
496
496
|
class="nodrag"
|
|
497
497
|
data-testid="frame-add-initiative"
|
|
@@ -499,7 +499,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
499
499
|
variant="ghost"
|
|
500
500
|
color="neutral"
|
|
501
501
|
icon="i-lucide-milestone"
|
|
502
|
-
:
|
|
502
|
+
:label="t('board.frame.createInitiativeTitle')"
|
|
503
503
|
@click.stop="createInitiative"
|
|
504
504
|
/>
|
|
505
505
|
<!-- Hunting a tracker board for a bug worth adopting is TRIAGE, not intake: it
|
|
@@ -507,7 +507,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
507
507
|
engineer/PM judgement call. So it is dropped for a narrowed role, whose three
|
|
508
508
|
routes in (a new task, a task from a named ticket, a task from a design) all
|
|
509
509
|
start from work somebody has already decided to do. -->
|
|
510
|
-
<
|
|
510
|
+
<IconButton
|
|
511
511
|
v-if="tasks.anyOffered && uiRole.fullSurface"
|
|
512
512
|
class="nodrag"
|
|
513
513
|
data-testid="frame-hunt-bugs"
|
|
@@ -515,7 +515,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
515
515
|
variant="ghost"
|
|
516
516
|
color="neutral"
|
|
517
517
|
icon="i-lucide-radar"
|
|
518
|
-
:
|
|
518
|
+
:label="t('board.frame.huntBugsTitle')"
|
|
519
519
|
@click.stop="huntBugs"
|
|
520
520
|
/>
|
|
521
521
|
</template>
|
|
@@ -530,7 +530,7 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
530
530
|
stays is what the canvas can't show at a glance. -->
|
|
531
531
|
<div
|
|
532
532
|
v-if="modules.length || prTasks"
|
|
533
|
-
class="flex items-center gap-2 text-
|
|
533
|
+
class="flex items-center gap-2 text-3xs uppercase tracking-wide text-dimmed"
|
|
534
534
|
>
|
|
535
535
|
<span v-if="modules.length">{{
|
|
536
536
|
t('board.frame.moduleCount', { count: modules.length }, modules.length)
|
|
@@ -560,15 +560,16 @@ const ITEM_ICON: Record<string, string> = {
|
|
|
560
560
|
|
|
561
561
|
<FrameSwimlanes v-if="hasTasks" :frame-id="block.id" :lane-body-height="laneBodyHeight" />
|
|
562
562
|
|
|
563
|
-
<
|
|
563
|
+
<UButton
|
|
564
|
+
color="neutral"
|
|
565
|
+
variant="ghost"
|
|
564
566
|
v-if="!hasTasks && access.canWriteBoard.value"
|
|
565
|
-
type="button"
|
|
566
567
|
data-testid="frame-add-task-empty"
|
|
567
|
-
class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-muted text-
|
|
568
|
+
class="absolute inset-4 flex items-center justify-center gap-1 rounded-lg border border-dashed border-muted text-2xs text-dimmed hover:border-app-500 hover:text-toned"
|
|
568
569
|
@click.stop="addTask"
|
|
569
570
|
>
|
|
570
571
|
<UIcon name="i-lucide-plus" class="h-3.5 w-3.5" /> {{ t('board.frame.addFirstTask') }}
|
|
571
|
-
</
|
|
572
|
+
</UButton>
|
|
572
573
|
</div>
|
|
573
574
|
</div>
|
|
574
575
|
|
|
@@ -16,8 +16,9 @@ const displayLabel = computed(() => props.label ?? t('board.decisionBadge.decisi
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<template>
|
|
19
|
-
<
|
|
20
|
-
|
|
19
|
+
<UButton
|
|
20
|
+
color="neutral"
|
|
21
|
+
variant="ghost"
|
|
21
22
|
class="board-pulse flex items-center gap-1 rounded-full bg-app-warning-500 px-2 py-0.5 text-xs font-semibold text-app-warning-50 dark:text-app-warning-950 shadow-lg transition hover:bg-app-warning-400"
|
|
22
23
|
@click.stop="$emit('open')"
|
|
23
24
|
>
|
|
@@ -26,5 +27,5 @@ const displayLabel = computed(() => props.label ?? t('board.decisionBadge.decisi
|
|
|
26
27
|
<span v-if="count && count > 1" class="rounded-full bg-app-warning-950/30 px-1">
|
|
27
28
|
{{ count }}
|
|
28
29
|
</span>
|
|
29
|
-
</
|
|
30
|
+
</UButton>
|
|
30
31
|
</template>
|
|
@@ -36,10 +36,10 @@ const selected = computed(() => ui.selectedBlockId === props.id)
|
|
|
36
36
|
>
|
|
37
37
|
<div class="flex items-center gap-1.5">
|
|
38
38
|
<UIcon name="i-lucide-layers" class="h-3.5 w-3.5 shrink-0 text-app-secondary-400" />
|
|
39
|
-
<span class="text-
|
|
39
|
+
<span class="text-3xs font-semibold uppercase tracking-wide text-app-secondary-300">{{
|
|
40
40
|
t('board.epic.label')
|
|
41
41
|
}}</span>
|
|
42
|
-
<span class="ms-auto text-
|
|
42
|
+
<span class="ms-auto text-3xs text-muted">{{ done }}/{{ total }}</span>
|
|
43
43
|
</div>
|
|
44
44
|
<div class="mt-1 truncate text-sm font-medium text-app-100" :title="block.title">
|
|
45
45
|
{{ block.title }}
|
|
@@ -50,10 +50,10 @@ const selected = computed(() => ui.selectedBlockId === props.id)
|
|
|
50
50
|
:style="{ width: total ? `${Math.round((done / total) * 100)}%` : '0%' }"
|
|
51
51
|
/>
|
|
52
52
|
</div>
|
|
53
|
-
<div v-if="active" class="mt-1 text-
|
|
53
|
+
<div v-if="active" class="mt-1 text-3xs text-muted">
|
|
54
54
|
{{ t('board.epic.activeCount', { count: active }) }}
|
|
55
55
|
</div>
|
|
56
|
-
<div v-else-if="total === 0" class="mt-1 text-
|
|
56
|
+
<div v-else-if="total === 0" class="mt-1 text-3xs text-dimmed">
|
|
57
57
|
{{ t('board.epic.noTasksYet') }}
|
|
58
58
|
</div>
|
|
59
59
|
</div>
|
|
@@ -67,8 +67,9 @@ const withheldNote = computed(() => {
|
|
|
67
67
|
is the one lane whose emptiness says nothing a reader needs (a new service has merged
|
|
68
68
|
nothing, which its three live lanes already show). -->
|
|
69
69
|
<div v-if="doneLane && doneLane.total > 0" class="rounded-lg bg-default/40">
|
|
70
|
-
<
|
|
71
|
-
|
|
70
|
+
<UButton
|
|
71
|
+
color="neutral"
|
|
72
|
+
variant="ghost"
|
|
72
73
|
class="nodrag flex w-full items-center gap-1.5 rounded-lg px-2 py-1.5 text-left hover:bg-elevated/40"
|
|
73
74
|
data-testid="done-lane-toggle"
|
|
74
75
|
:aria-expanded="!laneView.doneLaneCollapsed"
|
|
@@ -83,12 +84,12 @@ const withheldNote = computed(() => {
|
|
|
83
84
|
class="h-3.5 w-3.5 shrink-0"
|
|
84
85
|
:style="{ color: LANE_META.done.color }"
|
|
85
86
|
/>
|
|
86
|
-
<span class="text-
|
|
87
|
+
<span class="text-2xs font-semibold text-default">{{ t(LANE_META.done.labelKey) }}</span>
|
|
87
88
|
<!-- The TOTAL, not what the caps admitted: "this service has finished 312 tasks" is the
|
|
88
89
|
fact the lane carries, and counting only the visible cards would understate it by
|
|
89
90
|
two orders of magnitude. -->
|
|
90
91
|
<span
|
|
91
|
-
class="shrink-0 rounded px-1 text-
|
|
92
|
+
class="shrink-0 rounded-sm px-1 text-3xs font-semibold tabular-nums"
|
|
92
93
|
:style="{
|
|
93
94
|
backgroundColor: tint(LANE_META.done.color),
|
|
94
95
|
color: LANE_META.done.color,
|
|
@@ -96,10 +97,10 @@ const withheldNote = computed(() => {
|
|
|
96
97
|
data-testid="lane-count-done"
|
|
97
98
|
>{{ doneLane.total }}</span
|
|
98
99
|
>
|
|
99
|
-
<span v-if="withheldNote" class="ms-auto truncate text-
|
|
100
|
+
<span v-if="withheldNote" class="ms-auto truncate text-3xs text-dimmed">{{
|
|
100
101
|
withheldNote
|
|
101
102
|
}}</span>
|
|
102
|
-
</
|
|
103
|
+
</UButton>
|
|
103
104
|
|
|
104
105
|
<!-- The archive opens as a WIDE GRID: each group takes the strip's full width and wraps its
|
|
105
106
|
own cards across it, and the groups stack. Wrapping the GROUPS instead read correctly
|
|
@@ -116,10 +117,7 @@ const withheldNote = computed(() => {
|
|
|
116
117
|
>
|
|
117
118
|
<!-- A zero cap is a real setting ("count them, show none"), so the strip explains why it
|
|
118
119
|
has nothing in it rather than looking broken. -->
|
|
119
|
-
<p
|
|
120
|
-
v-if="doneSelection.shown.length === 0"
|
|
121
|
-
class="px-1 text-[10px] leading-snug text-app-600"
|
|
122
|
-
>
|
|
120
|
+
<p v-if="doneSelection.shown.length === 0" class="px-1 text-3xs leading-snug text-app-600">
|
|
123
121
|
{{ t('board.lanes.done.allWithheld') }}
|
|
124
122
|
</p>
|
|
125
123
|
<LaneGroup
|
|
@@ -82,17 +82,17 @@ function select() {
|
|
|
82
82
|
{{ statusLabel }}
|
|
83
83
|
</UBadge>
|
|
84
84
|
</div>
|
|
85
|
-
<div class="mt-1 text-
|
|
85
|
+
<div class="mt-1 text-3xs uppercase tracking-wide text-primary/70">
|
|
86
86
|
{{ t('initiative.card.kind') }}
|
|
87
87
|
</div>
|
|
88
88
|
<div v-if="progress" class="mt-2 space-y-1">
|
|
89
|
-
<div class="h-1.5 overflow-hidden rounded bg-elevated">
|
|
89
|
+
<div class="h-1.5 overflow-hidden rounded-sm bg-elevated">
|
|
90
90
|
<div
|
|
91
|
-
class="h-full rounded bg-primary"
|
|
91
|
+
class="h-full rounded-sm bg-primary"
|
|
92
92
|
:style="{ width: `${Math.round((progress.settled / progress.total) * 100)}%` }"
|
|
93
93
|
/>
|
|
94
94
|
</div>
|
|
95
|
-
<div class="text-
|
|
95
|
+
<div class="text-3xs text-muted">
|
|
96
96
|
{{ t('initiative.card.progress', { done: progress.settled, total: progress.total }) }}
|
|
97
97
|
</div>
|
|
98
98
|
</div>
|
|
@@ -4,6 +4,7 @@ import { MODULE_META, taskTypeMeta } from '~/utils/catalog'
|
|
|
4
4
|
import { LANE_GEOMETRY } from '~/utils/laneGeometry'
|
|
5
5
|
import type { LaneGroup, LaneGroupKey } from '~/utils/laneSort'
|
|
6
6
|
import { LANE_REASON_LABEL_KEYS, type LaneReason } from '~/utils/swimlanes'
|
|
7
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* One labelled run of cards inside a lane.
|
|
@@ -73,14 +74,11 @@ const icon = computed(() => {
|
|
|
73
74
|
<div :data-drop-zone="dropZone ?? undefined" class="space-y-1.5">
|
|
74
75
|
<!-- `none` grouping renders no header: one unlabelled group IS the flat lane, and a header
|
|
75
76
|
saying "all of them" would be a row of chrome carrying no information. -->
|
|
76
|
-
<
|
|
77
|
-
v-if="groupKey !== 'none'"
|
|
78
|
-
class="flex items-center gap-1 px-0.5 text-[10px] uppercase tracking-wide text-dimmed"
|
|
79
|
-
>
|
|
77
|
+
<SectionLabel v-if="groupKey !== 'none'" class="flex items-center gap-1 px-0.5">
|
|
80
78
|
<UIcon v-if="icon" :name="icon" class="h-3 w-3 shrink-0" />
|
|
81
79
|
<span class="truncate" :title="label">{{ label }}</span>
|
|
82
80
|
<span class="ms-auto shrink-0 tabular-nums">{{ group.entries.length }}</span>
|
|
83
|
-
</
|
|
81
|
+
</SectionLabel>
|
|
84
82
|
<div :class="layout === 'grid' ? 'flex flex-wrap items-start gap-2' : 'space-y-1.5'">
|
|
85
83
|
<LaneTask
|
|
86
84
|
v-for="entry in group.entries"
|
|
@@ -5,6 +5,7 @@ import { STATUS_META, MODULE_META, taskTypeMeta } from '~/utils/catalog'
|
|
|
5
5
|
import { composeRunOutcome, hasOutcomeToShow } from '~/utils/runOutcome'
|
|
6
6
|
import AgentFailureCard from '~/components/board/AgentFailureCard.vue'
|
|
7
7
|
import TaskPipelineMini from './TaskPipelineMini.vue'
|
|
8
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
8
9
|
|
|
9
10
|
const props = defineProps<{ taskId: string }>()
|
|
10
11
|
|
|
@@ -327,7 +328,7 @@ function selectTask() {
|
|
|
327
328
|
hover. Renders a built-in OR a deployment-registered custom type via `taskTypeMeta`. -->
|
|
328
329
|
<span
|
|
329
330
|
v-if="typeBadge"
|
|
330
|
-
class="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded"
|
|
331
|
+
class="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-sm"
|
|
331
332
|
:style="{ color: typeBadge.color, backgroundColor: tint(typeBadge.color) }"
|
|
332
333
|
:title="typeBadge.label"
|
|
333
334
|
:data-task-type-badge="task.taskType"
|
|
@@ -346,7 +347,7 @@ function selectTask() {
|
|
|
346
347
|
"
|
|
347
348
|
/>
|
|
348
349
|
<span
|
|
349
|
-
class="ms-auto truncate text-
|
|
350
|
+
class="ms-auto truncate text-3xs uppercase tracking-wide"
|
|
350
351
|
:class="
|
|
351
352
|
runFailed
|
|
352
353
|
? 'text-app-error-400'
|
|
@@ -360,15 +361,19 @@ function selectTask() {
|
|
|
360
361
|
{{ statusText }}
|
|
361
362
|
</span>
|
|
362
363
|
<!-- drag-to-connect handle: drag onto another task to make it depend on this one -->
|
|
363
|
-
<
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
364
|
+
<IconButton
|
|
365
|
+
color="neutral"
|
|
366
|
+
variant="ghost"
|
|
367
|
+
icon="i-lucide-spline"
|
|
368
|
+
class="nodrag shrink-0"
|
|
369
|
+
:label="t('board.task.dragToConnect')"
|
|
370
|
+
:ui="{
|
|
371
|
+
base: 'cursor-crosshair touch-none rounded-full p-0.5 text-dimmed hover:bg-elevated hover:text-app-warning-400 pointer-coarse:p-2.5',
|
|
372
|
+
leadingIcon: 'h-3 w-3 pointer-coarse:h-5 pointer-coarse:w-5',
|
|
373
|
+
}"
|
|
367
374
|
@pointerdown.stop="startConnect(task.id, $event)"
|
|
368
375
|
@click.stop
|
|
369
|
-
|
|
370
|
-
<UIcon name="i-lucide-spline" class="h-3 w-3 pointer-coarse:h-5 pointer-coarse:w-5" />
|
|
371
|
-
</button>
|
|
376
|
+
/>
|
|
372
377
|
</div>
|
|
373
378
|
|
|
374
379
|
<!-- title gets a full-width row so long titles wrap to two lines rather than
|
|
@@ -379,7 +384,7 @@ function selectTask() {
|
|
|
379
384
|
title is the one always-rendered part of the body that no control can occupy. -->
|
|
380
385
|
<div
|
|
381
386
|
data-testid="task-title"
|
|
382
|
-
class="mt-1 line-clamp-2 break-words text-
|
|
387
|
+
class="mt-1 line-clamp-2 break-words text-2xs font-semibold leading-snug text-app-100"
|
|
383
388
|
:title="task.title"
|
|
384
389
|
>
|
|
385
390
|
{{ task.title }}
|
|
@@ -415,7 +420,7 @@ function selectTask() {
|
|
|
415
420
|
<span
|
|
416
421
|
v-for="d in deps"
|
|
417
422
|
:key="d.id"
|
|
418
|
-
class="inline-flex items-center gap-0.5 rounded bg-elevated/80 px-1 py-0.5 text-
|
|
423
|
+
class="inline-flex items-center gap-0.5 rounded-sm bg-elevated/80 px-1 py-0.5 text-3xs"
|
|
419
424
|
:class="d.status === 'done' ? 'text-muted' : 'text-app-warning-300'"
|
|
420
425
|
:title="depLabel(d)"
|
|
421
426
|
>
|
|
@@ -431,7 +436,7 @@ function selectTask() {
|
|
|
431
436
|
<div class="nodrag mt-2 flex flex-wrap items-center gap-1">
|
|
432
437
|
<!-- a reviewer gate folding/re-reviewing in the background: a working indicator,
|
|
433
438
|
NOT a gate — the human is back on the board and summoned only if input is needed -->
|
|
434
|
-
<span v-if="reviewStage" class="inline-flex items-center gap-1 text-
|
|
439
|
+
<span v-if="reviewStage" class="inline-flex items-center gap-1 text-3xs text-primary">
|
|
435
440
|
<UIcon name="i-lucide-loader-circle" class="h-3 w-3 animate-spin" />
|
|
436
441
|
{{ reviewStageLabel }}
|
|
437
442
|
</span>
|
|
@@ -481,7 +486,7 @@ function selectTask() {
|
|
|
481
486
|
</UButton>
|
|
482
487
|
<span
|
|
483
488
|
v-if="runnable && defaultPipeline"
|
|
484
|
-
class="inline-flex items-center gap-0.5 text-
|
|
489
|
+
class="inline-flex items-center gap-0.5 text-3xs text-dimmed"
|
|
485
490
|
>
|
|
486
491
|
<UIcon name="i-lucide-workflow" class="h-2.5 w-2.5" />{{ defaultPipeline.name }}
|
|
487
492
|
</span>
|
|
@@ -539,7 +544,7 @@ function selectTask() {
|
|
|
539
544
|
<!-- A merged task is the one people come back to READ, so its result stays openable
|
|
540
545
|
rather than collapsing to a tick the moment it lands. -->
|
|
541
546
|
<template v-else-if="task.status === 'done'">
|
|
542
|
-
<span class="inline-flex items-center gap-1 text-
|
|
547
|
+
<span class="inline-flex items-center gap-1 text-3xs text-app-success-400">
|
|
543
548
|
<UIcon name="i-lucide-check-check" class="h-3 w-3" /> {{ t('board.task.implemented') }}
|
|
544
549
|
</span>
|
|
545
550
|
<UButton
|
|
@@ -565,7 +570,7 @@ function selectTask() {
|
|
|
565
570
|
class="mt-2 flex flex-wrap items-center gap-1 border-t border-default pt-2"
|
|
566
571
|
>
|
|
567
572
|
<span
|
|
568
|
-
class="inline-flex items-center gap-1 rounded bg-app-secondary-500/15 px-1.5 py-0.5 text-
|
|
573
|
+
class="inline-flex items-center gap-1 rounded-sm bg-app-secondary-500/15 px-1.5 py-0.5 text-3xs text-app-secondary-200"
|
|
569
574
|
:title="t('board.task.module', { name: task.moduleName })"
|
|
570
575
|
>
|
|
571
576
|
<UIcon :name="MODULE_META.icon" class="h-3 w-3" :style="{ color: MODULE_META.color }" />
|
|
@@ -46,9 +46,9 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
|
|
|
46
46
|
:style="{ borderColor: tint(meta.color, 20) }"
|
|
47
47
|
>
|
|
48
48
|
<UIcon :name="meta.icon" class="h-3.5 w-3.5 shrink-0" :style="{ color: meta.color }" />
|
|
49
|
-
<span class="truncate text-
|
|
49
|
+
<span class="truncate text-2xs font-semibold text-default">{{ t(meta.labelKey) }}</span>
|
|
50
50
|
<span
|
|
51
|
-
class="ms-auto shrink-0 rounded px-1 text-
|
|
51
|
+
class="ms-auto shrink-0 rounded-sm px-1 text-3xs font-semibold tabular-nums"
|
|
52
52
|
:style="{ backgroundColor: tint(meta.color), color: meta.color }"
|
|
53
53
|
:data-testid="`lane-count-${rendered.lane}`"
|
|
54
54
|
>{{ rendered.total }}</span
|
|
@@ -65,7 +65,7 @@ const isEmpty = computed(() => props.rendered.groups.every((g) => g.entries.leng
|
|
|
65
65
|
<!-- An empty lane SAYS it is empty. Left blank, "nothing needs you" and "the lane failed
|
|
66
66
|
to render" look identical, and the first is worth stating: it is the answer a reader
|
|
67
67
|
scanning the needs-you column is hoping for. -->
|
|
68
|
-
<p v-if="isEmpty" class="px-1 pt-2 text-
|
|
68
|
+
<p v-if="isEmpty" class="px-1 pt-2 text-3xs leading-snug text-app-600">
|
|
69
69
|
{{ t(meta.emptyKey) }}
|
|
70
70
|
</p>
|
|
71
71
|
<LaneGroup
|