From 4e85c0225b3892d83aa04a3864ff947dca536cd3 Mon Sep 17 00:00:00 2001 From: jaina heartles Date: Sat, 19 Nov 2022 03:13:05 -0800 Subject: [PATCH] Sample Cluster admin page --- src/api/lib.zig | 23 ++++++++++++++++++ src/main/controllers/web.zig | 16 +++++++++++++ .../web/cluster/overview.tmpl.html | 24 +++++++++++++++++++ src/template/lib.zig | 4 +++- 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 src/main/controllers/web/cluster/overview.tmpl.html diff --git a/src/api/lib.zig b/src/api/lib.zig index 4b2a434..5db4791 100644 --- a/src/api/lib.zig +++ b/src/api/lib.zig @@ -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(), + ); + } }; } diff --git a/src/main/controllers/web.zig b/src/main/controllers/web.zig index 183c3ce..9ee8ac4 100644 --- a/src/main/controllers/web.zig +++ b/src/main/controllers/web.zig @@ -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, + }); + } + }; +}; diff --git a/src/main/controllers/web/cluster/overview.tmpl.html b/src/main/controllers/web/cluster/overview.tmpl.html new file mode 100644 index 0000000..3b55caf --- /dev/null +++ b/src/main/controllers/web/cluster/overview.tmpl.html @@ -0,0 +1,24 @@ + + + + + { .community.name } + + +
+

{ .community.name }

+
+ +
+

Cluster Overview

+
+ Home to { .meta.community_count } communities + hosting { .meta.user_count } users. +
+
+ + diff --git a/src/template/lib.zig b/src/template/lib.zig index aef9e1e..8c6c8e9 100644 --- a/src/template/lib.zig +++ b/src/template/lib.zig @@ -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");