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 })) { LL dialogs = reversed(unnull(conv.oldDialogs)); l.add(webChatBotLogsHTML_formatDialog(str(conv.id + "/" + (l(dialogs)+1)), conv.msgs)); int i = l(dialogs); for (L msgs : dialogs) 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); }