docbrown/app/views/admin/articles/_article_item.html.erb
Rajat Talesra b397292a33
Admin comments page with flag and quality reaction details. (#19647)
* Created separate comments page

* Optimised code for single comment and multiple comments

* Indifual comments poage added

* Minor header change

* Created show method

* Full implementation with eager loading error

* Temporarily suppress Bullet from Admin::CommentsController

* Minor fixes

* Minor fixes

* Added table

* Added french translations

* Added reaction stats / summary

* Tests added fore empty comments

* Added seed data and few more tests

* Updated test

* Added model tests for comment and article

* Nit test fix

* Applied changes as per PJ's review

---------

Co-authored-by: Joshua Wehner <joshua@forem.com>
2023-07-05 22:05:35 +05:30

240 lines
14 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<% decorated_article = article.decorate %>
<div
data-controller="article"
data-article-id-value="<%= article.id %>"
data-article-pin-path-value="<%= stories_feed_pinned_article_path %>"
data-article-bg-highlighted-class="bg-highlighted"
data-article-border-highlighted-class="border-highlighted"
data-action="ajax:success@document->article#ajaxSuccess">
<article class="js-individual-article crayons-card p-6 flex flex-col gap-4">
<header>
<% if decorated_article.pinned? || article.featured || article.approved || (!article.published? && article.published_from_feed?) || article.video || article.user&.warned? %>
<div class="flex gap-1 mb-1">
<% if !article.published? && article.published_from_feed? %>
<span class="c-indicator c-indicator--danger"><%= t("views.moderations.article.unplublished") %></span>
<% end %>
<% if decorated_article.pinned? %>
<span class="c-indicator c-indicator--warning" data-testid="pinned-indicator"><%= t("views.moderations.article.pinned") %></span>
<% end %>
<% if article.featured %>
<span class="c-indicator c-indicator--success"><%= t("views.moderations.article.featured") %></span>
<% end %>
<% if article.approved %>
<span class="c-indicator c-indicator--info"><%= t("views.moderations.article.approved") %></span>
<% end %>
<% if article.video %>
<span class="c-indicator"><%= t("views.moderations.article.contains_video") %></span>
<% end %>
<% cache "admin-user-info-#{article.user_id}-#{article.user&.updated_at}", expires_in: 4.hours do %>
<% if article.user&.warned? %>
<span class="c-indicator c-indicator--danger"><%= t("views.moderations.article.user_warned") %></span>
<% end %>
<% end %>
</div>
<% end %>
<% if article.main_image.present? %>
<a href="<%= article.path %>" target="_blank" rel="noopener" class="c-link c-link--branded mb-4">
<img src="<%= cloud_cover_url(article.main_image) %>" style="background: <%= article.main_image_background_hex_color %>; max-height:150px; max-width: 300px;" alt="" loading="lazy" class="block radius-default h-auto w-100" />
</a>
<% end %>
<div class="flex justify-between gap-4 items-center">
<h2 class="crayons-subtitle-1">
<a href="<%= article.path %>" target="_blank" rel="noopener" class="c-link c-link--branded">
<%= article.title %>
</a>
</h2>
<div class="flex items-center gap-1">
<span class="crayons-card crayons-card--secondary px-3 py-1 flex gap-2 items-center" title="<%= t("views.moderations.actions.thumb_up") %>">
<%= crayons_icon_tag("twemoji/thumb-up", native: true, width: 16, height: 16) %>
<span class="fs-s fw-medium lh-base"><%= article.privileged_reaction_counts["thumbsup"] || "0" %></span>
</span>
<span class="crayons-card crayons-card--secondary px-3 py-1 flex gap-2 items-center" title="<%= t("views.moderations.actions.thumb_down") %>">
<%= crayons_icon_tag("twemoji/thumb-down", native: true, width: 16, height: 16) %>
<span class="fs-s fw-medium lh-base"><%= article.privileged_reaction_counts["thumbsdown"] || "0" %></span>
</span>
<span class="crayons-card crayons-card--secondary px-3 py-1 flex gap-2 items-center" title="<%= t("views.moderations.actions.vomit") %>">
<%= crayons_icon_tag("twemoji/suspicious", native: true, width: 16, height: 16) %>
<span class="fs-s fw-medium lh-base"><%= (@countable_vomits&.dig(article.id) || 0) %></span>
</span>
<span class="crayons-card crayons-card--secondary px-3 py-1 ml-3 flex gap-2 items-center" title="<%= t("views.moderations.actions.score") %>">
<%= crayons_icon_tag("analytics", native: true, width: 16, height: 16) %>
<span class="fs-s fw-medium lh-base"><%= article.score %></span>
</span>
</div>
</div>
<div class="-ml-1 fs-s flex items-center gap-4">
<div class="flex gap-px">
<% decorated_article.cached_tag_list_array.each do |tag| %>
<a class="crayons-tag crayons-tag--monochrome" href='<%= tag_path(tag) %>'><span class="crayons-tag__prefix">#</span><%= tag %></a>
<% end %>
</div>
<span>❤️&nbsp;<%= article.public_reactions_count %> <%= t("views.moderations.article.likes") %></span>
<span>💬&nbsp;<%= article.comments_count %> <%= t("views.moderations.article.comments") %></span>
</div>
<div class="flex justify-between gap-4 items-center">
<div>
<a href="<%= admin_user_path(article.user_id) %>" class="c-link">@<%= article.user&.username %></a>
<% if article.published_from_feed? && !article.published? %>
RSS Import <%= article.created_at.strftime("%b %d, %Y") %>
Originally Published <%= article.published_at&.strftime("%b %d, %Y") %>
<% elsif article.crossposted_at? %>
Crossposted <%= article.crossposted_at.strftime("%b %d, %Y") %> & Published
<%= article.published_at&.strftime("%b %d, %Y") %>
<% else %>
<%= article.published_at&.strftime("%b %d, %Y") %>
<% end %>
</div>
<div class="flex gap-1">
<% if !defined?(show_on_individual_article_only) || !show_on_individual_article_only %>
<a href="/admin/content_manager/articles/<%= article.id %>" class="c-link c-link--block">
<%= t("views.moderations.article.view_details") %>
</a>
<% end %>
<% if decorated_article.pinned? %>
<form method="post" action="<%= unpin_admin_article_path(decorated_article.id) %>" class="inline"
data-action="submit->article#unpinArticle">
<input type="hidden" name="_method" value="delete" />
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
<button type="submit" class="c-btn">
<%= t("views.moderations.article.unpin_post") %>
</button>
</form>
<% else %>
<form method="post" action="<%= pin_admin_article_path(decorated_article.id) %>" class="inline"
data-action="submit->article#pinArticle">
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
<button type="submit" class="c-btn">
<%= t("views.moderations.article.pin_post") %>
</button>
</form>
<% end %>
<a class="c-link c-link--block" href="<%= admin_user_path(article.user_id) %>" target="_blank" rel="noopener"><%= t("views.moderations.article.user") %></a>
<a href="<%= article.path %>/edit" target="_blank" rel="noopener" class="c-link c-link--block"><%= t("views.moderations.article.edit") %></a>
</div>
</div>
</header>
<% cache "admin-user-notes-#{article.user_id}-#{article.user&.updated_at}", expires_in: 4.hours do %>
<% if article.user&.notes&.any? %>
<div class="crayons-card crayons-card--secondary p-4 pt-3">
<div class="flex gap-2 items-center">
<h3 class="crayons-subtitle-2"><%= article.user&.notes&.size %> <%= t("views.moderations.article.notes.user_notes") %></h3>
<a href="<%= admin_user_path(article.user_id) %>" class="c-link c-link--block c-link--branded"><%= t("views.moderations.article.notes.view_all") %></a>
</div>
<% article.user&.notes&.last(3)&.each do |note| %>
<p>
<%= note.content %>
<span class="color-secondary fs-s">
<%= note.author_id ? User.find(note.author_id).username : "No author" %>
<time datetime="<%= note.created_at.strftime("%Y-%m-%dT%H:%M:%S%z") %>" title="<%= note.created_at.strftime("%Y-%m-%d, %H:%M") %>">
<%= note.created_at.strftime("%b %e '%y") %>
</time>
</span>
</p>
<% end %>
</div>
<% end %>
<% end %>
<%= form_with url: admin_article_path(article.id), model: article, local: true, class: "crayons-card crayons-card--secondary p-4 flex flex-col gap-3" do |f| %>
<input name="utf8" type="hidden" value="✓">
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>" />
<input type="hidden" name="_method" value="patch" />
<div class="flex gap-4">
<div class="crayons-field flex-1">
<label for="author_id_<%= article.id %>" class="crayons-field__label"><%= t("views.moderations.article.author_id") %></label>
<input id="author_id_<%= article.id %>" class="crayons-textfield" size="6" name="article[user_id]"
value="<%= article.user_id %>">
</div>
<div class="crayons-field flex-1">
<label for="co_author_ids_list_<%= article.id %>" class="crayons-field__label"><%= t("views.moderations.article.co_author_ids") %></label>
<input id="co_author_ids_list_<%= article.id %>" class="crayons-textfield" size="6" name="article[co_author_ids_list]" placeholder="Comma separated"
value="<%= article.co_author_ids&.join(", ") %>">
</div>
</div>
<% if article.published? %>
<div class="flex">
<div class="crayons-field">
<label for="published_at_<%= article.id %>" class="crayons-field__label"><%= t("views.moderations.article.published_at") %></label>
<div class="flex gap-1 items-center flex-wrap">
<%= f.datetime_select :published_at, { required: true, include_blank: true, include_seconds: true }, class: "crayons-select w-auto" %>
<span class="whitespace-nowrap color-secondary">UTC</span>
</div>
</div>
</div>
<% end %>
<div class="flex items-center gap-4">
<div class="crayons-field crayons-field--checkbox">
<%= f.check_box :featured, id: "featured-#{article.id}", class: "crayons-checkbox" %>
<label for="featured-<%= article.id %>" class="crayons-field__label">
<%= t("views.moderations.article.featured") %>
</label>
</div>
<div class="crayons-field crayons-field--checkbox">
<%= f.check_box :approved, id: "approved-#{article.id}", class: "crayons-checkbox" %>
<label for="approved-<%= article.id %>" class="crayons-field__label">
<%= t("views.moderations.article.approved") %>
</label>
</div>
</div>
<div>
<button class="c-btn c-btn--secondary"><%= t("views.moderations.article.save") %></button>
</div>
<% end %>
</article>
<% if defined?(show_on_individual_article_only) && show_on_individual_article_only %>
<% privileged_article_reactions = article.reactions.privileged_category.select { |reaction| reaction.reactable_type == "Article" } %>
<% vomit_article_reactions = privileged_article_reactions.select { |reaction| reaction.category == "vomit" }.reverse %>
<% quality_article_reactions = (privileged_article_reactions - vomit_article_reactions).reverse %>
<article class="js-individual-article crayons-card py-6 flex flex-col mt-4">
<h2 class="crayons-subtitle-2 mx-6"><%= t("views.admin.articles.priviliged_actions.title") %></h2>
<p class="crayons-subtitle-3 fw-normal color-secondary mt-1 mx-6"><%= t("views.admin.articles.priviliged_actions.description") %></p>
<nav class="mt-4 pt-1 pb-2 px-3 member-data-heading" aria-label="Member details">
<ul class="crayons-navigation crayons-navigation--horizontal">
<li><%= link_to "Flags", admin_article_path(tab: :flags), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if params[:tab] == 'flags' || params[:tab].blank?}", aria: @current_tab == "flags" ? { current: "" } : {} %></li></li>
<li><%= link_to "Quality reactions", admin_article_path(tab: :quality_reactions), class: "crayons-navigation__item #{'crayons-navigation__item crayons-navigation__item--current' if params[:tab] == 'quality_reactions'}",
aria: @current_tab == "quality_reactions" ? { current: "" } : {} %></li></li>
</ul>
</nav>
<div id="reaction-content" class="flex flex-col gap-3 px-6 mt-6" style="overflow: auto; height: 406px;">
<% if params[:tab].blank? || params[:tab] == "flags" %>
<%= render "admin/shared/flag_reactions_table",
vomit_reactions: vomit_article_reactions,
text_section: "articles",
empty_text: t("views.admin.articles.priviliged_actions.no_flags") %>
<% end %>
<% if params[:tab] == "quality_reactions" %>
<% if quality_article_reactions.present? %>
<% quality_article_reactions.each do |quality_reaction| %>
<%= render "admin/shared/quality_action_item", quality_reaction: quality_reaction %>
<hr id="js__reaction__div__hr__<%= quality_reaction.id %>" class="w-100 hr-no-margins">
<% end %>
<% else %>
<div class="flex flex-col justify-center items-center gap-4 h-100">
<div class="flex p-4 gap-2 radius-default" style="background: #EEF2FF;">
<%= crayons_icon_tag("quality-reactions", native: true, width: 56, height: 56) %>
</div>
<p class="crayons-subtitle-3 fw-normal color-secondary"><%= t("views.admin.articles.priviliged_actions.no_quality_reactions") %></p>
</div>
<% end %>
<% end %>
<div>
</article>
<% end %>
</div>