!7 sclass HCRUD_Data { //LS fields() { null; } L> list() { null; } S fieldNameToHTML(S name) { ret htmlencode(humanizeLabel(name)); } S idField() { ret "id"; } } sclass HCRUD { HCRUD_Data data; S baseLink; S newLink() { ret baseLink + "new"; } S render(bool withCmds) { S table = renderTable(withCmds); ret !withCmds ? table : p(ahref(newLink(), "New entry")) + table; } S renderTable(bool withCmds) { L> l = data.list(); if (empty(l)) ret p("No entries"); //LS fields = data.fields(); //if (fields == null) fields = allKeysFromList_inOrder(); l = map(l, map -> { Map map2 = mapKeysAndValues( s -> or(data.fieldNameToHTML(s), s), value -> htmlEncode2(strOrEmpty(value)), map); if (withCmds) map2.put("", ahref(deleteLink(map.get(data.idField())), "delete", onClick := "return confirm(" + jsQuote("Are you sure?") + ");")); ret map2; }); ret htmlTable2_noHtmlEncode(l); } } concept Car { S brand; } p { db(); } html { new HCRUD crud; crud.baseLink = appendSlash(rawLink()); crud.data = new HCRUD_Data { //LS fields() { ret conceptFields(Car); } L> list() { ret (L) conceptsToMaps_gen(main list(Car)); } }; ret h1_title("Cars") + crud.render(true); }