@crvouga/mockingbird-service-slack 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-XNPGYYVE.js → chunk-6NKJ75J3.js} +89 -10
- package/dist/chunk-6NKJ75J3.js.map +7 -0
- package/dist/{chunk-GPFJICAV.js → chunk-PKYQRMRQ.js} +2 -2
- 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-XNPGYYVE.js.map +0 -7
- /package/dist/{chunk-GPFJICAV.js.map → chunk-PKYQRMRQ.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
# Changelog — @crvouga/mockingbird-service-slack
|
|
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
|
|
|
@@ -2162,6 +2162,50 @@ function bootAdmin(config) {
|
|
|
2162
2162
|
if (render)
|
|
2163
2163
|
await render();
|
|
2164
2164
|
}
|
|
2165
|
+
const delay = (ms) => new Promise((resolve) => {
|
|
2166
|
+
window.setTimeout(resolve, ms);
|
|
2167
|
+
});
|
|
2168
|
+
const confirmAction = async (button, pending, done, work) => {
|
|
2169
|
+
if (button.dataset.pending === "1")
|
|
2170
|
+
return;
|
|
2171
|
+
const label = button.textContent ?? "";
|
|
2172
|
+
const width = button.offsetWidth;
|
|
2173
|
+
button.dataset.pending = "1";
|
|
2174
|
+
button.classList.add("pressed");
|
|
2175
|
+
button.setAttribute("aria-busy", "true");
|
|
2176
|
+
button.style.minWidth = `${width}px`;
|
|
2177
|
+
button.textContent = pending;
|
|
2178
|
+
try {
|
|
2179
|
+
await work();
|
|
2180
|
+
button.textContent = done;
|
|
2181
|
+
await delay(1e3);
|
|
2182
|
+
} catch (error) {
|
|
2183
|
+
showError(error);
|
|
2184
|
+
} finally {
|
|
2185
|
+
button.textContent = label;
|
|
2186
|
+
button.style.minWidth = "";
|
|
2187
|
+
button.classList.remove("pressed");
|
|
2188
|
+
button.removeAttribute("aria-busy");
|
|
2189
|
+
delete button.dataset.pending;
|
|
2190
|
+
}
|
|
2191
|
+
};
|
|
2192
|
+
document.addEventListener("click", (event) => {
|
|
2193
|
+
const target = event.target;
|
|
2194
|
+
if (!(target instanceof Element))
|
|
2195
|
+
return;
|
|
2196
|
+
const button = target.closest("button");
|
|
2197
|
+
if (!(button instanceof HTMLButtonElement) || button.dataset.pending === "1")
|
|
2198
|
+
return;
|
|
2199
|
+
button.classList.add("pressed");
|
|
2200
|
+
const token = String(Date.now());
|
|
2201
|
+
button.dataset.press = token;
|
|
2202
|
+
window.setTimeout(() => {
|
|
2203
|
+
if (button.dataset.press !== token || button.dataset.pending === "1")
|
|
2204
|
+
return;
|
|
2205
|
+
button.classList.remove("pressed");
|
|
2206
|
+
delete button.dataset.press;
|
|
2207
|
+
}, 450);
|
|
2208
|
+
});
|
|
2165
2209
|
el("namespace", HTMLSelectElement).addEventListener("change", () => {
|
|
2166
2210
|
state.namespace = el("namespace", HTMLSelectElement).value;
|
|
2167
2211
|
refresh().catch(showError);
|
|
@@ -2172,7 +2216,7 @@ function bootAdmin(config) {
|
|
|
2172
2216
|
refresh().catch(showError);
|
|
2173
2217
|
});
|
|
2174
2218
|
el("refresh", HTMLButtonElement).addEventListener("click", () => {
|
|
2175
|
-
refresh().catch(showError);
|
|
2219
|
+
confirmAction(el("refresh", HTMLButtonElement), "Refreshing...", "Updated", () => refresh()).catch(showError);
|
|
2176
2220
|
});
|
|
2177
2221
|
el("collections", HTMLElement).addEventListener("click", (event) => {
|
|
2178
2222
|
const target = event.target;
|
|
@@ -2295,10 +2339,10 @@ function bootAdmin(config) {
|
|
|
2295
2339
|
}).then(() => renderFaults()).catch(showError);
|
|
2296
2340
|
});
|
|
2297
2341
|
el("fault-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2298
|
-
api("DELETE", "/faults").then(() => renderFaults()).catch(showError);
|
|
2342
|
+
confirmAction(el("fault-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/faults").then(() => renderFaults())).catch(showError);
|
|
2299
2343
|
});
|
|
2300
2344
|
el("journal-clear", HTMLButtonElement).addEventListener("click", () => {
|
|
2301
|
-
api("DELETE", "/requests").then(() => renderJournal()).catch(showError);
|
|
2345
|
+
confirmAction(el("journal-clear", HTMLButtonElement), "Clearing...", "Cleared", () => api("DELETE", "/requests").then(() => renderJournal())).catch(showError);
|
|
2302
2346
|
});
|
|
2303
2347
|
el("route-list", HTMLElement).addEventListener("click", (event) => {
|
|
2304
2348
|
const target = event.target;
|
|
@@ -2413,9 +2457,13 @@ function bootAdmin(config) {
|
|
|
2413
2457
|
var clientPrelude = [isRecord2, mountAdminBrand, startAdminBrand, faultPresetList, bootAdmin].map((fn) => fn.toString()).join("\n");
|
|
2414
2458
|
var adminClientSource = (config) => {
|
|
2415
2459
|
const payload = JSON.stringify(config).replace(/</g, "\\u003c");
|
|
2460
|
+
const entry = bootAdmin.name;
|
|
2461
|
+
if (!/^[A-Za-z_$][\w$]*$/.test(entry)) {
|
|
2462
|
+
throw new Error("admin client cannot call its boot function");
|
|
2463
|
+
}
|
|
2416
2464
|
return `<script>
|
|
2417
2465
|
${clientPrelude}
|
|
2418
|
-
|
|
2466
|
+
${entry}(${payload});
|
|
2419
2467
|
</script>`;
|
|
2420
2468
|
};
|
|
2421
2469
|
|
|
@@ -2629,9 +2677,24 @@ var renderAdminDocument = (service) => {
|
|
|
2629
2677
|
.controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
2630
2678
|
label.field { display: flex; flex-direction: column; gap: 2px; font-size: 11px; color: var(--faint); }
|
|
2631
2679
|
label.field input, label.field select, .controls input[type="password"] {
|
|
2632
|
-
background: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2633
|
-
padding: 7px 8px; min-height: 36px;
|
|
2634
|
-
}
|
|
2680
|
+
background-color: var(--bg-inset); border: 1px solid var(--line); border-radius: 8px;
|
|
2681
|
+
padding: 7px 8px; min-height: 36px; line-height: 1.2;
|
|
2682
|
+
}
|
|
2683
|
+
/* A native menu ignores min-height, so Preset rendered about half as tall as
|
|
2684
|
+
the text fields in the same form. Paint it like those fields. */
|
|
2685
|
+
label.field select {
|
|
2686
|
+
-webkit-appearance: none; appearance: none;
|
|
2687
|
+
padding-right: 28px;
|
|
2688
|
+
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");
|
|
2689
|
+
background-repeat: no-repeat; background-position: right 10px center; background-size: 12px 12px;
|
|
2690
|
+
}
|
|
2691
|
+
.stack > .field > input,
|
|
2692
|
+
.stack > .field > select,
|
|
2693
|
+
.stack > .field > textarea,
|
|
2694
|
+
dialog .field > input,
|
|
2695
|
+
dialog .field > select,
|
|
2696
|
+
dialog .field > textarea { width: 100%; }
|
|
2697
|
+
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger, nav.side button { cursor: pointer; }
|
|
2635
2698
|
.icon-btn, .btn, .btn-primary, .btn-quiet, .btn-danger {
|
|
2636
2699
|
border-radius: 9px; min-height: 36px; padding: 0 12px; border: 1px solid var(--line);
|
|
2637
2700
|
background: var(--bg-elev);
|
|
@@ -2639,6 +2702,14 @@ var renderAdminDocument = (service) => {
|
|
|
2639
2702
|
.btn-primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; }
|
|
2640
2703
|
.btn-quiet { background: transparent; }
|
|
2641
2704
|
.btn-danger { color: var(--err); }
|
|
2705
|
+
/* Held after mouseup. Clearing an empty journal changes nothing on screen,
|
|
2706
|
+
so the press itself has to stay visible. */
|
|
2707
|
+
.icon-btn:active, .btn:active, .btn-quiet:active, .btn-danger:active, nav.side button:active,
|
|
2708
|
+
.icon-btn.pressed, .btn.pressed, .btn-quiet.pressed, .btn-danger.pressed, nav.side button.pressed {
|
|
2709
|
+
background: var(--bg-inset); border-color: var(--line-strong); color: var(--ink);
|
|
2710
|
+
}
|
|
2711
|
+
.btn-danger:active, .btn-danger.pressed { background: var(--err-soft); color: var(--err); }
|
|
2712
|
+
.btn-primary:active, .btn-primary.pressed { filter: brightness(0.88); color: var(--accent-ink); }
|
|
2642
2713
|
/* minmax(0, 1fr): a 1fr column will not shrink below its content, so a long
|
|
2643
2714
|
record or the full nav row would widen the page past the viewport. */
|
|
2644
2715
|
.layout {
|
|
@@ -2727,8 +2798,16 @@ var renderAdminDocument = (service) => {
|
|
|
2727
2798
|
input, select, textarea { font-size: 16px; }
|
|
2728
2799
|
.brand, .vendor, .controls { width: 100%; }
|
|
2729
2800
|
label.field, label.field select, label.field input { flex: 1; min-width: 0; }
|
|
2730
|
-
|
|
2801
|
+
/* The layout fills the screen. A single-column grid stretches every auto
|
|
2802
|
+
row, so the tab bar grew with the leftover height and the buttons floated
|
|
2803
|
+
in the middle of it. The bar stays one row; the page below takes the rest. */
|
|
2804
|
+
.layout {
|
|
2805
|
+
grid-template-columns: minmax(0, 1fr);
|
|
2806
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
2807
|
+
align-content: start;
|
|
2808
|
+
}
|
|
2731
2809
|
nav.side {
|
|
2810
|
+
align-self: start; height: auto;
|
|
2732
2811
|
flex-direction: row; align-items: center; overflow-x: auto; min-width: 0;
|
|
2733
2812
|
border-right: 0; border-bottom: 1px solid var(--line);
|
|
2734
2813
|
padding: 8px;
|
|
@@ -3522,7 +3601,7 @@ var stateAdminRoutes = (routes) => {
|
|
|
3522
3601
|
};
|
|
3523
3602
|
|
|
3524
3603
|
// ../core/dist/version.js
|
|
3525
|
-
var PACKAGE_VERSION = true ? "1.6.
|
|
3604
|
+
var PACKAGE_VERSION = true ? "1.6.1" : UNRELEASED_VERSION;
|
|
3526
3605
|
|
|
3527
3606
|
// ../core/dist/webhooks.js
|
|
3528
3607
|
var json5 = (status, body) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
@@ -5352,4 +5431,4 @@ export {
|
|
|
5352
5431
|
slackCredential,
|
|
5353
5432
|
SlackAPI
|
|
5354
5433
|
};
|
|
5355
|
-
//# sourceMappingURL=chunk-
|
|
5434
|
+
//# sourceMappingURL=chunk-6NKJ75J3.js.map
|