refactor: unify StartToolModal — remove inline duplicate from workspace detail
- Delete inline hardcoded StartToolModal from workspace-detail.tsx - Import shared StartToolModal that fetches real tool types from API - Pass workspace object to ToolsTab so shared modal gets proper context - onStart handler passes optional configProfileId through to useWorkspaceInstances.create() Quality gates: tsc --noEmit clean
This commit is contained in:
@@ -76,9 +76,7 @@ export function StartToolModal({
|
|||||||
{status === "loading" && (
|
{status === "loading" && (
|
||||||
<span className="muted">Loading tools...</span>
|
<span className="muted">Loading tools...</span>
|
||||||
)}
|
)}
|
||||||
{loadError && (
|
{loadError && <span className="error-text">{loadError}</span>}
|
||||||
<span className="error-text">{loadError}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="form-group">
|
<div className="form-group">
|
||||||
<label htmlFor="config-profile">Config Profile (optional)</label>
|
<label htmlFor="config-profile">Config Profile (optional)</label>
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import { useWorkspaceFiles } from "../hooks/use-workspace-files";
|
|||||||
import { useWorkspaceGit } from "../hooks/use-workspace-git";
|
import { useWorkspaceGit } from "../hooks/use-workspace-git";
|
||||||
import { useWorkspaceInstances } from "../hooks/use-workspace-instances";
|
import { useWorkspaceInstances } from "../hooks/use-workspace-instances";
|
||||||
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
import { useMobileViewport } from "../hooks/use-mobile-viewport";
|
||||||
|
import { StartToolModal } from "../components/start-tool-modal";
|
||||||
import type { FileEntry } from "../api/workspace-files";
|
import type { FileEntry } from "../api/workspace-files";
|
||||||
|
import type { Workspace } from "../types/workspace";
|
||||||
|
|
||||||
type Tab = "files" | "git" | "tools" | "settings";
|
type Tab = "files" | "git" | "tools" | "settings";
|
||||||
|
|
||||||
@@ -40,7 +42,7 @@ export function WorkspaceDetailPage() {
|
|||||||
<div className="workspace-content">
|
<div className="workspace-content">
|
||||||
{activeTab === "files" && <FilesTab workspaceId={workspace.id} />}
|
{activeTab === "files" && <FilesTab workspaceId={workspace.id} />}
|
||||||
{activeTab === "git" && <GitTab workspaceId={workspace.id} />}
|
{activeTab === "git" && <GitTab workspaceId={workspace.id} />}
|
||||||
{activeTab === "tools" && <ToolsTab workspaceId={workspace.id} />}
|
{activeTab === "tools" && <ToolsTab workspace={workspace} />}
|
||||||
{activeTab === "settings" && <SettingsTab workspace={workspace} />}
|
{activeTab === "settings" && <SettingsTab workspace={workspace} />}
|
||||||
</div>
|
</div>
|
||||||
{isMobile && <MobileTabBar active={activeTab} onChange={setActiveTab} />}
|
{isMobile && <MobileTabBar active={activeTab} onChange={setActiveTab} />}
|
||||||
@@ -309,8 +311,8 @@ function GitTab({ workspaceId }: { workspaceId: string }) {
|
|||||||
|
|
||||||
/* ─── Tools Tab ─── */
|
/* ─── Tools Tab ─── */
|
||||||
|
|
||||||
function ToolsTab({ workspaceId }: { workspaceId: string }) {
|
function ToolsTab({ workspace }: { workspace: Workspace }) {
|
||||||
const { instances, loading, create } = useWorkspaceInstances(workspaceId);
|
const { instances, loading, create } = useWorkspaceInstances(workspace.id);
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -360,9 +362,10 @@ function ToolsTab({ workspaceId }: { workspaceId: string }) {
|
|||||||
)}
|
)}
|
||||||
{showModal && (
|
{showModal && (
|
||||||
<StartToolModal
|
<StartToolModal
|
||||||
|
workspace={workspace}
|
||||||
onClose={() => setShowModal(false)}
|
onClose={() => setShowModal(false)}
|
||||||
onStart={async (toolTypeId: string) => {
|
onStart={async (toolTypeId, configProfileId) => {
|
||||||
await create(toolTypeId);
|
await create(toolTypeId, undefined, configProfileId);
|
||||||
setShowModal(false);
|
setShowModal(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -376,14 +379,7 @@ function ToolsTab({ workspaceId }: { workspaceId: string }) {
|
|||||||
function SettingsTab({
|
function SettingsTab({
|
||||||
workspace,
|
workspace,
|
||||||
}: {
|
}: {
|
||||||
workspace: {
|
workspace: Workspace;
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
branch: string;
|
|
||||||
path: string;
|
|
||||||
status: string;
|
|
||||||
created_at: string;
|
|
||||||
};
|
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div className="settings-tab">
|
<div className="settings-tab">
|
||||||
@@ -416,56 +412,4 @@ function SettingsTab({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ─── Start Tool Modal ─── */
|
|
||||||
|
|
||||||
function StartToolModal({
|
|
||||||
onClose,
|
|
||||||
onStart,
|
|
||||||
}: {
|
|
||||||
onClose: () => void;
|
|
||||||
onStart: (toolTypeId: string) => Promise<void>;
|
|
||||||
}) {
|
|
||||||
const [toolTypeId, setToolTypeId] = useState("");
|
|
||||||
const [submitting, setSubmitting] = useState(false);
|
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!toolTypeId) return;
|
|
||||||
setSubmitting(true);
|
|
||||||
try {
|
|
||||||
await onStart(toolTypeId);
|
|
||||||
} finally {
|
|
||||||
setSubmitting(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="modal-overlay" onClick={onClose}>
|
|
||||||
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
|
||||||
<h3>Start Tool</h3>
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<div className="form-group">
|
|
||||||
<label>Tool Type</label>
|
|
||||||
<select
|
|
||||||
value={toolTypeId}
|
|
||||||
onChange={(e) => setToolTypeId(e.target.value)}
|
|
||||||
>
|
|
||||||
<option value="">Select...</option>
|
|
||||||
<option value="code-server">Code Server</option>
|
|
||||||
<option value="jupyter-notebook">Jupyter Notebook</option>
|
|
||||||
<option value="terminal">Terminal</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div className="form-actions">
|
|
||||||
<button type="button" onClick={onClose} disabled={submitting}>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
<button type="submit" disabled={!toolTypeId || submitting}>
|
|
||||||
{submitting ? "Starting..." : "Start"}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user