feat(workflows): add Gmail sending and testing workflows

- Introduced a new `send-gmail` workflow for sending emails via Gmail SMTP, with configurable parameters for recipients, subject, and body content.
- Added a `test-send-gmail` workflow to facilitate testing the email sending functionality with sample data.
- Implemented a `track` workflow to monitor Gojek trips, enhancing the server's capabilities for tracking and notifications.
- Updated the workflow management interface to include new workflows and improved organization of existing scripts.

Co-authored-by: Nasyarobby Putra <nasyarobby@gmail.com>
This commit is contained in:
2026-08-15 18:33:13 +07:00
parent 94ba931d9b
commit 7fe5defc43
22 changed files with 2486 additions and 159 deletions
@@ -0,0 +1,99 @@
import { useMemo, useState } from "react";
import { useScripts } from "../../api/hooks.js";
export function AddScriptDialog({ open, onClose, onPick }) {
const { data: scripts = [], isLoading } = useScripts();
const [q, setQ] = useState("");
const filtered = useMemo(() => {
const term = q.trim().toLowerCase();
const list = scripts.map((s) => ({
name: typeof s === "string" ? s : s.name,
description: typeof s === "string" ? "" : s.meta?.description ?? "",
meta: typeof s === "string" ? null : s.meta,
metaError: typeof s === "string" ? null : s.metaError,
}));
if (!term) return list;
return list.filter(
(s) =>
s.name.toLowerCase().includes(term) ||
s.description.toLowerCase().includes(term),
);
}, [scripts, q]);
if (!open) return null;
return (
<dialog className="modal modal-open">
<div className="modal-box max-w-lg">
<h3 className="font-bold text-lg">Add script</h3>
<input
className="input input-sm w-full mt-3"
placeholder="Search scripts"
value={q}
onChange={(e) => setQ(e.target.value)}
autoFocus
/>
<ul className="menu mt-3 max-h-80 overflow-auto rounded-box border border-base-300 p-0">
<li>
<button
type="button"
onClick={() => {
onPick({ kind: "set" });
setQ("");
}}
>
<span className="font-semibold">Set (JSONata)</span>
<span className="text-xs opacity-70">Assign a JSONata result to a variable</span>
</button>
</li>
{isLoading ? (
<li className="p-4">
<span className="loading loading-spinner loading-sm" />
</li>
) : (
filtered.map((s) => (
<li key={s.name}>
<button
type="button"
onClick={() => {
onPick({ kind: "script", name: s.name, meta: s.meta });
setQ("");
}}
>
<span className="font-mono">{s.name}</span>
<span className="text-xs opacity-70 line-clamp-2">
{s.metaError ? s.metaError : s.description || "No description"}
</span>
</button>
</li>
))
)}
</ul>
<div className="modal-action">
<button
type="button"
className="btn"
onClick={() => {
setQ("");
onClose();
}}
>
Cancel
</button>
</div>
</div>
<form method="dialog" className="modal-backdrop">
<button
type="button"
onClick={() => {
setQ("");
onClose();
}}
>
close
</button>
</form>
</dialog>
);
}