~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs-socialweb-computer-requester

socialweb.computer market requester and policy modules for atlibs, with its web pages and lexicons

0
0
main
58 lines · 2.8 KB Raw History
import { templated } from 'atlibs/component/index.js'

const Base = await templated(new URL('./swc-sessions.html', import.meta.url));

const names = (form) => new FormData(form).getAll("sessions");

// Login and module sessions, and the agent features. Emits login {username, names},
// set-sessions {names}, announce, allow-agent-requests {allow}. Renders {ui, compute}.
customElements.define('swc-sessions', class extends Base {
	connectedCallback() {
		super.connectedCallback();
		const emit = (type, detail) => this.dispatchEvent(new CustomEvent(type, { bubbles: true, detail }));
		this.querySelector(".login-form").onsubmit = (e) => {
			e.preventDefault();
			emit("login", { username: e.target.username.value, names: names(e.target) });
		};
		this.querySelector(".sessions-form").onsubmit = (e) => {
			e.preventDefault();
			emit("set-sessions", { names: names(e.target) });
		};
		this.querySelector(".announce-button").onclick = () => emit("announce");
		this.querySelector(".allow").onchange = (e) => emit("allow-agent-requests", { allow: e.target.checked });
	}

	// One checkbox per policy session, in both forms; login ticks them all.
	setPolicy(policy) {
		for (const fieldset of this.querySelectorAll(".choices")) {
			fieldset.replaceChildren(...Object.entries(policy.sessions).map(([name, { label, scope }]) => {
				const choice = Base.templates.choice.content.cloneNode(true);
				Object.assign(choice.querySelector("input"), { value: name, checked: true });
				choice.querySelector(".label").textContent = label ?? name;
				choice.querySelector("label").title = scope;
				return choice;
			}));
		}
		this.policy = policy;
	}

	render({ ui, compute }, previous) {
		this.querySelector(".login").style.display = ui.session === "signed-out" ? "block" : "none";
		this.querySelector(".panel").style.display = ui.session === "signed-in" ? "block" : "none";
		this.querySelector(".login-button").toggleAttribute("aria-busy", ui.login.busy);
		this.querySelector(".login .error").textContent = ui.login.error ?? "";
		if (previous?.ui.granted !== ui.granted) {
			for (const input of this.querySelectorAll(".sessions-form input")) input.checked = ui.granted.includes(input.value);
		}
		const on = ui.features.includes("agents");
		const requires = this.policy?.features.agents.requires.join(" + ") ?? "";
		this.querySelector(".feature").textContent = on ? `on (${requires})` : `off: needs ${requires}`;
		const announce = this.querySelector(".announce-button");
		announce.disabled = !on || !compute.receipt;
		announce.toggleAttribute("aria-busy", ui.announce.status === "busy");
		const allow = this.querySelector(".allow");
		allow.disabled = !on;
		allow.checked = ui.allowAgentRequests;
		this.querySelector(".announce").textContent = ui.announce.error ?? (ui.announce.status === "done" ? "posted" : on && !compute.receipt ? "Find a guest (below) to announce it." : "");
	}
});