List pagination and html tables

This commit is contained in:
tezlm 2023-10-04 21:33:37 -07:00
parent 0328932c54
commit 5443768b5c
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA

View file

@ -33,6 +33,8 @@ use crate::{
use super::pdu::PduBuilder;
const PAGE_SIZE: usize = 100;
#[cfg_attr(test, derive(Debug))]
#[derive(Parser)]
#[command(name = "@conduit:server.name:", version = env!("CARGO_PKG_VERSION"))]
@ -164,7 +166,9 @@ enum UserCommand {
#[derive(Subcommand)]
enum RoomCommand {
/// List all rooms the server knows about
List,
List {
page: Option<usize>,
},
#[command(subcommand)]
/// Manage rooms' aliases
@ -227,7 +231,9 @@ enum RoomDirectoryCommand {
/// List rooms that are published
// TODO: is this really necessary?
List,
List {
page: Option<usize>,
},
}
#[cfg_attr(test, derive(Debug))]
@ -733,26 +739,46 @@ impl Service {
},
}
AdminCommand::Room(command) => match command {
RoomCommand::List => {
RoomCommand::List { page } => {
// TODO: i know there's a way to do this with clap, but i can't seem to find it
let page = page.unwrap_or(1);
let mut rooms = services().rooms.metadata.iter_ids()
.filter_map(|r| r.ok())
.map(|id| (
id.clone(),
services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()),
services().rooms.state_cache.room_joined_count(&id).ok().flatten().unwrap_or(0),
services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()),
))
.collect::<Vec<_>>();
rooms.sort_by_key(|r| r.2);
rooms.sort_by_key(|r| r.1);
rooms.reverse();
let output = format!(
let slice_start = page.saturating_sub(1) * PAGE_SIZE;
let Some(rooms) = rooms.get(slice_start..slice_start + PAGE_SIZE) else {
return Ok(RoomMessageEventContent::text_plain("No more rooms."));
};
let output_plain = format!(
"Rooms:\n{}",
rooms
.iter()
.map(|(id, name, members)| format!("{id}\tName: {name}\tMembers: {members}"))
.map(|(id, members, name)| format!("{id}\tMembers: {members}\tName: {name}"))
.collect::<Vec<_>>()
.join("\n")
);
RoomMessageEventContent::text_plain(output)
let output_html = format!(
"<table><caption>Room list - page {page}</caption>\n<tr><th>id</th>\t<th>name</th>\t<th>members</th></tr>\n{}</table>",
rooms
.iter()
.map(|(id, members, name)| format!(
"<tr><td>{}</td>\t<td>{}</td>\t<td>{}</td></tr>\n",
escape_html(&id.to_string()),
members,
escape_html(name),
))
.collect::<String>()
);
RoomMessageEventContent::text_html(output_plain, output_html)
}
// TODO: clean up and deduplicate code
RoomCommand::Alias(command) => {
@ -853,26 +879,45 @@ impl Service {
Ok(()) => RoomMessageEventContent::text_plain("Room unpublished"),
Err(err) => RoomMessageEventContent::text_plain(&format!("Unable to update room: {}", err)),
}
RoomDirectoryCommand::List => {
RoomDirectoryCommand::List { page } => {
let page = page.unwrap_or(1);
let mut rooms = services().rooms.directory.public_rooms()
.filter_map(|r| r.ok())
.map(|id| (
id.clone(),
services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()),
services().rooms.state_cache.room_joined_count(&id).ok().flatten().unwrap_or(0),
services().rooms.state_accessor.get_name(&id).ok().flatten().unwrap_or(id.to_string()),
))
.collect::<Vec<_>>();
rooms.sort_by_key(|r| r.2);
rooms.sort_by_key(|r| r.1);
rooms.reverse();
let output = format!(
let slice_start = page.saturating_sub(1) * PAGE_SIZE;
let Some(rooms) = rooms.get(slice_start..slice_start + PAGE_SIZE) else {
return Ok(RoomMessageEventContent::text_plain("No more rooms."));
};
let output_plain = format!(
"Rooms:\n{}",
rooms
.iter()
.map(|(id, name, members)| format!("{id}\tName: {name}\tMembers: {members}"))
.map(|(id, members, name)| format!("{id}\tMembers: {members}\tName: {name}"))
.collect::<Vec<_>>()
.join("\n")
);
RoomMessageEventContent::text_plain(output)
let output_html = format!(
"<table><caption>Room directory - page {page}</caption>\n<tr><th>id</th>\t<th>name</th>\t<th>members</th></tr>\n{}</table>",
rooms
.iter()
.map(|(id, members, name)| format!(
"<tr><td>{}</td>\t<td>{}</td>\t<td>{}</td></tr>\n",
escape_html(&id.to_string()),
members,
escape_html(name),
))
.collect::<String>()
);
RoomMessageEventContent::text_html(output_plain, output_html)
}
}
}