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

Commit 476a87f

Browse files
committed
created a quota selector
1 parent 0b81801 commit 476a87f

File tree

3 files changed

+125
-9
lines changed

3 files changed

+125
-9
lines changed

assets/javascripts/discourse/components/ai-llm-quota-editor.gjs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { service } from "@ember/service";
77
import DButton from "discourse/components/d-button";
88
import I18n from "discourse-i18n";
99
import GroupChooser from "select-kit/components/group-chooser";
10+
import DurationSelector from "./ai-quota-duration-selector";
1011

1112
export default class AiLlmQuotaEditor extends Component {
1213
@service store;
@@ -29,8 +30,8 @@ export default class AiLlmQuotaEditor extends Component {
2930
}
3031

3132
@action
32-
updateExistingQuotaDuration(quota, event) {
33-
quota.duration_seconds = event.target.value;
33+
updateExistingQuotaDuration(quota, value) {
34+
quota.duration_seconds = value;
3435
}
3536

3637
get canAddQuota() {
@@ -124,12 +125,9 @@ export default class AiLlmQuotaEditor extends Component {
124125
/>
125126
</td>
126127
<td class="ai-llm-quotas__cell">
127-
<input
128-
type="number"
129-
value={{quota.duration_seconds}}
130-
class="ai-llm-quotas__input"
131-
min="1"
132-
{{on "input" (fn this.updateExistingQuotaDuration quota)}}
128+
<DurationSelector
129+
@value={{quota.duration_seconds}}
130+
@onChange={{fn this.updateExistingQuotaDuration quota}}
133131
/>
134132
</td>
135133
<td class="ai-llm-quotas__cell ai-llm-quotas__cell--actions">
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import Component from "@glimmer/component";
2+
import { tracked } from "@glimmer/tracking";
3+
import { on } from "@ember/modifier";
4+
import { action } from "@ember/object";
5+
import I18n from "discourse-i18n";
6+
import ComboBox from "select-kit/components/combo-box";
7+
8+
const DURATION_PRESETS = [
9+
{
10+
id: "3600",
11+
seconds: 3600,
12+
nameKey: "discourse_ai.llms.quotas.durations.hour",
13+
},
14+
{
15+
id: "21600",
16+
seconds: 21600,
17+
nameKey: "discourse_ai.llms.quotas.durations.six_hours",
18+
},
19+
{
20+
id: "86400",
21+
seconds: 86400,
22+
nameKey: "discourse_ai.llms.quotas.durations.day",
23+
},
24+
{
25+
id: "604800",
26+
seconds: 604800,
27+
nameKey: "discourse_ai.llms.quotas.durations.week",
28+
},
29+
{ id: "custom", nameKey: "discourse_ai.llms.quotas.durations.custom" },
30+
];
31+
32+
export default class DurationSelector extends Component {
33+
@tracked selectedPresetId = "86400"; // Default to 1 day
34+
@tracked customHours = null;
35+
36+
constructor() {
37+
super(...arguments);
38+
const seconds = this.args.value;
39+
const preset = DURATION_PRESETS.find((p) => p.seconds === seconds);
40+
if (preset) {
41+
this.selectedPresetId = preset.id;
42+
} else {
43+
this.selectedPresetId = "custom";
44+
this.customHours = Math.round(seconds / 3600);
45+
}
46+
}
47+
48+
get presetOptions() {
49+
return DURATION_PRESETS.map((preset) => ({
50+
id: preset.id,
51+
name: I18n.t(preset.nameKey),
52+
seconds: preset.seconds,
53+
}));
54+
}
55+
56+
get isCustom() {
57+
return this.selectedPresetId === "custom";
58+
}
59+
60+
get currentDurationSeconds() {
61+
if (this.isCustom) {
62+
return this.customHours ? this.customHours * 3600 : 0;
63+
} else {
64+
return parseInt(this.selectedPresetId, 10);
65+
}
66+
}
67+
68+
@action
69+
onPresetChange(value) {
70+
this.selectedPresetId = value;
71+
this.updateValue();
72+
}
73+
74+
@action
75+
onCustomHoursChange(event) {
76+
this.customHours = parseInt(event.target.value, 10);
77+
this.updateValue();
78+
}
79+
80+
updateValue() {
81+
if (this.args.onChange) {
82+
this.args.onChange(this.currentDurationSeconds);
83+
}
84+
}
85+
86+
<template>
87+
<div class="duration-selector">
88+
<ComboBox
89+
@content={{this.presetOptions}}
90+
@value={{this.selectedPresetId}}
91+
@onChange={{this.onPresetChange}}
92+
class="duration-selector__preset"
93+
/>
94+
95+
{{#if this.isCustom}}
96+
<div class="duration-selector__custom">
97+
<input
98+
type="number"
99+
value={{this.customHours}}
100+
class="duration-selector__hours-input"
101+
min="1"
102+
{{on "input" this.onCustomHoursChange}}
103+
/>
104+
<span class="duration-selector__hours-label">
105+
{{I18n.t "discourse_ai.llms.quotas.hours"}}
106+
</span>
107+
</div>
108+
{{/if}}
109+
</div>
110+
</template>
111+
}

config/locales/client.en.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,15 @@ en:
342342
group: "Group"
343343
max_tokens: "Max Tokens"
344344
max_usages: "Max Uses"
345-
duration: "Duration (seconds)"
345+
duration: "Duration"
346346
confirm_delete: "Are you sure you want to delete this quota?"
347+
durations:
348+
hour: "1 hour"
349+
six_hours: "6 hours"
350+
day: "24 hours"
351+
week: "7 days"
352+
custom: "Custom..."
353+
hours: "hours"
347354
usage:
348355
ai_bot: "AI bot"
349356
ai_helper: "Helper"

0 commit comments

Comments
 (0)