mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Add attribution to staff notice and rename functionality (#30920)
The name "Staff Notice" was not quite right since TL4 users can also add these notices. This commit changes the wording to "Official Notice". In addition to this, currently you have to go look into the staff action logs to see who is responsible for a notice. This commit stores the ID of the user who created the notice, then shows this information on each notice to staff users. Finally, I migrated the ChangePostNoticeModal component to gjs.
This commit is contained in:
parent
692fccb0d9
commit
1b9e2ff4f9
@ -0,0 +1,110 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { fn } from "@ember/helper";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { service } from "@ember/service";
|
||||||
|
import { isEmpty } from "@ember/utils";
|
||||||
|
import DButton from "discourse/components/d-button";
|
||||||
|
import DModal from "discourse/components/d-modal";
|
||||||
|
import DModalCancel from "discourse/components/d-modal-cancel";
|
||||||
|
import withEventValue from "discourse/helpers/with-event-value";
|
||||||
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
|
export default class ChangePostNoticeModal extends Component {
|
||||||
|
@service currentUser;
|
||||||
|
@tracked post = this.args.model.post;
|
||||||
|
@tracked notice = this.args.model.post.notice?.raw ?? "";
|
||||||
|
@tracked saving = false;
|
||||||
|
|
||||||
|
resolve = this.args.model.resolve;
|
||||||
|
reject = this.args.model.reject;
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return (
|
||||||
|
this.saving ||
|
||||||
|
isEmpty(this.notice) ||
|
||||||
|
this.notice === this.post.notice?.raw
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
saveNotice() {
|
||||||
|
this.setNotice(this.notice);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
deleteNotice() {
|
||||||
|
this.setNotice();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
setNotice(notice) {
|
||||||
|
const { resolve, reject } = this;
|
||||||
|
|
||||||
|
this.saving = true;
|
||||||
|
this.resolve = null;
|
||||||
|
this.reject = null;
|
||||||
|
|
||||||
|
this.post
|
||||||
|
.updatePostField("notice", notice)
|
||||||
|
.then((response) => {
|
||||||
|
if (notice) {
|
||||||
|
return response.cooked_notice;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((cooked) => {
|
||||||
|
this.post.set(
|
||||||
|
"notice",
|
||||||
|
cooked
|
||||||
|
? {
|
||||||
|
type: "custom",
|
||||||
|
raw: notice,
|
||||||
|
cooked: cooked.toString(),
|
||||||
|
}
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
this.post.set("noticeCreatedByUser", this.currentUser);
|
||||||
|
})
|
||||||
|
.then(resolve, reject)
|
||||||
|
.finally(() => this.args.closeModal());
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DModal
|
||||||
|
@title={{if
|
||||||
|
@model.post.notice
|
||||||
|
(i18n "post.controls.change_post_notice")
|
||||||
|
(i18n "post.controls.add_post_notice")
|
||||||
|
}}
|
||||||
|
@closeModal={{@closeModal}}
|
||||||
|
class="change-post-notice-modal"
|
||||||
|
>
|
||||||
|
<:body>
|
||||||
|
<form>
|
||||||
|
<textarea
|
||||||
|
value={{this.notice}}
|
||||||
|
{{on "input" (withEventValue (fn (mut this.notice)))}}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</:body>
|
||||||
|
<:footer>
|
||||||
|
<DButton
|
||||||
|
@label={{if this.saving "saving" "save"}}
|
||||||
|
@action={{fn this.setNotice this.notice}}
|
||||||
|
@disabled={{this.disabled}}
|
||||||
|
class="btn-primary"
|
||||||
|
/>
|
||||||
|
{{#if @model.post.notice}}
|
||||||
|
<DButton
|
||||||
|
@label="post.controls.delete_post_notice"
|
||||||
|
@action={{this.setNotice}}
|
||||||
|
@disabled={{this.saving}}
|
||||||
|
class="btn-danger"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
<DModalCancel @close={{@closeModal}} />
|
||||||
|
</:footer>
|
||||||
|
</DModal>
|
||||||
|
</template>
|
||||||
|
}
|
@ -1,30 +0,0 @@
|
|||||||
<DModal
|
|
||||||
@title={{if
|
|
||||||
@model.post.notice
|
|
||||||
(i18n "post.controls.change_post_notice")
|
|
||||||
(i18n "post.controls.add_post_notice")
|
|
||||||
}}
|
|
||||||
@closeModal={{@closeModal}}
|
|
||||||
class="change-post-notice-modal"
|
|
||||||
>
|
|
||||||
<:body>
|
|
||||||
<form><Textarea @value={{this.notice}} /></form>
|
|
||||||
</:body>
|
|
||||||
<:footer>
|
|
||||||
<DButton
|
|
||||||
@label={{if this.saving "saving" "save"}}
|
|
||||||
@action={{fn this.setNotice this.notice}}
|
|
||||||
@disabled={{this.disabled}}
|
|
||||||
class="btn-primary"
|
|
||||||
/>
|
|
||||||
{{#if @model.post.notice}}
|
|
||||||
<DButton
|
|
||||||
@label="post.controls.delete_post_notice"
|
|
||||||
@action={{this.setNotice}}
|
|
||||||
@disabled={{this.saving}}
|
|
||||||
class="btn-danger"
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
<DModalCancel @close={{@closeModal}} />
|
|
||||||
</:footer>
|
|
||||||
</DModal>
|
|
@ -1,63 +0,0 @@
|
|||||||
import Component from "@glimmer/component";
|
|
||||||
import { tracked } from "@glimmer/tracking";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import { isEmpty } from "@ember/utils";
|
|
||||||
import { cook } from "discourse/lib/text";
|
|
||||||
|
|
||||||
export default class ChangePostNoticeModal extends Component {
|
|
||||||
@tracked post = this.args.model.post;
|
|
||||||
@tracked notice = this.args.model.post.notice?.raw ?? "";
|
|
||||||
@tracked saving = false;
|
|
||||||
|
|
||||||
resolve = this.args.model.resolve;
|
|
||||||
reject = this.args.model.reject;
|
|
||||||
|
|
||||||
get disabled() {
|
|
||||||
return (
|
|
||||||
this.saving ||
|
|
||||||
isEmpty(this.notice) ||
|
|
||||||
this.notice === this.post.notice?.raw
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
saveNotice() {
|
|
||||||
this.setNotice(this.notice);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
deleteNotice() {
|
|
||||||
this.setNotice();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
setNotice(notice) {
|
|
||||||
const { resolve, reject } = this;
|
|
||||||
|
|
||||||
this.saving = true;
|
|
||||||
this.resolve = null;
|
|
||||||
this.reject = null;
|
|
||||||
|
|
||||||
this.post
|
|
||||||
.updatePostField("notice", notice)
|
|
||||||
.then(() => {
|
|
||||||
if (notice) {
|
|
||||||
return cook(notice, { features: { onebox: false } });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((cooked) =>
|
|
||||||
this.post.set(
|
|
||||||
"notice",
|
|
||||||
cooked
|
|
||||||
? {
|
|
||||||
type: "custom",
|
|
||||||
raw: notice,
|
|
||||||
cooked: cooked.toString(),
|
|
||||||
}
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.then(resolve, reject)
|
|
||||||
.finally(() => this.args.closeModal());
|
|
||||||
}
|
|
||||||
}
|
|
@ -169,6 +169,7 @@ export default function transformPost(
|
|||||||
|
|
||||||
if (post.notice) {
|
if (post.notice) {
|
||||||
postAtts.notice = post.notice;
|
postAtts.notice = post.notice;
|
||||||
|
postAtts.noticeCreatedByUser = post.notice_created_by_user;
|
||||||
if (postAtts.notice.type === "returning_user") {
|
if (postAtts.notice.type === "returning_user") {
|
||||||
postAtts.notice.lastPostedAt = new Date(post.notice.last_posted_at);
|
postAtts.notice.lastPostedAt = new Date(post.notice.last_posted_at);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +232,10 @@ export default class Post extends RestModel {
|
|||||||
data[field] = value;
|
data[field] = value;
|
||||||
|
|
||||||
return ajax(`/posts/${this.id}/${field}`, { type: "PUT", data })
|
return ajax(`/posts/${this.id}/${field}`, { type: "PUT", data })
|
||||||
.then(() => this.set(field, value))
|
.then((response) => {
|
||||||
|
this.set(field, value);
|
||||||
|
return response;
|
||||||
|
})
|
||||||
.catch(popupAjaxError);
|
.catch(popupAjaxError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,11 @@ import {
|
|||||||
import { consolePrefix } from "discourse/lib/source-identifier";
|
import { consolePrefix } from "discourse/lib/source-identifier";
|
||||||
import { transformBasicPost } from "discourse/lib/transform-post";
|
import { transformBasicPost } from "discourse/lib/transform-post";
|
||||||
import DiscourseURL from "discourse/lib/url";
|
import DiscourseURL from "discourse/lib/url";
|
||||||
import { clipboardCopy, formatUsername } from "discourse/lib/utilities";
|
import {
|
||||||
|
clipboardCopy,
|
||||||
|
escapeExpression,
|
||||||
|
formatUsername,
|
||||||
|
} from "discourse/lib/utilities";
|
||||||
import DecoratorHelper from "discourse/widgets/decorator-helper";
|
import DecoratorHelper from "discourse/widgets/decorator-helper";
|
||||||
import widgetHbs from "discourse/widgets/hbs-compiler";
|
import widgetHbs from "discourse/widgets/hbs-compiler";
|
||||||
import PostCooked from "discourse/widgets/post-cooked";
|
import PostCooked from "discourse/widgets/post-cooked";
|
||||||
@ -808,9 +812,28 @@ createWidget("post-notice", {
|
|||||||
|
|
||||||
html(attrs) {
|
html(attrs) {
|
||||||
if (attrs.notice.type === "custom") {
|
if (attrs.notice.type === "custom") {
|
||||||
|
let createdByHTML = "";
|
||||||
|
if (attrs.noticeCreatedByUser) {
|
||||||
|
const createdByName = escapeExpression(
|
||||||
|
prioritizeNameInUx(attrs.noticeCreatedByUser.name)
|
||||||
|
? attrs.noticeCreatedByUser.name
|
||||||
|
: attrs.noticeCreatedByUser.username
|
||||||
|
);
|
||||||
|
createdByHTML = i18n("post.notice.custom_created_by", {
|
||||||
|
userLinkHTML: `<a
|
||||||
|
class="trigger-user-card"
|
||||||
|
data-user-card="${attrs.noticeCreatedByUser.username}"
|
||||||
|
title="${createdByName}"
|
||||||
|
aria-hidden="false"
|
||||||
|
role="listitem"
|
||||||
|
>${createdByName}</a>`,
|
||||||
|
});
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
iconNode("user-shield"),
|
iconNode("user-shield"),
|
||||||
new RawHtml({ html: `<div>${attrs.notice.cooked}</div>` }),
|
new RawHtml({
|
||||||
|
html: `<div class="post-notice-message">${attrs.notice.cooked} ${createdByHTML}</div>`,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,6 +1126,38 @@ module("Integration | Component | Widget | post", function (hooks) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("post notice - custom official notice with created by username", async function (assert) {
|
||||||
|
this.siteSettings.display_name_on_posts = false;
|
||||||
|
this.siteSettings.prioritize_username_in_ux = true;
|
||||||
|
this.set("args", {
|
||||||
|
notice: {
|
||||||
|
type: "custom",
|
||||||
|
cooked: "<p>This is an official notice</p>",
|
||||||
|
},
|
||||||
|
noticeCreatedByUser: {
|
||||||
|
username: "codinghorror",
|
||||||
|
name: "Jeff",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await render(hbs`
|
||||||
|
<MountWidget @widget="post" @args={{this.args}} />`);
|
||||||
|
|
||||||
|
assert.dom(".post-notice.custom").hasText(
|
||||||
|
"This is an official notice " +
|
||||||
|
i18n("post.notice.custom_created_by", {
|
||||||
|
userLinkHTML: "codinghorror",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert
|
||||||
|
.dom(
|
||||||
|
".post-notice.custom .post-notice-message a.trigger-user-card[data-user-card='codinghorror']"
|
||||||
|
)
|
||||||
|
.exists();
|
||||||
|
});
|
||||||
|
|
||||||
test("post notice - with name", async function (assert) {
|
test("post notice - with name", async function (assert) {
|
||||||
this.siteSettings.display_name_on_posts = true;
|
this.siteSettings.display_name_on_posts = true;
|
||||||
this.siteSettings.prioritize_username_in_ux = false;
|
this.siteSettings.prioritize_username_in_ux = false;
|
||||||
|
@ -1432,6 +1432,10 @@ span.mention {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.post-notice-message p {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@ -625,10 +625,12 @@ class PostsController < ApplicationController
|
|||||||
old_notice = post.custom_fields[Post::NOTICE]
|
old_notice = post.custom_fields[Post::NOTICE]
|
||||||
|
|
||||||
if params[:notice].present?
|
if params[:notice].present?
|
||||||
|
cooked_notice = PrettyText.cook(params[:notice], features: { onebox: false })
|
||||||
post.custom_fields[Post::NOTICE] = {
|
post.custom_fields[Post::NOTICE] = {
|
||||||
type: Post.notices[:custom],
|
type: Post.notices[:custom],
|
||||||
raw: params[:notice],
|
raw: params[:notice],
|
||||||
cooked: PrettyText.cook(params[:notice], features: { onebox: false }),
|
cooked: cooked_notice,
|
||||||
|
created_by_user_id: current_user.id,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
post.custom_fields.delete(Post::NOTICE)
|
post.custom_fields.delete(Post::NOTICE)
|
||||||
@ -642,7 +644,7 @@ class PostsController < ApplicationController
|
|||||||
new_value: params[:notice],
|
new_value: params[:notice],
|
||||||
)
|
)
|
||||||
|
|
||||||
render body: nil
|
render json: success_json.merge(cooked_notice:)
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy_bookmark
|
def destroy_bookmark
|
||||||
|
@ -11,6 +11,7 @@ class PostSerializer < BasicPostSerializer
|
|||||||
post_actions
|
post_actions
|
||||||
all_post_actions
|
all_post_actions
|
||||||
add_excerpt
|
add_excerpt
|
||||||
|
notice_created_by_users
|
||||||
]
|
]
|
||||||
|
|
||||||
INSTANCE_VARS.each { |v| self.public_send(:attr_accessor, v) }
|
INSTANCE_VARS.each { |v| self.public_send(:attr_accessor, v) }
|
||||||
@ -82,6 +83,7 @@ class PostSerializer < BasicPostSerializer
|
|||||||
:action_code_who,
|
:action_code_who,
|
||||||
:action_code_path,
|
:action_code_path,
|
||||||
:notice,
|
:notice,
|
||||||
|
:notice_created_by_user,
|
||||||
:last_wiki_edit,
|
:last_wiki_edit,
|
||||||
:locked,
|
:locked,
|
||||||
:excerpt,
|
:excerpt,
|
||||||
@ -518,6 +520,19 @@ class PostSerializer < BasicPostSerializer
|
|||||||
include_action_code? && action_code_path.present?
|
include_action_code? && action_code_path.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include_notice_created_by_user?
|
||||||
|
scope.is_staff? && notice.present? && notice_created_by_users.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def notice_created_by_user
|
||||||
|
return if notice.blank?
|
||||||
|
return if notice["type"] != Post.notices[:custom]
|
||||||
|
return if notice["created_by_user_id"].blank?
|
||||||
|
found_user = notice_created_by_users&.find { |user| user.id == notice["created_by_user_id"] }
|
||||||
|
return if !found_user
|
||||||
|
BasicUserSerializer.new(found_user, root: false).as_json
|
||||||
|
end
|
||||||
|
|
||||||
def notice
|
def notice
|
||||||
post_custom_fields[Post::NOTICE]
|
post_custom_fields[Post::NOTICE]
|
||||||
end
|
end
|
||||||
|
@ -64,11 +64,25 @@ module PostStreamSerializerMixin
|
|||||||
serializer.add_raw = true if @options[:include_raw]
|
serializer.add_raw = true if @options[:include_raw]
|
||||||
serializer.topic_view = object
|
serializer.topic_view = object
|
||||||
|
|
||||||
|
serializer.notice_created_by_users = post_notice_created_by_users if scope.is_staff?
|
||||||
|
|
||||||
serializer.as_json
|
serializer.as_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def post_notice_created_by_users
|
||||||
|
@post_notice_created_by_users ||=
|
||||||
|
begin
|
||||||
|
user_ids =
|
||||||
|
object
|
||||||
|
.post_custom_fields
|
||||||
|
.filter_map { |_, custom_fields| custom_fields.dig(Post::NOTICE, "created_by_user_id") }
|
||||||
|
.uniq
|
||||||
|
User.real.where(id: user_ids)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def theme_modifier_helper
|
def theme_modifier_helper
|
||||||
@theme_modifier_helper ||= ThemeModifierHelper.new(request: scope.request)
|
@theme_modifier_helper ||= ThemeModifierHelper.new(request: scope.request)
|
||||||
end
|
end
|
||||||
|
@ -3811,6 +3811,7 @@ en:
|
|||||||
notice:
|
notice:
|
||||||
new_user: "This is the first time %{user} has posted — let’s welcome them to our community!"
|
new_user: "This is the first time %{user} has posted — let’s welcome them to our community!"
|
||||||
returning_user: "It’s been a while since we’ve seen %{user} — their last post was %{time}."
|
returning_user: "It’s been a while since we’ve seen %{user} — their last post was %{time}."
|
||||||
|
custom_created_by: "(added by %{userLinkHTML})"
|
||||||
|
|
||||||
unread: "Post is unread"
|
unread: "Post is unread"
|
||||||
has_replies:
|
has_replies:
|
||||||
@ -3940,9 +3941,9 @@ en:
|
|||||||
delete_topic_confirm_modal_no: "No, keep this topic"
|
delete_topic_confirm_modal_no: "No, keep this topic"
|
||||||
delete_topic_error: "An error occurred while deleting this topic"
|
delete_topic_error: "An error occurred while deleting this topic"
|
||||||
delete_topic: "delete topic"
|
delete_topic: "delete topic"
|
||||||
add_post_notice: "Add Staff Notice…"
|
add_post_notice: "Add Official Notice…"
|
||||||
change_post_notice: "Change Staff Notice…"
|
change_post_notice: "Change Official Notice…"
|
||||||
delete_post_notice: "Delete Staff Notice"
|
delete_post_notice: "Delete Official Notice"
|
||||||
remove_timer: "remove timer"
|
remove_timer: "remove timer"
|
||||||
edit_timer: "edit timer"
|
edit_timer: "edit timer"
|
||||||
|
|
||||||
|
@ -595,6 +595,9 @@ RSpec.describe "posts" do
|
|||||||
notice: {
|
notice: {
|
||||||
type: :object,
|
type: :object,
|
||||||
},
|
},
|
||||||
|
notice_created_by_user: {
|
||||||
|
type: %i[object null],
|
||||||
|
},
|
||||||
reviewable_id: {
|
reviewable_id: {
|
||||||
type: %i[integer null],
|
type: %i[integer null],
|
||||||
},
|
},
|
||||||
|
@ -2911,6 +2911,7 @@ RSpec.describe PostsController do
|
|||||||
"type" => Post.notices[:custom],
|
"type" => Post.notices[:custom],
|
||||||
"raw" => raw_notice,
|
"raw" => raw_notice,
|
||||||
"cooked" => PrettyText.cook(raw_notice, features: { onebox: false }),
|
"cooked" => PrettyText.cook(raw_notice, features: { onebox: false }),
|
||||||
|
"created_by_user_id" => moderator.id,
|
||||||
)
|
)
|
||||||
expect(UserHistory.where(action: UserHistory.actions[:post_staff_note_create]).count).to eq(1)
|
expect(UserHistory.where(action: UserHistory.actions[:post_staff_note_create]).count).to eq(1)
|
||||||
|
|
||||||
@ -2944,6 +2945,7 @@ RSpec.describe PostsController do
|
|||||||
"type" => Post.notices[:custom],
|
"type" => Post.notices[:custom],
|
||||||
"raw" => raw_notice,
|
"raw" => raw_notice,
|
||||||
"cooked" => PrettyText.cook(raw_notice, features: { onebox: false }),
|
"cooked" => PrettyText.cook(raw_notice, features: { onebox: false }),
|
||||||
|
"created_by_user_id" => user.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
put "/posts/#{public_post.id}/notice.json", params: { notice: nil }
|
put "/posts/#{public_post.id}/notice.json", params: { notice: nil }
|
||||||
|
@ -224,32 +224,102 @@ RSpec.describe PostSerializer do
|
|||||||
fab!(:user) { Fabricate(:user, trust_level: 1) }
|
fab!(:user) { Fabricate(:user, trust_level: 1) }
|
||||||
fab!(:user_tl1) { Fabricate(:user, trust_level: 1) }
|
fab!(:user_tl1) { Fabricate(:user, trust_level: 1) }
|
||||||
fab!(:user_tl2) { Fabricate(:user, trust_level: 2) }
|
fab!(:user_tl2) { Fabricate(:user, trust_level: 2) }
|
||||||
|
fab!(:post) { Fabricate(:post, user: user) }
|
||||||
|
|
||||||
let(:post) do
|
def json_for_user(user, serializer_opts = {})
|
||||||
post = Fabricate(:post, user: user)
|
serializer = PostSerializer.new(post, scope: Guardian.new(user), root: false)
|
||||||
post.custom_fields[Post::NOTICE] = {
|
|
||||||
type: Post.notices[:returning_user],
|
if serializer_opts[:notice_created_by_users]
|
||||||
last_posted_at: 1.day.ago,
|
serializer.notice_created_by_users = serializer_opts[:notice_created_by_users]
|
||||||
}
|
end
|
||||||
post.save_custom_fields
|
|
||||||
post
|
serializer.as_json(serializer_opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
def json_for_user(user)
|
describe "returning_user notice" do
|
||||||
PostSerializer.new(post, scope: Guardian.new(user), root: false).as_json
|
before do
|
||||||
|
post.custom_fields[Post::NOTICE] = {
|
||||||
|
type: Post.notices[:returning_user],
|
||||||
|
last_posted_at: 1.day.ago,
|
||||||
|
}
|
||||||
|
post.save_custom_fields
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is visible for TL2+ users (except poster)" do
|
||||||
|
expect(json_for_user(nil)[:notice]).to eq(nil)
|
||||||
|
expect(json_for_user(user)[:notice]).to eq(nil)
|
||||||
|
|
||||||
|
SiteSetting.returning_user_notice_tl = 2
|
||||||
|
expect(json_for_user(user_tl1)[:notice]).to eq(nil)
|
||||||
|
expect(json_for_user(user_tl2)[:notice][:type]).to eq(Post.notices[:returning_user])
|
||||||
|
|
||||||
|
SiteSetting.returning_user_notice_tl = 1
|
||||||
|
expect(json_for_user(user_tl1)[:notice][:type]).to eq(Post.notices[:returning_user])
|
||||||
|
expect(json_for_user(user_tl2)[:notice][:type]).to eq(Post.notices[:returning_user])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is visible for TL2+ users (except poster)" do
|
describe "custom notice" do
|
||||||
expect(json_for_user(nil)[:notice]).to eq(nil)
|
fab!(:moderator)
|
||||||
expect(json_for_user(user)[:notice]).to eq(nil)
|
|
||||||
|
|
||||||
SiteSetting.returning_user_notice_tl = 2
|
before do
|
||||||
expect(json_for_user(user_tl1)[:notice]).to eq(nil)
|
post.custom_fields[Post::NOTICE] = {
|
||||||
expect(json_for_user(user_tl2)[:notice][:type]).to eq(Post.notices[:returning_user])
|
type: Post.notices[:custom],
|
||||||
|
raw: "This is a notice",
|
||||||
|
cooked: "<p>This is a notice</p>",
|
||||||
|
created_by_user_id: moderator.id,
|
||||||
|
}
|
||||||
|
post.save_custom_fields
|
||||||
|
end
|
||||||
|
|
||||||
SiteSetting.returning_user_notice_tl = 1
|
it "displays for all trust levels" do
|
||||||
expect(json_for_user(user_tl1)[:notice][:type]).to eq(Post.notices[:returning_user])
|
expect(json_for_user(user)[:notice]).to eq(
|
||||||
expect(json_for_user(user_tl2)[:notice][:type]).to eq(Post.notices[:returning_user])
|
{
|
||||||
|
cooked: "<p>This is a notice</p>",
|
||||||
|
created_by_user_id: moderator.id,
|
||||||
|
raw: "This is a notice",
|
||||||
|
type: Post.notices[:custom],
|
||||||
|
}.with_indifferent_access,
|
||||||
|
)
|
||||||
|
expect(json_for_user(user_tl1)[:notice]).to eq(
|
||||||
|
{
|
||||||
|
cooked: "<p>This is a notice</p>",
|
||||||
|
created_by_user_id: moderator.id,
|
||||||
|
raw: "This is a notice",
|
||||||
|
type: Post.notices[:custom],
|
||||||
|
}.with_indifferent_access,
|
||||||
|
)
|
||||||
|
expect(json_for_user(user_tl2)[:notice]).to eq(
|
||||||
|
{
|
||||||
|
cooked: "<p>This is a notice</p>",
|
||||||
|
created_by_user_id: moderator.id,
|
||||||
|
raw: "This is a notice",
|
||||||
|
type: Post.notices[:custom],
|
||||||
|
}.with_indifferent_access,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "only displays the created_by_user for staff" do
|
||||||
|
expect(
|
||||||
|
json_for_user(user, notice_created_by_users: [moderator])[:notice_created_by_user],
|
||||||
|
).to eq(nil)
|
||||||
|
expect(
|
||||||
|
json_for_user(user_tl1, notice_created_by_users: [moderator])[:notice_created_by_user],
|
||||||
|
).to eq(nil)
|
||||||
|
expect(
|
||||||
|
json_for_user(user_tl2, notice_created_by_users: [moderator])[:notice_created_by_user],
|
||||||
|
).to eq(nil)
|
||||||
|
expect(
|
||||||
|
json_for_user(moderator, notice_created_by_users: [moderator])[:notice_created_by_user],
|
||||||
|
).to eq(
|
||||||
|
{
|
||||||
|
id: moderator.id,
|
||||||
|
username: moderator.username,
|
||||||
|
name: moderator.name,
|
||||||
|
avatar_template: moderator.avatar_template,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ describe "Post menu", type: :system do
|
|||||||
expect(topic_page).to have_post_action_button(post2, :admin)
|
expect(topic_page).to have_post_action_button(post2, :admin)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "displays the admin button when the user can wiki the post / edit staff notices" do
|
it "displays the admin button when the user can wiki the post / edit official notices" do
|
||||||
# display the admin button when the user can wiki
|
# display the admin button when the user can wiki
|
||||||
sign_in(Fabricate(:trust_level_4))
|
sign_in(Fabricate(:trust_level_4))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user