Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 222e2cf

Browse files
UX: Use new DStatTiles reusable component from core (#1025)
For the Spam and Usage tabs in admin
1 parent 94b85ec commit 222e2cf

File tree

5 files changed

+65
-122
lines changed

5 files changed

+65
-122
lines changed

assets/javascripts/discourse/components/ai-spam.gjs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { action } from "@ember/object";
66
import { LinkTo } from "@ember/routing";
77
import { service } from "@ember/service";
88
import DButton from "discourse/components/d-button";
9+
import DStatTiles from "discourse/components/d-stat-tiles";
910
import DToggleSwitch from "discourse/components/d-toggle-switch";
1011
import DTooltip from "discourse/components/d-tooltip";
1112
import withEventValue from "discourse/helpers/with-event-value";
@@ -121,7 +122,7 @@ export default class AiSpam extends Component {
121122

122123
get metrics() {
123124
const detected = {
124-
label: "discourse_ai.spam.spam_detected",
125+
label: i18n("discourse_ai.spam.spam_detected"),
125126
value: this.stats.spam_detected,
126127
};
127128
if (this.args.model.flagging_username) {
@@ -131,17 +132,19 @@ export default class AiSpam extends Component {
131132
}
132133
return [
133134
{
134-
label: "discourse_ai.spam.scanned_count",
135+
label: i18n("discourse_ai.spam.scanned_count"),
135136
value: this.stats.scanned_count,
136137
},
137138
detected,
138139
{
139-
label: "discourse_ai.spam.false_positives",
140+
label: i18n("discourse_ai.spam.false_positives"),
140141
value: this.stats.false_positives,
142+
tooltip: i18n("discourse_ai.spam.stat_tooltips.incorrectly_flagged"),
141143
},
142144
{
143-
label: "discourse_ai.spam.false_negatives",
145+
label: i18n("discourse_ai.spam.false_negatives"),
144146
value: this.stats.false_negatives,
147+
tooltip: i18n("discourse_ai.spam.stat_tooltips.missed_spam"),
145148
},
146149
];
147150
}
@@ -220,22 +223,16 @@ export default class AiSpam extends Component {
220223
class="ai-spam__stats"
221224
>
222225
<:content>
223-
<div class="ai-spam__metrics">
226+
<DStatTiles as |tiles|>
224227
{{#each this.metrics as |metric|}}
225-
<div class="ai-spam__metrics-item">
226-
<span class="ai-spam__metrics-label">{{i18n
227-
metric.label
228-
}}</span>
229-
{{#if metric.href}}
230-
<a href={{metric.href}} class="ai-spam__metrics-value">
231-
{{metric.value}}
232-
</a>
233-
{{else}}
234-
<span class="ai-spam__metrics-value">{{metric.value}}</span>
235-
{{/if}}
236-
</div>
228+
<tiles.Tile
229+
@label={{metric.label}}
230+
@url={{metric.href}}
231+
@value={{metric.value}}
232+
@tooltip={{metric.tooltip}}
233+
/>
237234
{{/each}}
238-
</div>
235+
</DStatTiles>
239236
</:content>
240237
</AdminConfigAreaCard>
241238
</div>

assets/javascripts/discourse/components/ai-usage.gjs

Lines changed: 41 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { service } from "@ember/service";
77
import { eq, gt, lt } from "truth-helpers";
88
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
99
import DButton from "discourse/components/d-button";
10+
import DStatTiles from "discourse/components/d-stat-tiles";
1011
import DateTimeInputRange from "discourse/components/date-time-input-range";
1112
import avatar from "discourse/helpers/avatar";
1213
import concatClass from "discourse/helpers/concat-class";
@@ -124,6 +125,36 @@ export default class AiUsage extends Component {
124125
return normalized;
125126
}
126127

128+
get metrics() {
129+
return [
130+
{
131+
label: i18n("discourse_ai.usage.total_requests"),
132+
value: this.data.summary.total_requests,
133+
tooltip: i18n("discourse_ai.usage.stat_tooltips.total_requests"),
134+
},
135+
{
136+
label: i18n("discourse_ai.usage.total_tokens"),
137+
value: this.data.summary.total_tokens,
138+
tooltip: i18n("discourse_ai.usage.stat_tooltips.total_tokens"),
139+
},
140+
{
141+
label: i18n("discourse_ai.usage.request_tokens"),
142+
value: this.data.summary.total_request_tokens,
143+
tooltip: i18n("discourse_ai.usage.stat_tooltips.request_tokens"),
144+
},
145+
{
146+
label: i18n("discourse_ai.usage.response_tokens"),
147+
value: this.data.summary.total_response_tokens,
148+
tooltip: i18n("discourse_ai.usage.stat_tooltips.response_tokens"),
149+
},
150+
{
151+
label: i18n("discourse_ai.usage.cached_tokens"),
152+
value: this.data.summary.total_cached_tokens,
153+
tooltip: i18n("discourse_ai.usage.stat_tooltips.cached_tokens"),
154+
},
155+
];
156+
}
157+
127158
get chartConfig() {
128159
if (!this.data?.data) {
129160
return;
@@ -344,53 +375,16 @@ export default class AiUsage extends Component {
344375
class="ai-usage__summary"
345376
>
346377
<:content>
347-
<div class="ai-usage__summary-stats">
348-
<div class="ai-usage__summary-stat">
349-
<span class="label">{{i18n
350-
"discourse_ai.usage.total_requests"
351-
}}</span>
352-
<span
353-
class="value"
354-
title={{this.data.summary.total_requests}}
355-
>{{number this.data.summary.total_requests}}</span>
356-
</div>
357-
<div class="ai-usage__summary-stat">
358-
<span class="label">{{i18n
359-
"discourse_ai.usage.total_tokens"
360-
}}</span>
361-
<span
362-
class="value"
363-
title={{this.data.summary.total_tokens}}
364-
>{{number this.data.summary.total_tokens}}</span>
365-
</div>
366-
<div class="ai-usage__summary-stat">
367-
<span class="label">{{i18n
368-
"discourse_ai.usage.request_tokens"
369-
}}</span>
370-
<span
371-
class="value"
372-
title={{this.data.summary.total_request_tokens}}
373-
>{{number this.data.summary.total_request_tokens}}</span>
374-
</div>
375-
<div class="ai-usage__summary-stat">
376-
<span class="label">{{i18n
377-
"discourse_ai.usage.response_tokens"
378-
}}</span>
379-
<span
380-
class="value"
381-
title={{this.data.summary.total_response_tokens}}
382-
>{{number this.data.summary.total_response_tokens}}</span>
383-
</div>
384-
<div class="ai-usage__summary-stat">
385-
<span class="label">{{i18n
386-
"discourse_ai.usage.cached_tokens"
387-
}}</span>
388-
<span
389-
class="value"
390-
title={{this.data.summary.total_cached_tokens}}
391-
>{{number this.data.summary.total_cached_tokens}}</span>
392-
</div>
393-
</div>
378+
<DStatTiles as |tiles|>
379+
{{#each this.metrics as |metric|}}
380+
<tiles.Tile
381+
@label={{metric.label}}
382+
@href={{metric.href}}
383+
@value={{metric.value}}
384+
@tooltip={{metric.tooltip}}
385+
/>
386+
{{/each}}
387+
</DStatTiles>
394388
</:content>
395389
</AdminConfigAreaCard>
396390

assets/stylesheets/modules/llms/common/spam.scss

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -45,37 +45,6 @@
4545
&__stats {
4646
margin-top: 2em;
4747
}
48-
49-
&__stats-title {
50-
margin-bottom: 1em;
51-
}
52-
53-
&__metrics {
54-
display: grid;
55-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
56-
gap: 1em;
57-
margin-bottom: 2em;
58-
}
59-
60-
&__metrics-item {
61-
display: flex;
62-
flex-direction: column;
63-
padding: 1em;
64-
background: var(--primary-very-low);
65-
border-radius: 0.25em;
66-
}
67-
68-
&__metrics-label {
69-
color: var(--primary-medium);
70-
font-size: 0.875em;
71-
margin-bottom: 0.5em;
72-
}
73-
74-
&__metrics-value {
75-
color: var(--primary);
76-
font-size: 1.5em;
77-
font-weight: bold;
78-
}
7948
}
8049

8150
.spam-test-modal {

assets/stylesheets/modules/llms/common/usage.scss

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -68,32 +68,6 @@
6868
font-size: 1.2em;
6969
}
7070

71-
&__summary-stats {
72-
display: grid;
73-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
74-
gap: 1em;
75-
}
76-
77-
&__summary-stat {
78-
display: flex;
79-
flex-direction: column;
80-
padding: 1em;
81-
background: var(--primary-very-low);
82-
border-radius: 0.25em;
83-
84-
.label {
85-
color: var(--primary-medium);
86-
font-size: 0.875em;
87-
margin-bottom: 0.5em;
88-
}
89-
90-
.value {
91-
color: var(--primary);
92-
font-size: 1.5em;
93-
font-weight: bold;
94-
}
95-
}
96-
9771
&__charts {
9872
margin-top: 2em;
9973
}

config/locales/client.en.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ en:
157157
run: "Run test"
158158
spam: "Spam"
159159
not_spam: "Not spam"
160+
stat_tooltips:
161+
incorrectly_flagged: "Items that the AI bot flagged as spam where moderators disagreed"
162+
missed_spam: "Items flagged by the community as spam that were not detected by the AI bot, which moderators agreed with"
160163

161164
usage:
162165
short_title: "Usage"
@@ -182,6 +185,12 @@ en:
182185
no_models: "No model usage data found"
183186
no_features: "No feature usage data found"
184187
subheader_description: "Tokens are the basic units that LLMs use to understand and generate text, usage data may affect costs."
188+
stat_tooltips:
189+
total_requests: "All requests made to LLMs through Discourse"
190+
total_tokens: "All the tokens used when prompting an LLM"
191+
request_tokens: "Tokens used when the LLM tries to understand what you are saying"
192+
response_tokens: "Tokens used when the LLM responds to your prompt"
193+
cached_tokens: "Previously processed request tokens that the LLM reuses to optimize performance and cost"
185194
periods:
186195
last_day: "Last 24 hours"
187196
last_week: "Last week"

0 commit comments

Comments
 (0)