FEATURE: Show draft count in user menu and activity (#13812)
This commit adds the number of drafts a user has next to the "Draft" label in the user preferences menu and activity tab. The count is updated via MessageBus when a draft is created or destroyed.
This commit is contained in:
parent
d801e33e0b
commit
760c9a5698
|
@ -3,7 +3,7 @@ import I18n from "I18n";
|
|||
import { alias } from "@ember/object/computed";
|
||||
import bootbox from "bootbox";
|
||||
import { exportUserArchive } from "discourse/lib/export-csv";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Controller.extend({
|
||||
application: controller(),
|
||||
|
@ -28,6 +28,13 @@ export default Controller.extend({
|
|||
this.set("application.showFooter", showFooter);
|
||||
},
|
||||
|
||||
@discourseComputed("currentUser.draft_count")
|
||||
draftLabel(count) {
|
||||
return count > 0
|
||||
? I18n.t("drafts.label_with_count", { count })
|
||||
: I18n.t("drafts.label");
|
||||
},
|
||||
|
||||
actions: {
|
||||
exportUserArchive() {
|
||||
bootbox.confirm(
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
export default {
|
||||
name: "subscribe-user-changes",
|
||||
after: "message-bus",
|
||||
|
||||
initialize(container) {
|
||||
const user = container.lookup("current-user:main");
|
||||
|
||||
if (user) {
|
||||
const bus = container.lookup("message-bus:main");
|
||||
bus.subscribe("/user", (data) => {
|
||||
user.setProperties(data);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
{{#if user.showDrafts}}
|
||||
{{#d-navigation-item route="userActivity.drafts"}}
|
||||
{{i18n "user_action_groups.15"}}
|
||||
{{draftLabel}}
|
||||
{{/d-navigation-item}}
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -84,7 +84,12 @@ createWidgetFrom(QuickAccessPanel, "quick-access-profile", {
|
|||
{
|
||||
icon: "pencil-alt",
|
||||
href: `${this.attrs.path}/activity/drafts`,
|
||||
content: I18n.t("user_action_groups.15"),
|
||||
content:
|
||||
this.currentUser.draft_count > 0
|
||||
? I18n.t("drafts.label_with_count", {
|
||||
count: this.currentUser.draft_count,
|
||||
})
|
||||
: I18n.t("drafts.label"),
|
||||
className: "drafts",
|
||||
},
|
||||
{
|
||||
|
|
|
@ -7,6 +7,8 @@ class Draft < ActiveRecord::Base
|
|||
|
||||
belongs_to :user
|
||||
|
||||
after_commit :update_draft_count, on: [:create, :destroy]
|
||||
|
||||
class OutOfSequence < StandardError; end
|
||||
|
||||
def self.set(user, key, sequence, data, owner = nil, force_save: false)
|
||||
|
@ -92,6 +94,8 @@ class Draft < ActiveRecord::Base
|
|||
owner = :owner,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
SQL
|
||||
|
||||
UserStat.update_draft_count(user.id)
|
||||
end
|
||||
|
||||
sequence
|
||||
|
@ -338,6 +342,9 @@ class Draft < ActiveRecord::Base
|
|||
|
||||
end
|
||||
|
||||
def update_draft_count
|
||||
UserStat.update_draft_count(self.user_id)
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -202,6 +202,21 @@ class UserStat < ActiveRecord::Base
|
|||
self.class.update_distinct_badge_count(self.user_id)
|
||||
end
|
||||
|
||||
def self.update_draft_count(user_id)
|
||||
draft_count = DB.query_single <<~SQL, user_id: user_id
|
||||
UPDATE user_stats
|
||||
SET draft_count = (SELECT COUNT(*) FROM drafts WHERE user_id = :user_id)
|
||||
WHERE user_id = :user_id
|
||||
RETURNING draft_count
|
||||
SQL
|
||||
|
||||
MessageBus.publish(
|
||||
'/user',
|
||||
{ draft_count: draft_count.first },
|
||||
user_ids: [user_id]
|
||||
)
|
||||
end
|
||||
|
||||
# topic_reply_count is a count of posts in other users' topics
|
||||
def calc_topic_reply_count!(start_time = nil)
|
||||
sql = <<~SQL
|
||||
|
@ -292,4 +307,5 @@ end
|
|||
# distinct_badge_count :integer default(0), not null
|
||||
# first_unread_pm_at :datetime not null
|
||||
# digest_attempted_at :datetime
|
||||
# draft_count :integer default(0), not null
|
||||
#
|
||||
|
|
|
@ -65,6 +65,7 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
:do_not_disturb_until,
|
||||
:has_topic_draft,
|
||||
:can_review,
|
||||
:draft_count,
|
||||
|
||||
def groups
|
||||
owned_group_ids = GroupUser.where(user_id: id, owner: true).pluck(:group_id).to_set
|
||||
|
@ -315,4 +316,8 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
def include_has_topic_draft?
|
||||
Draft.has_topic_draft(object)
|
||||
end
|
||||
|
||||
def draft_count
|
||||
object.user_stat.draft_count
|
||||
end
|
||||
end
|
||||
|
|
|
@ -332,6 +332,8 @@ en:
|
|||
copied: "copied!"
|
||||
|
||||
drafts:
|
||||
label: "Drafts"
|
||||
label_with_count: "Drafts (%{count})"
|
||||
resume: "Resume"
|
||||
remove: "Remove"
|
||||
remove_confirmation: "Are you sure you want to delete this draft?"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDraftCountToUserStat < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :user_stats, :draft_count, :integer, default: 0, null: false
|
||||
|
||||
execute <<~SQL
|
||||
UPDATE user_stats
|
||||
SET draft_count = new_user_stats.draft_count
|
||||
FROM (SELECT user_stats.user_id, COUNT(drafts.id) draft_count
|
||||
FROM user_stats
|
||||
LEFT JOIN drafts ON user_stats.user_id = drafts.user_id
|
||||
GROUP BY user_stats.user_id) new_user_stats
|
||||
WHERE user_stats.user_id = new_user_stats.user_id
|
||||
AND user_stats.draft_count <> new_user_stats.draft_count
|
||||
SQL
|
||||
end
|
||||
end
|
|
@ -176,6 +176,20 @@ describe Draft do
|
|||
expect(Draft.count).to eq 0
|
||||
end
|
||||
|
||||
it 'updates draft count when a draft is created or destroyed' do
|
||||
messages = MessageBus.track_publish("/user") do
|
||||
Draft.set(user, "test", 0, "data")
|
||||
end
|
||||
|
||||
expect(messages.first.data[:draft_count]).to eq(1)
|
||||
|
||||
messages = MessageBus.track_publish("/user") do
|
||||
Draft.where(user: user).destroy_all
|
||||
end
|
||||
|
||||
expect(messages.first.data[:draft_count]).to eq(0)
|
||||
end
|
||||
|
||||
describe '#stream' do
|
||||
fab!(:public_post) { Fabricate(:post) }
|
||||
let(:public_topic) { public_post.topic }
|
||||
|
|
|
@ -222,4 +222,18 @@ describe UserStat do
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
describe '.update_draft_count' do
|
||||
fab!(:user) { Fabricate(:user) }
|
||||
|
||||
it 'updates draft_count' do
|
||||
Draft.create!(user: user, draft_key: "topic_1", data: {})
|
||||
Draft.create!(user: user, draft_key: "new_topic", data: {})
|
||||
Draft.create!(user: user, draft_key: "topic_2", data: {})
|
||||
UserStat.update_all(draft_count: 0)
|
||||
|
||||
UserStat.update_draft_count(user.id)
|
||||
expect(user.user_stat.draft_count).to eq(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue