@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
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
// The one section "eyebrow": the small uppercase label that titles a group inside a panel, a
|
|
3
|
+
// result window, an inspector section or a dropdown (issue #2248).
|
|
4
|
+
//
|
|
5
|
+
// The recipe:
|
|
6
|
+
//
|
|
7
|
+
// text-2xs font-semibold uppercase tracking-wide text-muted
|
|
8
|
+
//
|
|
9
|
+
// Those five are the whole component and are NOT overridable. A caller that wants a different
|
|
10
|
+
// size or colour wants a different thing, not a variant of this one.
|
|
11
|
+
//
|
|
12
|
+
// The colour is `text-muted`, not `text-dimmed`, for contrast: at this size `text-dimmed` is 2.63:1
|
|
13
|
+
// on a light surface, under WCAG AA's 4.5:1 and under the 3:1 large-text floor. `text-muted` is
|
|
14
|
+
// 4.76:1. Do not "correct" it to the fainter token.
|
|
15
|
+
//
|
|
16
|
+
// A label that merely SHARES the uppercase styling is not this component: a pill or chip carrying
|
|
17
|
+
// a fill and a radius, an accent-coloured label signalling state or category, or a metadata row
|
|
18
|
+
// (`board/nodes/BlockNode.vue`'s composition line) that states counts rather than titling the
|
|
19
|
+
// block after it. Nor is a caption INSIDE a control: a switcher trigger's "Language" line above its
|
|
20
|
+
// value, a slider's end labels. A caption names part of the control and titles nothing after it.
|
|
21
|
+
// Those keep their own classes on a named step.
|
|
22
|
+
//
|
|
23
|
+
// What a caller DOES control:
|
|
24
|
+
// - `as`, the element. The default `div` suits a label that titles a region without being a
|
|
25
|
+
// document heading; pass `h3` / `h4` when the section is a real heading, `label` with an `:id`
|
|
26
|
+
// when it names a field. A collapsing section is a `UButton` around `as="span"`: the button
|
|
27
|
+
// owns the focus ring and the disabled state, which a raw `as="button"` would not have.
|
|
28
|
+
// - Layout, through the ordinary `class` attribute (`mb-2`, `px-2 pt-2`), which Vue merges onto
|
|
29
|
+
// the root. Spacing is the caller's business because it belongs to the surrounding block.
|
|
30
|
+
// - Every other attribute and listener, which fall through to the root element.
|
|
31
|
+
withDefaults(defineProps<{ as?: string }>(), { as: 'div' })
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<component :is="as" class="text-2xs font-semibold uppercase tracking-wide text-muted">
|
|
36
|
+
<slot />
|
|
37
|
+
</component>
|
|
38
|
+
</template>
|
|
@@ -12,6 +12,7 @@ import CopyButton from '~/components/common/CopyButton.vue'
|
|
|
12
12
|
import MarkdownProse from '~/components/common/MarkdownProse.vue'
|
|
13
13
|
import ResultWindowShell from '~/components/panels/ResultWindowShell.vue'
|
|
14
14
|
import { agentKindMeta } from '~/utils/catalog'
|
|
15
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
15
16
|
|
|
16
17
|
const { t, n } = useI18n()
|
|
17
18
|
|
|
@@ -165,12 +166,12 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
165
166
|
<!-- synthesized result -->
|
|
166
167
|
<section v-if="session.synthesis" class="mb-6">
|
|
167
168
|
<div class="mb-2 flex items-center gap-2">
|
|
168
|
-
<
|
|
169
|
+
<SectionLabel as="h3">
|
|
169
170
|
{{ t('consensus.synthesizedResult') }}
|
|
170
|
-
</
|
|
171
|
+
</SectionLabel>
|
|
171
172
|
<span
|
|
172
173
|
v-if="session.confidence != null"
|
|
173
|
-
class="rounded bg-app-success-500/15 px-1.5 py-0.5 text-xs text-app-success-300"
|
|
174
|
+
class="rounded-sm bg-app-success-500/15 px-1.5 py-0.5 text-xs text-app-success-300"
|
|
174
175
|
>{{ t('consensus.confidence', { pct: pct(session.confidence) }) }}</span
|
|
175
176
|
>
|
|
176
177
|
<CopyButton :text="session.synthesis" class="ms-auto -my-1" />
|
|
@@ -193,9 +194,9 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
193
194
|
|
|
194
195
|
<!-- participants -->
|
|
195
196
|
<section class="mb-6">
|
|
196
|
-
<h3 class="mb-2
|
|
197
|
+
<SectionLabel as="h3" class="mb-2">
|
|
197
198
|
{{ t('consensus.panel') }}
|
|
198
|
-
</
|
|
199
|
+
</SectionLabel>
|
|
199
200
|
<div class="flex flex-wrap gap-2">
|
|
200
201
|
<div
|
|
201
202
|
v-for="(p, i) in session.participants"
|
|
@@ -215,10 +216,10 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
215
216
|
|
|
216
217
|
<!-- rounds -->
|
|
217
218
|
<section v-for="round in session.rounds" :key="round.index" class="mb-5">
|
|
218
|
-
<h3 class="mb-2
|
|
219
|
+
<SectionLabel as="h3" class="mb-2">
|
|
219
220
|
{{ t('consensus.round.heading', { n: round.index + 1 }) }} ·
|
|
220
221
|
{{ roundLabel(round.kind) }}
|
|
221
|
-
</
|
|
222
|
+
</SectionLabel>
|
|
222
223
|
<div class="space-y-3">
|
|
223
224
|
<div
|
|
224
225
|
v-for="c in round.contributions"
|
|
@@ -232,7 +233,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
232
233
|
<span class="text-xs text-dimmed">{{ roleFor(c.participantId) }}</span>
|
|
233
234
|
<span
|
|
234
235
|
v-if="topScore(c)"
|
|
235
|
-
class="ms-auto rounded bg-elevated px-1.5 py-0.5 text-xs text-toned"
|
|
236
|
+
class="ms-auto rounded-sm bg-elevated px-1.5 py-0.5 text-xs text-toned"
|
|
236
237
|
>{{
|
|
237
238
|
t('consensus.topScore', {
|
|
238
239
|
label: topScore(c)!.label,
|
|
@@ -247,7 +248,7 @@ function topScore(c: ConsensusContribution): { label: string; value: number } |
|
|
|
247
248
|
<span
|
|
248
249
|
v-for="s in c.scores"
|
|
249
250
|
:key="s.dimension"
|
|
250
|
-
class="rounded bg-elevated/80 px-1.5 py-0.5 text-xs text-muted"
|
|
251
|
+
class="rounded-sm bg-elevated/80 px-1.5 py-0.5 text-xs text-muted"
|
|
251
252
|
>{{ s.dimension }}: {{ pct(s.value) }}</span
|
|
252
253
|
>
|
|
253
254
|
</div>
|
|
@@ -21,6 +21,8 @@ import { claimCandidates, firstLinkCandidate } from '~/components/context/pasted
|
|
|
21
21
|
import { connectableSources } from '~/utils/sourcePicker'
|
|
22
22
|
import ContextDocumentPicker from '~/components/documents/ContextDocumentPicker.vue'
|
|
23
23
|
import ContextIssuePicker from '~/components/tasks/ContextIssuePicker.vue'
|
|
24
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
25
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
24
26
|
|
|
25
27
|
const props = defineProps<{
|
|
26
28
|
/** The staged attachments; the host owns the array and commits it after creating the block. */
|
|
@@ -188,9 +190,9 @@ function removePending(item: PendingContext) {
|
|
|
188
190
|
<!-- Context documents (ungated; Attach disabled until a source is connected). -->
|
|
189
191
|
<div class="space-y-2">
|
|
190
192
|
<div class="flex items-center justify-between">
|
|
191
|
-
<
|
|
193
|
+
<SectionLabel as="span">
|
|
192
194
|
{{ t('contextAttachments.documents') }}
|
|
193
|
-
</
|
|
195
|
+
</SectionLabel>
|
|
194
196
|
<UButton
|
|
195
197
|
v-if="docsConnected"
|
|
196
198
|
color="neutral"
|
|
@@ -288,24 +290,29 @@ function removePending(item: PendingContext) {
|
|
|
288
290
|
>
|
|
289
291
|
{{ t('contextAttachments.importsOnAdd') }}
|
|
290
292
|
</UBadge>
|
|
291
|
-
<
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
<IconButton
|
|
294
|
+
color="neutral"
|
|
295
|
+
variant="ghost"
|
|
296
|
+
icon="i-lucide-x"
|
|
297
|
+
class="ms-auto shrink-0"
|
|
298
|
+
:label="t('contextAttachments.removePending', { name: item.title })"
|
|
299
|
+
:ui="{
|
|
300
|
+
base: 'p-0 text-muted hover:bg-transparent hover:text-default',
|
|
301
|
+
leadingIcon: 'h-3.5 w-3.5',
|
|
302
|
+
}"
|
|
294
303
|
@click="removePending(item)"
|
|
295
|
-
|
|
296
|
-
<UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
|
|
297
|
-
</button>
|
|
304
|
+
/>
|
|
298
305
|
</div>
|
|
299
306
|
<p
|
|
300
307
|
v-if="item.unreadable"
|
|
301
|
-
class="px-2 pb-1.5 text-
|
|
308
|
+
class="px-2 pb-1.5 text-2xs text-app-warning-400"
|
|
302
309
|
data-testid="context-item-unreadable"
|
|
303
310
|
>
|
|
304
311
|
{{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
|
|
305
312
|
</p>
|
|
306
313
|
</div>
|
|
307
314
|
</div>
|
|
308
|
-
<p v-else class="text-
|
|
315
|
+
<p v-else class="text-2xs text-dimmed">
|
|
309
316
|
{{ docsHint }}
|
|
310
317
|
</p>
|
|
311
318
|
</div>
|
|
@@ -313,9 +320,9 @@ function removePending(item: PendingContext) {
|
|
|
313
320
|
<!-- Context issues (ungated; Attach disabled until a tracker is connected). -->
|
|
314
321
|
<div class="space-y-2">
|
|
315
322
|
<div class="flex items-center justify-between">
|
|
316
|
-
<
|
|
323
|
+
<SectionLabel as="span">
|
|
317
324
|
{{ t('contextAttachments.issues') }}
|
|
318
|
-
</
|
|
325
|
+
</SectionLabel>
|
|
319
326
|
<UButton
|
|
320
327
|
v-if="issuesConnected"
|
|
321
328
|
color="neutral"
|
|
@@ -396,27 +403,32 @@ function removePending(item: PendingContext) {
|
|
|
396
403
|
>
|
|
397
404
|
{{ t('contextAttachments.importsOnAdd') }}
|
|
398
405
|
</UBadge>
|
|
399
|
-
<
|
|
400
|
-
|
|
401
|
-
|
|
406
|
+
<IconButton
|
|
407
|
+
color="neutral"
|
|
408
|
+
variant="ghost"
|
|
409
|
+
icon="i-lucide-x"
|
|
410
|
+
class="ms-auto shrink-0"
|
|
411
|
+
:label="t('contextAttachments.removePending', { name: item.title })"
|
|
412
|
+
:ui="{
|
|
413
|
+
base: 'p-0 text-muted hover:bg-transparent hover:text-default',
|
|
414
|
+
leadingIcon: 'h-3.5 w-3.5',
|
|
415
|
+
}"
|
|
402
416
|
@click="removePending(item)"
|
|
403
|
-
|
|
404
|
-
<UIcon name="i-lucide-x" class="h-3.5 w-3.5" />
|
|
405
|
-
</button>
|
|
417
|
+
/>
|
|
406
418
|
</div>
|
|
407
419
|
<!-- An issue reference gets no pre-flight of its own (there is no `parseRef` to ask a
|
|
408
420
|
tracker), so this line IS its warning: the fetch is attempted when the form opens and
|
|
409
421
|
again on submit, and a failure now blocks the create. -->
|
|
410
422
|
<p
|
|
411
423
|
v-if="item.unreadable"
|
|
412
|
-
class="px-2 pb-1.5 text-
|
|
424
|
+
class="px-2 pb-1.5 text-2xs text-app-warning-400"
|
|
413
425
|
data-testid="context-item-unreadable"
|
|
414
426
|
>
|
|
415
427
|
{{ t('contextAttachments.unreadable', { error: item.unreadable }) }}
|
|
416
428
|
</p>
|
|
417
429
|
</div>
|
|
418
430
|
</div>
|
|
419
|
-
<p v-else class="text-
|
|
431
|
+
<p v-else class="text-2xs text-dimmed">
|
|
420
432
|
{{ issuesHint }}
|
|
421
433
|
</p>
|
|
422
434
|
</div>
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
interviewGatePhase,
|
|
25
25
|
interviewStepReached,
|
|
26
26
|
} from '~/utils/interviewGate'
|
|
27
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
27
28
|
|
|
28
29
|
const board = useBoardStore()
|
|
29
30
|
const docInterview = useDocInterviewStore()
|
|
@@ -131,7 +132,7 @@ const onProceed = () =>
|
|
|
131
132
|
</div>
|
|
132
133
|
|
|
133
134
|
<template v-else>
|
|
134
|
-
<p class="mb-4 text-
|
|
135
|
+
<p class="mb-4 text-sm leading-relaxed text-toned">
|
|
135
136
|
{{ t('docInterview.intro') }}
|
|
136
137
|
</p>
|
|
137
138
|
|
|
@@ -171,20 +172,20 @@ const onProceed = () =>
|
|
|
171
172
|
class="rounded-lg border border-default bg-app-950/40 p-4"
|
|
172
173
|
data-testid="doc-interview-converged"
|
|
173
174
|
>
|
|
174
|
-
<p class="mb-2
|
|
175
|
+
<SectionLabel as="p" class="mb-2">
|
|
175
176
|
{{ t('docInterview.brief') }}
|
|
176
|
-
</
|
|
177
|
+
</SectionLabel>
|
|
177
178
|
<pre
|
|
178
179
|
v-if="session.brief"
|
|
179
|
-
class="whitespace-pre-wrap break-words text-
|
|
180
|
+
class="whitespace-pre-wrap break-words text-sm leading-relaxed text-toned"
|
|
180
181
|
>{{ session.brief }}</pre>
|
|
181
|
-
<p v-else class="text-
|
|
182
|
+
<p v-else class="text-sm text-muted">{{ t('docInterview.converged') }}</p>
|
|
182
183
|
</div>
|
|
183
184
|
|
|
184
185
|
<!-- No pending questions but not yet converged -->
|
|
185
186
|
<div
|
|
186
187
|
v-else-if="questions.length === 0"
|
|
187
|
-
class="rounded-lg border border-default bg-app-950/40 p-4 text-center text-
|
|
188
|
+
class="rounded-lg border border-default bg-app-950/40 p-4 text-center text-sm text-muted"
|
|
188
189
|
>
|
|
189
190
|
{{ t('docInterview.converged') }}
|
|
190
191
|
</div>
|
|
@@ -197,7 +198,7 @@ const onProceed = () =>
|
|
|
197
198
|
class="rounded-lg border border-default bg-app-950/40 p-3"
|
|
198
199
|
data-testid="doc-interview-question"
|
|
199
200
|
>
|
|
200
|
-
<p class="mb-2 text-
|
|
201
|
+
<p class="mb-2 text-sm font-medium text-default">{{ q.question }}</p>
|
|
201
202
|
<UTextarea
|
|
202
203
|
v-model="drafts[q.key]"
|
|
203
204
|
:rows="2"
|
|
@@ -212,7 +213,7 @@ const onProceed = () =>
|
|
|
212
213
|
for an answer to go. Saying so beats taking text the flush could only drop. -->
|
|
213
214
|
<p
|
|
214
215
|
v-if="!addressable(q)"
|
|
215
|
-
class="mt-1 text-
|
|
216
|
+
class="mt-1 text-2xs text-app-warning-300"
|
|
216
217
|
data-testid="doc-interview-unanswerable"
|
|
217
218
|
>
|
|
218
219
|
{{ t('docInterview.unanswerable') }}
|
|
@@ -228,7 +229,7 @@ const onProceed = () =>
|
|
|
228
229
|
v-if="session && phase === 'awaiting' && questions.length > 0"
|
|
229
230
|
class="flex items-center justify-between gap-3 border-t border-default px-5 py-3"
|
|
230
231
|
>
|
|
231
|
-
<p class="text-
|
|
232
|
+
<p class="text-2xs text-dimmed">
|
|
232
233
|
<span
|
|
233
234
|
v-if="unanswered > 0"
|
|
234
235
|
class="text-app-warning-400/90"
|
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
reconcileSource,
|
|
50
50
|
sourceMenuItems,
|
|
51
51
|
} from '~/utils/sourcePicker'
|
|
52
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
52
53
|
|
|
53
54
|
// Repo-backed document sources pick a FILE out of a repository (repo search → file
|
|
54
55
|
// search / tree browse) instead of the generic free-text catalogue search. Today only
|
|
@@ -420,12 +421,9 @@ onMounted(() => {
|
|
|
420
421
|
here (each opens the connect modal over the caller's form). Rendered as plain text when
|
|
421
422
|
there is nothing to decide, which for a member is the usual case. -->
|
|
422
423
|
<div class="flex items-center gap-1.5">
|
|
423
|
-
<span
|
|
424
|
-
:id="sourceLabelId"
|
|
425
|
-
class="shrink-0 text-[11px] font-semibold uppercase tracking-wide text-dimmed"
|
|
426
|
-
>
|
|
424
|
+
<SectionLabel as="span" :id="sourceLabelId" class="shrink-0">
|
|
427
425
|
{{ t('documents.picker.sourceLabel') }}
|
|
428
|
-
</
|
|
426
|
+
</SectionLabel>
|
|
429
427
|
<UDropdownMenu
|
|
430
428
|
v-if="sourcePickable"
|
|
431
429
|
:items="sourceMenu"
|
|
@@ -490,7 +488,7 @@ onMounted(() => {
|
|
|
490
488
|
@keydown.enter="refRow && pickRef(refRow)"
|
|
491
489
|
/>
|
|
492
490
|
|
|
493
|
-
<p v-if="searchError" class="px-1 text-
|
|
491
|
+
<p v-if="searchError" class="px-1 text-2xs text-app-warning-400">
|
|
494
492
|
{{ t('documents.picker.searchFailed', { error: searchError }) }}
|
|
495
493
|
</p>
|
|
496
494
|
|
|
@@ -498,14 +496,14 @@ onMounted(() => {
|
|
|
498
496
|
the user can still edit, rather than as a toast after the task is created. -->
|
|
499
497
|
<p
|
|
500
498
|
v-if="refState.status === 'checking'"
|
|
501
|
-
class="px-1 text-
|
|
499
|
+
class="px-1 text-2xs text-dimmed"
|
|
502
500
|
data-testid="doc-ref-checking"
|
|
503
501
|
>
|
|
504
502
|
{{ t('documents.picker.refChecking') }}
|
|
505
503
|
</p>
|
|
506
504
|
<div
|
|
507
505
|
v-else-if="refRejection"
|
|
508
|
-
class="flex flex-wrap items-center gap-x-2 gap-y-1 px-1 text-
|
|
506
|
+
class="flex flex-wrap items-center gap-x-2 gap-y-1 px-1 text-2xs text-app-warning-400"
|
|
509
507
|
data-testid="doc-ref-rejected"
|
|
510
508
|
>
|
|
511
509
|
<span>{{ refRejection }}</span>
|
|
@@ -523,7 +521,7 @@ onMounted(() => {
|
|
|
523
521
|
</div>
|
|
524
522
|
<p
|
|
525
523
|
v-else-if="refState.status === 'unchecked'"
|
|
526
|
-
class="px-1 text-
|
|
524
|
+
class="px-1 text-2xs text-app-warning-400"
|
|
527
525
|
data-testid="doc-ref-unchecked"
|
|
528
526
|
>
|
|
529
527
|
{{ t('documents.picker.refCheckFailed', { error: refState.message }) }}
|
|
@@ -532,7 +530,7 @@ onMounted(() => {
|
|
|
532
530
|
at all reads as a picker that dropped it. -->
|
|
533
531
|
<p
|
|
534
532
|
v-else-if="refAlreadyAttached"
|
|
535
|
-
class="px-1 text-
|
|
533
|
+
class="px-1 text-2xs text-dimmed"
|
|
536
534
|
data-testid="doc-ref-already-attached"
|
|
537
535
|
>
|
|
538
536
|
{{ t('documents.picker.refAlreadyAttached') }}
|
|
@@ -540,10 +538,11 @@ onMounted(() => {
|
|
|
540
538
|
|
|
541
539
|
<div class="max-h-56 space-y-0.5 overflow-y-auto">
|
|
542
540
|
<!-- Already-imported documents (linked directly, no re-fetch). -->
|
|
543
|
-
<
|
|
541
|
+
<UButton
|
|
542
|
+
color="neutral"
|
|
543
|
+
variant="ghost"
|
|
544
544
|
v-for="d in importedRows"
|
|
545
545
|
:key="`imp:${d.externalId}`"
|
|
546
|
-
type="button"
|
|
547
546
|
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"
|
|
548
547
|
@click="pickImported(d.externalId, d.title, d.excerpt)"
|
|
549
548
|
>
|
|
@@ -552,26 +551,28 @@ onMounted(() => {
|
|
|
552
551
|
<UBadge color="neutral" variant="soft" size="xs" class="ms-auto shrink-0">{{
|
|
553
552
|
t('documents.picker.importedBadge')
|
|
554
553
|
}}</UBadge>
|
|
555
|
-
</
|
|
554
|
+
</UButton>
|
|
556
555
|
|
|
557
556
|
<!-- Source search hits (imported on add). -->
|
|
558
|
-
<
|
|
557
|
+
<UButton
|
|
558
|
+
color="neutral"
|
|
559
|
+
variant="ghost"
|
|
559
560
|
v-for="r in searchRows"
|
|
560
561
|
:key="`hit:${r.externalId}`"
|
|
561
|
-
type="button"
|
|
562
562
|
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"
|
|
563
563
|
@click="pickSearch(r)"
|
|
564
564
|
>
|
|
565
565
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-muted" />
|
|
566
566
|
<span class="truncate">{{ r.title }}</span>
|
|
567
|
-
</
|
|
567
|
+
</UButton>
|
|
568
568
|
|
|
569
569
|
<!-- Explicit URL/ID reference, RESOLVED: the row shows the canonical form the source
|
|
570
570
|
settled on, so a share link's title segment and tracking params are visibly gone
|
|
571
571
|
before the attachment is staged. -->
|
|
572
|
-
<
|
|
572
|
+
<UButton
|
|
573
|
+
color="neutral"
|
|
574
|
+
variant="ghost"
|
|
573
575
|
v-if="refRow"
|
|
574
|
-
type="button"
|
|
575
576
|
class="flex w-full items-start gap-1.5 rounded-md px-2 py-1.5 text-start text-xs text-toned hover:bg-elevated/70"
|
|
576
577
|
data-testid="doc-ref-attach"
|
|
577
578
|
@click="pickRef(refRow)"
|
|
@@ -585,7 +586,7 @@ onMounted(() => {
|
|
|
585
586
|
</template>
|
|
586
587
|
</i18n-t>
|
|
587
588
|
</span>
|
|
588
|
-
<span v-if="refRow.trimmed" class="block truncate text-
|
|
589
|
+
<span v-if="refRow.trimmed" class="block truncate text-2xs text-dimmed">
|
|
589
590
|
{{ t('documents.picker.refTrimmed') }}
|
|
590
591
|
</span>
|
|
591
592
|
<!-- A WIDENED reference, which the trim note above must never be left to imply: the
|
|
@@ -593,7 +594,7 @@ onMounted(() => {
|
|
|
593
594
|
around it. Amber and separate, because it is a loss rather than tidying. -->
|
|
594
595
|
<span
|
|
595
596
|
v-if="refRow.droppedScope"
|
|
596
|
-
class="block text-
|
|
597
|
+
class="block text-2xs text-app-warning-400"
|
|
597
598
|
data-testid="doc-ref-widened"
|
|
598
599
|
>
|
|
599
600
|
{{ t('documents.picker.refWidened', { scope: refRow.droppedScope }) }}
|
|
@@ -608,7 +609,7 @@ onMounted(() => {
|
|
|
608
609
|
>
|
|
609
610
|
{{ t('documents.picker.importedBadge') }}
|
|
610
611
|
</UBadge>
|
|
611
|
-
</
|
|
612
|
+
</UButton>
|
|
612
613
|
|
|
613
614
|
<EmptyState
|
|
614
615
|
v-if="empty"
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { DocumentSourceKind } from '~/types/domain'
|
|
3
3
|
import DocumentSyncState from '~/components/documents/DocumentSyncState.vue'
|
|
4
4
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
5
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
5
6
|
|
|
6
7
|
// Import pages from a connected document source and pick one to expand into
|
|
7
8
|
// board structure. A source selector lets the user choose which connected source
|
|
@@ -125,9 +126,9 @@ function preview(externalId: string) {
|
|
|
125
126
|
</div>
|
|
126
127
|
|
|
127
128
|
<div v-if="sourceDocs.length" class="space-y-2">
|
|
128
|
-
<
|
|
129
|
+
<SectionLabel as="h3">
|
|
129
130
|
{{ t('documents.import.importedHeading') }}
|
|
130
|
-
</
|
|
131
|
+
</SectionLabel>
|
|
131
132
|
<div
|
|
132
133
|
v-for="doc in sourceDocs"
|
|
133
134
|
:key="`${doc.source}:${doc.externalId}`"
|
|
@@ -135,14 +136,15 @@ function preview(externalId: string) {
|
|
|
135
136
|
>
|
|
136
137
|
<div class="flex items-start justify-between gap-2">
|
|
137
138
|
<div class="min-w-0">
|
|
138
|
-
<
|
|
139
|
-
|
|
139
|
+
<ULink
|
|
140
|
+
raw
|
|
141
|
+
:to="doc.url"
|
|
140
142
|
target="_blank"
|
|
141
143
|
rel="noopener"
|
|
142
144
|
class="truncate text-sm font-medium text-highlighted hover:underline"
|
|
143
145
|
>
|
|
144
146
|
{{ doc.title }}
|
|
145
|
-
</
|
|
147
|
+
</ULink>
|
|
146
148
|
<p class="mt-0.5 line-clamp-2 text-xs text-dimmed">{{ doc.excerpt }}</p>
|
|
147
149
|
<DocumentSyncState :doc="doc" class="mt-1" />
|
|
148
150
|
</div>
|
|
@@ -16,15 +16,18 @@ const { t } = useI18n()
|
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
18
|
<template>
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
19
|
+
<ULink
|
|
20
|
+
v-if="props.url"
|
|
21
|
+
raw
|
|
22
|
+
:to="props.url"
|
|
23
|
+
target="_blank"
|
|
24
|
+
rel="noopener"
|
|
25
|
+
:title="props.url"
|
|
26
|
+
:class="props.hoverClass"
|
|
27
27
|
>
|
|
28
28
|
<slot />
|
|
29
|
-
</
|
|
29
|
+
</ULink>
|
|
30
|
+
<span v-else :title="t('documents.taskDocs.uploadedHint')">
|
|
31
|
+
<slot />
|
|
32
|
+
</span>
|
|
30
33
|
</template>
|
|
@@ -132,10 +132,10 @@ async function disconnect() {
|
|
|
132
132
|
>
|
|
133
133
|
{{ t('documents.connect.oauth.action', { source: descriptor.label }) }}
|
|
134
134
|
</UButton>
|
|
135
|
-
<p class="text-
|
|
135
|
+
<p class="text-2xs text-dimmed">
|
|
136
136
|
{{ t('documents.connect.oauth.scopes', { scopes: oauth.scopes.join(', ') }) }}
|
|
137
137
|
</p>
|
|
138
|
-
<p class="text-
|
|
138
|
+
<p class="text-2xs text-dimmed">{{ t('documents.connect.oauth.fallback') }}</p>
|
|
139
139
|
</div>
|
|
140
140
|
|
|
141
141
|
<div class="space-y-3">
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { isConnectableSource } from '@cat-factory/contracts'
|
|
3
|
+
import IconButton from '~/components/common/IconButton.vue'
|
|
3
4
|
import type { SourceDocument } from '~/types/domain'
|
|
4
5
|
import {
|
|
5
6
|
CHANGE_KEYS,
|
|
@@ -165,7 +166,7 @@ async function refresh() {
|
|
|
165
166
|
</script>
|
|
166
167
|
|
|
167
168
|
<template>
|
|
168
|
-
<div class="flex items-center gap-1.5 text-
|
|
169
|
+
<div class="flex items-center gap-1.5 text-2xs text-dimmed">
|
|
169
170
|
<span class="truncate">
|
|
170
171
|
{{ t('documents.freshness.updated', { when: d(new Date(props.doc.syncedAt), 'long') }) }}
|
|
171
172
|
</span>
|
|
@@ -182,15 +183,14 @@ async function refresh() {
|
|
|
182
183
|
<UIcon name="i-lucide-image-off" class="h-3 w-3 shrink-0" />
|
|
183
184
|
<span class="truncate">{{ renders }}</span>
|
|
184
185
|
</span>
|
|
185
|
-
<
|
|
186
|
+
<IconButton
|
|
186
187
|
v-if="askable"
|
|
187
188
|
color="neutral"
|
|
188
189
|
variant="ghost"
|
|
189
190
|
size="xs"
|
|
190
191
|
icon="i-lucide-refresh-cw"
|
|
191
192
|
:loading="busy"
|
|
192
|
-
:
|
|
193
|
-
:title="t('documents.freshness.refresh')"
|
|
193
|
+
:label="t('documents.freshness.refresh')"
|
|
194
194
|
class="ml-auto shrink-0"
|
|
195
195
|
@click="refresh"
|
|
196
196
|
/>
|
|
@@ -3,6 +3,7 @@ import { DOC_KINDS } from '~/types/domain'
|
|
|
3
3
|
import type { DocKind, DocumentLinkRole, SourceDocument } from '~/types/domain'
|
|
4
4
|
import DocumentOriginLink from '~/components/documents/DocumentOriginLink.vue'
|
|
5
5
|
import IntegrationBackTitle from '~/components/layout/IntegrationBackTitle.vue'
|
|
6
|
+
import SectionLabel from '~/components/common/SectionLabel.vue'
|
|
6
7
|
|
|
7
8
|
// Manage the workspace's per-DocKind TEMPLATE (singular) + EXEMPLAR (multi) document links (WS1).
|
|
8
9
|
// A kind can be pointed at one of the workspace's already-imported documents so its parsed
|
|
@@ -132,9 +133,9 @@ async function unlink(doc: SourceDocument) {
|
|
|
132
133
|
|
|
133
134
|
<!-- Template (singular per kind) ------------------------------------ -->
|
|
134
135
|
<section class="rounded-lg border border-default bg-default/50 p-3">
|
|
135
|
-
<
|
|
136
|
+
<SectionLabel as="h3">
|
|
136
137
|
{{ t('documents.templates.templateHeading') }}
|
|
137
|
-
</
|
|
138
|
+
</SectionLabel>
|
|
138
139
|
<p class="mt-0.5 text-xs text-dimmed">
|
|
139
140
|
{{ t('documents.templates.templateHint', { kind }) }}
|
|
140
141
|
</p>
|
|
@@ -167,9 +168,9 @@ async function unlink(doc: SourceDocument) {
|
|
|
167
168
|
|
|
168
169
|
<!-- Exemplars (multi per kind) -------------------------------------- -->
|
|
169
170
|
<section class="rounded-lg border border-default bg-default/50 p-3">
|
|
170
|
-
<
|
|
171
|
+
<SectionLabel as="h3">
|
|
171
172
|
{{ t('documents.templates.exemplarsHeading') }}
|
|
172
|
-
</
|
|
173
|
+
</SectionLabel>
|
|
173
174
|
<p class="mt-0.5 text-xs text-dimmed">
|
|
174
175
|
{{ t('documents.templates.exemplarsHint') }}
|
|
175
176
|
</p>
|
|
@@ -238,21 +238,22 @@ onMounted(() => {
|
|
|
238
238
|
class="w-full"
|
|
239
239
|
:placeholder="t('documents.repoPicker.searchFilesPlaceholder')"
|
|
240
240
|
/>
|
|
241
|
-
<p v-if="filesError" class="px-1 text-
|
|
241
|
+
<p v-if="filesError" class="px-1 text-2xs text-app-warning-400">
|
|
242
242
|
{{ t('documents.repoPicker.filesFailed', { error: filesError }) }}
|
|
243
243
|
</p>
|
|
244
244
|
<div class="max-h-56 space-y-0.5 overflow-y-auto">
|
|
245
|
-
<
|
|
245
|
+
<UButton
|
|
246
|
+
color="neutral"
|
|
247
|
+
variant="ghost"
|
|
246
248
|
v-for="f in fileMatches"
|
|
247
249
|
:key="f.path"
|
|
248
|
-
type="button"
|
|
249
250
|
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"
|
|
250
251
|
@click="pickFile(f.path)"
|
|
251
252
|
>
|
|
252
253
|
<UIcon :name="icon" class="h-3.5 w-3.5 shrink-0 text-primary" />
|
|
253
254
|
<span class="truncate">{{ f.path }}</span>
|
|
254
|
-
</
|
|
255
|
-
<p v-if="fileMatchesTruncated" class="px-2 py-1 text-
|
|
255
|
+
</UButton>
|
|
256
|
+
<p v-if="fileMatchesTruncated" class="px-2 py-1 text-2xs text-dimmed">
|
|
256
257
|
{{ t('documents.repoPicker.moreFiles', { count: FILE_RESULTS_CAP }) }}
|
|
257
258
|
</p>
|
|
258
259
|
<EmptyState
|
|
@@ -261,10 +262,7 @@ onMounted(() => {
|
|
|
261
262
|
icon="i-lucide-file-search"
|
|
262
263
|
:title="t('documents.repoPicker.noFileMatches')"
|
|
263
264
|
/>
|
|
264
|
-
<p
|
|
265
|
-
v-else-if="!loadingFiles && !fileQuery.trim()"
|
|
266
|
-
class="px-2 py-1 text-[11px] text-dimmed"
|
|
267
|
-
>
|
|
265
|
+
<p v-else-if="!loadingFiles && !fileQuery.trim()" class="px-2 py-1 text-2xs text-dimmed">
|
|
268
266
|
{{ t('documents.repoPicker.searchFilesHint') }}
|
|
269
267
|
</p>
|
|
270
268
|
</div>
|
|
@@ -191,18 +191,18 @@ function stage() {
|
|
|
191
191
|
<UIcon name="i-lucide-frame" class="h-4 w-4 text-primary" />
|
|
192
192
|
<span class="truncate">{{ row.label }}</span>
|
|
193
193
|
</div>
|
|
194
|
-
<p v-if="row.trimmed" class="text-
|
|
194
|
+
<p v-if="row.trimmed" class="text-2xs text-muted">
|
|
195
195
|
{{ t('documents.startFromDesign.trimmed') }}
|
|
196
196
|
</p>
|
|
197
197
|
<!-- Its own line, in amber: a trim resolves the same page, a drop widens ONE frame to
|
|
198
198
|
the whole design file, and the second is what a designer needs to see. -->
|
|
199
|
-
<p v-if="row.droppedScope" class="text-
|
|
199
|
+
<p v-if="row.droppedScope" class="text-2xs text-app-warning-300">
|
|
200
200
|
{{ t('documents.startFromDesign.widened', { scope: row.droppedScope }) }}
|
|
201
201
|
</p>
|
|
202
|
-
<p v-if="row.unchecked && target" class="text-
|
|
202
|
+
<p v-if="row.unchecked && target" class="text-2xs text-muted">
|
|
203
203
|
{{ t('documents.startFromDesign.unchecked') }}
|
|
204
204
|
</p>
|
|
205
|
-
<p v-else-if="row.unchecked" class="text-
|
|
205
|
+
<p v-else-if="row.unchecked" class="text-2xs text-app-warning-300">
|
|
206
206
|
{{ t('documents.startFromDesign.uncheckedAmbiguous') }}
|
|
207
207
|
</p>
|
|
208
208
|
</div>
|
|
@@ -165,7 +165,7 @@ async function attach(item: PendingContext) {
|
|
|
165
165
|
<DocumentSyncState :doc="doc" class="mt-1" />
|
|
166
166
|
</div>
|
|
167
167
|
</div>
|
|
168
|
-
<p v-else class="text-
|
|
168
|
+
<p v-else class="text-2xs text-dimmed">
|
|
169
169
|
{{ emptyHint }}
|
|
170
170
|
</p>
|
|
171
171
|
</InspectorSection>
|