import { html, nothing } from 'lit'; import { unsafeHTML } from 'lit/directives/unsafe-html.js'; import { LightElement } from '../../lib/base.js'; import { toString as cronToString } from 'cronstrue'; import { formatDate } from './utils.js'; import { t } from '../../lib/i18n.js'; export class CronJobsSection extends LightElement { static properties = { _jobs: { state: true }, _error: { state: true }, }; constructor() { super(); this._jobs = []; this._error = null; } connectedCallback() { super.connectedCallback(); this.__onLocaleChanged = () => this.requestUpdate(); window.addEventListener('locale-changed', this.__onLocaleChanged); } disconnectedCallback() { window.removeEventListener('locale-changed', this.__onLocaleChanged); super.disconnectedCallback(); } async load() { this._error = null; try { const res = await fetch('/api/cron/jobs'); if (!res.ok) throw new Error(`HTTP ${res.status}`); const allJobs = await res.json(); this._jobs = allJobs.filter(j => j.kind === 'cron' && !j.single_run); } catch (e) { this._error = e.message; } } async _delete(job) { if (!confirm(t('cron.confirm.delete', { title: job.title }))) return; try { const res = await fetch(`/api/cron/jobs/${job.id}`, { method: 'DELETE' }); if (!res.ok) throw new Error(await res.text()); await this.load(); } catch (e) { this._error = e.message; } } async _toggle(job) { try { const res = await fetch(`/api/cron/jobs/${job.id}/toggle`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled: !job.enabled }), }); if (!res.ok) throw new Error(await res.text()); await this.load(); } catch (e) { this._error = e.message; } } _statusBadge(job) { if (job.running_session_id != null) return html`${t('cron.badge.running')}`; if (!job.enabled) return html`${t('cron.badge.disabled')}`; return html`${t('cron.badge.idle')}`; } _renderCard(job) { return html`
${job.title} ${this._statusBadge(job)}
${job.description ? html`
${job.description}
` : nothing}
${cronToString(job.cron)} ${job.cron}
${t('cron.card.label_agent')} ${job.agent_id}
${t('cron.card.label_last_run')} ${formatDate(job.last_run_at)}
${t('cron.card.label_next_run')} ${formatDate(job.next_run_at)}
`; } render() { return html`

${t('cron.title')}

${t(this._jobs.length === 1 ? 'cron.count_one' : 'cron.count_other', { n: this._jobs.length })}
${this._error ? html`
${this._error}
` : nothing} ${this._jobs.length === 0 ? html`

${t('cron.empty.title')} ${unsafeHTML(t('cron.empty.hint'))}

` : html`
${this._jobs.map(j => this._renderCard(j))}
`}
`; } }