Files
the-custodian/state-hub/dashboard/src/policy/workstream-dod.md
tegwick 02b7d4ae62 feat(dashboard): CUST-WP-0019 — Repository nav section, config.js cleanup
T01: Restructure nav — "Repos" → collapsible "Repository" section with
     Repo Sync, SBOM, Debt as sub-pages; Debt moved out of Workstreams
T02: workstream-dod.md migrated from inline const API to config.js import
T03: todo.md suggestion filter (done in previous commit)

Closes CUST-WP-0019. Resolves UI suggestion c2fc284a.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 02:01:10 +01:00

2.3 KiB

title
title
Workstream Definition of Done
import {API} from "../components/config.js";
import {marked} from "npm:marked";

const _resp = await fetch(`${API}/policy/workstream-dod`);
if (!_resp.ok) throw new Error(`Failed to load policy: ${_resp.status}`);
const _policy = await _resp.json();
let _content = _policy.content;
let _editing = false;

const _root = display(html`<div></div>`);

async function _save(text) {
  const r = await fetch(`${API}/policy/workstream-dod`, {
    method: "PUT",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({content: text}),
  });
  if (!r.ok) throw new Error(`Save failed: ${r.status}`);
  _content = text;
}

function _toolbar(...nodes) {
  return html`<div style="display:flex;gap:0.5rem;margin-bottom:1rem">${nodes}</div>`;
}

function _btn(label, primary = false) {
  return html`<button style="
    padding:0.35rem 0.9rem;border-radius:4px;cursor:pointer;font-size:13px;
    background:${primary ? "#1e293b" : "#f1f5f9"};
    color:${primary ? "#f8fafc" : "#1e293b"};
    border:1px solid ${primary ? "#1e293b" : "#cbd5e1"};
  ">${label}</button>`;
}

function _render() {
  _root.innerHTML = "";

  if (_editing) {
    const area = html`<textarea style="
      width:100%;box-sizing:border-box;height:520px;
      font-family:ui-monospace,monospace;font-size:13px;line-height:1.6;
      padding:0.75rem;border:1px solid #cbd5e1;border-radius:4px;
      background:#f8fafc;color:#1e293b;resize:vertical;
    ">${_content}</textarea>`;

    const saveBtn  = _btn("Save", true);
    const cancelBtn = _btn("Cancel");

    saveBtn.onclick = async () => {
      saveBtn.disabled = true;
      saveBtn.textContent = "Saving…";
      try {
        await _save(area.value);
        _editing = false;
        _render();
      } catch (e) {
        saveBtn.disabled = false;
        saveBtn.textContent = "Save";
        alert(e.message);
      }
    };

    cancelBtn.onclick = () => { _editing = false; _render(); };

    _root.append(_toolbar(saveBtn, cancelBtn), area);

  } else {
    const editBtn = _btn("Edit");
    editBtn.onclick = () => { _editing = true; _render(); };

    const body = html`<div style="
      max-width:720px;line-height:1.7;
    "></div>`;
    body.innerHTML = marked.parse(_content);

    _root.append(_toolbar(editBtn), body);
  }
}

_render();