Sample Cluster admin page
This commit is contained in:
parent
1b379513f7
commit
4e85c0225b
4 changed files with 66 additions and 1 deletions
|
@ -14,6 +14,12 @@ const services = struct {
|
|||
const follows = @import("./services/follows.zig");
|
||||
};
|
||||
|
||||
pub const ClusterMeta = struct {
|
||||
community_count: usize,
|
||||
user_count: usize,
|
||||
note_count: usize,
|
||||
};
|
||||
|
||||
pub const RegistrationOptions = struct {
|
||||
invite_code: ?[]const u8 = null,
|
||||
email: ?[]const u8 = null,
|
||||
|
@ -485,5 +491,22 @@ fn ApiConn(comptime DbConn: type) type {
|
|||
const result = try services.follows.create(self.db, self.user_id orelse return error.NoToken, followee, self.arena.allocator());
|
||||
defer util.deepFree(self.arena.allocator(), result);
|
||||
}
|
||||
|
||||
pub fn getClusterMeta(self: *Self) !ClusterMeta {
|
||||
return try self.db.queryRow(
|
||||
ClusterMeta,
|
||||
\\SELECT
|
||||
\\ COUNT(DISTINCT note.id) AS note_count,
|
||||
\\ COUNT(DISTINCT actor.id) AS user_count,
|
||||
\\ COUNT(DISTINCT community.id) AS community_count
|
||||
\\FROM note, actor, community
|
||||
\\WHERE
|
||||
\\ actor.community_id = community.id AND
|
||||
\\ community.kind != 'admin'
|
||||
,
|
||||
.{},
|
||||
self.arena.allocator(),
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ pub const routes = .{
|
|||
about,
|
||||
login,
|
||||
global_timeline,
|
||||
cluster.overview,
|
||||
};
|
||||
|
||||
const index = struct {
|
||||
|
@ -70,3 +71,18 @@ const global_timeline = struct {
|
|||
});
|
||||
}
|
||||
};
|
||||
|
||||
const cluster = struct {
|
||||
const overview = struct {
|
||||
pub const path = "/cluster/overview";
|
||||
pub const method = .GET;
|
||||
|
||||
pub fn handler(_: anytype, res: anytype, srv: anytype) !void {
|
||||
const meta = try srv.getClusterMeta();
|
||||
try res.template(.ok, @embedFile("./web/cluster/overview.tmpl.html"), .{
|
||||
.community = srv.community,
|
||||
.meta = meta,
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
24
src/main/controllers/web/cluster/overview.tmpl.html
Normal file
24
src/main/controllers/web/cluster/overview.tmpl.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{ .community.name }</title>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>{ .community.name }</h1>
|
||||
</header>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="communities">Communities</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<main>
|
||||
<h2>Cluster Overview</h2>
|
||||
<div>
|
||||
Home to <span>{ .meta.community_count }</span> communities
|
||||
hosting <span>{ .meta.user_count }</span> users.
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -59,7 +59,9 @@ fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype, ca
|
|||
}
|
||||
|
||||
fn print(writer: anytype, arg: anytype) !void {
|
||||
if (comptime std.meta.trait.isZigString(@TypeOf(arg))) return writer.writeAll(arg);
|
||||
const T = @TypeOf(arg);
|
||||
if (comptime std.meta.trait.isZigString(T)) return writer.writeAll(arg);
|
||||
if (comptime std.meta.trait.isNumber(T)) return std.fmt.format(writer, "{}", .{arg});
|
||||
@compileLog(@TypeOf(arg));
|
||||
|
||||
@compileError("TODO");
|
||||
|
|
Loading…
Reference in a new issue