This update improves some of the UI around sentiment analysis reports: 1. Improve titles so it is above and truncated when long 2. Change doughnut to only show total count 3. Ensures sentiment posts have dates 4. Ensure expand post doesn't appear on short posts
102 lines
3.3 KiB
Ruby
102 lines
3.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseAi
|
|
module Sentiment
|
|
class SentimentController < ::Admin::StaffController
|
|
include Constants
|
|
requires_plugin ::DiscourseAi::PLUGIN_NAME
|
|
|
|
DEFAULT_POSTS_LIMIT = 50
|
|
MAX_POSTS_LIMIT = 100
|
|
|
|
def posts
|
|
group_by = params.required(:group_by)&.to_sym
|
|
group_value = params.required(:group_value).presence
|
|
start_date = params[:start_date].presence
|
|
end_date = params[:end_date]
|
|
threshold = SENTIMENT_THRESHOLD
|
|
|
|
raise Discourse::InvalidParameters if %i[category tag].exclude?(group_by)
|
|
|
|
limit = fetch_limit_from_params(default: DEFAULT_POSTS_LIMIT, max: MAX_POSTS_LIMIT)
|
|
offset = params[:offset].to_i || 0
|
|
|
|
case group_by
|
|
when :category
|
|
grouping_clause = "c.name"
|
|
grouping_join = "" # categories already joined
|
|
when :tag
|
|
grouping_clause = "tags.name"
|
|
grouping_join =
|
|
"INNER JOIN topic_tags tt ON tt.topic_id = p.topic_id INNER JOIN tags ON tags.id = tt.tag_id"
|
|
end
|
|
|
|
posts =
|
|
DB.query(
|
|
<<~SQL,
|
|
SELECT
|
|
p.id AS post_id,
|
|
p.topic_id,
|
|
t.title AS topic_title,
|
|
p.cooked as post_cooked,
|
|
p.user_id,
|
|
p.post_number,
|
|
p.created_at AS created_at,
|
|
u.username,
|
|
u.name,
|
|
u.uploaded_avatar_id,
|
|
c.id AS category_id,
|
|
c.name AS category_name,
|
|
c.color AS category_color,
|
|
c.slug AS category_slug,
|
|
c.description AS category_description,
|
|
(CASE
|
|
WHEN (cr.classification::jsonb->'positive')::float > :threshold THEN 'positive'
|
|
WHEN (cr.classification::jsonb->'negative')::float > :threshold THEN 'negative'
|
|
ELSE 'neutral'
|
|
END) AS sentiment
|
|
FROM posts p
|
|
INNER JOIN topics t ON t.id = p.topic_id
|
|
INNER JOIN classification_results cr ON cr.target_id = p.id AND cr.target_type = 'Post'
|
|
LEFT JOIN users u ON u.id = p.user_id
|
|
LEFT JOIN categories c ON c.id = t.category_id
|
|
#{grouping_join}
|
|
WHERE
|
|
#{grouping_clause} = :group_value AND
|
|
t.archetype = 'regular' AND
|
|
p.user_id > 0 AND
|
|
cr.model_used = 'cardiffnlp/twitter-roberta-base-sentiment-latest' AND
|
|
((:start_date IS NULL OR p.created_at > :start_date) AND (:end_date IS NULL OR p.created_at < :end_date))
|
|
AND p.deleted_at IS NULL
|
|
ORDER BY p.created_at DESC
|
|
LIMIT :limit OFFSET :offset
|
|
SQL
|
|
group_value: group_value,
|
|
start_date: start_date,
|
|
end_date: end_date,
|
|
threshold: threshold,
|
|
limit: limit + 1,
|
|
offset: offset,
|
|
)
|
|
|
|
has_more = posts.length > limit
|
|
posts.pop if has_more
|
|
|
|
render_json_dump(
|
|
posts:
|
|
serialize_data(
|
|
posts,
|
|
AiSentimentPostSerializer,
|
|
scope: guardian,
|
|
add_raw: true,
|
|
add_excerpt: true,
|
|
add_title: true,
|
|
),
|
|
has_more: has_more,
|
|
next_offset: has_more ? offset + limit : nil,
|
|
)
|
|
end
|
|
end
|
|
end
|
|
end
|