DEV: Strip out old modal based AI helper (#209)

This commit is contained in:
Keegan George 2023-09-06 13:28:47 -07:00 committed by GitHub
parent 0733ff7e67
commit abe96d5533
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 1 additions and 408 deletions

View File

@ -1,69 +0,0 @@
<DModalBody @title="discourse_ai.ai_helper.title">
<span>{{i18n "discourse_ai.ai_helper.description"}}</span>
<ComboBox
@value={{this.selected}}
@content={{this.helperOptions}}
@onChange={{action this.updateSelected}}
@valueProperty="value"
@class="ai-helper-mode"
/>
<div class="text-preview">
<Textarea
@value={{this.composedMessage}}
disabled="true"
class="preview-area"
/>
</div>
<div class="selection-hint">{{i18n
"discourse_ai.ai_helper.selection_hint"
}}</div>
<div class="text-preview">
<ConditionalLoadingSpinner @condition={{this.loading}} />
{{#unless this.loading}}
{{#if this.selectingTopicTitle}}
<div class="radios">
{{#each this.generatedTitlesSuggestions as |title index|}}
<label class="radio-label" for="title-suggestion-{{index}}">
<RadioButton
@id="title-suggestion-{{index}}"
@name="title-suggestion"
@value={{title}}
@selection={{this.selectedTitle}}
/>
<b>{{title}}</b>
</label>
{{/each}}
</div>
{{else if this.proofreadingText}}
{{html-safe this.proofreadDiff}}
{{else if this.translatingText}}
<Textarea
@value={{this.translatedSuggestion}}
disabled="true"
class="preview-area"
/>
{{/if}}
{{/unless}}
</div>
</DModalBody>
<div class="modal-footer">
{{#if this.canSave}}
<DButton
@class="btn-primary create"
@action={{this.applySuggestion}}
@label="save"
/>
<DModalCancel @close={{route-action "closeModal"}} />
{{else}}
<div class="ai-helper-waiting-selection">{{i18n
"discourse_ai.modals.select_option"
}}</div>
{{/if}}
</div>

View File

@ -1,152 +0,0 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action, computed } from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
const LIST = "list";
const TEXT = "text";
const DIFF = "diff";
export default class AiHelper extends Component {
@tracked selected = null;
@tracked loading = false;
@tracked generatedTitlesSuggestions = [];
@tracked proofReadSuggestion = null;
@tracked translatedSuggestion = null;
@tracked selectedTitle = null;
@tracked proofreadDiff = null;
@tracked helperOptions = [];
prompts = [];
promptTypes = {};
constructor() {
super(...arguments);
this.loadPrompts();
}
async loadPrompts() {
let prompts = await ajax("/discourse-ai/ai-helper/prompts");
prompts.map((p) => {
this.prompts[p.id] = p;
});
this.promptTypes = prompts.reduce((memo, p) => {
memo[p.name] = p.prompt_type;
return memo;
}, {});
this.helperOptions = prompts.map((p) => {
return {
name: p.translated_name,
value: p.id,
};
});
}
get composedMessage() {
const editor = this.args.editor;
return editor.getSelected().value || editor.value;
}
@computed("selected", "selectedTitle", "translatingText", "proofreadingText")
get canSave() {
return (
(this.selected &&
this.prompts[this.selected].prompt_type === LIST &&
this.selectedTitle) ||
this.translatingText ||
this.proofreadingText
);
}
@computed("selected", "translatedSuggestion")
get translatingText() {
return (
this.selected &&
this.prompts[this.selected].prompt_type === TEXT &&
this.translatedSuggestion
);
}
@computed("selected", "proofReadSuggestion")
get proofreadingText() {
return (
this.selected &&
this.prompts[this.selected].prompt_type === DIFF &&
this.proofReadSuggestion
);
}
@computed("selected", "generatedTitlesSuggestions")
get selectingTopicTitle() {
return (
this.selected &&
this.prompts[this.selected].prompt_type === LIST &&
this.generatedTitlesSuggestions.length > 0
);
}
_updateSuggestedByAI(data) {
switch (data.type) {
case LIST:
this.generatedTitlesSuggestions = data.suggestions;
break;
case TEXT:
this.translatedSuggestion = data.suggestions[0];
break;
case DIFF:
this.proofReadSuggestion = data.suggestions[0];
this.proofreadDiff = data.diff;
break;
}
}
@action
async updateSelected(value) {
this.loading = true;
this.selected = value;
if (value === LIST) {
this.selectedTitle = null;
}
if (this.hasSuggestion) {
this.loading = false;
} else {
return ajax("/discourse-ai/ai-helper/suggest", {
method: "POST",
data: { mode: this.selected, text: this.composedMessage },
})
.then((data) => {
this._updateSuggestedByAI(data);
})
.catch(popupAjaxError)
.finally(() => (this.loading = false));
}
}
@action
applySuggestion() {
if (this.selectingTopicTitle) {
const composer = this.args.editor.outletArgs?.composer;
if (composer) {
composer.set("title", this.selectedTitle);
}
} else {
const newText = this.proofreadingText
? this.proofReadSuggestion
: this.translatedSuggestion;
this.args.editor.replaceText(this.composedMessage, newText);
}
this.args.closeModal();
}
}

View File

@ -39,7 +39,7 @@ export default class ModalDiffModal extends Component {
</:footer>
</DModal>
</template>
@action
triggerConfirmChanges() {
this.args.closeModal();

View File

@ -1 +0,0 @@
<AiHelper @editor={{this.editor}} @closeModal={{route-action "closeModal"}} />

View File

@ -1,72 +0,0 @@
import { withPluginApi } from "discourse/lib/plugin-api";
import showModal from "discourse/lib/show-modal";
function initializeComposerAIHelper(api) {
api.modifyClass("component:composer-editor", {
pluginId: "discourse-ai",
actions: {
extraButtons(toolbar) {
this._super(toolbar);
const removeAiHelperFromPM =
this.composerModel.privateMessage &&
!this.siteSettings.ai_helper_allowed_in_pm;
if (removeAiHelperFromPM) {
const extrasGroup = toolbar.groups.find((g) => g.group === "extras");
const newButtons = extrasGroup.buttons.filter(
(b) => b.id !== "ai-helper"
);
extrasGroup.buttons = newButtons;
}
},
},
});
api.modifyClass("component:d-editor", {
pluginId: "discourse-ai",
actions: {
openAIHelper() {
if (this.value) {
showModal("composer-ai-helper").setProperties({ editor: this });
}
},
},
});
api.onToolbarCreate((toolbar) => {
toolbar.addButton({
id: "ai-helper",
title: "discourse_ai.ai_helper.title",
group: "extras",
icon: "discourse-sparkles",
className: "composer-ai-helper",
sendAction: () => toolbar.context.send("openAIHelper"),
});
});
}
export default {
name: "discourse-ai-composer-helper",
initialize(container) {
const settings = container.lookup("service:site-settings");
const user = container.lookup("service:current-user");
const helperEnabled =
settings.discourse_ai_enabled && settings.composer_ai_helper_enabled;
const allowedGroups = settings.ai_helper_allowed_groups
.split("|")
.map((id) => parseInt(id, 10));
const canUseAssistant = user?.groups.some((g) =>
allowedGroups.includes(g.id)
);
if (helperEnabled && canUseAssistant) {
withPluginApi("1.6.0", initializeComposerAIHelper);
}
},
};

View File

@ -1,10 +1,4 @@
.composer-ai-helper-modal {
.combobox,
.text-preview,
.ai-helper-waiting-selection {
margin: 10px 0 10px 0;
}
.text-preview,
.inline-diff {
ins {
@ -31,11 +25,6 @@
background-color: var(--success-low);
color: var(--success);
}
.selection-hint {
font-size: var(--font-down-2);
margin-bottom: 20px;
}
}
.topic-above-suggested-outlet.related-topics {

View File

@ -13,7 +13,6 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
let(:composer) { PageObjects::Components::Composer.new }
let(:ai_helper_context_menu) { PageObjects::Components::AIHelperContextMenu.new }
let(:ai_helper_modal) { PageObjects::Modals::AiHelper.new }
let(:diff_modal) { PageObjects::Modals::DiffModal.new }
let(:ai_suggestion_dropdown) { PageObjects::Components::AISuggestionDropdown.new }
fab!(:category) { Fabricate(:category) }
@ -24,79 +23,6 @@ RSpec.describe "AI Composer helper", type: :system, js: true do
fab!(:feedback) { Fabricate(:tag) }
fab!(:review) { Fabricate(:tag) }
context "when using the translation mode" do
let(:mode) { OpenAiCompletionsInferenceStubs::TRANSLATE }
before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) }
it "replaces the composed message with AI generated content" do
visit("/latest")
page.find("#create-topic").click
composer.fill_content(OpenAiCompletionsInferenceStubs.spanish_text)
page.find(".composer-ai-helper").click
expect(ai_helper_modal).to be_visible
ai_helper_modal.select_helper_model(OpenAiCompletionsInferenceStubs.text_mode_to_id(mode))
ai_helper_modal.save_changes
expect(composer.composer_input.value).to eq(
OpenAiCompletionsInferenceStubs.translated_response.strip,
)
end
end
context "when using the proofreading mode" do
let(:mode) { OpenAiCompletionsInferenceStubs::PROOFREAD }
before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) }
it "replaces the composed message with AI generated content" do
visit("/latest")
page.find("#create-topic").click
composer.fill_content(OpenAiCompletionsInferenceStubs.translated_response)
page.find(".composer-ai-helper").click
expect(ai_helper_modal).to be_visible
ai_helper_modal.select_helper_model(OpenAiCompletionsInferenceStubs.text_mode_to_id(mode))
wait_for { ai_helper_modal.has_diff? == true }
ai_helper_modal.save_changes
expect(composer.composer_input.value).to eq(
OpenAiCompletionsInferenceStubs.proofread_response.strip,
)
end
end
context "when selecting an AI generated title" do
let(:mode) { OpenAiCompletionsInferenceStubs::GENERATE_TITLES }
before { OpenAiCompletionsInferenceStubs.stub_prompt(mode) }
it "replaces the topic title" do
visit("/latest")
page.find("#create-topic").click
composer.fill_content(OpenAiCompletionsInferenceStubs.translated_response)
page.find(".composer-ai-helper").click
expect(ai_helper_modal).to be_visible
ai_helper_modal.select_helper_model(OpenAiCompletionsInferenceStubs.text_mode_to_id(mode))
ai_helper_modal.select_title_suggestion(2)
ai_helper_modal.save_changes
expected_title = "The Quiet Piece that Moves Literature: A Gaucho's Story"
expect(find("#reply-title").value).to eq(expected_title)
end
end
def trigger_context_menu(content)
visit("/latest")
page.find("#create-topic").click

View File

@ -1,28 +0,0 @@
# frozen_string_literal: true
module PageObjects
module Modals
class AiHelper < PageObjects::Modals::Base
def visible?
page.has_css?(".composer-ai-helper-modal", wait: 5)
end
def select_helper_model(mode)
find(".ai-helper-mode").click
find(".select-kit-row[data-value=\"#{mode}\"]").click
end
def save_changes
find(".modal-footer button.create", wait: 5).click
end
def select_title_suggestion(option_number)
find("input#title-suggestion-#{option_number}").click
end
def has_diff?
has_css?(".text-preview .inline-diff")
end
end
end
end