feat: add script dry-run functionality and enhance script management
- Introduced a new dry-run endpoint for executing scripts without saving changes. - Implemented a dedicated ScriptDryRunPage for user interaction with dry-run functionality. - Enhanced ScriptsPage to support navigation to the dry-run feature. - Added LogViewer component for displaying logs during script execution. - Created ScriptEditPage for editing scripts with integrated dry-run capabilities. - Updated workflows to include new scripts for fetching and notifying data. - Improved overall user experience with better navigation and error handling.
This commit is contained in:
@@ -1,19 +1,20 @@
|
||||
import Editor from "@monaco-editor/react";
|
||||
import { useTheme } from "../theme.jsx";
|
||||
|
||||
export function CodeEditor({ language, value, onChange, height = "50vh" }) {
|
||||
export function CodeEditor({ language, value, onChange, height = "50vh", readOnly = false }) {
|
||||
const { theme } = useTheme();
|
||||
const isMobile = typeof window !== "undefined" && window.innerWidth < 768;
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden rounded-box border border-base-300">
|
||||
<div className="overflow-hidden rounded-box border border-base-300 h-full min-h-0">
|
||||
<Editor
|
||||
height={height}
|
||||
language={language}
|
||||
value={value}
|
||||
onChange={(v) => onChange(v ?? "")}
|
||||
onChange={readOnly ? undefined : (v) => onChange(v ?? "")}
|
||||
theme={theme === "dark" ? "vs-dark" : "light"}
|
||||
options={{
|
||||
readOnly,
|
||||
minimap: { enabled: !isMobile },
|
||||
lineNumbers: "on",
|
||||
tabSize: 2,
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { useState } from "react";
|
||||
import { levelName } from "../lib/format.jsx";
|
||||
|
||||
export function LogViewer({ logs = [], className = "" }) {
|
||||
const [wordWrap, setWordWrap] = useState(true);
|
||||
|
||||
return (
|
||||
<section className={`flex min-h-0 flex-col ${className}`}>
|
||||
<div className="mb-2 flex shrink-0 items-center justify-between gap-2">
|
||||
<h2 className="font-semibold text-sm">Logs</h2>
|
||||
<label className="label cursor-pointer gap-2 py-0">
|
||||
<span className="label-text text-sm">Word wrap</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="checkbox checkbox-sm"
|
||||
checked={wordWrap}
|
||||
onChange={(e) => setWordWrap(e.target.checked)}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
<div className="mockup-code min-h-0 flex-1 overflow-auto text-xs">
|
||||
{logs.length === 0 ? (
|
||||
<div className="flex gap-3 px-5 py-0.5 font-mono opacity-50">
|
||||
<span className="w-12 shrink-0 text-right">—</span>
|
||||
<span>no logs</span>
|
||||
</div>
|
||||
) : (
|
||||
logs.map((l, i) => (
|
||||
<div key={l.id ?? i} className="flex gap-3 px-5 py-0.5 font-mono">
|
||||
<span className="w-12 shrink-0 text-right opacity-50">
|
||||
{levelName(l.level)}
|
||||
</span>
|
||||
<span
|
||||
className={
|
||||
wordWrap
|
||||
? "min-w-0 flex-1 whitespace-pre-wrap break-words"
|
||||
: "whitespace-pre"
|
||||
}
|
||||
>
|
||||
{l.ts} {l.msg ?? ""}
|
||||
{l.payload ? ` ${JSON.stringify(l.payload)}` : ""}
|
||||
</span>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export function MermaidDiagram({ chart, scriptIds = {} }) {
|
||||
el.style.cursor = "pointer";
|
||||
el.setAttribute("title", script);
|
||||
el.addEventListener("click", () => {
|
||||
navigate(`/scripts?edit=${encodeURIComponent(script)}`);
|
||||
navigate(`/scripts/${encodeURIComponent(script)}/edit`);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user