static S webChatBotLogsHTML() { ret withDBLock(func -> S { new L l; for (Conversation conv : sortByCalculatedFieldDesc(list(Conversation), func(Conversation c) { empty(c.msgs) ? c.created : last(c.msgs).time })) { l.add(webChatBotLogsHTML_formatDialog(str(conv.id), conv.msgs)); int i = 0; for (L msgs : reversed(unnull(conv.oldDialogs))) l.add(webChatBotLogsHTML_formatDialog(conv.id + "/" + (++i), msgs)); } ret h3_htitle("Chat Logs") + ul(l); }); } sS webChatBotLogsHTML_formatDialog(S id, L msgs) { new L lc; for (Msg m : msgs) lc.add(htmlencode((m.fromUser ? "> " : "< ") + m.text)); ret id + ul(lc); }