153 lines
3.5 KiB
JavaScript
153 lines
3.5 KiB
JavaScript
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();
|
|
}
|
|
}
|