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

Commit e86d2fd

Browse files
committed
Clean up CSS and add persona selector
1 parent d2d46f0 commit e86d2fd

File tree

5 files changed

+94
-202
lines changed

5 files changed

+94
-202
lines changed

assets/javascripts/discourse/controllers/discourse-ai-bot-conversations.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,46 @@
11
import Controller from "@ember/controller";
22
import { action } from "@ember/object";
33
import { service } from "@ember/service";
4+
import { tracked } from "@ember-compat/tracked-built-ins";
45

56
export default class DiscourseAiBotConversations extends Controller {
67
@service aiBotConversationsHiddenSubmit;
8+
@service currentUser;
9+
10+
@tracked selectedPersona = this.personaOptions[0].username;
711

812
textarea = null;
913

14+
init() {
15+
super.init(...arguments);
16+
this.selectedPersonaChanged(this.selectedPersona);
17+
}
18+
19+
get personaOptions() {
20+
if (this.currentUser.ai_enabled_personas) {
21+
return this.currentUser.ai_enabled_personas
22+
.filter((persona) => persona.username)
23+
.map((persona) => {
24+
return {
25+
id: persona.id,
26+
username: persona.username,
27+
name: persona.name,
28+
description: persona.description,
29+
};
30+
});
31+
}
32+
}
33+
34+
get filterable() {
35+
return this.personaOptions.length > 4;
36+
}
37+
38+
@action
39+
selectedPersonaChanged(username) {
40+
this.selectedPersona = username;
41+
this.aiBotConversationsHiddenSubmit.personaUsername = username;
42+
}
43+
1044
@action
1145
updateInputValue(event) {
1246
this._autoExpandTextarea();

assets/javascripts/discourse/lib/ai-bot-helper.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,22 @@ export async function composeAiBotMessage(
2929
options = {
3030
skipFocus: false,
3131
topicBody: "",
32+
personaUsername: null,
3233
}
3334
) {
3435
const currentUser = composer.currentUser;
3536
const draftKey = "new_private_message_ai_" + new Date().getTime();
3637

37-
const botUsername = !targetBot
38-
? currentUser.ai_enabled_chat_bots[0].username
39-
: currentUser.ai_enabled_chat_bots.find(
40-
(bot) => bot.model_name === targetBot
41-
)?.username;
38+
let botUsername;
39+
if (targetBot) {
40+
botUsername = currentUser.ai_enabled_chat_bots.find(
41+
(bot) => bot.model_name === targetBot
42+
)?.username;
43+
} else if (options.personaUsername) {
44+
botUsername = options.personaUsername;
45+
} else {
46+
botUsername = currentUser.ai_enabled_chat_bots[0].username;
47+
}
4248

4349
const data = {
4450
action: Composer.PRIVATE_MESSAGE,

assets/javascripts/discourse/services/ai-bot-conversations-hidden-submit.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export default class AiBotConversationsHiddenSubmit extends Service {
99
@service aiConversationsSidebarManager;
1010
@service dialog;
1111

12+
personaUsername;
13+
1214
inputValue = "";
1315

1416
@action
@@ -41,6 +43,7 @@ export default class AiBotConversationsHiddenSubmit extends Service {
4143
await composeAiBotMessage(null, this.composer, {
4244
skipFocus: true,
4345
topicBody: this.inputValue,
46+
personaUsername: this.personaUsername,
4447
});
4548

4649
try {
Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,37 @@
1-
{{body-class "discourse-ai-bot-conversations-page"}}
2-
3-
<div class="custom-homepage__content-wrapper">
4-
<h1>{{i18n "discourse_ai.ai_bot.conversations.header"}}</h1>
5-
<div class="custom-homepage__input-wrapper">
6-
<textarea
7-
{{didInsert this.setTextArea}}
8-
{{on "input" this.updateInputValue}}
9-
{{on "keydown" this.handleKeyDown}}
10-
id="custom-homepage-input"
11-
placeholder={{i18n "discourse_ai.ai_bot.conversations.placeholder"}}
12-
minlength="10"
13-
rows="1"
14-
/>
15-
<DButton
16-
@action={{this.aiBotConversationsHiddenSubmit.submitToBot}}
17-
@icon="paper-plane"
18-
@title="discourse_ai.ai_bot.conversations.header"
19-
class="ai-bot-button btn-primary ai-conversation-submit"
1+
<div class="ai-bot-conversations">
2+
<div class="ai-bot-conversations__persona-selector">
3+
<DropdownSelectBox
4+
class="persona-llm-selector__persona-dropdown"
5+
@value={{this.selectedPersona}}
6+
@valueProperty="username"
7+
@content={{this.personaOptions}}
8+
@options={{hash icon="robot" filterable=this.filterable}}
9+
@onChange={{this.selectedPersonaChanged}}
2010
/>
2111
</div>
22-
<p class="ai-disclaimer">
23-
{{i18n "discourse_ai.ai_bot.conversations.disclaimer"}}
24-
</p>
12+
13+
<div class="ai-bot-conversations__content-wrapper">
14+
15+
<h1>{{i18n "discourse_ai.ai_bot.conversations.header"}}</h1>
16+
<div class="ai-bot-conversations__input-wrapper">
17+
<textarea
18+
{{didInsert this.setTextArea}}
19+
{{on "input" this.updateInputValue}}
20+
{{on "keydown" this.handleKeyDown}}
21+
id="ai-bot-conversations-input"
22+
placeholder={{i18n "discourse_ai.ai_bot.conversations.placeholder"}}
23+
minlength="10"
24+
rows="1"
25+
/>
26+
<DButton
27+
@action={{this.aiBotConversationsHiddenSubmit.submitToBot}}
28+
@icon="paper-plane"
29+
@title="discourse_ai.ai_bot.conversations.header"
30+
class="ai-bot-button btn-primary ai-conversation-submit"
31+
/>
32+
</div>
33+
<p class="ai-disclaimer">
34+
{{i18n "discourse_ai.ai_bot.conversations.disclaimer"}}
35+
</p>
36+
</div>
2537
</div>

assets/stylesheets/modules/ai-bot-conversations/common.scss

Lines changed: 12 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -165,70 +165,19 @@ body.has-ai-conversations-sidebar {
165165
margin-left: calc(var(--topic-avatar-width) - 1.15em);
166166
}
167167

168-
// custom header notification button
169-
.user-menu.revamped .menu-tabs-container {
170-
display: none;
171-
}
172-
173-
// custom homepage
174-
html.composer-open .custom-homepage #main-outlet {
175-
padding-bottom: 0;
176-
}
177-
178-
.custom-homepage {
179-
@media screen and (max-width: 676px) {
180-
#main-outlet {
181-
padding-top: 0;
182-
}
183-
184-
#main-outlet-wrapper #main-outlet {
185-
max-width: 95vw;
186-
overflow-x: hidden;
187-
}
188-
}
189-
190-
// hide toggle until we know there are messages
191-
&:not(.sidebar-animate) {
192-
&.has-sidebar-page .header-sidebar-toggle {
193-
display: none;
194-
}
195-
}
196-
197-
// show toggle when populated
198-
&:has(.sidebar-wrapper [data-section-name="ai-conversations-history"]) {
199-
.header-sidebar-toggle {
200-
display: block;
201-
}
202-
}
168+
.ai-bot-conversations {
169+
height: calc(100dvh - var(--header-offset) - 1.25em);
203170

204-
// hide the sidebar on the homepage, if empty
205-
#main-outlet-wrapper:not(
206-
:has([data-section-name="ai-conversations-history"])
207-
) {
208-
grid-template-areas: "content";
209-
grid-template-columns: 1fr !important;
210-
211-
@media screen and (min-width: 900px) {
212-
.custom-homepage__content-wrapper {
213-
margin-left: 1em;
214-
}
215-
}
216-
}
217-
218-
// can't use this on the homepage due to composer hacks
219-
.ai-new-question-button {
220-
display: none;
221-
}
222-
223-
// could maybe show if we force in:messages
224-
.d-header-icons .header-dropdown-toggle.search-dropdown {
225-
display: none;
171+
@media screen and (min-width: 675px) {
172+
border: 1px solid var(--primary-low);
173+
padding: 2em 2em 3em;
174+
border-radius: var(--border-radius);
175+
height: calc(100dvh - var(--header-offset) - 10em);
226176
}
227177

228-
// the homepage has a custom input that submits the composer automatically
229-
// so this is a hack to hide the composer appearing
230-
#reply-control {
231-
display: none !important;
178+
&__persona-selector {
179+
display: flex;
180+
justify-content: flex-end;
232181
}
233182

234183
&__content-wrapper {
@@ -237,14 +186,7 @@ body.has-ai-conversations-sidebar {
237186
box-sizing: border-box;
238187
align-items: center;
239188
justify-content: center;
240-
height: calc(100dvh - var(--header-offset) - 1.25em);
241-
242-
@media screen and (min-width: 675px) {
243-
border: 1px solid var(--primary-low);
244-
padding: 2em 2em 3em;
245-
border-radius: var(--border-radius);
246-
height: calc(100dvh - var(--header-offset) - 4em);
247-
}
189+
height: 100%;
248190
}
249191

250192
&__input-wrapper {
@@ -265,7 +207,7 @@ body.has-ai-conversations-sidebar {
265207
min-height: 2.5em;
266208
}
267209

268-
#custom-homepage-input {
210+
#ai-bot-conversations-input {
269211
width: 100%;
270212
margin: 0;
271213
resize: none;
@@ -279,45 +221,6 @@ body.has-ai-conversations-sidebar {
279221
}
280222
}
281223

282-
&__button-wrapper {
283-
margin-bottom: 1em;
284-
display: flex;
285-
gap: 1em;
286-
287-
@media screen and (max-width: 600px) {
288-
padding-right: 2em;
289-
box-sizing: border-box;
290-
max-width: 95dvw;
291-
min-width: 0;
292-
overflow: auto;
293-
font-size: var(--font-down-1);
294-
padding-bottom: 0.5em;
295-
margin-bottom: 0.5em;
296-
297-
&::after {
298-
position: absolute;
299-
content: "";
300-
width: 4em;
301-
background: linear-gradient(
302-
to right,
303-
rgba(var(--secondary-rgb), 0),
304-
rgba(var(--secondary-rgb), 1)
305-
);
306-
right: 0;
307-
height: 2.5em;
308-
z-index: 2;
309-
}
310-
311-
button {
312-
display: flex;
313-
314-
.d-button-label {
315-
white-space: nowrap;
316-
}
317-
}
318-
}
319-
}
320-
321224
h1 {
322225
margin-bottom: 0.45em;
323226
max-width: 20em;
@@ -399,72 +302,6 @@ body.has-ai-conversations-sidebar {
399302
margin-top: 0;
400303
}
401304

402-
// custom header menus
403-
.custom-admin-menu-trigger {
404-
position: relative;
405-
background: transparent;
406-
407-
&.-has-messages {
408-
&::after {
409-
position: absolute;
410-
content: "";
411-
background: var(--danger);
412-
border-radius: 100%;
413-
padding: 0.25em;
414-
top: 0.5em;
415-
right: 0.25em;
416-
}
417-
}
418-
}
419-
420-
.custom-menu {
421-
.mod-message-badge {
422-
padding: 0.25em;
423-
background: var(--danger);
424-
border-radius: 100%;
425-
font-size: var(--font-down-3);
426-
}
427-
428-
&[class*="__links"] {
429-
margin: 0;
430-
list-style-type: none;
431-
display: flex;
432-
flex-direction: column;
433-
padding: 0.75em;
434-
gap: 0.25em;
435-
436-
li {
437-
.discourse-no-touch & {
438-
&:hover {
439-
background: var(--d-hover);
440-
}
441-
}
442-
}
443-
444-
.btn,
445-
a {
446-
box-sizing: border-box;
447-
display: inline-flex;
448-
justify-content: start;
449-
gap: 0.5em;
450-
width: 100%;
451-
color: var(--primary);
452-
padding: 0.25em 0.5em;
453-
line-height: var(--line-height-large);
454-
455-
.d-icon {
456-
color: var(--primary-high);
457-
}
458-
459-
span {
460-
display: flex;
461-
gap: 0.5em;
462-
align-items: center;
463-
}
464-
}
465-
}
466-
}
467-
468305
@media screen and (max-width: 600px) {
469306
.share-ai-conversation-button {
470307
.d-icon {

0 commit comments

Comments
 (0)