From 8b575a0babc5a58a8e495de12c7a1be9b4241f1a Mon Sep 17 00:00:00 2001 From: Nat Date: Wed, 20 Apr 2022 02:15:35 +0800 Subject: [PATCH 1/4] Add column for priorities --- db/migrate/20220419093001_add_priority_to_assignments.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 db/migrate/20220419093001_add_priority_to_assignments.rb diff --git a/db/migrate/20220419093001_add_priority_to_assignments.rb b/db/migrate/20220419093001_add_priority_to_assignments.rb new file mode 100644 index 00000000..5cadf452 --- /dev/null +++ b/db/migrate/20220419093001_add_priority_to_assignments.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddPriorityToAssignments < ActiveRecord::Migration[6.1] + def change + add_column :assignments, :priority, :integer, null: true + end +end From ad45c6703f0f20b60966a8d6f21f1d75f8bc3b65 Mon Sep 17 00:00:00 2001 From: Nat Date: Wed, 20 Apr 2022 02:15:36 +0800 Subject: [PATCH 2/4] Add ability to select priority in modal And also disable immediately triggering assign when user is selected --- .../controllers/assign-user.js | 26 +++++++++++++------ .../initializers/extend-for-assigns.js | 1 + .../discourse/services/task-actions.js | 1 + .../discourse/templates/modal/assign-user.hbs | 11 ++++++++ config/locales/client.en.yml | 9 ++++++- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/assets/javascripts/discourse-assign/controllers/assign-user.js b/assets/javascripts/discourse-assign/controllers/assign-user.js index 7d6b8267..577d76e7 100644 --- a/assets/javascripts/discourse-assign/controllers/assign-user.js +++ b/assets/javascripts/discourse-assign/controllers/assign-user.js @@ -1,10 +1,18 @@ import Controller, { inject as controller } from "@ember/controller"; +import { action } from "@ember/object"; +import { not, or } from "@ember/object/computed"; import { inject as service } from "@ember/service"; +import { isEmpty } from "@ember/utils"; import { ajax } from "discourse/lib/ajax"; import { popupAjaxError } from "discourse/lib/ajax-error"; -import { not, or } from "@ember/object/computed"; -import { isEmpty } from "@ember/utils"; -import { action } from "@ember/object"; +import I18n from "I18n"; + +const PRIORITIES = [ + { name: I18n.t("discourse_assign.priorities.low"), value: 4 }, + { name: I18n.t("discourse_assign.priorities.medium"), value: 3 }, + { name: I18n.t("discourse_assign.priorities.high"), value: 2 }, + { name: I18n.t("discourse_assign.priorities.urgent"), value: 1 }, +]; export default Controller.extend({ topicBulkActions: controller(), @@ -13,6 +21,7 @@ export default Controller.extend({ taskActions: service(), autofocus: not("capabilities.touch"), assigneeName: or("model.username", "model.group_name"), + priorities: PRIORITIES, init() { this._super(...arguments); @@ -63,7 +72,6 @@ export default Controller.extend({ } this.send("closeModal"); - return ajax(path, { type: "PUT", data: { @@ -71,6 +79,7 @@ export default Controller.extend({ group_name: this.get("model.group_name"), target_id: this.get("model.target.id"), target_type: this.get("model.targetType"), + priority: this.get("model.priority"), }, }) .then(() => { @@ -99,14 +108,15 @@ export default Controller.extend({ "model.allowedGroups": this.taskActions.allowedGroups, }); } - - if (name) { - return this.assign(); - } }, @action assignUsername(selected) { this.assignUser(selected.firstObject); }, + + @action + assignPriority(priority) { + this.set("model.priority", priority); + }, }); diff --git a/assets/javascripts/discourse-assign/initializers/extend-for-assigns.js b/assets/javascripts/discourse-assign/initializers/extend-for-assigns.js index 3ef81b78..d036aaa9 100644 --- a/assets/javascripts/discourse-assign/initializers/extend-for-assigns.js +++ b/assets/javascripts/discourse-assign/initializers/extend-for-assigns.js @@ -23,6 +23,7 @@ const DEPENDENT_KEYS = [ "topic.assigned_to_group", "currentUser.can_assign", "topic.assigned_to_user.username", + "topic.assignment_priority", ]; function titleForState(name) { diff --git a/assets/javascripts/discourse/services/task-actions.js b/assets/javascripts/discourse/services/task-actions.js index c7cae11b..4eec1296 100644 --- a/assets/javascripts/discourse/services/task-actions.js +++ b/assets/javascripts/discourse/services/task-actions.js @@ -38,6 +38,7 @@ export default Service.extend({ group_name: target.assigned_to_group?.name, target, targetType: options.targetType, + priority: target.assignment_priority, }, }); }, diff --git a/assets/javascripts/discourse/templates/modal/assign-user.hbs b/assets/javascripts/discourse/templates/modal/assign-user.hbs index 1043095c..7144e26d 100644 --- a/assets/javascripts/discourse/templates/modal/assign-user.hbs +++ b/assets/javascripts/discourse/templates/modal/assign-user.hbs @@ -25,6 +25,17 @@ {{/each}} + + {{combo-box + name="assign-priority" + content=priorities + value=model.priority + valueProperty="value" + onChange=(action "assignPriority") + options=(hash + none="discourse_assign.priorities.none" + ) + }} {{/d-modal-body}} diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 629b81f1..ade1a773 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -47,12 +47,13 @@ en: help: "Reassign Topic to a different user" reassign_modal: title: "Reassign Topic" - description: "Enter the name of the user you'd like to Reassign this topic" + description: "Enter the name of the user you'd like to reassign this topic" assign_modal: title: "Assign Topic" reassign_title: "Reassign Topic" description: "Enter the name of the user you'd like to assign this topic" assign: "Assign" + priority_label: Set a priority (Optional) assign_post_modal: title: "Assign Post" description: "Enter the name of the user you'd like to assign this post" @@ -79,6 +80,12 @@ en: assign: "Assign" assignable_levels: title: "Who can assign this group" + priorities: + none: None + low: Low + medium: Medium + high: High + urgent: Urgent user: messages: assigned_title: "Assigned (%{count})" From 4489b9d4fe5d76cf7c00b816ba360a6aed5ce8c7 Mon Sep 17 00:00:00 2001 From: Nat Date: Wed, 20 Apr 2022 02:15:36 +0800 Subject: [PATCH 3/4] Commit and return priorities in topics and posts --- .../discourse_assign/assign_controller.rb | 3 +- app/models/assignment.rb | 8 ++++ lib/assigner.rb | 4 +- plugin.rb | 16 ++++++++ spec/lib/assigner_spec.rb | 6 +++ spec/requests/assign_controller_spec.rb | 9 +++++ spec/serializers/post_serializer_spec.rb | 6 +++ .../serializers/topic_view_serializer_spec.rb | 38 +++++++++++++++++++ 8 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 spec/serializers/topic_view_serializer_spec.rb diff --git a/app/controllers/discourse_assign/assign_controller.rb b/app/controllers/discourse_assign/assign_controller.rb index d49260af..8e3efaa1 100644 --- a/app/controllers/discourse_assign/assign_controller.rb +++ b/app/controllers/discourse_assign/assign_controller.rb @@ -48,6 +48,7 @@ def assign target_type = params.require(:target_type) username = params.permit(:username)['username'] group_name = params.permit(:group_name)['group_name'] + priority = (params.permit(:priority)['priority'])&.to_i assign_to = username.present? ? User.find_by(username_lower: username.downcase) : Group.where("LOWER(name) = ?", group_name.downcase).first @@ -56,7 +57,7 @@ def assign target = target_type.constantize.where(id: target_id).first raise Discourse::NotFound unless target - assign = Assigner.new(target, current_user).assign(assign_to) + assign = Assigner.new(target, current_user).assign(assign_to, priority: priority) if assign[:success] render json: success_json diff --git a/app/models/assignment.rb b/app/models/assignment.rb index 1563ab63..b6e3f0be 100644 --- a/app/models/assignment.rb +++ b/app/models/assignment.rb @@ -8,6 +8,13 @@ class Assignment < ActiveRecord::Base belongs_to :assigned_by_user, class_name: "User" belongs_to :target, polymorphic: true + enum priority: { + low: 4, + medium: 3, + high: 2, + urgent: 1, + }, _prefix: true + scope :joins_with_topics, -> { joins("INNER JOIN topics ON topics.id = assignments.target_id AND assignments.target_type = 'Topic' AND topics.deleted_at IS NULL") } def self.valid_type?(type) @@ -37,6 +44,7 @@ def assigned_to_group? # target_id :integer not null # target_type :string not null # active :boolean default(TRUE) +# priority :integer # # Indexes # diff --git a/lib/assigner.rb b/lib/assigner.rb index 73b98380..0801d1f3 100644 --- a/lib/assigner.rb +++ b/lib/assigner.rb @@ -199,7 +199,7 @@ def forbidden_reasons(assign_to:, type:) end end - def assign(assign_to, silent: false) + def assign(assign_to, priority: nil, silent: false) type = assign_to.is_a?(User) ? "User" : "Group" forbidden_reason = forbidden_reasons(assign_to: assign_to, type: type) @@ -211,7 +211,7 @@ def assign(assign_to, silent: false) @target.assignment&.destroy! - assignment = @target.create_assignment!(assigned_to_id: assign_to.id, assigned_to_type: type, assigned_by_user_id: @assigned_by.id, topic_id: topic.id) + assignment = @target.create_assignment!(assigned_to_id: assign_to.id, assigned_to_type: type, assigned_by_user_id: @assigned_by.id, topic_id: topic.id, priority: priority) first_post.publish_change_to_clients!(:revised, reload_topic: true) diff --git a/plugin.rb b/plugin.rb index c1bac326..98761f68 100644 --- a/plugin.rb +++ b/plugin.rb @@ -484,6 +484,14 @@ class ::ListController (SiteSetting.assigns_public || scope.can_assign?) && object.topic.indirectly_assigned_to.present? end + add_to_serializer(:topic_view, :assignment_priority, false) do + Assignment.priorities[object.topic.assignment.priority] + end + + add_to_serializer(:topic_view, :include_assignment_priority?, false) do + (SiteSetting.assigns_public || scope.can_assign?) && object.topic.assignment.present? + end + # SuggestedTopic serializer add_to_serializer(:suggested_topic, :assigned_to_user, false) do DiscourseAssign::Helpers.build_assigned_to_user(object.assigned_to, object) @@ -631,6 +639,14 @@ class ::ListController (SiteSetting.assigns_public || scope.can_assign?) && object.assignment&.assigned_to&.is_a?(Group) && object.assignment.active end + add_to_serializer(:post, :assignment_priority, false) do + Assignment.priorities[object.assignment.priority] + end + + add_to_serializer(:post, :include_assignment_priority?, false) do + (SiteSetting.assigns_public || scope.can_assign?) && object.assignment.present? + end + # CurrentUser serializer add_to_serializer(:current_user, :can_assign) do object.can_assign? diff --git a/spec/lib/assigner_spec.rb b/spec/lib/assigner_spec.rb index 4db66696..87ca08b0 100644 --- a/spec/lib/assigner_spec.rb +++ b/spec/lib/assigner_spec.rb @@ -43,6 +43,12 @@ .to eq(TopicUser.notification_levels[:tracking]) end + it "can assign with priority" do + assigner.assign(moderator, priority: 2) + + expect(topic.assignment.priority_high?).to eq true + end + it 'does not update notification level if already watching' do TopicUser.change(moderator.id, topic.id, notification_level: TopicUser.notification_levels[:watching] diff --git a/spec/requests/assign_controller_spec.rb b/spec/requests/assign_controller_spec.rb index e563adb9..28352691 100644 --- a/spec/requests/assign_controller_spec.rb +++ b/spec/requests/assign_controller_spec.rb @@ -116,6 +116,15 @@ expect(post.topic.reload.assignment.assigned_to_id).to eq(user2.id) end + it 'assigns topic with priority to a user' do + put '/assign/assign.json', params: { + target_id: post.topic_id, target_type: 'Topic', username: user2.username, priority: 4 + } + + topicPriority = post.topic.reload.assignment.priority + expect(Assignment.priorities[topicPriority]).to eq(4) + end + it 'assigns topic to a group' do put '/assign/assign.json', params: { target_id: post.topic_id, target_type: 'Topic', group_name: assign_allowed_group.name diff --git a/spec/serializers/post_serializer_spec.rb b/spec/serializers/post_serializer_spec.rb index 80742fda..16378ca8 100644 --- a/spec/serializers/post_serializer_spec.rb +++ b/spec/serializers/post_serializer_spec.rb @@ -29,4 +29,10 @@ expect(serializer.as_json[:post][:assigned_to_group].id).to eq(assign_allowed_group.id) expect(serializer.as_json[:post][:assigned_to_user]).to be nil end + + it "includes priority in serializer" do + Assigner.new(post, user).assign(user, priority: 1) + serializer = PostSerializer.new(post, scope: guardian) + expect(serializer.as_json[:post][:assignment_priority]).to eq(1) + end end diff --git a/spec/serializers/topic_view_serializer_spec.rb b/spec/serializers/topic_view_serializer_spec.rb new file mode 100644 index 00000000..14f657b5 --- /dev/null +++ b/spec/serializers/topic_view_serializer_spec.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'rails_helper' +require_relative '../support/assign_allowed_group' + +RSpec.describe TopicViewSerializer do + fab!(:user) { Fabricate(:user) } + fab!(:topic) { Fabricate(:topic) } + fab!(:post) { Fabricate(:post, topic: topic) } + let(:guardian) { Guardian.new(user) } + + include_context 'A group that is allowed to assign' + + before do + SiteSetting.assign_enabled = true + add_to_assign_allowed_group(user) + end + + it "includes assigned user in serializer" do + Assigner.new(topic, user).assign(user) + serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian) + expect(serializer.as_json[:topic_view][:assigned_to_user][:username]).to eq(user.username) + expect(serializer.as_json[:topic_view][:assigned_to_group]).to be nil + end + + it "includes assigned group in serializer" do + Assigner.new(topic, user).assign(assign_allowed_group) + serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian) + expect(serializer.as_json[:topic_view][:assigned_to_group][:name]).to eq(assign_allowed_group.name) + expect(serializer.as_json[:topic_view][:assigned_to_user]).to be nil + end + + it "includes priority in serializer" do + Assigner.new(topic, user).assign(user, priority: 1) + serializer = TopicViewSerializer.new(TopicView.new(topic), scope: guardian) + expect(serializer.as_json[:topic_view][:assignment_priority]).to eq(1) + end +end From 1e0fa0a0c7ede7ecb4f1084c7f9d608c0e6a9ae7 Mon Sep 17 00:00:00 2001 From: Nat Date: Mon, 25 Apr 2022 19:33:37 +0800 Subject: [PATCH 4/4] Remove unneeded require --- assets/stylesheets/assigns.scss | 2 ++ spec/requests/assign_controller_spec.rb | 1 - spec/serializers/topic_view_serializer_spec.rb | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/stylesheets/assigns.scss b/assets/stylesheets/assigns.scss index b9d8b866..70d120ca 100644 --- a/assets/stylesheets/assigns.scss +++ b/assets/stylesheets/assigns.scss @@ -78,6 +78,8 @@ .assign-suggestions { margin-top: 15px; + margin-bottom: 15px; + img { margin-right: 5px; cursor: pointer; diff --git a/spec/requests/assign_controller_spec.rb b/spec/requests/assign_controller_spec.rb index 28352691..0948942a 100644 --- a/spec/requests/assign_controller_spec.rb +++ b/spec/requests/assign_controller_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'rails_helper' require_relative '../support/assign_allowed_group' RSpec.describe DiscourseAssign::AssignController do diff --git a/spec/serializers/topic_view_serializer_spec.rb b/spec/serializers/topic_view_serializer_spec.rb index 14f657b5..9b26d3f6 100644 --- a/spec/serializers/topic_view_serializer_spec.rb +++ b/spec/serializers/topic_view_serializer_spec.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require 'rails_helper' require_relative '../support/assign_allowed_group' RSpec.describe TopicViewSerializer do