fix: address greptile routine review

This commit is contained in:
dotta
2026-03-20 16:26:29 -05:00
parent 99eb317600
commit 9093cfbe4f
6 changed files with 157 additions and 19 deletions

View File

@@ -0,0 +1,71 @@
import { describe, expect, it } from "vitest";
import type { RoutineTrigger } from "@paperclipai/shared";
import { buildRoutineTriggerPatch } from "./routine-trigger-patch";
function makeScheduleTrigger(overrides: Partial<RoutineTrigger> = {}): RoutineTrigger {
return {
id: "trigger-1",
companyId: "company-1",
routineId: "routine-1",
kind: "schedule",
label: "Daily",
enabled: true,
cronExpression: "0 10 * * *",
timezone: "UTC",
nextRunAt: null,
lastFiredAt: null,
publicId: null,
secretId: null,
signingMode: null,
replayWindowSec: null,
lastRotatedAt: null,
lastResult: null,
createdByAgentId: null,
createdByUserId: null,
updatedByAgentId: null,
updatedByUserId: null,
createdAt: new Date("2026-03-20T00:00:00.000Z"),
updatedAt: new Date("2026-03-20T00:00:00.000Z"),
...overrides,
};
}
describe("buildRoutineTriggerPatch", () => {
it("preserves an existing schedule trigger timezone when saving edits", () => {
const patch = buildRoutineTriggerPatch(
makeScheduleTrigger({ timezone: "UTC" }),
{
label: "Daily label edit",
cronExpression: "0 10 * * *",
signingMode: "bearer",
replayWindowSec: "300",
},
"America/Chicago",
);
expect(patch).toEqual({
label: "Daily label edit",
cronExpression: "0 10 * * *",
timezone: "UTC",
});
});
it("falls back to the local timezone when a schedule trigger has none", () => {
const patch = buildRoutineTriggerPatch(
makeScheduleTrigger({ timezone: null }),
{
label: "",
cronExpression: "15 9 * * 1-5",
signingMode: "bearer",
replayWindowSec: "300",
},
"America/Chicago",
);
expect(patch).toEqual({
label: null,
cronExpression: "15 9 * * 1-5",
timezone: "America/Chicago",
});
});
});

View File

@@ -0,0 +1,30 @@
import type { RoutineTrigger } from "@paperclipai/shared";
export type RoutineTriggerEditorDraft = {
label: string;
cronExpression: string;
signingMode: string;
replayWindowSec: string;
};
export function buildRoutineTriggerPatch(
trigger: RoutineTrigger,
draft: RoutineTriggerEditorDraft,
fallbackTimezone: string,
) {
const patch: Record<string, unknown> = {
label: draft.label.trim() || null,
};
if (trigger.kind === "schedule") {
patch.cronExpression = draft.cronExpression.trim();
patch.timezone = trigger.timezone ?? fallbackTimezone;
}
if (trigger.kind === "webhook") {
patch.signingMode = draft.signingMode;
patch.replayWindowSec = Number(draft.replayWindowSec || "300");
}
return patch;
}

View File

@@ -24,6 +24,7 @@ import { useCompany } from "../context/CompanyContext";
import { useBreadcrumbs } from "../context/BreadcrumbContext";
import { useToast } from "../context/ToastContext";
import { queryKeys } from "../lib/queryKeys";
import { buildRoutineTriggerPatch } from "../lib/routine-trigger-patch";
import { timeAgo } from "../lib/timeAgo";
import { EmptyState } from "../components/EmptyState";
import { PageSkeleton } from "../components/PageSkeleton";
@@ -61,7 +62,7 @@ const concurrencyPolicyDescriptions: Record<string, string> = {
};
const catchUpPolicyDescriptions: Record<string, string> = {
skip_missed: "Ignore schedule windows that were missed while the routine or scheduler was paused.",
enqueue_missed_with_cap: "Catch up missed schedule windows with a capped backlog after recovery.",
enqueue_missed_with_cap: "Catch up missed schedule windows in capped batches after recovery.",
};
const signingModeDescriptions: Record<string, string> = {
bearer: "Expect a shared bearer token in the Authorization header.",
@@ -212,20 +213,7 @@ function TriggerEditor({
<Button
variant="outline"
size="sm"
onClick={() =>
onSave(trigger.id, {
label: draft.label.trim() || null,
...(trigger.kind === "schedule"
? { cronExpression: draft.cronExpression.trim(), timezone: getLocalTimezone() }
: {}),
...(trigger.kind === "webhook"
? {
signingMode: draft.signingMode,
replayWindowSec: Number(draft.replayWindowSec || "300"),
}
: {}),
})
}
onClick={() => onSave(trigger.id, buildRoutineTriggerPatch(trigger, draft, getLocalTimezone()))}
>
<Save className="mr-1.5 h-3.5 w-3.5" />
Save

View File

@@ -43,7 +43,7 @@ const concurrencyPolicyDescriptions: Record<string, string> = {
};
const catchUpPolicyDescriptions: Record<string, string> = {
skip_missed: "Ignore windows that were missed while the scheduler or routine was paused.",
enqueue_missed_with_cap: "Catch up missed schedule windows with a capped backlog after recovery.",
enqueue_missed_with_cap: "Catch up missed schedule windows in capped batches after recovery.",
};
function autoResizeTextarea(element: HTMLTextAreaElement | null) {