import { createElement, navigate } from "../../lib/skeleton/index.js"; import rxjs, { effect, applyMutation, preventDefault } from "../../lib/rx.js"; import { qs, qsa, safe } from "../../lib/dom.js"; import { animate, slideYIn } from "../../lib/animate.js"; import { createForm } from "../../lib/form.js"; import { formTmpl } from "../../components/form.js"; import { CSS } from "../../helpers/loader.js"; import { createSession } from "../../model/session.js"; import config$ from "./model_config.js"; import backend$ from "./model_backend.js"; import { setCurrentBackend, getCurrentBackend } from "./state.js"; export default async function(render) { const $page = createElement(`
`); // feature1: backend selector effect(config$.pipe( // dom creation rxjs.map(({ connections }) => connections), rxjs.mergeMap((conns) => conns.map((conn, i) => ({ ...conn, n: i }))), rxjs.map(({ label, n }) => createElement(``)), rxjs.map(($button) => [$button]), applyMutation(qs($page, "[role=\"navigation\"]"), "appendChild"), // initialise selection rxjs.toArray(), rxjs.map((conns) => Math.max(0, conns.length / 2 - 1)), rxjs.tap((current) => setCurrentBackend(current)) )); // feature2: interaction with the buttons effect(getCurrentBackend().pipe( rxjs.first(), rxjs.map(() => qsa($page, "[role=\"navigation\"] button")), rxjs.mergeMap((els) => els), rxjs.mergeMap(($button) => rxjs.fromEvent($button, "click")), rxjs.map((e) => parseInt(e.target.getAttribute("data-current"))), rxjs.tap((current) => setCurrentBackend(current)) )); // feature3: highlight the selected button effect(getCurrentBackend().pipe( rxjs.map((n) => ({ $buttons: qsa($page, "[role=\"navigation\"] button"), n })), rxjs.tap(({ $buttons }) => $buttons.forEach(($node) => $node.classList.remove("active", "primary"))), rxjs.map(({ $buttons, n }) => $buttons[n]), rxjs.filter(($button) => !!$button), rxjs.tap(($button) => $button.classList.add("active", "primary")) )); // feature4: insert all the connection form const tmpl = formTmpl({ renderNode: () => createElement("
"), renderLeaf: ({ label, type }) => { if (type === "enable") { return createElement(` `); } return createElement(""); } }); effect(rxjs.combineLatest( config$.pipe( rxjs.first(), rxjs.mergeMap(({ connections }) => connections), rxjs.mergeMap(({ type }) => backend$.pipe(rxjs.map((spec) => spec[type]))), rxjs.mergeMap((formSpec) => createForm(formSpec, tmpl)), rxjs.toArray(), rxjs.share() ), getCurrentBackend() ).pipe( rxjs.map(([$forms, n]) => [$forms[n]]), applyMutation(qs($page, "form"), "replaceChildren"), rxjs.tap(() => animate($page.querySelector("form > div"), { time: 200, keyframes: slideYIn(-2) })), rxjs.tap(() => qs($page, "form").appendChild(createElement(""))) )); // feature5: form submission effect(rxjs.fromEvent(qs($page, "form"), "submit").pipe( preventDefault(), rxjs.map((e) => new FormData(e.target)), rxjs.map((formData) => { const json = {}; for (const pair of formData.entries()) { json[pair[0]] = pair[1] === "" ? null : pair[1]; } return json; }), // rxjs.map((formData) => JSON.parse(JSON.stringify(a, (key, value) => { // if (value !== null) return value; // })), rxjs.mergeMap((creds) => createSession(creds)), rxjs.tap(() => navigate("/")), // TODO: error with notification )); render($page); }