diff options
-rw-r--r-- | app/assets/javascripts/subscription.js.coffee | 18 | ||||
-rw-r--r-- | app/controllers/projects/issues_controller.rb | 11 | ||||
-rw-r--r-- | app/controllers/projects/merge_requests_controller.rb | 11 | ||||
-rw-r--r-- | app/models/concerns/issuable.rb | 10 | ||||
-rw-r--r-- | app/models/subscribe.rb | 3 | ||||
-rw-r--r-- | app/services/notification_service.rb | 18 | ||||
-rw-r--r-- | app/views/projects/issues/_issue_context.html.haml | 16 | ||||
-rw-r--r-- | app/views/projects/merge_requests/show/_context.html.haml | 16 | ||||
-rw-r--r-- | config/routes.rb | 4 | ||||
-rw-r--r-- | db/migrate/20150313012111_create_subscribes_table.rb | 12 | ||||
-rw-r--r-- | db/schema.rb | 11 |
11 files changed, 127 insertions, 3 deletions
diff --git a/app/assets/javascripts/subscription.js.coffee b/app/assets/javascripts/subscription.js.coffee new file mode 100644 index 00000000000..f457622fc3a --- /dev/null +++ b/app/assets/javascripts/subscription.js.coffee @@ -0,0 +1,18 @@ +class @Subscription + constructor: (url) -> + $(".subscribe-button").click (event)=> + self = @ + btn = $(event.currentTarget) + action = btn.prop("value") + current_status = $(".sub_status").text().trim() + $(".fa-spinner.subscription").removeClass("hidden") + $(".sub_status").empty() + + $.post url, subscription: action, => + $(".fa-spinner.subscription").addClass("hidden") + status = if current_status == "subscribed" then "unsubscribed" else "subscribed" + $(".sub_status").text(status) + action = if status == "subscribed" then "Unsubscribe" else "Subscribe" + btn.prop("value", action) + + diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 4266bcaef16..4eb5092b9d9 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -1,6 +1,6 @@ class Projects::IssuesController < Projects::ApplicationController before_filter :module_enabled - before_filter :issue, only: [:edit, :update, :show] + before_filter :issue, only: [:edit, :update, :show, :set_subscription] # Allow read any issue before_filter :authorize_read_issue! @@ -97,6 +97,15 @@ class Projects::IssuesController < Projects::ApplicationController redirect_to :back, notice: "#{result[:count]} issues updated" end + def set_subscription + subscribed = params[:subscription] == "Subscribe" + + sub = @issue.subscribes.find_or_create_by(user_id: current_user.id) + sub.update(subscribed: subscribed) + + render nothing: true + end + protected def issue diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb index 93d79d81661..5613eee35c0 100644 --- a/app/controllers/projects/merge_requests_controller.rb +++ b/app/controllers/projects/merge_requests_controller.rb @@ -2,7 +2,7 @@ require 'gitlab/satellite/satellite' class Projects::MergeRequestsController < Projects::ApplicationController before_filter :module_enabled - before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status] + before_filter :merge_request, only: [:edit, :update, :show, :diffs, :automerge, :automerge_check, :ci_status, :set_subscription] before_filter :closes_issues, only: [:edit, :update, :show, :diffs] before_filter :validates_merge_request, only: [:show, :diffs] before_filter :define_show_vars, only: [:show, :diffs] @@ -174,6 +174,15 @@ class Projects::MergeRequestsController < Projects::ApplicationController render json: response end + def set_subscription + subscribed = params[:subscription] == "Subscribe" + + sub = @merge_request.subscribes.find_or_create_by(user_id: current_user.id) + sub.update(subscribed: subscribed) + + render nothing: true + end + protected def selected_target_project diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index f5e23e9dc2d..e89dcbf9acb 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -15,6 +15,7 @@ module Issuable has_many :notes, as: :noteable, dependent: :destroy has_many :label_links, as: :target, dependent: :destroy has_many :labels, through: :label_links + has_many :subscribes, dependent: :destroy validates :author, presence: true validates :title, presence: true, length: { within: 0..255 } @@ -132,6 +133,15 @@ module Issuable users.concat(mentions.reduce([], :|)).uniq end + def subscribe_status(user) + sub = subscribes.find_by_user_id(user.id) + if sub + return sub.subscribed + end + + participants.include?(user) + end + def to_hook_data(user) { object_kind: self.class.name.underscore, diff --git a/app/models/subscribe.rb b/app/models/subscribe.rb new file mode 100644 index 00000000000..a68546667f1 --- /dev/null +++ b/app/models/subscribe.rb @@ -0,0 +1,3 @@ +class Subscribe < ActiveRecord::Base + belongs_to :user +end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 0063b7ce40c..4fa775a28ce 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -314,6 +314,13 @@ class NotificationService end end + def reject_unsubscribed_users(recipients, target) + recipients.reject do |user| + subscribe = target.subscribes.find_by_user_id(user.id) + subscribe && !subscribe.subscribed + end + end + def new_resource_email(target, project, method) recipients = build_recipients(target, project) recipients.delete(target.author) @@ -361,10 +368,21 @@ class NotificationService recipients = reject_muted_users(recipients, project) recipients = reject_mention_users(recipients, project) + recipients = add_subscribers(recipients, project) recipients = recipients.concat(project_watchers(project)).uniq + recipients = reject_unsubscribed_users(recipients, target) recipients end + def add_subscribers(recipients, target) + subs = target.subscribes + if subs.any? + recipients.merge(subs.where("subscribed is true").map(&:user)) + else + recipients + end + end + def mailer Notify.delay end diff --git a/app/views/projects/issues/_issue_context.html.haml b/app/views/projects/issues/_issue_context.html.haml index 4c7654354f4..09c531ac7fc 100644 --- a/app/views/projects/issues/_issue_context.html.haml +++ b/app/views/projects/issues/_issue_context.html.haml @@ -26,3 +26,19 @@ = f.select(:milestone_id, milestone_options(@issue), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :issue_context = f.submit class: 'btn' + + %div.prepend-top-20.clearfix + .issuable-context-title + %label + Subscription: + %i.fa.fa-spinner.fa-spin.hidden.subscription + %span.sub_status + = @issue.subscribe_status(current_user) ? "subscribed" : "unsubscribed" + - subscribe_action = @issue.subscribe_status(current_user) ? "Unsubscribe" : "Subscribe" + %input.btn.subscribe-button{:type => "button", :value => subscribe_action} + +:coffeescript + $ -> + new Subscription("#{set_subscription_namespace_project_issue_path(@issue.project.namespace, @project, @issue)}") + +
\ No newline at end of file diff --git a/app/views/projects/merge_requests/show/_context.html.haml b/app/views/projects/merge_requests/show/_context.html.haml index a74f3fb24e7..aae0aa24ed7 100644 --- a/app/views/projects/merge_requests/show/_context.html.haml +++ b/app/views/projects/merge_requests/show/_context.html.haml @@ -28,3 +28,19 @@ = f.select(:milestone_id, milestone_options(@merge_request), { include_blank: "Select milestone" }, {class: 'select2 select2-compact js-select2 js-milestone'}) = hidden_field_tag :merge_request_context = f.submit class: 'btn' + + %div.prepend-top-20.clearfix + .issuable-context-title + %label + Subscription: + %i.fa.fa-spinner.fa-spin.hidden.subscription + %span.sub_status + = @merge_request.subscribe_status(current_user) ? "subscribed" : "unsubscribed" + - subscribe_action = @merge_request.subscribe_status(current_user) ? "Unsubscribe" : "Subscribe" + %input.btn.subscribe-button{:type => "button", :value => subscribe_action} + +:coffeescript + $ -> + new Subscription("#{set_subscription_namespace_project_issue_path(@merge_request.project.namespace, @project, @merge_request)}") + +
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 889995e92a6..a976ba9d593 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -406,6 +406,7 @@ Gitlab::Application.routes.draw do post :automerge get :automerge_check get :ci_status + post :set_subscription end collection do @@ -440,6 +441,9 @@ Gitlab::Application.routes.draw do end resources :issues, constraints: { id: /\d+/ }, except: [:destroy] do + member do + post :set_subscription + end collection do post :bulk_update end diff --git a/db/migrate/20150313012111_create_subscribes_table.rb b/db/migrate/20150313012111_create_subscribes_table.rb new file mode 100644 index 00000000000..706cf77118c --- /dev/null +++ b/db/migrate/20150313012111_create_subscribes_table.rb @@ -0,0 +1,12 @@ +class CreateSubscribesTable < ActiveRecord::Migration + def change + create_table :subscribes do |t| + t.integer :user_id + t.integer :merge_request_id + t.integer :issue_id + t.boolean :subscribed + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 3afbc082b70..6afb79069e4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150306023112) do +ActiveRecord::Schema.define(version: 20150313012111) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -397,6 +397,15 @@ ActiveRecord::Schema.define(version: 20150306023112) do add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree + create_table "subscribes", force: true do |t| + t.integer "user_id" + t.integer "merge_request_id" + t.integer "issue_id" + t.boolean "subscribed" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "taggings", force: true do |t| t.integer "tag_id" t.integer "taggable_id" |