Remove the experimental workspace toggle
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -17,7 +17,6 @@ import { PriorityIcon } from "./PriorityIcon";
|
|||||||
import { Identity } from "./Identity";
|
import { Identity } from "./Identity";
|
||||||
import { formatDate, cn, projectUrl } from "../lib/utils";
|
import { formatDate, cn, projectUrl } from "../lib/utils";
|
||||||
import { timeAgo } from "../lib/timeAgo";
|
import { timeAgo } from "../lib/timeAgo";
|
||||||
import { useExperimentalWorkspacesEnabled } from "../lib/experimentalSettings";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||||
import { User, Hexagon, ArrowUpRight, Tag, Plus, Trash2 } from "lucide-react";
|
import { User, Hexagon, ArrowUpRight, Tag, Plus, Trash2 } from "lucide-react";
|
||||||
@@ -134,7 +133,6 @@ function PropertyPicker({
|
|||||||
|
|
||||||
export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProps) {
|
export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProps) {
|
||||||
const { selectedCompanyId } = useCompany();
|
const { selectedCompanyId } = useCompany();
|
||||||
const { enabled: showExperimentalWorkspaceUi } = useExperimentalWorkspacesEnabled();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const companyId = issue.companyId ?? selectedCompanyId;
|
const companyId = issue.companyId ?? selectedCompanyId;
|
||||||
const [assigneeOpen, setAssigneeOpen] = useState(false);
|
const [assigneeOpen, setAssigneeOpen] = useState(false);
|
||||||
@@ -219,11 +217,8 @@ export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProp
|
|||||||
const currentProject = issue.projectId
|
const currentProject = issue.projectId
|
||||||
? orderedProjects.find((project) => project.id === issue.projectId) ?? null
|
? orderedProjects.find((project) => project.id === issue.projectId) ?? null
|
||||||
: null;
|
: null;
|
||||||
const currentProjectExecutionWorkspacePolicy = showExperimentalWorkspaceUi
|
const currentProjectExecutionWorkspacePolicy = currentProject?.executionWorkspacePolicy ?? null;
|
||||||
? currentProject?.executionWorkspacePolicy ?? null
|
|
||||||
: null;
|
|
||||||
const currentProjectSupportsExecutionWorkspace = Boolean(currentProjectExecutionWorkspacePolicy?.enabled);
|
const currentProjectSupportsExecutionWorkspace = Boolean(currentProjectExecutionWorkspacePolicy?.enabled);
|
||||||
const currentProjectWorkspaces = currentProject?.workspaces ?? [];
|
|
||||||
const currentExecutionWorkspaceSelection =
|
const currentExecutionWorkspaceSelection =
|
||||||
issue.executionWorkspacePreference
|
issue.executionWorkspacePreference
|
||||||
?? issue.executionWorkspaceSettings?.mode
|
?? issue.executionWorkspaceSettings?.mode
|
||||||
@@ -240,7 +235,7 @@ export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProp
|
|||||||
projectWorkspaceId: issue.projectWorkspaceId ?? undefined,
|
projectWorkspaceId: issue.projectWorkspaceId ?? undefined,
|
||||||
reuseEligible: true,
|
reuseEligible: true,
|
||||||
}),
|
}),
|
||||||
enabled: Boolean(companyId) && showExperimentalWorkspaceUi && Boolean(issue.projectId),
|
enabled: Boolean(companyId) && Boolean(issue.projectId),
|
||||||
});
|
});
|
||||||
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
||||||
(workspace) => workspace.id === issue.executionWorkspaceId,
|
(workspace) => workspace.id === issue.executionWorkspaceId,
|
||||||
@@ -509,10 +504,10 @@ export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProp
|
|||||||
const defaultMode = defaultExecutionWorkspaceModeForProject(p);
|
const defaultMode = defaultExecutionWorkspaceModeForProject(p);
|
||||||
onUpdate({
|
onUpdate({
|
||||||
projectId: p.id,
|
projectId: p.id,
|
||||||
projectWorkspaceId: showExperimentalWorkspaceUi ? defaultProjectWorkspaceIdForProject(p) : null,
|
projectWorkspaceId: defaultProjectWorkspaceIdForProject(p),
|
||||||
executionWorkspaceId: null,
|
executionWorkspaceId: null,
|
||||||
executionWorkspacePreference: showExperimentalWorkspaceUi ? defaultMode : null,
|
executionWorkspacePreference: defaultMode,
|
||||||
executionWorkspaceSettings: showExperimentalWorkspaceUi && p.executionWorkspacePolicy?.enabled
|
executionWorkspaceSettings: p.executionWorkspacePolicy?.enabled
|
||||||
? { mode: defaultMode }
|
? { mode: defaultMode }
|
||||||
: null,
|
: null,
|
||||||
});
|
});
|
||||||
@@ -602,28 +597,7 @@ export function IssueProperties({ issue, onUpdate, inline }: IssuePropertiesProp
|
|||||||
{projectContent}
|
{projectContent}
|
||||||
</PropertyPicker>
|
</PropertyPicker>
|
||||||
|
|
||||||
{showExperimentalWorkspaceUi && currentProjectWorkspaces.length > 0 && (
|
{currentProjectSupportsExecutionWorkspace && (
|
||||||
<PropertyRow label="Codebase">
|
|
||||||
<select
|
|
||||||
className="w-full rounded border border-border bg-transparent px-2 py-1.5 text-xs outline-none"
|
|
||||||
value={issue.projectWorkspaceId ?? ""}
|
|
||||||
onChange={(e) =>
|
|
||||||
onUpdate({
|
|
||||||
projectWorkspaceId: e.target.value || null,
|
|
||||||
executionWorkspaceId: null,
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{currentProjectWorkspaces.map((workspace) => (
|
|
||||||
<option key={workspace.id} value={workspace.id}>
|
|
||||||
{workspace.name}
|
|
||||||
{workspace.isPrimary ? " (default)" : ""}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</PropertyRow>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{showExperimentalWorkspaceUi && currentProjectSupportsExecutionWorkspace && (
|
|
||||||
<PropertyRow label="Workspace">
|
<PropertyRow label="Workspace">
|
||||||
<div className="w-full space-y-2">
|
<div className="w-full space-y-2">
|
||||||
<select
|
<select
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ import { issueStatusText, issueStatusTextDefault, priorityColor, priorityColorDe
|
|||||||
import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor";
|
import { MarkdownEditor, type MarkdownEditorRef, type MentionOption } from "./MarkdownEditor";
|
||||||
import { AgentIcon } from "./AgentIconPicker";
|
import { AgentIcon } from "./AgentIconPicker";
|
||||||
import { InlineEntitySelector, type InlineEntityOption } from "./InlineEntitySelector";
|
import { InlineEntitySelector, type InlineEntityOption } from "./InlineEntitySelector";
|
||||||
import { useExperimentalWorkspacesEnabled } from "../lib/experimentalSettings";
|
|
||||||
|
|
||||||
const DRAFT_KEY = "paperclip:issue-draft";
|
const DRAFT_KEY = "paperclip:issue-draft";
|
||||||
const DEBOUNCE_MS = 800;
|
const DEBOUNCE_MS = 800;
|
||||||
@@ -280,7 +279,6 @@ function issueExecutionWorkspaceModeForExistingWorkspace(mode: string | null | u
|
|||||||
export function NewIssueDialog() {
|
export function NewIssueDialog() {
|
||||||
const { newIssueOpen, newIssueDefaults, closeNewIssue } = useDialog();
|
const { newIssueOpen, newIssueDefaults, closeNewIssue } = useDialog();
|
||||||
const { companies, selectedCompanyId, selectedCompany } = useCompany();
|
const { companies, selectedCompanyId, selectedCompany } = useCompany();
|
||||||
const { enabled: showExperimentalWorkspaceUi } = useExperimentalWorkspacesEnabled();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { pushToast } = useToast();
|
const { pushToast } = useToast();
|
||||||
const [title, setTitle] = useState("");
|
const [title, setTitle] = useState("");
|
||||||
@@ -339,7 +337,7 @@ export function NewIssueDialog() {
|
|||||||
projectWorkspaceId: projectWorkspaceId || undefined,
|
projectWorkspaceId: projectWorkspaceId || undefined,
|
||||||
reuseEligible: true,
|
reuseEligible: true,
|
||||||
}),
|
}),
|
||||||
enabled: Boolean(effectiveCompanyId) && newIssueOpen && showExperimentalWorkspaceUi && Boolean(projectId),
|
enabled: Boolean(effectiveCompanyId) && newIssueOpen && Boolean(projectId),
|
||||||
});
|
});
|
||||||
const { data: session } = useQuery({
|
const { data: session } = useQuery({
|
||||||
queryKey: queryKeys.auth.session,
|
queryKey: queryKeys.auth.session,
|
||||||
@@ -639,9 +637,7 @@ export function NewIssueDialog() {
|
|||||||
chrome: assigneeChrome,
|
chrome: assigneeChrome,
|
||||||
});
|
});
|
||||||
const selectedProject = orderedProjects.find((project) => project.id === projectId);
|
const selectedProject = orderedProjects.find((project) => project.id === projectId);
|
||||||
const executionWorkspacePolicy = showExperimentalWorkspaceUi
|
const executionWorkspacePolicy = selectedProject?.executionWorkspacePolicy ?? null;
|
||||||
? selectedProject?.executionWorkspacePolicy
|
|
||||||
: null;
|
|
||||||
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
||||||
(workspace) => workspace.id === selectedExecutionWorkspaceId,
|
(workspace) => workspace.id === selectedExecutionWorkspaceId,
|
||||||
);
|
);
|
||||||
@@ -749,10 +745,7 @@ export function NewIssueDialog() {
|
|||||||
? (agents ?? []).find((a) => a.id === selectedAssigneeAgentId)
|
? (agents ?? []).find((a) => a.id === selectedAssigneeAgentId)
|
||||||
: null;
|
: null;
|
||||||
const currentProject = orderedProjects.find((project) => project.id === projectId);
|
const currentProject = orderedProjects.find((project) => project.id === projectId);
|
||||||
const currentProjectWorkspaces = currentProject?.workspaces ?? [];
|
const currentProjectExecutionWorkspacePolicy = currentProject?.executionWorkspacePolicy ?? null;
|
||||||
const currentProjectExecutionWorkspacePolicy = showExperimentalWorkspaceUi
|
|
||||||
? currentProject?.executionWorkspacePolicy ?? null
|
|
||||||
: null;
|
|
||||||
const currentProjectSupportsExecutionWorkspace = Boolean(currentProjectExecutionWorkspacePolicy?.enabled);
|
const currentProjectSupportsExecutionWorkspace = Boolean(currentProjectExecutionWorkspacePolicy?.enabled);
|
||||||
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
const selectedReusableExecutionWorkspace = (reusableExecutionWorkspaces ?? []).find(
|
||||||
(workspace) => workspace.id === selectedExecutionWorkspaceId,
|
(workspace) => workspace.id === selectedExecutionWorkspaceId,
|
||||||
@@ -822,7 +815,7 @@ export function NewIssueDialog() {
|
|||||||
setProjectWorkspaceId(defaultProjectWorkspaceIdForProject(project));
|
setProjectWorkspaceId(defaultProjectWorkspaceIdForProject(project));
|
||||||
setExecutionWorkspaceMode(defaultExecutionWorkspaceModeForProject(project));
|
setExecutionWorkspaceMode(defaultExecutionWorkspaceModeForProject(project));
|
||||||
setSelectedExecutionWorkspaceId("");
|
setSelectedExecutionWorkspaceId("");
|
||||||
}, [newIssueOpen, orderedProjects, projectId, showExperimentalWorkspaceUi]);
|
}, [newIssueOpen, orderedProjects, projectId]);
|
||||||
const modelOverrideOptions = useMemo<InlineEntityOption[]>(
|
const modelOverrideOptions = useMemo<InlineEntityOption[]>(
|
||||||
() => {
|
() => {
|
||||||
return [...(assigneeAdapterModels ?? [])]
|
return [...(assigneeAdapterModels ?? [])]
|
||||||
@@ -1102,29 +1095,8 @@ export function NewIssueDialog() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{showExperimentalWorkspaceUi && currentProject && (
|
{currentProject && (
|
||||||
<div className="px-4 pb-2 shrink-0 space-y-2">
|
<div className="px-4 pb-2 shrink-0 space-y-2">
|
||||||
{currentProjectWorkspaces.length > 0 && (
|
|
||||||
<div className="rounded-md border border-border px-3 py-2 space-y-1.5">
|
|
||||||
<div className="text-xs font-medium">Codebase</div>
|
|
||||||
<div className="text-[11px] text-muted-foreground">
|
|
||||||
Choose which project workspace this issue should use.
|
|
||||||
</div>
|
|
||||||
<select
|
|
||||||
className="w-full rounded border border-border bg-transparent px-2 py-1.5 text-xs outline-none"
|
|
||||||
value={projectWorkspaceId}
|
|
||||||
onChange={(e) => setProjectWorkspaceId(e.target.value)}
|
|
||||||
>
|
|
||||||
{currentProjectWorkspaces.map((workspace) => (
|
|
||||||
<option key={workspace.id} value={workspace.id}>
|
|
||||||
{workspace.name}
|
|
||||||
{workspace.isPrimary ? " (default)" : ""}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{currentProjectSupportsExecutionWorkspace && (
|
{currentProjectSupportsExecutionWorkspace && (
|
||||||
<div className="rounded-md border border-border px-3 py-2 space-y-1.5">
|
<div className="rounded-md border border-border px-3 py-2 space-y-1.5">
|
||||||
<div className="text-xs font-medium">Execution workspace</div>
|
<div className="text-xs font-medium">Execution workspace</div>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { AlertCircle, Archive, ArchiveRestore, Check, ExternalLink, Github, Load
|
|||||||
import { ChoosePathButton } from "./PathInstructionsModal";
|
import { ChoosePathButton } from "./PathInstructionsModal";
|
||||||
import { DraftInput } from "./agent-config-primitives";
|
import { DraftInput } from "./agent-config-primitives";
|
||||||
import { InlineEditor } from "./InlineEditor";
|
import { InlineEditor } from "./InlineEditor";
|
||||||
import { useExperimentalWorkspacesEnabled } from "../lib/experimentalSettings";
|
|
||||||
|
|
||||||
const PROJECT_STATUSES = [
|
const PROJECT_STATUSES = [
|
||||||
{ value: "backlog", label: "Backlog" },
|
{ value: "backlog", label: "Backlog" },
|
||||||
@@ -152,7 +151,6 @@ function ProjectStatusPicker({ status, onChange }: { status: string; onChange: (
|
|||||||
|
|
||||||
export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSaveState, onArchive, archivePending }: ProjectPropertiesProps) {
|
export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSaveState, onArchive, archivePending }: ProjectPropertiesProps) {
|
||||||
const { selectedCompanyId } = useCompany();
|
const { selectedCompanyId } = useCompany();
|
||||||
const { enabled: showExperimentalWorkspaceUi } = useExperimentalWorkspacesEnabled();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [goalOpen, setGoalOpen] = useState(false);
|
const [goalOpen, setGoalOpen] = useState(false);
|
||||||
const [executionWorkspaceAdvancedOpen, setExecutionWorkspaceAdvancedOpen] = useState(false);
|
const [executionWorkspaceAdvancedOpen, setExecutionWorkspaceAdvancedOpen] = useState(false);
|
||||||
@@ -749,9 +747,6 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* PAP-525: workspace UI gated by useExperimentalWorkspacesEnabled() */}
|
|
||||||
{showExperimentalWorkspaceUi && (
|
|
||||||
<>
|
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
|
|
||||||
<div className="py-1.5 space-y-2">
|
<div className="py-1.5 space-y-2">
|
||||||
@@ -990,8 +985,6 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
|
|
||||||
const WORKSPACES_KEY = "paperclip:experimental:workspaces";
|
|
||||||
|
|
||||||
export function loadExperimentalWorkspacesEnabled(): boolean {
|
|
||||||
if (typeof window === "undefined") return false;
|
|
||||||
return window.localStorage.getItem(WORKSPACES_KEY) === "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
export function saveExperimentalWorkspacesEnabled(enabled: boolean) {
|
|
||||||
if (typeof window === "undefined") return;
|
|
||||||
window.localStorage.setItem(WORKSPACES_KEY, enabled ? "true" : "false");
|
|
||||||
window.dispatchEvent(new CustomEvent("paperclip:experimental:workspaces", { detail: enabled }));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useExperimentalWorkspacesEnabled() {
|
|
||||||
const [enabled, setEnabled] = useState(loadExperimentalWorkspacesEnabled);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const handleStorage = (event: StorageEvent) => {
|
|
||||||
if (event.key && event.key !== WORKSPACES_KEY) return;
|
|
||||||
setEnabled(loadExperimentalWorkspacesEnabled());
|
|
||||||
};
|
|
||||||
const handleCustom = () => setEnabled(loadExperimentalWorkspacesEnabled());
|
|
||||||
window.addEventListener("storage", handleStorage);
|
|
||||||
window.addEventListener("paperclip:experimental:workspaces", handleCustom as EventListener);
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener("storage", handleStorage);
|
|
||||||
window.removeEventListener("paperclip:experimental:workspaces", handleCustom as EventListener);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const update = (next: boolean) => {
|
|
||||||
saveExperimentalWorkspacesEnabled(next);
|
|
||||||
setEnabled(next);
|
|
||||||
};
|
|
||||||
|
|
||||||
return { enabled, setEnabled: update };
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { queryKeys } from "../lib/queryKeys";
|
import { queryKeys } from "../lib/queryKeys";
|
||||||
import { formatDateTime, relativeTime } from "../lib/utils";
|
import { formatDateTime, relativeTime } from "../lib/utils";
|
||||||
import { useExperimentalWorkspacesEnabled } from "../lib/experimentalSettings";
|
|
||||||
|
|
||||||
function asRecord(value: unknown): Record<string, unknown> | null {
|
function asRecord(value: unknown): Record<string, unknown> | null {
|
||||||
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
||||||
@@ -31,7 +30,6 @@ export function InstanceSettings() {
|
|||||||
const { setBreadcrumbs } = useBreadcrumbs();
|
const { setBreadcrumbs } = useBreadcrumbs();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const [actionError, setActionError] = useState<string | null>(null);
|
const [actionError, setActionError] = useState<string | null>(null);
|
||||||
const { enabled: workspacesEnabled, setEnabled: setWorkspacesEnabled } = useExperimentalWorkspacesEnabled();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setBreadcrumbs([
|
setBreadcrumbs([
|
||||||
@@ -112,34 +110,6 @@ export function InstanceSettings() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-5xl space-y-6">
|
<div className="max-w-5xl space-y-6">
|
||||||
<div className="space-y-3 rounded-lg border border-border bg-card p-4">
|
|
||||||
<div className="space-y-1">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Settings className="h-4 w-4 text-muted-foreground" />
|
|
||||||
<h2 className="text-sm font-semibold">Experimental</h2>
|
|
||||||
</div>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
UI-only feature flags for in-progress product surfaces.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center justify-between rounded-md border border-border px-3 py-2">
|
|
||||||
<div className="space-y-0.5">
|
|
||||||
<div className="text-sm font-medium">Workspaces</div>
|
|
||||||
<div className="text-xs text-muted-foreground">
|
|
||||||
Show workspace, execution workspace, and work product controls in project and issue UI.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant={workspacesEnabled ? "default" : "outline"}
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setWorkspacesEnabled(!workspacesEnabled)}
|
|
||||||
>
|
|
||||||
{workspacesEnabled ? "Enabled" : "Disabled"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Settings className="h-5 w-5 text-muted-foreground" />
|
<Settings className="h-5 w-5 text-muted-foreground" />
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { useCompany } from "../context/CompanyContext";
|
|||||||
import { usePanel } from "../context/PanelContext";
|
import { usePanel } from "../context/PanelContext";
|
||||||
import { useBreadcrumbs } from "../context/BreadcrumbContext";
|
import { useBreadcrumbs } from "../context/BreadcrumbContext";
|
||||||
import { queryKeys } from "../lib/queryKeys";
|
import { queryKeys } from "../lib/queryKeys";
|
||||||
import { useExperimentalWorkspacesEnabled } from "../lib/experimentalSettings";
|
|
||||||
import { readIssueDetailBreadcrumb } from "../lib/issueDetailBreadcrumb";
|
import { readIssueDetailBreadcrumb } from "../lib/issueDetailBreadcrumb";
|
||||||
import { useProjectOrder } from "../hooks/useProjectOrder";
|
import { useProjectOrder } from "../hooks/useProjectOrder";
|
||||||
import { relativeTime, cn, formatTokens, visibleRunCostUsd } from "../lib/utils";
|
import { relativeTime, cn, formatTokens, visibleRunCostUsd } from "../lib/utils";
|
||||||
@@ -216,7 +215,6 @@ function ActorIdentity({ evt, agentMap }: { evt: ActivityEvent; agentMap: Map<st
|
|||||||
export function IssueDetail() {
|
export function IssueDetail() {
|
||||||
const { issueId } = useParams<{ issueId: string }>();
|
const { issueId } = useParams<{ issueId: string }>();
|
||||||
const { selectedCompanyId } = useCompany();
|
const { selectedCompanyId } = useCompany();
|
||||||
const { enabled: experimentalWorkspacesEnabled } = useExperimentalWorkspacesEnabled();
|
|
||||||
const { openPanel, closePanel, panelVisible, setPanelVisible } = usePanel();
|
const { openPanel, closePanel, panelVisible, setPanelVisible } = usePanel();
|
||||||
const { setBreadcrumbs } = useBreadcrumbs();
|
const { setBreadcrumbs } = useBreadcrumbs();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -662,10 +660,7 @@ export function IssueDetail() {
|
|||||||
// Ancestors are returned oldest-first from the server (root at end, immediate parent at start)
|
// Ancestors are returned oldest-first from the server (root at end, immediate parent at start)
|
||||||
const ancestors = issue.ancestors ?? [];
|
const ancestors = issue.ancestors ?? [];
|
||||||
const workProducts = issue.workProducts ?? [];
|
const workProducts = issue.workProducts ?? [];
|
||||||
const showOutputsTab =
|
const showOutputsTab = Boolean(issue.currentExecutionWorkspace) || workProducts.length > 0;
|
||||||
experimentalWorkspacesEnabled ||
|
|
||||||
Boolean(issue.currentExecutionWorkspace) ||
|
|
||||||
workProducts.length > 0;
|
|
||||||
|
|
||||||
const handleFilePicked = async (evt: ChangeEvent<HTMLInputElement>) => {
|
const handleFilePicked = async (evt: ChangeEvent<HTMLInputElement>) => {
|
||||||
const files = evt.target.files;
|
const files = evt.target.files;
|
||||||
|
|||||||
Reference in New Issue
Block a user