UX: Disclose AI model used and add animation to placeholder (#22670)

* UX: Disclose AI model used and add animation to placeholder

* Move text into hbs template

DTooltip (weirdly) attaches to a sibling element, so we need something else to be rendered inside the RenderGlimmer wrapper div

---------

Co-authored-by: David Taylor <david@taylorhq.com>
This commit is contained in:
Roman Rizzi 2023-07-19 12:03:36 -03:00 committed by GitHub
parent 00ab94bf53
commit 3820fae041
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 60 deletions

View File

@ -1,5 +1,5 @@
import { createWidget } from "discourse/widgets/widget";
import hbs from "discourse/widgets/hbs-compiler";
import { hbs } from "ember-cli-htmlbars";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { cookAsync } from "discourse/lib/text";
@ -7,18 +7,35 @@ import RawHtml from "discourse/widgets/raw-html";
import I18n from "I18n";
import { shortDateNoYear } from "discourse/lib/formatter";
import { h } from "virtual-dom";
import { iconNode } from "discourse-common/lib/icon-library";
import RenderGlimmer from "discourse/widgets/render-glimmer";
createWidget("summary-skeleton", {
tagName: "section.placeholder-summary",
template: hbs`
<div class="placeholder-summary-text placeholder-animation"></div>
<div class="placeholder-summary-text placeholder-animation"></div>
<div class="placeholder-summary-text placeholder-animation"></div>
<div class="placeholder-summary-text">{{transformed.in_progress_label}}</div>
`,
transform() {
return { in_progress_label: I18n.t("summary.in_progress") };
html() {
const html = [];
html.push(this.buildPlaceholderDiv());
html.push(this.buildPlaceholderDiv());
html.push(this.buildPlaceholderDiv());
html.push(
h("span", {}, [
iconNode("magic", { class: "rotate-center" }),
h(
"p.placeholder-generating-summary-text",
{},
I18n.t("summary.in_progress")
),
])
);
return html;
},
buildPlaceholderDiv() {
return h("div.placeholder-summary-text.placeholder-animation");
},
});
@ -30,41 +47,28 @@ export default createWidget("summary-box", {
return { expandSummarizedOn: false };
},
html(attrs, state) {
html(attrs) {
const html = [];
if (attrs.summary) {
html.push(new RawHtml({ html: `<div>${attrs.summary}</div>` }));
if (state.expandSummarizedOn) {
html.push(
h(
"div.summarized-on",
{},
I18n.t("summary.summarized_on", {
method: attrs.summarizedBy,
date: attrs.summarizedOn,
})
)
);
} else {
html.push(
h("div.summarized-on", [
this.attach("button", {
className: "btn btn-link summarized-on",
translatedTitle: I18n.t("summary.summarized_on", {
method: "AI",
h("div.summarized-on", {}, [
new RenderGlimmer(
this,
"div",
hbs`{{@data.summarizedOn}}<DTooltip @placement="top-end">{{d-icon "info-circle"}}
{{i18n "summary.model_used" model=@data.attrs.summarizedBy}}
</DTooltip>`,
{
attrs,
summarizedOn: I18n.t("summary.summarized_on", {
date: attrs.summarizedOn,
}),
translatedLabel: I18n.t("summary.summarized_on", {
method: "AI",
date: attrs.summarizedOn,
}),
action: "showFullSummarizedOn",
}),
}
),
])
);
}
} else {
html.push(this.attach("summary-skeleton"));
this.fetchSummary(attrs.topicId);

View File

@ -2,6 +2,7 @@
@import "vendor/normalize";
@import "vendor/normalize-ext";
@import "vendor/pikaday";
@import "vendor/rotate-center";
@import "vendor/tippy";
@import "vendor/svg-arrow";
@import "common/whcm";

View File

@ -58,6 +58,7 @@
@import "tooltip";
@import "topic-admin-menu";
@import "topic-post";
@import "topic-summary";
@import "topic";
@import "upload";
@import "user-badges";

View File

@ -838,27 +838,6 @@ aside.quote {
margin-left: 0.25em;
}
}
.toggle-summary {
.summarization-buttons {
display: flex;
}
.placeholder-summary {
padding-top: 0.5em;
}
.placeholder-summary-text {
display: inline-block;
height: 1em;
margin-top: 0.6em;
width: 100%;
}
.summarized-on {
text-align: right;
}
}
}
.topic-avatar,

View File

@ -0,0 +1,38 @@
.topic-map {
.toggle-summary {
.summarization-buttons {
display: flex;
}
.placeholder-summary {
padding-top: 0.5em;
}
.placeholder-summary-text {
display: inline-block;
height: 1em;
margin-top: 0.6em;
width: 100%;
}
.rotate-center {
-webkit-animation: rotate-center 3s cubic-bezier(0.68, -0.55, 0.265, 1.55)
0.5s infinite both;
animation: rotate-center 3s cubic-bezier(0.68, -0.55, 0.265, 1.55) 0.5s
infinite both;
}
.placeholder-generating-summary-text {
display: inline-block;
margin-left: 3px;
}
.summarized-on {
text-align: right;
.model-used {
margin-left: 3px;
}
}
}
}

View File

@ -0,0 +1,32 @@
/* ----------------------------------------------
* Generated by Animista on 2023-7-17 8:32:34
* Licensed under FreeBSD License.
* See http://animista.net/license for more info.
* w: http://animista.net, t: @cssanimista
* ---------------------------------------------- */
/**
* ----------------------------------------
* animation rotate-center
* ----------------------------------------
*/
@-webkit-keyframes rotate-center {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes rotate-center {
0% {
-webkit-transform: rotate(0);
transform: rotate(0);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}

View File

@ -2041,7 +2041,8 @@ en:
summary:
in_progress: "Summarizing topic using AI..."
summarized_on: "Summarized with %{method} on %{date}"
summarized_on: "Summarized with AI on %{date}"
model_used: "AI used: %{model}"
enabled_description: "You're viewing this topic top replies: the most interesting posts as determined by the community."
description:
one: "There is <b>%{count}</b> reply."