UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

106 lines (105 loc) 3.86 kB
import { jsxs, Fragment, jsx } from "react/jsx-runtime"; import { useState } from "react"; import { Button } from "../components/button.js"; import { Icon } from "../data/Icon.js"; import { Modal } from "../overlay/Modal.js"; import { CommandForm } from "./CommandForm.js"; import { CommandOutput } from "./CommandOutput.js"; import { InlineError } from "./InlineError.js"; function OperationActionDialog({ operation, client, initialValues, label, defaultAccept = "application/clicky+json", onNavigateAction }) { const [open, setOpen] = useState(false); const [isExecuting, setIsExecuting] = useState(false); const [response, setResponse] = useState(null); const [error, setError] = useState(null); async function handleExecute(params, headers) { if (onNavigateAction) { const href = hrefForOperationAction(operation.path, params); if (!href) return; const separator = href.includes("?") ? "&" : "?"; onNavigateAction(`${href}${separator}autoRun=1`); return; } setIsExecuting(true); setError(null); setResponse(null); try { const result = await client.executeCommand(operation.path, operation.method, params, headers); setResponse(result); } catch (err) { setError(err); } finally { setIsExecuting(false); } } return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(true), children: [ /* @__PURE__ */ jsx(Icon, { name: "codicon:play" }), label ] }), /* @__PURE__ */ jsx(Modal, { open, onClose: () => setOpen(false), title: label, size: "lg", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [ /* @__PURE__ */ jsx( CommandForm, { parameters: operation.operation.parameters ?? [], onExecute: handleExecute, isPending: isExecuting, method: operation.method, path: operation.path, accept: defaultAccept, initialValues } ), error ? /* @__PURE__ */ jsx(InlineError, { title: `Failed to execute ${operation.path}`, error }) : response ? /* @__PURE__ */ jsx(CommandOutput, { response }) : null ] }) }) ] }); } function hrefForOperationAction(path, params) { const nextParams = { ...params }; const args = parseArgsParam(params.args); let route = apiPathToRoutePath(path); for (const [index, name] of pathParamNames(path).entries()) { const value = nextParams[name] || args[index]; if (!value) return void 0; route = route.replace(`:${name}`, encodeURIComponent(value)); delete nextParams[name]; if (!nextParams[name] && value === args[index]) { delete nextParams.args; } } const search = new URLSearchParams(); for (const [key, value] of Object.entries(nextParams)) { if (value && key !== "autoRun") search.set(key, value); } const query = search.toString(); return query ? `${route}?${query}` : route; } function apiPathToRoutePath(path) { const cliPath = path.trim().replace(/^\/api\/v1\/?/, "").replace(/^\/+/, "").replace(/\/+$/, ""); if (!cliPath) return "/"; return `/${cliPath.replace(/\{([^}]+)\}/g, ":$1")}`; } function pathParamNames(path) { return [...path.matchAll(/\{([^}]+)\}/g)].map((match) => match[1]).filter((name) => Boolean(name)); } function parseArgsParam(value) { if (!value) return []; const trimmed = value.trim(); if (!trimmed || trimmed === "[]" || trimmed.toLowerCase() === "null") return []; try { const parsed = JSON.parse(trimmed); if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean); } catch { } return trimmed.split(",").map((part) => part.trim()).filter(Boolean); } export { OperationActionDialog }; //# sourceMappingURL=OperationActionDialog.js.map