import { state, property } from "lit/decorators.js"; import { msg, localized, str } from "@lit/localize"; import cronstrue from "cronstrue"; // TODO localize import LiteElement, { html } from "../utils/LiteElement"; import { getLocaleTimeZone } from "../utils/localization"; import type { CrawlTemplate } from "../pages/archive/types"; const nowHour = new Date().getHours(); const initialHours = nowHour % 12 || 12; const initialPeriod = nowHour > 11 ? "PM" : "AM"; /** * Usage: * ```ts * * ``` * * @event submit * @event cancel */ @localized() export class CrawlTemplatesScheduler extends LiteElement { @property({ type: String }) schedule?: CrawlTemplate["schedule"]; @property({ type: Boolean }) isSubmitting: boolean = false; @property({ type: Boolean }) cancelable?: boolean = false; @state() private editedSchedule?: string; @state() private isScheduleDisabled?: boolean; @state() private schedulePeriod: "AM" | "PM" = initialPeriod; private get timeZoneShortName() { return getLocaleTimeZone(); } render() { // TODO consolidate with new const hours = Array.from({ length: 12 }).map((x, i) => ({ value: i + 1, label: `${i + 1}`, })); const minutes = Array.from({ length: 60 }).map((x, i) => ({ value: i, label: `${i}`.padStart(2, "0"), })); const getInitialScheduleInterval = (schedule: string) => { const [minute, hour, dayofMonth, month, dayOfWeek] = schedule.split(" "); if (dayofMonth === "*") { if (dayOfWeek === "*") { return "daily"; } return "weekly"; } return "monthly"; }; const scheduleIntervalsMap = { daily: `0 ${nowHour} * * *`, weekly: `0 ${nowHour} * * ${new Date().getDay()}`, monthly: `0 ${nowHour} ${new Date().getDate()} * *`, }; const initialInterval = this.schedule ? getInitialScheduleInterval(this.schedule) : "weekly"; const nextSchedule = this.editedSchedule || scheduleIntervalsMap[initialInterval]; return html`
{ if (e.target.value) { this.isScheduleDisabled = false; this.editedSchedule = `${nextSchedule .split(" ") .slice(0, 2) .join(" ")} ${(scheduleIntervalsMap as any)[e.target.value] .split(" ") .slice(2) .join(" ")}`; } else { this.isScheduleDisabled = true; } }} > ${msg("None")} ${msg("Daily")} ${msg("Weekly")} ${msg("Monthly")}
{ const hour = +e.target.value; const period = this.schedulePeriod; this.setScheduleHour({ hour, period, schedule: nextSchedule, }); }} > ${hours.map( ({ value, label }) => html`${label}` )} : (this.editedSchedule = `${e.target.value} ${nextSchedule .split(" ") .slice(1) .join(" ")}`)} > ${minutes.map( ({ value, label }) => html`${label}` )}
{ const hour = +e.target .closest("sl-form") .querySelector('sl-select[name="scheduleHour"]').value; const period = "AM"; this.schedulePeriod = period; this.setScheduleHour({ hour, period, schedule: nextSchedule, }); }} >${msg("AM", { desc: "Time AM/PM" })} { const hour = +e.target .closest("sl-form") .querySelector('sl-select[name="scheduleHour"]').value; const period = "PM"; this.schedulePeriod = period; this.setScheduleHour({ hour, period, schedule: nextSchedule, }); }} >${msg("PM", { desc: "Time AM/PM" })}
${this.isScheduleDisabled ? msg(html`Crawls will not repeat.`) : msg( html`New schedule will be:
${cronstrue.toString(nextSchedule, { verbose: true, })} (in ${this.timeZoneShortName} time zone)` )}
${this.cancelable ? html` ${msg("Cancel")} ` : ""} ${msg("Save Changes")}
`; } private onCancel(event: any) { this.dispatchEvent(new CustomEvent("cancel", event)); } private onSubmit(event: any) { this.dispatchEvent(new CustomEvent("submit", event)); } /** * Set correct local hour in schedule in 24-hr format **/ private setScheduleHour({ hour, period, schedule, }: { hour: number; period: "AM" | "PM"; schedule: string; }) { // Convert 12-hr to 24-hr time let periodOffset = 0; if (hour === 12) { if (period === "AM") { periodOffset = -12; } } else if (period === "PM") { periodOffset = 12; } this.editedSchedule = `${schedule.split(" ")[0]} ${ hour + periodOffset } ${schedule.split(" ").slice(2).join(" ")}`; } /** * Stop propgation of sl-select events. * Prevents bug where sl-dialog closes when dropdown closes * https://github.com/shoelace-style/shoelace/issues/170 */ private stopProp(e: CustomEvent) { e.stopPropagation(); } } customElements.define("btrix-crawl-scheduler", CrawlTemplatesScheduler);