mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-20 12:30:38 +09:00
Merge remote-tracking branch 'public-gh/master' into paperclip-subissues
* public-gh/master: Drop lockfile from watcher change Tighten plugin dev file watching Fix plugin smoke example typecheck Fix plugin dev watcher and migration snapshot Clarify plugin authoring and external dev workflow Expand kitchen sink plugin demos fix: set AGENT_HOME env var for agent processes Add kitchen sink plugin example Simplify plugin runtime and cleanup lifecycle Add plugin framework and settings UI # Conflicts: # packages/db/src/migrations/meta/0029_snapshot.json # packages/db/src/migrations/meta/_journal.json
This commit is contained in:
commit
6e6d67372c
141 changed files with 47521 additions and 961 deletions
|
|
@ -26,6 +26,8 @@ import { StatusIcon } from "../components/StatusIcon";
|
|||
import { PriorityIcon } from "../components/PriorityIcon";
|
||||
import { StatusBadge } from "../components/StatusBadge";
|
||||
import { Identity } from "../components/Identity";
|
||||
import { PluginSlotMount, PluginSlotOutlet, usePluginSlots } from "@/plugins/slots";
|
||||
import { PluginLauncherOutlet } from "@/plugins/launchers";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
|
@ -244,6 +246,7 @@ export function IssueDetail() {
|
|||
queryFn: () => issuesApi.get(issueId!),
|
||||
enabled: !!issueId,
|
||||
});
|
||||
const resolvedCompanyId = issue?.companyId ?? selectedCompanyId;
|
||||
|
||||
const { data: comments } = useQuery({
|
||||
queryKey: queryKeys.issues.comments(issueId!),
|
||||
|
|
@ -333,6 +336,21 @@ export function IssueDetail() {
|
|||
companyId: selectedCompanyId,
|
||||
userId: currentUserId,
|
||||
});
|
||||
const { slots: issuePluginDetailSlots } = usePluginSlots({
|
||||
slotTypes: ["detailTab"],
|
||||
entityType: "issue",
|
||||
companyId: resolvedCompanyId,
|
||||
enabled: !!resolvedCompanyId,
|
||||
});
|
||||
const issuePluginTabItems = useMemo(
|
||||
() => issuePluginDetailSlots.map((slot) => ({
|
||||
value: `plugin:${slot.pluginKey}:${slot.id}`,
|
||||
label: slot.displayName,
|
||||
slot,
|
||||
})),
|
||||
[issuePluginDetailSlots],
|
||||
);
|
||||
const activePluginTab = issuePluginTabItems.find((item) => item.value === detailTab) ?? null;
|
||||
|
||||
const agentMap = useMemo(() => {
|
||||
const map = new Map<string, Agent>();
|
||||
|
|
@ -868,6 +886,47 @@ export function IssueDetail() {
|
|||
/>
|
||||
</div>
|
||||
|
||||
<PluginSlotOutlet
|
||||
slotTypes={["toolbarButton", "contextMenuItem"]}
|
||||
entityType="issue"
|
||||
context={{
|
||||
companyId: issue.companyId,
|
||||
projectId: issue.projectId ?? null,
|
||||
entityId: issue.id,
|
||||
entityType: "issue",
|
||||
}}
|
||||
className="flex flex-wrap gap-2"
|
||||
itemClassName="inline-flex"
|
||||
missingBehavior="placeholder"
|
||||
/>
|
||||
|
||||
<PluginLauncherOutlet
|
||||
placementZones={["toolbarButton"]}
|
||||
entityType="issue"
|
||||
context={{
|
||||
companyId: issue.companyId,
|
||||
projectId: issue.projectId ?? null,
|
||||
entityId: issue.id,
|
||||
entityType: "issue",
|
||||
}}
|
||||
className="flex flex-wrap gap-2"
|
||||
itemClassName="inline-flex"
|
||||
/>
|
||||
|
||||
<PluginSlotOutlet
|
||||
slotTypes={["taskDetailView"]}
|
||||
entityType="issue"
|
||||
context={{
|
||||
companyId: issue.companyId,
|
||||
projectId: issue.projectId ?? null,
|
||||
entityId: issue.id,
|
||||
entityType: "issue",
|
||||
}}
|
||||
className="space-y-3"
|
||||
itemClassName="rounded-lg border border-border p-3"
|
||||
missingBehavior="placeholder"
|
||||
/>
|
||||
|
||||
<IssueDocumentsSection
|
||||
issue={issue}
|
||||
canDeleteDocuments={Boolean(session?.user?.id)}
|
||||
|
|
@ -971,12 +1030,19 @@ export function IssueDetail() {
|
|||
<ActivityIcon className="h-3.5 w-3.5" />
|
||||
Activity
|
||||
</TabsTrigger>
|
||||
{issuePluginTabItems.map((item) => (
|
||||
<TabsTrigger key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="comments">
|
||||
<CommentThread
|
||||
comments={commentsWithRunMeta}
|
||||
linkedRuns={timelineRuns}
|
||||
companyId={issue.companyId}
|
||||
projectId={issue.projectId}
|
||||
issueStatus={issue.status}
|
||||
agentMap={agentMap}
|
||||
draftKey={`paperclip:issue-comment-draft:${issue.id}`}
|
||||
|
|
@ -1242,6 +1308,21 @@ export function IssueDetail() {
|
|||
</div>
|
||||
)}
|
||||
</TabsContent>
|
||||
|
||||
{activePluginTab && (
|
||||
<TabsContent value={activePluginTab.value}>
|
||||
<PluginSlotMount
|
||||
slot={activePluginTab.slot}
|
||||
context={{
|
||||
companyId: issue.companyId,
|
||||
projectId: issue.projectId ?? null,
|
||||
entityId: issue.id,
|
||||
entityType: "issue",
|
||||
}}
|
||||
missingBehavior="placeholder"
|
||||
/>
|
||||
</TabsContent>
|
||||
)}
|
||||
</Tabs>
|
||||
|
||||
{linkedApprovals && linkedApprovals.length > 0 && (
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue