mirror of
https://github.com/discourse/discourse.git
synced 2025-01-18 18:02:46 +08:00
FEATURE: Add new notification for admin problems (#21287)
Add new notification for admin problems to replace old PM-based flow.
This commit is contained in:
parent
076def505e
commit
cc18a99105
|
@ -1,5 +1,6 @@
|
||||||
import NotificationTypeBase from "discourse/lib/notification-types/base";
|
import NotificationTypeBase from "discourse/lib/notification-types/base";
|
||||||
|
|
||||||
|
import AdminProblems from "discourse/lib/notification-types/admin-problems";
|
||||||
import BookmarkReminder from "discourse/lib/notification-types/bookmark-reminder";
|
import BookmarkReminder from "discourse/lib/notification-types/bookmark-reminder";
|
||||||
import Custom from "discourse/lib/notification-types/custom";
|
import Custom from "discourse/lib/notification-types/custom";
|
||||||
import GrantedBadge from "discourse/lib/notification-types/granted-badge";
|
import GrantedBadge from "discourse/lib/notification-types/granted-badge";
|
||||||
|
@ -27,6 +28,7 @@ const CLASS_FOR_TYPE = {
|
||||||
membership_request_consolidated: MembershipRequestConsolidated,
|
membership_request_consolidated: MembershipRequestConsolidated,
|
||||||
moved_post: MovedPost,
|
moved_post: MovedPost,
|
||||||
new_features: NewFeatures,
|
new_features: NewFeatures,
|
||||||
|
admin_problems: AdminProblems,
|
||||||
watching_first_post: WatchingFirstPost,
|
watching_first_post: WatchingFirstPost,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import NotificationTypeBase from "discourse/lib/notification-types/base";
|
||||||
|
import getURL from "discourse-common/lib/get-url";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
export default class extends NotificationTypeBase {
|
||||||
|
get label() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get description() {
|
||||||
|
return I18n.t("notifications.admin_problems");
|
||||||
|
}
|
||||||
|
|
||||||
|
get linkHref() {
|
||||||
|
return getURL("/admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
get icon() {
|
||||||
|
return "gift";
|
||||||
|
}
|
||||||
|
}
|
36
app/jobs/scheduled/admin_problems.rb
Normal file
36
app/jobs/scheduled/admin_problems.rb
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jobs
|
||||||
|
class AdminProblems < ::Jobs::Scheduled
|
||||||
|
every 30.minutes
|
||||||
|
|
||||||
|
def execute(args)
|
||||||
|
Notification
|
||||||
|
.where(notification_type: Notification.types[:admin_problems])
|
||||||
|
.where("created_at < ?", 7.days.ago)
|
||||||
|
.destroy_all
|
||||||
|
|
||||||
|
return if !persistent_problems?
|
||||||
|
|
||||||
|
notified_user_ids =
|
||||||
|
Notification.where(notification_type: Notification.types[:admin_problems]).pluck(:user_id)
|
||||||
|
|
||||||
|
users = Group[:admins].users.where.not(id: notified_user_ids)
|
||||||
|
|
||||||
|
users.each do |user|
|
||||||
|
Notification.create!(
|
||||||
|
notification_type: Notification.types[:admin_problems],
|
||||||
|
user_id: user.id,
|
||||||
|
data: "{}",
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def persistent_problems?
|
||||||
|
problems_started_at = AdminDashboardData.problems_started_at
|
||||||
|
problems_started_at && problems_started_at < 2.days.ago
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,27 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Jobs
|
|
||||||
class DashboardStats < ::Jobs::Scheduled
|
|
||||||
every 30.minutes
|
|
||||||
|
|
||||||
def execute(args)
|
|
||||||
if persistent_problems?
|
|
||||||
# If there have been problems reported on the dashboard for a while,
|
|
||||||
# send a message to admins no more often than once per week.
|
|
||||||
group_message =
|
|
||||||
GroupMessage.new(Group[:admins].name, :dashboard_problems, limit_once_per: 7.days.to_i)
|
|
||||||
Topic.transaction do
|
|
||||||
group_message.delete_previous!
|
|
||||||
group_message.create
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def persistent_problems?
|
|
||||||
problems_started_at = AdminDashboardData.problems_started_at
|
|
||||||
problems_started_at && problems_started_at < 2.days.ago
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -152,6 +152,7 @@ class Notification < ActiveRecord::Base
|
||||||
question_answer_user_commented: 35, # Used by https://github.com/discourse/discourse-question-answer
|
question_answer_user_commented: 35, # Used by https://github.com/discourse/discourse-question-answer
|
||||||
watching_category_or_tag: 36,
|
watching_category_or_tag: 36,
|
||||||
new_features: 37,
|
new_features: 37,
|
||||||
|
admin_problems: 38,
|
||||||
following: 800, # Used by https://github.com/discourse/discourse-follow
|
following: 800, # Used by https://github.com/discourse/discourse-follow
|
||||||
following_created_topic: 801, # Used by https://github.com/discourse/discourse-follow
|
following_created_topic: 801, # Used by https://github.com/discourse/discourse-follow
|
||||||
following_replied: 802, # Used by https://github.com/discourse/discourse-follow
|
following_replied: 802, # Used by https://github.com/discourse/discourse-follow
|
||||||
|
|
|
@ -2580,6 +2580,7 @@ en:
|
||||||
reaction_2: "<span>%{username}, %{username2}</span> %{description}"
|
reaction_2: "<span>%{username}, %{username2}</span> %{description}"
|
||||||
votes_released: "%{description} - completed"
|
votes_released: "%{description} - completed"
|
||||||
new_features: "New features available!"
|
new_features: "New features available!"
|
||||||
|
admin_problems: "New advice on your site dashboard"
|
||||||
dismiss_confirmation:
|
dismiss_confirmation:
|
||||||
body:
|
body:
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -3538,16 +3538,6 @@ en:
|
||||||
subject_template: "Downloading remote images disabled"
|
subject_template: "Downloading remote images disabled"
|
||||||
text_body_template: "The `download_remote_images_to_local` setting was disabled because the disk space limit at `download_remote_images_threshold` was reached."
|
text_body_template: "The `download_remote_images_to_local` setting was disabled because the disk space limit at `download_remote_images_threshold` was reached."
|
||||||
|
|
||||||
dashboard_problems:
|
|
||||||
title: "Dashboard Problems"
|
|
||||||
subject_template: "New advice on your site dashboard"
|
|
||||||
text_body_template: |
|
|
||||||
We have some new advice and recommendations for you based on your current site settings.
|
|
||||||
|
|
||||||
[Visit your site dashboard](%{base_url}/admin) to see it.
|
|
||||||
|
|
||||||
If nothing is visible on your dashboard, another staff member may have already acted on this advice. A list of staff actions can be found in your [Staff Action Logs](%{base_url}/admin/logs/staff_action_logs).
|
|
||||||
|
|
||||||
new_user_of_the_month:
|
new_user_of_the_month:
|
||||||
title: "You're a New User of the Month!"
|
title: "You're a New User of the Month!"
|
||||||
subject_template: "You're a New User of the Month!"
|
subject_template: "You're a New User of the Month!"
|
||||||
|
|
37
spec/jobs/admin_problems_spec.rb
Normal file
37
spec/jobs/admin_problems_spec.rb
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe ::Jobs::AdminProblems do
|
||||||
|
fab!(:admin) { Fabricate(:admin) }
|
||||||
|
|
||||||
|
it "creates notification when problems persist for at least 2 days" do
|
||||||
|
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, Time.zone.now.to_s)
|
||||||
|
expect { described_class.new.execute({}) }.not_to change { Notification.count }
|
||||||
|
|
||||||
|
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
||||||
|
expect { described_class.new.execute({}) }.to change { Notification.count }.by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not replace old notification created in last 7 days" do
|
||||||
|
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
||||||
|
expect { described_class.new.execute({}) }.to change { Notification.count }.by(1)
|
||||||
|
old_notification = Notification.last
|
||||||
|
|
||||||
|
expect { described_class.new.execute({}) }.not_to change { Notification.count }
|
||||||
|
new_notification = Notification.last
|
||||||
|
|
||||||
|
expect(old_notification.id).to equal(new_notification.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "replace old notification created more than 7 days ago" do
|
||||||
|
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 13.days.ago)
|
||||||
|
freeze_time 10.days.ago do
|
||||||
|
expect { described_class.new.execute({}) }.to change { Notification.count }.by(1)
|
||||||
|
end
|
||||||
|
old_notification = Notification.last
|
||||||
|
|
||||||
|
expect { described_class.new.execute({}) }.not_to change { Notification.count }
|
||||||
|
new_notification = Notification.last
|
||||||
|
|
||||||
|
expect(old_notification.id).not_to equal(new_notification.id)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,60 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
RSpec.describe ::Jobs::DashboardStats do
|
|
||||||
let(:group_message) do
|
|
||||||
GroupMessage.new(Group[:admins].name, :dashboard_problems, limit_once_per: 7.days.to_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
def clear_recently_sent!
|
|
||||||
# We won't immediately create new PMs due to the limit_once_per option, reset the value for testing purposes.
|
|
||||||
Discourse.redis.del(group_message.sent_recently_key)
|
|
||||||
end
|
|
||||||
|
|
||||||
after { clear_recently_sent! }
|
|
||||||
|
|
||||||
it "creates group message when problems are persistent for 2 days" do
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, Time.zone.now.to_s)
|
|
||||||
expect { described_class.new.execute({}) }.not_to change { Topic.count }
|
|
||||||
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "replaces old message" do
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
old_topic = Topic.last
|
|
||||||
clear_recently_sent!
|
|
||||||
|
|
||||||
new_topic = described_class.new.execute({}).topic
|
|
||||||
expect(old_topic.reload.deleted_at.present?).to eq(true)
|
|
||||||
expect(new_topic.reload.deleted_at).to be_nil
|
|
||||||
expect(new_topic.title).to eq(old_topic.title)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "respects the sent_recently? check when deleting previous message" do
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
|
|
||||||
expect { described_class.new.execute({}) }.not_to change { Topic.count }
|
|
||||||
end
|
|
||||||
|
|
||||||
it "duplicates message if previous one has replies" do
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
clear_recently_sent!
|
|
||||||
|
|
||||||
_reply_1 = Fabricate(:post, topic: Topic.last)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
it "duplicates message if previous was 3 months ago" do
|
|
||||||
freeze_time 3.months.ago do
|
|
||||||
Discourse.redis.setex(AdminDashboardData.problems_started_key, 14.days.to_i, 3.days.ago)
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
clear_recently_sent!
|
|
||||||
end
|
|
||||||
|
|
||||||
expect { described_class.new.execute({}) }.to change { Topic.count }.by(1)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -41,6 +41,9 @@
|
||||||
"new_features": {
|
"new_features": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
"admin_problems": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
"moved_post": {
|
"moved_post": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user