diff options
author | Brett Walker <bwalker@gitlab.com> | 2019-08-17 08:56:48 +0300 |
---|---|---|
committer | Paul Slaughter <pslaughter@gitlab.com> | 2019-08-17 08:56:48 +0300 |
commit | 9be16e1f495655e68bc980fced9a8075223ccccf (patch) | |
tree | c3ac8db7b555e7b4aef5d1d9f12eb08ad17dd5dd /app | |
parent | 9eabc0d6fc268023db13e8dad315f99f4fe1a6da (diff) |
UI for disabling group/project email notification
- Adds UI to configure in group and project settings
- Removes notification configuration for users when
disabled at group or project level
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue | 15 | ||||
-rw-r--r-- | app/helpers/groups_helper.rb | 5 | ||||
-rw-r--r-- | app/helpers/notifications_helper.rb | 14 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 10 | ||||
-rw-r--r-- | app/serializers/issuable_sidebar_basic_entity.rb | 4 | ||||
-rw-r--r-- | app/views/groups/_home_panel.html.haml | 3 | ||||
-rw-r--r-- | app/views/groups/settings/_permissions.html.haml | 10 | ||||
-rw-r--r-- | app/views/profiles/notifications/_group_settings.html.haml | 9 | ||||
-rw-r--r-- | app/views/profiles/notifications/_project_settings.html.haml | 9 | ||||
-rw-r--r-- | app/views/projects/_home_panel.html.haml | 4 | ||||
-rw-r--r-- | app/views/shared/issuable/_sidebar.html.haml | 6 | ||||
-rw-r--r-- | app/views/shared/notifications/_button.html.haml | 15 | ||||
-rw-r--r-- | app/views/shared/notifications/_new_button.html.haml | 13 |
13 files changed, 94 insertions, 23 deletions
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index 627d37bac68..a223a8f5b08 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -28,6 +28,11 @@ export default { type: Object, required: true, }, + canDisableEmails: { + type: Boolean, + required: false, + default: false, + }, canChangeVisibilityLevel: { type: Boolean, required: false, @@ -104,6 +109,7 @@ export default { lfsEnabled: true, requestAccessEnabled: true, highlightChangesClass: false, + emailsDisabled: false, }; return { ...defaults, ...this.currentSettings }; @@ -341,5 +347,14 @@ export default { /> </project-setting-row> </div> + <project-setting-row v-if="canDisableEmails" class="mb-3"> + <label class="js-emails-disabled"> + <input :value="emailsDisabled" type="hidden" name="project[emails_disabled]" /> + <input v-model="emailsDisabled" type="checkbox" /> {{ __('Disable email notifications') }} + </label> + <span class="form-text text-muted">{{ + __('This setting will override user notification preferences for all project members.') + }}</span> + </project-setting-row> </div> </template> diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index 160f9ac4793..bd26bd01313 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -31,6 +31,11 @@ module GroupsHelper can?(current_user, :change_share_with_group_lock, group) end + def can_disable_group_emails?(group) + Feature.enabled?(:emails_disabled, group, default_enabled: true) && + can?(current_user, :set_emails_disabled, group) && !group.parent&.emails_disabled? + end + def group_issues_count(state:) IssuesFinder .new(current_user, group_id: @group.id, state: state, non_archived: true, include_subgroups: true) diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 11b9cf22142..5678304ffcf 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -5,7 +5,7 @@ module NotificationsHelper def notification_icon_class(level) case level.to_sym - when :disabled + when :disabled, :owner_disabled 'microphone-slash' when :participating 'volume-up' @@ -18,6 +18,16 @@ module NotificationsHelper end end + def notification_icon_level(notification_setting, emails_disabled = false) + if emails_disabled + 'owner_disabled' + elsif notification_setting.global? + current_user.global_notification_setting.level + else + notification_setting.level + end + end + def notification_icon(level, text = nil) icon("#{notification_icon_class(level)} fw", text: text) end @@ -53,6 +63,8 @@ module NotificationsHelper _('Use your global notification setting') when :custom _('You will only receive notifications for the events you choose') + when :owner_disabled + _('Notifications have been disabled by the project or group owner') end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 71c9c121e48..33bf2d57fae 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -155,6 +155,12 @@ module ProjectsHelper end end + def can_disable_emails?(project, current_user) + return false if project.group&.emails_disabled? + + can?(current_user, :set_emails_disabled, project) && Feature.enabled?(:emails_disabled, project, default_enabled: true) + end + def last_push_event current_user&.recent_push(@project) end @@ -541,13 +547,15 @@ module ProjectsHelper snippetsAccessLevel: feature.snippets_access_level, pagesAccessLevel: feature.pages_access_level, containerRegistryEnabled: !!project.container_registry_enabled, - lfsEnabled: !!project.lfs_enabled + lfsEnabled: !!project.lfs_enabled, + emailsDisabled: project.emails_disabled? } end def project_permissions_panel_data(project) { currentSettings: project_permissions_settings(project), + canDisableEmails: can_disable_emails?(project, current_user), canChangeVisibilityLevel: can_change_visibility_level?(project, current_user), allowedVisibilityOptions: project_allowed_visibility_levels(project), visibilityHelpPath: help_page_path('public_access/public_access'), diff --git a/app/serializers/issuable_sidebar_basic_entity.rb b/app/serializers/issuable_sidebar_basic_entity.rb index 61de3c93337..c02fd024345 100644 --- a/app/serializers/issuable_sidebar_basic_entity.rb +++ b/app/serializers/issuable_sidebar_basic_entity.rb @@ -98,6 +98,10 @@ class IssuableSidebarBasicEntity < Grape::Entity autocomplete_projects_path(project_id: issuable.project.id) end + expose :project_emails_disabled do |issuable| + issuable.project.emails_disabled? + end + private def current_user diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml index 4daf3683eaf..e50d2b8e994 100644 --- a/app/views/groups/_home_panel.html.haml +++ b/app/views/groups/_home_panel.html.haml @@ -1,4 +1,5 @@ - can_create_subgroups = can?(current_user, :create_subgroup, @group) +- emails_disabled = @group.emails_disabled? .group-home-panel .row.mb-3 @@ -21,7 +22,7 @@ .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end - if current_user .group-buttons - = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn' + = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn', emails_disabled: emails_disabled - if can? current_user, :create_projects, @group - new_project_label = _("New project") - new_subgroup_label = _("New subgroup") diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml index 162d28abb8c..94a938021f9 100644 --- a/app/views/groups/settings/_permissions.html.haml +++ b/app/views/groups/settings/_permissions.html.haml @@ -11,12 +11,18 @@ .form-check = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input' = f.label :share_with_group_lock, class: 'form-check-label' do - %span + %span.d-block - group_link = link_to @group.name, group_path(@group) = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link } - %br %span.descr.text-muted= share_with_group_lock_help_text(@group) + .form-group.append-bottom-default + .form-check + = f.check_box :emails_disabled, checked: @group.emails_disabled?, disabled: !can_disable_group_emails?(@group), class: 'form-check-input' + = f.label :emails_disabled, class: 'form-check-label' do + %span.d-block= s_('GroupSettings|Disable email notifications') + %span.text-muted= s_('GroupSettings|This setting will override user notification preferences for all members of the group, subgroups, and projects.') + = render_if_exists 'groups/settings/ip_restriction', f: f, group: @group = render_if_exists 'groups/settings/allowed_email_domain', f: f, group: @group = render 'groups/settings/lfs', f: f diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml index cf17ee44145..1776d260e19 100644 --- a/app/views/profiles/notifications/_group_settings.html.haml +++ b/app/views/profiles/notifications/_group_settings.html.haml @@ -1,16 +1,15 @@ +- emails_disabled = group.emails_disabled? + .gl-responsive-table-row.notification-list-item .table-section.section-40 %span.notification.fa.fa-holder.append-right-5 - - if setting.global? - = notification_icon(current_user.global_notification_setting.level) - - else - = notification_icon(setting.level) + = notification_icon(notification_icon_level(setting, emails_disabled)) %span.str-truncated = link_to group.name, group_path(group) .table-section.section-30.text-right - = render 'shared/notifications/button', notification_setting: setting + = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled .table-section.section-30 = form_for @user.notification_settings.find { |ns| ns.source == group }, url: profile_notifications_group_path(group), method: :put, html: { class: 'update-notifications' } do |f| diff --git a/app/views/profiles/notifications/_project_settings.html.haml b/app/views/profiles/notifications/_project_settings.html.haml index 823fec3fab4..63a77b335b6 100644 --- a/app/views/profiles/notifications/_project_settings.html.haml +++ b/app/views/profiles/notifications/_project_settings.html.haml @@ -1,12 +1,11 @@ +- emails_disabled = project.emails_disabled? + %li.notification-list-item %span.notification.fa.fa-holder.append-right-5 - - if setting.global? - = notification_icon(current_user.global_notification_setting.level) - - else - = notification_icon(setting.level) + = notification_icon(notification_icon_level(setting, emails_disabled)) %span.str-truncated = link_to_project(project) .float-right - = render 'shared/notifications/button', notification_setting: setting + = render 'shared/notifications/button', notification_setting: setting, emails_disabled: emails_disabled diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 824fe3c791d..4783b10cf6d 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -1,6 +1,8 @@ - empty_repo = @project.empty_repo? - show_auto_devops_callout = show_auto_devops_callout?(@project) - max_project_topic_length = 15 +- emails_disabled = @project.emails_disabled? + .project-home-panel{ class: [("empty-project" if empty_repo), ("js-keep-hidden-on-navigation" if vue_file_list_enabled?)] } .row.append-bottom-8 .home-panel-title-row.col-md-12.col-lg-6.d-flex @@ -41,7 +43,7 @@ .project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end - if current_user .d-inline-flex - = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs' + = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs', emails_disabled: emails_disabled .count-buttons.d-inline-flex = render 'projects/buttons/star' diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index b4f8377c008..825088a58e7 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -137,7 +137,11 @@ .js-sidebar-participants-entry-point - if signed_in - .js-sidebar-subscriptions-entry-point + - if issuable_sidebar[:project_emails_disabled] + .block.js-emails-disabled + = notification_description(:owner_disabled) + - else + .js-sidebar-subscriptions-entry-point - project_ref = issuable_sidebar[:reference] .block.project-reference diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml index 749aa258af6..b4266937a4e 100644 --- a/app/views/shared/notifications/_button.html.haml +++ b/app/views/shared/notifications/_button.html.haml @@ -1,6 +1,15 @@ -- btn_class = local_assigns.fetch(:btn_class, nil) +- btn_class = local_assigns.fetch(:btn_class, '') +- emails_disabled = local_assigns.fetch(:emails_disabled, false) - if notification_setting + - if emails_disabled + - button_title = notification_description(:owner_disabled) + - aria_label = button_title + - btn_class << " disabled" + - else + - button_title = _("Notification setting") + - aria_label = _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) } + .js-notification-dropdown.notification-dropdown.mr-md-2.home-panel-action-button.dropdown.inline = form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f| = hidden_setting_source_input(notification_setting) @@ -8,14 +17,14 @@ .js-notification-toggle-btns %div{ class: ("btn-group" if notification_setting.custom?) } - if notification_setting.custom? - %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn.text-left#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } + %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn.text-left#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => aria_label, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } = icon("bell", class: "js-notification-loading") = notification_title(notification_setting.level) %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } = icon('caret-down') .sr-only Toggle dropdown - else - %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting"), class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } + %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => aria_label, data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } .float-left = icon("bell", class: "js-notification-loading") = notification_title(notification_setting.level) diff --git a/app/views/shared/notifications/_new_button.html.haml b/app/views/shared/notifications/_new_button.html.haml index 052e6da5bae..3c8cc023848 100644 --- a/app/views/shared/notifications/_new_button.html.haml +++ b/app/views/shared/notifications/_new_button.html.haml @@ -1,6 +1,13 @@ -- btn_class = local_assigns.fetch(:btn_class, nil) +- btn_class = local_assigns.fetch(:btn_class, '') +- emails_disabled = local_assigns.fetch(:emails_disabled, false) - if notification_setting + - if emails_disabled + - button_title = notification_description(:owner_disabled) + - btn_class << " disabled" + - else + - button_title = _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) } + .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline = form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f| = hidden_setting_source_input(notification_setting) @@ -9,14 +16,14 @@ .js-notification-toggle-btns %div{ class: ("btn-group" if notification_setting.custom?) } - if notification_setting.custom? - %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } + %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } } = notification_setting_icon(notification_setting) %span.js-notification-loading.fa.hidden %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" } = sprite_icon("arrow-down", css_class: "icon mr-0") .sr-only Toggle dropdown - else - %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } + %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: button_title, class: "#{btn_class}", "aria-label" => button_title, data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } } = notification_setting_icon(notification_setting) %span.js-notification-loading.fa.hidden = sprite_icon("arrow-down", css_class: "icon") |