@yemi33/minions 0.1.108 → 0.1.110
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/CHANGELOG.md +10 -0
- package/dashboard/js/render-schedules.js +59 -4
- package/dashboard/js/utils.js +27 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -177,23 +177,33 @@ async function _parseNaturalCron() {
|
|
|
177
177
|
|
|
178
178
|
// ─── Rendering ──────────────────────────────────────────────────────────────
|
|
179
179
|
|
|
180
|
+
let _schedPage = 0;
|
|
181
|
+
const SCHED_PER_PAGE = 15;
|
|
182
|
+
|
|
180
183
|
function renderSchedules(schedules) {
|
|
181
184
|
const el = document.getElementById('scheduled-content');
|
|
182
185
|
const countEl = document.getElementById('scheduled-count');
|
|
183
186
|
countEl.textContent = schedules.length;
|
|
187
|
+
window._lastSchedules = schedules;
|
|
184
188
|
if (!schedules.length) {
|
|
185
189
|
el.innerHTML = '<p class="empty">No scheduled tasks. Add one to automate recurring work.</p>';
|
|
186
190
|
return;
|
|
187
191
|
}
|
|
192
|
+
|
|
193
|
+
const totalPages = Math.ceil(schedules.length / SCHED_PER_PAGE);
|
|
194
|
+
if (_schedPage >= totalPages) _schedPage = totalPages - 1;
|
|
195
|
+
const start = _schedPage * SCHED_PER_PAGE;
|
|
196
|
+
const pageItems = schedules.slice(start, start + SCHED_PER_PAGE);
|
|
197
|
+
|
|
188
198
|
let html = '<div class="pr-table-wrap"><table class="pr-table"><thead><tr><th>ID</th><th>Title</th><th>Schedule</th><th>Type</th><th>Project</th><th>Agent</th><th>Enabled</th><th>Last Run</th><th></th></tr></thead><tbody>';
|
|
189
|
-
for (const s of
|
|
199
|
+
for (const s of pageItems) {
|
|
190
200
|
const enabledBadge = s.enabled
|
|
191
201
|
? '<span class="pr-badge approved">enabled</span>'
|
|
192
202
|
: '<span class="pr-badge rejected">disabled</span>';
|
|
193
203
|
const lastRun = s._lastRun ? timeAgo(s._lastRun) : 'never';
|
|
194
204
|
const typeBadge = '<span class="dispatch-type ' + escHtml(s.type || 'implement') + '">' + escHtml(s.type || 'implement') + '</span>';
|
|
195
205
|
const humanCron = _cronToHuman(s.cron || '');
|
|
196
|
-
html += '<tr>' +
|
|
206
|
+
html += '<tr style="cursor:pointer" onclick="openScheduleDetail(\'' + escHtml(s.id) + '\')">' +
|
|
197
207
|
'<td><span class="pr-id">' + escHtml(s.id || '') + '</span></td>' +
|
|
198
208
|
'<td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="' + escHtml(s.title || '') + '">' + escHtml(s.title || '') + '</td>' +
|
|
199
209
|
'<td><span title="' + escHtml(s.cron || '') + '" style="font-size:11px;color:var(--blue)">' + escHtml(humanCron) + '</span></td>' +
|
|
@@ -210,8 +220,53 @@ function renderSchedules(schedules) {
|
|
|
210
220
|
'</tr>';
|
|
211
221
|
}
|
|
212
222
|
html += '</tbody></table></div>';
|
|
223
|
+
|
|
224
|
+
if (schedules.length > SCHED_PER_PAGE) {
|
|
225
|
+
html += '<div class="pr-pager">' +
|
|
226
|
+
'<span class="pr-page-info">Showing ' + (start+1) + ' to ' + Math.min(start+SCHED_PER_PAGE, schedules.length) + ' of ' + schedules.length + '</span>' +
|
|
227
|
+
'<div class="pr-pager-btns">' +
|
|
228
|
+
'<button class="pr-pager-btn ' + (_schedPage === 0 ? 'disabled' : '') + '" onclick="_schedPrev()">Prev</button>' +
|
|
229
|
+
'<button class="pr-pager-btn ' + (_schedPage >= totalPages-1 ? 'disabled' : '') + '" onclick="_schedNext()">Next</button>' +
|
|
230
|
+
'</div>' +
|
|
231
|
+
'</div>';
|
|
232
|
+
}
|
|
233
|
+
|
|
213
234
|
el.innerHTML = html;
|
|
214
|
-
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function _schedPrev() { if (_schedPage > 0) { _schedPage--; renderSchedules(window._lastSchedules || []); } }
|
|
238
|
+
function _schedNext() { var tp = Math.ceil((window._lastSchedules || []).length / SCHED_PER_PAGE); if (_schedPage < tp-1) { _schedPage++; renderSchedules(window._lastSchedules || []); } }
|
|
239
|
+
|
|
240
|
+
function openScheduleDetail(id) {
|
|
241
|
+
const s = (window._lastSchedules || []).find(x => x.id === id);
|
|
242
|
+
if (!s) return;
|
|
243
|
+
const humanCron = _cronToHuman(s.cron || '');
|
|
244
|
+
const lastRun = s._lastRun ? new Date(s._lastRun).toLocaleString() : 'never';
|
|
245
|
+
const enabledLabel = s.enabled ? '<span class="pr-badge approved">enabled</span>' : '<span class="pr-badge rejected">disabled</span>';
|
|
246
|
+
|
|
247
|
+
document.getElementById('modal-title').innerHTML = escHtml(s.title || s.id) +
|
|
248
|
+
' <div style="display:flex;gap:4px;margin-top:4px">' +
|
|
249
|
+
'<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--blue)" onclick="closeModal();openEditScheduleModal(\'' + escHtml(s.id) + '\')">Edit</button>' +
|
|
250
|
+
'<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:' + (s.enabled ? 'var(--yellow)' : 'var(--green)') + '" onclick="toggleScheduleEnabled(\'' + escHtml(s.id) + '\',' + !s.enabled + ');closeModal()">' + (s.enabled ? 'Disable' : 'Enable') + '</button>' +
|
|
251
|
+
'<button class="pr-pager-btn" style="font-size:10px;padding:2px 10px;color:var(--red)" onclick="deleteSchedule(\'' + escHtml(s.id) + '\');closeModal()">Delete</button>' +
|
|
252
|
+
'</div>';
|
|
253
|
+
|
|
254
|
+
var body = '<div style="display:flex;flex-direction:column;gap:10px;font-size:12px;line-height:1.6">' +
|
|
255
|
+
'<div><strong style="color:var(--muted)">ID:</strong> ' + escHtml(s.id) + '</div>' +
|
|
256
|
+
'<div><strong style="color:var(--muted)">Schedule:</strong> <span style="color:var(--blue)">' + escHtml(humanCron) + '</span> <code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:10px">' + escHtml(s.cron || '') + '</code></div>' +
|
|
257
|
+
'<div><strong style="color:var(--muted)">Type:</strong> <span class="dispatch-type ' + escHtml(s.type || 'implement') + '">' + escHtml(s.type || 'implement') + '</span></div>' +
|
|
258
|
+
'<div><strong style="color:var(--muted)">Priority:</strong> ' + escHtml(s.priority || 'medium') + '</div>' +
|
|
259
|
+
'<div><strong style="color:var(--muted)">Project:</strong> ' + escHtml(s.project || 'any') + '</div>' +
|
|
260
|
+
'<div><strong style="color:var(--muted)">Agent:</strong> ' + escHtml(s.agent || 'auto') + '</div>' +
|
|
261
|
+
'<div><strong style="color:var(--muted)">Status:</strong> ' + enabledLabel + '</div>' +
|
|
262
|
+
'<div><strong style="color:var(--muted)">Last Run:</strong> ' + escHtml(lastRun) + '</div>' +
|
|
263
|
+
(s.description ? '<div><strong style="color:var(--muted)">Description:</strong><div style="margin-top:4px;padding:8px;background:var(--surface2);border-radius:4px">' + renderMd(s.description) + '</div></div>' : '') +
|
|
264
|
+
'</div>';
|
|
265
|
+
|
|
266
|
+
document.getElementById('modal-body').innerHTML = body;
|
|
267
|
+
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
268
|
+
document.getElementById('modal-body').style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
269
|
+
document.getElementById('modal').classList.add('open');
|
|
215
270
|
}
|
|
216
271
|
|
|
217
272
|
// ─── Form ───────────────────────────────────────────────────────────────────
|
|
@@ -405,4 +460,4 @@ async function deleteSchedule(id) {
|
|
|
405
460
|
// Expose _generateScheduleId globally for the inline oninput handler
|
|
406
461
|
window._generateScheduleId = _generateScheduleId;
|
|
407
462
|
|
|
408
|
-
window.MinionsSchedules = { renderSchedules, openCreateScheduleModal, openEditScheduleModal, submitSchedule, toggleScheduleEnabled, deleteSchedule, _cronToHuman, _parseNaturalCron, _toggleCronMode, _quickSelectDays, _toggleDayPill, _updateCronPreview };
|
|
463
|
+
window.MinionsSchedules = { renderSchedules, openCreateScheduleModal, openEditScheduleModal, openScheduleDetail, submitSchedule, toggleScheduleEnabled, deleteSchedule, _cronToHuman, _parseNaturalCron, _toggleCronMode, _quickSelectDays, _toggleDayPill, _updateCronPreview, _schedPrev, _schedNext };
|
package/dashboard/js/utils.js
CHANGED
|
@@ -114,6 +114,33 @@ function renderMd(s) {
|
|
|
114
114
|
continue;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
// Table: detect | col | col | rows, consume until non-table line
|
|
118
|
+
if (line.match(/^\|.+\|/)) {
|
|
119
|
+
closeList();
|
|
120
|
+
var tableRows = [];
|
|
121
|
+
var sepIdx = -1;
|
|
122
|
+
while (i < lines.length && lines[i].match(/^\|.+\|/)) {
|
|
123
|
+
var row = lines[i].replace(/^\|/, '').replace(/\|$/, '').split('|').map(function(c) { return c.trim(); });
|
|
124
|
+
if (lines[i].match(/^\|[\s:]*-{2,}[\s:]*\|/)) { sepIdx = tableRows.length; }
|
|
125
|
+
else { tableRows.push(row); }
|
|
126
|
+
i++;
|
|
127
|
+
}
|
|
128
|
+
i--; // back up one since the for loop will increment
|
|
129
|
+
var tableHtml = '<table class="pr-table" style="margin:4px 0;font-size:11px"><thead><tr>';
|
|
130
|
+
if (tableRows.length > 0) {
|
|
131
|
+
tableRows[0].forEach(function(c) { tableHtml += '<th>' + c + '</th>'; });
|
|
132
|
+
tableHtml += '</tr></thead><tbody>';
|
|
133
|
+
for (var ti = 1; ti < tableRows.length; ti++) {
|
|
134
|
+
tableHtml += '<tr>';
|
|
135
|
+
tableRows[ti].forEach(function(c) { tableHtml += '<td>' + c + '</td>'; });
|
|
136
|
+
tableHtml += '</tr>';
|
|
137
|
+
}
|
|
138
|
+
tableHtml += '</tbody></table>';
|
|
139
|
+
}
|
|
140
|
+
out.push(tableHtml);
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
|
|
117
144
|
// Checkbox list (must come before UL — both start with - )
|
|
118
145
|
var cbMatch = line.match(/^(\s*)[-*]\s\[([ xX])\]\s(.+)/);
|
|
119
146
|
if (cbMatch) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.110",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|