FEATURE: Special call-out for new / returning posters. (#7115)
This commit is contained in:
parent
65464969cd
commit
35942f7c7c
|
@ -134,6 +134,13 @@ export default function transformPost(
|
|||
postAtts.topicUrl = topic.get("url");
|
||||
postAtts.isSaving = post.isSaving;
|
||||
|
||||
if (post.post_notice_type) {
|
||||
postAtts.postNoticeType = post.post_notice_type;
|
||||
if (postAtts.postNoticeType === "returning") {
|
||||
postAtts.postNoticeTime = new Date(post.post_notice_time);
|
||||
}
|
||||
}
|
||||
|
||||
const showPMMap =
|
||||
topic.archetype === "private_message" && post.post_number === 1;
|
||||
if (showPMMap) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
formatUsername
|
||||
} from "discourse/lib/utilities";
|
||||
import hbs from "discourse/widgets/hbs-compiler";
|
||||
import { relativeAge } from "discourse/lib/formatter";
|
||||
|
||||
function transformWithCallbacks(post) {
|
||||
let transformed = transformBasicPost(post);
|
||||
|
@ -427,6 +428,29 @@ createWidget("post-contents", {
|
|||
}
|
||||
});
|
||||
|
||||
createWidget("post-notice", {
|
||||
tagName: "div.post-notice",
|
||||
|
||||
html(attrs) {
|
||||
let text, icon;
|
||||
if (attrs.postNoticeType === "first") {
|
||||
icon = "hands-helping";
|
||||
text = I18n.t("post.notice.first", { user: attrs.username });
|
||||
} else if (attrs.postNoticeType === "returning") {
|
||||
icon = "far-smile";
|
||||
text = I18n.t("post.notice.return", {
|
||||
user: attrs.username,
|
||||
time: relativeAge(attrs.postNoticeTime, {
|
||||
format: "tiny",
|
||||
addAgo: true
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return h("p", [iconNode(icon), text]);
|
||||
}
|
||||
});
|
||||
|
||||
createWidget("post-body", {
|
||||
tagName: "div.topic-body.clearfix",
|
||||
|
||||
|
@ -505,6 +529,10 @@ createWidget("post-article", {
|
|||
);
|
||||
}
|
||||
|
||||
if (attrs.postNoticeType) {
|
||||
rows.push(h("div.row", [this.attach("post-notice", attrs)]));
|
||||
}
|
||||
|
||||
rows.push(
|
||||
h("div.row", [
|
||||
this.attach("post-avatar", attrs),
|
||||
|
|
|
@ -864,3 +864,22 @@ a.mention-group {
|
|||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.post-notice {
|
||||
background-color: $tertiary-low;
|
||||
border-top: 1px solid $primary-low;
|
||||
color: $primary;
|
||||
padding: 1em;
|
||||
width: calc(
|
||||
#{$topic-body-width} + #{$topic-avatar-width} - #{$topic-body-width-padding} +
|
||||
3px
|
||||
);
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.d-icon {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,6 +194,7 @@ class Post < ActiveRecord::Base
|
|||
def recover!
|
||||
super
|
||||
update_flagged_posts_count
|
||||
delete_post_notices
|
||||
recover_public_post_actions
|
||||
TopicLink.extract_from(self)
|
||||
QuotedPost.extract_from(self)
|
||||
|
@ -381,6 +382,11 @@ class Post < ActiveRecord::Base
|
|||
PostAction.update_flagged_posts_count
|
||||
end
|
||||
|
||||
def delete_post_notices
|
||||
self.custom_fields.delete("post_notice_type")
|
||||
self.custom_fields.delete("post_notice_time")
|
||||
end
|
||||
|
||||
def recover_public_post_actions
|
||||
PostAction.publics
|
||||
.with_deleted
|
||||
|
|
|
@ -70,6 +70,8 @@ class PostSerializer < BasicPostSerializer
|
|||
:is_auto_generated,
|
||||
:action_code,
|
||||
:action_code_who,
|
||||
:post_notice_type,
|
||||
:post_notice_time,
|
||||
:last_wiki_edit,
|
||||
:locked,
|
||||
:excerpt
|
||||
|
@ -363,6 +365,22 @@ class PostSerializer < BasicPostSerializer
|
|||
include_action_code? && action_code_who.present?
|
||||
end
|
||||
|
||||
def post_notice_type
|
||||
post_custom_fields["post_notice_type"]
|
||||
end
|
||||
|
||||
def include_post_notice_type?
|
||||
post_notice_type.present?
|
||||
end
|
||||
|
||||
def post_notice_time
|
||||
post_custom_fields["post_notice_time"]
|
||||
end
|
||||
|
||||
def include_post_notice_time?
|
||||
post_notice_time.present?
|
||||
end
|
||||
|
||||
def locked
|
||||
true
|
||||
end
|
||||
|
|
|
@ -2149,6 +2149,10 @@ en:
|
|||
one: "view 1 hidden reply"
|
||||
other: "view {{count}} hidden replies"
|
||||
|
||||
notice:
|
||||
first: "This is the first time {{user}} has posted — let's welcome them to our community!"
|
||||
return: "It's been a while since we've seen {{user}} — their last post was in {{time}}."
|
||||
|
||||
unread: "Post is unread"
|
||||
has_replies:
|
||||
one: "{{count}} Reply"
|
||||
|
|
|
@ -1901,6 +1901,8 @@ en:
|
|||
max_allowed_message_recipients: "Maximum recipients allowed in a message."
|
||||
watched_words_regular_expressions: "Watched words are regular expressions."
|
||||
|
||||
returning_users_days: "How many days should pass before a user is considered to be returning."
|
||||
|
||||
default_email_digest_frequency: "How often users receive summary emails by default."
|
||||
default_include_tl0_in_digests: "Include posts from new users in summary emails by default. Users can change this in their preferences."
|
||||
default_email_personal_messages: "Send an email when someone messages the user by default."
|
||||
|
|
|
@ -807,6 +807,8 @@ posting:
|
|||
default: false
|
||||
client: true
|
||||
shadowed_by_global: true
|
||||
returning_users_days:
|
||||
default: 60
|
||||
|
||||
email:
|
||||
email_time_window_mins:
|
||||
|
|
|
@ -165,6 +165,7 @@ class PostCreator
|
|||
transaction do
|
||||
build_post_stats
|
||||
create_topic
|
||||
create_post_notice
|
||||
save_post
|
||||
extract_links
|
||||
track_topic
|
||||
|
@ -508,6 +509,21 @@ class PostCreator
|
|||
@user.update_attributes(last_posted_at: @post.created_at)
|
||||
end
|
||||
|
||||
def create_post_notice
|
||||
last_post_time = Post.where(user_id: @user.id)
|
||||
.order(created_at: :desc)
|
||||
.limit(1)
|
||||
.pluck(:created_at)
|
||||
.first
|
||||
|
||||
if !last_post_time
|
||||
@post.custom_fields["post_notice_type"] = "first"
|
||||
elsif SiteSetting.returning_users_days > 0 && last_post_time < SiteSetting.returning_users_days.days.ago
|
||||
@post.custom_fields["post_notice_type"] = "returning"
|
||||
@post.custom_fields["post_notice_time"] = last_post_time
|
||||
end
|
||||
end
|
||||
|
||||
def publish
|
||||
return if @opts[:import_mode] || @post.post_number == 1
|
||||
@post.publish_change_to_clients! :created
|
||||
|
|
|
@ -118,6 +118,7 @@ module SvgSprite
|
|||
"globe",
|
||||
"globe-americas",
|
||||
"hand-point-right",
|
||||
"hands-helping",
|
||||
"heading",
|
||||
"heart",
|
||||
"home",
|
||||
|
|
|
@ -18,7 +18,7 @@ class TopicView
|
|||
end
|
||||
|
||||
def self.default_post_custom_fields
|
||||
@default_post_custom_fields ||= ["action_code_who"]
|
||||
@default_post_custom_fields ||= ["action_code_who", "post_notice_type", "post_notice_time"]
|
||||
end
|
||||
|
||||
def self.post_custom_fields_whitelisters
|
||||
|
|
|
@ -1238,4 +1238,32 @@ describe PostCreator do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#create_post_notice" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:new_user) { Fabricate(:user) }
|
||||
let(:returning_user) { Fabricate(:user) }
|
||||
|
||||
it "generates post notices" do
|
||||
# new users
|
||||
post = PostCreator.create(new_user, title: "one of my first topics", raw: "one of my first posts")
|
||||
expect(post.custom_fields["post_notice_type"]).to eq("first")
|
||||
post = PostCreator.create(new_user, title: "another one of my first topics", raw: "another one of my first posts")
|
||||
expect(post.custom_fields["post_notice_type"]).to eq(nil)
|
||||
|
||||
# returning users
|
||||
SiteSetting.returning_users_days = 30
|
||||
old_post = Fabricate(:post, user: returning_user, created_at: 31.days.ago)
|
||||
post = PostCreator.create(returning_user, title: "this is a returning topic", raw: "this is a post")
|
||||
expect(post.custom_fields["post_notice_type"]).to eq("returning")
|
||||
expect(post.custom_fields["post_notice_time"]).to eq(old_post.created_at.to_s)
|
||||
end
|
||||
|
||||
it "does not generate post notices" do
|
||||
Fabricate(:post, user: user, created_at: 3.days.ago)
|
||||
post = PostCreator.create(user, title: "this is another topic", raw: "this is my another post")
|
||||
expect(post.custom_fields["post_notice_type"]).to eq(nil)
|
||||
expect(post.custom_fields["post_notice_time"]).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -134,6 +134,29 @@ describe Post do
|
|||
end
|
||||
end
|
||||
|
||||
context 'a post with notices' do
|
||||
let(:post) {
|
||||
post = Fabricate(:post, post_args)
|
||||
post.custom_fields["post_notice_type"] = "returning"
|
||||
post.custom_fields["post_notice_time"] = 1.day.ago
|
||||
post
|
||||
}
|
||||
|
||||
before do
|
||||
post.trash!
|
||||
post.reload
|
||||
end
|
||||
|
||||
describe 'recovery' do
|
||||
it 'deletes notices' do
|
||||
post.recover!
|
||||
|
||||
expect(post.custom_fields).not_to have_key("post_notice_type")
|
||||
expect(post.custom_fields).not_to have_key("post_notice_time")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'flagging helpers' do
|
||||
|
|
|
@ -852,3 +852,22 @@ widgetTest("pm map", {
|
|||
assert.equal(find(".private-message-map .user").length, 1);
|
||||
}
|
||||
});
|
||||
|
||||
widgetTest("post notice", {
|
||||
template: '{{mount-widget widget="post" args=args}}',
|
||||
beforeEach() {
|
||||
this.set("args", {
|
||||
postNoticeType: "returning",
|
||||
postNoticeTime: new Date("2010-01-01 12:00:00 UTC"),
|
||||
username: "codinghorror"
|
||||
});
|
||||
},
|
||||
test(assert) {
|
||||
assert.equal(
|
||||
find(".post-notice")
|
||||
.text()
|
||||
.trim(),
|
||||
I18n.t("post.notice.return", { user: "codinghorror", time: "Jan '10" })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue