Remove namespace from skill detail page header

Per feedback, the detail page looks cleaner without the org/repo
namespace line above the skill name. The icon remains on the name row.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Dotta
2026-03-16 19:07:54 -05:00
parent b339f923d6
commit 52978e84ba

View File

@@ -7,6 +7,7 @@ import type {
CompanySkillFileDetail,
CompanySkillFileInventoryEntry,
CompanySkillListItem,
CompanySkillProjectScanResult,
CompanySkillSourceBadge,
CompanySkillUpdateStatus,
} from "@paperclipai/shared";
@@ -167,6 +168,17 @@ function shortRef(ref: string | null | undefined) {
return ref.slice(0, 7);
}
function formatProjectScanSummary(result: CompanySkillProjectScanResult) {
const parts = [
`${result.discovered} found`,
`${result.imported.length} imported`,
`${result.updated.length} updated`,
];
if (result.conflicts.length > 0) parts.push(`${result.conflicts.length} conflicts`);
if (result.skipped.length > 0) parts.push(`${result.skipped.length} skipped`);
return `${parts.join(", ")} across ${result.scannedWorkspaces} workspace${result.scannedWorkspaces === 1 ? "" : "s"}.`;
}
function fileIcon(kind: CompanySkillFileInventoryEntry["kind"]) {
if (kind === "script" || kind === "reference") return FileCode2;
return FileText;
@@ -542,11 +554,6 @@ function SkillPane({
<div className="border-b border-border px-5 py-4">
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="min-w-0">
{detail.key.includes("/") && (
<div className="truncate font-mono text-xs text-muted-foreground">
{detail.key.split("/").slice(0, -1).join("/")}
</div>
)}
<h1 className="flex items-center gap-2 truncate text-2xl font-semibold">
<SourceIcon className="h-5 w-5 shrink-0 text-muted-foreground" />
{detail.name}
@@ -734,6 +741,7 @@ export function CompanySkills() {
const [draft, setDraft] = useState("");
const [displayedDetail, setDisplayedDetail] = useState<CompanySkillDetail | null>(null);
const [displayedFile, setDisplayedFile] = useState<CompanySkillFileDetail | null>(null);
const [scanStatusMessage, setScanStatusMessage] = useState<string | null>(null);
const parsedRoute = useMemo(() => parseSkillRoute(routePath), [routePath]);
const routeSkillId = parsedRoute.skillId;
const selectedPath = parsedRoute.filePath;
@@ -876,6 +884,45 @@ export function CompanySkills() {
},
});
const scanProjects = useMutation({
mutationFn: () => companySkillsApi.scanProjects(selectedCompanyId!),
onMutate: () => {
setScanStatusMessage("Scanning project workspaces for skills...");
},
onSuccess: async (result) => {
setScanStatusMessage("Refreshing skills list...");
await queryClient.invalidateQueries({ queryKey: queryKeys.companySkills.list(selectedCompanyId!) });
const summary = formatProjectScanSummary(result);
setScanStatusMessage(summary);
pushToast({
tone: "success",
title: "Project skill scan complete",
body: summary,
});
if (result.conflicts[0]) {
pushToast({
tone: "warn",
title: "Skill conflicts found",
body: result.conflicts[0].reason,
});
} else if (result.warnings[0]) {
pushToast({
tone: "warn",
title: "Scan warnings",
body: result.warnings[0],
});
}
},
onError: (error) => {
setScanStatusMessage(null);
pushToast({
tone: "error",
title: "Project skill scan failed",
body: error instanceof Error ? error.message : "Failed to scan project workspaces.",
});
},
});
const saveFile = useMutation({
mutationFn: () => companySkillsApi.updateFile(
selectedCompanyId!,
@@ -1002,10 +1049,11 @@ export function CompanySkills() {
<Button
variant="ghost"
size="icon-sm"
onClick={() => queryClient.invalidateQueries({ queryKey: queryKeys.companySkills.list(selectedCompanyId) })}
disabled={skillsQuery.isLoading}
onClick={() => scanProjects.mutate()}
disabled={scanProjects.isPending}
title="Scan project workspaces for skills"
>
<RefreshCw className="h-4 w-4" />
<RefreshCw className={cn("h-4 w-4", scanProjects.isPending && "animate-spin")} />
</Button>
<Button variant="ghost" size="icon-sm" onClick={() => setCreateOpen((value) => !value)}>
<Plus className="h-4 w-4" />
@@ -1039,6 +1087,11 @@ export function CompanySkills() {
{importSkill.isPending ? <RefreshCw className="h-4 w-4 animate-spin" /> : "Add"}
</Button>
</div>
{scanStatusMessage && (
<p className="mt-3 text-xs text-muted-foreground">
{scanStatusMessage}
</p>
)}
</div>
{createOpen && (