@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
|
@@ -37,10 +37,10 @@ function stepLabel(key: string | undefined): string {
|
|
|
37
37
|
|
|
38
38
|
<template>
|
|
39
39
|
<div class="space-y-2" data-testid="env-setup-stepper">
|
|
40
|
-
<p v-if="total" class="text-
|
|
40
|
+
<p v-if="total" class="text-2xs font-medium text-muted" data-testid="env-setup-progress">
|
|
41
41
|
{{ t('environmentWizard.progress', { index: index + 1, total }) }}
|
|
42
42
|
</p>
|
|
43
|
-
<ol class="flex items-center gap-2 text-
|
|
43
|
+
<ol class="flex items-center gap-2 text-2xs">
|
|
44
44
|
<li
|
|
45
45
|
v-for="(step, i) in steps"
|
|
46
46
|
:key="step.entry"
|
|
@@ -48,7 +48,7 @@ function stepLabel(key: string | undefined): string {
|
|
|
48
48
|
:data-testid="`env-setup-crumb-${step.entry}`"
|
|
49
49
|
>
|
|
50
50
|
<span
|
|
51
|
-
class="flex h-5 w-5 items-center justify-center rounded-full text-
|
|
51
|
+
class="flex h-5 w-5 items-center justify-center rounded-full text-3xs font-semibold"
|
|
52
52
|
:class="{
|
|
53
53
|
'bg-primary text-inverted': i === index,
|
|
54
54
|
'bg-app-success-600/70 text-highlighted': i < index,
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
readStatusNote,
|
|
10
10
|
showsProviderFailure,
|
|
11
11
|
} from '~/components/environments/EnvironmentStatusPanel.logic'
|
|
12
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
12
13
|
|
|
13
14
|
const props = defineProps<{
|
|
14
15
|
environment: RunEnvironment | null
|
|
@@ -106,11 +107,11 @@ const envInTransition = computed(
|
|
|
106
107
|
|
|
107
108
|
<template>
|
|
108
109
|
<section class="rounded-lg border border-default bg-default/60 p-3">
|
|
109
|
-
<h3 class="mb-2
|
|
110
|
+
<SectionLabel as="h3" class="mb-2">
|
|
110
111
|
{{ t('environments.title') }}
|
|
111
|
-
</
|
|
112
|
+
</SectionLabel>
|
|
112
113
|
<div v-if="environment" class="space-y-2">
|
|
113
|
-
<div class="flex items-center gap-2 text-
|
|
114
|
+
<div class="flex items-center gap-2 text-sm">
|
|
114
115
|
<UIcon
|
|
115
116
|
:name="ENV_STATUS_META[environment.status].icon"
|
|
116
117
|
class="h-3.5 w-3.5"
|
|
@@ -123,27 +124,28 @@ const envInTransition = computed(
|
|
|
123
124
|
ENV_STATUS_META[environment.status].label
|
|
124
125
|
}}</span>
|
|
125
126
|
</div>
|
|
126
|
-
<
|
|
127
|
+
<ULink
|
|
128
|
+
raw
|
|
127
129
|
v-if="environment.url"
|
|
128
|
-
:
|
|
130
|
+
:to="environment.url"
|
|
129
131
|
target="_blank"
|
|
130
132
|
rel="noopener"
|
|
131
|
-
class="inline-flex items-center gap-1.5 break-all text-
|
|
133
|
+
class="inline-flex items-center gap-1.5 break-all text-sm text-app-info-300 hover:underline"
|
|
132
134
|
>
|
|
133
135
|
<UIcon name="i-lucide-external-link" class="h-3.5 w-3.5 shrink-0" />
|
|
134
136
|
{{ environment.url }}
|
|
135
|
-
</
|
|
136
|
-
<p v-if="environment.expiresAt" class="text-
|
|
137
|
+
</ULink>
|
|
138
|
+
<p v-if="environment.expiresAt" class="text-2xs text-dimmed">
|
|
137
139
|
{{ t('environments.expires', { date: d(new Date(environment.expiresAt), 'long') }) }}
|
|
138
140
|
</p>
|
|
139
141
|
<!-- The resolved provision type + engine recorded at provision time, so a run states
|
|
140
142
|
exactly what was provisioned and how (the what/where ÷ how split). -->
|
|
141
143
|
<dl v-if="provisionTypeLabel || engineLabel" class="flex flex-wrap gap-x-4 gap-y-0.5">
|
|
142
|
-
<div v-if="provisionTypeLabel" class="flex items-center gap-1 text-
|
|
144
|
+
<div v-if="provisionTypeLabel" class="flex items-center gap-1 text-2xs">
|
|
143
145
|
<dt class="text-dimmed">{{ t('environments.provisionTypeLabel') }}</dt>
|
|
144
146
|
<dd class="text-toned">{{ provisionTypeLabel }}</dd>
|
|
145
147
|
</div>
|
|
146
|
-
<div v-if="engineLabel" class="flex items-center gap-1 text-
|
|
148
|
+
<div v-if="engineLabel" class="flex items-center gap-1 text-2xs">
|
|
147
149
|
<dt class="text-dimmed">{{ t('environments.engineLabel') }}</dt>
|
|
148
150
|
<dd class="text-toned">{{ engineLabel }}</dd>
|
|
149
151
|
</div>
|
|
@@ -151,7 +153,7 @@ const envInTransition = computed(
|
|
|
151
153
|
<!-- The verbatim provider error when the environment failed/expired. -->
|
|
152
154
|
<pre
|
|
153
155
|
v-if="failureShown"
|
|
154
|
-
class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded border border-app-error-900/60 bg-app-error-950/40 p-1.5 text-
|
|
156
|
+
class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap rounded-sm border border-app-error-900/60 bg-app-error-950/40 p-1.5 text-2xs text-app-error-200/90"
|
|
155
157
|
>{{ environment.lastError }}</pre>
|
|
156
158
|
<!-- What the provider says it is still waiting on. Muted rather than alarming: an
|
|
157
159
|
environment mid-rollout is healthy, and styling this like the error above would report
|
|
@@ -159,12 +161,12 @@ const envInTransition = computed(
|
|
|
159
161
|
prose. -->
|
|
160
162
|
<p
|
|
161
163
|
v-if="statusNote"
|
|
162
|
-
class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap break-words text-
|
|
164
|
+
class="mt-1 max-h-32 overflow-auto whitespace-pre-wrap break-words text-2xs text-muted"
|
|
163
165
|
>
|
|
164
166
|
{{ t('environments.statusNote', { note: statusNote }) }}
|
|
165
167
|
</p>
|
|
166
168
|
</div>
|
|
167
|
-
<p v-else class="text-
|
|
169
|
+
<p v-else class="text-xs text-dimmed">
|
|
168
170
|
{{ degradedReason ?? t('environments.empty') }}
|
|
169
171
|
</p>
|
|
170
172
|
</section>
|
|
@@ -51,21 +51,21 @@ const PREFLIGHT_COLOR: Record<'pass' | 'warn' | 'fail', 'success' | 'warning' |
|
|
|
51
51
|
|
|
52
52
|
<p
|
|
53
53
|
v-if="!store.recipe.prerequisites?.length"
|
|
54
|
-
class="text-
|
|
54
|
+
class="text-xs text-dimmed"
|
|
55
55
|
data-testid="env-setup-preflight-none"
|
|
56
56
|
>
|
|
57
57
|
{{ t('environmentWizard.preflight.none') }}
|
|
58
58
|
</p>
|
|
59
59
|
<p
|
|
60
60
|
v-else-if="preflightsUnavailable"
|
|
61
|
-
class="text-
|
|
61
|
+
class="text-xs text-app-warning-300/80"
|
|
62
62
|
data-testid="env-setup-preflight-unavailable"
|
|
63
63
|
>
|
|
64
64
|
{{ t('environmentWizard.preflight.unavailable') }}
|
|
65
65
|
</p>
|
|
66
66
|
<p
|
|
67
67
|
v-if="store.preflightError"
|
|
68
|
-
class="text-
|
|
68
|
+
class="text-xs text-app-error-300/80"
|
|
69
69
|
data-testid="env-setup-preflight-error"
|
|
70
70
|
>
|
|
71
71
|
{{ store.preflightError }}
|
|
@@ -79,21 +79,21 @@ const PREFLIGHT_COLOR: Record<'pass' | 'warn' | 'fail', 'success' | 'warning' |
|
|
|
79
79
|
<li
|
|
80
80
|
v-for="r in store.preflightResults"
|
|
81
81
|
:key="r.title"
|
|
82
|
-
class="rounded border border-default bg-default/40 p-2"
|
|
82
|
+
class="rounded-sm border border-default bg-default/40 p-2"
|
|
83
83
|
>
|
|
84
84
|
<div class="flex items-center gap-2">
|
|
85
85
|
<UBadge :color="PREFLIGHT_COLOR[r.status]" variant="subtle" size="sm">
|
|
86
86
|
{{ r.status }}
|
|
87
87
|
</UBadge>
|
|
88
|
-
<span class="text-
|
|
89
|
-
<span v-if="!r.required" class="ms-auto text-
|
|
88
|
+
<span class="text-xs text-default">{{ r.title }}</span>
|
|
89
|
+
<span v-if="!r.required" class="ms-auto text-3xs text-dimmed">
|
|
90
90
|
{{ t('environmentWizard.preflight.optional') }}
|
|
91
91
|
</span>
|
|
92
92
|
</div>
|
|
93
|
-
<p v-if="r.detail" class="mt-1 text-
|
|
93
|
+
<p v-if="r.detail" class="mt-1 text-2xs text-muted">{{ r.detail }}</p>
|
|
94
94
|
<pre
|
|
95
95
|
v-if="r.status !== 'pass' && r.remediation"
|
|
96
|
-
class="mt-1 max-h-40 overflow-auto whitespace-pre-wrap rounded border border-app-warning-900/40 bg-app-warning-950/20 p-1.5 text-
|
|
96
|
+
class="mt-1 max-h-40 overflow-auto whitespace-pre-wrap rounded-sm border border-app-warning-900/40 bg-app-warning-950/20 p-1.5 text-2xs text-app-warning-200/90"
|
|
97
97
|
>{{ r.remediation }}</pre>
|
|
98
98
|
</li>
|
|
99
99
|
</ul>
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
} from '@cat-factory/contracts'
|
|
15
15
|
import JourneyStepNav from '~/components/environments/steps/JourneyStepNav.vue'
|
|
16
16
|
import { useEnvironmentWizardTarget } from '~/modular/journeys/environmentSetup.frame'
|
|
17
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
17
18
|
|
|
18
19
|
const props = defineProps<{
|
|
19
20
|
input: { frameId: string | null }
|
|
@@ -114,7 +115,7 @@ const canLeaveReview = computed(
|
|
|
114
115
|
<div class="flex items-center justify-between gap-2">
|
|
115
116
|
<div class="min-w-0">
|
|
116
117
|
<p class="text-sm font-medium text-default">{{ store.targetFrame?.title }}</p>
|
|
117
|
-
<p class="text-
|
|
118
|
+
<p class="text-2xs text-dimmed">{{ t('environmentWizard.review.detectHint') }}</p>
|
|
118
119
|
</div>
|
|
119
120
|
<UButton
|
|
120
121
|
size="xs"
|
|
@@ -130,12 +131,12 @@ const canLeaveReview = computed(
|
|
|
130
131
|
</UButton>
|
|
131
132
|
</div>
|
|
132
133
|
|
|
133
|
-
<p v-if="!store.hasRepo" class="text-
|
|
134
|
+
<p v-if="!store.hasRepo" class="text-xs text-app-warning-300/80">
|
|
134
135
|
{{ t('environmentWizard.review.noRepo') }}
|
|
135
136
|
</p>
|
|
136
137
|
<p
|
|
137
138
|
v-else-if="store.detectError"
|
|
138
|
-
class="text-
|
|
139
|
+
class="text-xs text-app-error-300/80"
|
|
139
140
|
data-testid="env-setup-detect-error"
|
|
140
141
|
>
|
|
141
142
|
{{ t('environmentWizard.review.detectError') }}
|
|
@@ -149,7 +150,7 @@ const canLeaveReview = computed(
|
|
|
149
150
|
>
|
|
150
151
|
<p
|
|
151
152
|
v-if="repoCliHint"
|
|
152
|
-
class="mb-2 flex items-start gap-1.5 text-
|
|
153
|
+
class="mb-2 flex items-start gap-1.5 text-2xs text-primary"
|
|
153
154
|
data-testid="env-setup-cli-nudge"
|
|
154
155
|
>
|
|
155
156
|
<UIcon name="i-lucide-lightbulb" class="mt-0.5 h-3.5 w-3.5 shrink-0" />
|
|
@@ -157,10 +158,10 @@ const canLeaveReview = computed(
|
|
|
157
158
|
</p>
|
|
158
159
|
<div class="flex items-center justify-between gap-2">
|
|
159
160
|
<div class="min-w-0">
|
|
160
|
-
<p class="text-
|
|
161
|
+
<p class="text-xs font-medium text-toned">
|
|
161
162
|
{{ t('environmentWizard.analysis.title') }}
|
|
162
163
|
</p>
|
|
163
|
-
<p class="text-
|
|
164
|
+
<p class="text-2xs text-dimmed">{{ t('environmentWizard.analysis.hint') }}</p>
|
|
164
165
|
</div>
|
|
165
166
|
<UButton
|
|
166
167
|
size="xs"
|
|
@@ -177,14 +178,14 @@ const canLeaveReview = computed(
|
|
|
177
178
|
</div>
|
|
178
179
|
<p
|
|
179
180
|
v-if="!store.canAnalyze"
|
|
180
|
-
class="mt-2 text-
|
|
181
|
+
class="mt-2 text-2xs text-dimmed"
|
|
181
182
|
data-testid="env-setup-analysis-unavailable"
|
|
182
183
|
>
|
|
183
184
|
{{ t('environmentWizard.analysis.unavailable') }}
|
|
184
185
|
</p>
|
|
185
186
|
<p
|
|
186
187
|
v-else-if="store.analysisStatus === 'failed'"
|
|
187
|
-
class="mt-2 text-
|
|
188
|
+
class="mt-2 text-2xs text-app-error-300/80"
|
|
188
189
|
>
|
|
189
190
|
{{ t('environmentWizard.analysis.failed') }}
|
|
190
191
|
</p>
|
|
@@ -193,7 +194,7 @@ const canLeaveReview = computed(
|
|
|
193
194
|
class="mt-2 space-y-2"
|
|
194
195
|
data-testid="env-setup-analysis-ready"
|
|
195
196
|
>
|
|
196
|
-
<p v-if="store.merged?.summary" class="text-
|
|
197
|
+
<p v-if="store.merged?.summary" class="text-2xs leading-snug text-muted">
|
|
197
198
|
{{ store.merged.summary }}
|
|
198
199
|
</p>
|
|
199
200
|
<UButton
|
|
@@ -211,9 +212,9 @@ const canLeaveReview = computed(
|
|
|
211
212
|
|
|
212
213
|
<!-- per-field provenance -->
|
|
213
214
|
<div v-if="store.merged?.fields.length" class="space-y-1.5">
|
|
214
|
-
<
|
|
215
|
+
<SectionLabel as="p">
|
|
215
216
|
{{ t('environmentWizard.review.provenanceTitle') }}
|
|
216
|
-
</
|
|
217
|
+
</SectionLabel>
|
|
217
218
|
<div class="flex flex-wrap gap-1.5">
|
|
218
219
|
<UBadge
|
|
219
220
|
v-for="f in store.merged.fields"
|
|
@@ -261,9 +262,9 @@ const canLeaveReview = computed(
|
|
|
261
262
|
|
|
262
263
|
<!-- compose file layering -->
|
|
263
264
|
<div v-if="composeFileCandidates.length" class="space-y-1.5">
|
|
264
|
-
<
|
|
265
|
+
<SectionLabel as="p">
|
|
265
266
|
{{ t('environmentWizard.review.composeFiles') }}
|
|
266
|
-
</
|
|
267
|
+
</SectionLabel>
|
|
267
268
|
<div class="flex flex-wrap gap-1.5">
|
|
268
269
|
<UButton
|
|
269
270
|
v-for="c in composeFileCandidates"
|
|
@@ -275,16 +276,16 @@ const canLeaveReview = computed(
|
|
|
275
276
|
:data-testid="`env-setup-file-${c.name}`"
|
|
276
277
|
@click="store.toggleComposeFile(c.path)"
|
|
277
278
|
>
|
|
278
|
-
{{ c.name }}<span v-if="c.os" class="ms-1 text-
|
|
279
|
+
{{ c.name }}<span v-if="c.os" class="ms-1 text-3xs opacity-70">{{ c.os }}</span>
|
|
279
280
|
</UButton>
|
|
280
281
|
</div>
|
|
281
282
|
</div>
|
|
282
283
|
|
|
283
284
|
<!-- compose profiles -->
|
|
284
285
|
<div v-if="profileCandidates.length" class="space-y-1.5">
|
|
285
|
-
<
|
|
286
|
+
<SectionLabel as="p">
|
|
286
287
|
{{ t('environmentWizard.review.profiles') }}
|
|
287
|
-
</
|
|
288
|
+
</SectionLabel>
|
|
288
289
|
<div class="flex flex-wrap gap-1.5">
|
|
289
290
|
<UButton
|
|
290
291
|
v-for="c in profileCandidates"
|
|
@@ -303,16 +304,16 @@ const canLeaveReview = computed(
|
|
|
303
304
|
|
|
304
305
|
<!-- seed dumps -->
|
|
305
306
|
<div v-if="seedDumpCandidates.length" class="space-y-1.5">
|
|
306
|
-
<
|
|
307
|
+
<SectionLabel as="p">
|
|
307
308
|
{{ t('environmentWizard.review.seedDumps') }}
|
|
308
|
-
</
|
|
309
|
+
</SectionLabel>
|
|
309
310
|
<div class="space-y-1">
|
|
310
311
|
<div
|
|
311
312
|
v-for="c in seedDumpCandidates"
|
|
312
313
|
:key="c.path"
|
|
313
|
-
class="flex items-center justify-between gap-2 rounded border border-default bg-default/40 px-2 py-1"
|
|
314
|
+
class="flex items-center justify-between gap-2 rounded-sm border border-default bg-default/40 px-2 py-1"
|
|
314
315
|
>
|
|
315
|
-
<span class="truncate text-
|
|
316
|
+
<span class="truncate text-2xs text-toned">{{ c.path }}</span>
|
|
316
317
|
<UButton
|
|
317
318
|
size="xs"
|
|
318
319
|
:color="seedAdded(c.path) ? 'success' : 'neutral'"
|
|
@@ -348,12 +349,12 @@ const canLeaveReview = computed(
|
|
|
348
349
|
<UTextarea
|
|
349
350
|
v-model="rawText"
|
|
350
351
|
:rows="10"
|
|
351
|
-
class="w-full font-mono text-
|
|
352
|
+
class="w-full font-mono text-2xs"
|
|
352
353
|
data-testid="env-setup-raw-text"
|
|
353
354
|
/>
|
|
354
355
|
<p
|
|
355
356
|
v-if="rawError"
|
|
356
|
-
class="text-
|
|
357
|
+
class="text-2xs text-app-error-300/80"
|
|
357
358
|
data-testid="env-setup-raw-error"
|
|
358
359
|
>
|
|
359
360
|
{{ rawError }}
|
|
@@ -31,7 +31,7 @@ useEnvironmentWizardTarget(() => props.input.frameId)
|
|
|
31
31
|
<UInput v-model="store.handlerLabel" class="w-full" data-testid="env-setup-handler-label" />
|
|
32
32
|
</UFormField>
|
|
33
33
|
|
|
34
|
-
<div class="rounded-md border border-default bg-default/40 p-3 text-
|
|
34
|
+
<div class="rounded-md border border-default bg-default/40 p-3 text-xs text-toned">
|
|
35
35
|
<p>
|
|
36
36
|
{{
|
|
37
37
|
t('environmentWizard.save.summary', {
|
|
@@ -44,7 +44,7 @@ useEnvironmentWizardTarget(() => props.input.frameId)
|
|
|
44
44
|
|
|
45
45
|
<p
|
|
46
46
|
v-if="store.saveError"
|
|
47
|
-
class="text-
|
|
47
|
+
class="text-xs text-app-error-300/80"
|
|
48
48
|
data-testid="env-setup-save-error"
|
|
49
49
|
>
|
|
50
50
|
{{ store.saveError }}
|
|
@@ -66,7 +66,7 @@ useEnvironmentWizardTarget(() => props.input.frameId)
|
|
|
66
66
|
<!-- saved: confirmation + optional trial provision -->
|
|
67
67
|
<template v-else>
|
|
68
68
|
<div
|
|
69
|
-
class="flex items-center gap-2 rounded-md border border-app-success-800/50 bg-app-success-950/30 p-2 text-
|
|
69
|
+
class="flex items-center gap-2 rounded-md border border-app-success-800/50 bg-app-success-950/30 p-2 text-xs text-app-success-200"
|
|
70
70
|
data-testid="env-setup-saved"
|
|
71
71
|
>
|
|
72
72
|
<UIcon name="i-lucide-check-circle" class="h-4 w-4" />
|
|
@@ -74,7 +74,7 @@ useEnvironmentWizardTarget(() => props.input.frameId)
|
|
|
74
74
|
</div>
|
|
75
75
|
|
|
76
76
|
<div class="flex items-center justify-between gap-2">
|
|
77
|
-
<p class="text-
|
|
77
|
+
<p class="text-2xs text-dimmed">{{ t('environmentWizard.trial.hint') }}</p>
|
|
78
78
|
<UButton
|
|
79
79
|
size="xs"
|
|
80
80
|
variant="soft"
|
|
@@ -88,7 +88,7 @@ useEnvironmentWizardTarget(() => props.input.frameId)
|
|
|
88
88
|
{{ t('environmentWizard.trial.run') }}
|
|
89
89
|
</UButton>
|
|
90
90
|
</div>
|
|
91
|
-
<p v-if="store.trialError" class="text-
|
|
91
|
+
<p v-if="store.trialError" class="text-2xs text-app-error-300/80">
|
|
92
92
|
{{ store.trialError }}
|
|
93
93
|
</p>
|
|
94
94
|
<ProvisioningLogsDrawer v-if="store.trialStarted" subsystem="environment" />
|
|
@@ -6,6 +6,7 @@ import { pipelineAllowedForManualStart } from '~/utils/pipeline'
|
|
|
6
6
|
import PipelineProgress from '~/components/pipeline/PipelineProgress.vue'
|
|
7
7
|
import IconButton from '~/components/common/IconButton.vue'
|
|
8
8
|
import { useInitiativePlanning } from '~/composables/useInitiativePlanning'
|
|
9
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
9
10
|
|
|
10
11
|
const board = useBoardStore()
|
|
11
12
|
const pipelines = usePipelinesStore()
|
|
@@ -203,9 +204,9 @@ function openApprovalFor(approvalId: string) {
|
|
|
203
204
|
>
|
|
204
205
|
<div class="mb-4 flex items-center gap-2">
|
|
205
206
|
<UIcon name="i-lucide-workflow" class="h-4 w-4 text-dimmed" />
|
|
206
|
-
<
|
|
207
|
+
<SectionLabel as="h2">
|
|
207
208
|
{{ instance ? instance.pipelineName : t('focus.noPipelineRunning') }}
|
|
208
|
-
</
|
|
209
|
+
</SectionLabel>
|
|
209
210
|
</div>
|
|
210
211
|
|
|
211
212
|
<PipelineProgress
|
|
@@ -226,30 +227,30 @@ function openApprovalFor(approvalId: string) {
|
|
|
226
227
|
<!-- side: details -->
|
|
227
228
|
<aside class="space-y-4 overflow-auto rounded-2xl border border-default bg-default/60 p-5">
|
|
228
229
|
<div>
|
|
229
|
-
<
|
|
230
|
+
<SectionLabel class="mb-1">
|
|
230
231
|
{{ t('focus.description') }}
|
|
231
|
-
</
|
|
232
|
+
</SectionLabel>
|
|
232
233
|
<p class="text-sm text-toned">{{ block.description }}</p>
|
|
233
234
|
</div>
|
|
234
235
|
<div v-if="instance">
|
|
235
|
-
<
|
|
236
|
+
<SectionLabel class="mb-1">
|
|
236
237
|
{{ t('focus.overallProgress') }}
|
|
237
|
-
</
|
|
238
|
+
</SectionLabel>
|
|
238
239
|
<UProgress :model-value="Math.round(block.progress * 100)" />
|
|
239
|
-
<div class="mt-1 text-
|
|
240
|
+
<div class="mt-1 text-2xs text-muted">
|
|
240
241
|
{{ n(block.progress, 'percent') }}
|
|
241
242
|
</div>
|
|
242
243
|
</div>
|
|
243
244
|
<div>
|
|
244
|
-
<
|
|
245
|
+
<SectionLabel class="mb-1">
|
|
245
246
|
{{ t('focus.dependencies') }}
|
|
246
|
-
</
|
|
247
|
+
</SectionLabel>
|
|
247
248
|
<div v-if="deps.length" class="flex flex-wrap gap-1">
|
|
248
249
|
<UBadge v-for="d in deps" :key="d.id" color="neutral" variant="subtle" size="sm">
|
|
249
250
|
{{ d.title }}
|
|
250
251
|
</UBadge>
|
|
251
252
|
</div>
|
|
252
|
-
<div v-else class="text-
|
|
253
|
+
<div v-else class="text-2xs text-dimmed">{{ t('focus.noDependencies') }}</div>
|
|
253
254
|
</div>
|
|
254
255
|
</aside>
|
|
255
256
|
</div>
|
|
@@ -162,7 +162,7 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
162
162
|
>
|
|
163
163
|
<UIcon :name="FOLLOW_UP_COMPANION_META.icon" class="h-8 w-8 opacity-40" />
|
|
164
164
|
<p class="text-sm">{{ t('followUp.empty.title') }}</p>
|
|
165
|
-
<p class="max-w-sm text-
|
|
165
|
+
<p class="max-w-sm text-2xs text-dimmed">
|
|
166
166
|
{{ t('followUp.empty.hint') }}
|
|
167
167
|
</p>
|
|
168
168
|
</div>
|
|
@@ -170,7 +170,7 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
170
170
|
<div v-else class="space-y-3">
|
|
171
171
|
<p
|
|
172
172
|
v-if="followUps.error"
|
|
173
|
-
class="rounded-md bg-app-error-500/10 px-3 py-2 text-
|
|
173
|
+
class="rounded-md bg-app-error-500/10 px-3 py-2 text-xs text-app-error-300"
|
|
174
174
|
>
|
|
175
175
|
{{ followUps.error }}
|
|
176
176
|
</p>
|
|
@@ -189,31 +189,32 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
189
189
|
/>
|
|
190
190
|
<div class="min-w-0 flex-1">
|
|
191
191
|
<div class="flex items-center gap-2">
|
|
192
|
-
<h3 class="min-w-0 flex-1 truncate text-
|
|
192
|
+
<h3 class="min-w-0 flex-1 truncate text-sm font-medium text-app-100">
|
|
193
193
|
{{ item.title }}
|
|
194
194
|
</h3>
|
|
195
195
|
<UBadge :color="STATUS_META[item.status].badge" variant="subtle" size="sm">
|
|
196
196
|
{{ t(STATUS_LABEL_KEYS[item.status]) }}
|
|
197
197
|
</UBadge>
|
|
198
198
|
</div>
|
|
199
|
-
<p v-if="item.detail" class="mt-1 whitespace-pre-wrap text-
|
|
199
|
+
<p v-if="item.detail" class="mt-1 whitespace-pre-wrap text-xs text-toned">
|
|
200
200
|
{{ item.detail }}
|
|
201
201
|
</p>
|
|
202
|
-
<p v-if="item.suggestedAction" class="mt-1 text-
|
|
202
|
+
<p v-if="item.suggestedAction" class="mt-1 text-2xs text-muted">
|
|
203
203
|
<span class="text-dimmed">{{ t('followUp.suggested') }}</span>
|
|
204
204
|
{{ item.suggestedAction }}
|
|
205
205
|
</p>
|
|
206
|
-
<p v-if="item.status === 'filed' && item.ticketUrl" class="mt-1 text-
|
|
207
|
-
<
|
|
208
|
-
|
|
206
|
+
<p v-if="item.status === 'filed' && item.ticketUrl" class="mt-1 text-2xs">
|
|
207
|
+
<ULink
|
|
208
|
+
raw
|
|
209
|
+
:to="item.ticketUrl"
|
|
209
210
|
target="_blank"
|
|
210
211
|
rel="noopener"
|
|
211
212
|
class="text-app-success-300 hover:underline"
|
|
212
213
|
>
|
|
213
214
|
{{ item.ticketExternalId ?? t('followUp.viewIssue') }}
|
|
214
|
-
</
|
|
215
|
+
</ULink>
|
|
215
216
|
</p>
|
|
216
|
-
<p v-if="hasRecordedAnswer(item)" class="mt-1 text-
|
|
217
|
+
<p v-if="hasRecordedAnswer(item)" class="mt-1 text-2xs text-toned">
|
|
217
218
|
<span class="text-dimmed">
|
|
218
219
|
{{
|
|
219
220
|
item.status === 'closed' ? t('followUp.yourRuling') : t('followUp.yourAnswer')
|
|
@@ -223,7 +224,7 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
223
224
|
</p>
|
|
224
225
|
<!-- A decision that was made and then thrown away when the budget ran out. It must
|
|
225
226
|
not read like one the Coder acted on. -->
|
|
226
|
-
<p v-if="item.sendBackDropped" class="mt-1 text-
|
|
227
|
+
<p v-if="item.sendBackDropped" class="mt-1 text-2xs text-app-warning-300">
|
|
227
228
|
{{ t('followUp.sendBackDropped') }}
|
|
228
229
|
</p>
|
|
229
230
|
|
|
@@ -231,11 +232,13 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
231
232
|
<div v-if="item.status === 'pending'" class="mt-2.5">
|
|
232
233
|
<!-- A question: answer it -->
|
|
233
234
|
<div v-if="item.kind === 'question'" class="space-y-2">
|
|
234
|
-
<
|
|
235
|
+
<UTextarea
|
|
235
236
|
v-model="drafts[item.id]"
|
|
236
|
-
rows="2"
|
|
237
|
+
:rows="2"
|
|
237
238
|
:placeholder="t('followUp.answerPlaceholder')"
|
|
238
|
-
|
|
239
|
+
size="xs"
|
|
240
|
+
class="w-full"
|
|
241
|
+
:ui="{ base: 'resize-y' }"
|
|
239
242
|
/>
|
|
240
243
|
<!-- Wraps, like the follow-up row below: three buttons whose labels are two
|
|
241
244
|
words each in English are one long line in most of the other locales, and
|
|
@@ -323,7 +326,7 @@ function hasRecordedAnswer(item: FollowUpItem): boolean {
|
|
|
323
326
|
</div>
|
|
324
327
|
|
|
325
328
|
<footer
|
|
326
|
-
class="flex items-center justify-between border-t border-default px-5 py-2.5 text-
|
|
329
|
+
class="flex items-center justify-between border-t border-default px-5 py-2.5 text-2xs text-muted"
|
|
327
330
|
>
|
|
328
331
|
<span>
|
|
329
332
|
{{
|