johnandersen777.bsky.social/atlibs-socialweb-computer-requester
socialweb.computer market requester and policy modules for atlibs, with its web pages and lexicons
0
0
import { templated } from 'atlibs/component/index.js'
const Base = await templated(new URL('./requester-actions.html', import.meta.url));
// The requester module's module.json actions as forms. Emits run-entry {entry, input}; empty
// fields are left out, values go as text (the cubit types them by module.json).
customElements.define('requester-actions', class extends Base {
setActions(actions) {
this.querySelector(".actions").replaceChildren(...actions.map(({ entry, label, description, fields }) => {
const action = Base.templates.action.content.cloneNode(true);
action.querySelector(".label").textContent = label;
action.querySelector(".description").textContent = description;
action.querySelector(".fields").replaceChildren(...fields.map(({ key, label }) => {
const field = Base.templates.field.content.cloneNode(true);
field.querySelector(".label").textContent = label;
field.querySelector("textarea").name = key;
return field;
}));
const form = action.querySelector("form");
form.dataset.entry = entry;
form.onsubmit = (e) => {
e.preventDefault();
const input = Object.fromEntries([...new FormData(form)].filter(([, v]) => v.trim()).map(([k, v]) => [k, v.trim()]));
this.dispatchEvent(new CustomEvent("run-entry", { bubbles: true, detail: { entry, input } }));
};
return action;
}));
}
render(state, previous) {
this.querySelector(".panel").style.display = state.session === "signed-in" ? "block" : "none";
if (previous?.results === state.results && previous?.running === state.running) return;
for (const form of this.querySelectorAll("form[data-entry]")) {
const { entry } = form.dataset;
form.querySelector(".run").toggleAttribute("aria-busy", state.running === entry);
form.querySelector(".result").textContent = entry in state.results ? JSON.stringify(state.results[entry], null, 1) : "";
}
}
});