dashboard.js javascript
115 lines 3.7 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 /**
2 * Hosted governance dashboard UI — viewer Bearer in JS memory only (§HGD.6.7).
3 * Do not persist the viewer credential in browser storage APIs.
4 */
5 (function () {
6 "use strict";
7
8 /** @type {string|null} */
9 var viewerToken = null;
10
11 var authPanel = document.getElementById("auth-panel");
12 var tabs = document.getElementById("tabs");
13 var content = document.getElementById("content");
14 var authStatus = document.getElementById("auth-status");
15 var orgOutput = document.getElementById("org-output");
16 var orgList = document.getElementById("org-list");
17 var repoOutput = document.getElementById("repo-output");
18
19 function api(path) {
20 return fetch(path, {
21 method: "GET",
22 headers: {
23 Authorization: "Bearer " + viewerToken,
24 Accept: "application/json",
25 },
26 }).then(function (res) {
27 return res.json().then(function (body) {
28 return { status: res.status, body: body };
29 });
30 });
31 }
32
33 function showMain() {
34 authPanel.hidden = true;
35 tabs.hidden = false;
36 content.hidden = false;
37 }
38
39 document.getElementById("auth-save").addEventListener("click", function () {
40 var input = document.getElementById("viewer-input");
41 var value = (input && input.value ? input.value : "").trim();
42 if (!value) {
43 authStatus.textContent = "Token required.";
44 return;
45 }
46 viewerToken = value;
47 input.value = "";
48 authStatus.textContent = "Connected (token held in memory only).";
49 showMain();
50 refreshOrg();
51 });
52
53 tabs.addEventListener("click", function (ev) {
54 var btn = ev.target.closest("button[data-tab]");
55 if (!btn) return;
56 var name = btn.getAttribute("data-tab");
57 tabs.querySelectorAll("button").forEach(function (b) {
58 b.classList.toggle("active", b === btn);
59 });
60 document.querySelectorAll(".tab-panel").forEach(function (panel) {
61 panel.classList.toggle("active", panel.id === "tab-" + name);
62 });
63 });
64
65 function refreshOrg() {
66 api("/api/org/summary").then(function (res) {
67 orgOutput.textContent = JSON.stringify(res.body, null, 2);
68 orgList.innerHTML = "";
69 var repos = (res.body.result && res.body.result.repos) || [];
70 repos.forEach(function (repo) {
71 var li = document.createElement("li");
72 li.textContent =
73 repo.full_name +
74 " — " +
75 repo.eligibility +
76 (repo.marker_present ? " (marker)" : "");
77 li.addEventListener("click", function () {
78 document.getElementById("repo-owner").value = repo.owner;
79 document.getElementById("repo-name").value = repo.name;
80 tabs.querySelector('button[data-tab="repo"]').click();
81 });
82 orgList.appendChild(li);
83 });
84 });
85 }
86
87 document.getElementById("refresh-org").addEventListener("click", refreshOrg);
88
89 function loadDoc(action) {
90 var owner = document.getElementById("repo-owner").value.trim();
91 var name = document.getElementById("repo-name").value.trim();
92 if (!owner || !name) {
93 repoOutput.textContent = "Owner and repo required.";
94 return;
95 }
96 api("/api/repos/" + encodeURIComponent(owner) + "/" + encodeURIComponent(name) + "/" + action).then(
97 function (res) {
98 repoOutput.textContent = JSON.stringify(res.body, null, 2);
99 }
100 );
101 }
102
103 document.getElementById("load-roadmap").addEventListener("click", function () {
104 loadDoc("roadmap");
105 });
106 document.getElementById("load-handover").addEventListener("click", function () {
107 loadDoc("handover");
108 });
109 document.getElementById("load-gates").addEventListener("click", function () {
110 loadDoc("gates");
111 });
112 document.getElementById("load-marker").addEventListener("click", function () {
113 loadDoc("config-marker");
114 });
115 })();
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago