@goodandready/dsh-cron 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +88 -2
- package/lib/index.js +8 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -123,6 +123,20 @@ const React = window.React || require('react');
|
|
|
123
123
|
.dsh-cron-card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
|
|
124
124
|
.dsh-cron-card-title { font-size: 15px; font-weight: 600; color: var(--dsw-alias-label-primary, #fff); }
|
|
125
125
|
.dsh-cron-card-desc { font-size: 13px; color: var(--dsw-alias-label-secondary, #888); margin-bottom: 16px; line-height: 1.4; }
|
|
126
|
+
|
|
127
|
+
.dsh-cron-modal-nav { display: flex; gap: 4px; border-bottom: 1px solid #2e2e2e; margin-bottom: 18px; padding-bottom: 2px; }
|
|
128
|
+
.dsh-cron-modal-tab { appearance: none; background: transparent; border: none; border-bottom: 2px solid transparent; padding: 8px 14px; font-size: 13.5px; color: #888; cursor: pointer; font-weight: 500; transition: color 0.15s, border-color 0.15s; }
|
|
129
|
+
.dsh-cron-modal-tab:hover { color: #ccc; }
|
|
130
|
+
.dsh-cron-modal-tab[data-active="true"] { color: #fff; border-bottom-color: #ededed; }
|
|
131
|
+
.dsh-cron-history-list { display: flex; flex-direction: column; gap: 10px; max-height: 420px; overflow-y: auto; padding-right: 4px; }
|
|
132
|
+
.dsh-cron-history-item { background: #161616; border: 1px solid #2a2a2a; border-radius: 8px; padding: 12px 14px; font-size: 12.5px; }
|
|
133
|
+
.dsh-cron-history-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
|
|
134
|
+
.dsh-cron-history-status { font-weight: 600; font-size: 11.5px; text-transform: uppercase; padding: 2px 6px; border-radius: 4px; }
|
|
135
|
+
.dsh-cron-history-status[data-status="success"] { background: rgba(16, 185, 129, 0.15); color: #10b981; }
|
|
136
|
+
.dsh-cron-history-status[data-status="error"] { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
|
|
137
|
+
.dsh-cron-history-time { color: #777; font-size: 12px; }
|
|
138
|
+
.dsh-cron-history-output { background: #0c0c0c; border: 1px solid #222; border-radius: 6px; padding: 8px 10px; font-family: monospace; font-size: 12px; color: #bbb; max-height: 140px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; margin-top: 6px; }
|
|
139
|
+
.dsh-cron-history-empty { text-align: center; padding: 36px 0; color: #666; font-size: 13.5px; }
|
|
126
140
|
`;
|
|
127
141
|
|
|
128
142
|
function ensureStyles() {
|
|
@@ -220,6 +234,9 @@ const React = window.React || require('react');
|
|
|
220
234
|
const [formModel, setFormModel] = React.useState('');
|
|
221
235
|
const [formDelivery, setFormDelivery] = React.useState('isolated');
|
|
222
236
|
const [selectedTaskMeta, setSelectedTaskMeta] = React.useState(null);
|
|
237
|
+
const [modalTab, setModalTab] = React.useState('params');
|
|
238
|
+
const [taskHistory, setTaskHistory] = React.useState([]);
|
|
239
|
+
const [historyLoading, setHistoryLoading] = React.useState(false);
|
|
223
240
|
|
|
224
241
|
// DSH dialog state
|
|
225
242
|
const [dshModalOpen, setDshModalOpen] = React.useState(false);
|
|
@@ -317,10 +334,26 @@ const React = window.React || require('react');
|
|
|
317
334
|
setManualModalOpen(true);
|
|
318
335
|
};
|
|
319
336
|
|
|
337
|
+
const loadTaskHistory = async (taskId) => {
|
|
338
|
+
setHistoryLoading(true);
|
|
339
|
+
try {
|
|
340
|
+
const res = await fetch('/dsh-cron/action/' + encodeURIComponent(taskId) + '/history');
|
|
341
|
+
const data = await res.json();
|
|
342
|
+
if (data.ok) {
|
|
343
|
+
setTaskHistory(data.history || []);
|
|
344
|
+
}
|
|
345
|
+
} catch (e) {
|
|
346
|
+
console.error('[dsh-cron] history load failed:', e);
|
|
347
|
+
} finally {
|
|
348
|
+
setHistoryLoading(false);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
320
352
|
const openEditModal = (task) => {
|
|
321
353
|
setDropdownOpen(false);
|
|
322
354
|
setFormId(task.id);
|
|
323
355
|
setSelectedTaskMeta(task);
|
|
356
|
+
setModalTab('params');
|
|
324
357
|
setFormTitle(task.title || '');
|
|
325
358
|
setFormSchedule(task.schedule || '');
|
|
326
359
|
setFormType(task.type || 'llm');
|
|
@@ -330,6 +363,7 @@ const React = window.React || require('react');
|
|
|
330
363
|
setFormDelivery(task.delivery || 'isolated');
|
|
331
364
|
if (task.provider) loadModels(task.provider);
|
|
332
365
|
else if (defaultModelInfo?.provider) loadModels(defaultModelInfo.provider);
|
|
366
|
+
loadTaskHistory(task.id);
|
|
333
367
|
setManualModalOpen(true);
|
|
334
368
|
};
|
|
335
369
|
|
|
@@ -547,7 +581,7 @@ const React = window.React || require('react');
|
|
|
547
581
|
style: { maxWidth: '640px' },
|
|
548
582
|
onClick: (e) => e.stopPropagation()
|
|
549
583
|
},
|
|
550
|
-
React.createElement('div', { className: 'dsh-cron-modal-head', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '18px' } },
|
|
584
|
+
React.createElement('div', { className: 'dsh-cron-modal-head', style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: formId ? '12px' : '18px' } },
|
|
551
585
|
React.createElement('div', { className: 'dsh-cron-modal-title', style: { margin: 0 } }, formId ? 'Редактирование задачи' : 'Новая запланированная задача'),
|
|
552
586
|
selectedTaskMeta && React.createElement('span', {
|
|
553
587
|
style: {
|
|
@@ -559,6 +593,55 @@ const React = window.React || require('react');
|
|
|
559
593
|
}
|
|
560
594
|
}, selectedTaskMeta.status === 'active' ? '● Активна' : '○ На паузе')
|
|
561
595
|
),
|
|
596
|
+
|
|
597
|
+
formId && React.createElement('div', { className: 'dsh-cron-modal-nav' },
|
|
598
|
+
React.createElement('button', {
|
|
599
|
+
type: 'button',
|
|
600
|
+
className: 'dsh-cron-modal-tab',
|
|
601
|
+
'data-active': modalTab === 'params',
|
|
602
|
+
onClick: () => setModalTab('params')
|
|
603
|
+
}, 'Параметры'),
|
|
604
|
+
React.createElement('button', {
|
|
605
|
+
type: 'button',
|
|
606
|
+
className: 'dsh-cron-modal-tab',
|
|
607
|
+
'data-active': modalTab === 'history',
|
|
608
|
+
onClick: () => { setModalTab('history'); if (formId) loadTaskHistory(formId); }
|
|
609
|
+
}, 'История запусков (' + (taskHistory.length || 0) + ')')
|
|
610
|
+
),
|
|
611
|
+
|
|
612
|
+
modalTab === 'history' && formId ? React.createElement('div', null,
|
|
613
|
+
historyLoading ? React.createElement('div', { className: 'dsh-cron-history-empty' }, 'Загрузка истории...') :
|
|
614
|
+
taskHistory.length === 0 ? React.createElement('div', { className: 'dsh-cron-history-empty' }, 'История запусков пока пуста') :
|
|
615
|
+
React.createElement('div', { className: 'dsh-cron-history-list' },
|
|
616
|
+
taskHistory.map((run) => React.createElement('div', { key: run.id, className: 'dsh-cron-history-item' },
|
|
617
|
+
React.createElement('div', { className: 'dsh-cron-history-head' },
|
|
618
|
+
React.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } },
|
|
619
|
+
React.createElement('span', {
|
|
620
|
+
className: 'dsh-cron-history-status',
|
|
621
|
+
'data-status': run.status
|
|
622
|
+
}, run.status === 'success' ? 'Успешно' : 'Ошибка'),
|
|
623
|
+
React.createElement('span', { className: 'dsh-cron-history-time' }, run.at ? new Date(run.at).toLocaleString() : '')
|
|
624
|
+
),
|
|
625
|
+
React.createElement('span', { style: { color: '#888', fontSize: '11.5px' } }, (run.durationMs || 0) + ' ms')
|
|
626
|
+
),
|
|
627
|
+
run.output && React.createElement('div', { className: 'dsh-cron-history-output' }, run.output),
|
|
628
|
+
run.error && React.createElement('div', { className: 'dsh-cron-history-output', style: { color: '#ef4444', borderColor: '#552222' } }, run.error)
|
|
629
|
+
))
|
|
630
|
+
),
|
|
631
|
+
React.createElement('div', { className: 'dsh-cron-modal-foot', style: { marginTop: '18px' } },
|
|
632
|
+
React.createElement('button', {
|
|
633
|
+
type: 'button',
|
|
634
|
+
className: 'dsh-cron-btn-secondary',
|
|
635
|
+
onClick: () => { if (formId) loadTaskHistory(formId); }
|
|
636
|
+
}, 'Обновить историю'),
|
|
637
|
+
React.createElement('button', {
|
|
638
|
+
type: 'button',
|
|
639
|
+
className: 'dsh-cron-btn-primary',
|
|
640
|
+
onClick: () => setManualModalOpen(false)
|
|
641
|
+
}, 'Закрыть')
|
|
642
|
+
)
|
|
643
|
+
) :
|
|
644
|
+
|
|
562
645
|
React.createElement('form', { onSubmit: handleSaveManual },
|
|
563
646
|
React.createElement('div', { className: 'dsh-cron-form-group' },
|
|
564
647
|
React.createElement('label', null, 'Название задачи'),
|
|
@@ -645,7 +728,10 @@ const React = window.React || require('react');
|
|
|
645
728
|
type: 'button',
|
|
646
729
|
className: 'dsh-cron-btn-secondary',
|
|
647
730
|
style: { padding: '4px 10px', fontSize: '12px' },
|
|
648
|
-
onClick: () => {
|
|
731
|
+
onClick: async () => {
|
|
732
|
+
await handleRunNow(selectedTaskMeta.id);
|
|
733
|
+
if (formId) loadTaskHistory(formId);
|
|
734
|
+
}
|
|
649
735
|
}, 'Запустить сейчас')
|
|
650
736
|
),
|
|
651
737
|
React.createElement('div', { className: 'dsh-cron-modal-foot' },
|
package/lib/index.js
CHANGED
|
@@ -177,6 +177,14 @@ export function apply(ctx, config) {
|
|
|
177
177
|
return;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
+
const historyMatch = pathname.match(/^\/dsh-cron\/action\/([^/]+)\/history$/);
|
|
181
|
+
if (req.method === 'GET' && historyMatch) {
|
|
182
|
+
const taskId = historyMatch[1];
|
|
183
|
+
const history = store.getHistory(taskId, 30);
|
|
184
|
+
sendJson(res, 200, { ok: true, history });
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
180
188
|
sendJson(res, 404, { ok: false, error: 'Action not found' });
|
|
181
189
|
} catch (err) {
|
|
182
190
|
sendJson(res, 500, { ok: false, error: err.message });
|