@crvouga/mockingbird-service-odx 1.6.0 → 1.6.1
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 +9 -1
- package/dist/{chunk-POYXJBSV.js → chunk-BHLJXOSH.js} +2 -2
- package/dist/{chunk-JQSFQSCJ.js → chunk-QY3DD74Z.js} +89 -10
- package/dist/chunk-QY3DD74Z.js.map +7 -0
- package/dist/cli.js +2 -2
- package/dist/index.js +1 -1
- package/dist/server.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-JQSFQSCJ.js.map +0 -7
- /package/dist/{chunk-POYXJBSV.js.map → chunk-BHLJXOSH.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-odx
|
|
2
2
|
|
|
3
|
-
## 1.6.
|
|
3
|
+
## 1.6.1 (2026-09-30)
|
|
4
|
+
|
|
5
|
+
### Fixes and improvements
|
|
6
|
+
|
|
7
|
+
- keep admin buttons pressed until the action finishes ([0aabfcb](https://github.com/crvouga/mockingbird/commit/0aabfcb5f392aa51e193f9c3f817d5877d92bc6a))
|
|
8
|
+
- size admin select fields like the text inputs beside them ([0fb3ef2](https://github.com/crvouga/mockingbird/commit/0fb3ef2ddbf43376c93a2ae6d87c6c9bf890dafc))
|
|
9
|
+
- keep admin section tabs wired when boot is renamed ([4eda25e](https://github.com/crvouga/mockingbird/commit/4eda25eacd59da048d196f7cc8369d7a02b47bfc))
|
|
10
|
+
|
|
11
|
+
## 1.6.0 (2026-09-29)
|
|
4
12
|
|
|
5
13
|
### Features
|
|
6
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createRuntime
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QY3DD74Z.js";
|
|
4
4
|
|
|
5
5
|
// ../../adapters/node/dist/cli.js
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
@@ -360,4 +360,4 @@ export {
|
|
|
360
360
|
createServer2 as createServer,
|
|
361
361
|
serveTarget
|
|
362
362
|
};
|
|
363
|
-
//# sourceMappingURL=chunk-
|
|
363
|
+
//# sourceMappingURL=chunk-BHLJXOSH.js.map
|
|
@@ -2066,6 +2066,50 @@ function bootAdmin(config) {
|
|
|
2066
2066
|
if (render)
|
|
2067
2067
|
await render();
|
|
2068
2068
|
}
|
|
2069
|
+
const delay = (ms) => new Promise((resolve) => {
|
|
2070
|
+
window.setTimeout(resolve, ms);
|
|
2071
|
+
});
|
|
2072
|
+
const confirmAction = async (button, pending, done, work) => {
|
|
2073
|
+
if (button.dataset.pending === "1")
|
|
2074
|
+
return;
|
|
2075
|
+
const label = button.textContent ?? "";
|
|
2076
|
+
const width = button.offsetWidth;
|
|
2077
|
+
button.dataset.pending = "1";
|
|
2078
|
+
button.classList.add("pressed");
|
|
2079
|
+
button.setAttribute("aria-busy", "true");
|
|
2080
|
+
button.style.minWidth = `${width}px`;
|
|
2081
|
+
button.textContent = pending;
|
|
2082
|
+
try {
|
|
2083
|
+
await work();
|
|
2084
|
+
button.textContent = done;
|
|
2085
|
+
await delay(1e3);
|
|
2086
|
+
} catch (error) {
|
|
2087
|
+
showError(error);
|
|
2088
|
+
} finally {
|
|
2089
|
+
button.textContent = label;
|
|
2090
|
+
button.style.minWidth = "";
|
|
2091
|
+
button.classList.remove("pressed");
|
|
2092
|
+
button.removeAttribute("aria-busy");
|
|
2093
|
+
delete button.dataset.pending;
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
document.addEventListener("click", (event) => {
|
|
2097
|
+
const target = event.target;
|
|
2098
|
+
if (!(target instanceof Element))
|
|
2099
|
+
return;
|
|
2100
|
+
const button = target.closest("button");
|
|
2101
|
+
if (!(button instanceof HTMLButtonElement) || button.dataset.pending === "1")
|
|
2102
|
+
return;
|
|
2103
|
+
button.classList.add("pressed");
|
|
2104
|
+
const token = String(Date.now());
|
|
2105
|
+
button.dataset.press = token;
|
|
2106
|
+
window.setTimeout(() => {
|
|
2107
|
+
if (button.dataset.press !== token || button.dataset.pending === "1")
|
|
2108
|
+
return;
|
|
2109
|
+
button.classList.remove("pressed");
|
|
2110
|
+
delete button.dataset.press;
|
|
2111
|
+
}, 450);
|
|
2112
|
+
});
|
|
2069
2113
|
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2070
2114
|
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2071
2115
|
refresh().catch(showError);
|
|
@@ -2076,7 +2120,7 @@ function bootAdmin(config) {
|
|
|
2076
2120
|
refresh().catch(showError);
|
|
2077
2121
|
});
|
|
2078
2122
|
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2079
|
-
refresh().catch(showError);
|
|
2123
|
+
confirmAction(el("refresh", HTMLButtonElement), "Refreshing...", "Updated", () => refresh()).catch(showError);
|
|
2080
2124
|
});
|
|
2081
2125
|
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2082
2126
|
const target = event.target;
|
|
@@ -2199,10 +2243,10 @@ function bootAdmin(config) {
|
|
|
2199
2243
|
}).then(() => renderFaults()).catch(showError);
|
|
2200
2244
|
});
|
|
2201
2245
|
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2202
|
-
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2246
|
+
confirmAction(el("fault-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/faults").then(() => renderFaults())).catch(showError);
|
|
2203
2247
|
});
|
|
2204
2248
|
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2205
|
-
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2249
|
+
confirmAction(el("journal-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/requests").then(() => renderJournal())).catch(showError);
|
|
2206
2250
|
});
|
|
2207
2251
|
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2208
2252
|
const target = event.target;
|
|
@@ -2317,9 +2361,13 @@ function bootAdmin(config) {
|
|
|
2317
2361
|
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2318
2362
|
var adminClientSource = (config) => {
|
|
2319
2363
|
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2364
|
+
const entry = bootAdmin.name;
|
|
2365
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(entry)) {
|
|
2366
|
+
throw new Error("admin client cannot call its boot function");
|
|
2367
|
+
}
|
|
2320
2368
|
return `<script>
|
|
2321
2369
|
${clientPrelude}
|
|
2322
|
-
|
|
2370
|
+
${entry}(${payload});
|
|
2323
2371
|
</script>`;
|
|
2324
2372
|
};
|
|
2325
2373
|
|
|
@@ -2533,9 +2581,24 @@ var renderAdminDocument = (service) => {
|
|
|
2533
2581
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2534
2582
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
2535
2583
|
label.field input, label.field select, .controls input[type="password"] {
|
|
2536
|
-
background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2537
|
-
padding: 7px 8px; min-height: 36px;
|
|
2538
|
-
}
|
|
2584
|
+
background-color: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2585
|
+
padding: 7px 8px; min-height: 36px; line-height: 1.2;
|
|
2586
|
+
}
|
|
2587
|
+
/* A native menu ignores min-height, so Preset rendered about half as tall as
|
|
2588
|
+
the text fields in the same form. Paint it like those fields. */
|
|
2589
|
+
label.field select {
|
|
2590
|
+
-webkit-appearance: none; appearance: none;
|
|
2591
|
+
padding-right: 28px;
|
|
2592
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2371717a' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5 6 8l3.5-3.5'/%3E%3C/svg%3E");
|
|
2593
|
+
background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 12px;
|
|
2594
|
+
}
|
|
2595
|
+
.stack > .field > input,
|
|
2596
|
+
.stack > .field > select,
|
|
2597
|
+
.stack > .field > textarea,
|
|
2598
|
+
dialog .field > input,
|
|
2599
|
+
dialog .field > select,
|
|
2600
|
+
dialog .field > textarea { width: 100%; }
|
|
2601
|
+
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger, nav.side button { cursor: pointer; }
|
|
2539
2602
|
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger {
|
|
2540
2603
|
border-radius: 9px; min-height: 36px; padding: 0 12px; border: 1px solid var(--line);
|
|
2541
2604
|
background: var(--bg-elev);
|
|
@@ -2543,6 +2606,14 @@ var renderAdminDocument = (service) => {
|
|
|
2543
2606
|
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
|
|
2544
2607
|
.btn-quiet { background: transparent; }
|
|
2545
2608
|
.btn-danger { color: var(--err); }
|
|
2609
|
+
/* Held after mouseup. Clearing an empty journal changes nothing on screen,
|
|
2610
|
+
so the press itself has to stay visible. */
|
|
2611
|
+
.icon-btn:active, .btn:active, .btn-quiet:active, .btn-danger:active, nav.side button:active,
|
|
2612
|
+
.icon-btn.pressed, .btn.pressed, .btn-quiet.pressed, .btn-danger.pressed, nav.side button.pressed {
|
|
2613
|
+
background: var(--bg-inset); border-color: var(--line-strong); color: var(--ink);
|
|
2614
|
+
}
|
|
2615
|
+
.btn-danger:active, .btn-danger.pressed { background: var(--err-soft); color: var(--err); }
|
|
2616
|
+
.btn-primary:active, .btn-primary.pressed { filter: brightness(0.88); color: var(--accent-ink); }
|
|
2546
2617
|
/* minmax(0, 1fr): a 1fr column will not shrink below its content, so a long
|
|
2547
2618
|
record or the full nav row would widen the page past the viewport. */
|
|
2548
2619
|
.layout {
|
|
@@ -2631,8 +2702,16 @@ var renderAdminDocument = (service) => {
|
|
|
2631
2702
|
input, select, textarea { font-size: 16px; }
|
|
2632
2703
|
.brand, .vendor, .controls { width: 100%; }
|
|
2633
2704
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
2634
|
-
|
|
2705
|
+
/* The layout fills the screen. A single-column grid stretches every auto
|
|
2706
|
+
row, so the tab bar grew with the leftover height and the buttons floated
|
|
2707
|
+
in the middle of it. The bar stays one row; the page below takes the rest. */
|
|
2708
|
+
.layout {
|
|
2709
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2710
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
2711
|
+
align-content: start;
|
|
2712
|
+
}
|
|
2635
2713
|
nav.side {
|
|
2714
|
+
align-self: start; height: auto;
|
|
2636
2715
|
flex-direction: row; align-items: center; overflow-x: auto; min-width: 0;
|
|
2637
2716
|
border-right: 0; border-bottom: 1px solid var(--line);
|
|
2638
2717
|
padding: 8px;
|
|
@@ -3426,7 +3505,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
3426
3505
|
};
|
|
3427
3506
|
|
|
3428
3507
|
// ../core/dist/version.js
|
|
3429
|
-
var PACKAGE_VERSION = true ? "1.6.
|
|
3508
|
+
var PACKAGE_VERSION = true ? "1.6.1" : UNRELEASED_VERSION;
|
|
3430
3509
|
|
|
3431
3510
|
// ../core/dist/signing.js
|
|
3432
3511
|
var encoder = new TextEncoder();
|
|
@@ -5462,4 +5541,4 @@ export {
|
|
|
5462
5541
|
apiKeyCredential,
|
|
5463
5542
|
OdxAPI
|
|
5464
5543
|
};
|
|
5465
|
-
//# sourceMappingURL=chunk-
|
|
5544
|
+
//# sourceMappingURL=chunk-QY3DD74Z.js.map
|