mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
fix(ui): expose all automation schedule filters (#126962)
* fix(ui): expose all automation schedule filters Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b * refactor(ui): derive cron filters from protocol Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b --------- Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
committed by
GitHub
parent
e2a48d4b70
commit
2acfc47b7f
@@ -2,6 +2,7 @@
|
|||||||
import { parseBoolean } from "@openclaw/normalization-core/boolean-coercion";
|
import { parseBoolean } from "@openclaw/normalization-core/boolean-coercion";
|
||||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||||
import {
|
import {
|
||||||
|
type CronListParams,
|
||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
errorShape,
|
errorShape,
|
||||||
GatewayErrorDetailCodes,
|
GatewayErrorDetailCodes,
|
||||||
@@ -488,21 +489,7 @@ export const cronHandlers: GatewayRequestHandlers = {
|
|||||||
if (!assertValidParams(params, validateCronListParams, "cron.list", respond)) {
|
if (!assertValidParams(params, validateCronListParams, "cron.list", respond)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const p = params as {
|
const p = params as CronListParams;
|
||||||
includeDisabled?: boolean;
|
|
||||||
limit?: number;
|
|
||||||
offset?: number;
|
|
||||||
query?: string;
|
|
||||||
enabled?: "all" | "enabled" | "disabled";
|
|
||||||
scheduleKind?: "all" | "at" | "every" | "cron";
|
|
||||||
lastRunStatus?: "all" | "ok" | "error" | "skipped" | "unknown";
|
|
||||||
trigger?: "all" | "conditional" | "unconditional";
|
|
||||||
sortBy?: "nextRunAtMs" | "updatedAtMs" | "name";
|
|
||||||
sortDir?: "asc" | "desc";
|
|
||||||
agentId?: string;
|
|
||||||
compact?: boolean;
|
|
||||||
includeDeliveryPreviews?: boolean;
|
|
||||||
};
|
|
||||||
const callerScope = readCronCallerScope(client);
|
const callerScope = readCronCallerScope(client);
|
||||||
const requestedAgentId = p.agentId ? normalizeAgentId(p.agentId) : undefined;
|
const requestedAgentId = p.agentId ? normalizeAgentId(p.agentId) : undefined;
|
||||||
if (callerScope && requestedAgentId && requestedAgentId !== callerScope.agentId) {
|
if (callerScope && requestedAgentId && requestedAgentId !== callerScope.agentId) {
|
||||||
|
|||||||
@@ -555,6 +555,7 @@ export type {
|
|||||||
export type CronRunStatus = NonNullable<ProtocolCronRunLogEntry["status"]>;
|
export type CronRunStatus = NonNullable<ProtocolCronRunLogEntry["status"]>;
|
||||||
export type CronDeliveryStatus = NonNullable<ProtocolCronRunLogEntry["deliveryStatus"]>;
|
export type CronDeliveryStatus = NonNullable<ProtocolCronRunLogEntry["deliveryStatus"]>;
|
||||||
export type CronJobsEnabledFilter = NonNullable<CronListParams["enabled"]>;
|
export type CronJobsEnabledFilter = NonNullable<CronListParams["enabled"]>;
|
||||||
|
export type CronJobsScheduleKindFilter = NonNullable<CronListParams["scheduleKind"]>;
|
||||||
export type CronJobsTriggerFilter = NonNullable<CronListParams["trigger"]>;
|
export type CronJobsTriggerFilter = NonNullable<CronListParams["trigger"]>;
|
||||||
export type CronJobsSortBy = NonNullable<CronListParams["sortBy"]>;
|
export type CronJobsSortBy = NonNullable<CronListParams["sortBy"]>;
|
||||||
export type CronRunScope = NonNullable<CronRunsParams["scope"]>;
|
export type CronRunScope = NonNullable<CronRunsParams["scope"]>;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import type {
|
|||||||
CronJob,
|
CronJob,
|
||||||
CronDeliveryStatus,
|
CronDeliveryStatus,
|
||||||
CronJobsEnabledFilter,
|
CronJobsEnabledFilter,
|
||||||
|
CronJobsScheduleKindFilter,
|
||||||
CronJobsTriggerFilter,
|
CronJobsTriggerFilter,
|
||||||
CronJobsListResult,
|
CronJobsListResult,
|
||||||
CronJobsSortBy,
|
CronJobsSortBy,
|
||||||
@@ -191,7 +192,6 @@ export type CronFieldKey =
|
|||||||
|
|
||||||
export type CronFieldErrors = Partial<Record<CronFieldKey, string>>;
|
export type CronFieldErrors = Partial<Record<CronFieldKey, string>>;
|
||||||
|
|
||||||
export type CronJobsScheduleKindFilter = "all" | "at" | "every" | "cron" | "on-exit" | "stream";
|
|
||||||
export type CronJobsLastStatusFilter = "all" | CronRunStatus | "unknown";
|
export type CronJobsLastStatusFilter = "all" | CronRunStatus | "unknown";
|
||||||
type CronRunsLoadStatus = "ok" | "error" | "skipped";
|
type CronRunsLoadStatus = "ok" | "error" | "skipped";
|
||||||
|
|
||||||
|
|||||||
@@ -122,9 +122,21 @@ describe("cron view list pane", () => {
|
|||||||
'[data-test-id="cron-jobs-schedule-filter"]',
|
'[data-test-id="cron-jobs-schedule-filter"]',
|
||||||
HTMLSelectElement,
|
HTMLSelectElement,
|
||||||
);
|
);
|
||||||
scheduleFilter.value = "cron";
|
expect(Array.from(scheduleFilter.options, (option) => option.value)).toEqual([
|
||||||
scheduleFilter.dispatchEvent(new Event("change", { bubbles: true }));
|
"all",
|
||||||
expect(onJobsFiltersChange).toHaveBeenCalledWith({ cronJobsScheduleKindFilter: "cron" });
|
"at",
|
||||||
|
"every",
|
||||||
|
"cron",
|
||||||
|
"on-exit",
|
||||||
|
"stream",
|
||||||
|
]);
|
||||||
|
for (const scheduleKind of ["on-exit", "stream"] as const) {
|
||||||
|
scheduleFilter.value = scheduleKind;
|
||||||
|
scheduleFilter.dispatchEvent(new Event("change", { bubbles: true }));
|
||||||
|
expect(onJobsFiltersChange).toHaveBeenCalledWith({
|
||||||
|
cronJobsScheduleKindFilter: scheduleKind,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const lastStatusFilter = getElement(
|
const lastStatusFilter = getElement(
|
||||||
container,
|
container,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import type {
|
|||||||
CronStatus,
|
CronStatus,
|
||||||
CronDeliveryStatus,
|
CronDeliveryStatus,
|
||||||
CronJobsEnabledFilter,
|
CronJobsEnabledFilter,
|
||||||
|
CronJobsScheduleKindFilter,
|
||||||
CronJobsTriggerFilter,
|
CronJobsTriggerFilter,
|
||||||
CronRunsStatusValue,
|
CronRunsStatusValue,
|
||||||
CronJobsSortBy,
|
CronJobsSortBy,
|
||||||
@@ -51,7 +52,6 @@ import type {
|
|||||||
CronFieldKey,
|
CronFieldKey,
|
||||||
CronFormState,
|
CronFormState,
|
||||||
CronJobsLastStatusFilter,
|
CronJobsLastStatusFilter,
|
||||||
CronJobsScheduleKindFilter,
|
|
||||||
} from "../../lib/cron/index.ts";
|
} from "../../lib/cron/index.ts";
|
||||||
import { formatUiExternalText } from "../../lib/format-error.ts";
|
import { formatUiExternalText } from "../../lib/format-error.ts";
|
||||||
import { formatRelativeTimestamp, formatMs } from "../../lib/format.ts";
|
import { formatRelativeTimestamp, formatMs } from "../../lib/format.ts";
|
||||||
@@ -448,6 +448,15 @@ const ENABLED_TABS: Array<{ value: CronJobsEnabledFilter; labelKey: string }> =
|
|||||||
{ value: "disabled", labelKey: "cron.tabs.paused" },
|
{ value: "disabled", labelKey: "cron.tabs.paused" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const SCHEDULE_KIND_FILTER_LABELS: Record<CronJobsScheduleKindFilter, string> = {
|
||||||
|
all: "cron.jobs.all",
|
||||||
|
at: "cron.form.at",
|
||||||
|
every: "cron.form.every",
|
||||||
|
cron: "cron.form.cronOption",
|
||||||
|
"on-exit": "cron.form.repeatOnExit",
|
||||||
|
stream: "cron.form.repeatStream",
|
||||||
|
};
|
||||||
|
|
||||||
function renderListView(props: CronProps) {
|
function renderListView(props: CronProps) {
|
||||||
const hasAdvancedJobsFilters =
|
const hasAdvancedJobsFilters =
|
||||||
props.jobsScheduleKindFilter !== "all" ||
|
props.jobsScheduleKindFilter !== "all" ||
|
||||||
@@ -646,12 +655,10 @@ function renderJobsFilterPopover(props: CronProps, active: boolean) {
|
|||||||
label: t("cron.jobs.schedule"),
|
label: t("cron.jobs.schedule"),
|
||||||
value: props.jobsScheduleKindFilter,
|
value: props.jobsScheduleKindFilter,
|
||||||
testId: "cron-jobs-schedule-filter",
|
testId: "cron-jobs-schedule-filter",
|
||||||
options: [
|
options: Object.entries(SCHEDULE_KIND_FILTER_LABELS).map(([value, labelKey]) => ({
|
||||||
{ value: "all", label: t("cron.jobs.all") },
|
value,
|
||||||
{ value: "at", label: t("cron.form.at") },
|
label: t(labelKey),
|
||||||
{ value: "every", label: t("cron.form.every") },
|
})),
|
||||||
{ value: "cron", label: t("cron.form.cronOption") },
|
|
||||||
],
|
|
||||||
})}
|
})}
|
||||||
${renderJobsFilter(props, "cronJobsLastStatusFilter", {
|
${renderJobsFilter(props, "cronJobsLastStatusFilter", {
|
||||||
label: t("cron.jobs.lastRun"),
|
label: t("cron.jobs.lastRun"),
|
||||||
|
|||||||
Reference in New Issue
Block a user