Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 38 additions & 29 deletions assets/javascripts/discourse/components/ai-gist-toggle.gjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,66 @@ import { action } from "@ember/object";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import DropdownMenu from "discourse/components/dropdown-menu";
import bodyClass from "discourse/helpers/body-class";
import icon from "discourse-common/helpers/d-icon";
import i18n from "discourse-common/helpers/i18n";
import DMenu from "float-kit/components/d-menu";
import eq from "truth-helpers/helpers/eq";

export default class AiGistToggle extends Component {
@service router;
@service gistPreference;

get shouldShow() {
return this.router.currentRoute.attributes?.list?.topics?.some(
(topic) => topic.ai_topic_gist
);
}
@service gists;

get buttons() {
return [
{
id: "gists_enabled",
label: "discourse_ai.summarization.gists_enabled_long",
icon: "discourse-sparkles",
id: "table",
label: "discourse_ai.summarization.topic_list_layout.button.compact",
icon: "discourse-table",
},
{
id: "gists_disabled",
label: "discourse_ai.summarization.gists_disabled",
icon: "far-eye-slash",
id: "table-ai",
label: "discourse_ai.summarization.topic_list_layout.button.expanded",
icon: "discourse-table-sparkles",
description:
"discourse_ai.summarization.topic_list_layout.button.expanded_description",
},
];
}

get selectedOptionId() {
return this.gists.get("preference");
}

get currentButton() {
const buttonPreference = this.buttons.find(
(button) => button.id === this.selectedOptionId
);
return buttonPreference || this.buttons[0];
}

@action
onRegisterApi(api) {
this.dMenu = api;
}

@action
onSelect(optionId) {
this.gistPreference.setPreference(optionId);
this.gists.setPreference(optionId);
this.dMenu.close();
}

<template>
{{#if this.shouldShow}}

{{#if this.gists.shouldShow}}
{{bodyClass (concat "topic-list-layout-" this.gists.preference)}}
<DMenu
@modalForMobile={{true}}
@autofocus={{true}}
@identifier="ai-gists-dropdown"
@identifier="topic-list-layout"
@onRegisterApi={{this.onRegisterApi}}
@triggerClass="btn-transparent"
@triggerClass="btn-default btn-icon"
>
<:trigger>
<span class="d-button-label">
{{i18n
(concat
"discourse_ai.summarization." this.gistPreference.preference
)
}}
</span>
{{icon "angle-down"}}
{{icon this.currentButton.icon}}
</:trigger>
<:content>
<DropdownMenu as |dropdown|>
Expand All @@ -71,9 +72,17 @@ export default class AiGistToggle extends Component {
<DButton
@label={{button.label}}
@icon={{button.icon}}
class="btn-transparent"
class="btn-transparent
{{if button.description '--with-description'}}
{{if (eq this.currentButton.id button.id) '--active'}}"
@action={{fn this.onSelect button.id}}
/>
>
{{#if button.description}}
<div class="btn__description">
{{i18n button.description}}
</div>
{{/if}}
</DButton>
</dropdown.item>
{{/each}}
</DropdownMenu>
Expand Down
33 changes: 16 additions & 17 deletions assets/javascripts/discourse/components/ai-topic-gist.gjs
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import bodyClass from "discourse/helpers/body-class";
import { htmlSafe } from "@ember/template";
import { emojiUnescape, sanitize } from "discourse/lib/text";

export default class AiTopicGist extends Component {
@service router;
@service gistPreference;
@service gists;

get prefersGist() {
return this.gistPreference.preference === "gists_enabled";
get shouldShow() {
return this.gists.preference === "table-ai" && this.gists.shouldShow;
}

get showGist() {
return (
this.args.topic?.ai_topic_gist &&
this.prefersGist &&
!this.args.topic?.excerpt
);
get gistOrExcerpt() {
const topic = this.args.topic;
const gist = topic.get("ai_topic_gist");
const excerpt = emojiUnescape(sanitize(topic.get("excerpt")));

return gist || excerpt;
}

<template>
{{#if this.showGist}}
{{bodyClass "--topic-list-with-gist"}}
<div class="ai-topic-gist">
<div class="ai-topic-gist__text">
{{@topic.ai_topic_gist}}
{{#if this.shouldShow}}
{{#if this.gistOrExcerpt}}
<div class="excerpt">
<div>{{htmlSafe this.gistOrExcerpt}}</div>
</div>
</div>
{{/if}}
{{/if}}
</template>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import AiGistToggle from "../../components/ai-gist-toggle";

export default class AiTopicGist extends Component {
@service topicThumbnails; // avoid Topic Thumbnails theme component

get shouldShow() {
return !this.topicThumbnails?.enabledForRoute;
}

<template>
<AiGistToggle />
</template>
}

This file was deleted.

This file was deleted.

12 changes: 0 additions & 12 deletions assets/javascripts/discourse/services/gist-preference.js

This file was deleted.

29 changes: 29 additions & 0 deletions assets/javascripts/discourse/services/gists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { tracked } from "@glimmer/tracking";
import Service, { service } from "@ember/service";

export default class Gists extends Service {
@service router;

@tracked preference = localStorage.getItem("topicListLayout");

get shouldShow() {
const currentRoute = this.router.currentRoute.name;
const isDiscovery = currentRoute.includes("discovery");
const isNotCategories = !currentRoute.includes("categories");
const gistsAvailable =
this.router.currentRoute.attributes?.list?.topics?.some(
(topic) => topic.ai_topic_gist
);

return isDiscovery && isNotCategories && gistsAvailable;
}

setPreference(value) {
this.preference = value;
localStorage.setItem("topicListLayout", value);

if (this.preference === "table-ai") {
localStorage.setItem("aiPreferred", true);
}
}
}
65 changes: 65 additions & 0 deletions assets/stylesheets/modules/summarization/common/ai-gists.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.topic-list-layout-content {
.btn.--with-description {
display: grid;
grid-template-areas: "icon title" "icon description";
grid-template-columns: auto 1fr;
text-align: left;
.btn__description {
grid-area: description;
width: 100%;
font-size: var(--font-down-1);
color: var(--primary-high);
}
}

.btn:focus {
background: transparent;
}

.btn:focus-visible {
outline: 2px solid var(--tertiary);
background: transparent;
outline-offset: -2px;
}

.btn.--active {
background: var(--d-selected);
}
}

.topic-list-layout-table-ai {
.topic-list-item {
.link-bottom-line {
font-size: var(--font-down-1);
margin-top: 0.25em;
line-height: var(--line-height-medium);
}
.excerpt {
width: 100%;
line-height: var(--line-height-large);
margin-top: 0.15em;
margin-bottom: 0.15em;
max-width: 70ch;
}
&:not(.visited) {
.excerpt {
color: var(--primary-high);
}
}
}
.topic-excerpt {
display: none;
}

.mobile-view & {
.topic-list-item .excerpt {
margin-top: -0.25em;
margin-bottom: 0.25em;
}

.topic-item-stats .num.activity {
align-self: end;
margin-bottom: -0.15em; // vertical alignment
}
}
}
74 changes: 0 additions & 74 deletions assets/stylesheets/modules/summarization/common/ai-summary.scss
Original file line number Diff line number Diff line change
Expand Up @@ -215,77 +215,3 @@
opacity: 1;
}
}

.ai-topic-gist {
width: 100%;
.mobile-view & {
position: relative;
top: -0.33em;
line-height: 1.4;
width: 90%;
}

&__text {
color: var(--primary-high);
text-wrap: pretty;
word-wrap: break-word;
font-size: var(--font-down-1);
max-width: 65ch;
.visited & {
color: var(--primary-medium);
}
}
}

.--topic-list-with-gist {
.topic-list-item {
.main-link {
line-height: var(--line-height-medium);
}
.link-bottom-line {
font-size: var(--font-down-1);
margin-top: 0.25em;
}
.ai-topic-gist {
font-size: var(--font-up-1);
line-height: var(--line-height-large);
margin-top: 0.25em;
margin-bottom: 0.15em;
}
.topic-post-badges {
font-size: var(--font-down-1);
}
}

.mobile-view & {
.topic-list {
.topic-list-item > .topic-list-data {
padding: 1em 0;
}
.topic-item-stats .num.activity {
align-self: end;
margin-bottom: -0.15em; // vertical alignment
}
.pull-left {
padding-top: 0.25em;
}
.right {
margin-left: 3.75em;
}
}
}
}

.ai-gists-dropdown-trigger {
font-size: var(--font-down-1);
color: var(--primary-medium);
padding-left: 0.25em;
.mobile-view & {
padding-left: 0;
color: var(--primary-high);
}
.d-icon {
color: var(--primary-low-mid);
margin-left: 0.15em;
}
}
Loading