[IMP] web_editor: general improvements to ChatGPT alternatives dialog

With this commit, opening the ChatGPT alternatives dialog still
generates three alternatives, but whenever the user clicks on one of the
buttons:

1. one new version is generated (rather than three)
2. this new version is added at the top of the list (rather than
   replacing everything)
3. older versions are showed in grey so as to differenciate them from
   the new one
4. a badge next to each version shows which instruction was used to
   generate it (shorten, lengthen, etc.)

Since we add new versions from bottom to top, the spinner is now shown
above the existing versions.

Since a badge is added, it's not necessary to keep the last used button
green anymore so once the AI is done generating the new version, the
button returns to its blue state.

task-3572397

Part-of: odoo/odoo#139857
This commit is contained in:
Antoine Guenet
2023-11-02 16:57:48 +00:00
parent 752624a2f2
commit 5be690a553
2 changed files with 27 additions and 16 deletions
@@ -40,6 +40,7 @@ export class ChatGPTAlternativesDialog extends ChatGPTDialog {
}],
messages: [],
alternativesMode: '',
messagesInProgress: 0,
currentBatchId: null,
});
this._generationIndex = 0;
@@ -52,20 +53,20 @@ export class ChatGPTAlternativesDialog extends ChatGPTDialog {
switchAlternativesMode(ev) {
this.state.alternativesMode = ev.currentTarget.getAttribute('data-mode');
this.state.messages = [];
this._generateAlternatives();
this._generateAlternatives(1);
}
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
async _generateAlternatives() {
async _generateAlternatives(numberOfAlternatives = this.props.numberOfAlternatives) {
this.state.messagesInProgress = numberOfAlternatives;
const batchId = new Date().getTime();
this.state.currentBatchId = batchId;
let wasError = false;
let messageIndex = 0;
while (!wasError && messageIndex < this.props.numberOfAlternatives && this.state.currentBatchId === batchId) {
while (!wasError && messageIndex < numberOfAlternatives && this.state.currentBatchId === batchId) {
this._generationIndex += 1;
let query = messageIndex ? 'Write one alternative version of the original text.' : 'Try again another single version of the original text.';
if (this.state.alternativesMode && !messageIndex) {
@@ -85,10 +86,12 @@ export class ChatGPTAlternativesDialog extends ChatGPTDialog {
content,
});
}
this.state.messages.push({
this.state.messages.unshift({
author: 'assistant',
text: alternative,
isError,
batchId,
mode: this.state.alternativesMode,
});
}
}).catch(() => {
@@ -98,9 +101,11 @@ export class ChatGPTAlternativesDialog extends ChatGPTDialog {
}
});
messageIndex += 1;
this.state.messagesInProgress -= 1;
if (wasError) {
break;
}
}
this.state.messagesInProgress = 0;
}
}
@@ -7,17 +7,26 @@
<div class="mb-3">
<t t-foreach="Object.entries(props.alternativesModes)"
t-as="alternative" t-key="alternative_index">
<button type="button" class="btn me-2 btn-sm"
t-att-class="state.alternativesMode == alternative[0] ? 'btn-success' : 'btn-info'"
<button type="button" class="btn me-2 btn-sm btn-info"
t-att-class="state.alternativesMode == alternative[0] and state.messagesInProgress ? 'btn-success' : 'btn-info'"
t-on-click="switchAlternativesMode" t-att-data-mode="alternative[0]">
<t t-out="alternative[1]"/>
</button>
</t>
</div>
<div class="list-group">
<div t-if="state.messagesInProgress" class="d-flex align" t-att-class="{ 'mb-3': state.messages.length }">
<img src="/web/static/img/spin.svg" alt="Loading..." class="me-2"
style="filter:invert(1); opacity: 0.5; width: 30px; height: 30px;"/>
<p class="m-0 text-muted align-self-center">
<em t-if="state.messagesInProgress == 1">Generating an alternative...</em>
<em t-else="">Generating <t t-out="state.messagesInProgress"/> alternatives...</em>
</p>
</div>
<t t-foreach="state.messages" t-as="message" t-key="message_index">
<t t-if="message.isError">
<div class="list-group-item o-chatgpt-alternative border-danger bg-danger o-message-error">
<div class="list-group-item o-chatgpt-alternative border-danger bg-danger o-message-error"
t-att-class="{ 'text-muted': state.currentBatchId != message.batchId }">
<t t-out="message.text"/>
</div>
</t>
@@ -25,18 +34,15 @@
<button type="button" class="list-group-item list-group-item-action o-chatgpt-alternative"
t-on-click="selectMessage"
t-att-data-message-index="message_index"
t-att-class="{ active: state.selectedMessage == message_index }">
t-att-class="{
active: state.selectedMessage == message_index,
'text-muted': state.currentBatchId != message.batchId,
}">
<span t-if="message.mode" class="badge bg-secondary float-end"><t t-out="props.alternativesModes[message.mode]"/></span>
<t t-out="formatContent(message.text)"/>
</button>
</t>
</t>
<div t-if="state.messages.length &lt; props.numberOfAlternatives and !(state.messages.length and state.messages[state.messages.length - 1].isError)" class="d-flex mt-2 align">
<img src="/web/static/img/spin.svg" alt="Loading..." class="me-2"
style="filter:invert(1); opacity: 0.5; width: 30px; height: 30px;"/>
<p class="m-0 text-muted align-self-center">
<em>Generating alternatives...</em>
</p>
</div>
</div>
</div>