feat(dashboard): pending guild names count on the Review Queue and Guilds badges

The dashboard snapshot counts guilds whose name waits for moderation; the moderation counts (WebSocket and
/api/moderation/counts) include it, the Review Queue badge adds it for staff with guilds_manage, and the Guilds menu
entry has its own badge. Check: create a guild with a name off the allow list: both badges go up; approve it: they
go down.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 08:46:34 -05:00
parent 24d96f13df
commit 33402425e4
7 changed files with 10 additions and 2 deletions

View File

@@ -471,6 +471,7 @@ namespace {
JsonReply(reply, eHTTPStatusCode::OK, {
{"pendingNames", snapshot.pendingNames},
{"pendingPetNames", snapshot.pendingPetNames},
{"pendingGuildNames", snapshot.pendingGuildNames},
{"pendingProperties", snapshot.pendingProperties},
{"unresolvedBugReports", snapshot.unresolvedBugReports},
{"openEconomyFlags", snapshot.openEconomyFlags}

View File

@@ -22,6 +22,7 @@ namespace {
return {
{"pendingNames", snapshot.pendingNames},
{"pendingPetNames", snapshot.pendingPetNames},
{"pendingGuildNames", snapshot.pendingGuildNames},
{"pendingProperties", snapshot.pendingProperties},
{"unresolvedBugReports", snapshot.unresolvedBugReports},
{"openEconomyFlags", snapshot.openEconomyFlags}

View File

@@ -126,8 +126,9 @@
function updateBadges(counts) {
var map = {
'moderation': (counts.pendingNames || 0) + (DASH.can('moderate_pet_names') ? counts.pendingPetNames || 0 : 0) + (DASH.can('moderate_properties') ? counts.pendingProperties || 0 : 0),
'moderation': (counts.pendingNames || 0) + (DASH.can('moderate_pet_names') ? counts.pendingPetNames || 0 : 0) + (DASH.can('guilds_manage') ? counts.pendingGuildNames || 0 : 0) + (DASH.can('moderate_properties') ? counts.pendingProperties || 0 : 0),
'pet_names': counts.pendingPetNames || 0,
'guilds': counts.pendingGuildNames || 0,
'bug_reports': counts.unresolvedBugReports || 0,
'reports': counts.openEconomyFlags || 0
};

View File

@@ -44,7 +44,7 @@
{% if can.chat_view %}<a href="/chat_log" class="list-group-item list-group-item-action{% if current_page == "chat_log" %} active{% endif %}">Chat Log</a>{% endif %}
{% if can.chat_filter_manage %}<a href="/chat_filter" class="list-group-item list-group-item-action{% if current_page == "chat_filter" %} active{% endif %}">Chat Filter</a>{% endif %}
{% if can.moderate_pet_names %}<a href="/pet_names" class="list-group-item list-group-item-action{% if current_page == "pet_names" %} active{% endif %}">Pet Names</a>{% endif %}
{% if can.guilds_manage %}<a href="/guilds" class="list-group-item list-group-item-action{% if current_page == "guilds" %} active{% endif %}">Guilds</a>{% endif %}
{% if can.guilds_manage %}<a href="/guilds" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center{% if current_page == "guilds" %} active{% endif %}">Guilds <span class="badge rounded-pill text-bg-warning d-none" data-badge="guilds" title="Guild names waiting for review"></span></a>{% endif %}
{% if can.characters_mail %}<a href="/mail" class="list-group-item list-group-item-action{% if current_page == "mail" %} active{% endif %}">Mail</a>{% endif %}
{% if can.mail_send %}<a href="/send_mail" class="list-group-item list-group-item-action{% if current_page == "send_mail" %} active{% endif %}">Send Mail</a>{% endif %}
</div>

View File

@@ -19,6 +19,7 @@ public:
uint64_t unresolvedBugReports{};
uint64_t petNames{};
uint64_t pendingPetNames{};
uint64_t pendingGuildNames{}; // guilds whose name waits for moderation
uint64_t activityLogMaxId{};
uint64_t chatLogMaxId{};
uint64_t commandLogMaxId{};

View File

@@ -19,6 +19,7 @@ namespace {
"(SELECT COUNT(*) FROM bug_reports WHERE resolved_time IS NULL) AS unresolved_bug_reports, "
"(SELECT COUNT(*) FROM pet_names) AS pet_names, "
"(SELECT COUNT(*) FROM pet_names WHERE approved = 1) AS pending_pet_names, "
"(SELECT COUNT(*) FROM guilds WHERE name_status = 1) AS pending_guild_names, "
"(SELECT COALESCE(MAX(id), 0) FROM activity_log) AS activity_log_max_id, "
"(SELECT COALESCE(MAX(id), 0) FROM chat_log) AS chat_log_max_id, "
"(SELECT COALESCE(MAX(id), 0) FROM command_log) AS command_log_max_id, "
@@ -255,6 +256,7 @@ IDashboardStats::Snapshot MySQLDatabase::GetDashboardSnapshot() {
snapshot.unresolvedBugReports = result->getUInt64("unresolved_bug_reports");
snapshot.petNames = result->getUInt64("pet_names");
snapshot.pendingPetNames = result->getUInt64("pending_pet_names");
snapshot.pendingGuildNames = result->getUInt64("pending_guild_names");
snapshot.activityLogMaxId = result->getUInt64("activity_log_max_id");
snapshot.chatLogMaxId = result->getUInt64("chat_log_max_id");
snapshot.commandLogMaxId = result->getUInt64("command_log_max_id");

View File

@@ -19,6 +19,7 @@ namespace {
"(SELECT COUNT(*) FROM bug_reports WHERE resolved_time IS NULL) AS unresolved_bug_reports, "
"(SELECT COUNT(*) FROM pet_names) AS pet_names, "
"(SELECT COUNT(*) FROM pet_names WHERE approved = 1) AS pending_pet_names, "
"(SELECT COUNT(*) FROM guilds WHERE name_status = 1) AS pending_guild_names, "
"(SELECT COALESCE(MAX(id), 0) FROM activity_log) AS activity_log_max_id, "
"(SELECT COALESCE(MAX(id), 0) FROM chat_log) AS chat_log_max_id, "
"(SELECT COALESCE(MAX(id), 0) FROM command_log) AS command_log_max_id, "
@@ -260,6 +261,7 @@ IDashboardStats::Snapshot SQLiteDatabase::GetDashboardSnapshot() {
snapshot.unresolvedBugReports = result.getInt64Field("unresolved_bug_reports");
snapshot.petNames = result.getInt64Field("pet_names");
snapshot.pendingPetNames = result.getInt64Field("pending_pet_names");
snapshot.pendingGuildNames = result.getInt64Field("pending_guild_names");
snapshot.activityLogMaxId = result.getInt64Field("activity_log_max_id");
snapshot.chatLogMaxId = result.getInt64Field("chat_log_max_id");
snapshot.commandLogMaxId = result.getInt64Field("command_log_max_id");