@a83/orbiter-admin 0.3.45 → 0.3.47
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/package.json +1 -1
- package/public/style.css +32 -0
- package/public/xfce.js +142 -21
package/package.json
CHANGED
package/public/style.css
CHANGED
|
@@ -2023,6 +2023,12 @@ a.xfce-sb-logo:hover { opacity: .8; }
|
|
|
2023
2023
|
font-family: var(--mono); transition: background .15s;
|
|
2024
2024
|
}
|
|
2025
2025
|
.xfce-sb-palette-btn:hover { background: color-mix(in srgb, var(--accent) 14%, transparent); }
|
|
2026
|
+
.xfce-sb-cheat {
|
|
2027
|
+
background: none; border: none; cursor: pointer; padding: 0 3px;
|
|
2028
|
+
font-size: 13px; color: var(--muted); font-family: var(--mono); line-height: 1;
|
|
2029
|
+
transition: color .15s;
|
|
2030
|
+
}
|
|
2031
|
+
.xfce-sb-cheat:hover { color: var(--accent); }
|
|
2026
2032
|
|
|
2027
2033
|
/* Draft badge on dock items */
|
|
2028
2034
|
.xfce-dock-badge {
|
|
@@ -2335,6 +2341,32 @@ html[data-zen="1"] .main {
|
|
|
2335
2341
|
.xfce-notif-err .xfce-notif-msg { color: var(--red); }
|
|
2336
2342
|
.xfce-notif-empty { padding: 20px 12px; color: var(--muted); font-size: 10px; text-align: center; }
|
|
2337
2343
|
|
|
2344
|
+
/* ── Build indicator — running state ────────────────────── */
|
|
2345
|
+
.xfce-sb-build--running {
|
|
2346
|
+
color: var(--accent) !important;
|
|
2347
|
+
animation: xfce-blink .9s step-end infinite;
|
|
2348
|
+
}
|
|
2349
|
+
|
|
2350
|
+
/* ── Status bar breadcrumb ───────────────────────────────── */
|
|
2351
|
+
.xfce-sb-crumb-link {
|
|
2352
|
+
color: var(--accent); text-decoration: none; font-family: var(--mono); font-size: 11px;
|
|
2353
|
+
}
|
|
2354
|
+
.xfce-sb-crumb-link:hover { text-decoration: underline; }
|
|
2355
|
+
.xfce-sb-crumb-sep { color: var(--muted); font-size: 10px; margin: 0 2px; }
|
|
2356
|
+
.xfce-sb-crumb-page { color: var(--text); font-family: var(--mono); font-size: 11px; }
|
|
2357
|
+
|
|
2358
|
+
/* ── HUD Activity feed ───────────────────────────────────── */
|
|
2359
|
+
.xfce-hud-act-row {
|
|
2360
|
+
display: flex; align-items: baseline; justify-content: space-between;
|
|
2361
|
+
gap: 8px; padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,.04);
|
|
2362
|
+
font-size: 10px; font-family: var(--mono);
|
|
2363
|
+
}
|
|
2364
|
+
.xfce-hud-act-row:last-child { border-bottom: none; }
|
|
2365
|
+
.xfce-hud-act-msg { flex: 1; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2366
|
+
.xfce-hud-act-time { color: var(--line); font-size: 9px; flex-shrink: 0; }
|
|
2367
|
+
.xfce-hud-act-ok .xfce-hud-act-msg { color: var(--jade, #5dc97e); }
|
|
2368
|
+
.xfce-hud-act-err .xfce-hud-act-msg { color: var(--red, #e06c6c); }
|
|
2369
|
+
|
|
2338
2370
|
/* ── HUD Drafts section ──────────────────────────────────── */
|
|
2339
2371
|
.xfce-hud-draft-row {
|
|
2340
2372
|
display: flex; align-items: baseline; justify-content: space-between;
|
package/public/xfce.js
CHANGED
|
@@ -64,9 +64,11 @@
|
|
|
64
64
|
'</div>',
|
|
65
65
|
'<div class="xfce-sb-center" id="xfce-sb-title"></div>',
|
|
66
66
|
'<div class="xfce-sb-right">',
|
|
67
|
-
'<span id="xfce-sb-g-ind" class="xfce-sb-g-ind" style="display:none" title="g mode: d=dashboard m=media s=settings u=users b=build i=import
|
|
67
|
+
'<span id="xfce-sb-g-ind" class="xfce-sb-g-ind" style="display:none" title="g mode: d=dashboard m=media s=settings u=users b=build i=import c=schema h=HUD a=account">g ›</span>',
|
|
68
68
|
'<button id="xfce-sb-bell" class="xfce-sb-bell" title="Notifications"><span id="xfce-sb-bell-icon">○</span><span id="xfce-sb-bell-badge" class="xfce-sb-bell-badge" style="display:none"></span></button>',
|
|
69
69
|
'<span class="xfce-sb-div">·</span>',
|
|
70
|
+
'<button id="xfce-sb-cheat" class="xfce-sb-cheat" title="Shortcuts (?)">?</button>',
|
|
71
|
+
'<span class="xfce-sb-div">·</span>',
|
|
70
72
|
'<button id="xfce-sb-palette-btn" class="xfce-sb-palette-btn" title="Command palette (⌘K)">⌘</button>',
|
|
71
73
|
'<span class="xfce-sb-div">·</span>',
|
|
72
74
|
'<span id="xfce-sb-build" class="xfce-sb-build" title="Last build"></span>',
|
|
@@ -80,10 +82,18 @@
|
|
|
80
82
|
].join('');
|
|
81
83
|
document.body.insertBefore(sb, document.body.firstChild);
|
|
82
84
|
|
|
83
|
-
//
|
|
84
|
-
var title = document.title.replace(/\s*—\s*Orbiter.*$/, '').trim();
|
|
85
|
+
// Breadcrumb / page title
|
|
85
86
|
var titleEl = document.getElementById('xfce-sb-title');
|
|
86
|
-
if (titleEl
|
|
87
|
+
if (titleEl) {
|
|
88
|
+
if (activeCol && (page === 'entries' || page === 'editor')) {
|
|
89
|
+
// will be filled in by loadInfo once we know the collection label
|
|
90
|
+
titleEl.dataset.col = activeCol;
|
|
91
|
+
titleEl.dataset.page = page;
|
|
92
|
+
} else {
|
|
93
|
+
var title = document.title.replace(/\s*—\s*Orbiter.*$/, '').trim();
|
|
94
|
+
if (title) titleEl.textContent = title;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
87
97
|
|
|
88
98
|
// Clock
|
|
89
99
|
function tick() {
|
|
@@ -111,6 +121,12 @@
|
|
|
111
121
|
e.stopPropagation();
|
|
112
122
|
toggleNotifPanel();
|
|
113
123
|
});
|
|
124
|
+
|
|
125
|
+
// Cheatsheet
|
|
126
|
+
document.getElementById('xfce-sb-cheat').addEventListener('click', function (e) {
|
|
127
|
+
e.stopPropagation();
|
|
128
|
+
toggleCheatsheet();
|
|
129
|
+
});
|
|
114
130
|
}
|
|
115
131
|
|
|
116
132
|
// ── HUD Meta Panel ────────────────────────────────────────────────────
|
|
@@ -131,6 +147,8 @@
|
|
|
131
147
|
'<div id="xfce-hud-cols" class="xfce-hud-rows"></div>',
|
|
132
148
|
'<div class="xfce-hud-section-label" style="margin-top:16px">Drafts</div>',
|
|
133
149
|
'<div id="xfce-hud-drafts" class="xfce-hud-rows xfce-hud-drafts"></div>',
|
|
150
|
+
'<div class="xfce-hud-section-label" style="margin-top:16px">Activity</div>',
|
|
151
|
+
'<div id="xfce-hud-activity" class="xfce-hud-rows xfce-hud-activity"></div>',
|
|
134
152
|
'<div class="xfce-hud-section-label" style="margin-top:16px">Navigation</div>',
|
|
135
153
|
'<div class="xfce-hud-nav-links" id="xfce-hud-nav"></div>',
|
|
136
154
|
'</div>',
|
|
@@ -155,6 +173,7 @@
|
|
|
155
173
|
function toggleHUD() {
|
|
156
174
|
if (!metaPanel) return;
|
|
157
175
|
metaPanel.classList.toggle('open');
|
|
176
|
+
if (metaPanel.classList.contains('open')) refreshHUDActivity();
|
|
158
177
|
}
|
|
159
178
|
|
|
160
179
|
// ── Tools popup ───────────────────────────────────────────────────────
|
|
@@ -561,6 +580,8 @@
|
|
|
561
580
|
case 'search': palSearch(args.join(' ')); break;
|
|
562
581
|
case 'build': palBuild(); break;
|
|
563
582
|
case 'export': palExport(args); break;
|
|
583
|
+
case 'random': palRandom(); break;
|
|
584
|
+
case '=': palMath(args.join(' ')); break;
|
|
564
585
|
default: palPrint('unknown: <b>' + escHtml(cmd) + '</b> — try <b>> help</b>', 'err');
|
|
565
586
|
}
|
|
566
587
|
}
|
|
@@ -574,6 +595,8 @@
|
|
|
574
595
|
'<code>info</code> — pod & version info',
|
|
575
596
|
'<code>build</code> — trigger deploy',
|
|
576
597
|
'<code>export <col> [--md] [--drafts]</code> — download',
|
|
598
|
+
'<code>random</code> — jump to a random entry',
|
|
599
|
+
'<code>= <expr></code> — evaluate math expression',
|
|
577
600
|
].join('<br>'), 'dim');
|
|
578
601
|
}
|
|
579
602
|
|
|
@@ -690,12 +713,50 @@
|
|
|
690
713
|
.then(function (r) { return r.json(); })
|
|
691
714
|
.then(function (d) {
|
|
692
715
|
paletteResults.innerHTML = '';
|
|
693
|
-
if (d.ok || d.message) {
|
|
694
|
-
|
|
716
|
+
if (d.ok || d.message) {
|
|
717
|
+
palPrint('✓ ' + (d.message || 'build triggered'), 'ok');
|
|
718
|
+
startBuildPoll();
|
|
719
|
+
setTimeout(closePalette, 900);
|
|
720
|
+
} else palPrint('build error: ' + escHtml(d.error || JSON.stringify(d)), 'err');
|
|
695
721
|
})
|
|
696
722
|
.catch(function () { paletteResults.innerHTML = ''; palPrint('build request failed', 'err'); });
|
|
697
723
|
}
|
|
698
724
|
|
|
725
|
+
function palMath(expr) {
|
|
726
|
+
if (!expr) { palPrint('usage: <code>= 2 * 450 + 12</code>', 'dim'); return; }
|
|
727
|
+
try {
|
|
728
|
+
// only allow safe math chars
|
|
729
|
+
if (!/^[\d\s\+\-\*\/\.\(\)%,^]+$/.test(expr)) throw new Error('unsafe');
|
|
730
|
+
// replace ^ with ** for exponentiation
|
|
731
|
+
var safe = expr.replace(/\^/g, '**');
|
|
732
|
+
// eslint-disable-next-line no-new-func
|
|
733
|
+
var result = Function('"use strict"; return (' + safe + ')')();
|
|
734
|
+
if (typeof result !== 'number' || !isFinite(result)) throw new Error('not a number');
|
|
735
|
+
palPrint('<span style="font-size:15px;color:var(--accent)">' + result + '</span>'
|
|
736
|
+
+ ' <span style="color:var(--muted);font-size:10px">= ' + escHtml(expr) + '</span>', '');
|
|
737
|
+
} catch (e) {
|
|
738
|
+
palPrint('invalid expression', 'err');
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
function palRandom() {
|
|
743
|
+
palPrint('picking a random entry…', 'muted');
|
|
744
|
+
fetch('/api/search/recent?limit=50', { credentials: 'include' })
|
|
745
|
+
.then(function (r) { return r.ok ? r.json() : []; })
|
|
746
|
+
.then(function (rows) {
|
|
747
|
+
var published = rows.filter(function (r) { return r.status === 'published'; });
|
|
748
|
+
if (!published.length) { paletteResults.innerHTML = ''; palPrint('no published entries found', 'muted'); return; }
|
|
749
|
+
var pick = published[Math.floor(Math.random() * published.length)];
|
|
750
|
+
var href = '/collections/' + encodeURIComponent(pick.collection) + '/entries/' + encodeURIComponent(pick.slug);
|
|
751
|
+
paletteResults.innerHTML = '';
|
|
752
|
+
palPrint('✦ <a href="' + href + '" style="color:var(--accent)">' + escHtml(pick.title || pick.slug) + '</a>'
|
|
753
|
+
+ ' <span style="color:var(--muted)">in ' + escHtml(pick.label) + '</span>', '');
|
|
754
|
+
setTimeout(function () { location.href = href; closePalette(); }, 1200);
|
|
755
|
+
})
|
|
756
|
+
.catch(function () { paletteResults.innerHTML = ''; palPrint('error fetching entries', 'err'); });
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
|
|
699
760
|
function palExport(args) {
|
|
700
761
|
if (!args.length) { palPrint('usage: export <collection> [--md] [--drafts]', 'err'); return; }
|
|
701
762
|
var colId = args[0];
|
|
@@ -789,6 +850,7 @@
|
|
|
789
850
|
if (badge) { badge.textContent = _notifUnread > 9 ? '9+' : _notifUnread; badge.style.display = ''; }
|
|
790
851
|
if (icon) { icon.textContent = '●'; }
|
|
791
852
|
if (_notifPanel && _notifPanel.classList.contains('open')) renderNotifList();
|
|
853
|
+
refreshHUDActivity();
|
|
792
854
|
}
|
|
793
855
|
|
|
794
856
|
function buildNotifPanel() {
|
|
@@ -833,6 +895,24 @@
|
|
|
833
895
|
}).join('');
|
|
834
896
|
}
|
|
835
897
|
|
|
898
|
+
function refreshHUDActivity() {
|
|
899
|
+
var el2 = document.getElementById('xfce-hud-activity');
|
|
900
|
+
if (!el2) return;
|
|
901
|
+
if (!_notifications.length) {
|
|
902
|
+
el2.innerHTML = '<div class="xfce-hud-empty">No activity yet</div>';
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
el2.innerHTML = _notifications.slice(0, 8).map(function (n) {
|
|
906
|
+
var ago = Math.floor((Date.now() - n.time) / 1000);
|
|
907
|
+
var t = ago < 60 ? ago + 's' : ago < 3600 ? Math.floor(ago / 60) + 'm' : Math.floor(ago / 3600) + 'h';
|
|
908
|
+
var cls = n.type === 'success' ? 'xfce-hud-act-ok' : n.type === 'error' ? 'xfce-hud-act-err' : '';
|
|
909
|
+
return '<div class="xfce-hud-act-row' + (cls ? ' ' + cls : '') + '">'
|
|
910
|
+
+ '<span class="xfce-hud-act-msg">' + escHtml(n.msg) + '</span>'
|
|
911
|
+
+ '<span class="xfce-hud-act-time">' + t + '</span>'
|
|
912
|
+
+ '</div>';
|
|
913
|
+
}).join('');
|
|
914
|
+
}
|
|
915
|
+
|
|
836
916
|
function toggleNotifPanel() {
|
|
837
917
|
if (!_notifPanel) buildNotifPanel();
|
|
838
918
|
var isOpen = _notifPanel.classList.toggle('open');
|
|
@@ -1335,6 +1415,17 @@
|
|
|
1335
1415
|
return hudRow(col.label, col.total + ' published' + draftTxt);
|
|
1336
1416
|
}).join('');
|
|
1337
1417
|
}
|
|
1418
|
+
|
|
1419
|
+
// Breadcrumb in status bar center
|
|
1420
|
+
var titleEl = document.getElementById('xfce-sb-title');
|
|
1421
|
+
if (titleEl && titleEl.dataset.col) {
|
|
1422
|
+
var colMeta = (info.collections || []).find(function (c) { return c.id === titleEl.dataset.col; });
|
|
1423
|
+
var colLabel = colMeta ? colMeta.label : titleEl.dataset.col;
|
|
1424
|
+
var crumbPage = titleEl.dataset.page === 'editor' ? 'Editor' : 'Entries';
|
|
1425
|
+
titleEl.innerHTML = '<a href="/entries.html?col=' + encodeURIComponent(titleEl.dataset.col) + '" class="xfce-sb-crumb-link">' + escHtml(colLabel) + '</a>'
|
|
1426
|
+
+ '<span class="xfce-sb-crumb-sep"> › </span>'
|
|
1427
|
+
+ '<span class="xfce-sb-crumb-page">' + crumbPage + '</span>';
|
|
1428
|
+
}
|
|
1338
1429
|
})
|
|
1339
1430
|
.catch(function () {});
|
|
1340
1431
|
|
|
@@ -1425,13 +1516,13 @@
|
|
|
1425
1516
|
cheatRow('g + s', 'Settings'),
|
|
1426
1517
|
cheatRow('g + b', 'Build'),
|
|
1427
1518
|
cheatRow('g + i', 'Import'),
|
|
1428
|
-
cheatRow('g +
|
|
1519
|
+
cheatRow('g + c', 'Schema'),
|
|
1520
|
+
cheatRow('g + h', 'Toggle HUD'),
|
|
1429
1521
|
cheatRow('g + a', 'Account'),
|
|
1430
1522
|
cheatRow('1 – 9', 'Jump to nth dock item'),
|
|
1431
1523
|
'</div>',
|
|
1432
1524
|
'<div class="xfce-cheat-col">',
|
|
1433
1525
|
'<div class="xfce-cheat-section">Panels</div>',
|
|
1434
|
-
cheatRow('⌘⇧D', 'Toggle HUD'),
|
|
1435
1526
|
cheatRow('⌘⇧F', 'Focus / Zen mode'),
|
|
1436
1527
|
cheatRow('⌘⇧L', 'Switch to Glass mode'),
|
|
1437
1528
|
cheatRow('?', 'This cheatsheet'),
|
|
@@ -1442,6 +1533,8 @@
|
|
|
1442
1533
|
cheatRow('> search <q>', 'Search entries'),
|
|
1443
1534
|
cheatRow('> build', 'Trigger site build'),
|
|
1444
1535
|
cheatRow('> export <col>', 'Export collection'),
|
|
1536
|
+
cheatRow('> random', 'Jump to random entry'),
|
|
1537
|
+
cheatRow('> = <expr>', 'Evaluate math'),
|
|
1445
1538
|
cheatRow('> info', 'Show pod info'),
|
|
1446
1539
|
cheatRow('> help', 'Show command help'),
|
|
1447
1540
|
'</div>',
|
|
@@ -1475,7 +1568,7 @@
|
|
|
1475
1568
|
var _gPending = false, _gTimer = null;
|
|
1476
1569
|
var G_MAP = { d: '/dashboard.html', m: '/media.html', s: '/settings.html',
|
|
1477
1570
|
u: '/users.html', b: '/build.html', i: '/import.html',
|
|
1478
|
-
|
|
1571
|
+
c: '/schema.html', a: '/account.html' };
|
|
1479
1572
|
|
|
1480
1573
|
function setGMode(on) {
|
|
1481
1574
|
_gPending = on;
|
|
@@ -1521,16 +1614,11 @@
|
|
|
1521
1614
|
}
|
|
1522
1615
|
if (_gPending && !isEditing(e.target)) {
|
|
1523
1616
|
clearTimeout(_gTimer); setGMode(false);
|
|
1524
|
-
if (
|
|
1617
|
+
if (e.key === 'h') { e.preventDefault(); toggleHUD(); }
|
|
1618
|
+
else if (G_MAP[e.key]) { e.preventDefault(); location.href = G_MAP[e.key]; }
|
|
1525
1619
|
return;
|
|
1526
1620
|
}
|
|
1527
1621
|
|
|
1528
|
-
// ⌘⇧D — toggle HUD
|
|
1529
|
-
if (mod && e.shiftKey && (e.key === 'd' || e.key === 'D')) {
|
|
1530
|
-
e.preventDefault();
|
|
1531
|
-
toggleHUD();
|
|
1532
|
-
return;
|
|
1533
|
-
}
|
|
1534
1622
|
|
|
1535
1623
|
// ⌘⇧F — zen / focus mode
|
|
1536
1624
|
if (mod && e.shiftKey && (e.key === 'f' || e.key === 'F')) {
|
|
@@ -1573,19 +1661,40 @@
|
|
|
1573
1661
|
}
|
|
1574
1662
|
|
|
1575
1663
|
// ── Build status in status bar ────────────────────────────────────────
|
|
1664
|
+
var _buildPolling = false;
|
|
1665
|
+
|
|
1576
1666
|
function loadBuildStatus() {
|
|
1577
1667
|
fetch('/api/build/status', { credentials: 'include' })
|
|
1578
1668
|
.then(function (r) { return r.ok ? r.json() : null; })
|
|
1579
1669
|
.then(function (d) {
|
|
1580
|
-
if (!d
|
|
1670
|
+
if (!d) return;
|
|
1581
1671
|
var el2 = document.getElementById('xfce-sb-build');
|
|
1582
1672
|
var sep = document.getElementById('xfce-sb-build-sep');
|
|
1583
1673
|
if (!el2) return;
|
|
1584
|
-
|
|
1585
|
-
var
|
|
1586
|
-
|
|
1674
|
+
|
|
1675
|
+
var running = d.running === true;
|
|
1676
|
+
el2.classList.toggle('xfce-sb-build--running', running);
|
|
1677
|
+
|
|
1678
|
+
if (running) {
|
|
1679
|
+
el2.textContent = '◉ building…';
|
|
1680
|
+
el2.title = 'Build in progress';
|
|
1681
|
+
if (sep) sep.style.display = '';
|
|
1682
|
+
if (!_buildPolling) {
|
|
1683
|
+
_buildPolling = true;
|
|
1684
|
+
setTimeout(function poll() {
|
|
1685
|
+
loadBuildStatus();
|
|
1686
|
+
if (_buildPolling) setTimeout(poll, 4000);
|
|
1687
|
+
}, 4000);
|
|
1688
|
+
}
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
_buildPolling = false;
|
|
1693
|
+
if (!d.lastTriggered) return;
|
|
1694
|
+
var dt = new Date(d.lastTriggered.replace(' ', 'T'));
|
|
1695
|
+
var diffM = Math.floor((Date.now() - dt) / 60000);
|
|
1587
1696
|
var label = diffM < 1 ? 'built now'
|
|
1588
|
-
: diffM < 60
|
|
1697
|
+
: diffM < 60 ? 'built ' + diffM + 'm ago'
|
|
1589
1698
|
: diffM < 1440 ? 'built ' + Math.floor(diffM / 60) + 'h ago'
|
|
1590
1699
|
: 'built ' + dt.toLocaleDateString([], { month: 'short', day: 'numeric' });
|
|
1591
1700
|
el2.textContent = '◉ ' + label;
|
|
@@ -1594,6 +1703,18 @@
|
|
|
1594
1703
|
});
|
|
1595
1704
|
}
|
|
1596
1705
|
|
|
1706
|
+
function startBuildPoll() {
|
|
1707
|
+
_buildPolling = true;
|
|
1708
|
+
var el2 = document.getElementById('xfce-sb-build');
|
|
1709
|
+
var sep = document.getElementById('xfce-sb-build-sep');
|
|
1710
|
+
if (el2) { el2.textContent = '◉ building…'; el2.classList.add('xfce-sb-build--running'); }
|
|
1711
|
+
if (sep) sep.style.display = '';
|
|
1712
|
+
setTimeout(function poll() {
|
|
1713
|
+
loadBuildStatus();
|
|
1714
|
+
if (_buildPolling) setTimeout(poll, 4000);
|
|
1715
|
+
}, 3000);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1597
1718
|
|
|
1598
1719
|
// ── Init ──────────────────────────────────────────────────────────────
|
|
1599
1720
|
function init() {
|