@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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.110 (2026-04-01)
4
+
5
+ ### Dashboard
6
+ - dashboard/js/render-schedules.js
7
+
8
+ ## 0.1.109 (2026-04-01)
9
+
10
+ ### Dashboard
11
+ - dashboard/js/utils.js
12
+
3
13
  ## 0.1.108 (2026-04-01)
4
14
 
5
15
  ### Dashboard
@@ -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 schedules) {
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
- window._lastSchedules = schedules;
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 };
@@ -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.108",
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"