mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 18:30:39 +09:00
Merge pull request #1655 from paperclipai/pr/pap-795-company-portability
feat(portability): improve company import and export flow
This commit is contained in:
commit
eeb7e1a91a
36 changed files with 5238 additions and 271 deletions
|
|
@ -160,6 +160,7 @@ export const FRONTMATTER_FIELD_LABELS: Record<string, string> = {
|
|||
priority: "Priority",
|
||||
assignee: "Assignee",
|
||||
project: "Project",
|
||||
recurring: "Recurring",
|
||||
targetDate: "Target date",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ import { useCompany } from "../context/CompanyContext";
|
|||
import { useDialog } from "../context/DialogContext";
|
||||
import { useSidebar } from "../context/SidebarContext";
|
||||
import { agentsApi } from "../api/agents";
|
||||
import { authApi } from "../api/auth";
|
||||
import { heartbeatsApi } from "../api/heartbeats";
|
||||
import { queryKeys } from "../lib/queryKeys";
|
||||
import { cn, agentRouteRef, agentUrl } from "../lib/utils";
|
||||
import { useAgentOrder } from "../hooks/useAgentOrder";
|
||||
import { AgentIcon } from "./AgentIconPicker";
|
||||
import { BudgetSidebarMarker } from "./BudgetSidebarMarker";
|
||||
import {
|
||||
|
|
@ -17,28 +19,6 @@ import {
|
|||
CollapsibleTrigger,
|
||||
} from "@/components/ui/collapsible";
|
||||
import type { Agent } from "@paperclipai/shared";
|
||||
|
||||
/** BFS sort: roots first (no reportsTo), then their direct reports, etc. */
|
||||
function sortByHierarchy(agents: Agent[]): Agent[] {
|
||||
const byId = new Map(agents.map((a) => [a.id, a]));
|
||||
const childrenOf = new Map<string | null, Agent[]>();
|
||||
for (const a of agents) {
|
||||
const parent = a.reportsTo && byId.has(a.reportsTo) ? a.reportsTo : null;
|
||||
const list = childrenOf.get(parent) ?? [];
|
||||
list.push(a);
|
||||
childrenOf.set(parent, list);
|
||||
}
|
||||
const sorted: Agent[] = [];
|
||||
const queue = childrenOf.get(null) ?? [];
|
||||
while (queue.length > 0) {
|
||||
const agent = queue.shift()!;
|
||||
sorted.push(agent);
|
||||
const children = childrenOf.get(agent.id);
|
||||
if (children) queue.push(...children);
|
||||
}
|
||||
return sorted;
|
||||
}
|
||||
|
||||
export function SidebarAgents() {
|
||||
const [open, setOpen] = useState(true);
|
||||
const { selectedCompanyId } = useCompany();
|
||||
|
|
@ -51,6 +31,10 @@ export function SidebarAgents() {
|
|||
queryFn: () => agentsApi.list(selectedCompanyId!),
|
||||
enabled: !!selectedCompanyId,
|
||||
});
|
||||
const { data: session } = useQuery({
|
||||
queryKey: queryKeys.auth.session,
|
||||
queryFn: () => authApi.getSession(),
|
||||
});
|
||||
|
||||
const { data: liveRuns } = useQuery({
|
||||
queryKey: queryKeys.liveRuns(selectedCompanyId!),
|
||||
|
|
@ -71,8 +55,14 @@ export function SidebarAgents() {
|
|||
const filtered = (agents ?? []).filter(
|
||||
(a: Agent) => a.status !== "terminated"
|
||||
);
|
||||
return sortByHierarchy(filtered);
|
||||
return filtered;
|
||||
}, [agents]);
|
||||
const currentUserId = session?.user?.id ?? session?.session?.userId ?? null;
|
||||
const { orderedAgents } = useAgentOrder({
|
||||
agents: visibleAgents,
|
||||
companyId: selectedCompanyId,
|
||||
userId: currentUserId,
|
||||
});
|
||||
|
||||
const agentMatch = location.pathname.match(/^\/(?:[^/]+\/)?agents\/([^/]+)(?:\/([^/]+))?/);
|
||||
const activeAgentId = agentMatch?.[1] ?? null;
|
||||
|
|
@ -109,7 +99,7 @@ export function SidebarAgents() {
|
|||
|
||||
<CollapsibleContent>
|
||||
<div className="flex flex-col gap-0.5 mt-0.5">
|
||||
{visibleAgents.map((agent: Agent) => {
|
||||
{orderedAgents.map((agent: Agent) => {
|
||||
const runCount = liveCountByAgent.get(agent.id) ?? 0;
|
||||
return (
|
||||
<NavLink
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue