@yemi33/minions 0.1.2396 → 0.1.2397
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/dashboard/js/refresh.js +2 -1
- package/dashboard/js/render-prs.js +102 -11
- package/dashboard/pages/prs.html +29 -0
- package/dashboard/shared/pr-filters.js +166 -0
- package/dashboard/styles.css +29 -1
- package/dashboard-build.js +1 -1
- package/dashboard.js +1 -1
- package/package.json +1 -1
package/dashboard/js/refresh.js
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
// render-prs.js — PR tracker rendering functions extracted from dashboard.html
|
|
2
2
|
|
|
3
3
|
let allPrs = [];
|
|
4
|
+
let filteredPrs = [];
|
|
4
5
|
let prPage = 0;
|
|
6
|
+
let prFilterOptionsSignature = '';
|
|
5
7
|
const PR_PER_PAGE = 25;
|
|
8
|
+
const PR_FILTER_CONTROL_IDS = {
|
|
9
|
+
author: 'pr-filter-author',
|
|
10
|
+
lifecycle: 'pr-filter-lifecycle',
|
|
11
|
+
project: 'pr-filter-project',
|
|
12
|
+
review: 'pr-filter-review',
|
|
13
|
+
build: 'pr-filter-build',
|
|
14
|
+
};
|
|
15
|
+
const PR_FILTER_ALL_LABELS = {
|
|
16
|
+
author: 'All authors',
|
|
17
|
+
lifecycle: 'All lifecycle statuses',
|
|
18
|
+
project: 'All projects',
|
|
19
|
+
review: 'All review statuses',
|
|
20
|
+
build: 'All build statuses',
|
|
21
|
+
};
|
|
6
22
|
|
|
7
23
|
// Fetch each project's pull-requests.json straight off disk through the
|
|
8
24
|
// /state/projects/<name>/pull-requests.json static-file passthrough. This
|
|
@@ -373,32 +389,105 @@ function _restorePrScrollState(el, state) {
|
|
|
373
389
|
tableWrap.scrollTop = state.top || 0;
|
|
374
390
|
}
|
|
375
391
|
|
|
392
|
+
function _syncPrFilterOptions(prs) {
|
|
393
|
+
const options = getPrFilterOptions(prs);
|
|
394
|
+
const controls = Object.keys(PR_FILTER_CONTROL_IDS).map(function(dimension) {
|
|
395
|
+
return {
|
|
396
|
+
dimension,
|
|
397
|
+
select: document.getElementById(PR_FILTER_CONTROL_IDS[dimension]),
|
|
398
|
+
};
|
|
399
|
+
}).filter(function(entry) { return entry.select; });
|
|
400
|
+
if (!controls.length) return;
|
|
401
|
+
const signature = JSON.stringify(options);
|
|
402
|
+
if (signature === prFilterOptionsSignature) return;
|
|
403
|
+
prFilterOptionsSignature = signature;
|
|
404
|
+
controls.forEach(function(entry) {
|
|
405
|
+
const dimension = entry.dimension;
|
|
406
|
+
const select = entry.select;
|
|
407
|
+
const selected = select.value;
|
|
408
|
+
const all = document.createElement('option');
|
|
409
|
+
all.value = '';
|
|
410
|
+
all.textContent = PR_FILTER_ALL_LABELS[dimension];
|
|
411
|
+
const nodes = [all].concat((options[dimension] || []).map(function(option) {
|
|
412
|
+
const node = document.createElement('option');
|
|
413
|
+
node.value = option.value;
|
|
414
|
+
node.textContent = option.label;
|
|
415
|
+
return node;
|
|
416
|
+
}));
|
|
417
|
+
select.replaceChildren(...nodes);
|
|
418
|
+
if (nodes.some(function(node) { return node.value === selected; })) select.value = selected;
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function _readPrFilters() {
|
|
423
|
+
const filters = {};
|
|
424
|
+
Object.keys(PR_FILTER_CONTROL_IDS).forEach(function(dimension) {
|
|
425
|
+
const select = document.getElementById(PR_FILTER_CONTROL_IDS[dimension]);
|
|
426
|
+
filters[dimension] = select ? select.value : '';
|
|
427
|
+
});
|
|
428
|
+
return filters;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function _hasActivePrFilters(filters) {
|
|
432
|
+
return Object.keys(PR_FILTER_CONTROL_IDS).some(function(dimension) {
|
|
433
|
+
return Boolean(filters[dimension]);
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function applyPrFilters() {
|
|
438
|
+
prPage = 0;
|
|
439
|
+
renderPrs(allPrs, { preserveScroll: false });
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
function resetPrFilters() {
|
|
443
|
+
Object.keys(PR_FILTER_CONTROL_IDS).forEach(function(dimension) {
|
|
444
|
+
const select = document.getElementById(PR_FILTER_CONTROL_IDS[dimension]);
|
|
445
|
+
if (select) select.value = '';
|
|
446
|
+
});
|
|
447
|
+
applyPrFilters();
|
|
448
|
+
}
|
|
449
|
+
|
|
376
450
|
function renderPrs(prs, opts) {
|
|
377
451
|
opts = opts || {};
|
|
378
|
-
prs = prs.filter(p => !isDeleted('pr:' + p.id));
|
|
452
|
+
prs = Array.isArray(prs) ? prs.filter(p => p && !isDeleted('pr:' + p.id)) : [];
|
|
379
453
|
allPrs = prs;
|
|
454
|
+
_syncPrFilterOptions(allPrs);
|
|
455
|
+
const filters = _readPrFilters();
|
|
456
|
+
filteredPrs = filterPullRequests(allPrs, filters);
|
|
380
457
|
const el = document.getElementById('pr-content');
|
|
381
458
|
const count = document.getElementById('pr-count');
|
|
382
|
-
|
|
383
|
-
|
|
459
|
+
const summary = document.getElementById('pr-filter-summary');
|
|
460
|
+
count.textContent = filteredPrs.length;
|
|
461
|
+
if (summary) {
|
|
462
|
+
summary.textContent = _hasActivePrFilters(filters)
|
|
463
|
+
? 'Showing ' + filteredPrs.length + ' of ' + allPrs.length
|
|
464
|
+
: '';
|
|
465
|
+
}
|
|
466
|
+
if (!allPrs.length) {
|
|
467
|
+
prPage = 0;
|
|
384
468
|
el.innerHTML = '<p class="pr-empty">No pull requests yet. PRs created by agents will appear here with review, build, and merge status.</p>';
|
|
385
469
|
return;
|
|
386
470
|
}
|
|
387
|
-
|
|
471
|
+
if (!filteredPrs.length) {
|
|
472
|
+
prPage = 0;
|
|
473
|
+
el.innerHTML = '<p class="pr-empty">No pull requests match the selected filters.</p>';
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const totalPages = Math.ceil(filteredPrs.length / PR_PER_PAGE);
|
|
388
477
|
const previousPage = prPage;
|
|
389
478
|
if (prPage >= totalPages) prPage = totalPages - 1;
|
|
390
479
|
const start = prPage * PR_PER_PAGE;
|
|
391
|
-
const pagePrs =
|
|
480
|
+
const pagePrs = filteredPrs.slice(start, start + PR_PER_PAGE);
|
|
392
481
|
const rows = pagePrs.map(prRow).join('');
|
|
393
482
|
|
|
394
483
|
let pager = '';
|
|
395
|
-
if (
|
|
484
|
+
if (filteredPrs.length > PR_PER_PAGE) {
|
|
396
485
|
pager = '<div class="pr-pager">' +
|
|
397
|
-
'<span class="pr-page-info">Showing ' + (start+1) + ' to ' + Math.min(start+PR_PER_PAGE,
|
|
486
|
+
'<span class="pr-page-info">Showing ' + (start+1) + ' to ' + Math.min(start+PR_PER_PAGE, filteredPrs.length) + ' of ' + filteredPrs.length + '</span>' +
|
|
398
487
|
'<div class="pr-pager-btns">' +
|
|
399
488
|
'<button class="pr-pager-btn ' + (prPage === 0 ? 'disabled' : '') + '" onclick="prPrev()">Prev</button>' +
|
|
400
489
|
'<button class="pr-pager-btn ' + (prPage >= totalPages-1 ? 'disabled' : '') + '" onclick="prNext()">Next</button>' +
|
|
401
|
-
'<button class="pr-pager-btn see-all" onclick="openAllPrs()">See all ' +
|
|
490
|
+
'<button class="pr-pager-btn see-all" onclick="openAllPrs()">See all ' + filteredPrs.length + ' PRs</button>' +
|
|
402
491
|
'</div>' +
|
|
403
492
|
'</div>';
|
|
404
493
|
}
|
|
@@ -412,14 +501,14 @@ function renderPrs(prs, opts) {
|
|
|
412
501
|
}
|
|
413
502
|
|
|
414
503
|
function prPrev() { if (prPage > 0) { prPage--; renderPrs(allPrs, { preserveScroll: false }); } }
|
|
415
|
-
function prNext() { const totalPages = Math.ceil(
|
|
504
|
+
function prNext() { const totalPages = Math.ceil(filteredPrs.length / PR_PER_PAGE); if (prPage < totalPages-1) { prPage++; renderPrs(allPrs, { preserveScroll: false }); } }
|
|
416
505
|
|
|
417
506
|
function openAllPrs() {
|
|
418
507
|
const modalEl = document.querySelector('#modal .modal');
|
|
419
508
|
if (modalEl) modalEl.classList.add('modal-wide');
|
|
420
|
-
document.getElementById('modal-title').textContent = 'All Pull Requests (' +
|
|
509
|
+
document.getElementById('modal-title').textContent = 'All Pull Requests (' + filteredPrs.length + ')';
|
|
421
510
|
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all PR user data wrapped in escapeHtml() by prRow() (fields: PR id, title, description, agent, branch, review/build/status labels)
|
|
422
|
-
document.getElementById('modal-body').innerHTML = prTableHtml(
|
|
511
|
+
document.getElementById('modal-body').innerHTML = prTableHtml(filteredPrs.map(prRow).join(''));
|
|
423
512
|
document.getElementById('modal-body').style.fontFamily = "'Segoe UI', system-ui, sans-serif";
|
|
424
513
|
document.getElementById('modal-body').style.whiteSpace = 'normal';
|
|
425
514
|
document.getElementById('modal').classList.add('open');
|
|
@@ -862,6 +951,8 @@ window.MinionsPrs = {
|
|
|
862
951
|
prRow,
|
|
863
952
|
prTableHtml,
|
|
864
953
|
renderPrs,
|
|
954
|
+
applyPrFilters,
|
|
955
|
+
resetPrFilters,
|
|
865
956
|
renderPrDetail: _renderPrDetail, // exported for testing
|
|
866
957
|
prPrev,
|
|
867
958
|
prNext,
|
package/dashboard/pages/prs.html
CHANGED
|
@@ -4,5 +4,34 @@
|
|
|
4
4
|
<span style="font-size:var(--text-sm);color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0">created by agents, tracked with review + build status</span>
|
|
5
5
|
</h2>
|
|
6
6
|
<div id="pr-toast" class="cmd-toast cmd-toast-inline" style="margin:6px 0"></div>
|
|
7
|
+
<div class="pr-filters" role="group" aria-label="Pull request filters">
|
|
8
|
+
<label class="pr-filter">Author
|
|
9
|
+
<select id="pr-filter-author" onchange="applyPrFilters()">
|
|
10
|
+
<option value="">All authors</option>
|
|
11
|
+
</select>
|
|
12
|
+
</label>
|
|
13
|
+
<label class="pr-filter">Lifecycle
|
|
14
|
+
<select id="pr-filter-lifecycle" onchange="applyPrFilters()">
|
|
15
|
+
<option value="">All lifecycle statuses</option>
|
|
16
|
+
</select>
|
|
17
|
+
</label>
|
|
18
|
+
<label class="pr-filter">Project
|
|
19
|
+
<select id="pr-filter-project" onchange="applyPrFilters()">
|
|
20
|
+
<option value="">All projects</option>
|
|
21
|
+
</select>
|
|
22
|
+
</label>
|
|
23
|
+
<label class="pr-filter">Review
|
|
24
|
+
<select id="pr-filter-review" onchange="applyPrFilters()">
|
|
25
|
+
<option value="">All review statuses</option>
|
|
26
|
+
</select>
|
|
27
|
+
</label>
|
|
28
|
+
<label class="pr-filter">Build
|
|
29
|
+
<select id="pr-filter-build" onchange="applyPrFilters()">
|
|
30
|
+
<option value="">All build statuses</option>
|
|
31
|
+
</select>
|
|
32
|
+
</label>
|
|
33
|
+
<button class="pr-filter-reset" type="button" onclick="resetPrFilters()">Reset filters</button>
|
|
34
|
+
<span class="pr-filter-summary" id="pr-filter-summary" aria-live="polite"></span>
|
|
35
|
+
</div>
|
|
7
36
|
<div id="pr-content"><p class="pr-empty">No pull requests yet.</p></div>
|
|
8
37
|
</section>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Shared PR filter semantics. Slim embeds the classic /prs screen, and both
|
|
2
|
+
// bundles load this helper so lifecycle and legacy-field normalization stay
|
|
3
|
+
// identical across surfaces.
|
|
4
|
+
var PR_FILTER_DIMENSIONS = ['author', 'lifecycle', 'project', 'review', 'build'];
|
|
5
|
+
var PR_LIFECYCLE_FILTER_LABELS = {
|
|
6
|
+
open: 'Open / active',
|
|
7
|
+
merged: 'Merged',
|
|
8
|
+
closed: 'Closed',
|
|
9
|
+
};
|
|
10
|
+
var PR_FILTER_OPTION_ORDER = {
|
|
11
|
+
lifecycle: ['open', 'merged', 'closed'],
|
|
12
|
+
review: ['approved', 'changes-requested', 'waiting', 'pending'],
|
|
13
|
+
build: ['passing', 'failing', 'running', 'none'],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function _prFilterText(value) {
|
|
17
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function _prFilterName(value) {
|
|
21
|
+
var direct = _prFilterText(value);
|
|
22
|
+
if (direct) return direct;
|
|
23
|
+
if (!value || typeof value !== 'object') return '';
|
|
24
|
+
return _prFilterText(value.login)
|
|
25
|
+
|| _prFilterText(value.displayName)
|
|
26
|
+
|| _prFilterText(value.uniqueName)
|
|
27
|
+
|| _prFilterText(value.name);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function _prFilterKey(value) {
|
|
31
|
+
return _prFilterText(value).toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function normalizePrAuthor(pr) {
|
|
35
|
+
if (!pr || typeof pr !== 'object') return '';
|
|
36
|
+
return _prFilterName(pr.author)
|
|
37
|
+
|| _prFilterName(pr.createdBy)
|
|
38
|
+
|| _prFilterName(pr.created_by)
|
|
39
|
+
|| _prFilterName(pr.agent);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function normalizePrLifecycleStatus(pr) {
|
|
43
|
+
if (!pr || typeof pr !== 'object') return '';
|
|
44
|
+
var status = _prFilterKey(pr.status || pr.state);
|
|
45
|
+
if (pr.merged === true || pr.isMerged === true || pr.mergedAt || pr.merged_at
|
|
46
|
+
|| status === 'merged' || status === 'completed') {
|
|
47
|
+
return 'merged';
|
|
48
|
+
}
|
|
49
|
+
if (status === 'active' || status === 'open' || status === 'linked') return 'open';
|
|
50
|
+
if (status === 'closed' || status === 'abandoned' || status === 'declined') return 'closed';
|
|
51
|
+
return status;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function normalizePrProject(pr) {
|
|
55
|
+
if (!pr || typeof pr !== 'object') return '';
|
|
56
|
+
return _prFilterText(pr._project)
|
|
57
|
+
|| _prFilterText(pr.project)
|
|
58
|
+
|| _prFilterText(pr.sourceProject);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function normalizePrReviewStatus(pr) {
|
|
62
|
+
if (!pr || typeof pr !== 'object') return '';
|
|
63
|
+
var minionsStatus = pr.minionsReview && _prFilterText(pr.minionsReview.status);
|
|
64
|
+
var status = _prFilterKey(minionsStatus || pr.reviewStatus || pr.review_status);
|
|
65
|
+
if (!minionsStatus && status === 'waiting') {
|
|
66
|
+
if (normalizePrLifecycleStatus(pr) === 'merged') return 'approved';
|
|
67
|
+
if (_prFilterKey(pr.status) === 'abandoned') return 'pending';
|
|
68
|
+
}
|
|
69
|
+
if (status === 'approve') return 'approved';
|
|
70
|
+
if (status === 'rejected' || status === 'changes_requested'
|
|
71
|
+
|| status === 'requested-changes' || status === 'changesrequired') {
|
|
72
|
+
return 'changes-requested';
|
|
73
|
+
}
|
|
74
|
+
if (status === 'reviewing') return 'waiting';
|
|
75
|
+
return status;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizePrBuildStatus(pr) {
|
|
79
|
+
if (!pr || typeof pr !== 'object') return '';
|
|
80
|
+
var status = _prFilterKey(pr.buildStatus || pr.build_status);
|
|
81
|
+
if (status === 'success' || status === 'succeeded') return 'passing';
|
|
82
|
+
if (status === 'failed' || status === 'error') return 'failing';
|
|
83
|
+
if (status === 'in-progress' || status === 'in_progress' || status === 'queued') return 'running';
|
|
84
|
+
if (status === 'not-run' || status === 'not_run') return 'none';
|
|
85
|
+
return status;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function _prFilterEntry(pr, dimension) {
|
|
89
|
+
var label = '';
|
|
90
|
+
var value = '';
|
|
91
|
+
if (dimension === 'author') {
|
|
92
|
+
label = normalizePrAuthor(pr);
|
|
93
|
+
value = _prFilterKey(label);
|
|
94
|
+
} else if (dimension === 'lifecycle') {
|
|
95
|
+
value = normalizePrLifecycleStatus(pr);
|
|
96
|
+
label = PR_LIFECYCLE_FILTER_LABELS[value] || _formatPrFilterLabel(value);
|
|
97
|
+
} else if (dimension === 'project') {
|
|
98
|
+
label = normalizePrProject(pr);
|
|
99
|
+
value = _prFilterKey(label);
|
|
100
|
+
} else if (dimension === 'review') {
|
|
101
|
+
value = normalizePrReviewStatus(pr);
|
|
102
|
+
label = _formatPrFilterLabel(value);
|
|
103
|
+
} else if (dimension === 'build') {
|
|
104
|
+
value = normalizePrBuildStatus(pr);
|
|
105
|
+
label = _formatPrFilterLabel(value);
|
|
106
|
+
}
|
|
107
|
+
return value ? { value: value, label: label || value } : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function _formatPrFilterLabel(value) {
|
|
111
|
+
var text = _prFilterText(value).replace(/[-_]+/g, ' ');
|
|
112
|
+
return text ? text.charAt(0).toUpperCase() + text.slice(1) : '';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getPrFilterValue(pr, dimension) {
|
|
116
|
+
var entry = _prFilterEntry(pr, dimension);
|
|
117
|
+
return entry ? entry.value : '';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function matchesPullRequestFilters(pr, filters) {
|
|
121
|
+
filters = filters || {};
|
|
122
|
+
for (var i = 0; i < PR_FILTER_DIMENSIONS.length; i++) {
|
|
123
|
+
var dimension = PR_FILTER_DIMENSIONS[i];
|
|
124
|
+
var selected = _prFilterKey(filters[dimension]);
|
|
125
|
+
if (selected && getPrFilterValue(pr, dimension) !== selected) return false;
|
|
126
|
+
}
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function filterPullRequests(prs, filters) {
|
|
131
|
+
if (!Array.isArray(prs)) return [];
|
|
132
|
+
return prs.filter(function(pr) { return matchesPullRequestFilters(pr, filters); });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function getPrFilterOptions(prs) {
|
|
136
|
+
var result = {};
|
|
137
|
+
var records = Array.isArray(prs) ? prs : [];
|
|
138
|
+
PR_FILTER_DIMENSIONS.forEach(function(dimension) {
|
|
139
|
+
var seen = new Map();
|
|
140
|
+
records.forEach(function(pr) {
|
|
141
|
+
var entry = _prFilterEntry(pr, dimension);
|
|
142
|
+
if (entry && !seen.has(entry.value)) seen.set(entry.value, entry);
|
|
143
|
+
});
|
|
144
|
+
var order = PR_FILTER_OPTION_ORDER[dimension] || [];
|
|
145
|
+
result[dimension] = Array.from(seen.values()).sort(function(a, b) {
|
|
146
|
+
var ai = order.indexOf(a.value);
|
|
147
|
+
var bi = order.indexOf(b.value);
|
|
148
|
+
if (ai !== -1 || bi !== -1) {
|
|
149
|
+
if (ai === -1) return 1;
|
|
150
|
+
if (bi === -1) return -1;
|
|
151
|
+
if (ai !== bi) return ai - bi;
|
|
152
|
+
}
|
|
153
|
+
return a.label.localeCompare(b.label, undefined, { sensitivity: 'base' });
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
window.MinionsPrFilters = {
|
|
160
|
+
author: normalizePrAuthor,
|
|
161
|
+
normalizeLifecycle: normalizePrLifecycleStatus,
|
|
162
|
+
value: getPrFilterValue,
|
|
163
|
+
matches: matchesPullRequestFilters,
|
|
164
|
+
filter: filterPullRequests,
|
|
165
|
+
options: getPrFilterOptions,
|
|
166
|
+
};
|
package/dashboard/styles.css
CHANGED
|
@@ -322,6 +322,34 @@
|
|
|
322
322
|
.prd-pending { color: var(--yellow); font-style: italic; }
|
|
323
323
|
|
|
324
324
|
/* PR Tracker */
|
|
325
|
+
.pr-filters {
|
|
326
|
+
display: flex; flex-wrap: wrap; align-items: end; gap: var(--space-4);
|
|
327
|
+
padding: var(--space-4) 0 var(--space-6);
|
|
328
|
+
}
|
|
329
|
+
.pr-filter {
|
|
330
|
+
display: grid; gap: var(--space-1); min-width: 140px;
|
|
331
|
+
color: var(--muted); font-size: var(--text-sm); font-weight: 600;
|
|
332
|
+
}
|
|
333
|
+
.pr-filter select {
|
|
334
|
+
min-height: 32px; padding: var(--space-2) var(--space-4);
|
|
335
|
+
color: var(--text); background: var(--surface2);
|
|
336
|
+
border: 1px solid var(--border); border-radius: var(--radius-sm);
|
|
337
|
+
font: inherit; font-weight: 400;
|
|
338
|
+
}
|
|
339
|
+
.pr-filter select:focus-visible, .pr-filter-reset:focus-visible {
|
|
340
|
+
outline: 2px solid var(--blue); outline-offset: 2px;
|
|
341
|
+
}
|
|
342
|
+
.pr-filter-reset {
|
|
343
|
+
min-height: 32px; padding: var(--space-2) var(--space-5);
|
|
344
|
+
color: var(--blue); background: transparent;
|
|
345
|
+
border: 1px solid var(--blue); border-radius: var(--radius-sm);
|
|
346
|
+
cursor: pointer; font-size: var(--text-base);
|
|
347
|
+
}
|
|
348
|
+
.pr-filter-reset:hover { background: rgba(88,166,255,0.1); }
|
|
349
|
+
.pr-filter-summary {
|
|
350
|
+
min-height: 32px; display: inline-flex; align-items: center;
|
|
351
|
+
color: var(--muted); font-size: var(--text-base);
|
|
352
|
+
}
|
|
325
353
|
.pr-table-wrap { overflow-x: auto; }
|
|
326
354
|
.pr-table { width: 100%; border-collapse: collapse; font-size: var(--text-md); table-layout: auto; }
|
|
327
355
|
.pr-table th:last-child, .pr-table td:last-child { width: 36px; min-width: 36px; text-align: center; }
|
|
@@ -348,7 +376,7 @@
|
|
|
348
376
|
wrap) stay visible while the user is on this page. The modal "see all"
|
|
349
377
|
view uses the same colgroup but is unaffected — modal-body handles its
|
|
350
378
|
own scrolling. */
|
|
351
|
-
#pr-content .pr-table-wrap--prs { max-height: calc(100vh -
|
|
379
|
+
#pr-content .pr-table-wrap--prs { max-height: calc(100vh - 270px); overflow: auto; }
|
|
352
380
|
#pr-content .pr-table--prs thead th { position: sticky; top: 0; background: var(--surface); z-index: 1; }
|
|
353
381
|
.pr-table th { text-align: left; color: var(--muted); font-weight: 500; font-size: var(--text-base); text-transform: uppercase; letter-spacing: 0.5px; padding: var(--space-4) var(--space-5); border-bottom: 1px solid var(--border); }
|
|
354
382
|
.pr-table td { padding: var(--space-5); border-bottom: 1px solid var(--border); vertical-align: middle; white-space: nowrap; }
|
package/dashboard-build.js
CHANGED
|
@@ -8,7 +8,7 @@ const shared = require('./engine/shared');
|
|
|
8
8
|
const { safeRead } = shared;
|
|
9
9
|
|
|
10
10
|
const MINIONS_DIR = __dirname;
|
|
11
|
-
const DASHBOARD_SHARED_JS = ['pr-merge-state'];
|
|
11
|
+
const DASHBOARD_SHARED_JS = ['pr-merge-state', 'pr-filters'];
|
|
12
12
|
|
|
13
13
|
function buildDashboardHtml() {
|
|
14
14
|
const dashDir = path.join(MINIONS_DIR, 'dashboard');
|
package/dashboard.js
CHANGED
|
@@ -1796,7 +1796,7 @@ function buildDashboardHtml() {
|
|
|
1796
1796
|
'confirm-dialog', 'modal', 'modal-qa', 'settings', 'qa', 'fre', 'refresh'
|
|
1797
1797
|
];
|
|
1798
1798
|
let jsHtml = '';
|
|
1799
|
-
for (const f of ['pr-merge-state']) {
|
|
1799
|
+
for (const f of ['pr-merge-state', 'pr-filters']) {
|
|
1800
1800
|
const content = safeRead(path.join(dashDir, 'shared', f + '.js'));
|
|
1801
1801
|
jsHtml += `\n// ─── shared/${f}.js ────────────────────────────────────────\n${content}\n`;
|
|
1802
1802
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2397",
|
|
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"
|