Compare commits

..
Author SHA1 Message Date
Jordan Vidrine 47fdb1acbf FIX: Adjust for overlap in AI buttons 2023-11-04 12:48:46 -05:00
94 changed files with 31 additions and 966 deletions
@@ -1,12 +0,0 @@
# frozen_string_literal: true
module DiscourseAi
module Admin
class DashboardController < ::Admin::StaffController
requires_plugin DiscourseAi::PLUGIN_NAME
def sentiment
end
end
end
end
-121
View File
@@ -1,121 +0,0 @@
# frozen_string_literal: true
class AiPersona < ActiveRecord::Base
# places a hard limit, so per site we cache a maximum of 500 classes
MAX_PERSONAS_PER_SITE = 500
class MultisiteHash
def initialize(id)
@hash = Hash.new { |h, k| h[k] = {} }
@id = id
MessageBus.subscribe(channel_name) { |message| @hash[message.data] = {} }
end
def channel_name
"/multisite-hash-#{@id}"
end
def current_db
RailsMultisite::ConnectionManagement.current_db
end
def [](key)
@hash.dig(current_db, key)
end
def []=(key, val)
@hash[current_db][key] = val
end
def flush!
@hash[current_db] = {}
MessageBus.publish(channel_name, current_db)
end
end
def self.persona_cache
@persona_cache ||= MultisiteHash.new("persona_cache")
end
def self.all_personas
persona_cache[:value] ||= AiPersona
.order(:name)
.where(enabled: true)
.all
.limit(MAX_PERSONAS_PER_SITE)
.map do |ai_persona|
name = ai_persona.name
description = ai_persona.description
ai_persona_id = ai_persona.id
allowed_group_ids = ai_persona.allowed_group_ids
commands =
ai_persona.commands.filter_map do |inner_name|
begin
("DiscourseAi::AiBot::Commands::#{inner_name}").constantize
rescue StandardError
nil
end
end
Class.new(DiscourseAi::AiBot::Personas::Persona) do
define_singleton_method :name do
name
end
define_singleton_method :description do
description
end
define_singleton_method :allowed_group_ids do
allowed_group_ids
end
define_singleton_method :to_s do
"#<DiscourseAi::AiBot::Personas::Persona::Custom @name=#{self.name} @allowed_group_ids=#{self.allowed_group_ids.join(",")}>"
end
define_singleton_method :inspect do
"#<DiscourseAi::AiBot::Personas::Persona::Custom @name=#{self.name} @allowed_group_ids=#{self.allowed_group_ids.join(",")}>"
end
define_method :initialize do |*args, **kwargs|
@ai_persona = AiPersona.find_by(id: ai_persona_id)
super(*args, **kwargs)
end
define_method :commands do
commands
end
define_method :system_prompt do
@ai_persona&.system_prompt || "You are a helpful bot."
end
end
end
end
after_commit :bump_cache
def bump_cache
self.class.persona_cache.flush!
end
end
# == Schema Information
#
# Table name: ai_personas
#
# id :bigint not null, primary key
# name :string(100) not null
# description :string(2000) not null
# commands :string default([]), not null, is an Array
# system_prompt :string not null
# allowed_group_ids :integer default([]), not null, is an Array
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_ai_personas_on_name (name) UNIQUE
#
@@ -1,10 +0,0 @@
export default {
resource: "admin.dashboard",
path: "/dashboard",
map() {
this.route("admin.dashboardSentiment", {
path: "/dashboard/sentiment",
resetNamespace: true,
});
},
};
@@ -1,8 +1,13 @@
import Component from "@glimmer/component";
import ChatChannel from "discourse/plugins/chat/discourse/models/chat-channel";
import { inject as service } from "@ember/service";
export default class ReviewableAiChatMessage extends Component {
@service store;
get chatChannel() {
return ChatChannel.create(this.args.reviewable.chat_channel);
return this.store.createRecord(
"chat-channel",
this.args.reviewable.chat_channel
);
}
}
@@ -1,19 +0,0 @@
import Component from "@glimmer/component";
import { LinkTo } from "@ember/routing";
import I18n from "discourse-i18n";
const i18n = I18n.t.bind(I18n);
export default class AISentimentDashboard extends Component {
<template>
<li class="navigation-item sentiment">
<LinkTo @route="admin.dashboardSentiment" class="navigation-link">
{{i18n "discourse_ai.sentiments.dashboard.title"}}
</LinkTo>
</li>
</template>
static shouldRender(_outletArgs, helper) {
return helper.siteSettings.ai_sentiment_enabled;
}
}
@@ -1,38 +0,0 @@
import Controller from "@ember/controller";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import getURL from "discourse-common/lib/get-url";
import discourseComputed from "discourse-common/utils/decorators";
import CustomDateRangeModal from "admin/components/modal/custom-date-range";
import PeriodComputationMixin from "admin/mixins/period-computation";
export default class AdminDashboardSentiment extends Controller.extend(
PeriodComputationMixin
) {
@service modal;
@discourseComputed("startDate", "endDate")
filters(startDate, endDate) {
return { startDate, endDate };
}
_reportsForPeriodURL(period) {
return getURL(`/admin/dashboard/sentiment?period=${period}`);
}
@action
setCustomDateRange(startDate, endDate) {
this.setProperties({ startDate, endDate });
}
@action
openCustomDateRangeModal() {
this.modal.show(CustomDateRangeModal, {
model: {
startDate: this.startDate,
endDate: this.endDate,
setCustomDateRange: this.setCustomDateRange,
},
});
}
}
@@ -1,39 +0,0 @@
<div class="sentiment section">
<div class="period-section">
<div class="section-title">
<h2>
{{i18n "discourse_ai.sentiments.dashboard.title"}}
</h2>
<span>
<PeriodChooser
@period={{this.period}}
@action={{action "changePeriod"}}
@content={{this.availablePeriods}}
@fullDay={{false}}
/>
<DButton
@icon="cog"
class="custom-date-range-button"
@action={{this.openCustomDateRangeModal}}
@title="admin.dashboard.custom_date_range"
/>
</span>
</div>
</div>
<div class="section-body">
<div class="charts">
<AdminReport
@dataSourceName="overall_sentiment"
@filters={{this.filters}}
@showHeader={{true}}
/>
<AdminReport
@dataSourceName="post_emotion"
@filters={{this.filters}}
@showHeader={{true}}
/>
</div>
</div>
</div>
@@ -262,6 +262,10 @@
}
}
#reply-control .showing-ai-suggestions .category-chooser {
max-width: calc(100% - 41px); // width of AI button
}
.suggest-tags-button,
.suggest-category-button {
display: block;
@@ -292,13 +296,17 @@
position: relative;
}
// Prevent suggestion button from wrapping
#reply-control {
.with-category .showing-ai-suggestions .category-input,
.with-tags .showing-ai-suggestions .mini-tag-chooser {
flex-wrap: nowrap;
.select-kit {
max-width: calc(100% - 34px);
// Prevent suggestion button from wrapping on smaller screens
@media screen and (max-width: 768px) {
#reply-control .composer-fields.showing-ai-suggestions {
.category-input {
.category-chooser {
width: 10px;
}
+ .mini-tag-chooser {
width: 10px;
}
}
}
}
@@ -1,16 +0,0 @@
.dashboard.dashboard-sentiment {
.sentiment {
margin-bottom: 1em;
}
.navigation-item.sentiment {
border-bottom: 0.4em solid var(--tertiary);
}
.charts {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-column-gap: 1em;
grid-row-gap: 1em;
}
}
@@ -1,8 +0,0 @@
.dashboard.dashboard-sentiment .charts {
.overall-sentiment {
grid-column: span 8;
}
.post-emotion {
grid-column: span 4;
}
}
@@ -1,10 +0,0 @@
.dashboard.dashboard-sentiment {
.charts {
.overall-sentiment {
grid-column: span 12;
}
.post-emotion {
grid-column: span 12;
}
}
}
-3
View File
@@ -93,9 +93,6 @@ de:
gpt-3:
5-turbo: "GPT-3.5"
claude-2: "Claude 2"
sentiments:
dashboard:
title: "Stimmung"
review:
types:
reviewable_ai_post:
-3
View File
@@ -92,9 +92,6 @@ en:
gpt-3:
5-turbo: "GPT-3.5"
claude-2: "Claude 2"
sentiments:
dashboard:
title: "Sentiment"
review:
types:
-3
View File
@@ -93,9 +93,6 @@ he:
gpt-3:
5-turbo: "GPT-3.5"
claude-2: "Claude 2"
sentiments:
dashboard:
title: "רגש"
review:
types:
reviewable_ai_post:
-7
View File
@@ -70,9 +70,6 @@ ar:
errors:
prompt_message_length: تتجاوز الرسالة الحد الأقصى لعدد الحروف، والبالغ 1000 حرف، بمقدار %{idx}.
invalid_prompt_role: تنطوي الرسالة %{idx} على دور غير صالح.
reports:
overall_sentiment:
yaxis: "التاريخ"
discourse_ai:
ai_helper:
errors:
@@ -132,7 +129,3 @@ ar:
few: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
many: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
other: "قم بتكوين هذه الإعدادات أولًا: %{settings}"
sentiment:
reports:
post_emotion:
neutral: "محايد"
-5
View File
@@ -5,8 +5,3 @@
# https://translate.discourse.org/
be:
discourse_ai:
sentiment:
reports:
post_emotion:
neutral: "нейтральны"
-3
View File
@@ -5,6 +5,3 @@
# https://translate.discourse.org/
bg:
reports:
overall_sentiment:
yaxis: "Дата"
-3
View File
@@ -5,6 +5,3 @@
# https://translate.discourse.org/
bs_BA:
reports:
overall_sentiment:
yaxis: "Datum"
-8
View File
@@ -5,11 +5,3 @@
# https://translate.discourse.org/
ca:
reports:
overall_sentiment:
yaxis: "Data"
discourse_ai:
sentiment:
reports:
post_emotion:
neutral: "Neutre"
-3
View File
@@ -5,6 +5,3 @@
# https://translate.discourse.org/
cs:
reports:
overall_sentiment:
yaxis: "Datum"
-8
View File
@@ -5,11 +5,3 @@
# https://translate.discourse.org/
da:
reports:
overall_sentiment:
yaxis: "Dato"
discourse_ai:
sentiment:
reports:
post_emotion:
neutral: "Neutral"
-24
View File
@@ -92,15 +92,6 @@ de:
errors:
prompt_message_length: Die Nachricht %{idx} hat die 1000-Zeichen-Grenze überschritten.
invalid_prompt_role: Die Nachricht %{idx} hat eine ungültige Rolle.
reports:
overall_sentiment:
title: "Allgemeine Stimmung"
description: "Diese Grafik vergleicht die Anzahl der Beiträge, die als positiv oder negativ eingestuft werden."
xaxis: "Positiv(%)"
yaxis: "Datum"
post_emotion:
title: "Emotionen posten"
description: "Anzahl der Beiträge, die mit einer der folgenden Emotionen klassifiziert wurden, gruppiert nach dem Vertrauenslevel des Posters."
discourse_ai:
ai_helper:
errors:
@@ -172,18 +163,3 @@ de:
configuration_hint:
one: "Konfiguriere zunächst die Einstellung `%{setting}`."
other: "Konfiguriere zunächst diese Einstellungen: %{settings}"
sentiment:
reports:
overall_sentiment:
positive: "Positiv"
negative: "Negativ"
post_emotion:
tl_01: "Vertrauensstufen 0-1"
tl_234: "Vertrauensstufen 2+"
sadness: "Traurigkeit"
surprise: "Überraschung"
neutral: "Neutral"
fear: "Furcht"
anger: "Wut"
joy: "Freude"
disgust: "Ekel"
-3
View File
@@ -5,6 +5,3 @@
# https://translate.discourse.org/
el:
reports:
overall_sentiment:
yaxis: "Ημερομηνία"
-28
View File
@@ -99,18 +99,6 @@ en:
prompt_message_length: The message %{idx} is over the 1000 character limit.
invalid_prompt_role: The message %{idx} has an invalid role.
reports:
overall_sentiment:
title: "Overall sentiment"
description: "This chart compares the number of posts classified either positive or negative."
xaxis: "Positive(%)"
yaxis: "Date"
post_emotion:
title: "Post emotion"
description: "Number of posts classified with one of the following emotions, grouped by poster's trust level."
xaxis:
yaxis:
discourse_ai:
ai_helper:
errors:
@@ -184,19 +172,3 @@ en:
configuration_hint:
one: "Configure the `%{setting}` setting first."
other: "Configure these settings first: %{settings}"
sentiment:
reports:
overall_sentiment:
positive: "Positive"
negative: "Negative"
post_emotion:
tl_01: "Trust levels 0-1"
tl_234: "Trust levels 2+"
sadness: "Sadness"
surprise: "Surprise"
neutral: "Neutral"
fear: "Fear"
anger: "Anger"
joy: "Joy"
disgust: "Disgust"
-7
View File
@@ -70,9 +70,6 @@ es:
errors:
prompt_message_length: El mensaje %{idx} supera el límite de 1000 caracteres.
invalid_prompt_role: El mensaje %{idx} tiene un rol no válido.
reports:
overall_sentiment:
yaxis: "Fecha"
discourse_ai:
ai_helper:
errors:
@@ -112,7 +109,3 @@ es:
configuration_hint:
one: "Configura primero el ajuste `%{setting}`."
other: "Configura primero estos ajustes: %{settings}"
sentiment:
reports:
post_emotion:
neutral: "Neutro"
-8
View File
@@ -5,11 +5,3 @@
# https://translate.discourse.org/
et:
reports:
overall_sentiment:
yaxis: "Date"
discourse_ai:
sentiment:
reports:
post_emotion:
neutral: "Neutraalne"
-3
View File
@@ -7,9 +7,6 @@
fa_IR:
site_settings:
discourse_ai_enabled: "افزونه discourse AI را فعال کنید."
reports:
overall_sentiment:
yaxis: "تاریخ"
discourse_ai:
ai_bot:
command_summary:
-7
View File
@@ -70,9 +70,6 @@ fi:
errors:
prompt_message_length: Viesti %{idx} ylittää 1 000 merkin rajan.
invalid_prompt_role: Viestillä %{idx} on virheellinen rooli.
reports:
overall_sentiment:
yaxis: "Päivämäärä"
discourse_ai:
ai_helper:
errors:
@@ -112,7 +109,3 @@ fi:
configuration_hint:
one: "Määritä ensin %{setting}-asetus."
other: "Määritä ensin nämä asetukset: %{settings}"
sentiment:
reports:
post_emotion:
neutral: "Neutraali"
-7
View File
@@ -70,9 +70,6 @@ fr:
errors:
prompt_message_length: Le message %{idx} dépasse la limite de 1 000 caractères.
invalid_prompt_role: Le message %{idx} a un rôle invalide.
reports:
overall_sentiment:
yaxis: "Date"
discourse_ai:
ai_helper:
errors:
@@ -112,7 +109,3 @@ fr:
configuration_hint:
one: "Configurez d'abord le paramètre « %{setting} »."
other: "Configurez d'abord ces paramètres : %{settings}"
sentiment:
reports:
post_emotion:
neutral: "Neutre"
-8
View File
@@ -5,11 +5,3 @@
# https://translate.discourse.org/
gl:
reports:
overall_sentiment:
yaxis: "Data"
discourse_ai:
sentiment:
reports:
post_emotion:
neutral: "Neutro"

Some files were not shown because too many files have changed in this diff Show More