feat: launch scripts
ci-front / build (push) Successful in 2m19s

This commit is contained in:
nikita
2026-04-05 06:54:33 +03:00
parent d6512d6c97
commit 2bc3da21fd
11 changed files with 774 additions and 107 deletions
+86 -44
View File
@@ -2,7 +2,10 @@ import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { FiEdit3, FiPlay } from "react-icons/fi";
import { FaSpinner } from "react-icons/fa";
import { FilePicker, useFilePickerStore } from "../modules/ide";
import { FilePicker } from "../modules/ide";
import { RunScriptModal } from "../modules/ide/components/RunScriptModal";
import { TerminalOutput } from "../modules/terminal";
import { useTerminalStore } from "../modules/terminal/store/useTerminalStore";
import type { FileNode } from "../modules/ide";
import { scriptsApi } from "../modules/ide/api/scripts.api";
@@ -40,11 +43,15 @@ const convertTreeToFileNode = (data: any[]): FileNode => {
export const TemplatesPage = () => {
const navigate = useNavigate();
const selectedPaths = useFilePickerStore((s) => s.selectedPaths);
const runningScripts = useFilePickerStore((s) => s.runningScripts);
const runScript = useFilePickerStore((s) => s.runScript);
const [files, setFiles] = useState<FileNode | null>(null);
const [loading, setLoading] = useState(true);
const [runModal, setRunModal] = useState<{
scriptPath: string;
scriptId: number;
} | null>(null);
const terminalOpen = useTerminalStore((s) => s.isOpen);
const [terminalHeight] = useState(300);
useEffect(() => {
scriptsApi
@@ -59,18 +66,22 @@ export const TemplatesPage = () => {
.finally(() => setLoading(false));
}, []);
const handleRun = async (path: string) => {
await runScript(path);
const handleRun = (path: string, id?: number) => {
if (!id) {
console.warn("Script ID not found for:", path);
return;
}
setRunModal({ scriptPath: path, scriptId: id });
};
const runningCount = runningScripts.size;
return (
<div
style={{
height: "100vh",
position: "relative",
backgroundColor: "var(--bg-primary)",
display: "flex",
flexDirection: "column",
}}
>
{/* Floating header */}
@@ -85,24 +96,6 @@ export const TemplatesPage = () => {
gap: "16px",
}}
>
{/* Running scripts counter */}
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
padding: "6px 12px",
backgroundColor: "var(--card-bg)",
borderRadius: "4px",
border: "1px solid var(--border)",
}}
>
<FiPlay size={13} color="#61c454" />
<span style={{ fontSize: "12px", color: "var(--text-secondary)" }}>
{runningCount} script{runningCount !== 1 ? "s" : ""} running
</span>
</div>
{/* Open in Editor button */}
<button
onClick={() => navigate("/ide")}
@@ -132,29 +125,78 @@ export const TemplatesPage = () => {
</button>
</div>
{/* File Picker */}
<div style={{ height: "100%", overflow: "hidden" }}>
{loading ? (
<div
style={{
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<FaSpinner
size={24}
{/* File Picker + Terminal */}
<div
style={{
flex: 1,
display: "flex",
flexDirection: "column",
overflow: "hidden",
}}
>
<div style={{ flex: 1, overflow: "hidden" }}>
{loading ? (
<div
style={{
color: "var(--accent)",
animation: "spin 1s linear infinite",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<FaSpinner
size={24}
style={{
color: "var(--accent)",
animation: "spin 1s linear infinite",
}}
/>
</div>
) : files ? (
<FilePicker
files={files}
onRun={(path) => {
// Находим ID скрипта по пути
const findNodeById = (
node: FileNode,
p: string,
): FileNode | null => {
if (node.path === p) return node;
if (node.children) {
for (const child of node.children) {
const found = findNodeById(child, p);
if (found) return found;
}
}
return null;
};
const node = findNodeById(files, path);
if (node?.id) {
handleRun(path, node.id);
} else {
console.warn("Script ID not found for path:", path);
}
}}
/>
) : null}
</div>
{/* Terminal */}
{terminalOpen && (
<div style={{ height: `${terminalHeight}px`, flexShrink: 0 }}>
<TerminalOutput />
</div>
) : files ? (
<FilePicker files={files} onRun={handleRun} />
) : null}
)}
</div>
{/* Run Script Modal */}
{runModal && (
<RunScriptModal
scriptPath={runModal.scriptPath}
scriptId={runModal.scriptId}
onClose={() => setRunModal(null)}
/>
)}
</div>
);
};