From 2d6fd2c922be2043ed6bbae481c032908960baeb Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Tue, 15 Nov 2016 19:59:12 -0200 Subject: Allow users to subscribe to a group label at group or project level --- .../javascripts/group_label_subscription.js.es6 | 48 ++++++++++++++++++++++ app/assets/stylesheets/pages/labels.scss | 10 ++++- app/helpers/labels_helper.rb | 14 +++++++ app/models/concerns/subscribable.rb | 27 ++++++++++-- app/views/shared/_label.html.haml | 34 ++++++++++++--- 5 files changed, 122 insertions(+), 11 deletions(-) create mode 100644 app/assets/javascripts/group_label_subscription.js.es6 diff --git a/app/assets/javascripts/group_label_subscription.js.es6 b/app/assets/javascripts/group_label_subscription.js.es6 new file mode 100644 index 00000000000..3bc1d7127d1 --- /dev/null +++ b/app/assets/javascripts/group_label_subscription.js.es6 @@ -0,0 +1,48 @@ +/* eslint-disable */ +(function(global) { + class GroupLabelSubscription { + constructor(container) { + const $container = $(container); + this.$dropdown = $container.find('.dropdown'); + this.$unsubscribeBtn = $container.find('.js-unsubscribe-button'); + + $container.on('click', '.js-subscribe-button', this.subscribe.bind(this)); + $container.on('click', '.js-unsubscribe-button', this.unsubscribe.bind(this)); + } + + unsubscribe(event) { + event.preventDefault(); + + const url = this.$unsubscribeBtn.attr('data-url'); + + $.ajax({ + type: 'POST', + url: url + }).done(() => { + this.$dropdown.toggleClass('hidden'); + this.$unsubscribeBtn.toggleClass('hidden'); + this.$unsubscribeBtn.removeAttr('data-url'); + }); + } + + subscribe(event) { + event.preventDefault(); + + const $btn = $(event.currentTarget); + const url = $btn.attr('data-url'); + + this.$unsubscribeBtn.attr('data-url', url); + + $.ajax({ + type: 'POST', + url: url + }).done(() => { + this.$dropdown.toggleClass('hidden'); + this.$unsubscribeBtn.toggleClass('hidden'); + }); + } + } + + global.GroupLabelSubscription = GroupLabelSubscription; + +})(window.gl || (window.gl = {})); diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index 4eed1c7bfa6..e39ce19f846 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -90,7 +90,7 @@ @media (min-width: $screen-sm-min) { display: inline-block; - width: 35%; + width: 30%; margin-left: 10px; margin-bottom: 0; vertical-align: middle; @@ -222,6 +222,14 @@ width: 100%; } +.label-subscription { + vertical-align: middle; + + .dropdown-group-label a { + cursor: pointer; + } +} + .label-subscribe-button { .label-subscribe-button-icon { &[disabled] { diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb index a7c8a8a8650..7495414f525 100644 --- a/app/helpers/labels_helper.rb +++ b/app/helpers/labels_helper.rb @@ -140,6 +140,20 @@ module LabelsHelper end end + def group_label_subscription_status(label, project) + return 'project-level' if label.subscribed?(current_user, project) + return 'group-level' if label.subscribed?(current_user) + + 'unsubscribed' + end + + def group_label_unsubscribe_path(label, project) + case group_label_subscription_status(label, project) + when 'project-level' then toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) + when 'group-level' then toggle_subscription_group_label_path(label.group, label) + end + end + def label_subscription_status(label, project) label.subscribed?(current_user, project) ? 'subscribed' : 'unsubscribed' end diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb index 0723db548d8..83daa9b1a64 100644 --- a/app/models/concerns/subscribable.rb +++ b/app/models/concerns/subscribable.rb @@ -33,22 +33,41 @@ module Subscribable end def toggle_subscription(user, project = nil) + unsubscribe_from_other_levels(user, project) + find_or_initialize_subscription(user, project). update(subscribed: !subscribed?(user, project)) end def subscribe(user, project = nil) - find_or_initialize_subscription(user, project). - update(subscribed: true) + unsubscribe_from_other_levels(user, project) + + find_or_initialize_subscription(user, project) + .update(subscribed: true) end def unsubscribe(user, project = nil) - find_or_initialize_subscription(user, project). - update(subscribed: false) + unsubscribe_from_other_levels(user, project) + + find_or_initialize_subscription(user, project) + .update(subscribed: false) end private + def unsubscribe_from_other_levels(user, project) + other_subscriptions = subscriptions.where(user: user) + + other_subscriptions = + if project.blank? + other_subscriptions.where.not(project: nil) + else + other_subscriptions.where(project: nil) + end + + other_subscriptions.update_all(subscribed: false) + end + def find_or_initialize_subscription(user, project) subscriptions. find_or_initialize_by(user_id: user.id, project_id: project.try(:id)) diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml index 942da5dd5b7..e217b1ec85e 100644 --- a/app/views/shared/_label.html.haml +++ b/app/views/shared/_label.html.haml @@ -20,7 +20,7 @@ = pluralize open_issues_count, 'open issue' - if current_user && defined?(@project) %li.label-subscription - %a.js-subscribe-button.label-subscribe-button.subscription-status{ role: "button", href: "#", data: { toggle: "tooltip", status: label_subscription_status(label, @project), url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } } + %a.js-subscribe-button.label-subscribe-button{ role: 'button', href: '#', data: { toggle: 'tooltip', status: label_subscription_status(label, @project), url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } } %span= label_subscription_toggle_button_text(label, @project) - if can?(current_user, :admin_label, label) %li @@ -36,9 +36,27 @@ - if current_user && defined?(@project) .label-subscription.inline - %button.js-subscribe-button.label-subscribe-button.btn.btn-default.btn-action.subscription-status{ type: "button", title: label_subscription_toggle_button_text(label, @project), data: { toggle: "tooltip", status: label_subscription_status(label, @project), url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } } - %span= label_subscription_toggle_button_text(label, @project) - = icon('spinner spin', class: 'label-subscribe-button-loading') + - if label.is_a?(ProjectLabel) + %button.js-subscribe-button.label-subscribe-button.btn.btn-default.btn-action{ type: 'button', title: label_subscription_toggle_button_text(label, @project), data: { toggle: 'tooltip', status: label_subscription_status(label, @project), url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } } + %span= label_subscription_toggle_button_text(label, @project) + = icon('spinner spin', class: 'label-subscribe-button-loading') + - else + - status = group_label_subscription_status(label, @project).inquiry + + %button.js-unsubscribe-button.label-subscribe-button.btn.btn-default.btn-action{ type: 'button', class: ('hidden' if status.unsubscribed?), title: 'Unsubscribe', data: { toggle: 'tooltip', url: group_label_unsubscribe_path(label, @project) } } + %span Unsubscribe + = icon('spinner spin', class: 'label-subscribe-button-loading') + + .dropdown.dropdown-group-label{ class: ('hidden' unless status.unsubscribed?) } + %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} + %span Subscribe + = icon('chevron-down') + %ul.dropdown-menu + %li + %a.js-subscribe-button{ data: { url: toggle_subscription_namespace_project_label_path(@project.namespace, @project, label) } } + Project level + %a.js-subscribe-button{ data: { url: toggle_subscription_group_label_path(label.group, label) } } + Group level - if can?(current_user, :admin_label, label) = link_to edit_label_path(label), title: "Edit", class: 'btn btn-transparent btn-action', data: {toggle: "tooltip"} do @@ -49,5 +67,9 @@ = icon('trash-o') - if current_user && defined?(@project) - :javascript - new gl.LabelSubscription('##{dom_id(label)} .label-subscription'); + - if label.is_a?(ProjectLabel) + :javascript + new gl.LabelSubscription('##{dom_id(label)} .label-subscription'); + - else + :javascript + new gl.GroupLabelSubscription('##{dom_id(label)} .label-subscription'); -- cgit v1.2.1