{{.Games}}
{{.ActiveGames}}
{{.OpenComplaints}}
+{{.OpenFeedback}}
{{.PendingChanges}}
| Sender | Source | Channel | Attach | Reply | State | Filed |
|---|---|---|---|---|---|---|
| {{.SenderName}} | +{{.Source}} | +{{.Channel}} | +{{if .HasAttachment}}yes{{else}}—{{end}} | +{{if .Replied}}replied{{else}}—{{end}} | +{{if .Archived}}archived{{else if .Read}}read{{else}}unread{{end}} | +{{.CreatedAt}} | +
| no feedback | ||||||
{{.IP}}{{else}}none{{end}}sent {{.RepliedAt}}
+| Role | |
|---|---|
{{.}} |
no roles
{{end}} + +Think time per move number across all games — min · mean · max.
diff --git a/backend/internal/adminconsole/views.go b/backend/internal/adminconsole/views.go index 4a3ef41..7eb2a17 100644 --- a/backend/internal/adminconsole/views.go +++ b/backend/internal/adminconsole/views.go @@ -42,6 +42,7 @@ type DashboardView struct { Games int ActiveGames int OpenComplaints int + OpenFeedback int PendingChanges int // ActiveVersion is the dictionary version new games pin (the persisted active // version), distinct from the per-variant resident versions. @@ -142,6 +143,10 @@ type UserDetailView struct { // form; Reasons is the operator-editable reason picklist offered in the block form. Suspension SuspensionView Reasons []ReasonOption + // Roles is the account's current roles (each revocable); KnownRoles is the set the + // grant form offers. The first role is the feedback ban (see internal/account). + Roles []string + KnownRoles []string } // SuspensionView is an account's current manual-block state shown on the user card: whether it @@ -362,3 +367,58 @@ type MessageView struct { Body string Back string } + +// FeedbackView is the paginated user-feedback queue. Status is the active +// unread/read/archived filter; NameMask/ExtMask are the sender glob filters; +// UserID pins the list to one account (the per-user link from /users); +// FilterQuery is the active filters URL-encoded for the pager links (already +// escaped, hence template.URL — see UsersView.FilterQuery). +type FeedbackView struct { + Items []FeedbackRow + Status string + NameMask string + ExtMask string + UserID string + Pager Pager + FilterQuery template.URL +} + +// FeedbackRow is one feedback message in the queue: its sender (linked to the user +// card), source, channel, whether it has an attachment / a reply, its state and +// time. +type FeedbackRow struct { + ID string + AccountID string + SenderName string + Source string + Channel string + HasAttachment bool + Read bool + Replied bool + Archived bool + CreatedAt string +} + +// FeedbackDetailView is one feedback message with its body, attachment, state and +// the reply / archive / delete forms. Body, AttachmentName, SenderName and IP are +// user-controlled and rendered as plain auto-escaped text. IsImage gates the inline +//{t('feedback.fileRejected')}
{/if} + + {#if sent} +{t('feedback.sent')}
+ {:else if reason === 'pending'} +{t('feedback.waiting')}
+ {:else if reason === 'banned'} +{t('feedback.banned')}
+ {/if} + + {#if view?.reply} +{view.reply.body}
+