UX/DEV: Review queue redesign fixes (#20239)
* UX: add type tag and design update * UX: clarify status copy in reviewQ * DEV: switch to selectKit * UX: color approve/reject buttons in RQ * DEV: regroup actions * UX: add type tag and design update * UX: clarify status copy in reviewQ * Join questions for flagged post with "or" with new I18n function * Move ReviewableScores component out of context * Add CSS classes to reviewable-item based on human type * UX: add table header for scoring * UX: don't display % score * UX: prefix modifier class with dash * UX: reviewQ flag table styling * UX: consistent use of ignore icon * DEV: only show context question on pending status * UX: only show table headers on pending status * DEV: reviewQ regroup actions for hidden posts * UX: reviewQ > approve/reject buttons * UX: reviewQ add fadeout * UX: reviewQ styling * DEV: move scores back into component * UX: reviewQ mobile styling * UX: score table on mobile * UX: reviewQ > move meta info outside table * UX: reviewQ > score layout fixes * DEV: readd `agree_and_keep` and fix the spec tests. * Fix the spec tests * fix the quint test * DEV: readd deleting replies * UX: reviewQ copy tweaks * DEV: readd test for ignore + delete replies * Remove old * FIX: Add perform_ignore back in for backwards compat * DEV: add an action alias `ignore` for `ignore_and_do_nothing`. --------- Co-authored-by: Martin Brennan <martin@discourse.org> Co-authored-by: Vinoth Kannan <svkn.87@gmail.com>
This commit is contained in:
parent
67c0498f64
commit
e52bbc1230
|
@ -1,11 +1,11 @@
|
||||||
{{#if this.multiple}}
|
{{#if this.multiple}}
|
||||||
<DropdownSelectBox
|
<DropdownSelectBox
|
||||||
@class="reviewable-action-dropdown"
|
@class="reviewable-action-dropdown btn-icon-text"
|
||||||
@nameProperty="label"
|
@nameProperty="label"
|
||||||
@content={{this.bundle.actions}}
|
@content={{this.bundle.actions}}
|
||||||
@onChange={{action "performById"}}
|
@onChange={{action "performById"}}
|
||||||
@options={{hash
|
@options={{hash
|
||||||
icon=this.bundle.icon
|
showCaret=true
|
||||||
disabled=this.reviewableUpdating
|
disabled=this.reviewableUpdating
|
||||||
placement=this.placement
|
placement=this.placement
|
||||||
translatedNone=this.bundle.label
|
translatedNone=this.bundle.label
|
||||||
|
@ -19,7 +19,6 @@
|
||||||
" "
|
" "
|
||||||
this.first.button_class
|
this.first.button_class
|
||||||
}}
|
}}
|
||||||
@icon={{this.first.icon}}
|
|
||||||
@action={{action "perform" this.first}}
|
@action={{action "perform" this.first}}
|
||||||
@translatedLabel={{this.first.label}}
|
@translatedLabel={{this.first.label}}
|
||||||
@disabled={{this.reviewableUpdating}}
|
@disabled={{this.reviewableUpdating}}
|
||||||
|
|
|
@ -15,11 +15,13 @@
|
||||||
@tagName=""
|
@tagName=""
|
||||||
/>
|
/>
|
||||||
<div class="post-body">
|
<div class="post-body">
|
||||||
{{#if this.reviewable.blank_post}}
|
<div class="post-body__scroll">
|
||||||
<p>{{i18n "review.deleted_post"}}</p>
|
{{#if this.reviewable.blank_post}}
|
||||||
{{else}}
|
<p>{{i18n "review.deleted_post"}}</p>
|
||||||
{{html-safe this.reviewable.cooked}}
|
{{else}}
|
||||||
{{/if}}
|
{{html-safe this.reviewable.cooked}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>
|
<span>
|
||||||
<PluginOutlet
|
<PluginOutlet
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
class="reviewable-item {{this.customClasses}}"
|
class="reviewable-item {{this.customClasses}}"
|
||||||
>
|
>
|
||||||
<div class="reviewable-meta-data">
|
<div class="reviewable-meta-data">
|
||||||
<span class="reviewable-type">{{this.reviewable.humanType}}</span>
|
<span
|
||||||
|
class={{concat-class "reviewable-type" this.reviewable.humanTypeCssClass}}
|
||||||
|
>{{this.reviewable.humanType}}</span>
|
||||||
{{#if this.reviewable.reply_count}}
|
{{#if this.reviewable.reply_count}}
|
||||||
<span class="reply-count">{{i18n
|
<span class="reply-count">{{i18n
|
||||||
"review.replies"
|
"review.replies"
|
||||||
|
@ -65,6 +67,15 @@
|
||||||
{{/component}}
|
{{/component}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{#if (eq this.reviewable.type "ReviewableFlaggedPost")}}
|
||||||
|
{{#if (eq this.reviewable.status 0)}}
|
||||||
|
<h3 class="reviewable-item__context-question">
|
||||||
|
{{this.reviewable.flaggedPostContextQuestion}}
|
||||||
|
</h3>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="reviewable-actions">
|
<div class="reviewable-actions">
|
||||||
{{#if this.reviewable.last_performing_username}}
|
{{#if this.reviewable.last_performing_username}}
|
||||||
<div class="stale-help">{{html-safe
|
<div class="stale-help">{{html-safe
|
||||||
|
|
|
@ -4,25 +4,18 @@
|
||||||
{{avatar this.rs.user imageSize="tiny"}}
|
{{avatar this.rs.user imageSize="tiny"}}
|
||||||
{{this.rs.user.username}}
|
{{this.rs.user.username}}
|
||||||
</UserLink>
|
</UserLink>
|
||||||
<UserFlagPercentage
|
|
||||||
@agreed={{this.rs.agree_stats.agreed}}
|
|
||||||
@disagreed={{this.rs.agree_stats.disagreed}}
|
|
||||||
@ignored={{this.rs.agree_stats.ignored}}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{d-icon this.rs.score_type.icon}}
|
|
||||||
{{this.title}}
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
{{format-date this.rs.created_at format="tiny"}}
|
{{format-date this.rs.created_at format="tiny"}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{{#if this.showStatus}}
|
<td>
|
||||||
<td class="reviewable-score-spacer">
|
{{d-icon this.rs.score_type.icon}}
|
||||||
{{d-icon "angle-double-right"}}
|
{{this.title}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
{{#if this.showStatus}}
|
||||||
<td class="reviewed-by">
|
<td class="reviewed-by">
|
||||||
{{#if this.rs.reviewed_by}}
|
{{#if this.rs.reviewed_by}}
|
||||||
<UserLink @user={{this.rs.reviewed_by}}>
|
<UserLink @user={{this.rs.reviewed_by}}>
|
||||||
|
@ -34,46 +27,17 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
|
||||||
{{reviewable-status this.rs.status}}
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
{{#if this.rs.reviewed_by}}
|
{{#if this.rs.reviewed_by}}
|
||||||
{{format-date this.rs.reviewed_at format="tiny"}}
|
{{format-date this.rs.reviewed_at format="tiny"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{reviewable-status this.rs.status}}
|
||||||
|
</td>
|
||||||
|
|
||||||
{{else}}
|
{{else}}
|
||||||
<td colspan="4"></td>
|
<td colspan="4"></td>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
{{#if this.rs.reason}}
|
|
||||||
<tr>
|
|
||||||
<td colspan="7">
|
|
||||||
<div class="reviewable-score-reason">{{html-safe this.rs.reason}}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if this.rs.reviewable_conversation}}
|
|
||||||
<tr>
|
|
||||||
<td colspan="7">
|
|
||||||
<div class="reviewable-conversation">
|
|
||||||
{{#each
|
|
||||||
this.rs.reviewable_conversation.conversation_posts
|
|
||||||
as |p index|
|
|
||||||
}}
|
|
||||||
<ReviewableConversationPost @post={{p}} @index={{index}} />
|
|
||||||
{{/each}}
|
|
||||||
<div class="controls">
|
|
||||||
<a
|
|
||||||
href={{this.rs.reviewable_conversation.permalink}}
|
|
||||||
class="btn btn-small"
|
|
||||||
>
|
|
||||||
{{i18n "review.conversation.view_full"}}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{/if}}
|
|
|
@ -1,9 +1,44 @@
|
||||||
{{#if this.reviewable.reviewable_scores}}
|
{{#if this.reviewable.reviewable_scores}}
|
||||||
<table class="reviewable-scores">
|
<div class="reviewable-scores__table-wrapper">
|
||||||
<tbody>
|
<table class="reviewable-scores">
|
||||||
{{#each this.reviewable.reviewable_scores as |rs|}}
|
<thead>
|
||||||
<ReviewableScore @rs={{rs}} @reviewable={{this.reviewable}} />
|
<tr>
|
||||||
{{/each}}
|
<th>{{i18n "review.scores.submitted_by"}}</th>
|
||||||
</tbody>
|
<th>{{i18n "review.scores.date"}}</th>
|
||||||
</table>
|
<th>{{i18n "review.scores.type"}}</th>
|
||||||
|
<th>{{i18n "review.scores.reviewed_by"}}</th>
|
||||||
|
<th>{{i18n "review.scores.reviewed_timestamp"}}</th>
|
||||||
|
<th>{{i18n "review.scores.status"}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each this.reviewable.reviewable_scores as |rs|}}
|
||||||
|
<ReviewableScore @rs={{rs}} @reviewable={{this.reviewable}} />
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#each this.reviewable.reviewable_scores as |rs|}}
|
||||||
|
{{#if rs.reason}}
|
||||||
|
<div class="reviewable-score-reason">{{html-safe rs.reason}}</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if rs.reviewable_conversation}}
|
||||||
|
<div class="reviewable-conversation">
|
||||||
|
{{#each rs.reviewable_conversation.conversation_posts as |p index|}}
|
||||||
|
<ReviewableConversationPost @post={{p}} @index={{index}} />
|
||||||
|
{{/each}}
|
||||||
|
<div class="controls">
|
||||||
|
<a
|
||||||
|
href={{rs.reviewable_conversation.permalink}}
|
||||||
|
class="btn btn-small"
|
||||||
|
>
|
||||||
|
{{i18n "review.conversation.view_full"}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
{{/if}}
|
{{/if}}
|
|
@ -33,12 +33,10 @@ export function htmlStatus(status) {
|
||||||
let icon = data.icon ? iconHTML(data.icon) : "";
|
let icon = data.icon ? iconHTML(data.icon) : "";
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<span class='status'>
|
|
||||||
<span class="${data.name}">
|
<span class="${data.name}">
|
||||||
${icon}
|
${icon}
|
||||||
${I18n.t("review.statuses." + data.name + ".title")}
|
${I18n.t("review.statuses." + data.name + ".title")}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import categoryFromId from "discourse-common/utils/category-macro";
|
import categoryFromId from "discourse-common/utils/category-macro";
|
||||||
|
import { dasherize, underscore } from "@ember/string";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
import RestModel from "discourse/models/rest";
|
import RestModel from "discourse/models/rest";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { underscore } from "@ember/string";
|
|
||||||
|
|
||||||
export const PENDING = 0;
|
export const PENDING = 0;
|
||||||
export const APPROVED = 1;
|
export const APPROVED = 1;
|
||||||
|
@ -14,17 +14,50 @@ export const DELETED = 4;
|
||||||
|
|
||||||
const Reviewable = RestModel.extend({
|
const Reviewable = RestModel.extend({
|
||||||
@discourseComputed("type", "topic")
|
@discourseComputed("type", "topic")
|
||||||
humanType(type, topic) {
|
resolvedType(type, topic) {
|
||||||
// Display "Queued Topic" if the post will create a topic
|
// Display "Queued Topic" if the post will create a topic
|
||||||
if (type === "ReviewableQueuedPost" && !topic) {
|
if (type === "ReviewableQueuedPost" && !topic) {
|
||||||
type = "ReviewableQueuedTopic";
|
return "ReviewableQueuedTopic";
|
||||||
}
|
}
|
||||||
|
|
||||||
return I18n.t(`review.types.${underscore(type)}.title`, {
|
return type;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("resolvedType")
|
||||||
|
humanType(resolvedType) {
|
||||||
|
return I18n.t(`review.types.${underscore(resolvedType)}.title`, {
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed("humanType")
|
||||||
|
humanTypeCssClass(humanType) {
|
||||||
|
return "-" + dasherize(humanType);
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed
|
||||||
|
flaggedPostContextQuestion() {
|
||||||
|
const uniqueReviewableScores =
|
||||||
|
this.reviewable_scores.uniqBy("score_type.type");
|
||||||
|
|
||||||
|
if (uniqueReviewableScores.length === 1) {
|
||||||
|
if (uniqueReviewableScores[0].score_type.type === "notify_moderators") {
|
||||||
|
return I18n.t("review.context_question.something_else_wrong");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listOfQuestions = I18n.listJoiner(
|
||||||
|
uniqueReviewableScores
|
||||||
|
.map((score) => score.score_type.title.toLowerCase())
|
||||||
|
.uniq(),
|
||||||
|
I18n.t("review.context_question.delimiter")
|
||||||
|
);
|
||||||
|
|
||||||
|
return I18n.t("review.context_question.is_this_post", {
|
||||||
|
reviewable_human_score_types: listOfQuestions,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
category: categoryFromId("category_id"),
|
category: categoryFromId("category_id"),
|
||||||
|
|
||||||
update(updates) {
|
update(updates) {
|
||||||
|
|
|
@ -114,7 +114,9 @@ acceptance("Review", function (needs) {
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
query(".reviewable-flagged-post .post-body").innerHTML.trim(),
|
query(
|
||||||
|
".reviewable-flagged-post .post-body .post-body__scroll"
|
||||||
|
).innerHTML.trim(),
|
||||||
"<b>cooked content</b>"
|
"<b>cooked content</b>"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,19 @@ I18n.toHumanSize = function (number, options) {
|
||||||
return number;
|
return number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
I18n.listJoiner = function (listOfStrings, delimiter) {
|
||||||
|
if (listOfStrings.length === 1) {
|
||||||
|
return listOfStrings[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listOfStrings.length === 2) {
|
||||||
|
return listOfStrings[0] + " " + delimiter + " " + listOfStrings[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastString = listOfStrings.pop();
|
||||||
|
return listOfStrings.concat(delimiter).join(`, `) + " " + lastString;
|
||||||
|
};
|
||||||
|
|
||||||
I18n.pluralizer = function (locale) {
|
I18n.pluralizer = function (locale) {
|
||||||
var pluralizer = this.pluralizationRules[locale];
|
var pluralizer = this.pluralizationRules[locale];
|
||||||
if (pluralizer !== undefined) return pluralizer;
|
if (pluralizer !== undefined) return pluralizer;
|
||||||
|
|
|
@ -209,8 +209,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-item {
|
.reviewable-item {
|
||||||
padding-top: 2em;
|
background: var(--primary-very-low);
|
||||||
border-top: 1px solid var(--primary-low);
|
padding: 1.5rem;
|
||||||
|
|
||||||
.topic-statuses {
|
.topic-statuses {
|
||||||
font-size: var(--font-up-2);
|
font-size: var(--font-up-2);
|
||||||
|
@ -225,6 +225,21 @@
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
.reviewable-type {
|
.reviewable-type {
|
||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: var(--font-down-2);
|
||||||
|
color: var(--secondary);
|
||||||
|
border-radius: 8px;
|
||||||
|
&.-flagged-post,
|
||||||
|
&.-user,
|
||||||
|
&.-flagged-chat-message,
|
||||||
|
&.-aksimet-flagged-post,
|
||||||
|
&.-aksimet-flagged-user {
|
||||||
|
background-color: var(--danger-medium);
|
||||||
|
}
|
||||||
|
&.-queued-post {
|
||||||
|
background-color: var(--tertiary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.reply-count {
|
.reply-count {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
|
@ -244,16 +259,28 @@
|
||||||
.reviewable-contents {
|
.reviewable-contents {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-bottom: 2em;
|
margin: 1.5rem 0 1rem;
|
||||||
|
background: var(--secondary);
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-actions {
|
.reviewable-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.approve-post {
|
||||||
|
background-color: var(--success);
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
|
&.reject-post {
|
||||||
|
background-color: var(--danger);
|
||||||
|
color: var(--secondary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-action,
|
.reviewable-action,
|
||||||
|
@ -285,9 +312,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-scores {
|
.reviewable-scores {
|
||||||
|
margin-top: 1.5rem;
|
||||||
min-width: 50%;
|
min-width: 50%;
|
||||||
color: var(--primary-high);
|
color: var(--primary-high);
|
||||||
|
|
||||||
|
&__table-wrapper {
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.reviewed-by {
|
.reviewed-by {
|
||||||
.date {
|
.date {
|
||||||
margin-left: 0.5em;
|
margin-left: 0.5em;
|
||||||
|
@ -313,6 +349,16 @@
|
||||||
vertical-align: text-top;
|
vertical-align: text-top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.approved,
|
||||||
|
.approved svg {
|
||||||
|
color: var(--success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rejected,
|
||||||
|
.rejected svg {
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
|
|
||||||
tbody {
|
tbody {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
td {
|
td {
|
||||||
|
@ -324,27 +370,19 @@
|
||||||
@include ellipsis;
|
@include ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
td:last-of-type {
|
|
||||||
width: 100%;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
> tr > th {
|
> tr > th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
> tr > th,
|
> tr > th,
|
||||||
> tr > td {
|
> tr > td {
|
||||||
&:not(:empty) {
|
&:not(:empty) {
|
||||||
padding: 0.5em 1em 0.5em 0;
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
@include breakpoint("mobile-large") {
|
@include breakpoint("mobile-large") {
|
||||||
@include ellipsis;
|
@include ellipsis;
|
||||||
padding-right: 0.5em;
|
padding-right: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.reviewable-score-spacer {
|
|
||||||
padding-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,6 +411,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-item {
|
.reviewable-item {
|
||||||
|
margin-block: 3rem;
|
||||||
.show-raw-email {
|
.show-raw-email {
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
font-size: var(--font-down-2);
|
font-size: var(--font-down-2);
|
||||||
|
@ -425,10 +464,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.post-body {
|
.post-body {
|
||||||
|
position: relative;
|
||||||
max-width: var(--topic-body-width);
|
max-width: var(--topic-body-width);
|
||||||
max-height: 300px;
|
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
overflow-y: auto;
|
|
||||||
|
&__scroll {
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 1.5em;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgba(var(--secondary-rgb), 0),
|
||||||
|
rgba(var(--secondary-rgb), 100%)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p,
|
p,
|
||||||
aside {
|
aside {
|
||||||
|
@ -453,6 +508,10 @@
|
||||||
margin-right: 0.75em;
|
margin-right: 0.75em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__context-question {
|
||||||
|
margin-block: 1rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.editable-fields {
|
.editable-fields {
|
||||||
|
@ -486,28 +545,3 @@
|
||||||
.flag-modal .modal-inner-container .select-kit.reviewable-action-dropdown {
|
.flag-modal .modal-inner-container .select-kit.reviewable-action-dropdown {
|
||||||
width: initial;
|
width: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1000px) {
|
|
||||||
table.reviewable-scores {
|
|
||||||
width: 100%;
|
|
||||||
display: block;
|
|
||||||
tbody {
|
|
||||||
width: calc(100% - 5px);
|
|
||||||
display: block;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tr.reviewable-score {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: auto auto 1fr;
|
|
||||||
}
|
|
||||||
td.reviewable-score-spacer {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@include breakpoint("mobile-large") {
|
|
||||||
tr.reviewable-score {
|
|
||||||
grid-template-columns: auto auto auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -21,7 +21,34 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.reviewable-scores {
|
.reviewable-scores {
|
||||||
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow-x: scroll;
|
||||||
|
border-top: 1px solid var(--primary-low);
|
||||||
|
thead {
|
||||||
|
tr {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
display: flex;
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
.reviewable-score {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +85,6 @@
|
||||||
|
|
||||||
> div,
|
> div,
|
||||||
> button {
|
> button {
|
||||||
flex: 0 1 47%;
|
|
||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ module Jobs
|
||||||
.where("created_at < ?", SiteSetting.auto_handle_queued_age.to_i.days.ago)
|
.where("created_at < ?", SiteSetting.auto_handle_queued_age.to_i.days.ago)
|
||||||
.each do |reviewable|
|
.each do |reviewable|
|
||||||
if reviewable.is_a?(ReviewableFlaggedPost)
|
if reviewable.is_a?(ReviewableFlaggedPost)
|
||||||
reviewable.perform(Discourse.system_user, :ignore, expired: true)
|
reviewable.perform(Discourse.system_user, :ignore_and_do_nothing, expired: true)
|
||||||
elsif reviewable.is_a?(ReviewableQueuedPost)
|
elsif reviewable.is_a?(ReviewableQueuedPost)
|
||||||
reviewable.perform(Discourse.system_user, :reject_post)
|
reviewable.perform(Discourse.system_user, :reject_post)
|
||||||
elsif reviewable.is_a?(ReviewableUser)
|
elsif reviewable.is_a?(ReviewableUser)
|
||||||
|
|
|
@ -10,6 +10,7 @@ class ReviewableFlaggedPost < Reviewable
|
||||||
agree_and_silence: :agree_and_keep,
|
agree_and_silence: :agree_and_keep,
|
||||||
agree_and_suspend: :agree_and_keep,
|
agree_and_suspend: :agree_and_keep,
|
||||||
disagree_and_restore: :disagree,
|
disagree_and_restore: :disagree,
|
||||||
|
ignore_and_do_nothing: :ignore,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -56,6 +57,20 @@ class ReviewableFlaggedPost < Reviewable
|
||||||
build_action(actions, :agree_and_keep, icon: "thumbs-up", bundle: agree)
|
build_action(actions, :agree_and_keep, icon: "thumbs-up", bundle: agree)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if guardian.can_delete_post_or_topic?(post)
|
||||||
|
build_action(actions, :delete_and_agree, icon: "far-trash-alt", bundle: agree)
|
||||||
|
|
||||||
|
if post.reply_count > 0
|
||||||
|
build_action(
|
||||||
|
actions,
|
||||||
|
:delete_and_agree_replies,
|
||||||
|
icon: "far-trash-alt",
|
||||||
|
bundle: agree,
|
||||||
|
confirm: true,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if guardian.can_suspend?(target_created_by)
|
if guardian.can_suspend?(target_created_by)
|
||||||
build_action(
|
build_action(
|
||||||
actions,
|
actions,
|
||||||
|
@ -74,48 +89,43 @@ class ReviewableFlaggedPost < Reviewable
|
||||||
end
|
end
|
||||||
|
|
||||||
build_action(actions, :agree_and_restore, icon: "far-eye", bundle: agree) if post.user_deleted?
|
build_action(actions, :agree_and_restore, icon: "far-eye", bundle: agree) if post.user_deleted?
|
||||||
|
|
||||||
if post.hidden?
|
if post.hidden?
|
||||||
build_action(actions, :disagree_and_restore, icon: "thumbs-down")
|
build_action(actions, :disagree_and_restore, icon: "thumbs-down")
|
||||||
else
|
else
|
||||||
build_action(actions, :disagree, icon: "thumbs-down")
|
build_action(actions, :disagree, icon: "thumbs-down")
|
||||||
end
|
end
|
||||||
|
|
||||||
build_action(actions, :ignore, icon: "external-link-alt")
|
ignore =
|
||||||
|
actions.add_bundle(
|
||||||
delete_user_actions(actions) if potential_spam? && guardian.can_delete_user?(target_created_by)
|
"#{id}-ignore",
|
||||||
|
icon: "thumbs-up",
|
||||||
|
label: "reviewables.actions.ignore.title",
|
||||||
|
)
|
||||||
|
|
||||||
|
if !post.hidden?
|
||||||
|
build_action(actions, :ignore_and_do_nothing, icon: "external-link-alt", bundle: ignore)
|
||||||
|
end
|
||||||
if guardian.can_delete_post_or_topic?(post)
|
if guardian.can_delete_post_or_topic?(post)
|
||||||
delete =
|
build_action(actions, :delete_and_ignore, icon: "far-trash-alt", bundle: ignore)
|
||||||
actions.add_bundle(
|
|
||||||
"#{id}-delete",
|
|
||||||
icon: "far-trash-alt",
|
|
||||||
label: "reviewables.actions.delete.title",
|
|
||||||
)
|
|
||||||
build_action(actions, :delete_and_ignore, icon: "external-link-alt", bundle: delete)
|
|
||||||
if post.reply_count > 0
|
if post.reply_count > 0
|
||||||
build_action(
|
build_action(
|
||||||
actions,
|
actions,
|
||||||
:delete_and_ignore_replies,
|
:delete_and_ignore_replies,
|
||||||
icon: "external-link-alt",
|
icon: "far-trash-alt",
|
||||||
confirm: true,
|
|
||||||
bundle: delete,
|
|
||||||
)
|
|
||||||
end
|
|
||||||
build_action(actions, :delete_and_agree, icon: "thumbs-up", bundle: delete)
|
|
||||||
if post.reply_count > 0
|
|
||||||
build_action(
|
|
||||||
actions,
|
|
||||||
:delete_and_agree_replies,
|
|
||||||
icon: "external-link-alt",
|
|
||||||
bundle: delete,
|
|
||||||
confirm: true,
|
confirm: true,
|
||||||
|
bundle: ignore,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
delete_user_actions(actions) if potential_spam? && guardian.can_delete_user?(target_created_by)
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_ignore(performed_by, args)
|
def perform_ignore(performed_by, args)
|
||||||
|
perform_ignore_and_do_nothing(performed_by, args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_ignore_and_do_nothing(performed_by, args)
|
||||||
actions =
|
actions =
|
||||||
PostAction
|
PostAction
|
||||||
.active
|
.active
|
||||||
|
@ -221,13 +231,13 @@ class ReviewableFlaggedPost < Reviewable
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_delete_and_ignore(performed_by, args)
|
def perform_delete_and_ignore(performed_by, args)
|
||||||
result = perform_ignore(performed_by, args)
|
result = perform_ignore_and_do_nothing(performed_by, args)
|
||||||
destroyer(performed_by, post).destroy
|
destroyer(performed_by, post).destroy
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def perform_delete_and_ignore_replies(performed_by, args)
|
def perform_delete_and_ignore_replies(performed_by, args)
|
||||||
result = perform_ignore(performed_by, args)
|
result = perform_ignore_and_do_nothing(performed_by, args)
|
||||||
PostDestroyer.delete_with_replies(performed_by, post, self)
|
PostDestroyer.delete_with_replies(performed_by, post, self)
|
||||||
|
|
||||||
result
|
result
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class ReviewableScoreTypeSerializer < ApplicationSerializer
|
class ReviewableScoreTypeSerializer < ApplicationSerializer
|
||||||
attributes :id, :title, :reviewable_priority, :icon
|
attributes :id, :title, :reviewable_priority, :icon, :type
|
||||||
|
|
||||||
|
def type
|
||||||
|
ReviewableScore.types[id]
|
||||||
|
end
|
||||||
|
|
||||||
# Allow us to share post action type translations for backwards compatibility
|
# Allow us to share post action type translations for backwards compatibility
|
||||||
def title
|
def title
|
||||||
|
|
|
@ -581,28 +581,34 @@ en:
|
||||||
scores:
|
scores:
|
||||||
about: "This score is calculated based on the trust level of the reporter, the accuracy of their previous flags, and the priority of the item being reported."
|
about: "This score is calculated based on the trust level of the reporter, the accuracy of their previous flags, and the priority of the item being reported."
|
||||||
score: "Score"
|
score: "Score"
|
||||||
date: "Date"
|
date: "Report date"
|
||||||
type: "Type"
|
type: "Reason"
|
||||||
status: "Status"
|
status: "Status"
|
||||||
submitted_by: "Submitted By"
|
submitted_by: "Reported by"
|
||||||
reviewed_by: "Reviewed By"
|
reviewed_by: "Reviewed by"
|
||||||
|
reviewed_timestamp: "Review date"
|
||||||
|
|
||||||
statuses:
|
statuses:
|
||||||
pending:
|
pending:
|
||||||
title: "Pending"
|
title: "Pending"
|
||||||
approved:
|
approved:
|
||||||
title: "Approved"
|
title: "Flag approved"
|
||||||
rejected:
|
rejected:
|
||||||
title: "Rejected"
|
title: "Flag rejected"
|
||||||
ignored:
|
ignored:
|
||||||
title: "Ignored"
|
title: "Flag ignored"
|
||||||
deleted:
|
deleted:
|
||||||
title: "Deleted"
|
title: "Topic or post deleted"
|
||||||
reviewed:
|
reviewed:
|
||||||
title: "(all reviewed)"
|
title: "(all reviewed)"
|
||||||
all:
|
all:
|
||||||
title: "(everything)"
|
title: "(everything)"
|
||||||
|
|
||||||
|
context_question:
|
||||||
|
is_this_post: "Is this post %{reviewable_human_score_types}?"
|
||||||
|
delimiter: "or"
|
||||||
|
something_else_wrong: "Is there something else wrong with this post?"
|
||||||
|
|
||||||
types:
|
types:
|
||||||
reviewable_flagged_post:
|
reviewable_flagged_post:
|
||||||
title: "Flagged Post"
|
title: "Flagged Post"
|
||||||
|
|
|
@ -2456,7 +2456,7 @@ en:
|
||||||
search_tokenize_japanese_enabled: "You must disable 'search_tokenize_japanese' before enabling this setting."
|
search_tokenize_japanese_enabled: "You must disable 'search_tokenize_japanese' before enabling this setting."
|
||||||
discourse_connect_cannot_be_enabled_if_second_factor_enforced: "You cannot enable DiscourseConnect if 2FA is enforced."
|
discourse_connect_cannot_be_enabled_if_second_factor_enforced: "You cannot enable DiscourseConnect if 2FA is enforced."
|
||||||
delete_rejected_email_after_days: "This setting cannot be set lower than the delete_email_logs_after_days setting or greater than %{max}"
|
delete_rejected_email_after_days: "This setting cannot be set lower than the delete_email_logs_after_days setting or greater than %{max}"
|
||||||
invalid_uncategorized_category_setting: "The \"Uncategorized\" category cannot be selected if 'allow uncategorized topics' is not enabled."
|
invalid_uncategorized_category_setting: 'The "Uncategorized" category cannot be selected if ''allow uncategorized topics'' is not enabled.'
|
||||||
enable_new_notifications_menu_not_legacy_navigation_menu: "You must set `navigation_menu` to `legacy` before enabling this setting."
|
enable_new_notifications_menu_not_legacy_navigation_menu: "You must set `navigation_menu` to `legacy` before enabling this setting."
|
||||||
invalid_search_ranking_weights: "Value is invalid for search_ranking_weights site setting. Example: '{0.1,0.2,0.3,1.0}'. Note that maximum value for each weight is 1.0."
|
invalid_search_ranking_weights: "Value is invalid for search_ranking_weights site setting. Example: '{0.1,0.2,0.3,1.0}'. Note that maximum value for each weight is 1.0."
|
||||||
|
|
||||||
|
@ -5133,50 +5133,53 @@ en:
|
||||||
|
|
||||||
actions:
|
actions:
|
||||||
agree:
|
agree:
|
||||||
title: "Agree..."
|
title: "Yes"
|
||||||
agree_and_keep:
|
agree_and_keep:
|
||||||
title: "Keep Post"
|
title: "Keep post"
|
||||||
description: "Agree with flag and keep the post unchanged."
|
description: "Agree with flag but keep this post unchanged."
|
||||||
agree_and_keep_hidden:
|
agree_and_keep_hidden:
|
||||||
title: "Keep Post Hidden"
|
title: "Keep post hidden"
|
||||||
description: "Agree with flag and leave the post hidden."
|
description: "Agree with flag and keep the post hidden."
|
||||||
agree_and_suspend:
|
agree_and_suspend:
|
||||||
title: "Suspend User"
|
title: "Suspend user"
|
||||||
description: "Agree with flag and suspend the user."
|
description: "Agree with flag and suspend the user."
|
||||||
agree_and_silence:
|
agree_and_silence:
|
||||||
title: "Silence User"
|
title: "Silence user"
|
||||||
description: "Agree with flag and silence the user."
|
description: "Agree with flag and silence the user."
|
||||||
agree_and_restore:
|
agree_and_restore:
|
||||||
title: "Restore Post"
|
title: "Restore post"
|
||||||
description: "Restore the post so that all users can see it."
|
description: "Restore the post so that all users can see it."
|
||||||
agree_and_hide:
|
agree_and_hide:
|
||||||
title: "Hide Post"
|
title: "Hide post"
|
||||||
description: "Hide this post and automatically send the user a message urging them to edit it."
|
description: "Agree with flag and hide this post + automatically send the user a message urging them to edit it."
|
||||||
delete_single:
|
delete_single:
|
||||||
title: "Delete"
|
title: "Delete"
|
||||||
delete:
|
delete:
|
||||||
title: "Delete..."
|
title: "Delete..."
|
||||||
delete_and_ignore:
|
delete_and_ignore:
|
||||||
title: "Delete Post and Ignore"
|
title: "Ignore flag and delete post"
|
||||||
description: "Delete post; if the first post, delete the topic as well"
|
description: "Ignore the flag by removing it from the queue and delete the post; if the first post, delete the topic as well. "
|
||||||
delete_and_ignore_replies:
|
delete_and_ignore_replies:
|
||||||
title: "Delete Post + Replies and Ignore"
|
title: "Ignore flag, delete post and replies"
|
||||||
description: "Delete post and all of its replies; if the first post, delete the topic as well"
|
description: "Ignore the flag by removing it from the queue, delete the post and all of its replies; if the first post, delete the topic as well"
|
||||||
confirm: "Are you sure you want to delete the replies to the post as well?"
|
confirm: "Are you sure you want to delete the replies to the post as well?"
|
||||||
delete_and_agree:
|
delete_and_agree:
|
||||||
title: "Delete Post and Agree"
|
title: "Delete post"
|
||||||
description: "Delete post; if the first post, delete the topic as well"
|
description: "Agree with flag and delete this post; if the first post, delete the topic as well."
|
||||||
delete_and_agree_replies:
|
delete_and_agree_replies:
|
||||||
title: "Delete Post + Replies and Agree"
|
title: "Delete post and replies"
|
||||||
description: "Delete post and all of its replies; if the first post, delete the topic as well"
|
description: "Agree with flag and delete this post and all of its replies; if the first post, delete the topic as well."
|
||||||
confirm: "Are you sure you want to delete the replies to the post as well?"
|
confirm: "Are you sure you want to delete the replies to the post as well?"
|
||||||
disagree_and_restore:
|
disagree_and_restore:
|
||||||
title: "Disagree and Restore Post"
|
title: "No, restore post"
|
||||||
description: "Restore the post so that all users can see it."
|
description: "Restore the post so that all users can see it."
|
||||||
disagree:
|
disagree:
|
||||||
title: "Disagree"
|
title: "No"
|
||||||
ignore:
|
ignore:
|
||||||
title: "Ignore"
|
title: "Ignore"
|
||||||
|
ignore_and_do_nothing:
|
||||||
|
title: "Do nothing"
|
||||||
|
description: "Ignore the flag by removing it from the queue without taking any action. Hidden posts will stay hidden and be handled by the auto-tools."
|
||||||
approve:
|
approve:
|
||||||
title: "Approve"
|
title: "Approve"
|
||||||
approve_post:
|
approve_post:
|
||||||
|
|
|
@ -357,7 +357,7 @@ class PostDestroyer
|
||||||
end
|
end
|
||||||
|
|
||||||
def ignore(reviewable)
|
def ignore(reviewable)
|
||||||
reviewable.perform_ignore(@user, post_was_deleted: true)
|
reviewable.perform_ignore_and_do_nothing(@user, post_was_deleted: true)
|
||||||
reviewable.transition_to(:ignored, @user)
|
reviewable.transition_to(:ignored, @user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,7 @@ export function setup(helper) {
|
||||||
});
|
});
|
||||||
|
|
||||||
helper.buildCookFunction((opts, generateCookFunction) => {
|
helper.buildCookFunction((opts, generateCookFunction) => {
|
||||||
if (!opts.discourse.additionalOptions) {
|
if (!opts.discourse.additionalOptions?.chat) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ module DiscourseNarrativeBot
|
||||||
opts[:delete_removed_posts_after] = 1
|
opts[:delete_removed_posts_after] = 1
|
||||||
|
|
||||||
result = PostActionCreator.notify_moderators(self.discobot_user, post)
|
result = PostActionCreator.notify_moderators(self.discobot_user, post)
|
||||||
result.reviewable.perform(self.discobot_user, :ignore)
|
result.reviewable.perform(self.discobot_user, :ignore_and_do_nothing)
|
||||||
end
|
end
|
||||||
|
|
||||||
PostDestroyer.new(@user, post, opts).destroy
|
PostDestroyer.new(@user, post, opts).destroy
|
||||||
|
|
|
@ -53,7 +53,7 @@ RSpec.describe Jobs::TruncateUserFlagStats do
|
||||||
|
|
||||||
r0.perform(Discourse.system_user, :agree_and_keep)
|
r0.perform(Discourse.system_user, :agree_and_keep)
|
||||||
r1.perform(Discourse.system_user, :disagree)
|
r1.perform(Discourse.system_user, :disagree)
|
||||||
r2.perform(Discourse.system_user, :ignore)
|
r2.perform(Discourse.system_user, :ignore_and_do_nothing)
|
||||||
r3.perform(Discourse.system_user, :agree_and_keep)
|
r3.perform(Discourse.system_user, :agree_and_keep)
|
||||||
|
|
||||||
user.user_stat.reload
|
user.user_stat.reload
|
||||||
|
|
|
@ -191,7 +191,7 @@ RSpec.describe PostActionCreator do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "When the post was already reviewed by staff" do
|
describe "When the post was already reviewed by staff" do
|
||||||
before { reviewable.perform(admin, :ignore) }
|
before { reviewable.perform(admin, :ignore_and_do_nothing) }
|
||||||
|
|
||||||
it "fails because the post was recently reviewed" do
|
it "fails because the post was recently reviewed" do
|
||||||
freeze_time 10.seconds.from_now
|
freeze_time 10.seconds.from_now
|
||||||
|
|
|
@ -94,7 +94,7 @@ RSpec.describe PostDestroyer do
|
||||||
expect(reply1.deleted_at).to eq(nil)
|
expect(reply1.deleted_at).to eq(nil)
|
||||||
|
|
||||||
# ignore the flag, we should be able to delete the stub
|
# ignore the flag, we should be able to delete the stub
|
||||||
reviewable.perform(Discourse.system_user, :ignore)
|
reviewable.perform(Discourse.system_user, :ignore_and_do_nothing)
|
||||||
PostDestroyer.destroy_stubs
|
PostDestroyer.destroy_stubs
|
||||||
|
|
||||||
reply1.reload
|
reply1.reload
|
||||||
|
@ -938,7 +938,7 @@ RSpec.describe PostDestroyer do
|
||||||
|
|
||||||
it "should not send the flags_agreed_and_post_deleted message if flags were ignored" do
|
it "should not send the flags_agreed_and_post_deleted message if flags were ignored" do
|
||||||
expect(ReviewableFlaggedPost.pending.count).to eq(1)
|
expect(ReviewableFlaggedPost.pending.count).to eq(1)
|
||||||
flag_result.reviewable.perform(moderator, :ignore)
|
flag_result.reviewable.perform(moderator, :ignore_and_do_nothing)
|
||||||
second_post.reload
|
second_post.reload
|
||||||
expect(ReviewableFlaggedPost.pending.count).to eq(0)
|
expect(ReviewableFlaggedPost.pending.count).to eq(0)
|
||||||
|
|
||||||
|
|
|
@ -975,7 +975,8 @@ RSpec.describe PostAction do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "creates events for ignored" do
|
it "creates events for ignored" do
|
||||||
events = DiscourseEvent.track_events { reviewable.perform(moderator, :ignore) }
|
events =
|
||||||
|
DiscourseEvent.track_events { reviewable.perform(moderator, :ignore_and_do_nothing) }
|
||||||
|
|
||||||
reviewed_event = events.find { |e| e[:event_name] == :flag_reviewed }
|
reviewed_event = events.find { |e| e[:event_name] == :flag_reviewed }
|
||||||
expect(reviewed_event).to be_present
|
expect(reviewed_event).to be_present
|
||||||
|
|
|
@ -200,7 +200,7 @@ RSpec.describe Post do
|
||||||
|
|
||||||
it "is_flagged? is true if flag was deferred" do
|
it "is_flagged? is true if flag was deferred" do
|
||||||
result = PostActionCreator.off_topic(user, post)
|
result = PostActionCreator.off_topic(user, post)
|
||||||
result.reviewable.perform(admin, :ignore)
|
result.reviewable.perform(admin, :ignore_and_do_nothing)
|
||||||
expect(post.reload.is_flagged?).to eq(true)
|
expect(post.reload.is_flagged?).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ RSpec.describe Post do
|
||||||
result = PostActionCreator.spam(user, post)
|
result = PostActionCreator.spam(user, post)
|
||||||
expect(post.reviewable_flag).to eq(result.reviewable)
|
expect(post.reviewable_flag).to eq(result.reviewable)
|
||||||
|
|
||||||
result.reviewable.perform(admin, :ignore)
|
result.reviewable.perform(admin, :ignore_and_do_nothing)
|
||||||
expect(post.reviewable_flag).to be_nil
|
expect(post.reviewable_flag).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
expect(actions.has?(:delete_user)).to eq(true)
|
expect(actions.has?(:delete_user)).to eq(true)
|
||||||
expect(actions.has?(:delete_user_block)).to eq(true)
|
expect(actions.has?(:delete_user_block)).to eq(true)
|
||||||
expect(actions.has?(:disagree)).to eq(true)
|
expect(actions.has?(:disagree)).to eq(true)
|
||||||
expect(actions.has?(:ignore)).to eq(true)
|
expect(actions.has?(:ignore_and_do_nothing)).to eq(true)
|
||||||
expect(actions.has?(:delete_and_ignore)).to eq(true)
|
expect(actions.has?(:delete_and_ignore)).to eq(true)
|
||||||
expect(actions.has?(:delete_and_ignore_replies)).to eq(false)
|
expect(actions.has?(:delete_and_ignore_replies)).to eq(false)
|
||||||
expect(actions.has?(:delete_and_agree)).to eq(true)
|
expect(actions.has?(:delete_and_agree)).to eq(true)
|
||||||
|
@ -67,7 +67,6 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
it "returns delete replies options if there are replies" do
|
it "returns delete replies options if there are replies" do
|
||||||
post.update(reply_count: 3)
|
post.update(reply_count: 3)
|
||||||
expect(reviewable.actions_for(guardian).has?(:delete_and_agree_replies)).to eq(true)
|
expect(reviewable.actions_for(guardian).has?(:delete_and_agree_replies)).to eq(true)
|
||||||
expect(reviewable.actions_for(guardian).has?(:delete_and_ignore_replies)).to eq(true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns appropriate actions for a hidden post" do
|
it "returns appropriate actions for a hidden post" do
|
||||||
|
@ -168,7 +167,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "ignores the flags" do
|
it "ignores the flags" do
|
||||||
reviewable.perform(moderator, :ignore)
|
reviewable.perform(moderator, :ignore_and_do_nothing)
|
||||||
expect(reviewable).to be_ignored
|
expect(reviewable).to be_ignored
|
||||||
expect(score.reload).to be_ignored
|
expect(score.reload).to be_ignored
|
||||||
end
|
end
|
||||||
|
@ -273,7 +272,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
expect(post.hidden).to eq(false)
|
expect(post.hidden).to eq(false)
|
||||||
expect(post.hidden_at).to be_blank
|
expect(post.hidden_at).to be_blank
|
||||||
|
|
||||||
reviewable.perform(moderator, :ignore)
|
reviewable.perform(moderator, :ignore_and_do_nothing)
|
||||||
expect(pending_count).to eq(0)
|
expect(pending_count).to eq(0)
|
||||||
|
|
||||||
post.reload
|
post.reload
|
||||||
|
@ -340,6 +339,11 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
it "ignores flagged responses" do
|
it "ignores flagged responses" do
|
||||||
SiteSetting.notify_users_after_responses_deleted_on_flagged_post = true
|
SiteSetting.notify_users_after_responses_deleted_on_flagged_post = true
|
||||||
flagged_reply = Fabricate(:reviewable_flagged_post, target: reply)
|
flagged_reply = Fabricate(:reviewable_flagged_post, target: reply)
|
||||||
|
Fabricate(
|
||||||
|
:post,
|
||||||
|
reply_to_post_number: flagged_reply.target.post_number,
|
||||||
|
topic: flagged_reply.target.topic,
|
||||||
|
)
|
||||||
flagged_post.perform(moderator, :delete_and_agree_replies)
|
flagged_post.perform(moderator, :delete_and_agree_replies)
|
||||||
|
|
||||||
expect(flagged_reply.reload).to be_ignored
|
expect(flagged_reply.reload).to be_ignored
|
||||||
|
@ -366,7 +370,7 @@ RSpec.describe ReviewableFlaggedPost, type: :model do
|
||||||
let(:reviewable) { Fabricate(:reviewable_flagged_post, score: expected_score) }
|
let(:reviewable) { Fabricate(:reviewable_flagged_post, score: expected_score) }
|
||||||
|
|
||||||
it "doesn't recalculate the score after ignore" do
|
it "doesn't recalculate the score after ignore" do
|
||||||
reviewable.perform(moderator, :ignore)
|
reviewable.perform(moderator, :ignore_and_do_nothing)
|
||||||
|
|
||||||
expect(reviewable.score).to eq(expected_score)
|
expect(reviewable.score).to eq(expected_score)
|
||||||
end
|
end
|
||||||
|
|
|
@ -173,7 +173,7 @@ RSpec.describe Reviewable, type: :model do
|
||||||
it "can filter by who reviewed the flag" do
|
it "can filter by who reviewed the flag" do
|
||||||
reviewable = Fabricate(:reviewable_flagged_post)
|
reviewable = Fabricate(:reviewable_flagged_post)
|
||||||
admin = Fabricate(:admin)
|
admin = Fabricate(:admin)
|
||||||
reviewable.perform(admin, :ignore)
|
reviewable.perform(admin, :ignore_and_do_nothing)
|
||||||
|
|
||||||
reviewables = Reviewable.list_for(user, status: :all, reviewed_by: admin.username)
|
reviewables = Reviewable.list_for(user, status: :all, reviewed_by: admin.username)
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ RSpec.describe Reviewable, type: :model do
|
||||||
|
|
||||||
it "increases flags_ignored when ignored" do
|
it "increases flags_ignored when ignored" do
|
||||||
expect(user.user_stat.flags_ignored).to eq(0)
|
expect(user.user_stat.flags_ignored).to eq(0)
|
||||||
reviewable.perform(Discourse.system_user, :ignore)
|
reviewable.perform(Discourse.system_user, :ignore_and_do_nothing)
|
||||||
expect(user.user_stat.reload.flags_ignored).to eq(1)
|
expect(user.user_stat.reload.flags_ignored).to eq(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1955,7 +1955,10 @@ RSpec.describe User do
|
||||||
.perform(moderator, :agree_and_keep)
|
.perform(moderator, :agree_and_keep)
|
||||||
|
|
||||||
post_deferred = Fabricate(:post)
|
post_deferred = Fabricate(:post)
|
||||||
PostActionCreator.inappropriate(user, post_deferred).reviewable.perform(moderator, :ignore)
|
PostActionCreator
|
||||||
|
.inappropriate(user, post_deferred)
|
||||||
|
.reviewable
|
||||||
|
.perform(moderator, :ignore_and_do_nothing)
|
||||||
|
|
||||||
post_disagreed = Fabricate(:post)
|
post_disagreed = Fabricate(:post)
|
||||||
PostActionCreator
|
PostActionCreator
|
||||||
|
|
|
@ -2268,7 +2268,7 @@ RSpec.describe PostsController do
|
||||||
r2 = PostActionCreator.inappropriate(moderator, post_disagreed).reviewable
|
r2 = PostActionCreator.inappropriate(moderator, post_disagreed).reviewable
|
||||||
|
|
||||||
r0.perform(admin, :agree_and_keep)
|
r0.perform(admin, :agree_and_keep)
|
||||||
r1.perform(admin, :ignore)
|
r1.perform(admin, :ignore_and_do_nothing)
|
||||||
r2.perform(admin, :disagree)
|
r2.perform(admin, :disagree)
|
||||||
|
|
||||||
sign_in(Fabricate(:moderator))
|
sign_in(Fabricate(:moderator))
|
||||||
|
|
Loading…
Reference in New Issue