feat(06-01): fix named terminology straggler requirements (TERM-10 through TERM-17)
- TERM-10: Companies.tsx breadcrumb uses VOCAB.companies, loading/delete text uses VOCAB - TERM-11: InstanceSettings.tsx adds VOCAB import, uses VOCAB.company/companies - TERM-12: Costs.tsx adds VOCAB import and SCOPE_LABELS map, replaces hardcoded company strings - TERM-13: CompanyImport.tsx uses VOCAB.appName, VOCAB.company, VOCAB.board throughout - TERM-17: IssuesList.tsx (component) title='Board view' -> 'Kanban view' - Dashboard.tsx: 'awaiting board review' -> 'awaiting owner review' - CompanySettings.tsx: 'No company selected' uses VOCAB.company - ReportsToPicker.tsx: adds VOCAB import, default label uses VOCAB.ceo not hardcoded 'CEO'
This commit is contained in:
parent
f3eed12c30
commit
d23c7ea4d5
8 changed files with 34 additions and 24 deletions
|
|
@ -391,7 +391,7 @@ export function IssuesList({
|
|||
<button
|
||||
className={`p-1.5 transition-colors ${viewState.viewMode === "board" ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground"}`}
|
||||
onClick={() => updateView({ viewMode: "board" })}
|
||||
title="Board view"
|
||||
title="Kanban view"
|
||||
>
|
||||
<Columns3 className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useState } from "react";
|
||||
import { VOCAB } from "@paperclipai/branding";
|
||||
import type { Agent } from "@paperclipai/shared";
|
||||
import {
|
||||
Popover,
|
||||
|
|
@ -16,7 +17,7 @@ export function ReportsToPicker({
|
|||
onChange,
|
||||
disabled = false,
|
||||
excludeAgentIds = [],
|
||||
disabledEmptyLabel = "Reports to: N/A (CEO)",
|
||||
disabledEmptyLabel,
|
||||
chooseLabel = "Reports to...",
|
||||
}: {
|
||||
agents: Agent[];
|
||||
|
|
@ -27,6 +28,7 @@ export function ReportsToPicker({
|
|||
disabledEmptyLabel?: string;
|
||||
chooseLabel?: string;
|
||||
}) {
|
||||
const label = disabledEmptyLabel ?? `Reports to: N/A (${VOCAB.ceo})`;
|
||||
const [open, setOpen] = useState(false);
|
||||
const exclude = new Set(excludeAgentIds);
|
||||
const rows = agents.filter(
|
||||
|
|
@ -69,7 +71,7 @@ export function ReportsToPicker({
|
|||
<>
|
||||
<User className="h-3 w-3 shrink-0 text-muted-foreground" />
|
||||
<span className="min-w-0 truncate">
|
||||
{disabled ? disabledEmptyLabel : chooseLabel}
|
||||
{disabled ? label : chooseLabel}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export function Companies() {
|
|||
});
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumbs([{ label: "Companies" }]);
|
||||
setBreadcrumbs([{ label: VOCAB.companies }]);
|
||||
}, [setBreadcrumbs]);
|
||||
|
||||
function startEdit(companyId: string, currentName: string) {
|
||||
|
|
@ -98,7 +98,7 @@ export function Companies() {
|
|||
</div>
|
||||
|
||||
<div className="h-6">
|
||||
{loading && <p className="text-sm text-muted-foreground">Loading companies...</p>}
|
||||
{loading && <p className="text-sm text-muted-foreground">{`Loading ${VOCAB.companies.toLowerCase()}...`}</p>}
|
||||
{error && <p className="text-sm text-destructive">{error.message}</p>}
|
||||
</div>
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ export function Companies() {
|
|||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<p className="text-sm text-destructive font-medium">
|
||||
Delete this company and all its data? This cannot be undone.
|
||||
{`Delete this ${VOCAB.company.toLowerCase()} and all its data? This cannot be undone.`}
|
||||
</p>
|
||||
<div className="flex items-center gap-2 ml-4 shrink-0">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -704,7 +704,7 @@ export function CompanyImport() {
|
|||
}, [companyAgents]);
|
||||
|
||||
const localZipHelpText =
|
||||
"Upload a .zip exported directly from Paperclip. Re-zipped archives created by Finder, Explorer, or other zip tools may not import correctly.";
|
||||
`Upload a .zip exported directly from ${VOCAB.appName}. Re-zipped archives created by Finder, Explorer, or other zip tools may not import correctly.`;
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumbs([
|
||||
|
|
@ -1086,7 +1086,7 @@ export function CompanyImport() {
|
|||
const selectedAction = selectedFile ? (actionMap.get(selectedFile) ?? null) : null;
|
||||
|
||||
if (!selectedCompanyId) {
|
||||
return <EmptyState icon={Download} message="Select a company to import into." />;
|
||||
return <EmptyState icon={Download} message={`Select a ${VOCAB.company.toLowerCase()} to import into.`} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -1096,7 +1096,7 @@ export function CompanyImport() {
|
|||
<div>
|
||||
<h2 className="text-base font-semibold">Import source</h2>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Choose a GitHub repo or upload a local Paperclip zip package.
|
||||
{`Choose a GitHub repo or upload a local ${VOCAB.appName} zip package.`}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -1178,7 +1178,7 @@ export function CompanyImport() {
|
|||
</Field>
|
||||
)}
|
||||
|
||||
<Field label="Target" hint="Import into this company or create a new one.">
|
||||
<Field label="Target" hint={`Import into this ${VOCAB.company.toLowerCase()} or create a new one.`}>
|
||||
<select
|
||||
className="w-full rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm outline-none"
|
||||
value={targetMode}
|
||||
|
|
@ -1187,16 +1187,16 @@ export function CompanyImport() {
|
|||
setImportPreview(null);
|
||||
}}
|
||||
>
|
||||
<option value="new">Create new company</option>
|
||||
<option value="new">{`Create new ${VOCAB.company.toLowerCase()}`}</option>
|
||||
<option value="existing">
|
||||
Existing company: {selectedCompany?.name}
|
||||
{`Existing ${VOCAB.company.toLowerCase()}: ${selectedCompany?.name}`}
|
||||
</option>
|
||||
</select>
|
||||
</Field>
|
||||
|
||||
{targetMode === "new" && (
|
||||
<Field
|
||||
label="New company name"
|
||||
label={`New ${VOCAB.company.toLowerCase()} name`}
|
||||
hint="Optional override. Leave blank to use the package name."
|
||||
>
|
||||
<input
|
||||
|
|
@ -1211,7 +1211,7 @@ export function CompanyImport() {
|
|||
|
||||
<Field
|
||||
label="Collision strategy"
|
||||
hint="Board imports can rename, skip, or replace matching company content."
|
||||
hint={`${VOCAB.board} imports can rename, skip, or replace matching ${VOCAB.company.toLowerCase()} content.`}
|
||||
>
|
||||
<select
|
||||
className="w-full rounded-md border border-border bg-transparent px-2.5 py-1.5 text-sm outline-none"
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export function CompanySettings() {
|
|||
if (!selectedCompany) {
|
||||
return (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
No company selected. Select a company from the switcher above.
|
||||
{`No ${VOCAB.company.toLowerCase()} selected. Select a ${VOCAB.company.toLowerCase()} from the switcher above.`}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useEffect, useMemo, useRef, useState, type ComponentType } from "react";
|
||||
import { VOCAB } from "@paperclipai/branding";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import type {
|
||||
BudgetPolicySummary,
|
||||
|
|
@ -35,6 +36,12 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|||
|
||||
const NO_COMPANY = "__none__";
|
||||
|
||||
const SCOPE_LABELS: Record<string, string> = {
|
||||
company: VOCAB.company,
|
||||
agent: "Agent",
|
||||
project: "Project",
|
||||
};
|
||||
|
||||
function currentWeekRange(): { from: string; to: string } {
|
||||
const now = new Date();
|
||||
const day = now.getDay();
|
||||
|
|
@ -529,7 +536,7 @@ export function Costs() {
|
|||
}), [budgetPolicies]);
|
||||
|
||||
if (!selectedCompanyId) {
|
||||
return <EmptyState icon={DollarSign} message="Select a company to view costs." />;
|
||||
return <EmptyState icon={DollarSign} message={`Select a ${VOCAB.company.toLowerCase()} to view costs.`} />;
|
||||
}
|
||||
|
||||
const showCustomPrompt = preset === "custom" && !customReady;
|
||||
|
|
@ -855,7 +862,7 @@ export function Costs() {
|
|||
<MetricTile
|
||||
label="Pending approvals"
|
||||
value={String(budgetData?.pendingApprovalCount ?? 0)}
|
||||
subtitle="Budget override approvals awaiting board action"
|
||||
subtitle="Budget override approvals awaiting owner action"
|
||||
icon={ArrowUpRight}
|
||||
/>
|
||||
<MetricTile
|
||||
|
|
@ -907,10 +914,10 @@ export function Costs() {
|
|||
return (
|
||||
<section key={scopeType} className="space-y-3">
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold capitalize">{scopeType} budgets</h2>
|
||||
<h2 className="text-lg font-semibold">{SCOPE_LABELS[scopeType] ?? scopeType} budgets</h2>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{scopeType === "company"
|
||||
? "Company-wide monthly policy."
|
||||
? `${VOCAB.company}-wide monthly policy.`
|
||||
: scopeType === "agent"
|
||||
? "Recurring monthly spend policies for individual agents."
|
||||
: "Lifetime spend policies for execution-bound projects."}
|
||||
|
|
@ -939,7 +946,7 @@ export function Costs() {
|
|||
{budgetPolicies.length === 0 ? (
|
||||
<Card>
|
||||
<CardContent className="px-5 py-8 text-sm text-muted-foreground">
|
||||
No budget policies yet. Set agent and project budgets from their detail pages, or use the existing company monthly budget control.
|
||||
{`No budget policies yet. Set agent and project budgets from their detail pages, or use the existing ${VOCAB.company.toLowerCase()} monthly budget control.`}
|
||||
</CardContent>
|
||||
</Card>
|
||||
) : null}
|
||||
|
|
|
|||
|
|
@ -277,8 +277,8 @@ export function Dashboard() {
|
|||
description={
|
||||
<span>
|
||||
{data.budgets.pendingApprovals > 0
|
||||
? `${data.budgets.pendingApprovals} budget overrides awaiting board review`
|
||||
: "Awaiting board review"}
|
||||
? `${data.budgets.pendingApprovals} budget overrides awaiting owner review`
|
||||
: "Awaiting owner review"}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { VOCAB } from "@paperclipai/branding";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Clock3, ExternalLink, Settings } from "lucide-react";
|
||||
import type { InstanceSchedulerHeartbeatAgent } from "@paperclipai/shared";
|
||||
|
|
@ -171,14 +172,14 @@ export function InstanceSettings() {
|
|||
<h1 className="text-lg font-semibold">Scheduler Heartbeats</h1>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Agents with a timer heartbeat enabled across all of your companies.
|
||||
{`Agents with a timer heartbeat enabled across all of your ${VOCAB.companies.toLowerCase()}.`}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4 text-sm text-muted-foreground">
|
||||
<span><span className="font-semibold text-foreground">{activeCount}</span> active</span>
|
||||
<span><span className="font-semibold text-foreground">{disabledCount}</span> disabled</span>
|
||||
<span><span className="font-semibold text-foreground">{grouped.length}</span> {grouped.length === 1 ? "company" : "companies"}</span>
|
||||
<span><span className="font-semibold text-foreground">{grouped.length}</span> {grouped.length === 1 ? VOCAB.company.toLowerCase() : VOCAB.companies.toLowerCase()}</span>
|
||||
{anyEnabled && (
|
||||
<Button
|
||||
variant="destructive"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue