Files
model-platform/frontend/app/features/schedules/state/dialogSlice.ts
T

78 lines
2.3 KiB
TypeScript

// Dialog slice: create-schedule dialog state + cron preview.
// Pure setters + small mutations that read/write only dialog-owned fields.
import type { CronPreview } from "../../../services/api";
import type { StateCreator } from "zustand";
import { handleError, notify, requireApi } from "./helpers";
import type { SchedulesStore } from "./useSchedulesStore";
// ---- State ----
export type DialogSliceState = {
createDialogOpen: boolean;
newScheduleName: string;
cronResult: CronPreview | null;
};
// ---- Actions ----
export type DialogSliceActions = {
// pure setters
setCreateDialogOpen: (open: boolean) => void;
setNewScheduleName: (name: string) => void;
setCronResult: (result: CronPreview | null) => void;
// mutations
openCreateDialog: () => void;
runCronPreview: () => Promise<void>;
};
// `SchedulesStore` is the combined state+actions of all slices, so `get()`
// returns a fully typed snapshot — no `any` propagation.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const createDialogSlice: StateCreator<SchedulesStore, [], [], DialogSliceState & DialogSliceActions> = (set, get) => ({
// ---- initial state ----
createDialogOpen: false,
newScheduleName: "",
cronResult: null,
// ---- pure setters ----
setCreateDialogOpen: (open) => set({ createDialogOpen: open }),
setNewScheduleName: (name) => set({ newScheduleName: name }),
setCronResult: (result) => set({ cronResult: result }),
// ---- mutations ----
openCreateDialog: () => {
if (get().busy) return;
set((s: any) => ({
contextMenu: null,
newScheduleName: `新建调度 ${s.schedules.length + 1}`,
createDialogOpen: true,
}));
},
runCronPreview: async () => {
const api = requireApi();
const { scheduleForm } = get();
if (scheduleForm.triggerType !== "cron") return;
if (get().busy) return;
set({ busy: "cron-preview" });
try {
const result = await api.previewCron({
cron_expression: scheduleForm.cronExpression.trim(),
timezone: scheduleForm.timezone.trim(),
count: 5,
});
set({ cronResult: result });
notify({ tone: "success", message: "Cron 表达式校验通过" });
} catch (error) {
set({ cronResult: null });
await handleError(get, error, "Cron 预览失败");
} finally {
set({ busy: null });
}
},
});