@reddoorla/maintenance 0.57.0 → 0.59.0
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/dist/airtable-YZ6VMSQZ.js +9 -0
- package/dist/{announce-JEVCDDKL.js → announce-Q2DXP5OO.js} +3 -3
- package/dist/{bump-deps-O3SOLQYY.js → bump-deps-RYHQIKW4.js} +2 -2
- package/dist/{chunk-4PY4I5OR.js → chunk-5PHCZ6L5.js} +11 -2
- package/dist/chunk-5PHCZ6L5.js.map +1 -0
- package/dist/{chunk-J3OPWFZE.js → chunk-6CSCLBAA.js} +2 -2
- package/dist/{chunk-XO2RUYVM.js → chunk-HB7QPECR.js} +2 -2
- package/dist/{chunk-IMIR7SC2.js → chunk-HPSGCDWY.js} +3 -3
- package/dist/chunk-HPSGCDWY.js.map +1 -0
- package/dist/{chunk-5L2QXUTU.js → chunk-KC4HU7BC.js} +2 -2
- package/dist/{chunk-CLVTVDOU.js → chunk-L4ULXHIN.js} +14 -2
- package/dist/chunk-L4ULXHIN.js.map +1 -0
- package/dist/{chunk-5WL3ET24.js → chunk-LMXIZITU.js} +3 -3
- package/dist/chunk-LMXIZITU.js.map +1 -0
- package/dist/{chunk-JQG222CI.js → chunk-TLZ4V2BE.js} +2 -2
- package/dist/{chunk-W3G7XFBZ.js → chunk-TZN2G6FD.js} +2 -2
- package/dist/cli/bin.js +13 -13
- package/dist/cli/commands/audit.js +6 -6
- package/dist/{convert-to-pnpm-UR64X3OX.js → convert-to-pnpm-KNCXU6FM.js} +2 -2
- package/dist/{digest-YTO73BEO.js → digest-RVIOHUXR.js} +10 -5
- package/dist/digest-RVIOHUXR.js.map +1 -0
- package/dist/{github-signals-XLQXXH6Q.js → github-signals-NCDBYSVV.js} +4 -4
- package/dist/index.d.ts +12 -0
- package/dist/index.js +114 -17
- package/dist/index.js.map +1 -1
- package/dist/{init-JITQXFVL.js → init-KD56UENX.js} +4 -4
- package/dist/{launch-XW6PEKUL.js → launch-35KSDHYO.js} +13 -7
- package/dist/launch-35KSDHYO.js.map +1 -0
- package/dist/{lighthouse-airtable-4FKYKFH6.js → lighthouse-airtable-N3KCBPVA.js} +3 -3
- package/dist/{onboard-TCQOP2W4.js → onboard-SCZ3UKZ2.js} +2 -2
- package/dist/{orchestrate-LHH3LQNP.js → orchestrate-D72PB6NG.js} +3 -3
- package/dist/{renovate-dispatch-YVBTBJJY.js → renovate-dispatch-P2FAJTQK.js} +42 -3
- package/dist/renovate-dispatch-P2FAJTQK.js.map +1 -0
- package/dist/{report-WK3SKWJI.js → report-CN56TGMK.js} +5 -5
- package/dist/{self-updating-BYUBUNO4.js → self-updating-HLMF7KEG.js} +2 -2
- package/dist/{svelte-codemods-BYRJAU7I.js → svelte-codemods-HNITLWQM.js} +2 -2
- package/dist/{sync-configs-JPRLAW5J.js → sync-configs-BZXBYKTI.js} +2 -2
- package/dist/{upgrade-ERA45EVR.js → upgrade-6YDUELFA.js} +2 -2
- package/dist/{websites-X5DLC2PC.js → websites-IYP7IGLU.js} +8 -4
- package/dist/{write-audits-to-airtable-CE4POBAF.js → write-audits-to-airtable-VDGHCZGQ.js} +4 -4
- package/package.json +1 -1
- package/dist/airtable-2BJX4ATJ.js +0 -9
- package/dist/chunk-4PY4I5OR.js.map +0 -1
- package/dist/chunk-5WL3ET24.js.map +0 -1
- package/dist/chunk-CLVTVDOU.js.map +0 -1
- package/dist/chunk-IMIR7SC2.js.map +0 -1
- package/dist/digest-YTO73BEO.js.map +0 -1
- package/dist/launch-XW6PEKUL.js.map +0 -1
- package/dist/renovate-dispatch-YVBTBJJY.js.map +0 -1
- /package/dist/{airtable-2BJX4ATJ.js.map → airtable-YZ6VMSQZ.js.map} +0 -0
- /package/dist/{announce-JEVCDDKL.js.map → announce-Q2DXP5OO.js.map} +0 -0
- /package/dist/{bump-deps-O3SOLQYY.js.map → bump-deps-RYHQIKW4.js.map} +0 -0
- /package/dist/{chunk-J3OPWFZE.js.map → chunk-6CSCLBAA.js.map} +0 -0
- /package/dist/{chunk-XO2RUYVM.js.map → chunk-HB7QPECR.js.map} +0 -0
- /package/dist/{chunk-5L2QXUTU.js.map → chunk-KC4HU7BC.js.map} +0 -0
- /package/dist/{chunk-JQG222CI.js.map → chunk-TLZ4V2BE.js.map} +0 -0
- /package/dist/{chunk-W3G7XFBZ.js.map → chunk-TZN2G6FD.js.map} +0 -0
- /package/dist/{convert-to-pnpm-UR64X3OX.js.map → convert-to-pnpm-KNCXU6FM.js.map} +0 -0
- /package/dist/{github-signals-XLQXXH6Q.js.map → github-signals-NCDBYSVV.js.map} +0 -0
- /package/dist/{init-JITQXFVL.js.map → init-KD56UENX.js.map} +0 -0
- /package/dist/{lighthouse-airtable-4FKYKFH6.js.map → lighthouse-airtable-N3KCBPVA.js.map} +0 -0
- /package/dist/{onboard-TCQOP2W4.js.map → onboard-SCZ3UKZ2.js.map} +0 -0
- /package/dist/{orchestrate-LHH3LQNP.js.map → orchestrate-D72PB6NG.js.map} +0 -0
- /package/dist/{report-WK3SKWJI.js.map → report-CN56TGMK.js.map} +0 -0
- /package/dist/{self-updating-BYUBUNO4.js.map → self-updating-HLMF7KEG.js.map} +0 -0
- /package/dist/{svelte-codemods-BYRJAU7I.js.map → svelte-codemods-HNITLWQM.js.map} +0 -0
- /package/dist/{sync-configs-JPRLAW5J.js.map → sync-configs-BZXBYKTI.js.map} +0 -0
- /package/dist/{upgrade-ERA45EVR.js.map → upgrade-6YDUELFA.js.map} +0 -0
- /package/dist/{websites-X5DLC2PC.js.map → websites-IYP7IGLU.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-CE4POBAF.js.map → write-audits-to-airtable-VDGHCZGQ.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
DEFAULT_INIT_STEPS,
|
|
3
3
|
a11yFixturesPage,
|
|
4
4
|
init
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-HB7QPECR.js";
|
|
6
6
|
import {
|
|
7
7
|
svelteCodemods
|
|
8
8
|
} from "./chunk-FUD4I2ZW.js";
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
} from "./chunk-WVRPOXKH.js";
|
|
17
17
|
import {
|
|
18
18
|
draftReportForSite
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-TZN2G6FD.js";
|
|
20
20
|
import "./chunk-6LIWDIXU.js";
|
|
21
21
|
import {
|
|
22
22
|
sendApprovedReports
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-KC4HU7BC.js";
|
|
24
24
|
import "./chunk-OGGRFBL4.js";
|
|
25
25
|
import {
|
|
26
26
|
BLURRED_CID,
|
|
@@ -60,7 +60,7 @@ import {
|
|
|
60
60
|
runAudits,
|
|
61
61
|
runAuditsAcross,
|
|
62
62
|
securityAudit
|
|
63
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-5PHCZ6L5.js";
|
|
64
64
|
import "./chunk-LKGVSM2O.js";
|
|
65
65
|
import {
|
|
66
66
|
fromJsonFile,
|
|
@@ -71,12 +71,12 @@ import "./chunk-XXTZBPUY.js";
|
|
|
71
71
|
import "./chunk-XTK5VIQB.js";
|
|
72
72
|
import {
|
|
73
73
|
fromAirtableBase
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-TLZ4V2BE.js";
|
|
75
75
|
import "./chunk-U5SZ4FOP.js";
|
|
76
76
|
import {
|
|
77
77
|
SEVERITY_RANK,
|
|
78
78
|
siteSlug
|
|
79
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-L4ULXHIN.js";
|
|
80
80
|
import "./chunk-HN6I2XWI.js";
|
|
81
81
|
import "./chunk-WEKL2HYJ.js";
|
|
82
82
|
import "./chunk-6VAL7XJT.js";
|
|
@@ -232,6 +232,17 @@ var SUBMISSION_STATUS_SCRIPT = `document.querySelectorAll("button.subm-status").
|
|
|
232
232
|
});
|
|
233
233
|
});`;
|
|
234
234
|
|
|
235
|
+
// src/dashboard/site-details.ts
|
|
236
|
+
var SITE_STATUS_OPTIONS = [
|
|
237
|
+
"in development",
|
|
238
|
+
"launch period",
|
|
239
|
+
"maintenance",
|
|
240
|
+
"hosting",
|
|
241
|
+
"probably not our problem",
|
|
242
|
+
"deprecated"
|
|
243
|
+
];
|
|
244
|
+
var FREQ_OPTIONS = ["None", "Monthly", "Quarterly", "Yearly"];
|
|
245
|
+
|
|
235
246
|
// src/dashboard/render.ts
|
|
236
247
|
var DASH = "\u2014";
|
|
237
248
|
function scoreTile(label, value) {
|
|
@@ -380,21 +391,44 @@ function detailRow(label, value) {
|
|
|
380
391
|
const display = typeof value === "string" && value.trim().length > 0 ? escapeHtml(value.trim()) : DASH;
|
|
381
392
|
return `<div class="detail"><dt>${escapeHtml(label)}</dt><dd>${display}</dd></div>`;
|
|
382
393
|
}
|
|
394
|
+
function savedSpan(field) {
|
|
395
|
+
return `<span class="detail-saved" data-for="${field}"></span>`;
|
|
396
|
+
}
|
|
397
|
+
function selectRow(label, field, options, current, url) {
|
|
398
|
+
const inList = current !== null && options.includes(current);
|
|
399
|
+
const opts = options.map(
|
|
400
|
+
(o) => `<option value="${escapeHtml(o)}"${o === current ? " selected" : ""}>${escapeHtml(o)}</option>`
|
|
401
|
+
).join("");
|
|
402
|
+
const placeholder = inList ? "" : `<option value="" disabled selected hidden>\u2014 select \u2014</option>`;
|
|
403
|
+
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><select id="detail-${field}" data-detail-field="${field}" data-details-url="${url}">${placeholder}${opts}</select>${savedSpan(field)}</dd></div>`;
|
|
404
|
+
}
|
|
405
|
+
function inputRow(label, field, value, url) {
|
|
406
|
+
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="text" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" value="${escapeHtml(value ?? "")}" />${savedSpan(field)}</dd></div>`;
|
|
407
|
+
}
|
|
408
|
+
function textareaRow(label, field, value, url) {
|
|
409
|
+
return `<div class="detail wide"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><textarea id="detail-${field}" data-detail-field="${field}" data-details-url="${url}">${escapeHtml(value ?? "")}</textarea>${savedSpan(field)}</dd></div>`;
|
|
410
|
+
}
|
|
383
411
|
function siteDetailsSection(site) {
|
|
412
|
+
const url = `/api/sites/${escapeHtml(siteSlug(site.name))}/details`;
|
|
384
413
|
const lastCommit = site.lastCommitAt ? `${relativeTimeFromNow(site.lastCommitAt)}` : null;
|
|
385
414
|
const rows = [
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
415
|
+
selectRow("Status", "status", SITE_STATUS_OPTIONS, site.status, url),
|
|
416
|
+
selectRow("Maintenance cadence", "maintenanceFreq", FREQ_OPTIONS, site.maintenanceFreq, url),
|
|
417
|
+
selectRow("Testing cadence", "testingFreq", FREQ_OPTIONS, site.testingFreq, url),
|
|
418
|
+
inputRow("Report recipients (To)", "reportRecipientsTo", site.reportRecipientsTo, url),
|
|
419
|
+
inputRow("Report recipients (CC)", "reportRecipientsCc", site.reportRecipientsCc, url),
|
|
420
|
+
inputRow("Point of contact", "pointOfContact", site.pointOfContact, url),
|
|
421
|
+
inputRow("GA4 property", "ga4PropertyId", site.ga4PropertyId, url),
|
|
422
|
+
inputRow("Search query", "searchQuery", site.searchQuery, url),
|
|
423
|
+
inputRow("Git repo", "gitRepo", site.gitRepo, url),
|
|
424
|
+
textareaRow("Copy \u2014 Intro", "copyIntro", site.copyIntro, url),
|
|
425
|
+
textareaRow("Copy \u2014 Contact", "copyContact", site.copyContact, url),
|
|
426
|
+
textareaRow("Copy \u2014 Footer", "copyFooter", site.copyFooter, url),
|
|
394
427
|
detailRow("Last commit", lastCommit)
|
|
395
428
|
].join("");
|
|
429
|
+
const triggerBtn = site.gitRepo?.trim() ? `<button class="trigger-renovate" data-trigger-url="/api/sites/${escapeHtml(siteSlug(site.name))}/trigger-renovate">Trigger Renovate</button>` : "";
|
|
396
430
|
return `<div class="section site-details">
|
|
397
|
-
<h2>Site details</h2>
|
|
431
|
+
<h2>Site details ${triggerBtn}</h2>
|
|
398
432
|
<dl class="details">${rows}</dl>
|
|
399
433
|
</div>`;
|
|
400
434
|
}
|
|
@@ -445,8 +479,13 @@ button.approve:disabled { opacity: 0.6; cursor: default; }
|
|
|
445
479
|
.setup-missing { color: #a65a00; }
|
|
446
480
|
.details { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.5rem 1.5rem; margin: 0; }
|
|
447
481
|
.detail { display: flex; flex-direction: column; }
|
|
482
|
+
.detail.wide { grid-column: 1 / -1; }
|
|
448
483
|
.detail dt { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: #999; }
|
|
449
484
|
.detail dd { margin: 0; }
|
|
485
|
+
.detail dd input, .detail dd select, .detail dd textarea { width: 100%; box-sizing: border-box; font: inherit; padding: 0.25rem 0.4rem; border: 1px solid #ccc; border-radius: 4px; background: transparent; color: inherit; }
|
|
486
|
+
.detail dd textarea { min-height: 3.5rem; resize: vertical; }
|
|
487
|
+
.detail-saved { font-size: 0.8rem; color: #2a8; }
|
|
488
|
+
button.trigger-renovate { font: inherit; font-size: 0.8rem; padding: 0.15rem 0.6rem; margin-left: 0.5rem; border: 1px solid #888; border-radius: 6px; background: transparent; color: inherit; cursor: pointer; }
|
|
450
489
|
`;
|
|
451
490
|
function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = null, now = /* @__PURE__ */ new Date()) {
|
|
452
491
|
const name = escapeHtml(site.name);
|
|
@@ -524,6 +563,45 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
524
563
|
}
|
|
525
564
|
});
|
|
526
565
|
});
|
|
566
|
+
// Trigger-renovate button: async on-demand dispatch (mirrors the cockpit).
|
|
567
|
+
document.querySelectorAll("button.trigger-renovate").forEach((b) => {
|
|
568
|
+
b.addEventListener("click", async () => {
|
|
569
|
+
b.disabled = true;
|
|
570
|
+
b.textContent = "Dispatching\u2026";
|
|
571
|
+
try {
|
|
572
|
+
const res = await fetch(b.dataset.triggerUrl, { method: "POST" });
|
|
573
|
+
b.textContent = res.ok ? "Dispatched \u2713" : "Failed";
|
|
574
|
+
if (!res.ok) b.disabled = false;
|
|
575
|
+
} catch {
|
|
576
|
+
b.textContent = "Failed";
|
|
577
|
+
b.disabled = false;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
});
|
|
581
|
+
// Site-details editor: save on change (selects) / blur (inputs+textareas, only
|
|
582
|
+
// when the value actually changed). The per-field span shows \u2713 / \u2717.
|
|
583
|
+
function saveDetail(el) {
|
|
584
|
+
const span = document.querySelector('.detail-saved[data-for="' + el.dataset.detailField + '"]');
|
|
585
|
+
fetch(el.dataset.detailsUrl, {
|
|
586
|
+
method: "POST",
|
|
587
|
+
headers: { "content-type": "application/json" },
|
|
588
|
+
body: JSON.stringify({ field: el.dataset.detailField, value: el.value }),
|
|
589
|
+
})
|
|
590
|
+
.then((r) => {
|
|
591
|
+
if (span) span.textContent = r.ok ? " \u2713" : " \u2717";
|
|
592
|
+
})
|
|
593
|
+
.catch(() => {
|
|
594
|
+
if (span) span.textContent = " \u2717";
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
document.querySelectorAll("select[data-detail-field]").forEach((s) => {
|
|
598
|
+
s.addEventListener("change", () => saveDetail(s));
|
|
599
|
+
});
|
|
600
|
+
document.querySelectorAll("input[data-detail-field], textarea[data-detail-field]").forEach((i) => {
|
|
601
|
+
i.addEventListener("blur", () => {
|
|
602
|
+
if (i.value !== i.defaultValue) saveDetail(i);
|
|
603
|
+
});
|
|
604
|
+
});
|
|
527
605
|
${SUBMISSION_STATUS_SCRIPT}
|
|
528
606
|
// Checklist gate: ticking a box POSTs the one field; the response { complete }
|
|
529
607
|
// decides whether THIS report's Approve button is enabled. Scoped per report by
|
|
@@ -666,6 +744,7 @@ details.tier > summary { cursor:pointer; font-weight:700; font-size:1.05rem; pad
|
|
|
666
744
|
.chip { font-size:0.8rem; padding:0.1rem 0.5rem; border-radius:6px; background:#f0f0f0; }
|
|
667
745
|
@media (prefers-color-scheme: dark) { .chip { background:#222; } }
|
|
668
746
|
.chip.critical { background:#fdecea; color:#b00; }
|
|
747
|
+
.chip.stuck { border:1px solid #b00; font-weight:600; }
|
|
669
748
|
.badge { font-weight:700; color:#C00; font-size:0.72rem; margin-right:0.25rem; }
|
|
670
749
|
.all-clear { background:#e8f5e9; color:#1b7a2f; padding:0.6rem 1rem; border-radius:8px; margin-bottom:1.25rem; font-weight:600; }
|
|
671
750
|
@media (prefers-color-scheme: dark) { .all-clear { background:#10240f; color:#7fce85; } }
|
|
@@ -682,6 +761,7 @@ var FILTERS = [
|
|
|
682
761
|
"delivery",
|
|
683
762
|
"prs",
|
|
684
763
|
"ci",
|
|
764
|
+
"auto-fix-failed",
|
|
685
765
|
"stale",
|
|
686
766
|
"no-domain",
|
|
687
767
|
"pending",
|
|
@@ -695,6 +775,7 @@ function summaryBar(model) {
|
|
|
695
775
|
`${s.deliveryFailures} delivery`,
|
|
696
776
|
`${s.renovateFailing} PRs failing`,
|
|
697
777
|
`${s.ciRed} CI red`,
|
|
778
|
+
`${s.autoFixStuck} auto-fix stuck`,
|
|
698
779
|
`${s.pending} pending`,
|
|
699
780
|
`${s.newSubmissions ?? 0} new`
|
|
700
781
|
].join(" \xB7 ");
|
|
@@ -771,7 +852,7 @@ function attentionBadge(status) {
|
|
|
771
852
|
}
|
|
772
853
|
function chips(c) {
|
|
773
854
|
const items = c.items.map((it) => {
|
|
774
|
-
const cls = it.severity === "critical" ? "chip critical" : "chip";
|
|
855
|
+
const cls = it.autoFixExhausted ? "chip critical stuck" : it.severity === "critical" ? "chip critical" : "chip";
|
|
775
856
|
return `<span class="${cls}">${attentionBadge(it.status)}${escapeHtml(it.title)}</span>`;
|
|
776
857
|
});
|
|
777
858
|
for (const reason of c.watchReasons)
|
|
@@ -783,13 +864,19 @@ function signalsAttr(c) {
|
|
|
783
864
|
for (const it of c.items) {
|
|
784
865
|
kinds.add(it.kind === "vuln" ? "vulns" : it.kind === "renovate" ? "prs" : it.kind);
|
|
785
866
|
}
|
|
867
|
+
if (c.items.some((it) => it.autoFixExhausted)) kinds.add("auto-fix-failed");
|
|
786
868
|
for (const sig of c.watchSignals) kinds.add(sig);
|
|
787
869
|
return [...kinds].join(" ");
|
|
788
870
|
}
|
|
871
|
+
function triggerRenovateBtn(c) {
|
|
872
|
+
if (!c.site.gitRepo?.trim()) return "";
|
|
873
|
+
const url = `/api/sites/${escapeHtml(siteSlug(c.site.name))}/trigger-renovate`;
|
|
874
|
+
return `<button class="trigger-renovate" data-trigger-url="${url}">Trigger Renovate</button>`;
|
|
875
|
+
}
|
|
789
876
|
function cockpitCard(c) {
|
|
790
877
|
const base = card(c.site);
|
|
791
878
|
const pill = `<span class="pill ${c.tier}">${PILL_LABEL[c.tier]}</span>`;
|
|
792
|
-
const extra = `${pill}${chips(c)}${submBadge(c)}`;
|
|
879
|
+
const extra = `${pill}${chips(c)}${submBadge(c)}${triggerRenovateBtn(c)}`;
|
|
793
880
|
const opening = `<article class="card" data-signals="${signalsAttr(c)}">`;
|
|
794
881
|
return base.replace('<article class="card">', () => opening).replace("</article>", () => `${extra}</article>`);
|
|
795
882
|
}
|
|
@@ -822,6 +909,16 @@ var FILTER_SCRIPT = `<script>
|
|
|
822
909
|
catch(e){ b.textContent = 'Failed'; b.disabled = false; }
|
|
823
910
|
});
|
|
824
911
|
});
|
|
912
|
+
// trigger-renovate buttons: fire the on-demand dispatch (async, fire-and-forget).
|
|
913
|
+
document.querySelectorAll('button.trigger-renovate').forEach(function(b){
|
|
914
|
+
b.addEventListener('click', async function(){
|
|
915
|
+
b.disabled = true; b.textContent = 'Dispatching\u2026';
|
|
916
|
+
try { var res = await fetch(b.dataset.triggerUrl, { method: 'POST' });
|
|
917
|
+
b.textContent = res.ok ? 'Dispatched \u2713' : 'Failed';
|
|
918
|
+
if (!res.ok) b.disabled = false; }
|
|
919
|
+
catch(e){ b.textContent = 'Failed'; b.disabled = false; }
|
|
920
|
+
});
|
|
921
|
+
});
|
|
825
922
|
})();
|
|
826
923
|
</script>`;
|
|
827
924
|
function renderCockpitHtml(model) {
|