@reddoorla/maintenance 0.86.0 → 0.88.2
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-QG5ICI3Y.js +9 -0
- package/dist/{announce-MXTUQ6C7.js → announce-GKD5YJNB.js} +49 -28
- package/dist/announce-GKD5YJNB.js.map +1 -0
- package/dist/attachments-NLZIJ5NU.js +9 -0
- package/dist/{blux-ZGDSHI3U.js → blux-DN4MI532.js} +5 -5
- package/dist/{bump-deps-EC74CPLS.js → bump-deps-KGH5UYSF.js} +4 -4
- package/dist/{chunk-N45M3FDK.js → chunk-6I6L3CMX.js} +4 -4
- package/dist/{chunk-KTH5ZODA.js → chunk-7BZUOZPU.js} +2 -2
- package/dist/{chunk-2EVEFOZY.js → chunk-7FFUBF4I.js} +6 -3
- package/dist/chunk-7FFUBF4I.js.map +1 -0
- package/dist/{chunk-LDWZSLSU.js → chunk-7NYN2P6I.js} +7 -4
- package/dist/{chunk-LDWZSLSU.js.map → chunk-7NYN2P6I.js.map} +1 -1
- package/dist/{chunk-X3B723J4.js → chunk-7TMWBXX7.js} +184 -25
- package/dist/chunk-7TMWBXX7.js.map +1 -0
- package/dist/{chunk-3VQWSE3F.js → chunk-7UAYMAKR.js} +4 -4
- package/dist/{chunk-W7Z3BGCI.js → chunk-A2UNJIKH.js} +15 -7
- package/dist/chunk-A2UNJIKH.js.map +1 -0
- package/dist/{chunk-F5KM4LEQ.js → chunk-ANJNTAMM.js} +4 -70
- package/dist/chunk-ANJNTAMM.js.map +1 -0
- package/dist/{chunk-2ZPT7GLV.js → chunk-B23FFWU4.js} +4 -4
- package/dist/chunk-B23FFWU4.js.map +1 -0
- package/dist/{chunk-DJZWYIPP.js → chunk-BGTYPVLT.js} +1 -1
- package/dist/chunk-BGTYPVLT.js.map +1 -0
- package/dist/chunk-BRYXFH77.js +70 -0
- package/dist/chunk-BRYXFH77.js.map +1 -0
- package/dist/{chunk-2NDRHXMR.js → chunk-DGZWFI2G.js} +18 -141
- package/dist/chunk-DGZWFI2G.js.map +1 -0
- package/dist/{chunk-ACBRLLFT.js → chunk-F3JWOPTG.js} +7 -3
- package/dist/chunk-F3JWOPTG.js.map +1 -0
- package/dist/chunk-GQDDWYU2.js +372 -0
- package/dist/chunk-GQDDWYU2.js.map +1 -0
- package/dist/{chunk-Z7AXYKQB.js → chunk-IY6256GK.js} +1 -1
- package/dist/{chunk-BYK66EWO.js → chunk-J3WEZGIN.js} +52 -46
- package/dist/chunk-J3WEZGIN.js.map +1 -0
- package/dist/{chunk-BNM5POSJ.js → chunk-JRHIFA5R.js} +2 -2
- package/dist/{chunk-ZKXSX4LO.js → chunk-K6SLF6GI.js} +6 -6
- package/dist/{chunk-CQR4LIM7.js → chunk-KJGKZLCT.js} +7 -3
- package/dist/{chunk-CQR4LIM7.js.map → chunk-KJGKZLCT.js.map} +1 -1
- package/dist/{chunk-PPE5KZJK.js → chunk-KMCZA7CH.js} +13 -3
- package/dist/chunk-KMCZA7CH.js.map +1 -0
- package/dist/{chunk-3SF7D4DY.js → chunk-MFHS7IQ2.js} +36 -1
- package/dist/{chunk-3SF7D4DY.js.map → chunk-MFHS7IQ2.js.map} +1 -1
- package/dist/{chunk-SNSTJLQW.js → chunk-NO74DXDP.js} +48 -2
- package/dist/chunk-NO74DXDP.js.map +1 -0
- package/dist/{chunk-C6B4RHXR.js → chunk-O3GT46R2.js} +8 -2
- package/dist/chunk-O3GT46R2.js.map +1 -0
- package/dist/{chunk-ITIOFN7A.js → chunk-P6AORG32.js} +29 -10
- package/dist/chunk-P6AORG32.js.map +1 -0
- package/dist/{chunk-SLUQ7R6I.js → chunk-PR343K7F.js} +5 -5
- package/dist/{chunk-P2FE5AI6.js → chunk-Q47DU255.js} +4 -4
- package/dist/{chunk-EVBCK2KC.js → chunk-RARREDQE.js} +2 -1
- package/dist/{chunk-EVBCK2KC.js.map → chunk-RARREDQE.js.map} +1 -1
- package/dist/chunk-RUPPWAD6.js +7 -0
- package/dist/chunk-RUPPWAD6.js.map +1 -0
- package/dist/{chunk-VSBFM7DS.js → chunk-SJOXWJ5Y.js} +3 -3
- package/dist/{chunk-TERE5SDF.js → chunk-ULHPALI5.js} +4 -4
- package/dist/{chunk-XUGSZP7Z.js → chunk-W45FZEGE.js} +2 -2
- package/dist/{chunk-JHGHLKFS.js → chunk-WS6NU475.js} +2 -2
- package/dist/chunk-XP5WM2LV.js +146 -0
- package/dist/chunk-XP5WM2LV.js.map +1 -0
- package/dist/{chunk-ILUNZHYV.js → chunk-YFAXOD7Z.js} +10 -6
- package/dist/chunk-YFAXOD7Z.js.map +1 -0
- package/dist/{chunk-6TWWY7ZU.js → chunk-Z3JXLULD.js} +2 -2
- package/dist/cli/bin.js +34 -29
- package/dist/cli/bin.js.map +1 -1
- package/dist/cli/commands/audit.d.ts +4 -0
- package/dist/cli/commands/audit.js +25 -18
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/client-JYKPVCJX.js +11 -0
- package/dist/configs/playwright-a11y.js +1 -1
- package/dist/{convert-to-pnpm-6L6P74WR.js → convert-to-pnpm-NWB5FCQ2.js} +4 -4
- package/dist/{db-B35OGV3G.js → db-V6UIS433.js} +124 -29
- package/dist/db-V6UIS433.js.map +1 -0
- package/dist/{digest-BL6UJYKH.js → digest-2JEAEJK6.js} +60 -35
- package/dist/digest-2JEAEJK6.js.map +1 -0
- package/dist/digest-state-CRZRNGDI.js +25 -0
- package/dist/digest-state-CRZRNGDI.js.map +1 -0
- package/dist/digest-state-F37XUCS5.js +13 -0
- package/dist/{dump-P6EBSIOH.js → dump-EPL7AZFR.js} +38 -13
- package/dist/dump-EPL7AZFR.js.map +1 -0
- package/dist/{email-VTTTKKL5.js → email-SL7464YI.js} +16 -6
- package/dist/{email-VTTTKKL5.js.map → email-SL7464YI.js.map} +1 -1
- package/dist/{ensure-site-DFTB7MN3.js → ensure-site-FU6527OU.js} +19 -11
- package/dist/ensure-site-FU6527OU.js.map +1 -0
- package/dist/fleet-state-R5LU7IC3.js +41 -0
- package/dist/{forms-notify-target-75U6OU7L.js → forms-notify-target-SGDGXXK5.js} +10 -7
- package/dist/forms-notify-target-SGDGXXK5.js.map +1 -0
- package/dist/{github-signals-IJUPGCUX.js → github-signals-GWGCKEE2.js} +13 -12
- package/dist/{github-signals-IJUPGCUX.js.map → github-signals-GWGCKEE2.js.map} +1 -1
- package/dist/{header-image-AWLLQA4L.js → header-image-7A7XLVEU.js} +8 -8
- package/dist/{header-images-335L2AKB.js → header-images-SQBCE5OD.js} +21 -1
- package/dist/header-images-SQBCE5OD.js.map +1 -0
- package/dist/{health-endpoint-WJC2UMYS.js → health-endpoint-UVX6R5N5.js} +4 -4
- package/dist/health-mirror-GCDN7BJL.js +46 -0
- package/dist/health-mirror-GCDN7BJL.js.map +1 -0
- package/dist/{import-airtable-HE43FB4H.js → import-airtable-OHVY344G.js} +7 -5
- package/dist/index.d.ts +149 -0
- package/dist/index.js +245 -108
- package/dist/index.js.map +1 -1
- package/dist/{init-NJEOEO7I.js → init-FGTYNGUI.js} +11 -11
- package/dist/{launch-XNAX427U.js → launch-5H7LPEGP.js} +59 -29
- package/dist/launch-5H7LPEGP.js.map +1 -0
- package/dist/{lighthouse-airtable-LBVIYYP5.js → lighthouse-airtable-3GUWHETW.js} +3 -3
- package/dist/migrate-YITCXBLS.js +7 -0
- package/dist/{notify-C645PGD5.js → notify-4HP4GZ2H.js} +5 -5
- package/dist/{onboard-GK4PHPNI.js → onboard-BKCYBAVW.js} +4 -4
- package/dist/{orchestrate-77UO4BYJ.js → orchestrate-JNKCWU5K.js} +14 -13
- package/dist/parity-NBYZUBFU.js +14 -0
- package/dist/pdf-N5QLQ5ZQ.js +38 -0
- package/dist/pdf-N5QLQ5ZQ.js.map +1 -0
- package/dist/{pipeline-S6CVHDGB.js → pipeline-WYTXSLHX.js} +3 -3
- package/dist/{preflight-6WBNU2GZ.js → preflight-IMTYDDD4.js} +15 -14
- package/dist/{preflight-6WBNU2GZ.js.map → preflight-IMTYDDD4.js.map} +1 -1
- package/dist/{prismic-ci-3RHOZUUT.js → prismic-ci-MY2U6NN7.js} +7 -7
- package/dist/{prismic-models-QBGUT2Q3.js → prismic-models-NJN5JORF.js} +15 -10
- package/dist/prismic-models-NJN5JORF.js.map +1 -0
- package/dist/prospect/types.d.ts +281 -0
- package/dist/prospect/types.js +1 -0
- package/dist/{prospect-audit-IUNCJ2LV.js → prospect-audit-JMBRVXSG.js} +32 -13
- package/dist/prospect-audit-JMBRVXSG.js.map +1 -0
- package/dist/recipes/sync-configs.js +2 -2
- package/dist/render-VX72AESY.js +10 -0
- package/dist/render-VX72AESY.js.map +1 -0
- package/dist/render-from-row-DOYJDO2L.js +17 -0
- package/dist/render-from-row-DOYJDO2L.js.map +1 -0
- package/dist/{renovate-dispatch-QJY75ODR.js → renovate-dispatch-6GQWTRKX.js} +10 -10
- package/dist/{renovate-dispatch-QJY75ODR.js.map → renovate-dispatch-6GQWTRKX.js.map} +1 -1
- package/dist/{replay-C2LXMJZP.js → replay-4S6ENYCH.js} +3 -3
- package/dist/{report-4EVNDHOZ.js → report-TALY5P3L.js} +63 -21
- package/dist/report-TALY5P3L.js.map +1 -0
- package/dist/report-mirror-AAK3MXHY.js +55 -0
- package/dist/report-mirror-AAK3MXHY.js.map +1 -0
- package/dist/rerender-3FM6DNRH.js +32 -0
- package/dist/rerender-3FM6DNRH.js.map +1 -0
- package/dist/schema-75PJECAE.js +18 -0
- package/dist/schema-75PJECAE.js.map +1 -0
- package/dist/{self-updating-6DWI2Z56.js → self-updating-NTCCWJYZ.js} +4 -4
- package/dist/{selftest-RC36MTKP.js → selftest-NZTR4SM2.js} +26 -24
- package/dist/{selftest-RC36MTKP.js.map → selftest-NZTR4SM2.js.map} +1 -1
- package/dist/site-mirror-Q763PLGG.js +62 -0
- package/dist/site-mirror-Q763PLGG.js.map +1 -0
- package/dist/{smoke-suite-VYY2LXM2.js → smoke-suite-4JFZZYVW.js} +4 -4
- package/dist/{spam-classifier-XLBFCO7G.js → spam-classifier-T5H4VTP6.js} +4 -2
- package/dist/spam-classifier-T5H4VTP6.js.map +1 -0
- package/dist/{submissions-Q7DRFOCD.js → submissions-TEHPBSZJ.js} +5 -5
- package/dist/{svelte-codemods-25J2FO22.js → svelte-codemods-QAPDZC6F.js} +4 -4
- package/dist/{sync-34HNZZ56.js → sync-GBFV45WX.js} +6 -4
- package/dist/{sync-34HNZZ56.js.map → sync-GBFV45WX.js.map} +1 -1
- package/dist/{sync-configs-3SE6PSCO.js → sync-configs-34JIA6KZ.js} +6 -6
- package/dist/{upgrade-WBRQ62FX.js → upgrade-IR2OO3KP.js} +4 -4
- package/dist/{webflow-IRKOIT7S.js → webflow-624FEBFD.js} +4 -4
- package/dist/{webhook-VOGOW3W6.js → webhook-XM6EV4XT.js} +2 -2
- package/dist/{websites-SXWTP72S.js → websites-D6WYFAES.js} +2 -2
- package/dist/websites-D6WYFAES.js.map +1 -0
- package/dist/write-audits-to-airtable-OBHGR7DQ.js +17 -0
- package/dist/write-audits-to-airtable-OBHGR7DQ.js.map +1 -0
- package/package.json +5 -1
- package/dist/airtable-G7WBQQMI.js +0 -9
- package/dist/announce-MXTUQ6C7.js.map +0 -1
- package/dist/chunk-2EVEFOZY.js.map +0 -1
- package/dist/chunk-2NDRHXMR.js.map +0 -1
- package/dist/chunk-2ZPT7GLV.js.map +0 -1
- package/dist/chunk-ACBRLLFT.js.map +0 -1
- package/dist/chunk-BYK66EWO.js.map +0 -1
- package/dist/chunk-C6B4RHXR.js.map +0 -1
- package/dist/chunk-DJZWYIPP.js.map +0 -1
- package/dist/chunk-F5KM4LEQ.js.map +0 -1
- package/dist/chunk-ILUNZHYV.js.map +0 -1
- package/dist/chunk-ITIOFN7A.js.map +0 -1
- package/dist/chunk-PPE5KZJK.js.map +0 -1
- package/dist/chunk-SNSTJLQW.js.map +0 -1
- package/dist/chunk-W7Z3BGCI.js.map +0 -1
- package/dist/chunk-X3B723J4.js.map +0 -1
- package/dist/client-AUE3XUPO.js +0 -11
- package/dist/db-B35OGV3G.js.map +0 -1
- package/dist/digest-BL6UJYKH.js.map +0 -1
- package/dist/dump-P6EBSIOH.js.map +0 -1
- package/dist/ensure-site-DFTB7MN3.js.map +0 -1
- package/dist/forms-notify-target-75U6OU7L.js.map +0 -1
- package/dist/header-images-335L2AKB.js.map +0 -1
- package/dist/health-mirror-4B2L7T2Y.js +0 -75
- package/dist/health-mirror-4B2L7T2Y.js.map +0 -1
- package/dist/launch-XNAX427U.js.map +0 -1
- package/dist/migrate-GQH237A6.js +0 -7
- package/dist/parity-MWS24A3H.js +0 -12
- package/dist/prismic-models-QBGUT2Q3.js.map +0 -1
- package/dist/prospect-audit-IUNCJ2LV.js.map +0 -1
- package/dist/render-AQAVQDPZ.js +0 -10
- package/dist/report-4EVNDHOZ.js.map +0 -1
- package/dist/write-audits-to-airtable-MBEILLPU.js +0 -14
- /package/dist/{airtable-G7WBQQMI.js.map → airtable-QG5ICI3Y.js.map} +0 -0
- /package/dist/{client-AUE3XUPO.js.map → attachments-NLZIJ5NU.js.map} +0 -0
- /package/dist/{blux-ZGDSHI3U.js.map → blux-DN4MI532.js.map} +0 -0
- /package/dist/{bump-deps-EC74CPLS.js.map → bump-deps-KGH5UYSF.js.map} +0 -0
- /package/dist/{chunk-N45M3FDK.js.map → chunk-6I6L3CMX.js.map} +0 -0
- /package/dist/{chunk-KTH5ZODA.js.map → chunk-7BZUOZPU.js.map} +0 -0
- /package/dist/{chunk-3VQWSE3F.js.map → chunk-7UAYMAKR.js.map} +0 -0
- /package/dist/{chunk-Z7AXYKQB.js.map → chunk-IY6256GK.js.map} +0 -0
- /package/dist/{chunk-BNM5POSJ.js.map → chunk-JRHIFA5R.js.map} +0 -0
- /package/dist/{chunk-ZKXSX4LO.js.map → chunk-K6SLF6GI.js.map} +0 -0
- /package/dist/{chunk-SLUQ7R6I.js.map → chunk-PR343K7F.js.map} +0 -0
- /package/dist/{chunk-P2FE5AI6.js.map → chunk-Q47DU255.js.map} +0 -0
- /package/dist/{chunk-VSBFM7DS.js.map → chunk-SJOXWJ5Y.js.map} +0 -0
- /package/dist/{chunk-TERE5SDF.js.map → chunk-ULHPALI5.js.map} +0 -0
- /package/dist/{chunk-XUGSZP7Z.js.map → chunk-W45FZEGE.js.map} +0 -0
- /package/dist/{chunk-JHGHLKFS.js.map → chunk-WS6NU475.js.map} +0 -0
- /package/dist/{chunk-6TWWY7ZU.js.map → chunk-Z3JXLULD.js.map} +0 -0
- /package/dist/{import-airtable-HE43FB4H.js.map → client-JYKPVCJX.js.map} +0 -0
- /package/dist/{convert-to-pnpm-6L6P74WR.js.map → convert-to-pnpm-NWB5FCQ2.js.map} +0 -0
- /package/dist/{lighthouse-airtable-LBVIYYP5.js.map → digest-state-F37XUCS5.js.map} +0 -0
- /package/dist/{migrate-GQH237A6.js.map → fleet-state-R5LU7IC3.js.map} +0 -0
- /package/dist/{header-image-AWLLQA4L.js.map → header-image-7A7XLVEU.js.map} +0 -0
- /package/dist/{health-endpoint-WJC2UMYS.js.map → health-endpoint-UVX6R5N5.js.map} +0 -0
- /package/dist/{notify-C645PGD5.js.map → import-airtable-OHVY344G.js.map} +0 -0
- /package/dist/{init-NJEOEO7I.js.map → init-FGTYNGUI.js.map} +0 -0
- /package/dist/{orchestrate-77UO4BYJ.js.map → lighthouse-airtable-3GUWHETW.js.map} +0 -0
- /package/dist/{parity-MWS24A3H.js.map → migrate-YITCXBLS.js.map} +0 -0
- /package/dist/{pipeline-S6CVHDGB.js.map → notify-4HP4GZ2H.js.map} +0 -0
- /package/dist/{onboard-GK4PHPNI.js.map → onboard-BKCYBAVW.js.map} +0 -0
- /package/dist/{render-AQAVQDPZ.js.map → orchestrate-JNKCWU5K.js.map} +0 -0
- /package/dist/{spam-classifier-XLBFCO7G.js.map → parity-NBYZUBFU.js.map} +0 -0
- /package/dist/{websites-SXWTP72S.js.map → pipeline-WYTXSLHX.js.map} +0 -0
- /package/dist/{prismic-ci-3RHOZUUT.js.map → prismic-ci-MY2U6NN7.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-MBEILLPU.js.map → prospect/types.js.map} +0 -0
- /package/dist/{replay-C2LXMJZP.js.map → replay-4S6ENYCH.js.map} +0 -0
- /package/dist/{self-updating-6DWI2Z56.js.map → self-updating-NTCCWJYZ.js.map} +0 -0
- /package/dist/{smoke-suite-VYY2LXM2.js.map → smoke-suite-4JFZZYVW.js.map} +0 -0
- /package/dist/{submissions-Q7DRFOCD.js.map → submissions-TEHPBSZJ.js.map} +0 -0
- /package/dist/{svelte-codemods-25J2FO22.js.map → svelte-codemods-QAPDZC6F.js.map} +0 -0
- /package/dist/{sync-configs-3SE6PSCO.js.map → sync-configs-34JIA6KZ.js.map} +0 -0
- /package/dist/{upgrade-WBRQ62FX.js.map → upgrade-IR2OO3KP.js.map} +0 -0
- /package/dist/{webflow-IRKOIT7S.js.map → webflow-624FEBFD.js.map} +0 -0
- /package/dist/{webhook-VOGOW3W6.js.map → webhook-XM6EV4XT.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,29 +1,22 @@
|
|
|
1
|
+
import "./chunk-ANJNTAMM.js";
|
|
1
2
|
import "./chunk-2SLED3NB.js";
|
|
2
|
-
import "./chunk-F5KM4LEQ.js";
|
|
3
3
|
import {
|
|
4
4
|
draftReportForSite
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-J3WEZGIN.js";
|
|
6
6
|
import {
|
|
7
7
|
approveBlockers
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6I6L3CMX.js";
|
|
9
9
|
import {
|
|
10
10
|
findDueReports
|
|
11
11
|
} from "./chunk-PZR4EBPY.js";
|
|
12
|
-
import {
|
|
13
|
-
upgradeSvelte4to5
|
|
14
|
-
} from "./chunk-Z3KYFUN6.js";
|
|
15
12
|
import {
|
|
16
13
|
DEFAULT_INIT_STEPS,
|
|
17
14
|
a11yFixturesPage,
|
|
18
15
|
init
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
convertToPnpm
|
|
22
|
-
} from "./chunk-XIDUYLSR.js";
|
|
16
|
+
} from "./chunk-K6SLF6GI.js";
|
|
23
17
|
import {
|
|
24
18
|
svelteCodemods
|
|
25
19
|
} from "./chunk-IYSEC543.js";
|
|
26
|
-
import "./chunk-J7SZQUCW.js";
|
|
27
20
|
import "./chunk-BQRFQSGY.js";
|
|
28
21
|
import "./chunk-Y53WOQIJ.js";
|
|
29
22
|
import {
|
|
@@ -31,19 +24,39 @@ import {
|
|
|
31
24
|
selfCaretRange,
|
|
32
25
|
selfPackageVersion
|
|
33
26
|
} from "./chunk-7RJ2HMMJ.js";
|
|
34
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-YFAXOD7Z.js";
|
|
35
28
|
import {
|
|
36
29
|
bumpDeps
|
|
37
30
|
} from "./chunk-2NJQLSEU.js";
|
|
38
31
|
import "./chunk-R53VL3RI.js";
|
|
39
32
|
import {
|
|
40
|
-
|
|
41
|
-
} from "./chunk-
|
|
33
|
+
upgradeSvelte4to5
|
|
34
|
+
} from "./chunk-Z3KYFUN6.js";
|
|
35
|
+
import "./chunk-J7SZQUCW.js";
|
|
36
|
+
import {
|
|
37
|
+
convertToPnpm
|
|
38
|
+
} from "./chunk-XIDUYLSR.js";
|
|
42
39
|
import {
|
|
43
40
|
parseAddresses,
|
|
44
41
|
sendApprovedReports,
|
|
45
42
|
withGlobalCc
|
|
46
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-DGZWFI2G.js";
|
|
44
|
+
import "./chunk-BRYXFH77.js";
|
|
45
|
+
import "./chunk-NYUYNYQL.js";
|
|
46
|
+
import {
|
|
47
|
+
isPendingApproval
|
|
48
|
+
} from "./chunk-F3JWOPTG.js";
|
|
49
|
+
import {
|
|
50
|
+
checklistFor,
|
|
51
|
+
gatingFields,
|
|
52
|
+
isHealthGateClear
|
|
53
|
+
} from "./chunk-VAD43MOR.js";
|
|
54
|
+
import {
|
|
55
|
+
fromAirtableBase
|
|
56
|
+
} from "./chunk-PR343K7F.js";
|
|
57
|
+
import "./chunk-IY6256GK.js";
|
|
58
|
+
import "./chunk-HN6I2XWI.js";
|
|
59
|
+
import "./chunk-XP5WM2LV.js";
|
|
47
60
|
import "./chunk-GECESMVS.js";
|
|
48
61
|
import {
|
|
49
62
|
domainFromUrl,
|
|
@@ -55,29 +68,25 @@ import {
|
|
|
55
68
|
BLURRED_CID,
|
|
56
69
|
CHECK_CID,
|
|
57
70
|
loadBundledImages,
|
|
58
|
-
renderReportHtml
|
|
59
|
-
|
|
60
|
-
|
|
71
|
+
renderReportHtml,
|
|
72
|
+
rendersCommentary
|
|
73
|
+
} from "./chunk-KJGKZLCT.js";
|
|
61
74
|
import {
|
|
62
75
|
escapeHtml,
|
|
63
76
|
safeUrl
|
|
64
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-BGTYPVLT.js";
|
|
65
78
|
import {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
isHealthGateClear
|
|
72
|
-
} from "./chunk-VAD43MOR.js";
|
|
73
|
-
import "./chunk-HN6I2XWI.js";
|
|
79
|
+
CANONICAL_STATUSES,
|
|
80
|
+
SEVERITY_RANK,
|
|
81
|
+
siteSlug,
|
|
82
|
+
toAirtableStatus
|
|
83
|
+
} from "./chunk-7NYN2P6I.js";
|
|
74
84
|
import "./chunk-WEKL2HYJ.js";
|
|
75
|
-
import "./chunk-NYUYNYQL.js";
|
|
76
85
|
import {
|
|
77
86
|
syncConfigs
|
|
78
|
-
} from "./chunk-
|
|
79
|
-
import "./chunk-3G25KIWW.js";
|
|
87
|
+
} from "./chunk-7UAYMAKR.js";
|
|
80
88
|
import "./chunk-73UFRZKY.js";
|
|
89
|
+
import "./chunk-3G25KIWW.js";
|
|
81
90
|
import "./chunk-OTGB6YQO.js";
|
|
82
91
|
import {
|
|
83
92
|
ALL_AUDIT_NAMES,
|
|
@@ -87,18 +96,18 @@ import {
|
|
|
87
96
|
runAudits,
|
|
88
97
|
runAuditsAcross,
|
|
89
98
|
securityAudit
|
|
90
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-B23FFWU4.js";
|
|
91
100
|
import "./chunk-LKGVSM2O.js";
|
|
92
101
|
import "./chunk-GASBX52O.js";
|
|
93
102
|
import "./chunk-XHHMM5HX.js";
|
|
94
103
|
import {
|
|
95
104
|
fromJsonFile,
|
|
96
105
|
localPath
|
|
97
|
-
} from "./chunk-
|
|
98
|
-
import "./chunk-
|
|
99
|
-
import "./chunk-
|
|
100
|
-
import "./chunk-
|
|
101
|
-
import "./chunk-
|
|
106
|
+
} from "./chunk-Z3JXLULD.js";
|
|
107
|
+
import "./chunk-W45FZEGE.js";
|
|
108
|
+
import "./chunk-RARREDQE.js";
|
|
109
|
+
import "./chunk-WS6NU475.js";
|
|
110
|
+
import "./chunk-MFHS7IQ2.js";
|
|
102
111
|
import "./chunk-A3WDWNN5.js";
|
|
103
112
|
import {
|
|
104
113
|
isLeadFormType
|
|
@@ -111,15 +120,9 @@ import "./chunk-UDRHAQT7.js";
|
|
|
111
120
|
import "./chunk-PTDMVGKL.js";
|
|
112
121
|
import "./chunk-LBYOLBW7.js";
|
|
113
122
|
import "./chunk-XXTZBPUY.js";
|
|
114
|
-
import {
|
|
115
|
-
CANONICAL_STATUSES,
|
|
116
|
-
SEVERITY_RANK,
|
|
117
|
-
siteSlug,
|
|
118
|
-
toAirtableStatus
|
|
119
|
-
} from "./chunk-LDWZSLSU.js";
|
|
120
123
|
import "./chunk-6VAL7XJT.js";
|
|
121
124
|
import "./chunk-NMAWXBJA.js";
|
|
122
|
-
import "./chunk-
|
|
125
|
+
import "./chunk-O3GT46R2.js";
|
|
123
126
|
|
|
124
127
|
// src/recipes/index.ts
|
|
125
128
|
var ALL_RECIPE_NAMES = [
|
|
@@ -314,6 +317,15 @@ var SUBMISSION_STATUS_SCRIPT = `document.querySelectorAll("button.subm-status").
|
|
|
314
317
|
// src/dashboard/site-details.ts
|
|
315
318
|
var SITE_STATUS_OPTIONS = CANONICAL_STATUSES.map(toAirtableStatus);
|
|
316
319
|
var FREQ_OPTIONS = ["None", "Monthly", "Quarterly", "Yearly"];
|
|
320
|
+
var WATCH_CONDITION_OPTIONS = [
|
|
321
|
+
"Performance",
|
|
322
|
+
"Accessibility",
|
|
323
|
+
"Best Practices",
|
|
324
|
+
"SEO",
|
|
325
|
+
"stale repo",
|
|
326
|
+
"no custom domain"
|
|
327
|
+
];
|
|
328
|
+
var CLEAR_SECRET = "__clear__";
|
|
317
329
|
|
|
318
330
|
// src/dashboard/render.ts
|
|
319
331
|
var DASH = "\u2014";
|
|
@@ -465,14 +477,27 @@ function recipientsLine(site) {
|
|
|
465
477
|
const ccPart = cc.length > 0 ? ` \xB7 CC ${cc.map(escapeHtml).join(", ")}` : "";
|
|
466
478
|
return `<span class="recipients">To ${to.map(escapeHtml).join(", ")}${ccPart}</span>`;
|
|
467
479
|
}
|
|
480
|
+
function rerenderButton(r) {
|
|
481
|
+
if (r.sentAt !== null) return "";
|
|
482
|
+
const url = `/api/reports/${encodeURIComponent(r.id)}/rerender`;
|
|
483
|
+
return `<button class="rerender" data-rerender-url="${escapeHtml(url)}" title="Re-render this report from its current row (runs in Actions; takes a minute or two)">refresh preview</button>`;
|
|
484
|
+
}
|
|
485
|
+
function reportPreviewUrl(reportId) {
|
|
486
|
+
return `/api/reports/${encodeURIComponent(reportId)}/preview`;
|
|
487
|
+
}
|
|
488
|
+
function commentaryEditor(r) {
|
|
489
|
+
if (!rendersCommentary(r.reportType)) return "";
|
|
490
|
+
const url = `/api/reports/${encodeURIComponent(r.id)}/commentary`;
|
|
491
|
+
return `<div class="commentary"><label for="commentary-${escapeHtml(r.id)}">Commentary <span class="muted">(re-rendered into the email at send)</span></label><textarea id="commentary-${escapeHtml(r.id)}" data-commentary-for="${escapeHtml(r.id)}" data-commentary-url="${escapeHtml(url)}" rows="3">${escapeHtml(r.commentary ?? "")}</textarea><span class="commentary-saved" data-for="${escapeHtml(r.id)}"></span></div>`;
|
|
492
|
+
}
|
|
468
493
|
function pendingRow(r, site, now) {
|
|
469
494
|
const type = escapeHtml(r.reportType);
|
|
470
495
|
const period = r.period ? escapeHtml(r.period) : "\u2014";
|
|
471
496
|
const findings = approveBlockers(site, r);
|
|
472
497
|
const blocked = findings.some((f) => f.level === "fail");
|
|
473
|
-
const preview = r.renderedHtmlAttachment ? `<a href="${escapeHtml(
|
|
498
|
+
const preview = r.renderedHtmlAttachment ? `<a href="${escapeHtml(reportPreviewUrl(r.id))}" rel="noopener noreferrer" title="rendered at draft time \u2014 Commentary/subject edits after drafting are not reflected">draft preview \u25B8</a>` : `<span class="muted">no preview yet</span>`;
|
|
474
499
|
const sendLine = sendTimingLine(now);
|
|
475
|
-
return `<li><div class="pending-head"><strong>${type}</strong> <span class="muted">${period}</span> ${preflightChip(findings)} ${preview} ${approveButton(r, blocked)}</div><div class="pending-info">${recipientsLine(site)} ${sendLine}</div>${checklistBlock(r)}${overrideControl(r)}</li>`;
|
|
500
|
+
return `<li><div class="pending-head"><strong>${type}</strong> <span class="muted">${period}</span> ${preflightChip(findings)} ${preview} ${rerenderButton(r)} ${approveButton(r, blocked)}</div><div class="pending-info">${recipientsLine(site)} ${sendLine}</div>${checklistBlock(r)}${commentaryEditor(r)}${overrideControl(r)}</li>`;
|
|
476
501
|
}
|
|
477
502
|
function pendingSection(reports, site, now) {
|
|
478
503
|
const pending = reports.filter(isPendingApproval);
|
|
@@ -502,12 +527,13 @@ function reportRow(r, site) {
|
|
|
502
527
|
const id = escapeHtml(r.reportId);
|
|
503
528
|
const ga = gaUsersCell(r);
|
|
504
529
|
const search = searchCell(r);
|
|
505
|
-
const link = r.renderedHtmlAttachment ? `<a href="${escapeHtml(
|
|
530
|
+
const link = r.renderedHtmlAttachment ? `<a href="${escapeHtml(reportPreviewUrl(r.id))}">view</a>` : `<span class="muted">no attachment</span>`;
|
|
506
531
|
const action = isPendingApproval(r) ? approveButton(
|
|
507
532
|
r,
|
|
508
533
|
approveBlockers(site, r).some((f) => f.level === "fail")
|
|
509
534
|
) : "";
|
|
510
|
-
|
|
535
|
+
const commentary = r.sentAt === null && !isPendingApproval(r) ? `<tr class="commentary-row"><td colspan="7">${commentaryEditor(r)}</td></tr>` : "";
|
|
536
|
+
return `<tr><td>${date}</td><td>${type}</td><td><code>${id}</code></td><td>${ga}</td><td>${search}</td><td>${link}</td><td>${action}</td></tr>${commentary}`;
|
|
511
537
|
}
|
|
512
538
|
var SUBMISSIONS_PER_SITE_CAP = 25;
|
|
513
539
|
function submissionsSection(submissions, site) {
|
|
@@ -586,8 +612,45 @@ function selectRow(label, field, options, current, url) {
|
|
|
586
612
|
function inputRow(label, field, value, url) {
|
|
587
613
|
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>`;
|
|
588
614
|
}
|
|
615
|
+
var DETAIL_VALUE_FN = `function detailValue(el) {
|
|
616
|
+
if (el.type === "checkbox") return el.checked ? "true" : "false";
|
|
617
|
+
if (el.multiple) return Array.from(el.selectedOptions).map((o) => o.value).join(",");
|
|
618
|
+
return el.value;
|
|
619
|
+
}`;
|
|
620
|
+
var SAVE_DETAIL_FN = `function saveDetail(el, root) {
|
|
621
|
+
const span = root.querySelector('.detail-saved[data-for="' + el.dataset.detailField + '"]');
|
|
622
|
+
return fetch(el.dataset.detailsUrl, {
|
|
623
|
+
method: "POST",
|
|
624
|
+
headers: { "content-type": "application/json" },
|
|
625
|
+
body: JSON.stringify({ field: el.dataset.detailField, value: detailValue(el) }),
|
|
626
|
+
})
|
|
627
|
+
.then((r) => {
|
|
628
|
+
if (span) span.textContent = r.ok ? " \\u2713" : " \\u2717";
|
|
629
|
+
if (r.ok && "defaultValue" in el) el.defaultValue = el.value;
|
|
630
|
+
})
|
|
631
|
+
.catch(() => {
|
|
632
|
+
if (span) span.textContent = " \\u2717";
|
|
633
|
+
});
|
|
634
|
+
}`;
|
|
635
|
+
function toDateInputValue(value) {
|
|
636
|
+
return (value ?? "").slice(0, 10);
|
|
637
|
+
}
|
|
589
638
|
function dateRow(label, field, value, url) {
|
|
590
|
-
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="date" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" value="${escapeHtml(value
|
|
639
|
+
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="date" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" value="${escapeHtml(toDateInputValue(value))}" />${savedSpan(field)}</dd></div>`;
|
|
640
|
+
}
|
|
641
|
+
function checkboxRow(label, field, checked, url) {
|
|
642
|
+
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="checkbox" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}"${checked ? " checked" : ""} />${savedSpan(field)}</dd></div>`;
|
|
643
|
+
}
|
|
644
|
+
function multiSelectRow(label, field, options, selected, url) {
|
|
645
|
+
const sel = new Set(selected);
|
|
646
|
+
const opts = options.map(
|
|
647
|
+
(o) => `<option value="${escapeHtml(o)}"${sel.has(o) ? " selected" : ""}>${escapeHtml(o)}</option>`
|
|
648
|
+
).join("");
|
|
649
|
+
return `<div class="detail wide"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><select multiple id="detail-${field}" data-detail-field="${field}" data-details-url="${url}">${opts}</select>${savedSpan(field)}</dd></div>`;
|
|
650
|
+
}
|
|
651
|
+
function secretRow(label, field, isSet, url) {
|
|
652
|
+
const ph = isSet ? `\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022 (type to replace, or ${CLEAR_SECRET} to erase)` : "not set";
|
|
653
|
+
return `<div class="detail"><dt><label for="detail-${field}">${escapeHtml(label)}</label></dt><dd><input type="password" autocomplete="off" id="detail-${field}" data-detail-field="${field}" data-details-url="${url}" placeholder="${escapeHtml(ph)}" />${savedSpan(field)}</dd></div>`;
|
|
591
654
|
}
|
|
592
655
|
function textareaRow(label, field, value, url) {
|
|
593
656
|
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>`;
|
|
@@ -621,6 +684,15 @@ function siteDetailsSection(site) {
|
|
|
621
684
|
// Raw JSON, and shown as the raw cell rather than the parsed object: what the
|
|
622
685
|
// operator edits has to be the thing `parseNotifyRouting` will read back.
|
|
623
686
|
textareaRow("Notify routing (JSON)", "notifyRouting", site.notifyRoutingRaw, url),
|
|
687
|
+
checkboxRow("Require Turnstile", "requireTurnstile", site.requireTurnstile, url),
|
|
688
|
+
secretRow("Mailchimp API key", "mailchimpApiKey", site.mailchimpApiKey !== null, url),
|
|
689
|
+
multiSelectRow(
|
|
690
|
+
"Accepted watch conditions",
|
|
691
|
+
"acceptedWatchConditions",
|
|
692
|
+
WATCH_CONDITION_OPTIONS,
|
|
693
|
+
site.acceptedWatchConditions,
|
|
694
|
+
url
|
|
695
|
+
),
|
|
624
696
|
textareaRow("Copy \u2014 Intro", "copyIntro", site.copyIntro, url),
|
|
625
697
|
textareaRow("Copy \u2014 Contact", "copyContact", site.copyContact, url),
|
|
626
698
|
textareaRow("Copy \u2014 Footer", "copyFooter", site.copyFooter, url),
|
|
@@ -847,9 +919,18 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
847
919
|
${spamScreenSection(spamTotals, submissions, now)}
|
|
848
920
|
${submissionsSection(submissions, site)}
|
|
849
921
|
<script>
|
|
922
|
+
// The SAME pending report is rendered twice \u2014 once in the pending list, once
|
|
923
|
+
// in the reports history \u2014 so one report id owns two Approve buttons. Every
|
|
924
|
+
// state change has to reach both, or the two places you look disagree: one
|
|
925
|
+
// says "Approved", the other still says "Approve" and (with the gate clear)
|
|
926
|
+
// is still enabled.
|
|
927
|
+
function approveButtonsFor(id) {
|
|
928
|
+
return Array.from(document.querySelectorAll('button.approve[data-report-id="' + id + '"]'));
|
|
929
|
+
}
|
|
850
930
|
document.querySelectorAll("button.approve").forEach((b) => {
|
|
851
931
|
b.addEventListener("click", async () => {
|
|
852
|
-
|
|
932
|
+
const twins = approveButtonsFor(b.dataset.reportId);
|
|
933
|
+
twins.forEach((t) => { t.disabled = true; });
|
|
853
934
|
// is-loading swaps the label for a spinner; aria-busy is the same news for a
|
|
854
935
|
// screen reader, which cannot see it. Both are cleared in the finally below so
|
|
855
936
|
// no exit path can strand the button spinning forever.
|
|
@@ -858,30 +939,41 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
858
939
|
try {
|
|
859
940
|
const res = await fetch(b.dataset.approveUrl, { method: "POST" });
|
|
860
941
|
if (res.ok) {
|
|
861
|
-
|
|
862
|
-
//
|
|
863
|
-
//
|
|
864
|
-
|
|
942
|
+
// Terminal success: darker green, and they stay disabled (approving twice
|
|
943
|
+
// is a no-op server-side, but the button should not invite the second
|
|
944
|
+
// click). Applied to every twin, not just the one that was clicked.
|
|
945
|
+
twins.forEach((t) => {
|
|
946
|
+
t.textContent = "Approved";
|
|
947
|
+
t.classList.add("is-approved");
|
|
948
|
+
});
|
|
865
949
|
} else {
|
|
866
950
|
// A 409 carries { reason, blockers } \u2014 surface WHY instead of a bare
|
|
867
951
|
// "Failed" next to a possibly-stale green chip. textContent/title
|
|
868
952
|
// assignment only (no innerHTML), so server strings stay inert.
|
|
869
953
|
const data = await res.json().catch(() => null);
|
|
870
|
-
|
|
954
|
+
const label = data && data.reason === "send-blocked" ? "Blocked" : "Failed";
|
|
871
955
|
// Double-backslash, NOT single: this whole block lives inside the renderer's
|
|
872
956
|
// template literal, so a single-backslash escape is consumed HERE at build
|
|
873
957
|
// time and emits a real newline into the served HTML \u2014 an unterminated string
|
|
874
958
|
// literal that kills the parse of the entire script element, taking every
|
|
875
959
|
// handler on the page with it (exactly how approve/override/renovate went
|
|
876
960
|
// dead). Note this comment must also avoid backticks for the same reason.
|
|
877
|
-
|
|
878
|
-
|
|
961
|
+
const title = data && Array.isArray(data.blockers) ? data.blockers.join("\\n") : null;
|
|
962
|
+
// Re-enable EVERY twin, not just the clicked one \u2014 leaving the other
|
|
963
|
+
// disabled would strand it reading "Approve" and unusable.
|
|
964
|
+
twins.forEach((t) => {
|
|
965
|
+
t.textContent = label;
|
|
966
|
+
if (title !== null) t.title = title;
|
|
967
|
+
t.disabled = false;
|
|
968
|
+
});
|
|
879
969
|
}
|
|
880
970
|
} catch {
|
|
881
971
|
// Network rejection (offline, DNS, abort): mirror the !res.ok path so
|
|
882
|
-
// the
|
|
883
|
-
|
|
884
|
-
|
|
972
|
+
// the buttons don't sit permanently disabled reading "Approve".
|
|
973
|
+
twins.forEach((t) => {
|
|
974
|
+
t.textContent = "Failed";
|
|
975
|
+
t.disabled = false;
|
|
976
|
+
});
|
|
885
977
|
} finally {
|
|
886
978
|
b.classList.remove("is-loading");
|
|
887
979
|
b.removeAttribute("aria-busy");
|
|
@@ -894,7 +986,12 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
894
986
|
// refused client-side AND server-side).
|
|
895
987
|
document.querySelectorAll("button.override-toggle").forEach((b) => {
|
|
896
988
|
b.addEventListener("click", () => {
|
|
897
|
-
|
|
989
|
+
// Scoped lookup, not nextElementSibling: adjacency is a markup accident,
|
|
990
|
+
// and anything inserted between the toggle and its form would kill "Send
|
|
991
|
+
// anyway\u2026" silently. The submit handler six lines down already uses
|
|
992
|
+
// closest(); this is the same contract from the other end.
|
|
993
|
+
const wrap = b.closest(".override");
|
|
994
|
+
const form = wrap ? wrap.querySelector(".override-form") : null;
|
|
898
995
|
if (form) form.hidden = !form.hidden;
|
|
899
996
|
});
|
|
900
997
|
});
|
|
@@ -919,13 +1016,14 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
919
1016
|
if (res.ok) {
|
|
920
1017
|
if (status) status.textContent = "Overridden \u2713";
|
|
921
1018
|
if (input) input.disabled = true;
|
|
922
|
-
// Reflect the send-anyway state on the row's own Approve
|
|
923
|
-
//
|
|
924
|
-
// "waiting on you" once an override has gone through.
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
)
|
|
928
|
-
|
|
1019
|
+
// Reflect the send-anyway state on the row's own Approve buttons too \u2014
|
|
1020
|
+
// they stay server-gated disabled, but the label should stop implying
|
|
1021
|
+
// "waiting on you" once an override has gone through. ALL of them: the
|
|
1022
|
+
// same report is rendered in both the pending list and the history, so
|
|
1023
|
+
// a singular querySelector updated the first and left the second lying.
|
|
1024
|
+
approveButtonsFor(b.dataset.reportId).forEach((t) => {
|
|
1025
|
+
t.textContent = "Overridden";
|
|
1026
|
+
});
|
|
929
1027
|
} else {
|
|
930
1028
|
// A 409 carries { reason, blockers } \u2014 surface WHY (textContent only,
|
|
931
1029
|
// never innerHTML, so server strings stay inert).
|
|
@@ -963,26 +1061,66 @@ function renderSiteDashboardHtml(site, reports, submissions = [], spamTotals = n
|
|
|
963
1061
|
});
|
|
964
1062
|
// Site-details editor: save on change (selects) / blur (inputs+textareas, only
|
|
965
1063
|
// when the value actually changed). The per-field span shows \u2713 / \u2717.
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
fetch(el.dataset.detailsUrl, {
|
|
969
|
-
method: "POST",
|
|
970
|
-
headers: { "content-type": "application/json" },
|
|
971
|
-
body: JSON.stringify({ field: el.dataset.detailField, value: el.value }),
|
|
972
|
-
})
|
|
973
|
-
.then((r) => {
|
|
974
|
-
if (span) span.textContent = r.ok ? " \u2713" : " \u2717";
|
|
975
|
-
})
|
|
976
|
-
.catch(() => {
|
|
977
|
-
if (span) span.textContent = " \u2717";
|
|
978
|
-
});
|
|
979
|
-
}
|
|
1064
|
+
${DETAIL_VALUE_FN}
|
|
1065
|
+
${SAVE_DETAIL_FN}
|
|
980
1066
|
document.querySelectorAll("select[data-detail-field]").forEach((s) => {
|
|
981
|
-
s.addEventListener("change", () => saveDetail(s));
|
|
1067
|
+
s.addEventListener("change", () => saveDetail(s, document));
|
|
1068
|
+
});
|
|
1069
|
+
// Checkboxes save on CHANGE. They cannot use the blur path below: that path
|
|
1070
|
+
// only fires when \`value !== defaultValue\`, and for a checkbox both are the
|
|
1071
|
+
// "on" content attribute, so it would never save at all.
|
|
1072
|
+
document.querySelectorAll("input[type=checkbox][data-detail-field]").forEach((c) => {
|
|
1073
|
+
c.addEventListener("change", () => saveDetail(c, document));
|
|
982
1074
|
});
|
|
983
|
-
document.querySelectorAll("input[data-detail-field], textarea[data-detail-field]").forEach((i) => {
|
|
1075
|
+
document.querySelectorAll("input:not([type=checkbox])[data-detail-field], textarea[data-detail-field]").forEach((i) => {
|
|
1076
|
+
// A save needs BOTH a real edit gesture and a changed value. \`value !==
|
|
1077
|
+
// defaultValue\` alone is not evidence of an edit: the browser rewrites
|
|
1078
|
+
// \`.value\` on its own when a control is handed a value it cannot represent
|
|
1079
|
+
// (an ISO datetime in a date input sanitizes to ""), and the blur that
|
|
1080
|
+
// follows an untouched tab-through then posts that empty string as if the
|
|
1081
|
+
// operator had cleared the field. Requiring an \`input\` event first means
|
|
1082
|
+
// only a human keystroke or picker choice can arm the save.
|
|
1083
|
+
i.addEventListener("input", () => { i.dataset.edited = "1"; });
|
|
984
1084
|
i.addEventListener("blur", () => {
|
|
985
|
-
if (i.value !== i.defaultValue) saveDetail(i);
|
|
1085
|
+
if (i.dataset.edited === "1" && i.value !== i.defaultValue) saveDetail(i, document);
|
|
1086
|
+
});
|
|
1087
|
+
});
|
|
1088
|
+
// Refresh preview: dispatch the re-render workflow, then tell the operator to
|
|
1089
|
+
// reload once it lands. No polling \u2014 the run takes a minute or two and a
|
|
1090
|
+
// spinner that long reads as a hang.
|
|
1091
|
+
document.querySelectorAll("button.rerender").forEach((b) => {
|
|
1092
|
+
b.addEventListener("click", async () => {
|
|
1093
|
+
b.disabled = true;
|
|
1094
|
+
b.textContent = "Refreshing\u2026";
|
|
1095
|
+
try {
|
|
1096
|
+
const res = await fetch(b.dataset.rerenderUrl, { method: "POST" });
|
|
1097
|
+
b.textContent = res.ok ? "Queued \u2713 reload in ~2 min" : "Failed";
|
|
1098
|
+
if (!res.ok) b.disabled = false;
|
|
1099
|
+
} catch {
|
|
1100
|
+
b.textContent = "Failed";
|
|
1101
|
+
b.disabled = false;
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
});
|
|
1105
|
+
// Report commentary: save on blur, only when it actually changed. Same
|
|
1106
|
+
// shape as the site-details editor, but keyed on the REPORT id rather than a
|
|
1107
|
+
// field name, so it posts { text } to the report's own endpoint.
|
|
1108
|
+
document.querySelectorAll("textarea[data-commentary-for]").forEach((t) => {
|
|
1109
|
+
t.addEventListener("blur", () => {
|
|
1110
|
+
if (t.value === t.defaultValue) return;
|
|
1111
|
+
const span = document.querySelector('.commentary-saved[data-for="' + t.dataset.commentaryFor + '"]');
|
|
1112
|
+
fetch(t.dataset.commentaryUrl, {
|
|
1113
|
+
method: "POST",
|
|
1114
|
+
headers: { "content-type": "application/json" },
|
|
1115
|
+
body: JSON.stringify({ text: t.value }),
|
|
1116
|
+
})
|
|
1117
|
+
.then((r) => {
|
|
1118
|
+
if (span) span.textContent = r.ok ? " \u2713" : " \u2717";
|
|
1119
|
+
if (r.ok) t.defaultValue = t.value;
|
|
1120
|
+
})
|
|
1121
|
+
.catch(() => {
|
|
1122
|
+
if (span) span.textContent = " \u2717";
|
|
1123
|
+
});
|
|
986
1124
|
});
|
|
987
1125
|
});
|
|
988
1126
|
${SUBMISSION_STATUS_SCRIPT}
|
|
@@ -1537,41 +1675,38 @@ var AUDIT_SCRIPT = `<script>
|
|
|
1537
1675
|
function rfStop(){ try { localStorage.removeItem(RF_KEY); } catch(e){} }
|
|
1538
1676
|
// Per-workflow ETA hint (the lighthouse fleet sweep runs ~48 min; security ~1-2 min).
|
|
1539
1677
|
function rfEta(label){ return label === 'lighthouse' ? '~48m' : label === 'security' ? '~2m' : ''; }
|
|
1540
|
-
//
|
|
1541
|
-
//
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1678
|
+
// Escape before interpolating. The values here are server-side enums and a
|
|
1679
|
+
// GitHub html_url today, but this builds HTML from a REMOTE API response, and
|
|
1680
|
+
// the house rule everywhere else on these pages is that no server string ever
|
|
1681
|
+
// reaches the browser as markup. Cheaper to escape than to keep re-deciding.
|
|
1682
|
+
function rfEsc(v){
|
|
1683
|
+
return String(v == null ? '' : v)
|
|
1684
|
+
.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
|
1685
|
+
.replace(/"/g,'"').replace(/'/g,''');
|
|
1686
|
+
}
|
|
1687
|
+
// A run link must be a GitHub run URL. Anything else is dropped rather than
|
|
1688
|
+
// rendered, so a compromised or unexpected API response cannot place an
|
|
1689
|
+
// arbitrary href (javascript:, data:, an attacker's host) in the panel.
|
|
1690
|
+
function rfRunUrl(u){
|
|
1691
|
+
return typeof u === 'string' && u.indexOf('https://github.com/') === 0 ? rfEsc(u) : '';
|
|
1551
1692
|
}
|
|
1552
|
-
// Safe to build raw HTML: workflow/state/step are server-fixed (enums + GitHub step
|
|
1553
|
-
// names) and url is GitHub's own html_url for our central repo \u2014 none are
|
|
1554
|
-
// user-supplied. Don't interpolate untrusted fields here without escaping.
|
|
1555
1693
|
function rfRender(status, startedAt){
|
|
1556
1694
|
var failed = function(s){ return s === 'failure' || s === 'cancelled' || s === 'timed_out'; };
|
|
1557
1695
|
var mins = Math.floor((Date.now() - startedAt) / 60000);
|
|
1558
1696
|
var elapsed = mins < 1 ? '<1m' : mins + 'm';
|
|
1559
1697
|
return status.perWorkflow.map(function(w){
|
|
1560
|
-
var label = w.workflow.replace('.yml','').replace('fleet-','');
|
|
1698
|
+
var label = String(w.workflow || '').replace('.yml','').replace('fleet-','');
|
|
1561
1699
|
var done = w.state === 'success';
|
|
1562
1700
|
var isFailed = failed(w.state);
|
|
1563
1701
|
var icon = done ? '\u2713' : isFailed ? '\u2717' : '<span class="rf-spin"></span>';
|
|
1564
|
-
var line = icon + ' ' + label + ' \u2014 ' + w.state.replace('_',' ');
|
|
1702
|
+
var line = icon + ' ' + rfEsc(label) + ' \u2014 ' + rfEsc(String(w.state || '').replace('_',' '));
|
|
1703
|
+
var url = rfRunUrl(w.url);
|
|
1565
1704
|
if (!done && !isFailed){
|
|
1566
|
-
var phase = rfPhase(w.step);
|
|
1567
1705
|
var eta = rfEta(label);
|
|
1568
|
-
var
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
line += '<div class="rf-sub">' + detail.join(' \xB7 ') + link + '</div>';
|
|
1573
|
-
} else if (isFailed && w.url){
|
|
1574
|
-
line += ' <a href="'+w.url+'" target="_blank" rel="noopener">run</a>';
|
|
1706
|
+
var link = url ? ' \xB7 <a href="'+url+'" target="_blank" rel="noopener">view run \u2197</a>' : '';
|
|
1707
|
+
line += '<div class="rf-sub">' + elapsed + (eta ? ' / ' + eta : '') + link + '</div>';
|
|
1708
|
+
} else if (isFailed && url){
|
|
1709
|
+
line += ' <a href="'+url+'" target="_blank" rel="noopener">run</a>';
|
|
1575
1710
|
}
|
|
1576
1711
|
return '<div class="rf-row">' + line + '</div>';
|
|
1577
1712
|
}).join('');
|
|
@@ -1700,6 +1835,8 @@ var SESSION_TTL_SECONDS = 30 * 24 * 60 * 60;
|
|
|
1700
1835
|
|
|
1701
1836
|
// src/dashboard/prospect-audit-trigger.ts
|
|
1702
1837
|
var PROSPECT_AUDIT_DUPLICATE_WINDOW_MS = 10 * 60 * 1e3;
|
|
1838
|
+
var PROSPECT_AUDIT_DAILY_CAP = 25;
|
|
1839
|
+
var DAILY_CAP_LOOKBACK = PROSPECT_AUDIT_DAILY_CAP * 2;
|
|
1703
1840
|
export {
|
|
1704
1841
|
ALL_AUDIT_NAMES,
|
|
1705
1842
|
ALL_RECIPE_NAMES,
|