!7 concept AIList { S name; S text; long modified; S status; } p { dbIndexing(AIList, 'name); } html { if (!webAuthed(params)) ret redirectToWebAuth(); new Matches m; // API if (startsWith(uri, "/list-text/", m)) { S name = urldecode(m.get(0)); AIList l = conceptWhere(AIList, +name); ret serveText(jsonEncode(l == null ? litmap("Error", ll("List not found", name)) : litmap("Name" := l.name, "Text" :=l.text))); } if (eq(uri, "/list-names")) ret serveText(jsonEncode(sortedIC(collect(list(AIList), 'name)))); // Show list if (startsWith(uri, "/list/", m)) { AIList l = conceptWhere(AIList, name := urldecode(m.get(0))); if (l == null) ret "List not found"; // Update text S text = params.get("human"); S status = params.get("status"); if (text != null && neq(text, l.text)) { logStructure("versions.log", litmap(id := l.id, +text, date := now())); if (status != null) cset(l, +status); cset(l, +text, modified := now()); ret hrefresh(rawLink(uri)); } ret nav() + htitle_h2(htmlencode(l.name)) + "Status: " + htextinput('status, value := l.status) + hpostform(h3("Contents (human-edited)") + p(hsubmit("Save")) + htextarea(l.text, name := 'human, cols := 80, rows := 30)); } // New list S newList = params.get('newList); if (nempty(newList)) { AIList l = uniq(AIList, name := newList); ret hrefresh(rawLink("/list/" + urlencode(l.name))); } // Overview bool alphabetical = eq(uri, "/alphabetical"); L list = alphabetical ? sortedByFieldIC('name, list(AIList)) : sortedByFieldDesc('modified, list(AIList)); ret hmobilefix () + htitle_h3("mech.tinybrain.de") + hBoolSelector(alphabetical, "/", "By date", "/alphabetical", "Alphabetical") + ul(map(list, func(AIList l) -> S { int n = countLines(l.text); ret ahref(rawLink("/list/" + urlencode(l.name)), htmlencode(l.name)) + (n == 0 ? "" : " (" + n2(n, "line") + ")"); })) + h3("New list") + hpostform("Name: " + htextinput('newList) + " " + hsubmit("Create list")); } sS nav() { ret hmobilefix() + p(ahref(rawLink(), "<< back")); }