discourse-ai/assets/javascripts/discourse/components/ai-bot-header-icon.gjs
Sam 8b1b6811f4
FEATURE: add support for uploads when starting a convo (#1301)
This commit introduces file upload capabilities to the AI Bot conversations interface and improves the overall dedicated UX experience. It also changes the experimental setting to a more permanent one.

## Key changes:

- **File upload support**:
  - Integrates UppyUpload for handling file uploads in conversations
  - Adds UI for uploading, displaying, and managing attachments
  - Supports drag & drop, clipboard paste, and manual file selection
  - Shows upload progress indicators for in-progress uploads
  - Appends uploaded file markdown to message content

- **Renamed setting**:
  - Changed `ai_enable_experimental_bot_ux` to `ai_bot_enable_dedicated_ux`
  - Updated setting description to be clearer
  - Changed default value to `true` as this is now a stable feature
  - Added migration to handle the setting name change in database

- **UI improvements**:
  - Enhanced input area with better focus states
  - Improved layout and styling for conversations page
  - Added visual feedback for upload states
  - Better error handling for uploads in progress

- **Code organization**:
  - Refactored message submission logic to handle attachments
  - Updated DOM element IDs for consistency
  - Fixed focus management after submission

- **Added tests**:
  - Tests for file upload functionality
  - Tests for removing uploads before submission
  - Updated existing tests to work with the renamed setting


---------

Co-authored-by: awesomerobot <kris.aubuchon@discourse.org>
2025-05-01 12:21:07 +10:00

77 lines
2.2 KiB
Text

import Component from "@glimmer/component";
import { hash } from "@ember/helper";
import { action } from "@ember/object";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import PluginOutlet from "discourse/components/plugin-outlet";
import { defaultHomepage } from "discourse/lib/utilities";
import { i18n } from "discourse-i18n";
import { composeAiBotMessage } from "../lib/ai-bot-helper";
import { AI_CONVERSATIONS_PANEL } from "../services/ai-conversations-sidebar-manager";
export default class AiBotHeaderIcon extends Component {
@service composer;
@service currentUser;
@service navigationMenu;
@service router;
@service sidebarState;
@service siteSettings;
get bots() {
const availableBots = this.currentUser.ai_enabled_chat_bots
.filter((bot) => !bot.is_persosna)
.filter(Boolean);
return availableBots ? availableBots.map((bot) => bot.model_name) : [];
}
get showHeaderButton() {
return this.bots.length > 0 && this.siteSettings.ai_bot_add_to_header;
}
get icon() {
if (this.clickShouldRouteOutOfConversations) {
return "shuffle";
}
return "robot";
}
get clickShouldRouteOutOfConversations() {
return (
!this.navigationMenu.isHeaderDropdownMode &&
this.siteSettings.ai_bot_enable_dedicated_ux &&
this.sidebarState.currentPanel?.key === AI_CONVERSATIONS_PANEL
);
}
@action
onClick() {
if (this.clickShouldRouteOutOfConversations) {
return this.router.transitionTo(`discovery.${defaultHomepage()}`);
}
if (this.siteSettings.ai_bot_enable_dedicated_ux) {
return this.router.transitionTo("discourse-ai-bot-conversations");
}
composeAiBotMessage(this.bots[0], this.composer);
}
<template>
{{#if this.showHeaderButton}}
<li>
<PluginOutlet
@name="ai-bot-header-icon"
@outletArgs={{hash onClick=this.onClick icon=this.icon}}
>
<DButton
@action={{this.onClick}}
@icon={{this.icon}}
title={{i18n "discourse_ai.ai_bot.shortcut_title"}}
class="ai-bot-button icon btn-flat"
/>
</PluginOutlet>
</li>
{{/if}}
</template>
}