@a83/orbiter-admin 0.3.44 → 0.3.46
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 +132 -14
- package/public/xfce.js +299 -27
package/package.json
CHANGED
package/public/style.css
CHANGED
|
@@ -1158,8 +1158,8 @@ html[data-style="xfce"] .editor-shell {
|
|
|
1158
1158
|
flex-direction: column;
|
|
1159
1159
|
align-items: center;
|
|
1160
1160
|
justify-content: flex-end;
|
|
1161
|
-
width: var(--dock-item-base, 50px);
|
|
1162
|
-
padding:
|
|
1161
|
+
min-width: var(--dock-item-base, 50px);
|
|
1162
|
+
padding: 10px 12px 9px;
|
|
1163
1163
|
background: transparent;
|
|
1164
1164
|
border: none;
|
|
1165
1165
|
border-radius: 12px;
|
|
@@ -1196,21 +1196,25 @@ html[data-style="xfce"] .editor-shell {
|
|
|
1196
1196
|
}
|
|
1197
1197
|
.xfce-dock-item.active {
|
|
1198
1198
|
color: var(--accent);
|
|
1199
|
-
background: color-mix(in srgb, var(--accent)
|
|
1199
|
+
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
|
1200
|
+
box-shadow:
|
|
1201
|
+
0 0 0 1px color-mix(in srgb, var(--accent) 55%, transparent),
|
|
1202
|
+
0 0 14px color-mix(in srgb, var(--accent) 22%, transparent),
|
|
1203
|
+
inset 0 1px 0 color-mix(in srgb, white 18%, transparent);
|
|
1200
1204
|
}
|
|
1201
|
-
.xfce-dock-item.active::before { opacity: .
|
|
1202
|
-
/* active indicator: glowing
|
|
1205
|
+
.xfce-dock-item.active::before { opacity: .65; }
|
|
1206
|
+
/* active indicator: glowing dot at bottom */
|
|
1203
1207
|
.xfce-dock-item.active::after {
|
|
1204
1208
|
content: '';
|
|
1205
1209
|
position: absolute;
|
|
1206
|
-
bottom:
|
|
1210
|
+
bottom: 4px;
|
|
1207
1211
|
left: 50%;
|
|
1208
1212
|
transform: translateX(-50%);
|
|
1209
|
-
width:
|
|
1210
|
-
height:
|
|
1211
|
-
border-radius:
|
|
1212
|
-
background:
|
|
1213
|
-
box-shadow: 0 0
|
|
1213
|
+
width: 4px;
|
|
1214
|
+
height: 4px;
|
|
1215
|
+
border-radius: 50%;
|
|
1216
|
+
background: var(--accent);
|
|
1217
|
+
box-shadow: 0 0 6px 2px color-mix(in srgb, var(--accent) 80%, transparent);
|
|
1214
1218
|
}
|
|
1215
1219
|
|
|
1216
1220
|
.xfce-dock-icon {
|
|
@@ -1227,9 +1231,10 @@ html[data-style="xfce"] .editor-shell {
|
|
|
1227
1231
|
transform: scale(1.14);
|
|
1228
1232
|
}
|
|
1229
1233
|
.xfce-dock-item.active .xfce-dock-icon {
|
|
1230
|
-
opacity:
|
|
1234
|
+
opacity: 1;
|
|
1231
1235
|
color: var(--accent);
|
|
1232
|
-
filter: drop-shadow(0 0
|
|
1236
|
+
filter: drop-shadow(0 0 8px color-mix(in srgb, var(--accent) 80%, transparent));
|
|
1237
|
+
transform: scale(1.08);
|
|
1233
1238
|
}
|
|
1234
1239
|
.xfce-dock-lbl {
|
|
1235
1240
|
font-family: var(--mono);
|
|
@@ -1246,8 +1251,10 @@ html[data-style="xfce"] .editor-shell {
|
|
|
1246
1251
|
color: color-mix(in srgb, var(--accent) 80%, var(--heading));
|
|
1247
1252
|
}
|
|
1248
1253
|
.xfce-dock-item.active .xfce-dock-lbl {
|
|
1249
|
-
opacity:
|
|
1254
|
+
opacity: 1;
|
|
1250
1255
|
color: var(--accent);
|
|
1256
|
+
font-weight: 700;
|
|
1257
|
+
letter-spacing: .08em;
|
|
1251
1258
|
}
|
|
1252
1259
|
|
|
1253
1260
|
/* ── HUD Panel ────────────────────────────────────────────── */
|
|
@@ -2016,6 +2023,12 @@ a.xfce-sb-logo:hover { opacity: .8; }
|
|
|
2016
2023
|
font-family: var(--mono); transition: background .15s;
|
|
2017
2024
|
}
|
|
2018
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); }
|
|
2019
2032
|
|
|
2020
2033
|
/* Draft badge on dock items */
|
|
2021
2034
|
.xfce-dock-badge {
|
|
@@ -2150,6 +2163,20 @@ html[data-dock-pos="left"] .xfce-col-preview.visible {
|
|
|
2150
2163
|
.xfce-pal-item-body { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
|
|
2151
2164
|
.xfce-pal-snippet { font-size: 10px; color: var(--muted); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
2152
2165
|
|
|
2166
|
+
/* palette — recent entries */
|
|
2167
|
+
.xfce-pal-icon-sm { width: 20px; text-align: center; font-size: 10px; color: var(--muted); flex-shrink: 0; }
|
|
2168
|
+
.xfce-pal-group-sub {
|
|
2169
|
+
font-size: 8px; font-family: var(--mono); color: var(--line);
|
|
2170
|
+
letter-spacing: .08em; text-transform: uppercase;
|
|
2171
|
+
padding: 8px 14px 4px; border-top: 1px solid var(--line);
|
|
2172
|
+
}
|
|
2173
|
+
.xfce-pal-status {
|
|
2174
|
+
font-size: 9px; font-family: var(--mono); border-radius: 4px;
|
|
2175
|
+
padding: 1px 6px; border: 1px solid currentColor; white-space: nowrap;
|
|
2176
|
+
}
|
|
2177
|
+
.xfce-pal-status-published { color: var(--jade, #5dc97e); }
|
|
2178
|
+
.xfce-pal-status-draft { color: var(--muted); }
|
|
2179
|
+
|
|
2153
2180
|
/* ── Status bar build indicator ──────────────────────────── */
|
|
2154
2181
|
.xfce-sb-build { font-size: 9px; font-family: var(--mono); color: var(--muted); white-space: nowrap; }
|
|
2155
2182
|
.xfce-sb-g-ind {
|
|
@@ -2196,6 +2223,71 @@ html[data-style="xfce"][data-dock-pos="left"] .xfce-ws-overlay {
|
|
|
2196
2223
|
bottom: auto; left: 110px; top: 50%; transform: translateY(-50%);
|
|
2197
2224
|
}
|
|
2198
2225
|
|
|
2226
|
+
/* ── Zen / Focus mode ────────────────────────────────────── */
|
|
2227
|
+
html[data-zen="1"] .xfce-sb {
|
|
2228
|
+
opacity: 0; pointer-events: none;
|
|
2229
|
+
transform: translateY(-100%);
|
|
2230
|
+
transition: opacity .3s, transform .3s;
|
|
2231
|
+
}
|
|
2232
|
+
html[data-zen="1"] .xfce-dock {
|
|
2233
|
+
opacity: 0; pointer-events: none;
|
|
2234
|
+
transform: translateY(30px);
|
|
2235
|
+
transition: opacity .3s, transform .3s;
|
|
2236
|
+
}
|
|
2237
|
+
html[data-zen="1"][data-dock-pos="left"] .xfce-dock {
|
|
2238
|
+
transform: translateX(-30px);
|
|
2239
|
+
}
|
|
2240
|
+
html[data-zen="1"] .main {
|
|
2241
|
+
padding-top: 8px !important;
|
|
2242
|
+
padding-bottom: 20px !important;
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
/* ── Shortcut Cheatsheet ─────────────────────────────────── */
|
|
2246
|
+
.xfce-cheat-overlay {
|
|
2247
|
+
display: none; position: fixed; inset: 0;
|
|
2248
|
+
background: rgba(0,0,0,.55); backdrop-filter: blur(4px);
|
|
2249
|
+
z-index: 100001; align-items: center; justify-content: center;
|
|
2250
|
+
}
|
|
2251
|
+
.xfce-cheat-overlay.open { display: flex; }
|
|
2252
|
+
.xfce-cheat-panel {
|
|
2253
|
+
background: var(--bg1); border: 1px solid var(--line);
|
|
2254
|
+
border-radius: 14px; box-shadow: 0 16px 48px rgba(0,0,0,.55);
|
|
2255
|
+
width: 560px; max-width: calc(100vw - 40px); font-family: var(--mono);
|
|
2256
|
+
overflow: hidden;
|
|
2257
|
+
}
|
|
2258
|
+
.xfce-cheat-bar {
|
|
2259
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
2260
|
+
padding: 12px 16px; border-bottom: 1px solid var(--line);
|
|
2261
|
+
background: var(--bg2);
|
|
2262
|
+
}
|
|
2263
|
+
.xfce-cheat-title { color: var(--accent); font-size: 11px; font-weight: 700; letter-spacing: .07em; }
|
|
2264
|
+
.xfce-cheat-close {
|
|
2265
|
+
background: none; border: none; color: var(--muted); cursor: pointer;
|
|
2266
|
+
font-size: 13px; line-height: 1; padding: 2px 4px;
|
|
2267
|
+
}
|
|
2268
|
+
.xfce-cheat-close:hover { color: var(--text); }
|
|
2269
|
+
.xfce-cheat-body {
|
|
2270
|
+
display: grid; grid-template-columns: 1fr 1fr; gap: 0;
|
|
2271
|
+
padding: 16px; gap: 0 24px; max-height: 70vh; overflow-y: auto;
|
|
2272
|
+
}
|
|
2273
|
+
.xfce-cheat-section {
|
|
2274
|
+
font-size: 9px; letter-spacing: .1em; color: var(--accent);
|
|
2275
|
+
text-transform: uppercase; font-weight: 700;
|
|
2276
|
+
margin-bottom: 8px; margin-top: 4px;
|
|
2277
|
+
}
|
|
2278
|
+
.xfce-cheat-row {
|
|
2279
|
+
display: flex; align-items: baseline; gap: 10px;
|
|
2280
|
+
padding: 3px 0; border-bottom: 1px solid rgba(255,255,255,.04);
|
|
2281
|
+
}
|
|
2282
|
+
.xfce-cheat-row:last-child { border-bottom: none; }
|
|
2283
|
+
.xfce-cheat-key {
|
|
2284
|
+
background: var(--bg2); border: 1px solid var(--line);
|
|
2285
|
+
border-radius: 4px; padding: 1px 6px; font-size: 10px;
|
|
2286
|
+
color: var(--accent); font-family: var(--mono); white-space: nowrap;
|
|
2287
|
+
flex-shrink: 0; min-width: 80px; text-align: center;
|
|
2288
|
+
}
|
|
2289
|
+
.xfce-cheat-desc { font-size: 10px; color: var(--text); }
|
|
2290
|
+
|
|
2199
2291
|
/* ── Bell / Notification Center ─────────────────────────── */
|
|
2200
2292
|
.xfce-sb-bell {
|
|
2201
2293
|
background: none; border: none; cursor: pointer; padding: 0 2px;
|
|
@@ -2249,6 +2341,32 @@ html[data-style="xfce"][data-dock-pos="left"] .xfce-ws-overlay {
|
|
|
2249
2341
|
.xfce-notif-err .xfce-notif-msg { color: var(--red); }
|
|
2250
2342
|
.xfce-notif-empty { padding: 20px 12px; color: var(--muted); font-size: 10px; text-align: center; }
|
|
2251
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
|
+
|
|
2252
2370
|
/* ── HUD Drafts section ──────────────────────────────────── */
|
|
2253
2371
|
.xfce-hud-draft-row {
|
|
2254
2372
|
display: flex; align-items: baseline; justify-content: space-between;
|
package/public/xfce.js
CHANGED
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
var NAV = [
|
|
14
14
|
{ icon: '⬡', label: 'Dashboard', href: '/dashboard.html', key: 'dashboard' },
|
|
15
15
|
{ icon: '◫', label: 'Media', href: '/media.html', key: 'media' },
|
|
16
|
-
{ icon: '⚙', label: 'Settings', href: '/settings.html', key: 'settings' },
|
|
17
16
|
{ icon: '⊛', label: 'Users', href: '/users.html', key: 'users' },
|
|
18
17
|
];
|
|
19
18
|
|
|
20
19
|
var TOOLS = [
|
|
21
|
-
{ icon: '▦', label: 'Schema',
|
|
22
|
-
{ icon: '◉', label: 'Build',
|
|
23
|
-
{ icon: '↓', label: 'Import',
|
|
20
|
+
{ icon: '▦', label: 'Schema', href: '/schema.html', key: 'schema' },
|
|
21
|
+
{ icon: '◉', label: 'Build', href: '/build.html', key: 'build' },
|
|
22
|
+
{ icon: '↓', label: 'Import', href: '/import.html', key: 'import' },
|
|
23
|
+
{ icon: '⚙', label: 'Settings', href: '/settings.html', key: 'settings' },
|
|
24
24
|
];
|
|
25
25
|
|
|
26
26
|
var WORKSPACE = [
|
|
@@ -30,9 +30,10 @@
|
|
|
30
30
|
|
|
31
31
|
// palette items — nav + tools pre-seeded; collections appended after /api/info
|
|
32
32
|
var _palItems = NAV.concat(TOOLS).map(function (n) {
|
|
33
|
-
return { icon: n.icon, label: n.label, href: n.href, group: n.key in { schema:1, build:1, import:1 } ? 'Tools' : 'Nav' };
|
|
33
|
+
return { icon: n.icon, label: n.label, href: n.href, group: n.key in { schema:1, build:1, import:1, settings:1 } ? 'Tools' : 'Nav' };
|
|
34
34
|
});
|
|
35
|
-
var _termCols
|
|
35
|
+
var _termCols = []; // collection metadata for palette commands
|
|
36
|
+
var _palRecents = []; // prefetched recent entries for empty palette
|
|
36
37
|
|
|
37
38
|
// ── Helpers ───────────────────────────────────────────────────────────
|
|
38
39
|
function el(tag, cls, html) {
|
|
@@ -66,6 +67,8 @@
|
|
|
66
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 h=schema a=account">g ›</span>',
|
|
67
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>',
|
|
68
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>',
|
|
69
72
|
'<button id="xfce-sb-palette-btn" class="xfce-sb-palette-btn" title="Command palette (⌘K)">⌘</button>',
|
|
70
73
|
'<span class="xfce-sb-div">·</span>',
|
|
71
74
|
'<span id="xfce-sb-build" class="xfce-sb-build" title="Last build"></span>',
|
|
@@ -79,10 +82,18 @@
|
|
|
79
82
|
].join('');
|
|
80
83
|
document.body.insertBefore(sb, document.body.firstChild);
|
|
81
84
|
|
|
82
|
-
//
|
|
83
|
-
var title = document.title.replace(/\s*—\s*Orbiter.*$/, '').trim();
|
|
85
|
+
// Breadcrumb / page title
|
|
84
86
|
var titleEl = document.getElementById('xfce-sb-title');
|
|
85
|
-
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
|
+
}
|
|
86
97
|
|
|
87
98
|
// Clock
|
|
88
99
|
function tick() {
|
|
@@ -110,6 +121,12 @@
|
|
|
110
121
|
e.stopPropagation();
|
|
111
122
|
toggleNotifPanel();
|
|
112
123
|
});
|
|
124
|
+
|
|
125
|
+
// Cheatsheet
|
|
126
|
+
document.getElementById('xfce-sb-cheat').addEventListener('click', function (e) {
|
|
127
|
+
e.stopPropagation();
|
|
128
|
+
toggleCheatsheet();
|
|
129
|
+
});
|
|
113
130
|
}
|
|
114
131
|
|
|
115
132
|
// ── HUD Meta Panel ────────────────────────────────────────────────────
|
|
@@ -130,6 +147,8 @@
|
|
|
130
147
|
'<div id="xfce-hud-cols" class="xfce-hud-rows"></div>',
|
|
131
148
|
'<div class="xfce-hud-section-label" style="margin-top:16px">Drafts</div>',
|
|
132
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>',
|
|
133
152
|
'<div class="xfce-hud-section-label" style="margin-top:16px">Navigation</div>',
|
|
134
153
|
'<div class="xfce-hud-nav-links" id="xfce-hud-nav"></div>',
|
|
135
154
|
'</div>',
|
|
@@ -154,6 +173,7 @@
|
|
|
154
173
|
function toggleHUD() {
|
|
155
174
|
if (!metaPanel) return;
|
|
156
175
|
metaPanel.classList.toggle('open');
|
|
176
|
+
if (metaPanel.classList.contains('open')) refreshHUDActivity();
|
|
157
177
|
}
|
|
158
178
|
|
|
159
179
|
// ── Tools popup ───────────────────────────────────────────────────────
|
|
@@ -162,19 +182,12 @@
|
|
|
162
182
|
function buildToolsPopup() {
|
|
163
183
|
toolsPopup = el('div', 'xfce-tools-popup');
|
|
164
184
|
toolsPopup.id = 'xfce-tools-popup';
|
|
165
|
-
TOOLS.forEach(function (t) {
|
|
185
|
+
TOOLS.filter(function (t) { return t.key !== 'settings'; }).forEach(function (t) {
|
|
166
186
|
var a = el('a', 'xfce-tools-item' + (page === t.key ? ' active' : ''));
|
|
167
187
|
a.href = t.href;
|
|
168
188
|
a.innerHTML = '<span class="xfce-tools-icon">' + t.icon + '</span><span>' + t.label + '</span>';
|
|
169
189
|
toolsPopup.appendChild(a);
|
|
170
190
|
});
|
|
171
|
-
var settingsSep = document.createElement('div');
|
|
172
|
-
settingsSep.className = 'xfce-tools-sep';
|
|
173
|
-
toolsPopup.appendChild(settingsSep);
|
|
174
|
-
var settingsLink = el('a', 'xfce-tools-item' + (page === 'settings' ? ' active' : ''));
|
|
175
|
-
settingsLink.href = '/settings.html';
|
|
176
|
-
settingsLink.innerHTML = '<span class="xfce-tools-icon">⚙</span><span>Settings</span>';
|
|
177
|
-
toolsPopup.appendChild(settingsLink);
|
|
178
191
|
var sep = document.createElement('div');
|
|
179
192
|
sep.className = 'xfce-tools-sep';
|
|
180
193
|
toolsPopup.appendChild(sep);
|
|
@@ -446,9 +459,55 @@
|
|
|
446
459
|
}
|
|
447
460
|
|
|
448
461
|
q = q.toLowerCase();
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
462
|
+
|
|
463
|
+
// Empty input → show recents + nav
|
|
464
|
+
if (!q) {
|
|
465
|
+
var html = '';
|
|
466
|
+
if (_palRecents.length) {
|
|
467
|
+
html += '<div class="xfce-pal-group">Recent</div>';
|
|
468
|
+
_palRecents.forEach(function (r) {
|
|
469
|
+
var href = '/collections/' + encodeURIComponent(r.collection) + '/entries/' + encodeURIComponent(r.slug);
|
|
470
|
+
html += '<div class="xfce-pal-item" data-href="' + href + '">'
|
|
471
|
+
+ '<span class="xfce-pal-icon xfce-pal-icon-sm">◈</span>'
|
|
472
|
+
+ '<div class="xfce-pal-item-body">'
|
|
473
|
+
+ '<span class="xfce-pal-label">' + escHtml(r.title || r.slug) + '</span>'
|
|
474
|
+
+ '<span class="xfce-pal-snippet">' + escHtml(r.label) + '</span>'
|
|
475
|
+
+ '</div>'
|
|
476
|
+
+ '<span class="xfce-pal-hint-r xfce-pal-status xfce-pal-status-' + r.status + '">' + r.status + '</span>'
|
|
477
|
+
+ '</div>';
|
|
478
|
+
});
|
|
479
|
+
html += '<div class="xfce-pal-group">Navigation</div>';
|
|
480
|
+
}
|
|
481
|
+
var navGroups = {};
|
|
482
|
+
_palItems.forEach(function (it) {
|
|
483
|
+
var g = it.group || 'Nav';
|
|
484
|
+
if (!navGroups[g]) navGroups[g] = [];
|
|
485
|
+
navGroups[g].push(it);
|
|
486
|
+
});
|
|
487
|
+
Object.keys(navGroups).forEach(function (g) {
|
|
488
|
+
if (_palRecents.length) html += '<div class="xfce-pal-group-sub">' + g + '</div>';
|
|
489
|
+
else html += '<div class="xfce-pal-group">' + g + '</div>';
|
|
490
|
+
navGroups[g].forEach(function (it) {
|
|
491
|
+
html += '<div class="xfce-pal-item" data-href="' + it.href + '">'
|
|
492
|
+
+ '<span class="xfce-pal-icon">' + it.icon + '</span>'
|
|
493
|
+
+ '<span class="xfce-pal-label">' + escHtml(it.label) + '</span>'
|
|
494
|
+
+ (it.meta ? '<span class="xfce-pal-hint-r">' + escHtml(it.meta) + '</span>' : '')
|
|
495
|
+
+ '</div>';
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
paletteResults.innerHTML = html;
|
|
499
|
+
paletteResults.querySelectorAll('.xfce-pal-item[data-href]').forEach(function (item) {
|
|
500
|
+
item.addEventListener('click', function () { location.href = item.dataset.href; closePalette(); });
|
|
501
|
+
item.addEventListener('mouseenter', function () {
|
|
502
|
+
var items = paletteResults.querySelectorAll('.xfce-pal-item[data-href]');
|
|
503
|
+
palActive = Array.from(items).indexOf(item);
|
|
504
|
+
updatePalActive(items);
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
var filtered = _palItems.filter(function (it) { return it.label.toLowerCase().includes(q); });
|
|
452
511
|
|
|
453
512
|
if (!filtered.length) {
|
|
454
513
|
paletteResults.innerHTML = '<div class="xfce-pal-empty">No results</div>';
|
|
@@ -521,6 +580,8 @@
|
|
|
521
580
|
case 'search': palSearch(args.join(' ')); break;
|
|
522
581
|
case 'build': palBuild(); break;
|
|
523
582
|
case 'export': palExport(args); break;
|
|
583
|
+
case 'random': palRandom(); break;
|
|
584
|
+
case '=': palMath(args.join(' ')); break;
|
|
524
585
|
default: palPrint('unknown: <b>' + escHtml(cmd) + '</b> — try <b>> help</b>', 'err');
|
|
525
586
|
}
|
|
526
587
|
}
|
|
@@ -534,6 +595,8 @@
|
|
|
534
595
|
'<code>info</code> — pod & version info',
|
|
535
596
|
'<code>build</code> — trigger deploy',
|
|
536
597
|
'<code>export <col> [--md] [--drafts]</code> — download',
|
|
598
|
+
'<code>random</code> — jump to a random entry',
|
|
599
|
+
'<code>= <expr></code> — evaluate math expression',
|
|
537
600
|
].join('<br>'), 'dim');
|
|
538
601
|
}
|
|
539
602
|
|
|
@@ -650,12 +713,50 @@
|
|
|
650
713
|
.then(function (r) { return r.json(); })
|
|
651
714
|
.then(function (d) {
|
|
652
715
|
paletteResults.innerHTML = '';
|
|
653
|
-
if (d.ok || d.message) {
|
|
654
|
-
|
|
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');
|
|
655
721
|
})
|
|
656
722
|
.catch(function () { paletteResults.innerHTML = ''; palPrint('build request failed', 'err'); });
|
|
657
723
|
}
|
|
658
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
|
+
|
|
659
760
|
function palExport(args) {
|
|
660
761
|
if (!args.length) { palPrint('usage: export <collection> [--md] [--drafts]', 'err'); return; }
|
|
661
762
|
var colId = args[0];
|
|
@@ -749,6 +850,7 @@
|
|
|
749
850
|
if (badge) { badge.textContent = _notifUnread > 9 ? '9+' : _notifUnread; badge.style.display = ''; }
|
|
750
851
|
if (icon) { icon.textContent = '●'; }
|
|
751
852
|
if (_notifPanel && _notifPanel.classList.contains('open')) renderNotifList();
|
|
853
|
+
refreshHUDActivity();
|
|
752
854
|
}
|
|
753
855
|
|
|
754
856
|
function buildNotifPanel() {
|
|
@@ -793,6 +895,24 @@
|
|
|
793
895
|
}).join('');
|
|
794
896
|
}
|
|
795
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
|
+
|
|
796
916
|
function toggleNotifPanel() {
|
|
797
917
|
if (!_notifPanel) buildNotifPanel();
|
|
798
918
|
var isOpen = _notifPanel.classList.toggle('open');
|
|
@@ -1173,6 +1293,9 @@
|
|
|
1173
1293
|
});
|
|
1174
1294
|
dockInner.appendChild(toolsBtn);
|
|
1175
1295
|
|
|
1296
|
+
var settingsDockBtn = makeDockItem('⚙', 'Settings', '/settings.html', page === 'settings', false);
|
|
1297
|
+
dockInner.appendChild(settingsDockBtn);
|
|
1298
|
+
|
|
1176
1299
|
dockInner.appendChild(el('div', 'xfce-dock-sep'));
|
|
1177
1300
|
|
|
1178
1301
|
// HUD toggle
|
|
@@ -1292,6 +1415,17 @@
|
|
|
1292
1415
|
return hudRow(col.label, col.total + ' published' + draftTxt);
|
|
1293
1416
|
}).join('');
|
|
1294
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
|
+
}
|
|
1295
1429
|
})
|
|
1296
1430
|
.catch(function () {});
|
|
1297
1431
|
|
|
@@ -1336,12 +1470,100 @@
|
|
|
1336
1470
|
if (sbUser) sbUser.textContent = d.user.username;
|
|
1337
1471
|
})
|
|
1338
1472
|
.catch(function () {});
|
|
1473
|
+
|
|
1474
|
+
// Prefetch recent entries for palette empty state
|
|
1475
|
+
fetch('/api/search/recent?limit=7', { credentials: 'include' })
|
|
1476
|
+
.then(function (r) { return r.ok ? r.json() : []; })
|
|
1477
|
+
.then(function (rows) { _palRecents = rows; })
|
|
1478
|
+
.catch(function () {});
|
|
1339
1479
|
}
|
|
1340
1480
|
|
|
1341
1481
|
function hudRow(label, value) {
|
|
1342
1482
|
return '<div class="xfce-hud-row"><span>' + label + '</span><span>' + value + '</span></div>';
|
|
1343
1483
|
}
|
|
1344
1484
|
|
|
1485
|
+
// ── Zen / Focus mode ─────────────────────────────────────────────────
|
|
1486
|
+
function toggleZen() {
|
|
1487
|
+
var html = document.documentElement;
|
|
1488
|
+
var on = html.dataset.zen !== '1';
|
|
1489
|
+
html.dataset.zen = on ? '1' : '';
|
|
1490
|
+
localStorage.setItem('orb_zen', on ? '1' : '');
|
|
1491
|
+
if (on) window.xfceToast('Focus mode on — ⌘⇧F to exit', 'info');
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
// ── Shortcut cheatsheet ───────────────────────────────────────────────
|
|
1495
|
+
var _cheatEl = null;
|
|
1496
|
+
|
|
1497
|
+
function buildCheatsheet() {
|
|
1498
|
+
_cheatEl = el('div', 'xfce-cheat-overlay');
|
|
1499
|
+
_cheatEl.id = 'xfce-cheat';
|
|
1500
|
+
_cheatEl.innerHTML = [
|
|
1501
|
+
'<div class="xfce-cheat-panel">',
|
|
1502
|
+
'<div class="xfce-cheat-bar">',
|
|
1503
|
+
'<span class="xfce-cheat-title">⌨ Shortcuts</span>',
|
|
1504
|
+
'<button class="xfce-cheat-close" id="xfce-cheat-close">✕</button>',
|
|
1505
|
+
'</div>',
|
|
1506
|
+
'<div class="xfce-cheat-body">',
|
|
1507
|
+
'<div class="xfce-cheat-col">',
|
|
1508
|
+
'<div class="xfce-cheat-section">Navigation</div>',
|
|
1509
|
+
cheatRow('⌘K / /', 'Open command palette'),
|
|
1510
|
+
cheatRow('↑ ↓', 'Move selection in palette'),
|
|
1511
|
+
cheatRow('↵', 'Go to selected item'),
|
|
1512
|
+
cheatRow('Esc', 'Close overlay / panel'),
|
|
1513
|
+
cheatRow('g + d', 'Dashboard'),
|
|
1514
|
+
cheatRow('g + m', 'Media'),
|
|
1515
|
+
cheatRow('g + u', 'Users'),
|
|
1516
|
+
cheatRow('g + s', 'Settings'),
|
|
1517
|
+
cheatRow('g + b', 'Build'),
|
|
1518
|
+
cheatRow('g + i', 'Import'),
|
|
1519
|
+
cheatRow('g + h', 'Schema'),
|
|
1520
|
+
cheatRow('g + a', 'Account'),
|
|
1521
|
+
cheatRow('1 – 9', 'Jump to nth dock item'),
|
|
1522
|
+
'</div>',
|
|
1523
|
+
'<div class="xfce-cheat-col">',
|
|
1524
|
+
'<div class="xfce-cheat-section">Panels</div>',
|
|
1525
|
+
cheatRow('⌘⇧D', 'Toggle HUD'),
|
|
1526
|
+
cheatRow('⌘⇧F', 'Focus / Zen mode'),
|
|
1527
|
+
cheatRow('⌘⇧L', 'Switch to Glass mode'),
|
|
1528
|
+
cheatRow('?', 'This cheatsheet'),
|
|
1529
|
+
'<div class="xfce-cheat-section" style="margin-top:14px">Palette commands</div>',
|
|
1530
|
+
cheatRow('> ls', 'List collections'),
|
|
1531
|
+
cheatRow('> go <page>', 'Navigate to page'),
|
|
1532
|
+
cheatRow('> new <col>', 'New entry in collection'),
|
|
1533
|
+
cheatRow('> search <q>', 'Search entries'),
|
|
1534
|
+
cheatRow('> build', 'Trigger site build'),
|
|
1535
|
+
cheatRow('> export <col>', 'Export collection'),
|
|
1536
|
+
cheatRow('> random', 'Jump to random entry'),
|
|
1537
|
+
cheatRow('> = <expr>', 'Evaluate math'),
|
|
1538
|
+
cheatRow('> info', 'Show pod info'),
|
|
1539
|
+
cheatRow('> help', 'Show command help'),
|
|
1540
|
+
'</div>',
|
|
1541
|
+
'</div>',
|
|
1542
|
+
'</div>',
|
|
1543
|
+
].join('');
|
|
1544
|
+
document.body.appendChild(_cheatEl);
|
|
1545
|
+
document.getElementById('xfce-cheat-close').addEventListener('click', closeCheatsheet);
|
|
1546
|
+
_cheatEl.addEventListener('click', function (e) {
|
|
1547
|
+
if (e.target === _cheatEl) closeCheatsheet();
|
|
1548
|
+
});
|
|
1549
|
+
document.addEventListener('keydown', function (e) {
|
|
1550
|
+
if (e.key === 'Escape' && _cheatEl && _cheatEl.classList.contains('open')) closeCheatsheet();
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
function cheatRow(key, desc) {
|
|
1555
|
+
return '<div class="xfce-cheat-row"><kbd class="xfce-cheat-key">' + key + '</kbd><span class="xfce-cheat-desc">' + desc + '</span></div>';
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
function toggleCheatsheet() {
|
|
1559
|
+
if (!_cheatEl) buildCheatsheet();
|
|
1560
|
+
_cheatEl.classList.toggle('open');
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
function closeCheatsheet() {
|
|
1564
|
+
if (_cheatEl) _cheatEl.classList.remove('open');
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1345
1567
|
// ── Keyboard shortcuts ────────────────────────────────────────────────
|
|
1346
1568
|
var _gPending = false, _gTimer = null;
|
|
1347
1569
|
var G_MAP = { d: '/dashboard.html', m: '/media.html', s: '/settings.html',
|
|
@@ -1403,6 +1625,13 @@
|
|
|
1403
1625
|
return;
|
|
1404
1626
|
}
|
|
1405
1627
|
|
|
1628
|
+
// ⌘⇧F — zen / focus mode
|
|
1629
|
+
if (mod && e.shiftKey && (e.key === 'f' || e.key === 'F')) {
|
|
1630
|
+
e.preventDefault();
|
|
1631
|
+
toggleZen();
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1406
1635
|
// ⌘⇧L — switch back to glass mode
|
|
1407
1636
|
if (mod && e.shiftKey && (e.key === 'l' || e.key === 'L')) {
|
|
1408
1637
|
e.preventDefault();
|
|
@@ -1411,6 +1640,13 @@
|
|
|
1411
1640
|
return;
|
|
1412
1641
|
}
|
|
1413
1642
|
|
|
1643
|
+
// ? — shortcut cheatsheet
|
|
1644
|
+
if (!mod && !e.altKey && e.key === '?' && !isEditing(e.target)) {
|
|
1645
|
+
e.preventDefault();
|
|
1646
|
+
toggleCheatsheet();
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1414
1650
|
// 1–9 — jump to nth dock link (no modifier, not in input)
|
|
1415
1651
|
if (!mod && !e.shiftKey && !e.altKey && !isEditing(e.target)) {
|
|
1416
1652
|
var n = parseInt(e.key);
|
|
@@ -1430,19 +1666,40 @@
|
|
|
1430
1666
|
}
|
|
1431
1667
|
|
|
1432
1668
|
// ── Build status in status bar ────────────────────────────────────────
|
|
1669
|
+
var _buildPolling = false;
|
|
1670
|
+
|
|
1433
1671
|
function loadBuildStatus() {
|
|
1434
1672
|
fetch('/api/build/status', { credentials: 'include' })
|
|
1435
1673
|
.then(function (r) { return r.ok ? r.json() : null; })
|
|
1436
1674
|
.then(function (d) {
|
|
1437
|
-
if (!d
|
|
1675
|
+
if (!d) return;
|
|
1438
1676
|
var el2 = document.getElementById('xfce-sb-build');
|
|
1439
1677
|
var sep = document.getElementById('xfce-sb-build-sep');
|
|
1440
1678
|
if (!el2) return;
|
|
1441
|
-
|
|
1442
|
-
var
|
|
1443
|
-
|
|
1679
|
+
|
|
1680
|
+
var running = d.running === true;
|
|
1681
|
+
el2.classList.toggle('xfce-sb-build--running', running);
|
|
1682
|
+
|
|
1683
|
+
if (running) {
|
|
1684
|
+
el2.textContent = '◉ building…';
|
|
1685
|
+
el2.title = 'Build in progress';
|
|
1686
|
+
if (sep) sep.style.display = '';
|
|
1687
|
+
if (!_buildPolling) {
|
|
1688
|
+
_buildPolling = true;
|
|
1689
|
+
setTimeout(function poll() {
|
|
1690
|
+
loadBuildStatus();
|
|
1691
|
+
if (_buildPolling) setTimeout(poll, 4000);
|
|
1692
|
+
}, 4000);
|
|
1693
|
+
}
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
_buildPolling = false;
|
|
1698
|
+
if (!d.lastTriggered) return;
|
|
1699
|
+
var dt = new Date(d.lastTriggered.replace(' ', 'T'));
|
|
1700
|
+
var diffM = Math.floor((Date.now() - dt) / 60000);
|
|
1444
1701
|
var label = diffM < 1 ? 'built now'
|
|
1445
|
-
: diffM < 60
|
|
1702
|
+
: diffM < 60 ? 'built ' + diffM + 'm ago'
|
|
1446
1703
|
: diffM < 1440 ? 'built ' + Math.floor(diffM / 60) + 'h ago'
|
|
1447
1704
|
: 'built ' + dt.toLocaleDateString([], { month: 'short', day: 'numeric' });
|
|
1448
1705
|
el2.textContent = '◉ ' + label;
|
|
@@ -1451,6 +1708,18 @@
|
|
|
1451
1708
|
});
|
|
1452
1709
|
}
|
|
1453
1710
|
|
|
1711
|
+
function startBuildPoll() {
|
|
1712
|
+
_buildPolling = true;
|
|
1713
|
+
var el2 = document.getElementById('xfce-sb-build');
|
|
1714
|
+
var sep = document.getElementById('xfce-sb-build-sep');
|
|
1715
|
+
if (el2) { el2.textContent = '◉ building…'; el2.classList.add('xfce-sb-build--running'); }
|
|
1716
|
+
if (sep) sep.style.display = '';
|
|
1717
|
+
setTimeout(function poll() {
|
|
1718
|
+
loadBuildStatus();
|
|
1719
|
+
if (_buildPolling) setTimeout(poll, 4000);
|
|
1720
|
+
}, 3000);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1454
1723
|
|
|
1455
1724
|
// ── Init ──────────────────────────────────────────────────────────────
|
|
1456
1725
|
function init() {
|
|
@@ -1463,6 +1732,9 @@
|
|
|
1463
1732
|
bindKeys();
|
|
1464
1733
|
initFocusMode();
|
|
1465
1734
|
observeSavedFlash();
|
|
1735
|
+
if (localStorage.getItem('orb_zen') === '1') {
|
|
1736
|
+
document.documentElement.dataset.zen = '1';
|
|
1737
|
+
}
|
|
1466
1738
|
}
|
|
1467
1739
|
|
|
1468
1740
|
if (document.readyState === 'loading') {
|