import { useState } from "react";
import { LuChevronDown, LuCopy, LuGripVertical, LuTrash2 } from "react-icons/lu";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import cronstrue from "cronstrue";
import { namespacedPath, HTTP_METHODS, triggerDestinations } from "../../lib/workflow-doc.js";
import { CRON_CUSTOM, CRON_PRESETS, matchCronPreset, scheduleForPreset } from "../../lib/cron-presets.js";
import { FormInput, FormSelect } from "../FormControls.jsx";
import { AuthPicker } from "./AuthPicker.jsx";
export function TriggerCard(props) {
if (props.sortable === false) {
return ;
}
return ;
}
function TriggerCardSortable(props) {
const drag = useSortable({
id: props.trigger.uiId,
disabled: props.disabled,
});
return ;
}
function TriggerCardView({
trigger,
index,
owner,
onChange,
onRemove,
disabled,
auths = [],
pages = [],
workflows = [],
excludeFile,
sortable = true,
defaultExpanded = false,
drag,
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = drag ?? {
attributes: {},
listeners: {},
setNodeRef: undefined,
transform: null,
transition: undefined,
isDragging: false,
};
const style = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.6 : 1,
};
const type = trigger.type;
const [expanded, setExpanded] = useState(defaultExpanded);
const alertDestinations = triggerDestinations(workflows, { owner, excludeFile });
return (
{sortable !== false ? (
) : null}
{expanded ? (
<>
{type === "HTTP" ? (
) : null}
{type === "cron" ? (
) : null}
{type === "workflow" ? (
Other workflows can call this one with trigger-workflow.js.
No extra fields.
) : null}
{type !== "HTTP" && type !== "cron" && type !== "workflow" ? (
Unknown trigger type. Edit it in the YAML tab.
) : null}
>
) : null}
);
}
function triggerSummary(trigger, owner) {
const type = trigger?.type;
/** @type {string[]} */
const failureParts = [];
if (trigger.onConsecutiveFailures && trigger.onFailureWorkflow) {
failureParts.push(`onFailure@${trigger.onFailureWorkflow}`);
}
if (trigger.disableOnConsecutiveFailures) {
failureParts.push("auto-disable");
}
const failure = failureParts.length ? ` ยท ${failureParts.join(", ")}` : "";
if (type === "HTTP") {
return `${trigger.method || "POST"} ${namespacedPath(owner || "owner", trigger.path || "/")}${failure}`;
}
if (type === "cron") {
return `${trigger.schedule || ""}${failure}`;
}
if (type === "workflow") return "callable";
return "";
}
function typeLabel(type) {
if (type === "HTTP") return "HTTP";
if (type === "cron") return "Cron";
if (type === "workflow") return "Workflow";
return type || "Trigger";
}
function Field({ label, children, hint }) {
return (
{label ? {label} : null}
{children}
{hint ? {hint} : null}
);
}
function HttpFields({ trigger, owner, disabled, onChange, auths, pages, alertDestinations }) {
const path = trigger.path || "/";
const url = namespacedPath(owner || "owner", path);
const authEntries = Array.isArray(trigger.auth) ? trigger.auth : [];
const selectedIds = authEntries.filter((e) => typeof e === "string" && e).map(String);
const inlineEntries = authEntries.filter((e) => e && typeof e === "object");
function setAuthIds(nextIds) {
const next = [...nextIds, ...inlineEntries];
onChange({ ...trigger, auth: next.length ? next : null });
}
function copyUrl() {
if (typeof navigator?.clipboard?.writeText === "function") {
navigator.clipboard.writeText(url);
}
}
return (
onChange({ ...trigger, method: e.target.value })}
>
{HTTP_METHODS.map((m) => (
))}
{HTTP_METHODS.includes(trigger.method || "POST") ? null : (
)}
onChange({ ...trigger, path: e.target.value })}
placeholder="/hook"
/>
onChange({ ...trigger, response: e.target.value })}
>
{pages.map((p) => (
))}
{trigger.response && !pages.some((p) => p.name === trigger.response) ? (
) : null}
);
}
function CronFields({ trigger, disabled, onChange, alertDestinations }) {
const preset = matchCronPreset(trigger.schedule);
let human = "";
try {
human = cronstrue.toString(trigger.schedule || "", { throwExceptionOnParseError: true });
} catch {
human = "Invalid cron expression";
}
return (
{human}
Cron runs use this workflow's top-level data as the payload.
Set it in YAML or the Test panel prefill.
);
}
function FailureAlertFields({ trigger, disabled, onChange, alertDestinations }) {
return (
);
}