* initialize * expand tool result text limit | add syntax highlighting and json formatting to tool result rendering * fix onError jsdoc * lint * fix unread icon * route protection * improve form handling for NewJobModal * safeJsonParse * remove unneeded comments * remove trycatch * add truncateText helper * add explicit fallback value tos safeJsonParse * add shared cron constant and helpers * reduce frontend indirection * use isLight to compute syntax highlighting theme * remove dead code * remove forJob and make job limit to 50 * create recomputeNextRunAt helper method * add comment about nextRunAt recomputation * add job queue and concurrency control to scheduled jobs * use p-queue * change default max concurrent value to 1 * add comment explaining internal scheduling system * add recomputeNextRunAt on boot * add generated documents to run details * Modify toolsOverride functionality where no tools selected means no tools are given to the agent add a select all/deselect all toggle button for easily selecting all tools in the cerate job form * create usePolling hook * add polling to scheduled jobs and scheduled job runs pages * add cron generation feature in job form * remove cron generation feature | add cron builder feature | add max active scheduled jobs limit * set MAX_ACTIVE to null * replace hour and minute input fields with input with type time * simplify * organize components * move components to bottom of page component * change Generated Documents to Generated Files * add i18n to cronstrue * add i18n * add type="button" to button elements * refactor fileSource retrieval logic * one scheduled job run can have status "running" * add protection of file retrieveal from scheduled job in multiuser mode * fix comments * make job status default to queued * add queued status * fix bug with result trace rendering * store timeout ref and clearTimeout once race settles * remove unneeded handlerPromise tracking * move imports to top level * refactor hardcoded paths to path resolve functions * implement new job form design * simplify * fix button styles * fix runJob bug * implement styles for scheduled jobs page * apply dark mode figma styles * delete unused translation key * implement light mode for new new job modal, run history, and run details * lint * fix light mode scroll bar in tool call card * adjust table header contrast * fix type in subtitle * kill workers when job is in-flight before deleting job * add border-none to buttons * change locale time to iso string * import BackgroundService module level | instatiate backgroundService singltone once and reuse across handlers * add p-queue, @breejs/later and cron-validate as core deps * parse cron expression to a builder state once * add theme to day buttons in cron builder * fix stale tools selection caption * flip popover when popover clips screen height * make ScheduleJob.trigger() await the run insertion | disable run now button if job is in flight * regen table * refactor generated file card * refactor frontend * remove logs * major refactor for tool picking, fix bree/later bug * combine action endpoints, move contine to method * fix unoptimized query with include + take + order * fix dangerous use, refactor job to utils * add copy content to text response * improve notification system subscription for browser * remove unused translations * prevent gen-file cleanup job from deleting active job file generated references * rich text copy * Scheduled Jobs: Translations (#5482) * add locales for scheduled jobs * i18n --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com> * add config flag with UI notice * update README * telemetry datapoints * Always use UTC on backend, convert to local in frontend * fix tz render * Add job killing * cleanup thinking text in job notifications and break out reasoning in response text. Also hide zero metrics since that is useless * Port generatedFile schema to the normalized workspace chat `outputs` file format so porting to thread is simple and implem between chats <> jobs is 1:1 * what the fuck * compiled bug * fixed thinking oddity in complied frontend * supress multi-toast * fix duration call * Revert "fix duration call" This reverts commit 0491bc71f4223e65ea4046561b15b268fefb8da2. * revert and reapply fix --------- Co-authored-by: Timothy Carambat <rambat1010@gmail.com>
108 lines
4.4 KiB
JavaScript
108 lines
4.4 KiB
JavaScript
import { useNavigate } from "react-router-dom";
|
|
import { Play, PencilSimple, X } from "@phosphor-icons/react";
|
|
import paths from "@/utils/paths";
|
|
import { humanizeCron } from "../utils/cron";
|
|
import { useTranslation } from "react-i18next";
|
|
|
|
// One row of the scheduled-jobs list. Clicking the name navigates to the
|
|
// run history; CRUD callbacks come from the parent.
|
|
export default function JobRow({ job, onTrigger, onToggle, onEdit, onDelete }) {
|
|
const navigate = useNavigate();
|
|
const { t, i18n } = useTranslation();
|
|
// A job has at most one in-flight run; disable "Run now" while it's queued
|
|
// or running so users get visible feedback that their click registered and
|
|
// so the backend dedup never has to drop a manual trigger silently.
|
|
const inFlight =
|
|
job.latestRun?.status === "running" || job.latestRun?.status === "queued";
|
|
|
|
const statusText = job.latestRun
|
|
? t(`scheduledJobs.status.${job.latestRun.status}`, job.latestRun.status)
|
|
: t("scheduledJobs.row.neverRun");
|
|
|
|
const stop = (handler) => (e) => {
|
|
e.stopPropagation();
|
|
handler();
|
|
};
|
|
|
|
return (
|
|
<div
|
|
role="button"
|
|
tabIndex={0}
|
|
onClick={() => navigate(paths.settings.scheduledJobRuns(job.id))}
|
|
onKeyDown={(e) => {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault();
|
|
navigate(paths.settings.scheduledJobRuns(job.id));
|
|
}
|
|
}}
|
|
className="flex items-center justify-between px-4 h-14 hover:bg-white/5 light:hover:bg-slate-200 transition-colors cursor-pointer"
|
|
title={t("scheduledJobs.row.viewRuns")}
|
|
>
|
|
<span className="w-[150px] text-sm font-medium text-white light:text-slate-950 truncate">
|
|
{job.name}
|
|
</span>
|
|
<span className="w-[180px] text-sm text-zinc-400 light:text-slate-600 truncate">
|
|
{humanizeCron(job.schedule, i18n.language)}
|
|
</span>
|
|
<span className="w-[120px] text-sm text-zinc-400 light:text-slate-600 truncate">
|
|
{statusText}
|
|
</span>
|
|
<span className="w-[180px] text-sm text-zinc-400 light:text-slate-600 truncate">
|
|
{job.lastRunAt ? new Date(job.lastRunAt).toLocaleString() : "—"}
|
|
</span>
|
|
<span className="w-[180px] text-sm text-zinc-400 light:text-slate-600 truncate">
|
|
{job.enabled && job.nextRunAt
|
|
? new Date(job.nextRunAt).toLocaleString()
|
|
: "—"}
|
|
</span>
|
|
<div className="w-[140px] flex items-center justify-end gap-1">
|
|
<button
|
|
type="button"
|
|
onClick={stop(() => onDelete(job.id))}
|
|
className="border-none p-2 rounded-full text-zinc-400 light:text-slate-950 hover:text-red-400 light:hover:text-red-600 hover:bg-white/10 light:hover:bg-slate-300/50 transition-colors"
|
|
title={t("scheduledJobs.row.delete")}
|
|
>
|
|
<X className="h-4 w-4 shrink-0" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={stop(() => onEdit(job))}
|
|
className="border-none p-2 rounded-full text-zinc-400 light:text-slate-950 hover:text-white light:hover:text-slate-700 hover:bg-white/10 light:hover:bg-slate-300/50 transition-colors"
|
|
title={t("scheduledJobs.row.edit")}
|
|
>
|
|
<PencilSimple className="h-4 w-4 shrink-0" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={stop(() => onTrigger(job.id))}
|
|
disabled={inFlight}
|
|
className="border-none p-2 rounded-full text-zinc-400 light:text-slate-950 hover:text-white light:hover:text-slate-700 hover:bg-white/10 light:hover:bg-slate-300/50 transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent"
|
|
title={t("scheduledJobs.row.runNow")}
|
|
>
|
|
<Play className="h-4 w-4 shrink-0" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
role="switch"
|
|
aria-checked={job.enabled}
|
|
onClick={stop(() => onToggle(job.id))}
|
|
title={
|
|
job.enabled
|
|
? t("scheduledJobs.row.disable")
|
|
: t("scheduledJobs.row.enable")
|
|
}
|
|
className={`border-none relative h-[15px] w-7 rounded-full p-0.5 transition-colors ${
|
|
job.enabled ? "bg-green-400" : "bg-zinc-600 light:bg-slate-300"
|
|
}`}
|
|
>
|
|
<span
|
|
className={`block h-3 w-3 rounded-full bg-white shadow transition-transform ${
|
|
job.enabled ? "translate-x-[13px]" : "translate-x-0"
|
|
}`}
|
|
/>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|