clearotron 0.3.1-beta.2 → 0.3.1-beta.4
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/bin/grant.mjs +21 -22
- package/build-info.json +2 -2
- package/driver/CHANGELOG.md +33 -0
- package/driver/citation-census.json +3 -3
- package/driver/common-law-receipts.mjs +11 -1
- package/driver/connotation-search.mjs +56 -5
- package/driver/contract-e3-backlog.mjs +31 -31
- package/driver/contract-vocabulary.mjs +59 -58
- package/driver/engine/mcp/gather-config.mjs +1 -1
- package/driver/gateway.mjs +29 -2
- package/driver/matter-frame-record.mjs +54 -1
- package/driver/package.json +1 -1
- package/driver/portal-config-view.mjs +26 -1
- package/driver/portal-report.mjs +16 -2
- package/driver/portal-service.mjs +327 -8
- package/driver/publish/render.mjs +0 -45
- package/driver/publish/templates/report.css +1 -30
- package/driver/skills/knockout-assess/SKILL.md +35 -6
- package/driver/skills/knockout-frame/SKILL.md +2 -1
- package/driver/skills/prelim-search/risk-framework-triage.md +3 -3
- package/driver/stages.mjs +19 -5
- package/driver/suite-census.json +112 -16
- package/driver/verify-knockout.mjs +58 -0
- package/driver/verify.mjs +83 -7
- package/mcp-server/CHANGELOG.md +11 -0
- package/mcp-server/lib/audit.mjs +96 -3
- package/mcp-server/lib/http-handler.mjs +76 -3
- package/mcp-server/lib/runs.mjs +42 -2
- package/mcp-server/package.json +1 -1
- package/mcp-server/packs/client/CONNECT.md +10 -6
- package/mcp-server/server.mjs +37 -3
- package/package.json +1 -1
- package/portal-ui/dist/assets/{index-D8ITW-aD.js → index-ChIQsMYp.js} +1375 -817
- package/portal-ui/dist/assets/{index-D5WAoLZI.css → index-DBIs21e4.css} +37 -0
- package/portal-ui/dist/index.html +2 -2
- package/portal-ui/package.json +1 -1
- package/providers/oauth-mcp-bridge/CHANGELOG.md +8 -0
- package/providers/oauth-mcp-bridge/package.json +1 -1
- package/scripts/ask-ai-render-check.mjs +359 -0
- package/scripts/citation-line-check.mjs +53 -2
- package/scripts/deprecate-below.mjs +146 -0
- package/scripts/test-run.mjs +24 -1
- package/shared/connect-clients.mjs +52 -16
- package/shared/driver-dir.mjs +1 -1
- package/shared/grants-edit.mjs +99 -2
|
@@ -11629,6 +11629,11 @@ function decodeStatus(status, body) {
|
|
|
11629
11629
|
errors: errorsOf(body),
|
|
11630
11630
|
detail: refused
|
|
11631
11631
|
};
|
|
11632
|
+
if (refused) return {
|
|
11633
|
+
kind: "gate",
|
|
11634
|
+
message: "That could not be done. Nothing was changed.",
|
|
11635
|
+
detail: refused
|
|
11636
|
+
};
|
|
11632
11637
|
const msg = errorsOf(body)[0] ?? "This action could not be completed.";
|
|
11633
11638
|
return /version|conflict/i.test(msg) && !/confirmation|plan again|re-confirm/i.test(msg) ? {
|
|
11634
11639
|
kind: "conflict",
|
|
@@ -11794,6 +11799,33 @@ function decodeAccess(b) {
|
|
|
11794
11799
|
}];
|
|
11795
11800
|
});
|
|
11796
11801
|
}
|
|
11802
|
+
var decodeSteps = (raw) => asArray(raw).flatMap((x) => {
|
|
11803
|
+
const s = asRecord(x);
|
|
11804
|
+
const text = asString(s["text"]);
|
|
11805
|
+
if (!text) return [];
|
|
11806
|
+
const hint = asString(s["hint"]);
|
|
11807
|
+
const c = s["copy"] == null ? null : asRecord(s["copy"]);
|
|
11808
|
+
let copy;
|
|
11809
|
+
if (c) {
|
|
11810
|
+
const kind = asString(c["kind"]);
|
|
11811
|
+
if (kind === "block" && asString(c["text"])) copy = {
|
|
11812
|
+
kind,
|
|
11813
|
+
text: asString(c["text"])
|
|
11814
|
+
};
|
|
11815
|
+
else if (kind === "secret" && asString(c["label"]) && asString(c["template"]) && asString(c["slot"]) && asString(c["template"]).includes(asString(c["slot"]))) copy = {
|
|
11816
|
+
kind,
|
|
11817
|
+
label: asString(c["label"]),
|
|
11818
|
+
template: asString(c["template"]),
|
|
11819
|
+
slot: asString(c["slot"])
|
|
11820
|
+
};
|
|
11821
|
+
else return [];
|
|
11822
|
+
}
|
|
11823
|
+
return [{
|
|
11824
|
+
text,
|
|
11825
|
+
...hint ? { hint } : {},
|
|
11826
|
+
...copy ? { copy } : {}
|
|
11827
|
+
}];
|
|
11828
|
+
});
|
|
11797
11829
|
function decodePerson(r) {
|
|
11798
11830
|
return {
|
|
11799
11831
|
email: asString(r["email"]) ?? "",
|
|
@@ -11802,7 +11834,10 @@ function decodePerson(r) {
|
|
|
11802
11834
|
manage: asRecord(r["permissions"])["manage"] === true
|
|
11803
11835
|
},
|
|
11804
11836
|
access: decodeAccess(r),
|
|
11805
|
-
dangling: asArray(r["dangling"]).filter((s) => typeof s === "string")
|
|
11837
|
+
dangling: asArray(r["dangling"]).filter((s) => typeof s === "string"),
|
|
11838
|
+
listed: r["listed"] !== false,
|
|
11839
|
+
covered: r["covered"] === true,
|
|
11840
|
+
keys: typeof r["keys"] === "number" && r["keys"] > 0 ? r["keys"] : 0
|
|
11806
11841
|
};
|
|
11807
11842
|
}
|
|
11808
11843
|
var api = {
|
|
@@ -12051,6 +12086,7 @@ var api = {
|
|
|
12051
12086
|
keyUrl: asString(b["keyUrl"]),
|
|
12052
12087
|
email: asString(b["email"]),
|
|
12053
12088
|
enabled: b["enabled"] === true,
|
|
12089
|
+
aiConnected: typeof b["aiConnected"] === "boolean" ? b["aiConnected"] : null,
|
|
12054
12090
|
stdio: (() => {
|
|
12055
12091
|
const r = b["stdio"];
|
|
12056
12092
|
if (!r || typeof r !== "object") return null;
|
|
@@ -12085,33 +12121,12 @@ var api = {
|
|
|
12085
12121
|
...asString(r["sub"]) ? { sub: asString(r["sub"]) } : {},
|
|
12086
12122
|
...asString(r["verifiedOn"]) ? { verifiedOn: asString(r["verifiedOn"]) } : {},
|
|
12087
12123
|
...asString(r["by"]) ? { by: asString(r["by"]) } : {},
|
|
12088
|
-
steps:
|
|
12089
|
-
|
|
12090
|
-
|
|
12091
|
-
|
|
12092
|
-
|
|
12093
|
-
|
|
12094
|
-
let copy;
|
|
12095
|
-
if (c) {
|
|
12096
|
-
const kind = asString(c["kind"]);
|
|
12097
|
-
if (kind === "block" && asString(c["text"])) copy = {
|
|
12098
|
-
kind,
|
|
12099
|
-
text: asString(c["text"])
|
|
12100
|
-
};
|
|
12101
|
-
else if (kind === "secret" && asString(c["label"]) && asString(c["template"]) && asString(c["slot"]) && asString(c["template"]).includes(asString(c["slot"]))) copy = {
|
|
12102
|
-
kind,
|
|
12103
|
-
label: asString(c["label"]),
|
|
12104
|
-
template: asString(c["template"]),
|
|
12105
|
-
slot: asString(c["slot"])
|
|
12106
|
-
};
|
|
12107
|
-
else return [];
|
|
12108
|
-
}
|
|
12109
|
-
return [{
|
|
12110
|
-
text,
|
|
12111
|
-
...hint ? { hint } : {},
|
|
12112
|
-
...copy ? { copy } : {}
|
|
12113
|
-
}];
|
|
12114
|
-
}),
|
|
12124
|
+
steps: decodeSteps(r["steps"]),
|
|
12125
|
+
...r["door"] === "sign-in" || r["door"] === "key" ? { door: r["door"] } : Object.hasOwn(r, "door") ? { door: null } : {},
|
|
12126
|
+
...!(r["door"] === "sign-in" || r["door"] === "key") && Object.hasOwn(r, "altSteps") ? (() => {
|
|
12127
|
+
const a = decodeSteps(r["altSteps"]);
|
|
12128
|
+
return a.length ? { altSteps: a } : {};
|
|
12129
|
+
})() : {},
|
|
12115
12130
|
launch: (() => {
|
|
12116
12131
|
const u = asString(asRecord(r["launch"])["url"]);
|
|
12117
12132
|
return u && /^https:\/\//.test(u) ? { url: u } : null;
|
|
@@ -12218,7 +12233,8 @@ var api = {
|
|
|
12218
12233
|
} : null;
|
|
12219
12234
|
})(),
|
|
12220
12235
|
canAdd: b["canAdd"] === true,
|
|
12221
|
-
localSignIn: b["localSignIn"] === true
|
|
12236
|
+
localSignIn: b["localSignIn"] === true,
|
|
12237
|
+
keysRevocable: b["keysRevocable"] === true
|
|
12222
12238
|
})),
|
|
12223
12239
|
addPerson: (body) => call("/portal/admin/people", (b) => ({
|
|
12224
12240
|
person: decodePerson(asRecord(b["person"])),
|
|
@@ -12227,6 +12243,32 @@ var api = {
|
|
|
12227
12243
|
method: "POST",
|
|
12228
12244
|
body: JSON.stringify(body)
|
|
12229
12245
|
}),
|
|
12246
|
+
changePerson: (body) => call("/portal/admin/people/change", (b) => ({
|
|
12247
|
+
person: decodePerson(asRecord(b["person"])),
|
|
12248
|
+
switchesApplied: b["switchesApplied"] === true,
|
|
12249
|
+
added: typeof b["added"] === "number" ? b["added"] : 0,
|
|
12250
|
+
removed: typeof b["removed"] === "number" ? b["removed"] : 0
|
|
12251
|
+
}), {
|
|
12252
|
+
method: "POST",
|
|
12253
|
+
body: JSON.stringify(body)
|
|
12254
|
+
}),
|
|
12255
|
+
removePerson: (body) => call("/portal/admin/people/remove", (b) => {
|
|
12256
|
+
const k = asRecord(b["keys"]);
|
|
12257
|
+
return {
|
|
12258
|
+
removed: b["removed"] === "install" ? "install" : "organisations",
|
|
12259
|
+
organisations: asStrings(b["organisations"]),
|
|
12260
|
+
keys: {
|
|
12261
|
+
checked: k["checked"] === true,
|
|
12262
|
+
revoked: typeof k["revoked"] === "number" ? k["revoked"] : 0,
|
|
12263
|
+
lateArm: k["lateArm"] === true,
|
|
12264
|
+
failed: k["failed"] === true,
|
|
12265
|
+
note: asString(k["note"])
|
|
12266
|
+
}
|
|
12267
|
+
};
|
|
12268
|
+
}, {
|
|
12269
|
+
method: "POST",
|
|
12270
|
+
body: JSON.stringify(body)
|
|
12271
|
+
}),
|
|
12230
12272
|
adminObserved: () => call("/portal/admin/observed", (b) => ({
|
|
12231
12273
|
available: b["available"] === true,
|
|
12232
12274
|
truncated: b["truncated"] === true,
|
|
@@ -12302,6 +12344,15 @@ var NAV = [
|
|
|
12302
12344
|
hidden: true,
|
|
12303
12345
|
scope: "account"
|
|
12304
12346
|
},
|
|
12347
|
+
{
|
|
12348
|
+
id: "people.modify",
|
|
12349
|
+
label: "Modify access",
|
|
12350
|
+
path: "/portal/people/modify",
|
|
12351
|
+
icon: "users",
|
|
12352
|
+
needs: "manage",
|
|
12353
|
+
hidden: true,
|
|
12354
|
+
scope: "account"
|
|
12355
|
+
},
|
|
12305
12356
|
{
|
|
12306
12357
|
id: "new",
|
|
12307
12358
|
label: "New clearance",
|
|
@@ -12454,6 +12505,7 @@ function decode(segment) {
|
|
|
12454
12505
|
}
|
|
12455
12506
|
var PEOPLE = NAV.find((e) => e.id === "people");
|
|
12456
12507
|
var ADD_PERSON = NAV.find((e) => e.id === "people.add");
|
|
12508
|
+
var MODIFY_PERSON = NAV.find((e) => e.id === "people.modify");
|
|
12457
12509
|
//#endregion
|
|
12458
12510
|
//#region ../node_modules/react/cjs/react-jsx-runtime.production.js
|
|
12459
12511
|
var require_react_jsx_runtime_production = __commonJSMin(((exports) => {
|
|
@@ -12848,6 +12900,26 @@ function seesEverything(who) {
|
|
|
12848
12900
|
return who.allAccounts === true;
|
|
12849
12901
|
}
|
|
12850
12902
|
//#endregion
|
|
12903
|
+
//#region src/components/PageHeader.tsx
|
|
12904
|
+
function PageHeader({ title, lede, actions }) {
|
|
12905
|
+
return (0, import_jsx_runtime.jsxs)("header", {
|
|
12906
|
+
className: "page-header",
|
|
12907
|
+
children: [(0, import_jsx_runtime.jsxs)("div", {
|
|
12908
|
+
className: "page-header-text",
|
|
12909
|
+
children: [(0, import_jsx_runtime.jsx)("h1", {
|
|
12910
|
+
className: "page-title",
|
|
12911
|
+
children: title
|
|
12912
|
+
}), lede ? (0, import_jsx_runtime.jsx)("p", {
|
|
12913
|
+
className: "page-lede",
|
|
12914
|
+
children: lede
|
|
12915
|
+
}) : null]
|
|
12916
|
+
}), actions ? (0, import_jsx_runtime.jsx)("div", {
|
|
12917
|
+
className: "page-header-actions",
|
|
12918
|
+
children: actions
|
|
12919
|
+
}) : null]
|
|
12920
|
+
});
|
|
12921
|
+
}
|
|
12922
|
+
//#endregion
|
|
12851
12923
|
//#region src/shell/CompanyPicker.tsx
|
|
12852
12924
|
function CompanyCard({ row, onPick }) {
|
|
12853
12925
|
return (0, import_jsx_runtime.jsxs)("button", {
|
|
@@ -12907,51 +12979,26 @@ function CompanyCard({ row, onPick }) {
|
|
|
12907
12979
|
})]
|
|
12908
12980
|
});
|
|
12909
12981
|
}
|
|
12910
|
-
function CompanyPicker({
|
|
12982
|
+
function CompanyPicker({ heading, line, keys, orgOf, organisations, companyName, factsFor, onPick, onAdd }) {
|
|
12911
12983
|
const { headings, groups } = pickerGroups(keys, orgOf, organisations, companyName, factsFor);
|
|
12912
|
-
return (0, import_jsx_runtime.
|
|
12984
|
+
return (0, import_jsx_runtime.jsx)("div", {
|
|
12913
12985
|
className: "screen",
|
|
12914
|
-
children:
|
|
12915
|
-
className: "eyebrow",
|
|
12916
|
-
children: eyebrow
|
|
12917
|
-
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
12986
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
12918
12987
|
className: "measure",
|
|
12919
|
-
children: [(0, import_jsx_runtime.
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
gap: 20,
|
|
12924
|
-
margin: "4px 0 18px"
|
|
12925
|
-
},
|
|
12926
|
-
children: [(0, import_jsx_runtime.jsxs)("div", {
|
|
12927
|
-
style: { flex: 1 },
|
|
12928
|
-
children: [(0, import_jsx_runtime.jsx)("h1", {
|
|
12929
|
-
style: {
|
|
12930
|
-
fontSize: 27,
|
|
12931
|
-
margin: "0 0 4px",
|
|
12932
|
-
color: "var(--text-strong)"
|
|
12933
|
-
},
|
|
12934
|
-
children: heading
|
|
12935
|
-
}), (0, import_jsx_runtime.jsx)("p", {
|
|
12936
|
-
style: {
|
|
12937
|
-
margin: 0,
|
|
12938
|
-
color: "var(--text-muted)",
|
|
12939
|
-
fontSize: 14.5
|
|
12940
|
-
},
|
|
12941
|
-
children: line
|
|
12942
|
-
})]
|
|
12943
|
-
}), onAdd ? (0, import_jsx_runtime.jsx)("button", {
|
|
12988
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
12989
|
+
title: heading,
|
|
12990
|
+
lede: line,
|
|
12991
|
+
actions: onAdd ? (0, import_jsx_runtime.jsx)("button", {
|
|
12944
12992
|
type: "button",
|
|
12945
12993
|
className: "start-pill",
|
|
12946
12994
|
onClick: onAdd,
|
|
12947
12995
|
style: {
|
|
12948
|
-
flex: "none",
|
|
12949
12996
|
borderColor: "var(--accent-ink)",
|
|
12950
12997
|
color: "var(--text-accent)",
|
|
12951
12998
|
fontWeight: 700
|
|
12952
12999
|
},
|
|
12953
13000
|
children: "+ New company"
|
|
12954
|
-
}) : null
|
|
13001
|
+
}) : null
|
|
12955
13002
|
}), groups.map((g, i) => (0, import_jsx_runtime.jsxs)("div", { children: [headings && g.org ? (0, import_jsx_runtime.jsx)("div", {
|
|
12956
13003
|
className: "eyebrow",
|
|
12957
13004
|
style: { margin: i === 0 ? "0 0 8px" : "16px 0 8px" },
|
|
@@ -12969,12 +13016,11 @@ function CompanyPicker({ eyebrow, heading, line, keys, orgOf, organisations, com
|
|
|
12969
13016
|
onPick: () => onPick(r.key)
|
|
12970
13017
|
}, r.key))
|
|
12971
13018
|
})] }, g.org?.key ?? ""))]
|
|
12972
|
-
})
|
|
13019
|
+
})
|
|
12973
13020
|
});
|
|
12974
13021
|
}
|
|
12975
|
-
function CompanyGate({ ctx,
|
|
13022
|
+
function CompanyGate({ ctx, heading, line }) {
|
|
12976
13023
|
return (0, import_jsx_runtime.jsx)(CompanyPicker, {
|
|
12977
|
-
eyebrow,
|
|
12978
13024
|
heading,
|
|
12979
13025
|
line,
|
|
12980
13026
|
keys: ctx.ownerKeys,
|
|
@@ -13679,11 +13725,34 @@ var RANK = {
|
|
|
13679
13725
|
paused: 2,
|
|
13680
13726
|
queued: 3
|
|
13681
13727
|
};
|
|
13728
|
+
var STOPPED = new Set(["failed", "cancelled"]);
|
|
13729
|
+
var whenOf = (r) => {
|
|
13730
|
+
for (const raw of [r.issuedAt, r.date]) {
|
|
13731
|
+
if (!raw) continue;
|
|
13732
|
+
const t = new Date(raw).getTime();
|
|
13733
|
+
if (!Number.isNaN(t)) return t;
|
|
13734
|
+
}
|
|
13735
|
+
return null;
|
|
13736
|
+
};
|
|
13737
|
+
var withinWindow = (r, now, days) => {
|
|
13738
|
+
const at = whenOf(r);
|
|
13739
|
+
return at === null || now - at <= days * 24 * 60 * 60 * 1e3;
|
|
13740
|
+
};
|
|
13741
|
+
var failuresNewestFirst = (a, b) => {
|
|
13742
|
+
const at = whenOf(a), bt = whenOf(b);
|
|
13743
|
+
if (at === null && bt === null) return 0;
|
|
13744
|
+
if (at === null) return -1;
|
|
13745
|
+
if (bt === null) return 1;
|
|
13746
|
+
return newestFirst(a, b);
|
|
13747
|
+
};
|
|
13682
13748
|
function inFlight(runs) {
|
|
13683
|
-
return runs.filter((r) => r.state !== "delivered" && !r.
|
|
13749
|
+
return runs.filter((r) => r.state !== "delivered" && !STOPPED.has(r.state)).slice().sort((a, b) => (RANK[a.state] ?? 9) - (RANK[b.state] ?? 9));
|
|
13750
|
+
}
|
|
13751
|
+
function recentFailures(runs, { now = Date.now(), days = 7 } = {}) {
|
|
13752
|
+
return runs.filter((r) => STOPPED.has(r.state) && !r.acked && withinWindow(r, now, days)).slice().sort(failuresNewestFirst);
|
|
13684
13753
|
}
|
|
13685
|
-
function acknowledged(runs) {
|
|
13686
|
-
return runs.filter((r) => r.state
|
|
13754
|
+
function acknowledged(runs, { now = Date.now(), days = 7 } = {}) {
|
|
13755
|
+
return runs.filter((r) => STOPPED.has(r.state) && r.acked === true && withinWindow(r, now, days)).slice().sort(failuresNewestFirst);
|
|
13687
13756
|
}
|
|
13688
13757
|
function readStamps(rows) {
|
|
13689
13758
|
const identity = (r) => [
|
|
@@ -13842,11 +13911,14 @@ function Home({ ctx }) {
|
|
|
13842
13911
|
const allRuns = result?.kind === "ok" ? result.value : [];
|
|
13843
13912
|
const runs = (0, import_react.useMemo)(() => runsFor(allRuns, ctx.owner), [allRuns, ctx.owner]);
|
|
13844
13913
|
const rows = (0, import_react.useMemo)(() => inFlight(runs), [runs]);
|
|
13914
|
+
const stopped = (0, import_react.useMemo)(() => recentFailures(runs), [runs]);
|
|
13915
|
+
const [showStopped, setShowStopped] = (0, import_react.useState)(false);
|
|
13845
13916
|
const acked = (0, import_react.useMemo)(() => acknowledged(runs), [runs]);
|
|
13846
13917
|
const [showAcked, setShowAcked] = (0, import_react.useState)(false);
|
|
13847
13918
|
const cards = (0, import_react.useMemo)(() => active(rows), [rows]);
|
|
13848
13919
|
const queue = (0, import_react.useMemo)(() => waiting(rows), [rows]);
|
|
13849
13920
|
const stamps = (0, import_react.useMemo)(() => readStamps(rows), [rows]);
|
|
13921
|
+
const stoppedStamps = (0, import_react.useMemo)(() => readStamps(stopped), [stopped]);
|
|
13850
13922
|
const ackedStamps = (0, import_react.useMemo)(() => readStamps(acked), [acked]);
|
|
13851
13923
|
const done = (0, import_react.useMemo)(() => recentlyFinished(runs, void 0, 3), [runs]);
|
|
13852
13924
|
const recent = (0, import_react.useMemo)(() => done.map(lastFinishedOf).filter((r) => r !== null), [done]);
|
|
@@ -13859,23 +13931,18 @@ function Home({ ctx }) {
|
|
|
13859
13931
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
13860
13932
|
className: "screen home2",
|
|
13861
13933
|
children: [
|
|
13862
|
-
(0, import_jsx_runtime.jsx)(
|
|
13863
|
-
|
|
13864
|
-
children: "
|
|
13865
|
-
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
color: "var(--text-strong)"
|
|
13871
|
-
},
|
|
13872
|
-
children: "Now"
|
|
13934
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
13935
|
+
title: "Home",
|
|
13936
|
+
actions: (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsxs)("button", {
|
|
13937
|
+
type: "button",
|
|
13938
|
+
className: "btn-ghost home2-all",
|
|
13939
|
+
onClick: () => ctx.go("/portal/clearances"),
|
|
13940
|
+
children: [(0, import_jsx_runtime.jsx)(Icon, { name: "layers" }), (0, import_jsx_runtime.jsx)("span", { children: "All Clearances" })]
|
|
13941
|
+
}), canRun(ctx.me) ? (0, import_jsx_runtime.jsx)(NewClearanceButton, { onNew: () => ctx.go("/portal/new") }) : null] })
|
|
13873
13942
|
}),
|
|
13874
13943
|
(0, import_jsx_runtime.jsx)(InFlightBand, {
|
|
13875
13944
|
count: cards.length + queue.length,
|
|
13876
|
-
note: cards.length + queue.length === 0 ? `Nothing running right now.${canRun(ctx.me) ? " Start one with New clearance." : ""}` : slotNote(null, ctx.me.concurrentRuns)
|
|
13877
|
-
onNew: canRun(ctx.me) ? () => ctx.go("/portal/new") : null,
|
|
13878
|
-
onAll: () => ctx.go("/portal/clearances")
|
|
13945
|
+
note: cards.length + queue.length === 0 ? `Nothing running right now.${canRun(ctx.me) ? " Start one with New clearance." : ""}` : slotNote(null, ctx.me.concurrentRuns)
|
|
13879
13946
|
}),
|
|
13880
13947
|
(0, import_jsx_runtime.jsx)("div", {
|
|
13881
13948
|
style: { margin: "0 0 18px" },
|
|
@@ -13903,6 +13970,28 @@ function Home({ ctx }) {
|
|
|
13903
13970
|
onChanged: reload,
|
|
13904
13971
|
stamps
|
|
13905
13972
|
}) : null,
|
|
13973
|
+
stopped.length ? (0, import_jsx_runtime.jsxs)("div", {
|
|
13974
|
+
className: "home2-stopped",
|
|
13975
|
+
children: [(0, import_jsx_runtime.jsxs)("button", {
|
|
13976
|
+
type: "button",
|
|
13977
|
+
className: "home2-stopped-toggle",
|
|
13978
|
+
"aria-expanded": showStopped,
|
|
13979
|
+
onClick: () => setShowStopped((v) => !v),
|
|
13980
|
+
children: [
|
|
13981
|
+
stopped.length,
|
|
13982
|
+
" stopped recently",
|
|
13983
|
+
showStopped ? "" : " — show"
|
|
13984
|
+
]
|
|
13985
|
+
}), showStopped ? (0, import_jsx_runtime.jsx)("div", {
|
|
13986
|
+
className: "home2-cards",
|
|
13987
|
+
children: stopped.map((r) => (0, import_jsx_runtime.jsx)(Card, {
|
|
13988
|
+
run: r,
|
|
13989
|
+
ctx,
|
|
13990
|
+
onChanged: reload,
|
|
13991
|
+
stamp: stoppedStamps.get(r.runId) ?? null
|
|
13992
|
+
}, r.runId))
|
|
13993
|
+
}) : null]
|
|
13994
|
+
}) : null,
|
|
13906
13995
|
acked.length ? (0, import_jsx_runtime.jsxs)("div", {
|
|
13907
13996
|
className: "home2-acked",
|
|
13908
13997
|
children: [(0, import_jsx_runtime.jsxs)("button", {
|
|
@@ -13942,7 +14031,7 @@ function Home({ ctx }) {
|
|
|
13942
14031
|
total: finishedCount,
|
|
13943
14032
|
ctx
|
|
13944
14033
|
}) : null,
|
|
13945
|
-
answer === "ok" && !cards.length && !queue.length && !recent.length ? (0, import_jsx_runtime.jsx)(FirstRun$1, { onNew: canRun(ctx.me) ? () => ctx.go("/portal/new") : null }) : null,
|
|
14034
|
+
answer === "ok" && !cards.length && !queue.length && !recent.length && !stopped.length && !acked.length ? (0, import_jsx_runtime.jsx)(FirstRun$1, { onNew: canRun(ctx.me) ? () => ctx.go("/portal/new") : null }) : null,
|
|
13946
14035
|
usageRes?.kind === "ok" ? (0, import_jsx_runtime.jsx)("p", {
|
|
13947
14036
|
className: "home2-limits mono",
|
|
13948
14037
|
children: limitLine(usageRes.value.today, usageRes.value.dailyRuns)
|
|
@@ -13950,7 +14039,15 @@ function Home({ ctx }) {
|
|
|
13950
14039
|
]
|
|
13951
14040
|
});
|
|
13952
14041
|
}
|
|
13953
|
-
function
|
|
14042
|
+
function NewClearanceButton({ onNew }) {
|
|
14043
|
+
return (0, import_jsx_runtime.jsxs)("button", {
|
|
14044
|
+
type: "button",
|
|
14045
|
+
className: "home2-new",
|
|
14046
|
+
onClick: onNew,
|
|
14047
|
+
children: [(0, import_jsx_runtime.jsx)(Icon, { name: "plus-circle" }), "New clearance"]
|
|
14048
|
+
});
|
|
14049
|
+
}
|
|
14050
|
+
function InFlightBand({ count, note }) {
|
|
13954
14051
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
13955
14052
|
className: "home2-band",
|
|
13956
14053
|
children: [
|
|
@@ -13966,20 +14063,7 @@ function InFlightBand({ count, note, onNew, onAll }) {
|
|
|
13966
14063
|
(0, import_jsx_runtime.jsx)("span", {
|
|
13967
14064
|
className: "home2-band-note",
|
|
13968
14065
|
children: note
|
|
13969
|
-
})
|
|
13970
|
-
(0, import_jsx_runtime.jsxs)("button", {
|
|
13971
|
-
type: "button",
|
|
13972
|
-
className: "btn-ghost home2-all",
|
|
13973
|
-
onClick: onAll,
|
|
13974
|
-
style: { marginRight: 8 },
|
|
13975
|
-
children: [(0, import_jsx_runtime.jsx)(Icon, { name: "layers" }), (0, import_jsx_runtime.jsx)("span", { children: "All Clearances" })]
|
|
13976
|
-
}),
|
|
13977
|
-
onNew ? (0, import_jsx_runtime.jsxs)("button", {
|
|
13978
|
-
type: "button",
|
|
13979
|
-
className: "home2-new",
|
|
13980
|
-
onClick: onNew,
|
|
13981
|
-
children: [(0, import_jsx_runtime.jsx)(Icon, { name: "plus-circle" }), "New clearance"]
|
|
13982
|
-
}) : null
|
|
14066
|
+
})
|
|
13983
14067
|
]
|
|
13984
14068
|
});
|
|
13985
14069
|
}
|
|
@@ -14774,24 +14858,12 @@ function Clearances({ ctx }) {
|
|
|
14774
14858
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
14775
14859
|
className: "screen",
|
|
14776
14860
|
children: [
|
|
14777
|
-
(0, import_jsx_runtime.jsx)(
|
|
14778
|
-
|
|
14779
|
-
children: "
|
|
14780
|
-
|
|
14781
|
-
|
|
14782
|
-
|
|
14783
|
-
fontSize: 27,
|
|
14784
|
-
margin: "4px 0 6px",
|
|
14785
|
-
color: "var(--text-strong)"
|
|
14786
|
-
},
|
|
14787
|
-
children: ownerFilter ? ctx.ownerName(ownerFilter) : "All Clearances"
|
|
14788
|
-
}),
|
|
14789
|
-
(0, import_jsx_runtime.jsx)("p", {
|
|
14790
|
-
style: {
|
|
14791
|
-
margin: 0,
|
|
14792
|
-
color: "var(--text-muted)"
|
|
14793
|
-
},
|
|
14794
|
-
children: (0, import_jsx_runtime.jsx)(AllowanceLine, { account })
|
|
14861
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
14862
|
+
title: "All Clearances",
|
|
14863
|
+
lede: (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ownerFilter ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsx)("span", {
|
|
14864
|
+
"data-anon": "mark",
|
|
14865
|
+
children: ctx.ownerName(ownerFilter)
|
|
14866
|
+
}), " · "] }) : null, (0, import_jsx_runtime.jsx)(AllowanceLine, { account })] })
|
|
14795
14867
|
}),
|
|
14796
14868
|
(0, import_jsx_runtime.jsx)("div", {
|
|
14797
14869
|
className: "controls",
|
|
@@ -15784,16 +15856,48 @@ function frameCommand(command, value) {
|
|
|
15784
15856
|
}
|
|
15785
15857
|
//#endregion
|
|
15786
15858
|
//#region src/contract/askAi.ts
|
|
15787
|
-
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15791
|
-
|
|
15859
|
+
var MONTHS = [
|
|
15860
|
+
"",
|
|
15861
|
+
"January",
|
|
15862
|
+
"February",
|
|
15863
|
+
"March",
|
|
15864
|
+
"April",
|
|
15865
|
+
"May",
|
|
15866
|
+
"June",
|
|
15867
|
+
"July",
|
|
15868
|
+
"August",
|
|
15869
|
+
"September",
|
|
15870
|
+
"October",
|
|
15871
|
+
"November",
|
|
15872
|
+
"December"
|
|
15873
|
+
];
|
|
15874
|
+
function readableDate(iso) {
|
|
15875
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(iso ?? "").trim());
|
|
15876
|
+
if (!m) return null;
|
|
15877
|
+
const month = MONTHS[Number(m[2])];
|
|
15878
|
+
const day = Number(m[3]);
|
|
15879
|
+
if (!month || !(day >= 1 && day <= 31)) return null;
|
|
15880
|
+
return `${day} ${month}`;
|
|
15881
|
+
}
|
|
15882
|
+
function askAiPrompt(mark, date, kind = "clearance") {
|
|
15883
|
+
const name = String(mark ?? "").trim() || "this mark";
|
|
15884
|
+
const noun = kind === "knockout-batch" ? "knockout search" : "clearance";
|
|
15885
|
+
const when = readableDate(date);
|
|
15886
|
+
return when ? `Brief me on the ${name} ${noun} from ${when}.` : `Brief me on the ${name} ${noun}.`;
|
|
15887
|
+
}
|
|
15888
|
+
var ASSISTANTS = [{
|
|
15889
|
+
label: "Ask Claude",
|
|
15890
|
+
href: (q) => `https://claude.ai/new?q=${encodeURIComponent(q)}`
|
|
15891
|
+
}, {
|
|
15892
|
+
label: "Ask ChatGPT",
|
|
15893
|
+
href: (q) => `https://chatgpt.com/?q=${encodeURIComponent(q)}`
|
|
15894
|
+
}];
|
|
15895
|
+
var AI_SETUP_PATH = "/portal/ai";
|
|
15896
|
+
function askAiOffer(run, access) {
|
|
15792
15897
|
return {
|
|
15793
|
-
|
|
15794
|
-
|
|
15795
|
-
|
|
15796
|
-
stdio: access?.stdio ?? null
|
|
15898
|
+
drawn: !!access && (!!(access.enabled && access.url) || !!access.stdio),
|
|
15899
|
+
question: askAiPrompt(run.markName, run.date, run.kind),
|
|
15900
|
+
connected: access?.aiConnected === true
|
|
15797
15901
|
};
|
|
15798
15902
|
}
|
|
15799
15903
|
//#endregion
|
|
@@ -15851,12 +15955,12 @@ function useReportFrame() {
|
|
|
15851
15955
|
clearFailed: () => setFailed(null)
|
|
15852
15956
|
};
|
|
15853
15957
|
}
|
|
15854
|
-
function AskAiMenu({
|
|
15958
|
+
function AskAiMenu({ run, ctx }) {
|
|
15855
15959
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
15856
|
-
const [
|
|
15960
|
+
const [askAnyway, setAskAnyway] = (0, import_react.useState)(false);
|
|
15857
15961
|
const box = (0, import_react.useRef)(null);
|
|
15858
15962
|
const { result } = useLoad(() => api.mcpAccess(), []);
|
|
15859
|
-
const offer = askAiOffer(
|
|
15963
|
+
const offer = askAiOffer(run, result?.kind === "ok" ? result.value : null);
|
|
15860
15964
|
(0, import_react.useEffect)(() => {
|
|
15861
15965
|
if (!open) return;
|
|
15862
15966
|
function onDown(e) {
|
|
@@ -15872,115 +15976,151 @@ function AskAiMenu({ runId, mark, ctx }) {
|
|
|
15872
15976
|
document.removeEventListener("keydown", onKey);
|
|
15873
15977
|
};
|
|
15874
15978
|
}, [open]);
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
} catch {
|
|
15881
|
-
setCopied(`${what}-failed`);
|
|
15882
|
-
}
|
|
15883
|
-
})();
|
|
15979
|
+
if (!offer.drawn) return null;
|
|
15980
|
+
const showMenu = offer.connected || askAnyway;
|
|
15981
|
+
const ask = (href) => {
|
|
15982
|
+
setOpen(false);
|
|
15983
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
15884
15984
|
};
|
|
15885
|
-
|
|
15886
|
-
|
|
15887
|
-
|
|
15888
|
-
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
|
|
15895
|
-
style: {
|
|
15896
|
-
display: "flex",
|
|
15897
|
-
alignItems: "center",
|
|
15898
|
-
gap: 8
|
|
15899
|
-
},
|
|
15900
|
-
children: [(0, import_jsx_runtime.jsx)("span", {
|
|
15901
|
-
className: "mono",
|
|
15985
|
+
return (0, import_jsx_runtime.jsxs)("div", {
|
|
15986
|
+
ref: box,
|
|
15987
|
+
style: { position: "relative" },
|
|
15988
|
+
"data-ask-ai": showMenu ? "menu" : "connect",
|
|
15989
|
+
children: [
|
|
15990
|
+
(0, import_jsx_runtime.jsxs)("button", {
|
|
15991
|
+
type: "button",
|
|
15992
|
+
className: "nav-item",
|
|
15993
|
+
"aria-haspopup": showMenu ? "menu" : "dialog",
|
|
15994
|
+
"aria-expanded": open,
|
|
15902
15995
|
style: {
|
|
15903
|
-
|
|
15904
|
-
|
|
15905
|
-
|
|
15906
|
-
|
|
15996
|
+
width: "auto",
|
|
15997
|
+
margin: 0,
|
|
15998
|
+
padding: "6px 11px",
|
|
15999
|
+
border: "1px solid var(--border-hairline)"
|
|
15907
16000
|
},
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
|
|
16001
|
+
onClick: () => setOpen((v) => !v),
|
|
16002
|
+
children: [(0, import_jsx_runtime.jsx)(Icon, {
|
|
16003
|
+
name: "sparkles",
|
|
16004
|
+
size: 14
|
|
16005
|
+
}), (0, import_jsx_runtime.jsx)("span", { children: "Ask AI" })]
|
|
16006
|
+
}),
|
|
16007
|
+
open && showMenu ? (0, import_jsx_runtime.jsxs)("div", {
|
|
16008
|
+
className: "float",
|
|
16009
|
+
role: "menu",
|
|
15912
16010
|
style: {
|
|
15913
|
-
|
|
15914
|
-
|
|
16011
|
+
position: "absolute",
|
|
16012
|
+
right: 0,
|
|
16013
|
+
top: 38,
|
|
16014
|
+
width: 236,
|
|
16015
|
+
padding: 6,
|
|
16016
|
+
zIndex: 50
|
|
15915
16017
|
},
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
|
|
15919
|
-
|
|
15920
|
-
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
|
|
15924
|
-
|
|
15925
|
-
|
|
15926
|
-
|
|
15927
|
-
|
|
15928
|
-
|
|
15929
|
-
|
|
15930
|
-
|
|
15931
|
-
|
|
15932
|
-
|
|
15933
|
-
|
|
15934
|
-
|
|
15935
|
-
|
|
15936
|
-
|
|
15937
|
-
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
15946
|
-
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
|
|
15955
|
-
|
|
15956
|
-
|
|
15957
|
-
|
|
15958
|
-
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15965
|
-
|
|
15966
|
-
|
|
15967
|
-
|
|
15968
|
-
|
|
15969
|
-
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
},
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
16018
|
+
children: [
|
|
16019
|
+
ASSISTANTS.map((a) => (0, import_jsx_runtime.jsxs)("button", {
|
|
16020
|
+
type: "button",
|
|
16021
|
+
role: "menuitem",
|
|
16022
|
+
className: "nav-item",
|
|
16023
|
+
style: {
|
|
16024
|
+
fontSize: 13,
|
|
16025
|
+
padding: "7px 10px",
|
|
16026
|
+
margin: 0,
|
|
16027
|
+
justifyContent: "space-between"
|
|
16028
|
+
},
|
|
16029
|
+
onClick: () => ask(a.href(offer.question)),
|
|
16030
|
+
children: [(0, import_jsx_runtime.jsx)("span", { children: a.label }), (0, import_jsx_runtime.jsx)(Icon, {
|
|
16031
|
+
name: "arrow-right",
|
|
16032
|
+
size: 14
|
|
16033
|
+
})]
|
|
16034
|
+
}, a.label)),
|
|
16035
|
+
(0, import_jsx_runtime.jsx)("div", { style: {
|
|
16036
|
+
height: 1,
|
|
16037
|
+
background: "var(--border-hairline)",
|
|
16038
|
+
margin: "5px 8px"
|
|
16039
|
+
} }),
|
|
16040
|
+
(0, import_jsx_runtime.jsx)("button", {
|
|
16041
|
+
type: "button",
|
|
16042
|
+
role: "menuitem",
|
|
16043
|
+
className: "nav-item",
|
|
16044
|
+
style: {
|
|
16045
|
+
fontSize: 13,
|
|
16046
|
+
padding: "7px 10px",
|
|
16047
|
+
margin: 0,
|
|
16048
|
+
justifyContent: "space-between",
|
|
16049
|
+
color: "var(--text-muted)"
|
|
16050
|
+
},
|
|
16051
|
+
onClick: () => {
|
|
16052
|
+
setOpen(false);
|
|
16053
|
+
ctx.go(AI_SETUP_PATH);
|
|
16054
|
+
},
|
|
16055
|
+
children: (0, import_jsx_runtime.jsx)("span", { children: "Connect another AI" })
|
|
16056
|
+
})
|
|
16057
|
+
]
|
|
16058
|
+
}) : null,
|
|
16059
|
+
open && !showMenu ? (0, import_jsx_runtime.jsxs)("div", {
|
|
16060
|
+
className: "float",
|
|
16061
|
+
role: "dialog",
|
|
16062
|
+
"aria-label": "Connect your AI first",
|
|
16063
|
+
style: {
|
|
16064
|
+
position: "absolute",
|
|
16065
|
+
right: 0,
|
|
16066
|
+
top: 38,
|
|
16067
|
+
width: 276,
|
|
16068
|
+
padding: 12,
|
|
16069
|
+
zIndex: 50,
|
|
16070
|
+
display: "grid",
|
|
16071
|
+
gap: 9
|
|
16072
|
+
},
|
|
16073
|
+
children: [
|
|
16074
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
16075
|
+
style: {
|
|
16076
|
+
fontSize: 13.5,
|
|
16077
|
+
fontWeight: 700,
|
|
16078
|
+
color: "var(--text-strong)"
|
|
16079
|
+
},
|
|
16080
|
+
children: "Connect your AI first"
|
|
16081
|
+
}),
|
|
16082
|
+
(0, import_jsx_runtime.jsx)("p", {
|
|
16083
|
+
style: {
|
|
16084
|
+
margin: 0,
|
|
16085
|
+
fontSize: 12.5,
|
|
16086
|
+
color: "var(--text-muted)",
|
|
16087
|
+
lineHeight: 1.5
|
|
16088
|
+
},
|
|
16089
|
+
children: "Connect Claude or ChatGPT once. After that, this button opens it with a question about this report typed in."
|
|
16090
|
+
}),
|
|
16091
|
+
(0, import_jsx_runtime.jsxs)("button", {
|
|
16092
|
+
type: "button",
|
|
16093
|
+
className: "btn-primary",
|
|
16094
|
+
style: {
|
|
16095
|
+
fontSize: 13,
|
|
16096
|
+
padding: "6px 11px",
|
|
16097
|
+
justifySelf: "start",
|
|
16098
|
+
display: "inline-flex",
|
|
16099
|
+
alignItems: "center",
|
|
16100
|
+
gap: 6
|
|
16101
|
+
},
|
|
16102
|
+
onClick: () => {
|
|
16103
|
+
setOpen(false);
|
|
16104
|
+
ctx.go(AI_SETUP_PATH);
|
|
16105
|
+
},
|
|
16106
|
+
children: ["Set it up ", (0, import_jsx_runtime.jsx)(Icon, {
|
|
16107
|
+
name: "arrow-right",
|
|
16108
|
+
size: 14
|
|
16109
|
+
})]
|
|
16110
|
+
}),
|
|
16111
|
+
(0, import_jsx_runtime.jsx)("button", {
|
|
16112
|
+
type: "button",
|
|
16113
|
+
className: "link-btn",
|
|
16114
|
+
style: {
|
|
16115
|
+
fontSize: 12.5,
|
|
16116
|
+
justifySelf: "start"
|
|
16117
|
+
},
|
|
16118
|
+
onClick: () => setAskAnyway(true),
|
|
16119
|
+
children: "Already connected? Ask anyway"
|
|
16120
|
+
})
|
|
16121
|
+
]
|
|
16122
|
+
}) : null
|
|
16123
|
+
]
|
|
15984
16124
|
});
|
|
15985
16125
|
}
|
|
15986
16126
|
function ExportMenu({ send, runId, offered }) {
|
|
@@ -16258,8 +16398,7 @@ function Result({ ctx, runId, markSlug }) {
|
|
|
16258
16398
|
}),
|
|
16259
16399
|
(0, import_jsx_runtime.jsx)("span", { style: { flex: 1 } }),
|
|
16260
16400
|
(0, import_jsx_runtime.jsx)(AskAiMenu, {
|
|
16261
|
-
|
|
16262
|
-
mark: run.markName,
|
|
16401
|
+
run,
|
|
16263
16402
|
ctx
|
|
16264
16403
|
}),
|
|
16265
16404
|
doc ? (0, import_jsx_runtime.jsx)(ExportMenu, {
|
|
@@ -17874,7 +18013,6 @@ function NewClearance({ ctx }) {
|
|
|
17874
18013
|
});
|
|
17875
18014
|
if (needsOwner || searches?.kind === "pickAccount") return (0, import_jsx_runtime.jsx)(CompanyGate, {
|
|
17876
18015
|
ctx,
|
|
17877
|
-
eyebrow: "New clearance",
|
|
17878
18016
|
heading: "New clearance",
|
|
17879
18017
|
line: "Pick a company to run this clearance on."
|
|
17880
18018
|
});
|
|
@@ -17902,19 +18040,8 @@ function NewClearance({ ctx }) {
|
|
|
17902
18040
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
17903
18041
|
className: "screen",
|
|
17904
18042
|
children: [
|
|
17905
|
-
(0, import_jsx_runtime.jsx)("div", {
|
|
17906
|
-
className: "eyebrow",
|
|
17907
|
-
children: editingSlug ? "Custom search" : "New clearance"
|
|
17908
|
-
}),
|
|
17909
18043
|
(0, import_jsx_runtime.jsx)(CreatedStrip, {}),
|
|
17910
|
-
(0, import_jsx_runtime.jsx)("
|
|
17911
|
-
style: {
|
|
17912
|
-
fontSize: 27,
|
|
17913
|
-
margin: "4px 0 14px",
|
|
17914
|
-
color: "var(--text-strong)"
|
|
17915
|
-
},
|
|
17916
|
-
children: editingSlug ? "Edit a custom search" : "New clearance"
|
|
17917
|
-
}),
|
|
18044
|
+
(0, import_jsx_runtime.jsx)(PageHeader, { title: editingSlug ? "Edit a custom search" : "New clearance" }),
|
|
17918
18045
|
editingSlug ? editingRes && editingRes.kind !== "ok" ? (0, import_jsx_runtime.jsxs)("div", {
|
|
17919
18046
|
className: "notice",
|
|
17920
18047
|
style: { borderColor: "var(--tone-high)" },
|
|
@@ -18565,7 +18692,7 @@ function NewClearance({ ctx }) {
|
|
|
18565
18692
|
nativeControl === "toggle" ? (0, import_jsx_runtime.jsx)("div", {
|
|
18566
18693
|
className: "sunken-block",
|
|
18567
18694
|
style: { marginTop: 12 },
|
|
18568
|
-
children: (0, import_jsx_runtime.jsx)(Lever$
|
|
18695
|
+
children: (0, import_jsx_runtime.jsx)(Lever$2, {
|
|
18569
18696
|
label: "Native-language investigation",
|
|
18570
18697
|
hint: "Native marketplaces and native registers in the language of the countries you named. A clearance already searches the mark transliterated into the scripts its territories register marks in — this is the deeper read.",
|
|
18571
18698
|
on: draft.pick.nativeLanguage,
|
|
@@ -19277,7 +19404,7 @@ function SetupCommand({ route }) {
|
|
|
19277
19404
|
"from a copy of the source."
|
|
19278
19405
|
] });
|
|
19279
19406
|
}
|
|
19280
|
-
function Lever$
|
|
19407
|
+
function Lever$2({ label, hint, on, onToggle, coming }) {
|
|
19281
19408
|
return (0, import_jsx_runtime.jsxs)("button", {
|
|
19282
19409
|
type: "button",
|
|
19283
19410
|
onClick: coming ? void 0 : onToggle,
|
|
@@ -19834,51 +19961,37 @@ function OptionsUnavailable({ kind, onRetry }) {
|
|
|
19834
19961
|
function Submitted({ go, onAnother }) {
|
|
19835
19962
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
19836
19963
|
className: "screen",
|
|
19837
|
-
children: [
|
|
19838
|
-
|
|
19839
|
-
|
|
19840
|
-
children: "
|
|
19841
|
-
|
|
19842
|
-
|
|
19843
|
-
|
|
19844
|
-
|
|
19845
|
-
|
|
19846
|
-
|
|
19847
|
-
},
|
|
19848
|
-
|
|
19849
|
-
|
|
19850
|
-
|
|
19851
|
-
|
|
19852
|
-
|
|
19853
|
-
|
|
19854
|
-
(0, import_jsx_runtime.jsx)("
|
|
19855
|
-
|
|
19856
|
-
|
|
19857
|
-
|
|
19858
|
-
|
|
19859
|
-
|
|
19860
|
-
|
|
19861
|
-
|
|
19862
|
-
|
|
19863
|
-
|
|
19864
|
-
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19868
|
-
type: "button",
|
|
19869
|
-
className: "btn-primary",
|
|
19870
|
-
onClick: () => go("/portal/clearances"),
|
|
19871
|
-
children: "View in Clearances"
|
|
19872
|
-
}), (0, import_jsx_runtime.jsx)("button", {
|
|
19873
|
-
type: "button",
|
|
19874
|
-
className: "btn-ghost",
|
|
19875
|
-
onClick: onAnother,
|
|
19876
|
-
children: "Start another"
|
|
19877
|
-
})]
|
|
19878
|
-
})
|
|
19879
|
-
]
|
|
19880
|
-
})
|
|
19881
|
-
]
|
|
19964
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, { title: "Clearance started" }), (0, import_jsx_runtime.jsxs)("div", {
|
|
19965
|
+
className: "notice prose",
|
|
19966
|
+
children: [
|
|
19967
|
+
(0, import_jsx_runtime.jsx)("b", { children: "It is in the queue" }),
|
|
19968
|
+
(0, import_jsx_runtime.jsx)("p", {
|
|
19969
|
+
style: {
|
|
19970
|
+
margin: "6px 0 0",
|
|
19971
|
+
color: "var(--text-muted)"
|
|
19972
|
+
},
|
|
19973
|
+
children: "It will appear in Clearances, and the entry there tracks it the whole way — including if it stops early."
|
|
19974
|
+
}),
|
|
19975
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
19976
|
+
style: {
|
|
19977
|
+
marginTop: 14,
|
|
19978
|
+
display: "flex",
|
|
19979
|
+
gap: 10
|
|
19980
|
+
},
|
|
19981
|
+
children: [(0, import_jsx_runtime.jsx)("button", {
|
|
19982
|
+
type: "button",
|
|
19983
|
+
className: "btn-primary",
|
|
19984
|
+
onClick: () => go("/portal/clearances"),
|
|
19985
|
+
children: "View in Clearances"
|
|
19986
|
+
}), (0, import_jsx_runtime.jsx)("button", {
|
|
19987
|
+
type: "button",
|
|
19988
|
+
className: "btn-ghost",
|
|
19989
|
+
onClick: onAnother,
|
|
19990
|
+
children: "Start another"
|
|
19991
|
+
})]
|
|
19992
|
+
})
|
|
19993
|
+
]
|
|
19994
|
+
})]
|
|
19882
19995
|
});
|
|
19883
19996
|
}
|
|
19884
19997
|
function CreatedStrip() {
|
|
@@ -20515,29 +20628,14 @@ function NewCompany({ ctx }) {
|
|
|
20515
20628
|
const rejected = result && !isOk(result) && result.kind === "reject" ? result.errors : null;
|
|
20516
20629
|
const takenBy = result && !isOk(result) && result.kind === "reject" && result.detail?.code === "key_exists" ? result.detail.key : null;
|
|
20517
20630
|
const otherFailure = result && !isOk(result) && result.kind !== "reject" ? result : null;
|
|
20518
|
-
return (0, import_jsx_runtime.
|
|
20631
|
+
return (0, import_jsx_runtime.jsx)("div", {
|
|
20519
20632
|
className: "screen",
|
|
20520
|
-
children:
|
|
20521
|
-
className: "eyebrow",
|
|
20522
|
-
children: "Company"
|
|
20523
|
-
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
20633
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
20524
20634
|
className: "measure",
|
|
20525
20635
|
children: [
|
|
20526
|
-
(0, import_jsx_runtime.jsx)(
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
margin: "0 0 4px",
|
|
20530
|
-
color: "var(--text-strong)"
|
|
20531
|
-
},
|
|
20532
|
-
children: "New company"
|
|
20533
|
-
}),
|
|
20534
|
-
(0, import_jsx_runtime.jsx)("p", {
|
|
20535
|
-
style: {
|
|
20536
|
-
margin: "0 0 18px",
|
|
20537
|
-
color: "var(--text-muted)",
|
|
20538
|
-
fontSize: 14.5
|
|
20539
|
-
},
|
|
20540
|
-
children: "The business whose names you are checking. Only the name is needed; everything else has a default you can change later."
|
|
20636
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
20637
|
+
title: "New company",
|
|
20638
|
+
lede: "The business whose names you are checking. Only the name is needed; everything else has a default you can change later."
|
|
20541
20639
|
}),
|
|
20542
20640
|
orgsHeld.length > 1 ? (0, import_jsx_runtime.jsxs)("div", {
|
|
20543
20641
|
style: { marginBottom: 8 },
|
|
@@ -20684,7 +20782,7 @@ function NewCompany({ ctx }) {
|
|
|
20684
20782
|
}) : null]
|
|
20685
20783
|
})
|
|
20686
20784
|
]
|
|
20687
|
-
})
|
|
20785
|
+
})
|
|
20688
20786
|
});
|
|
20689
20787
|
}
|
|
20690
20788
|
function KeyLine({ value, onChange }) {
|
|
@@ -21140,23 +21238,12 @@ function Empty({ onNew }) {
|
|
|
21140
21238
|
function PickCompany({ ctx }) {
|
|
21141
21239
|
return (0, import_jsx_runtime.jsx)(CompanyGate, {
|
|
21142
21240
|
ctx,
|
|
21143
|
-
eyebrow: "Company",
|
|
21144
21241
|
heading: "Custom searches",
|
|
21145
21242
|
line: "Pick a company to see its custom searches."
|
|
21146
21243
|
});
|
|
21147
21244
|
}
|
|
21148
21245
|
function Heading() {
|
|
21149
|
-
return (0, import_jsx_runtime.
|
|
21150
|
-
className: "eyebrow",
|
|
21151
|
-
children: "Custom searches"
|
|
21152
|
-
}), (0, import_jsx_runtime.jsx)("h1", {
|
|
21153
|
-
style: {
|
|
21154
|
-
fontSize: 27,
|
|
21155
|
-
margin: "4px 0 6px",
|
|
21156
|
-
color: "var(--text-strong)"
|
|
21157
|
-
},
|
|
21158
|
-
children: "Custom searches"
|
|
21159
|
-
})] });
|
|
21246
|
+
return (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: (0, import_jsx_runtime.jsx)(PageHeader, { title: "Custom searches" }) });
|
|
21160
21247
|
}
|
|
21161
21248
|
//#endregion
|
|
21162
21249
|
//#region src/screens/Preferences.tsx
|
|
@@ -21172,222 +21259,203 @@ function Preferences({ ctx }) {
|
|
|
21172
21259
|
};
|
|
21173
21260
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
21174
21261
|
className: "screen",
|
|
21175
|
-
children: [
|
|
21176
|
-
|
|
21177
|
-
|
|
21178
|
-
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
|
|
21185
|
-
|
|
21186
|
-
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
|
|
21195
|
-
|
|
21196
|
-
|
|
21197
|
-
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21201
|
-
|
|
21202
|
-
|
|
21203
|
-
|
|
21204
|
-
|
|
21205
|
-
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
},
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
|
|
21216
|
-
}
|
|
21217
|
-
(
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
|
|
21221
|
-
|
|
21222
|
-
|
|
21262
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
21263
|
+
title: "Your preferences",
|
|
21264
|
+
lede: "Who you are signed in as, and how the portal looks on this computer."
|
|
21265
|
+
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
21266
|
+
className: "measure",
|
|
21267
|
+
style: { "--screen-measure": "720px" },
|
|
21268
|
+
children: [
|
|
21269
|
+
(0, import_jsx_runtime.jsxs)(Section, {
|
|
21270
|
+
title: "Your sign-in",
|
|
21271
|
+
hint: `Held by ${operatorName(ctx.me.brand)}. Nothing here can be changed from this page.`,
|
|
21272
|
+
children: [
|
|
21273
|
+
(0, import_jsx_runtime.jsxs)("dl", {
|
|
21274
|
+
style: {
|
|
21275
|
+
margin: 0,
|
|
21276
|
+
display: "grid",
|
|
21277
|
+
gridTemplateColumns: "auto 1fr",
|
|
21278
|
+
gap: "8px 18px",
|
|
21279
|
+
fontSize: 14
|
|
21280
|
+
},
|
|
21281
|
+
children: [
|
|
21282
|
+
(0, import_jsx_runtime.jsx)("dt", {
|
|
21283
|
+
style: { color: "var(--text-muted)" },
|
|
21284
|
+
children: "Address"
|
|
21285
|
+
}),
|
|
21286
|
+
(0, import_jsx_runtime.jsx)("dd", {
|
|
21287
|
+
style: {
|
|
21288
|
+
margin: 0,
|
|
21289
|
+
color: "var(--text-strong)",
|
|
21290
|
+
wordBreak: "break-all"
|
|
21291
|
+
},
|
|
21292
|
+
"data-anon": "mark",
|
|
21293
|
+
children: ctx.me.email || "—"
|
|
21294
|
+
}),
|
|
21295
|
+
(0, import_jsx_runtime.jsx)("dt", {
|
|
21296
|
+
style: { color: "var(--text-muted)" },
|
|
21297
|
+
children: "Permissions"
|
|
21298
|
+
}),
|
|
21299
|
+
(0, import_jsx_runtime.jsx)("dd", {
|
|
21300
|
+
style: {
|
|
21301
|
+
margin: 0,
|
|
21302
|
+
color: "var(--text-strong)"
|
|
21303
|
+
},
|
|
21304
|
+
children: permissionsPhrase(ctx.me.permissions)
|
|
21305
|
+
}),
|
|
21306
|
+
(0, import_jsx_runtime.jsx)("dt", {
|
|
21307
|
+
style: { color: "var(--text-muted)" },
|
|
21308
|
+
children: "Access to"
|
|
21309
|
+
}),
|
|
21310
|
+
(0, import_jsx_runtime.jsx)("dd", {
|
|
21311
|
+
style: {
|
|
21312
|
+
margin: 0,
|
|
21313
|
+
color: "var(--text-strong)"
|
|
21314
|
+
},
|
|
21315
|
+
children: ctx.me.access.length ? (0, import_jsx_runtime.jsx)("span", {
|
|
21223
21316
|
"data-anon": "mark",
|
|
21224
|
-
children: ctx.me.
|
|
21225
|
-
}),
|
|
21226
|
-
(0, import_jsx_runtime.jsx)("dt", {
|
|
21227
|
-
style: { color: "var(--text-muted)" },
|
|
21228
|
-
children: "Permissions"
|
|
21229
|
-
}),
|
|
21230
|
-
(0, import_jsx_runtime.jsx)("dd", {
|
|
21231
|
-
style: {
|
|
21232
|
-
margin: 0,
|
|
21233
|
-
color: "var(--text-strong)"
|
|
21234
|
-
},
|
|
21235
|
-
children: permissionsPhrase(ctx.me.permissions)
|
|
21236
|
-
}),
|
|
21237
|
-
(0, import_jsx_runtime.jsx)("dt", {
|
|
21317
|
+
children: accessChips(ctx.me.access).map((c) => c.label).join(", ")
|
|
21318
|
+
}) : (0, import_jsx_runtime.jsx)("span", {
|
|
21238
21319
|
style: { color: "var(--text-muted)" },
|
|
21239
|
-
children: "
|
|
21240
|
-
}),
|
|
21241
|
-
(0, import_jsx_runtime.jsx)("dd", {
|
|
21242
|
-
style: {
|
|
21243
|
-
margin: 0,
|
|
21244
|
-
color: "var(--text-strong)"
|
|
21245
|
-
},
|
|
21246
|
-
children: ctx.me.access.length ? (0, import_jsx_runtime.jsx)("span", {
|
|
21247
|
-
"data-anon": "mark",
|
|
21248
|
-
children: accessChips(ctx.me.access).map((c) => c.label).join(", ")
|
|
21249
|
-
}) : (0, import_jsx_runtime.jsx)("span", {
|
|
21250
|
-
style: { color: "var(--text-muted)" },
|
|
21251
|
-
children: "None recorded against this address."
|
|
21252
|
-
})
|
|
21320
|
+
children: "None recorded against this address."
|
|
21253
21321
|
})
|
|
21254
|
-
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
margin: "14px 0 0",
|
|
21259
|
-
fontSize: 13,
|
|
21260
|
-
color: "var(--text-muted)"
|
|
21261
|
-
},
|
|
21262
|
-
children: [
|
|
21263
|
-
"To change the address, the role or the companies on it, ask ",
|
|
21264
|
-
operatorName(ctx.me.brand),
|
|
21265
|
-
" — enrolment is done for you, not from this page."
|
|
21266
|
-
]
|
|
21267
|
-
}),
|
|
21268
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
21269
|
-
className: "pill",
|
|
21270
|
-
href: "/portal/sign-out",
|
|
21271
|
-
style: {
|
|
21272
|
-
display: "inline-block",
|
|
21273
|
-
marginTop: 12,
|
|
21274
|
-
textDecoration: "none"
|
|
21275
|
-
},
|
|
21276
|
-
children: "Log out"
|
|
21277
|
-
})
|
|
21278
|
-
]
|
|
21279
|
-
}),
|
|
21280
|
-
(0, import_jsx_runtime.jsxs)(Section, {
|
|
21281
|
-
title: "Appearance",
|
|
21282
|
-
hint: "Applies straight away, and is remembered in this browser.",
|
|
21283
|
-
children: [(0, import_jsx_runtime.jsxs)("div", {
|
|
21284
|
-
style: {
|
|
21285
|
-
display: "flex",
|
|
21286
|
-
gap: 10,
|
|
21287
|
-
flexWrap: "wrap"
|
|
21288
|
-
},
|
|
21289
|
-
children: [(0, import_jsx_runtime.jsx)(ThemeOption, {
|
|
21290
|
-
label: "Light",
|
|
21291
|
-
value: "light",
|
|
21292
|
-
current: theme,
|
|
21293
|
-
onPick: applyTheme
|
|
21294
|
-
}), (0, import_jsx_runtime.jsx)(ThemeOption, {
|
|
21295
|
-
label: "Dark",
|
|
21296
|
-
value: "dark",
|
|
21297
|
-
current: theme,
|
|
21298
|
-
onPick: applyTheme
|
|
21299
|
-
})]
|
|
21300
|
-
}), (0, import_jsx_runtime.jsx)("p", {
|
|
21322
|
+
})
|
|
21323
|
+
]
|
|
21324
|
+
}),
|
|
21325
|
+
(0, import_jsx_runtime.jsxs)("p", {
|
|
21301
21326
|
style: {
|
|
21302
|
-
margin: "
|
|
21327
|
+
margin: "14px 0 0",
|
|
21303
21328
|
fontSize: 13,
|
|
21304
21329
|
color: "var(--text-muted)"
|
|
21305
21330
|
},
|
|
21306
|
-
children:
|
|
21331
|
+
children: [
|
|
21332
|
+
"To change the address, the role or the companies on it, ask ",
|
|
21333
|
+
operatorName(ctx.me.brand),
|
|
21334
|
+
" — enrolment is done for you, not from this page."
|
|
21335
|
+
]
|
|
21336
|
+
}),
|
|
21337
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
21338
|
+
className: "pill",
|
|
21339
|
+
href: "/portal/sign-out",
|
|
21340
|
+
style: {
|
|
21341
|
+
display: "inline-block",
|
|
21342
|
+
marginTop: 12,
|
|
21343
|
+
textDecoration: "none"
|
|
21344
|
+
},
|
|
21345
|
+
children: "Log out"
|
|
21346
|
+
})
|
|
21347
|
+
]
|
|
21348
|
+
}),
|
|
21349
|
+
(0, import_jsx_runtime.jsxs)(Section, {
|
|
21350
|
+
title: "Appearance",
|
|
21351
|
+
hint: "Applies straight away, and is remembered in this browser.",
|
|
21352
|
+
children: [(0, import_jsx_runtime.jsxs)("div", {
|
|
21353
|
+
style: {
|
|
21354
|
+
display: "flex",
|
|
21355
|
+
gap: 10,
|
|
21356
|
+
flexWrap: "wrap"
|
|
21357
|
+
},
|
|
21358
|
+
children: [(0, import_jsx_runtime.jsx)(ThemeOption, {
|
|
21359
|
+
label: "Light",
|
|
21360
|
+
value: "light",
|
|
21361
|
+
current: theme,
|
|
21362
|
+
onPick: applyTheme
|
|
21363
|
+
}), (0, import_jsx_runtime.jsx)(ThemeOption, {
|
|
21364
|
+
label: "Dark",
|
|
21365
|
+
value: "dark",
|
|
21366
|
+
current: theme,
|
|
21367
|
+
onPick: applyTheme
|
|
21307
21368
|
})]
|
|
21308
|
-
}),
|
|
21309
|
-
|
|
21310
|
-
|
|
21311
|
-
|
|
21312
|
-
|
|
21313
|
-
|
|
21369
|
+
}), (0, import_jsx_runtime.jsx)("p", {
|
|
21370
|
+
style: {
|
|
21371
|
+
margin: "12px 0 0",
|
|
21372
|
+
fontSize: 13,
|
|
21373
|
+
color: "var(--text-muted)"
|
|
21374
|
+
},
|
|
21375
|
+
children: "The same choice is on the top bar, under the circle icon — this page and that button set one and the same setting."
|
|
21376
|
+
})]
|
|
21377
|
+
}),
|
|
21378
|
+
(0, import_jsx_runtime.jsxs)(Section, {
|
|
21379
|
+
title: "Blurring names while you share a screen",
|
|
21380
|
+
hint: "There is one control for this, and it is on the top bar.",
|
|
21381
|
+
children: [
|
|
21382
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
21383
|
+
style: {
|
|
21384
|
+
display: "flex",
|
|
21385
|
+
alignItems: "center",
|
|
21386
|
+
gap: 12
|
|
21387
|
+
},
|
|
21388
|
+
children: [(0, import_jsx_runtime.jsxs)("span", {
|
|
21389
|
+
className: "pill",
|
|
21314
21390
|
style: {
|
|
21315
|
-
display: "flex",
|
|
21391
|
+
display: "inline-flex",
|
|
21316
21392
|
alignItems: "center",
|
|
21317
|
-
gap:
|
|
21318
|
-
|
|
21319
|
-
children: [(0, import_jsx_runtime.jsxs)("span", {
|
|
21320
|
-
className: "pill",
|
|
21321
|
-
style: {
|
|
21322
|
-
display: "inline-flex",
|
|
21323
|
-
alignItems: "center",
|
|
21324
|
-
gap: 7,
|
|
21325
|
-
padding: "4px 11px"
|
|
21326
|
-
},
|
|
21327
|
-
children: [(0, import_jsx_runtime.jsx)(Icon, {
|
|
21328
|
-
name: "eye",
|
|
21329
|
-
size: 15
|
|
21330
|
-
}), "Top bar"]
|
|
21331
|
-
}), (0, import_jsx_runtime.jsx)("span", {
|
|
21332
|
-
style: {
|
|
21333
|
-
fontSize: 13.5,
|
|
21334
|
-
color: "var(--text-muted)"
|
|
21335
|
-
},
|
|
21336
|
-
children: "The eye button, to the left of your initials."
|
|
21337
|
-
})]
|
|
21338
|
-
}),
|
|
21339
|
-
(0, import_jsx_runtime.jsx)("p", {
|
|
21340
|
-
style: {
|
|
21341
|
-
margin: "12px 0 0",
|
|
21342
|
-
color: "var(--text-muted)",
|
|
21343
|
-
fontSize: 13.5
|
|
21393
|
+
gap: 7,
|
|
21394
|
+
padding: "4px 11px"
|
|
21344
21395
|
},
|
|
21345
|
-
children:
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
|
|
21396
|
+
children: [(0, import_jsx_runtime.jsx)(Icon, {
|
|
21397
|
+
name: "eye",
|
|
21398
|
+
size: 15
|
|
21399
|
+
}), "Top bar"]
|
|
21400
|
+
}), (0, import_jsx_runtime.jsx)("span", {
|
|
21349
21401
|
style: {
|
|
21350
|
-
|
|
21351
|
-
|
|
21402
|
+
fontSize: 13.5,
|
|
21403
|
+
color: "var(--text-muted)"
|
|
21352
21404
|
},
|
|
21353
|
-
children:
|
|
21354
|
-
|
|
21355
|
-
|
|
21356
|
-
|
|
21357
|
-
|
|
21358
|
-
|
|
21359
|
-
|
|
21360
|
-
|
|
21361
|
-
|
|
21362
|
-
|
|
21363
|
-
|
|
21364
|
-
|
|
21405
|
+
children: "The eye button, to the left of your initials."
|
|
21406
|
+
})]
|
|
21407
|
+
}),
|
|
21408
|
+
(0, import_jsx_runtime.jsx)("p", {
|
|
21409
|
+
style: {
|
|
21410
|
+
margin: "12px 0 0",
|
|
21411
|
+
color: "var(--text-muted)",
|
|
21412
|
+
fontSize: 13.5
|
|
21413
|
+
},
|
|
21414
|
+
children: "Pressing it blurs every brand name, mark and company the portal puts on screen — in the lists, on this page, in the heading above a report, and the report itself — so you can put the portal on a call or a projector without showing whose names are in clearance. Nothing is hidden from you: the text is still there and still selectable by the page, it is only blurred on screen. Press the button again to bring the names back."
|
|
21415
|
+
}),
|
|
21416
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
21417
|
+
className: "notice",
|
|
21418
|
+
style: {
|
|
21419
|
+
marginTop: 14,
|
|
21420
|
+
borderLeftColor: "var(--tone-medium)"
|
|
21421
|
+
},
|
|
21422
|
+
children: [(0, import_jsx_runtime.jsx)("b", {
|
|
21423
|
+
style: { color: "var(--text-strong)" },
|
|
21424
|
+
children: "An open report blurs completely"
|
|
21425
|
+
}), (0, import_jsx_runtime.jsx)("p", {
|
|
21365
21426
|
style: {
|
|
21366
|
-
margin: "
|
|
21367
|
-
color: "var(--text-muted)"
|
|
21368
|
-
fontSize: 13.5
|
|
21427
|
+
margin: "6px 0 0",
|
|
21428
|
+
color: "var(--text-muted)"
|
|
21369
21429
|
},
|
|
21370
|
-
children: "
|
|
21371
|
-
})
|
|
21372
|
-
|
|
21373
|
-
|
|
21374
|
-
(0, import_jsx_runtime.jsxs)("div", {
|
|
21375
|
-
className: "notice quiet",
|
|
21376
|
-
style: { marginTop: 26 },
|
|
21377
|
-
children: [(0, import_jsx_runtime.jsx)("b", {
|
|
21378
|
-
style: { color: "var(--text-strong)" },
|
|
21379
|
-
children: "These two settings stay on this computer"
|
|
21380
|
-
}), (0, import_jsx_runtime.jsxs)("p", {
|
|
21430
|
+
children: "A report is a separate document held inside the page, and it can only be covered whole. With a report open, the button blurs all of it rather than just the names in it. That is deliberate — it is the safer way round for a screen you are sharing."
|
|
21431
|
+
})]
|
|
21432
|
+
}),
|
|
21433
|
+
(0, import_jsx_runtime.jsx)("p", {
|
|
21381
21434
|
style: {
|
|
21382
|
-
margin: "
|
|
21383
|
-
color: "var(--text-muted)"
|
|
21435
|
+
margin: "10px 0 0",
|
|
21436
|
+
color: "var(--text-muted)",
|
|
21437
|
+
fontSize: 13.5
|
|
21384
21438
|
},
|
|
21385
|
-
children:
|
|
21386
|
-
})
|
|
21387
|
-
|
|
21388
|
-
|
|
21389
|
-
|
|
21390
|
-
|
|
21439
|
+
children: "It starts switched off every time you open the portal, so reloading the page brings the names back whether you meant it to or not. Turn it on again before you share."
|
|
21440
|
+
})
|
|
21441
|
+
]
|
|
21442
|
+
}),
|
|
21443
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
21444
|
+
className: "notice quiet",
|
|
21445
|
+
style: { marginTop: 26 },
|
|
21446
|
+
children: [(0, import_jsx_runtime.jsx)("b", {
|
|
21447
|
+
style: { color: "var(--text-strong)" },
|
|
21448
|
+
children: "These two settings stay on this computer"
|
|
21449
|
+
}), (0, import_jsx_runtime.jsxs)("p", {
|
|
21450
|
+
style: {
|
|
21451
|
+
margin: "6px 0 0",
|
|
21452
|
+
color: "var(--text-muted)"
|
|
21453
|
+
},
|
|
21454
|
+
children: [operatorName(ctx.me.brand, { lead: true }), " does not store them against your account. The appearance choice is kept by this browser, so it holds for this computer and this browser only — sign in somewhere else, or use a different browser here, and you will get the light theme again until you set it. The screen-share blur is not kept at all: it lasts until you reload or close the page."]
|
|
21455
|
+
})]
|
|
21456
|
+
})
|
|
21457
|
+
]
|
|
21458
|
+
})]
|
|
21391
21459
|
});
|
|
21392
21460
|
}
|
|
21393
21461
|
function ThemeOption({ label, value, current, onPick }) {
|
|
@@ -21512,74 +21580,103 @@ function StepsPanel({ offer, measuring = false, state = AT_REST, onBlock, onSecr
|
|
|
21512
21580
|
className: "steps-name",
|
|
21513
21581
|
children: offer.name
|
|
21514
21582
|
}),
|
|
21515
|
-
(0, import_jsx_runtime.jsx)("
|
|
21516
|
-
className: "steps",
|
|
21517
|
-
children:
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
|
|
21526
|
-
|
|
21527
|
-
|
|
21528
|
-
|
|
21529
|
-
|
|
21530
|
-
|
|
21531
|
-
|
|
21532
|
-
|
|
21533
|
-
|
|
21534
|
-
|
|
21535
|
-
|
|
21536
|
-
|
|
21537
|
-
|
|
21538
|
-
|
|
21539
|
-
|
|
21540
|
-
|
|
21541
|
-
type: "button",
|
|
21542
|
-
className: `btn-primary${flashed ? " is-copied" : ""}`,
|
|
21543
|
-
"data-step": i,
|
|
21544
|
-
tabIndex: measuring ? -1 : void 0,
|
|
21545
|
-
onClick: () => onSecret?.(i, c),
|
|
21546
|
-
children: flashed ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsx)(Icon, {
|
|
21547
|
-
name: "check",
|
|
21548
|
-
size: 15
|
|
21549
|
-
}), "Copied"] }) : landed ? "Copy again" : c.label
|
|
21550
|
-
})
|
|
21551
|
-
}),
|
|
21552
|
-
landed ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21553
|
-
className: "landed",
|
|
21554
|
-
children: [(0, import_jsx_runtime.jsx)("div", {
|
|
21555
|
-
className: "landed-label",
|
|
21556
|
-
children: "On your clipboard now"
|
|
21557
|
-
}), landed.split("\n").map((line, n) => (0, import_jsx_runtime.jsx)("div", {
|
|
21558
|
-
className: "mono",
|
|
21559
|
-
children: line
|
|
21560
|
-
}, n))]
|
|
21561
|
-
}) : null,
|
|
21562
|
-
!measuring && state.revealedAt === i && state.revealed ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21563
|
-
className: "landed",
|
|
21564
|
-
children: [(0, import_jsx_runtime.jsx)("p", {
|
|
21565
|
-
className: "ai-said",
|
|
21566
|
-
children: "Your browser would not let us copy it. Copy this by hand — it is yours, and it will not be shown again."
|
|
21567
|
-
}), (0, import_jsx_runtime.jsx)("pre", {
|
|
21568
|
-
className: "ai-pre",
|
|
21569
|
-
children: state.revealed
|
|
21570
|
-
})]
|
|
21571
|
-
}) : null
|
|
21572
|
-
] }) : null,
|
|
21573
|
-
s.hint ? (0, import_jsx_runtime.jsx)("div", {
|
|
21574
|
-
className: "step-hint",
|
|
21575
|
-
children: (0, import_jsx_runtime.jsx)(Marked, { text: s.hint })
|
|
21576
|
-
}) : null
|
|
21577
|
-
] }) }, i);
|
|
21578
|
-
})
|
|
21579
|
-
})
|
|
21583
|
+
offer.door === null && offer.altSteps?.length ? (0, import_jsx_runtime.jsx)("p", {
|
|
21584
|
+
className: "steps-unknown",
|
|
21585
|
+
children: "We could not check how this Clearotron lets an assistant in, so both ways are below. Try the first — your assistant will tell you if it needs the other."
|
|
21586
|
+
}) : null,
|
|
21587
|
+
(0, import_jsx_runtime.jsx)(StepList, {
|
|
21588
|
+
steps: offer.steps,
|
|
21589
|
+
offset: 0,
|
|
21590
|
+
measuring,
|
|
21591
|
+
state,
|
|
21592
|
+
onBlock,
|
|
21593
|
+
onSecret
|
|
21594
|
+
}),
|
|
21595
|
+
offer.door === null && offer.altSteps?.length ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21596
|
+
className: "steps-alt",
|
|
21597
|
+
children: [(0, import_jsx_runtime.jsx)("h4", {
|
|
21598
|
+
className: "steps-alt-head",
|
|
21599
|
+
children: "If your assistant asks to be let in another way"
|
|
21600
|
+
}), (0, import_jsx_runtime.jsx)(StepList, {
|
|
21601
|
+
steps: offer.altSteps,
|
|
21602
|
+
offset: offer.steps.length,
|
|
21603
|
+
measuring,
|
|
21604
|
+
state,
|
|
21605
|
+
onBlock,
|
|
21606
|
+
onSecret
|
|
21607
|
+
})]
|
|
21608
|
+
}) : null
|
|
21580
21609
|
]
|
|
21581
21610
|
});
|
|
21582
21611
|
}
|
|
21612
|
+
function StepList({ steps, offset, measuring = false, state = AT_REST, onBlock, onSecret }) {
|
|
21613
|
+
return (0, import_jsx_runtime.jsx)("ol", {
|
|
21614
|
+
className: "steps",
|
|
21615
|
+
children: steps.map((s, n) => {
|
|
21616
|
+
const i = n + offset;
|
|
21617
|
+
const c = s.copy;
|
|
21618
|
+
const flashed = !measuring && state.copiedAt === i;
|
|
21619
|
+
const landed = measuring && c?.kind === "secret" ? fill(c, mask("")) : state.landedAt === i ? state.landed : null;
|
|
21620
|
+
return (0, import_jsx_runtime.jsx)("li", { children: (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
21621
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
21622
|
+
className: "step-text",
|
|
21623
|
+
children: (0, import_jsx_runtime.jsx)(Marked, { text: s.text })
|
|
21624
|
+
}),
|
|
21625
|
+
c?.kind === "block" ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21626
|
+
className: "codeblock",
|
|
21627
|
+
children: [(0, import_jsx_runtime.jsx)("pre", { children: c.text }), (0, import_jsx_runtime.jsx)("button", {
|
|
21628
|
+
type: "button",
|
|
21629
|
+
className: `btn-ghost${flashed ? " is-copied" : ""}`,
|
|
21630
|
+
"data-step": i,
|
|
21631
|
+
tabIndex: measuring ? -1 : void 0,
|
|
21632
|
+
onClick: () => onBlock?.(i, c.text),
|
|
21633
|
+
children: flashed ? "✓ Copied" : "Copy"
|
|
21634
|
+
})]
|
|
21635
|
+
}) : null,
|
|
21636
|
+
c?.kind === "secret" ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
21637
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
21638
|
+
className: "secret-btn",
|
|
21639
|
+
children: (0, import_jsx_runtime.jsx)("button", {
|
|
21640
|
+
type: "button",
|
|
21641
|
+
className: `btn-primary${flashed ? " is-copied" : ""}`,
|
|
21642
|
+
"data-step": i,
|
|
21643
|
+
tabIndex: measuring ? -1 : void 0,
|
|
21644
|
+
onClick: () => onSecret?.(i, c),
|
|
21645
|
+
children: flashed ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsx)(Icon, {
|
|
21646
|
+
name: "check",
|
|
21647
|
+
size: 15
|
|
21648
|
+
}), "Copied"] }) : landed ? "Copy again" : c.label
|
|
21649
|
+
})
|
|
21650
|
+
}),
|
|
21651
|
+
landed ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21652
|
+
className: "landed",
|
|
21653
|
+
children: [(0, import_jsx_runtime.jsx)("div", {
|
|
21654
|
+
className: "landed-label",
|
|
21655
|
+
children: "On your clipboard now"
|
|
21656
|
+
}), landed.split("\n").map((line, n) => (0, import_jsx_runtime.jsx)("div", {
|
|
21657
|
+
className: "mono",
|
|
21658
|
+
children: line
|
|
21659
|
+
}, n))]
|
|
21660
|
+
}) : null,
|
|
21661
|
+
!measuring && state.revealedAt === i && state.revealed ? (0, import_jsx_runtime.jsxs)("div", {
|
|
21662
|
+
className: "landed",
|
|
21663
|
+
children: [(0, import_jsx_runtime.jsx)("p", {
|
|
21664
|
+
className: "ai-said",
|
|
21665
|
+
children: "Your browser would not let us copy it. Copy this by hand — it is yours, and it will not be shown again."
|
|
21666
|
+
}), (0, import_jsx_runtime.jsx)("pre", {
|
|
21667
|
+
className: "ai-pre",
|
|
21668
|
+
children: state.revealed
|
|
21669
|
+
})]
|
|
21670
|
+
}) : null
|
|
21671
|
+
] }) : null,
|
|
21672
|
+
s.hint ? (0, import_jsx_runtime.jsx)("div", {
|
|
21673
|
+
className: "step-hint",
|
|
21674
|
+
children: (0, import_jsx_runtime.jsx)(Marked, { text: s.hint })
|
|
21675
|
+
}) : null
|
|
21676
|
+
] }) }, i);
|
|
21677
|
+
})
|
|
21678
|
+
});
|
|
21679
|
+
}
|
|
21583
21680
|
function NotOnline() {
|
|
21584
21681
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
21585
21682
|
className: "notice ai-none",
|
|
@@ -21664,17 +21761,9 @@ function UseYourAI({ ctx }) {
|
|
|
21664
21761
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
21665
21762
|
className: "screen ai-screen",
|
|
21666
21763
|
children: [
|
|
21667
|
-
(0, import_jsx_runtime.jsx)(
|
|
21668
|
-
|
|
21669
|
-
|
|
21670
|
-
}),
|
|
21671
|
-
(0, import_jsx_runtime.jsx)("h1", {
|
|
21672
|
-
className: "ai-title",
|
|
21673
|
-
children: "Use your own AI"
|
|
21674
|
-
}),
|
|
21675
|
-
(0, import_jsx_runtime.jsx)("p", {
|
|
21676
|
-
className: "ai-lead",
|
|
21677
|
-
children: "Run and interrogate clearances from the assistant you already use — by voice, by email, or just by asking."
|
|
21764
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
21765
|
+
title: "Use your own AI",
|
|
21766
|
+
lede: "Run and interrogate clearances from the assistant you already use — by voice, by email, or just by asking."
|
|
21678
21767
|
}),
|
|
21679
21768
|
(0, import_jsx_runtime.jsxs)("section", {
|
|
21680
21769
|
className: "ctx-card ai-can",
|
|
@@ -21920,7 +22009,6 @@ function Profile({ ctx }) {
|
|
|
21920
22009
|
useUnsaved(dirty);
|
|
21921
22010
|
if (needsOwner || result?.kind === "pickAccount") return (0, import_jsx_runtime.jsx)(CompanyGate, {
|
|
21922
22011
|
ctx,
|
|
21923
|
-
eyebrow: "Company",
|
|
21924
22012
|
heading: "Profile",
|
|
21925
22013
|
line: "Pick a company to see its profile."
|
|
21926
22014
|
});
|
|
@@ -22472,7 +22560,6 @@ function Projects({ ctx }) {
|
|
|
22472
22560
|
const projects = result?.kind === "ok" ? result.value : [];
|
|
22473
22561
|
if (needsOwner || result?.kind === "pickAccount") return (0, import_jsx_runtime.jsx)(CompanyGate, {
|
|
22474
22562
|
ctx,
|
|
22475
|
-
eyebrow: "Company",
|
|
22476
22563
|
heading: "Projects",
|
|
22477
22564
|
line: "Pick a company to see its projects."
|
|
22478
22565
|
});
|
|
@@ -23685,54 +23772,29 @@ function PeopleAccess({ ctx }) {
|
|
|
23685
23772
|
const v = result.value;
|
|
23686
23773
|
const broken = v.people.filter((p) => p.dangling.length > 0);
|
|
23687
23774
|
const where = ctx.organisations.length === 1 ? `at ${ctx.organisations[0]?.name ?? ""}` : "here";
|
|
23688
|
-
return (0, import_jsx_runtime.
|
|
23775
|
+
return (0, import_jsx_runtime.jsx)("div", {
|
|
23689
23776
|
className: "screen",
|
|
23690
|
-
children:
|
|
23691
|
-
className: "eyebrow",
|
|
23692
|
-
children: "People"
|
|
23693
|
-
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
23777
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
23694
23778
|
className: "measure",
|
|
23695
23779
|
style: { "--screen-measure": "900px" },
|
|
23696
23780
|
children: [
|
|
23697
|
-
(0, import_jsx_runtime.
|
|
23698
|
-
|
|
23699
|
-
|
|
23700
|
-
|
|
23701
|
-
|
|
23702
|
-
|
|
23703
|
-
|
|
23704
|
-
|
|
23705
|
-
|
|
23706
|
-
|
|
23707
|
-
|
|
23708
|
-
fontSize: 27,
|
|
23709
|
-
margin: "0 0 4px",
|
|
23710
|
-
color: "var(--text-strong)"
|
|
23711
|
-
},
|
|
23712
|
-
children: "People"
|
|
23713
|
-
}), (0, import_jsx_runtime.jsxs)("p", {
|
|
23714
|
-
style: {
|
|
23715
|
-
margin: 0,
|
|
23716
|
-
color: "var(--text-muted)",
|
|
23717
|
-
fontSize: 14.5
|
|
23718
|
-
},
|
|
23719
|
-
children: [
|
|
23720
|
-
"Who can use Clearotron ",
|
|
23721
|
-
(0, import_jsx_runtime.jsx)("span", {
|
|
23722
|
-
"data-anon": "mark",
|
|
23723
|
-
children: where
|
|
23724
|
-
}),
|
|
23725
|
-
", what they can do, and which companies they can see."
|
|
23726
|
-
]
|
|
23727
|
-
})]
|
|
23728
|
-
}), (0, import_jsx_runtime.jsx)("button", {
|
|
23781
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
23782
|
+
title: "People",
|
|
23783
|
+
lede: (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
23784
|
+
"Who can use Clearotron ",
|
|
23785
|
+
(0, import_jsx_runtime.jsx)("span", {
|
|
23786
|
+
"data-anon": "mark",
|
|
23787
|
+
children: where
|
|
23788
|
+
}),
|
|
23789
|
+
", what they can do, and which companies they can see."
|
|
23790
|
+
] }),
|
|
23791
|
+
actions: (0, import_jsx_runtime.jsx)("button", {
|
|
23729
23792
|
type: "button",
|
|
23730
23793
|
className: "btn-primary",
|
|
23731
|
-
style: { flex: "none" },
|
|
23732
23794
|
disabled: !v.canAdd,
|
|
23733
23795
|
onClick: () => ctx.go(ADD_PERSON.path),
|
|
23734
23796
|
children: "+ Add a person"
|
|
23735
|
-
})
|
|
23797
|
+
})
|
|
23736
23798
|
}),
|
|
23737
23799
|
v.localSignIn ? (0, import_jsx_runtime.jsx)("div", {
|
|
23738
23800
|
className: "notice quiet",
|
|
@@ -23824,12 +23886,18 @@ function PeopleAccess({ ctx }) {
|
|
|
23824
23886
|
children: [(0, import_jsx_runtime.jsx)("thead", { children: (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
23825
23887
|
(0, import_jsx_runtime.jsx)("th", { children: "Person" }),
|
|
23826
23888
|
(0, import_jsx_runtime.jsx)("th", { children: "Permissions" }),
|
|
23827
|
-
(0, import_jsx_runtime.jsx)("th", { children: "Access to" })
|
|
23889
|
+
(0, import_jsx_runtime.jsx)("th", { children: "Access to" }),
|
|
23890
|
+
(0, import_jsx_runtime.jsx)("th", { "aria-label": "Change or remove" })
|
|
23828
23891
|
] }) }), (0, import_jsx_runtime.jsx)("tbody", { children: v.people.length === 0 ? (0, import_jsx_runtime.jsx)("tr", { children: (0, import_jsx_runtime.jsx)("td", {
|
|
23829
|
-
colSpan:
|
|
23892
|
+
colSpan: 4,
|
|
23830
23893
|
style: { color: "var(--text-muted)" },
|
|
23831
23894
|
children: "Nobody has been given access yet."
|
|
23832
|
-
}) }) : v.people.map((p) => (0, import_jsx_runtime.jsx)(Row, {
|
|
23895
|
+
}) }) : v.people.map((p) => (0, import_jsx_runtime.jsx)(Row, {
|
|
23896
|
+
person: p,
|
|
23897
|
+
you: p.email.toLowerCase() === ctx.me.email.toLowerCase(),
|
|
23898
|
+
canModify: !v.localSignIn,
|
|
23899
|
+
onModify: () => ctx.go(`${MODIFY_PERSON.path}?email=${encodeURIComponent(p.email)}`)
|
|
23900
|
+
}, p.email)) })]
|
|
23833
23901
|
})
|
|
23834
23902
|
}),
|
|
23835
23903
|
v.grantsFile ? (0, import_jsx_runtime.jsxs)("p", {
|
|
@@ -23862,7 +23930,7 @@ function PeopleAccess({ ctx }) {
|
|
|
23862
23930
|
}) : null,
|
|
23863
23931
|
(0, import_jsx_runtime.jsx)(Observed, { result: observed })
|
|
23864
23932
|
]
|
|
23865
|
-
})
|
|
23933
|
+
})
|
|
23866
23934
|
});
|
|
23867
23935
|
}
|
|
23868
23936
|
function Observed({ result }) {
|
|
@@ -23958,11 +24026,11 @@ function Observed({ result }) {
|
|
|
23958
24026
|
]
|
|
23959
24027
|
});
|
|
23960
24028
|
}
|
|
23961
|
-
function Row({ person }) {
|
|
24029
|
+
function Row({ person, you, canModify, onModify }) {
|
|
23962
24030
|
const chips = accessChips(person.access);
|
|
23963
24031
|
const viewOnly = !person.permissions.run && !person.permissions.manage;
|
|
23964
24032
|
return (0, import_jsx_runtime.jsxs)("tr", { children: [
|
|
23965
|
-
(0, import_jsx_runtime.
|
|
24033
|
+
(0, import_jsx_runtime.jsxs)("td", { children: [(0, import_jsx_runtime.jsx)("span", {
|
|
23966
24034
|
style: {
|
|
23967
24035
|
fontWeight: 700,
|
|
23968
24036
|
color: "var(--text-strong)",
|
|
@@ -23970,7 +24038,15 @@ function Row({ person }) {
|
|
|
23970
24038
|
},
|
|
23971
24039
|
"data-anon": "mark",
|
|
23972
24040
|
children: person.email
|
|
23973
|
-
})
|
|
24041
|
+
}), you ? (0, import_jsx_runtime.jsx)("span", {
|
|
24042
|
+
className: "pill",
|
|
24043
|
+
style: {
|
|
24044
|
+
fontSize: 10.5,
|
|
24045
|
+
padding: "1px 7px",
|
|
24046
|
+
marginLeft: 7
|
|
24047
|
+
},
|
|
24048
|
+
children: "You"
|
|
24049
|
+
}) : null] }),
|
|
23974
24050
|
(0, import_jsx_runtime.jsx)("td", {
|
|
23975
24051
|
style: { color: viewOnly ? "var(--text-muted)" : "var(--text-strong)" },
|
|
23976
24052
|
children: person.listed === false ? (0, import_jsx_runtime.jsx)("span", {
|
|
@@ -23992,7 +24068,24 @@ function Row({ person }) {
|
|
|
23992
24068
|
}) : (0, import_jsx_runtime.jsx)("span", {
|
|
23993
24069
|
style: { color: "var(--text-muted)" },
|
|
23994
24070
|
children: "Nothing yet — signed in, and given no access."
|
|
23995
|
-
}) })
|
|
24071
|
+
}) }),
|
|
24072
|
+
(0, import_jsx_runtime.jsx)("td", {
|
|
24073
|
+
style: {
|
|
24074
|
+
textAlign: "right",
|
|
24075
|
+
whiteSpace: "nowrap"
|
|
24076
|
+
},
|
|
24077
|
+
children: you ? null : (0, import_jsx_runtime.jsx)("button", {
|
|
24078
|
+
type: "button",
|
|
24079
|
+
className: "pill",
|
|
24080
|
+
disabled: !canModify,
|
|
24081
|
+
style: {
|
|
24082
|
+
cursor: canModify ? "pointer" : "default",
|
|
24083
|
+
fontSize: 12
|
|
24084
|
+
},
|
|
24085
|
+
onClick: onModify,
|
|
24086
|
+
children: "Modify"
|
|
24087
|
+
})
|
|
24088
|
+
})
|
|
23996
24089
|
] });
|
|
23997
24090
|
}
|
|
23998
24091
|
//#endregion
|
|
@@ -24020,22 +24113,12 @@ function GiveAccess({ ctx }) {
|
|
|
24020
24113
|
(0, import_react.useEffect)(() => {
|
|
24021
24114
|
if (saved && !kept) ctx.go(PEOPLE.path);
|
|
24022
24115
|
}, [saved, kept]);
|
|
24023
|
-
if (view && isOk(view) && !view.value.canAdd) return (0, import_jsx_runtime.
|
|
24116
|
+
if (view && isOk(view) && !view.value.canAdd) return (0, import_jsx_runtime.jsx)("div", {
|
|
24024
24117
|
className: "screen",
|
|
24025
|
-
children:
|
|
24026
|
-
className: "eyebrow",
|
|
24027
|
-
children: "People"
|
|
24028
|
-
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
24118
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
24029
24119
|
className: "measure",
|
|
24030
24120
|
style: { "--screen-measure": "640px" },
|
|
24031
|
-
children: [(0, import_jsx_runtime.jsx)("
|
|
24032
|
-
style: {
|
|
24033
|
-
fontSize: 27,
|
|
24034
|
-
margin: "4px 0 12px",
|
|
24035
|
-
color: "var(--text-strong)"
|
|
24036
|
-
},
|
|
24037
|
-
children: "Give someone access to Clearotron"
|
|
24038
|
-
}), (0, import_jsx_runtime.jsx)("div", {
|
|
24121
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, { title: "Give someone access to Clearotron" }), (0, import_jsx_runtime.jsx)("div", {
|
|
24039
24122
|
className: "notice quiet",
|
|
24040
24123
|
children: (0, import_jsx_runtime.jsxs)("p", {
|
|
24041
24124
|
style: {
|
|
@@ -24059,7 +24142,7 @@ function GiveAccess({ ctx }) {
|
|
|
24059
24142
|
]
|
|
24060
24143
|
})
|
|
24061
24144
|
})]
|
|
24062
|
-
})
|
|
24145
|
+
})
|
|
24063
24146
|
});
|
|
24064
24147
|
const holdsEverything = ctx.me.access.some((a) => a.kind === "everything");
|
|
24065
24148
|
const wholeOrgs = new Set(ctx.me.genericOrgs);
|
|
@@ -24110,31 +24193,16 @@ function GiveAccess({ ctx }) {
|
|
|
24110
24193
|
setBusy(false);
|
|
24111
24194
|
}
|
|
24112
24195
|
};
|
|
24113
|
-
const failure = result && !isOk(result) ? result.kind === "conflict" ? "This Clearotron now signs in one person, so nobody can be added. Nothing was saved." : result.kind === "notFound" ? "You can only give access to what you have access to yourself. Nothing was saved." : result.kind === "reject" ? result.errors.join(" ") : saveFailureText(result, "That could not be saved. Nothing was changed.") : null;
|
|
24114
|
-
return (0, import_jsx_runtime.
|
|
24196
|
+
const failure = result && !isOk(result) ? result.kind === "gate" && result.detail?.code === "local_sign_in" ? "This Clearotron now signs in one person, so nobody can be added. Nothing was saved." : result.kind === "conflict" ? "This Clearotron now signs in one person, so nobody can be added. Nothing was saved." : result.kind === "notFound" ? "You can only give access to what you have access to yourself. Nothing was saved." : result.kind === "reject" ? result.errors.join(" ") : saveFailureText(result, "That could not be saved. Nothing was changed.") : null;
|
|
24197
|
+
return (0, import_jsx_runtime.jsx)("div", {
|
|
24115
24198
|
className: "screen",
|
|
24116
|
-
children:
|
|
24117
|
-
className: "eyebrow",
|
|
24118
|
-
children: "People"
|
|
24119
|
-
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
24199
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
24120
24200
|
className: "measure",
|
|
24121
24201
|
style: { "--screen-measure": "640px" },
|
|
24122
24202
|
children: [
|
|
24123
|
-
(0, import_jsx_runtime.jsx)(
|
|
24124
|
-
|
|
24125
|
-
|
|
24126
|
-
margin: "4px 0 4px",
|
|
24127
|
-
color: "var(--text-strong)"
|
|
24128
|
-
},
|
|
24129
|
-
children: "Give someone access to Clearotron"
|
|
24130
|
-
}),
|
|
24131
|
-
(0, import_jsx_runtime.jsx)("p", {
|
|
24132
|
-
style: {
|
|
24133
|
-
margin: "0 0 22px",
|
|
24134
|
-
color: "var(--text-muted)",
|
|
24135
|
-
fontSize: 14.5
|
|
24136
|
-
},
|
|
24137
|
-
children: "Enter their email, choose what they can see and do, then save. They sign in the same way you do."
|
|
24203
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
24204
|
+
title: "Give someone access to Clearotron",
|
|
24205
|
+
lede: "Enter their email, choose what they can see and do, then save. They sign in the same way you do."
|
|
24138
24206
|
}),
|
|
24139
24207
|
(0, import_jsx_runtime.jsx)("label", {
|
|
24140
24208
|
className: "field-label",
|
|
@@ -24163,7 +24231,7 @@ function GiveAccess({ ctx }) {
|
|
|
24163
24231
|
gap: 8,
|
|
24164
24232
|
marginBottom: 6
|
|
24165
24233
|
},
|
|
24166
|
-
children: [(0, import_jsx_runtime.jsx)(Lever, {
|
|
24234
|
+
children: [(0, import_jsx_runtime.jsx)(Lever$1, {
|
|
24167
24235
|
on: permissions.run,
|
|
24168
24236
|
title: "Run clearances",
|
|
24169
24237
|
line: "Start and stop clearances on the companies they can see.",
|
|
@@ -24172,7 +24240,7 @@ function GiveAccess({ ctx }) {
|
|
|
24172
24240
|
...p,
|
|
24173
24241
|
run: !p.run
|
|
24174
24242
|
}))
|
|
24175
|
-
}), (0, import_jsx_runtime.jsx)(Lever, {
|
|
24243
|
+
}), (0, import_jsx_runtime.jsx)(Lever$1, {
|
|
24176
24244
|
on: permissions.manage,
|
|
24177
24245
|
title: "Manage",
|
|
24178
24246
|
line: "Add companies, add people and change settings for the companies they can see.",
|
|
@@ -24202,7 +24270,7 @@ function GiveAccess({ ctx }) {
|
|
|
24202
24270
|
gap: 6,
|
|
24203
24271
|
marginBottom: 8
|
|
24204
24272
|
},
|
|
24205
|
-
children: [holdsEverything ? (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24273
|
+
children: [holdsEverything ? (0, import_jsx_runtime.jsx)(AttachRow$1, {
|
|
24206
24274
|
on: chosen.everything,
|
|
24207
24275
|
name: "Everything on this Clearotron",
|
|
24208
24276
|
line: "all organisations and companies, including ones added later",
|
|
@@ -24213,7 +24281,7 @@ function GiveAccess({ ctx }) {
|
|
|
24213
24281
|
}))
|
|
24214
24282
|
}) : null, tree.map((t) => (0, import_jsx_runtime.jsxs)("div", {
|
|
24215
24283
|
style: { display: "contents" },
|
|
24216
|
-
children: [t.whole ? (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24284
|
+
children: [t.whole ? (0, import_jsx_runtime.jsx)(AttachRow$1, {
|
|
24217
24285
|
on: chosen.everything || chosen.orgs.has(t.org.key),
|
|
24218
24286
|
implied: chosen.everything,
|
|
24219
24287
|
name: t.org.name,
|
|
@@ -24223,7 +24291,7 @@ function GiveAccess({ ctx }) {
|
|
|
24223
24291
|
...c,
|
|
24224
24292
|
orgs: toggle(c.orgs, t.org.key)
|
|
24225
24293
|
}))
|
|
24226
|
-
}) : null, t.companies.map((k) => (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24294
|
+
}) : null, t.companies.map((k) => (0, import_jsx_runtime.jsx)(AttachRow$1, {
|
|
24227
24295
|
sub: t.whole,
|
|
24228
24296
|
on: covered(k),
|
|
24229
24297
|
implied: chosen.everything || chosen.orgs.has(t.org.key),
|
|
@@ -24319,10 +24387,10 @@ function GiveAccess({ ctx }) {
|
|
|
24319
24387
|
})] })
|
|
24320
24388
|
})
|
|
24321
24389
|
]
|
|
24322
|
-
})
|
|
24390
|
+
})
|
|
24323
24391
|
});
|
|
24324
24392
|
}
|
|
24325
|
-
function Lever({ on, title, line, disabled, onToggle }) {
|
|
24393
|
+
function Lever$1({ on, title, line, disabled, onToggle }) {
|
|
24326
24394
|
return (0, import_jsx_runtime.jsxs)("button", {
|
|
24327
24395
|
type: "button",
|
|
24328
24396
|
className: on ? "lever lever-on" : "lever",
|
|
@@ -24349,7 +24417,7 @@ function Lever({ on, title, line, disabled, onToggle }) {
|
|
|
24349
24417
|
})]
|
|
24350
24418
|
});
|
|
24351
24419
|
}
|
|
24352
|
-
function AttachRow({ on, implied = false, sub = false, name, line, disabled, onToggle }) {
|
|
24420
|
+
function AttachRow$1({ on, implied = false, sub = false, name, line, disabled, onToggle }) {
|
|
24353
24421
|
return (0, import_jsx_runtime.jsxs)("button", {
|
|
24354
24422
|
type: "button",
|
|
24355
24423
|
className: `attach-row${on ? " on" : ""}${sub ? " sub" : ""}`,
|
|
@@ -24374,101 +24442,604 @@ function AttachRow({ on, implied = false, sub = false, name, line, disabled, onT
|
|
|
24374
24442
|
});
|
|
24375
24443
|
}
|
|
24376
24444
|
//#endregion
|
|
24377
|
-
//#region src/screens/
|
|
24378
|
-
var
|
|
24379
|
-
|
|
24380
|
-
|
|
24381
|
-
|
|
24382
|
-
|
|
24383
|
-
|
|
24384
|
-
|
|
24385
|
-
|
|
24386
|
-
|
|
24387
|
-
|
|
24388
|
-
|
|
24389
|
-
return () => {
|
|
24390
|
-
live = false;
|
|
24391
|
-
};
|
|
24392
|
-
}, []);
|
|
24393
|
-
if (failed) return (0, import_jsx_runtime.jsxs)("section", {
|
|
24394
|
-
className: "screen",
|
|
24395
|
-
children: [
|
|
24396
|
-
(0, import_jsx_runtime.jsx)("h1", { children: "About" }),
|
|
24397
|
-
(0, import_jsx_runtime.jsx)("p", { children: "This deployment could not report which build it is running. That is a fault, not a configuration choice — the source offer below is incomplete without it." }),
|
|
24398
|
-
(0, import_jsx_runtime.jsxs)("p", { children: ["Source: ", (0, import_jsx_runtime.jsx)("a", {
|
|
24399
|
-
href: "https://github.com/CordilleraSarl/Clearotron",
|
|
24400
|
-
children: "github.com/CordilleraSarl/Clearotron"
|
|
24401
|
-
})] })
|
|
24402
|
-
]
|
|
24403
|
-
});
|
|
24404
|
-
if (!info) return (0, import_jsx_runtime.jsxs)("section", {
|
|
24445
|
+
//#region src/screens/ModifyAccess.tsx
|
|
24446
|
+
var emailInQuery = () => (new URLSearchParams(window.location.search).get("email") ?? "").trim().toLowerCase();
|
|
24447
|
+
var heldBy = (person) => ({
|
|
24448
|
+
orgs: new Set(person.access.filter((a) => a.kind === "organisation").map((a) => a.key)),
|
|
24449
|
+
companies: new Set(person.access.filter((a) => a.kind === "company").map((a) => a.key))
|
|
24450
|
+
});
|
|
24451
|
+
var sameSet = (a, b) => a.size === b.size && [...a].every((k) => b.has(k));
|
|
24452
|
+
function ModifyAccess({ ctx }) {
|
|
24453
|
+
const email = emailInQuery();
|
|
24454
|
+
const { result: view } = useLoad(() => api.adminAccess(), []);
|
|
24455
|
+
if (!view) return (0, import_jsx_runtime.jsx)("div", { className: "screen" });
|
|
24456
|
+
if (!isOk(view)) return (0, import_jsx_runtime.jsx)("div", {
|
|
24405
24457
|
className: "screen",
|
|
24406
|
-
children:
|
|
24458
|
+
children: (0, import_jsx_runtime.jsx)("div", {
|
|
24459
|
+
className: "empty",
|
|
24460
|
+
children: (0, import_jsx_runtime.jsx)("p", { children: "This page is not available." })
|
|
24461
|
+
})
|
|
24407
24462
|
});
|
|
24408
|
-
const
|
|
24409
|
-
return (0, import_jsx_runtime.
|
|
24463
|
+
const person = view.value.people.find((p) => p.email.toLowerCase() === email) ?? null;
|
|
24464
|
+
if (!person) return (0, import_jsx_runtime.jsx)("div", {
|
|
24410
24465
|
className: "screen",
|
|
24411
|
-
children:
|
|
24412
|
-
|
|
24413
|
-
|
|
24414
|
-
|
|
24415
|
-
(0, import_jsx_runtime.
|
|
24416
|
-
(0, import_jsx_runtime.jsx)("
|
|
24417
|
-
|
|
24418
|
-
|
|
24419
|
-
|
|
24420
|
-
|
|
24421
|
-
|
|
24422
|
-
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
children: info.sourceUrl
|
|
24426
|
-
}), !info.commit && (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [" ", (0, import_jsx_runtime.jsx)("strong", { children: "This links to the repository, not to the exact build you are using — this deployment could not report its commit." })] })] }),
|
|
24427
|
-
(0, import_jsx_runtime.jsx)("dt", { children: "Licence" }),
|
|
24428
|
-
(0, import_jsx_runtime.jsxs)("dd", { children: [
|
|
24429
|
-
info.license ?? "not reported",
|
|
24430
|
-
" — ",
|
|
24431
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
24432
|
-
href: LICENCE_URL,
|
|
24433
|
-
rel: "noreferrer",
|
|
24434
|
-
children: "full text"
|
|
24466
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
24467
|
+
className: "measure",
|
|
24468
|
+
style: { "--screen-measure": "640px" },
|
|
24469
|
+
children: [
|
|
24470
|
+
(0, import_jsx_runtime.jsx)(PageHeader, { title: "Modify access" }),
|
|
24471
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24472
|
+
className: "notice quiet",
|
|
24473
|
+
children: (0, import_jsx_runtime.jsx)("p", {
|
|
24474
|
+
style: {
|
|
24475
|
+
margin: 0,
|
|
24476
|
+
fontSize: 13.5,
|
|
24477
|
+
color: "var(--text-muted)"
|
|
24478
|
+
},
|
|
24479
|
+
children: "Nobody with that address has access you can see. They may have been removed, or their access may be somewhere you cannot reach."
|
|
24435
24480
|
})
|
|
24436
|
-
] }),
|
|
24437
|
-
(0, import_jsx_runtime.jsx)("dt", { children: "Copyright" }),
|
|
24438
|
-
(0, import_jsx_runtime.jsx)("dd", { children: info.copyright })
|
|
24439
|
-
] }),
|
|
24440
|
-
(0, import_jsx_runtime.jsxs)("p", { children: [
|
|
24441
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
24442
|
-
href: `${info.sourceRepo}/blob/main/LICENSE`,
|
|
24443
|
-
rel: "noreferrer",
|
|
24444
|
-
children: "Licence"
|
|
24445
|
-
}),
|
|
24446
|
-
" · ",
|
|
24447
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
24448
|
-
href: `${info.sourceRepo}/blob/main/NOTICES.md`,
|
|
24449
|
-
rel: "noreferrer",
|
|
24450
|
-
children: "Notices"
|
|
24451
|
-
}),
|
|
24452
|
-
" · ",
|
|
24453
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
24454
|
-
href: `${info.sourceRepo}/blob/main/TRADEMARKS.md`,
|
|
24455
|
-
rel: "noreferrer",
|
|
24456
|
-
children: "Trademarks policy"
|
|
24457
|
-
}),
|
|
24458
|
-
" · ",
|
|
24459
|
-
(0, import_jsx_runtime.jsx)("a", {
|
|
24460
|
-
href: `${info.sourceRepo}/blob/main/CONTRIBUTING.md`,
|
|
24461
|
-
rel: "noreferrer",
|
|
24462
|
-
children: "Contributing"
|
|
24463
24481
|
}),
|
|
24464
|
-
|
|
24465
|
-
|
|
24466
|
-
|
|
24467
|
-
|
|
24468
|
-
|
|
24469
|
-
|
|
24470
|
-
|
|
24471
|
-
|
|
24482
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24483
|
+
style: { marginTop: 16 },
|
|
24484
|
+
children: (0, import_jsx_runtime.jsx)("button", {
|
|
24485
|
+
type: "button",
|
|
24486
|
+
className: "btn-ghost",
|
|
24487
|
+
onClick: () => ctx.go(PEOPLE.path),
|
|
24488
|
+
children: "Back to People"
|
|
24489
|
+
})
|
|
24490
|
+
})
|
|
24491
|
+
]
|
|
24492
|
+
})
|
|
24493
|
+
});
|
|
24494
|
+
return (0, import_jsx_runtime.jsx)(Form, {
|
|
24495
|
+
ctx,
|
|
24496
|
+
person,
|
|
24497
|
+
view: view.value
|
|
24498
|
+
}, person.email);
|
|
24499
|
+
}
|
|
24500
|
+
function Form({ ctx, person, view }) {
|
|
24501
|
+
const readOnlyPeople = view.localSignIn;
|
|
24502
|
+
const held = heldBy(person);
|
|
24503
|
+
const [permissions, setPermissions] = (0, import_react.useState)(person.permissions);
|
|
24504
|
+
const [chosen, setChosen] = (0, import_react.useState)(held);
|
|
24505
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
24506
|
+
const [confirming, setConfirming] = (0, import_react.useState)(false);
|
|
24507
|
+
const [saved, setSaved] = (0, import_react.useState)(null);
|
|
24508
|
+
const [gone, setGone] = (0, import_react.useState)(null);
|
|
24509
|
+
const whole = person.covered === true;
|
|
24510
|
+
const holdsEverything = person.access.some((a) => a.kind === "everything");
|
|
24511
|
+
const orgName = (key) => ctx.organisations.find((o) => o.key === key)?.name ?? key;
|
|
24512
|
+
const wholeOrgs = new Set(ctx.me.genericOrgs);
|
|
24513
|
+
const companiesIn = (org) => ctx.ownerKeys.filter((k) => !isGenericKey(k) && ctx.orgOf(k) === org);
|
|
24514
|
+
const tree = ctx.organisations.map((o) => ({
|
|
24515
|
+
org: o,
|
|
24516
|
+
whole: wholeOrgs.has(o.key),
|
|
24517
|
+
companies: companiesIn(o.key)
|
|
24518
|
+
})).filter((t) => t.whole || t.companies.length > 0);
|
|
24519
|
+
const toggle = (set, key) => {
|
|
24520
|
+
const next = new Set(set);
|
|
24521
|
+
if (next.has(key)) next.delete(key);
|
|
24522
|
+
else next.add(key);
|
|
24523
|
+
return next;
|
|
24524
|
+
};
|
|
24525
|
+
const covered = (company) => chosen.companies.has(company) || chosen.orgs.has(ctx.orgOf(company) ?? "");
|
|
24526
|
+
const soloCompanies = [...chosen.companies].filter((k) => !chosen.orgs.has(ctx.orgOf(k) ?? ""));
|
|
24527
|
+
const dirty = !sameSet(chosen.orgs, held.orgs) || !sameSet(chosen.companies, held.companies) || permissions.run !== person.permissions.run || permissions.manage !== person.permissions.manage;
|
|
24528
|
+
useUnsaved(dirty && saved === null && gone === null);
|
|
24529
|
+
const access = [...[...chosen.orgs].map((key) => ({
|
|
24530
|
+
kind: "organisation",
|
|
24531
|
+
key
|
|
24532
|
+
})), ...soloCompanies.map((key) => ({
|
|
24533
|
+
kind: "company",
|
|
24534
|
+
key
|
|
24535
|
+
}))];
|
|
24536
|
+
const leftWithNothing = access.length === 0;
|
|
24537
|
+
const losing = [...[...held.orgs].filter((k) => !chosen.orgs.has(k)).map(orgName), ...[...held.companies].filter((k) => !covered(k)).map((k) => ctx.ownerName(k))];
|
|
24538
|
+
const sentence = accessSentence({
|
|
24539
|
+
who: person.email,
|
|
24540
|
+
permissions,
|
|
24541
|
+
everything: holdsEverything,
|
|
24542
|
+
organisations: [...chosen.orgs].map(orgName),
|
|
24543
|
+
companies: soloCompanies.map((k) => ({
|
|
24544
|
+
name: ctx.ownerName(k),
|
|
24545
|
+
organisation: orgName(ctx.orgOf(k) ?? "")
|
|
24546
|
+
}))
|
|
24547
|
+
});
|
|
24548
|
+
const save = async () => {
|
|
24549
|
+
setBusy(true);
|
|
24550
|
+
try {
|
|
24551
|
+
setSaved(await api.changePerson({
|
|
24552
|
+
email: person.email,
|
|
24553
|
+
permissions,
|
|
24554
|
+
access
|
|
24555
|
+
}));
|
|
24556
|
+
} finally {
|
|
24557
|
+
setBusy(false);
|
|
24558
|
+
}
|
|
24559
|
+
};
|
|
24560
|
+
const remove = async () => {
|
|
24561
|
+
setBusy(true);
|
|
24562
|
+
try {
|
|
24563
|
+
const r = await api.removePerson({ email: person.email });
|
|
24564
|
+
setGone(r);
|
|
24565
|
+
if (isOk(r)) ctx.go(PEOPLE.path);
|
|
24566
|
+
} finally {
|
|
24567
|
+
setBusy(false);
|
|
24568
|
+
}
|
|
24569
|
+
};
|
|
24570
|
+
const failure = (r) => r === null || isOk(r) ? null : r.kind === "gate" && r.detail?.code === "local_sign_in" ? "This Clearotron now signs in one person, so nobody else can be changed. Nothing was saved." : r.kind === "conflict" ? "This Clearotron now signs in one person, so nobody else can be changed. Nothing was saved." : r.kind === "notFound" ? "That is not access you can change. Nothing was saved." : r.kind === "reject" ? r.errors.join(" ") : saveFailureText(r, "That could not be saved. Nothing was changed.");
|
|
24571
|
+
const problem = failure(saved) ?? failure(gone);
|
|
24572
|
+
const loses = person.access.length ? person.access.map((a) => a.kind === "everything" ? "everything on this Clearotron" : a.name ?? a.key) : [];
|
|
24573
|
+
const holdsKey = (person.keys ?? 0) > 0;
|
|
24574
|
+
const keyStaysLive = holdsKey && view.keysRevocable !== true;
|
|
24575
|
+
const domain = person.email.startsWith("*@") ? person.email.slice(2) : null;
|
|
24576
|
+
return (0, import_jsx_runtime.jsx)("div", {
|
|
24577
|
+
className: "screen",
|
|
24578
|
+
children: (0, import_jsx_runtime.jsxs)("div", {
|
|
24579
|
+
className: "measure",
|
|
24580
|
+
style: { "--screen-measure": "640px" },
|
|
24581
|
+
children: [
|
|
24582
|
+
(0, import_jsx_runtime.jsx)(PageHeader, {
|
|
24583
|
+
title: "Modify access",
|
|
24584
|
+
lede: (0, import_jsx_runtime.jsx)("b", {
|
|
24585
|
+
style: {
|
|
24586
|
+
color: "var(--text-strong)",
|
|
24587
|
+
wordBreak: "break-all"
|
|
24588
|
+
},
|
|
24589
|
+
"data-anon": "mark",
|
|
24590
|
+
children: person.email
|
|
24591
|
+
})
|
|
24592
|
+
}),
|
|
24593
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24594
|
+
className: "field-label",
|
|
24595
|
+
children: "Permissions"
|
|
24596
|
+
}),
|
|
24597
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
24598
|
+
style: {
|
|
24599
|
+
display: "flex",
|
|
24600
|
+
flexDirection: "column",
|
|
24601
|
+
gap: 8,
|
|
24602
|
+
marginBottom: 6
|
|
24603
|
+
},
|
|
24604
|
+
children: [(0, import_jsx_runtime.jsx)(Lever, {
|
|
24605
|
+
on: permissions.run,
|
|
24606
|
+
title: "Run clearances",
|
|
24607
|
+
line: "Start and stop clearances on the companies they can see.",
|
|
24608
|
+
disabled: !whole || busy,
|
|
24609
|
+
onToggle: () => setPermissions((p) => ({
|
|
24610
|
+
...p,
|
|
24611
|
+
run: !p.run
|
|
24612
|
+
}))
|
|
24613
|
+
}), (0, import_jsx_runtime.jsx)(Lever, {
|
|
24614
|
+
on: permissions.manage,
|
|
24615
|
+
title: "Manage",
|
|
24616
|
+
line: "Add companies, add people and change settings for the companies they can see.",
|
|
24617
|
+
disabled: !whole || busy,
|
|
24618
|
+
onToggle: () => setPermissions((p) => ({
|
|
24619
|
+
...p,
|
|
24620
|
+
manage: !p.manage
|
|
24621
|
+
}))
|
|
24622
|
+
})]
|
|
24623
|
+
}),
|
|
24624
|
+
(0, import_jsx_runtime.jsx)("p", {
|
|
24625
|
+
style: {
|
|
24626
|
+
margin: "0 0 22px",
|
|
24627
|
+
fontSize: 12.5,
|
|
24628
|
+
color: "var(--text-faint)"
|
|
24629
|
+
},
|
|
24630
|
+
children: whole ? "Everyone can view reports for the companies they can see. Leave both off for a view-only person." : "They have access you can't see, so only someone who can see all of it can change their permissions."
|
|
24631
|
+
}),
|
|
24632
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24633
|
+
className: "field-label",
|
|
24634
|
+
children: "Access to"
|
|
24635
|
+
}),
|
|
24636
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
24637
|
+
style: {
|
|
24638
|
+
display: "flex",
|
|
24639
|
+
flexDirection: "column",
|
|
24640
|
+
gap: 6,
|
|
24641
|
+
marginBottom: 8
|
|
24642
|
+
},
|
|
24643
|
+
children: [holdsEverything ? (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24644
|
+
on: true,
|
|
24645
|
+
name: "Everything on this Clearotron",
|
|
24646
|
+
line: "all organisations and companies, including ones added later",
|
|
24647
|
+
disabled: true,
|
|
24648
|
+
onToggle: () => {}
|
|
24649
|
+
}) : null, tree.map((t) => (0, import_jsx_runtime.jsxs)("div", {
|
|
24650
|
+
style: { display: "contents" },
|
|
24651
|
+
children: [t.whole ? (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24652
|
+
on: chosen.orgs.has(t.org.key),
|
|
24653
|
+
name: t.org.name,
|
|
24654
|
+
line: "every company in it, including ones added later",
|
|
24655
|
+
disabled: busy,
|
|
24656
|
+
onToggle: () => setChosen((c) => ({
|
|
24657
|
+
...c,
|
|
24658
|
+
orgs: toggle(c.orgs, t.org.key)
|
|
24659
|
+
}))
|
|
24660
|
+
}) : null, t.companies.map((k) => (0, import_jsx_runtime.jsx)(AttachRow, {
|
|
24661
|
+
sub: t.whole,
|
|
24662
|
+
on: covered(k),
|
|
24663
|
+
implied: chosen.orgs.has(t.org.key),
|
|
24664
|
+
name: ctx.ownerName(k),
|
|
24665
|
+
line: t.whole ? "company" : `company in ${t.org.name}`,
|
|
24666
|
+
disabled: busy,
|
|
24667
|
+
onToggle: () => setChosen((c) => ({
|
|
24668
|
+
...c,
|
|
24669
|
+
companies: toggle(c.companies, k)
|
|
24670
|
+
}))
|
|
24671
|
+
}, k))]
|
|
24672
|
+
}, t.org.key))]
|
|
24673
|
+
}),
|
|
24674
|
+
(0, import_jsx_runtime.jsxs)("p", {
|
|
24675
|
+
style: {
|
|
24676
|
+
margin: "0 0 22px",
|
|
24677
|
+
fontSize: 12.5,
|
|
24678
|
+
color: "var(--text-faint)"
|
|
24679
|
+
},
|
|
24680
|
+
children: ["Untick a row to take that access away.", whole ? "" : " You are seeing the part of their access you can reach; the rest is not shown and is not changed."]
|
|
24681
|
+
}),
|
|
24682
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24683
|
+
className: "notice quiet",
|
|
24684
|
+
style: { marginBottom: 18 },
|
|
24685
|
+
children: (0, import_jsx_runtime.jsxs)("p", {
|
|
24686
|
+
style: {
|
|
24687
|
+
margin: 0,
|
|
24688
|
+
fontSize: 13.5,
|
|
24689
|
+
color: "var(--text-muted)"
|
|
24690
|
+
},
|
|
24691
|
+
"data-anon": "mark",
|
|
24692
|
+
children: [sentence, losing.length ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [" ", (0, import_jsx_runtime.jsxs)("b", {
|
|
24693
|
+
style: { color: "var(--text-strong)" },
|
|
24694
|
+
children: [
|
|
24695
|
+
"They lose ",
|
|
24696
|
+
losing.join(", "),
|
|
24697
|
+
"."
|
|
24698
|
+
]
|
|
24699
|
+
})] }) : null]
|
|
24700
|
+
})
|
|
24701
|
+
}),
|
|
24702
|
+
problem ? (0, import_jsx_runtime.jsx)("div", {
|
|
24703
|
+
className: "notice",
|
|
24704
|
+
style: {
|
|
24705
|
+
borderColor: "var(--tone-high)",
|
|
24706
|
+
marginBottom: 14
|
|
24707
|
+
},
|
|
24708
|
+
children: (0, import_jsx_runtime.jsx)("p", {
|
|
24709
|
+
style: {
|
|
24710
|
+
margin: 0,
|
|
24711
|
+
fontSize: 13.5
|
|
24712
|
+
},
|
|
24713
|
+
children: problem
|
|
24714
|
+
})
|
|
24715
|
+
}) : null,
|
|
24716
|
+
saved && isOk(saved) ? (0, import_jsx_runtime.jsx)("div", {
|
|
24717
|
+
className: "notice",
|
|
24718
|
+
style: {
|
|
24719
|
+
borderColor: "var(--tone-medium)",
|
|
24720
|
+
marginBottom: 14
|
|
24721
|
+
},
|
|
24722
|
+
children: (0, import_jsx_runtime.jsxs)("p", {
|
|
24723
|
+
style: {
|
|
24724
|
+
margin: 0,
|
|
24725
|
+
fontSize: 13.5
|
|
24726
|
+
},
|
|
24727
|
+
children: ["Saved. ", saved.value.switchesApplied ? permissionsPhrase(permissions) + "." : (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
24728
|
+
"Their permissions stay as they were: ",
|
|
24729
|
+
permissionsPhrase(person.permissions),
|
|
24730
|
+
". They have access you cannot see, and permissions apply everywhere a person has access."
|
|
24731
|
+
] })]
|
|
24732
|
+
})
|
|
24733
|
+
}) : null,
|
|
24734
|
+
readOnlyPeople ? (0, import_jsx_runtime.jsx)("div", {
|
|
24735
|
+
className: "notice quiet",
|
|
24736
|
+
style: { marginBottom: 14 },
|
|
24737
|
+
children: (0, import_jsx_runtime.jsxs)("p", {
|
|
24738
|
+
style: {
|
|
24739
|
+
margin: 0,
|
|
24740
|
+
fontSize: 13.5,
|
|
24741
|
+
color: "var(--text-muted)"
|
|
24742
|
+
},
|
|
24743
|
+
children: [(0, import_jsx_runtime.jsx)("b", {
|
|
24744
|
+
style: { color: "var(--text-strong)" },
|
|
24745
|
+
children: "This Clearotron signs in one person: you."
|
|
24746
|
+
}), " Nobody else can be changed or removed here. To hold more than one person, put it behind a login system such as your company single sign-on."]
|
|
24747
|
+
})
|
|
24748
|
+
}) : null,
|
|
24749
|
+
(0, import_jsx_runtime.jsxs)("div", {
|
|
24750
|
+
style: {
|
|
24751
|
+
display: "flex",
|
|
24752
|
+
gap: 10,
|
|
24753
|
+
alignItems: "center"
|
|
24754
|
+
},
|
|
24755
|
+
children: [
|
|
24756
|
+
(0, import_jsx_runtime.jsx)("button", {
|
|
24757
|
+
type: "button",
|
|
24758
|
+
className: "btn-primary",
|
|
24759
|
+
disabled: !dirty || busy || leftWithNothing || readOnlyPeople,
|
|
24760
|
+
onClick: () => void save(),
|
|
24761
|
+
children: busy && !confirming ? "Saving…" : "Save changes"
|
|
24762
|
+
}),
|
|
24763
|
+
(0, import_jsx_runtime.jsx)("button", {
|
|
24764
|
+
type: "button",
|
|
24765
|
+
className: "btn-ghost",
|
|
24766
|
+
onClick: () => ctx.go(PEOPLE.path),
|
|
24767
|
+
children: "Cancel"
|
|
24768
|
+
}),
|
|
24769
|
+
leftWithNothing ? (0, import_jsx_runtime.jsx)("span", {
|
|
24770
|
+
style: {
|
|
24771
|
+
fontSize: 12.5,
|
|
24772
|
+
color: "var(--text-faint)"
|
|
24773
|
+
},
|
|
24774
|
+
children: "Nothing is ticked. Leave them at least one, or remove them below."
|
|
24775
|
+
}) : null
|
|
24776
|
+
]
|
|
24777
|
+
}),
|
|
24778
|
+
(0, import_jsx_runtime.jsx)("div", {
|
|
24779
|
+
style: {
|
|
24780
|
+
marginTop: 34,
|
|
24781
|
+
paddingTop: 18,
|
|
24782
|
+
borderTop: "1px solid var(--border-hairline)",
|
|
24783
|
+
display: "flex",
|
|
24784
|
+
flexDirection: "column",
|
|
24785
|
+
gap: 10,
|
|
24786
|
+
alignItems: "flex-start"
|
|
24787
|
+
},
|
|
24788
|
+
children: confirming ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsx)("div", {
|
|
24789
|
+
className: "notice",
|
|
24790
|
+
style: {
|
|
24791
|
+
borderColor: "var(--tone-high)",
|
|
24792
|
+
margin: 0,
|
|
24793
|
+
width: "100%"
|
|
24794
|
+
},
|
|
24795
|
+
children: (0, import_jsx_runtime.jsxs)("p", {
|
|
24796
|
+
style: {
|
|
24797
|
+
margin: 0,
|
|
24798
|
+
fontSize: 13.5
|
|
24799
|
+
},
|
|
24800
|
+
children: [
|
|
24801
|
+
(0, import_jsx_runtime.jsx)("b", {
|
|
24802
|
+
"data-anon": "mark",
|
|
24803
|
+
children: person.email
|
|
24804
|
+
}),
|
|
24805
|
+
" ",
|
|
24806
|
+
whole ? (0, import_jsx_runtime.jsxs)("b", { children: [
|
|
24807
|
+
"loses access to ",
|
|
24808
|
+
loses.length ? loses.join(" and ") : "this Clearotron",
|
|
24809
|
+
" straight away,"
|
|
24810
|
+
] }) : (0, import_jsx_runtime.jsxs)("b", { children: [
|
|
24811
|
+
"loses ",
|
|
24812
|
+
loses.join(" and "),
|
|
24813
|
+
" straight away,"
|
|
24814
|
+
] }),
|
|
24815
|
+
" ",
|
|
24816
|
+
keyStaysLive ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
24817
|
+
"here. Their AI was issued a key this Clearotron cannot withdraw — it was started without a revocation list — so that key keeps working until it expires.",
|
|
24818
|
+
" ",
|
|
24819
|
+
(0, import_jsx_runtime.jsx)("b", {
|
|
24820
|
+
className: "mono",
|
|
24821
|
+
children: "clearotron doctor"
|
|
24822
|
+
}),
|
|
24823
|
+
" reports it.",
|
|
24824
|
+
" "
|
|
24825
|
+
] }) : (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: ["here and through their AI.", " "] }),
|
|
24826
|
+
holdsKey && !keyStaysLive ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
24827
|
+
"Their AI’s key is withdrawn at the same time;",
|
|
24828
|
+
" ",
|
|
24829
|
+
(0, import_jsx_runtime.jsx)("b", {
|
|
24830
|
+
className: "mono",
|
|
24831
|
+
children: "clearotron doctor"
|
|
24832
|
+
}),
|
|
24833
|
+
" says whether the connector has picked it up.",
|
|
24834
|
+
" "
|
|
24835
|
+
] }) : null,
|
|
24836
|
+
whole ? "To stop them reaching your sign-in page, take them off your login system too." : "They keep the access you cannot see.",
|
|
24837
|
+
domain ? (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [" ", (0, import_jsx_runtime.jsxs)("b", { children: [
|
|
24838
|
+
"This takes access away from everyone with an address at ",
|
|
24839
|
+
(0, import_jsx_runtime.jsx)("span", {
|
|
24840
|
+
"data-anon": "mark",
|
|
24841
|
+
children: domain
|
|
24842
|
+
}),
|
|
24843
|
+
"."
|
|
24844
|
+
] })] }) : null
|
|
24845
|
+
]
|
|
24846
|
+
})
|
|
24847
|
+
}), (0, import_jsx_runtime.jsxs)("div", {
|
|
24848
|
+
style: {
|
|
24849
|
+
display: "flex",
|
|
24850
|
+
gap: 8
|
|
24851
|
+
},
|
|
24852
|
+
children: [(0, import_jsx_runtime.jsx)("button", {
|
|
24853
|
+
type: "button",
|
|
24854
|
+
className: "pill",
|
|
24855
|
+
style: {
|
|
24856
|
+
cursor: "pointer",
|
|
24857
|
+
fontSize: 12,
|
|
24858
|
+
borderColor: "var(--tone-high)"
|
|
24859
|
+
},
|
|
24860
|
+
disabled: busy,
|
|
24861
|
+
onClick: () => void remove(),
|
|
24862
|
+
children: busy ? "Working…" : "Confirm — remove"
|
|
24863
|
+
}), (0, import_jsx_runtime.jsx)("button", {
|
|
24864
|
+
type: "button",
|
|
24865
|
+
className: "pill",
|
|
24866
|
+
style: {
|
|
24867
|
+
cursor: "pointer",
|
|
24868
|
+
fontSize: 12
|
|
24869
|
+
},
|
|
24870
|
+
onClick: () => setConfirming(false),
|
|
24871
|
+
children: "Cancel"
|
|
24872
|
+
})]
|
|
24873
|
+
})] }) : (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [(0, import_jsx_runtime.jsx)("button", {
|
|
24874
|
+
type: "button",
|
|
24875
|
+
className: "pill",
|
|
24876
|
+
style: {
|
|
24877
|
+
cursor: readOnlyPeople ? "default" : "pointer",
|
|
24878
|
+
fontSize: 12
|
|
24879
|
+
},
|
|
24880
|
+
disabled: busy || readOnlyPeople,
|
|
24881
|
+
onClick: () => setConfirming(true),
|
|
24882
|
+
children: whole ? domain ? `Remove everyone at ${domain}` : "Remove from Clearotron" : `Remove from ${[...held.orgs].map(orgName).join(", ") || "here"}`
|
|
24883
|
+
}), whole ? null : (0, import_jsx_runtime.jsx)("p", {
|
|
24884
|
+
style: {
|
|
24885
|
+
margin: 0,
|
|
24886
|
+
fontSize: 12.5,
|
|
24887
|
+
color: "var(--text-faint)"
|
|
24888
|
+
},
|
|
24889
|
+
children: "They keep the access you cannot see."
|
|
24890
|
+
})] })
|
|
24891
|
+
})
|
|
24892
|
+
]
|
|
24893
|
+
})
|
|
24894
|
+
});
|
|
24895
|
+
}
|
|
24896
|
+
function Lever({ on, title, line, disabled, onToggle }) {
|
|
24897
|
+
return (0, import_jsx_runtime.jsxs)("button", {
|
|
24898
|
+
type: "button",
|
|
24899
|
+
className: on ? "lever lever-on" : "lever",
|
|
24900
|
+
"aria-pressed": on,
|
|
24901
|
+
disabled,
|
|
24902
|
+
onClick: onToggle,
|
|
24903
|
+
children: [(0, import_jsx_runtime.jsx)("span", { className: on ? "lever-box lever-box-on" : "lever-box" }), (0, import_jsx_runtime.jsxs)("span", {
|
|
24904
|
+
style: { textAlign: "left" },
|
|
24905
|
+
children: [(0, import_jsx_runtime.jsx)("span", {
|
|
24906
|
+
style: {
|
|
24907
|
+
display: "block",
|
|
24908
|
+
fontWeight: 600,
|
|
24909
|
+
color: "var(--text-strong)"
|
|
24910
|
+
},
|
|
24911
|
+
children: title
|
|
24912
|
+
}), (0, import_jsx_runtime.jsx)("span", {
|
|
24913
|
+
style: {
|
|
24914
|
+
display: "block",
|
|
24915
|
+
fontSize: 12.5,
|
|
24916
|
+
color: "var(--text-muted)"
|
|
24917
|
+
},
|
|
24918
|
+
children: line
|
|
24919
|
+
})]
|
|
24920
|
+
})]
|
|
24921
|
+
});
|
|
24922
|
+
}
|
|
24923
|
+
function AttachRow({ on, implied = false, sub = false, name, line, disabled, onToggle }) {
|
|
24924
|
+
return (0, import_jsx_runtime.jsxs)("button", {
|
|
24925
|
+
type: "button",
|
|
24926
|
+
className: `attach-row${on ? " on" : ""}${sub ? " sub" : ""}`,
|
|
24927
|
+
"aria-pressed": on,
|
|
24928
|
+
disabled: disabled || implied,
|
|
24929
|
+
onClick: onToggle,
|
|
24930
|
+
children: [
|
|
24931
|
+
(0, import_jsx_runtime.jsx)("span", { className: on ? "lever-box lever-box-on" : "lever-box" }),
|
|
24932
|
+
(0, import_jsx_runtime.jsx)("span", {
|
|
24933
|
+
style: {
|
|
24934
|
+
color: "var(--text-strong)",
|
|
24935
|
+
fontWeight: sub ? 400 : 600
|
|
24936
|
+
},
|
|
24937
|
+
"data-anon": "mark",
|
|
24938
|
+
children: name
|
|
24939
|
+
}),
|
|
24940
|
+
(0, import_jsx_runtime.jsx)("span", {
|
|
24941
|
+
className: "sub-t",
|
|
24942
|
+
children: line
|
|
24943
|
+
})
|
|
24944
|
+
]
|
|
24945
|
+
});
|
|
24946
|
+
}
|
|
24947
|
+
//#endregion
|
|
24948
|
+
//#region src/screens/About.tsx
|
|
24949
|
+
var LICENCE_URL = "https://www.gnu.org/licenses/agpl-3.0.html";
|
|
24950
|
+
function About() {
|
|
24951
|
+
const [info, setInfo] = (0, import_react.useState)(null);
|
|
24952
|
+
const [failed, setFailed] = (0, import_react.useState)(false);
|
|
24953
|
+
(0, import_react.useEffect)(() => {
|
|
24954
|
+
let live = true;
|
|
24955
|
+
api.about().then((r) => {
|
|
24956
|
+
if (!live) return;
|
|
24957
|
+
if (isOk(r)) setInfo(r.value);
|
|
24958
|
+
else setFailed(true);
|
|
24959
|
+
});
|
|
24960
|
+
return () => {
|
|
24961
|
+
live = false;
|
|
24962
|
+
};
|
|
24963
|
+
}, []);
|
|
24964
|
+
if (failed) return (0, import_jsx_runtime.jsxs)("section", {
|
|
24965
|
+
className: "screen",
|
|
24966
|
+
children: [
|
|
24967
|
+
(0, import_jsx_runtime.jsx)(PageHeader, { title: "About" }),
|
|
24968
|
+
(0, import_jsx_runtime.jsx)("p", { children: "This deployment could not report which build it is running. That is a fault, not a configuration choice — the source offer below is incomplete without it." }),
|
|
24969
|
+
(0, import_jsx_runtime.jsxs)("p", { children: ["Source: ", (0, import_jsx_runtime.jsx)("a", {
|
|
24970
|
+
href: "https://github.com/CordilleraSarl/Clearotron",
|
|
24971
|
+
children: "github.com/CordilleraSarl/Clearotron"
|
|
24972
|
+
})] })
|
|
24973
|
+
]
|
|
24974
|
+
});
|
|
24975
|
+
if (!info) return (0, import_jsx_runtime.jsxs)("section", {
|
|
24976
|
+
className: "screen",
|
|
24977
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, { title: "About" }), (0, import_jsx_runtime.jsx)("p", { children: "Loading…" })]
|
|
24978
|
+
});
|
|
24979
|
+
const shortSha = info.commit ? info.commit.slice(0, 12) : null;
|
|
24980
|
+
return (0, import_jsx_runtime.jsxs)("section", {
|
|
24981
|
+
className: "screen",
|
|
24982
|
+
children: [
|
|
24983
|
+
(0, import_jsx_runtime.jsx)(PageHeader, { title: `About ${info.name}` }),
|
|
24984
|
+
(0, import_jsx_runtime.jsxs)("dl", { children: [
|
|
24985
|
+
(0, import_jsx_runtime.jsx)("dt", { children: "Product" }),
|
|
24986
|
+
(0, import_jsx_runtime.jsxs)("dd", { children: [info.name, info.version ? ` ${info.version}` : ""] }),
|
|
24987
|
+
(0, import_jsx_runtime.jsx)("dt", { children: "Build" }),
|
|
24988
|
+
(0, import_jsx_runtime.jsx)("dd", { children: shortSha ? (0, import_jsx_runtime.jsx)("code", {
|
|
24989
|
+
title: info.commit ?? void 0,
|
|
24990
|
+
children: shortSha
|
|
24991
|
+
}) : (0, import_jsx_runtime.jsx)("span", { children: "not reported by this deployment" }) }),
|
|
24992
|
+
(0, import_jsx_runtime.jsx)("dt", { children: "Source" }),
|
|
24993
|
+
(0, import_jsx_runtime.jsxs)("dd", { children: [(0, import_jsx_runtime.jsx)("a", {
|
|
24994
|
+
href: info.sourceUrl,
|
|
24995
|
+
rel: "noreferrer",
|
|
24996
|
+
children: info.sourceUrl
|
|
24997
|
+
}), !info.commit && (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [" ", (0, import_jsx_runtime.jsx)("strong", { children: "This links to the repository, not to the exact build you are using — this deployment could not report its commit." })] })] }),
|
|
24998
|
+
(0, import_jsx_runtime.jsx)("dt", { children: "Licence" }),
|
|
24999
|
+
(0, import_jsx_runtime.jsxs)("dd", { children: [
|
|
25000
|
+
info.license ?? "not reported",
|
|
25001
|
+
" — ",
|
|
25002
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25003
|
+
href: LICENCE_URL,
|
|
25004
|
+
rel: "noreferrer",
|
|
25005
|
+
children: "full text"
|
|
25006
|
+
})
|
|
25007
|
+
] }),
|
|
25008
|
+
(0, import_jsx_runtime.jsx)("dt", { children: "Copyright" }),
|
|
25009
|
+
(0, import_jsx_runtime.jsx)("dd", { children: info.copyright })
|
|
25010
|
+
] }),
|
|
25011
|
+
(0, import_jsx_runtime.jsxs)("p", { children: [
|
|
25012
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25013
|
+
href: `${info.sourceRepo}/blob/main/LICENSE`,
|
|
25014
|
+
rel: "noreferrer",
|
|
25015
|
+
children: "Licence"
|
|
25016
|
+
}),
|
|
25017
|
+
" · ",
|
|
25018
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25019
|
+
href: `${info.sourceRepo}/blob/main/NOTICES.md`,
|
|
25020
|
+
rel: "noreferrer",
|
|
25021
|
+
children: "Notices"
|
|
25022
|
+
}),
|
|
25023
|
+
" · ",
|
|
25024
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25025
|
+
href: `${info.sourceRepo}/blob/main/TRADEMARKS.md`,
|
|
25026
|
+
rel: "noreferrer",
|
|
25027
|
+
children: "Trademarks policy"
|
|
25028
|
+
}),
|
|
25029
|
+
" · ",
|
|
25030
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25031
|
+
href: `${info.sourceRepo}/blob/main/CONTRIBUTING.md`,
|
|
25032
|
+
rel: "noreferrer",
|
|
25033
|
+
children: "Contributing"
|
|
25034
|
+
}),
|
|
25035
|
+
" · ",
|
|
25036
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
25037
|
+
href: `${info.sourceRepo}/blob/main/SECURITY.md`,
|
|
25038
|
+
rel: "noreferrer",
|
|
25039
|
+
children: "Security"
|
|
25040
|
+
}),
|
|
25041
|
+
" · ",
|
|
25042
|
+
(0, import_jsx_runtime.jsx)("a", {
|
|
24472
25043
|
href: `${info.sourceRepo}/blob/main/CODE_OF_CONDUCT.md`,
|
|
24473
25044
|
rel: "noreferrer",
|
|
24474
25045
|
children: "Code of conduct"
|
|
@@ -24506,41 +25077,27 @@ function About() {
|
|
|
24506
25077
|
function NotYet({ title, phase, what }) {
|
|
24507
25078
|
return (0, import_jsx_runtime.jsxs)("div", {
|
|
24508
25079
|
className: "screen",
|
|
24509
|
-
children: [
|
|
24510
|
-
|
|
24511
|
-
|
|
24512
|
-
children: title
|
|
24513
|
-
}),
|
|
24514
|
-
(0, import_jsx_runtime.jsx)("h1", {
|
|
25080
|
+
children: [(0, import_jsx_runtime.jsx)(PageHeader, { title }), (0, import_jsx_runtime.jsxs)("div", {
|
|
25081
|
+
className: "notice quiet",
|
|
25082
|
+
children: [(0, import_jsx_runtime.jsx)("p", {
|
|
24515
25083
|
style: {
|
|
24516
|
-
|
|
24517
|
-
|
|
24518
|
-
color: "var(--text-strong)"
|
|
25084
|
+
margin: 0,
|
|
25085
|
+
color: "var(--text-muted)"
|
|
24519
25086
|
},
|
|
24520
|
-
children:
|
|
24521
|
-
}),
|
|
24522
|
-
|
|
24523
|
-
|
|
24524
|
-
|
|
24525
|
-
|
|
24526
|
-
|
|
24527
|
-
|
|
24528
|
-
|
|
24529
|
-
|
|
24530
|
-
|
|
24531
|
-
|
|
24532
|
-
|
|
24533
|
-
|
|
24534
|
-
color: "var(--text-faint)"
|
|
24535
|
-
},
|
|
24536
|
-
children: [
|
|
24537
|
-
"Being built — ",
|
|
24538
|
-
phase,
|
|
24539
|
-
"."
|
|
24540
|
-
]
|
|
24541
|
-
})]
|
|
24542
|
-
})
|
|
24543
|
-
]
|
|
25087
|
+
children: what
|
|
25088
|
+
}), (0, import_jsx_runtime.jsxs)("p", {
|
|
25089
|
+
style: {
|
|
25090
|
+
margin: "8px 0 0",
|
|
25091
|
+
fontSize: 13,
|
|
25092
|
+
color: "var(--text-faint)"
|
|
25093
|
+
},
|
|
25094
|
+
children: [
|
|
25095
|
+
"Being built — ",
|
|
25096
|
+
phase,
|
|
25097
|
+
"."
|
|
25098
|
+
]
|
|
25099
|
+
})]
|
|
25100
|
+
})]
|
|
24544
25101
|
});
|
|
24545
25102
|
}
|
|
24546
25103
|
var ownerKey = (ctx) => `${ctx.owner ?? "*"}#${ctx.visit}`;
|
|
@@ -24570,6 +25127,7 @@ function screen(id, ctx) {
|
|
|
24570
25127
|
case "about": return (0, import_jsx_runtime.jsx)(About, {});
|
|
24571
25128
|
case "people": return (0, import_jsx_runtime.jsx)(PeopleAccess, { ctx });
|
|
24572
25129
|
case "people.add": return (0, import_jsx_runtime.jsx)(GiveAccess, { ctx });
|
|
25130
|
+
case "people.modify": return (0, import_jsx_runtime.jsx)(ModifyAccess, { ctx });
|
|
24573
25131
|
case "admin":
|
|
24574
25132
|
case "admin.config": return (0, import_jsx_runtime.jsx)(GlobalConfig, { ctx });
|
|
24575
25133
|
default: return (0, import_jsx_runtime.jsx)(NotYet, {
|