Commit 8437c8e5 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'feat/broadcast-message-dimsiss' into 'master'

Add user dismiss option to broadcast messages

Closes #16999

See merge request gitlab-org/gitlab!20665
parents 04ab63a1 4bd1c999
...@@ -6,16 +6,14 @@ const handleOnDismiss = ({ currentTarget }) => { ...@@ -6,16 +6,14 @@ const handleOnDismiss = ({ currentTarget }) => {
dataset: { id }, dataset: { id },
} = currentTarget; } = currentTarget;
Cookies.set(`hide_broadcast_notification_message_${id}`, true); Cookies.set(`hide_broadcast_message_${id}`, true);
const notification = document.querySelector(`.js-broadcast-notification-${id}`); const notification = document.querySelector(`.js-broadcast-notification-${id}`);
notification.parentNode.removeChild(notification); notification.parentNode.removeChild(notification);
}; };
export default () => { export default () => {
const dismissButton = document.querySelector('.js-dismiss-current-broadcast-notification'); document
.querySelectorAll('.js-dismiss-current-broadcast-notification')
if (dismissButton) { .forEach(dismissButton => dismissButton.addEventListener('click', handleOnDismiss));
dismissButton.addEventListener('click', handleOnDismiss);
}
}; };
...@@ -25,9 +25,11 @@ export default () => { ...@@ -25,9 +25,11 @@ export default () => {
$broadcastMessageType.on('change', () => { $broadcastMessageType.on('change', () => {
const $broadcastMessageColorFormGroup = $('.js-broadcast-message-background-color-form-group'); const $broadcastMessageColorFormGroup = $('.js-broadcast-message-background-color-form-group');
const $broadcastMessageDismissableFormGroup = $('.js-broadcast-message-dismissable-form-group');
const $broadcastNotificationMessagePreview = $('.js-broadcast-notification-message-preview'); const $broadcastNotificationMessagePreview = $('.js-broadcast-notification-message-preview');
$broadcastMessageColorFormGroup.toggleClass('hidden'); $broadcastMessageColorFormGroup.toggleClass('hidden');
$broadcastMessageDismissableFormGroup.toggleClass('hidden');
$broadcastBannerMessagePreview.toggleClass('hidden'); $broadcastBannerMessagePreview.toggleClass('hidden');
$broadcastNotificationMessagePreview.toggleClass('hidden'); $broadcastNotificationMessagePreview.toggleClass('hidden');
}); });
......
...@@ -17,6 +17,10 @@ ...@@ -17,6 +17,10 @@
@extend .broadcast-message; @extend .broadcast-message;
@extend .alert-warning; @extend .alert-warning;
text-align: center; text-align: center;
.broadcast-message-dismiss {
color: inherit;
}
} }
.broadcast-notification-message { .broadcast-notification-message {
...@@ -36,6 +40,11 @@ ...@@ -36,6 +40,11 @@
&.preview { &.preview {
position: static; position: static;
} }
.broadcast-message-dismiss {
height: 100%;
color: $gray-800;
}
} }
.toggle-colors { .toggle-colors {
......
...@@ -62,6 +62,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController ...@@ -62,6 +62,7 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController
starts_at starts_at
target_path target_path
broadcast_type broadcast_type
dismissable
)) ))
end end
end end
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
module BroadcastMessagesHelper module BroadcastMessagesHelper
def current_broadcast_banner_messages def current_broadcast_banner_messages
BroadcastMessage.current_banner_messages(request.path) BroadcastMessage.current_banner_messages(request.path).select do |message|
cookies["hide_broadcast_message_#{message.id}"].blank?
end
end end
def current_broadcast_notification_message def current_broadcast_notification_message
not_hidden_messages = BroadcastMessage.current_notification_messages(request.path).select do |message| not_hidden_messages = BroadcastMessage.current_notification_messages(request.path).select do |message|
cookies["hide_broadcast_notification_message_#{message.id}"].blank? cookies["hide_broadcast_message_#{message.id}"].blank?
end end
not_hidden_messages.last not_hidden_messages.last
end end
......
...@@ -46,6 +46,13 @@ ...@@ -46,6 +46,13 @@
= render_suggested_colors = render_suggested_colors
.form-group.row.js-broadcast-message-dismissable-form-group{ class: ('hidden' unless @broadcast_message.banner? ) }
.col-sm-2.col-form-label.pt-0
= f.label :starts_at, _("Dismissable")
.col-sm-10
= f.check_box :dismissable
= f.label :dismissable do
= _('Allow users to dismiss the broadcast message')
.form-group.row.js-toggle-colors-container.toggle-colors.hide .form-group.row.js-toggle-colors-container.toggle-colors.hide
.col-sm-2.col-form-label .col-sm-2.col-form-label
= f.label :font, "Font Color" = f.label :font, "Font Color"
......
%div{ class: "broadcast-#{message.broadcast_type}-message #{opts[:preview] && 'preview'} js-broadcast-notification-#{message.id} d-flex", %div{ class: "broadcast-#{message.broadcast_type}-message #{opts[:preview] && 'preview'} js-broadcast-notification-#{message.id} d-flex",
style: broadcast_message_style(message), dir: 'auto' } style: broadcast_message_style(message), dir: 'auto' }
%div .flex-grow-1.text-right.pr-2
= sprite_icon('bullhorn', size: 16, css_class: 'vertical-align-text-top') = sprite_icon('bullhorn', size: 16, css_class: 'vertical-align-text-top')
%div{ class: !fluid_layout && 'container-limited' }
= render_broadcast_message(message) = render_broadcast_message(message)
- if message.notification? && opts[:preview].blank? .flex-grow-1.text-right{ style: 'flex-basis: 0' }
%button.js-dismiss-current-broadcast-notification.btn.btn-link.text-dark.pl-2.pr-2{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id } } - if (message.notification? || message.dismissable?) && opts[:preview].blank?
%button.broadcast-message-dismiss.js-dismiss-current-broadcast-notification.btn.btn-link.pl-2.pr-2{ 'aria-label' => _('Close'), :type => 'button', data: { id: message.id } }
%i.fa.fa-times %i.fa.fa-times
---
title: Add user dismiss option to broadcast messages
merge_request: 20665
author: Fabio Huser
type: added
# frozen_string_literal: true
class AddDismissableToBroadcastMessages < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
add_column :broadcast_messages, :dismissable, :boolean
end
end
...@@ -573,6 +573,7 @@ ActiveRecord::Schema.define(version: 2020_03_03_074328) do ...@@ -573,6 +573,7 @@ ActiveRecord::Schema.define(version: 2020_03_03_074328) do
t.integer "cached_markdown_version" t.integer "cached_markdown_version"
t.string "target_path", limit: 255 t.string "target_path", limit: 255
t.integer "broadcast_type", limit: 2, default: 1, null: false t.integer "broadcast_type", limit: 2, default: 1, null: false
t.boolean "dismissable"
t.index ["ends_at", "broadcast_type", "id"], name: "index_broadcast_message_on_ends_at_and_broadcast_type_and_id" t.index ["ends_at", "broadcast_type", "id"], name: "index_broadcast_message_on_ends_at_and_broadcast_type_and_id"
end end
......
...@@ -36,7 +36,8 @@ Example response: ...@@ -36,7 +36,8 @@ Example response:
"id":1, "id":1,
"active": false, "active": false,
"target_path": "*/welcome", "target_path": "*/welcome",
"broadcast_type": "banner" "broadcast_type": "banner",
"dismissable": false
} }
] ]
``` ```
...@@ -73,7 +74,8 @@ Example response: ...@@ -73,7 +74,8 @@ Example response:
"id":1, "id":1,
"active":false, "active":false,
"target_path": "*/welcome", "target_path": "*/welcome",
"broadcast_type": "banner" "broadcast_type": "banner",
"dismissable": false
} }
``` ```
...@@ -88,14 +90,15 @@ POST /broadcast_messages ...@@ -88,14 +90,15 @@ POST /broadcast_messages
Parameters: Parameters:
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|:------------|:---------|:---------|:------------------------------------------------------| |:----------------|:---------|:---------|:------------------------------------------------------|
| `message` | string | yes | Message to display. | | `message` | string | yes | Message to display. |
| `starts_at` | datetime | no | Starting time (defaults to current time). | | `starts_at` | datetime | no | Starting time (defaults to current time). |
| `ends_at` | datetime | no | Ending time (defaults to one hour from current time). | | `ends_at` | datetime | no | Ending time (defaults to one hour from current time). |
| `color` | string | no | Background color hex code. | | `color` | string | no | Background color hex code. |
| `font` | string | no | Foreground color hex code. | | `font` | string | no | Foreground color hex code. |
| `target_path`| string | no | Target path of the broadcast message. | | `target_path` | string | no | Target path of the broadcast message. |
| `broadcast_type`| string | no | Appearance type (defaults to banner) | | `broadcast_type`| string | no | Appearance type (defaults to banner) |
| `dismissable` | boolean | no | Can the user dismiss the message? |
Example request: Example request:
...@@ -116,6 +119,7 @@ Example response: ...@@ -116,6 +119,7 @@ Example response:
"active": true, "active": true,
"target_path": "*/welcome", "target_path": "*/welcome",
"broadcast_type": "notification", "broadcast_type": "notification",
"dismissable": false
} }
``` ```
...@@ -130,15 +134,16 @@ PUT /broadcast_messages/:id ...@@ -130,15 +134,16 @@ PUT /broadcast_messages/:id
Parameters: Parameters:
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
|:------------|:---------|:---------|:-----------------------------------| |:----------------|:---------|:---------|:--------------------------------------|
| `id` | integer | yes | ID of broadcast message to update. | | `id` | integer | yes | ID of broadcast message to update. |
| `message` | string | no | Message to display. | | `message` | string | no | Message to display. |
| `starts_at` | datetime | no | Starting time. | | `starts_at` | datetime | no | Starting time. |
| `ends_at` | datetime | no | Ending time. | | `ends_at` | datetime | no | Ending time. |
| `color` | string | no | Background color hex code. | | `color` | string | no | Background color hex code. |
| `font` | string | no | Foreground color hex code. | | `font` | string | no | Foreground color hex code. |
| `target_path`| string | no | Target path of the broadcast message. | | `target_path` | string | no | Target path of the broadcast message. |
| `broadcast_type`| string | no | Appearance type (defaults to banner) | | `broadcast_type`| string | no | Appearance type (defaults to banner) |
| `dismissable` | boolean | no | Can the user dismiss the message? |
Example request: Example request:
...@@ -159,6 +164,7 @@ Example response: ...@@ -159,6 +164,7 @@ Example response:
"active": true, "active": true,
"target_path": "*/welcome", "target_path": "*/welcome",
"broadcast_type": "notification", "broadcast_type": "notification",
"dismissable": false
} }
``` ```
......
...@@ -28,7 +28,7 @@ To add a broadcast message: ...@@ -28,7 +28,7 @@ To add a broadcast message:
NOTE: **Note:** NOTE: **Note:**
Once a broadcast message has expired, it is no longer displayed in the UI but is still listed in the Once a broadcast message has expired, it is no longer displayed in the UI but is still listed in the
list of broadcast messages. list of broadcast messages. User can also dismiss a broadcast message if the option **Dismissable** is set.
## Editing a broadcast message ## Editing a broadcast message
......
...@@ -36,6 +36,7 @@ module API ...@@ -36,6 +36,7 @@ module API
optional :font, type: String, desc: 'Foreground color' optional :font, type: String, desc: 'Foreground color'
optional :target_path, type: String, desc: 'Target path' optional :target_path, type: String, desc: 'Target path'
optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast type. Defaults to banner', default: -> { 'banner' } optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast type. Defaults to banner', default: -> { 'banner' }
optional :dismissable, type: Boolean, desc: 'Is dismissable'
end end
post do post do
authenticated_as_admin! authenticated_as_admin!
...@@ -75,6 +76,7 @@ module API ...@@ -75,6 +76,7 @@ module API
optional :font, type: String, desc: 'Foreground color' optional :font, type: String, desc: 'Foreground color'
optional :target_path, type: String, desc: 'Target path' optional :target_path, type: String, desc: 'Target path'
optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast Type' optional :broadcast_type, type: String, values: BroadcastMessage.broadcast_types.keys, desc: 'Broadcast Type'
optional :dismissable, type: Boolean, desc: 'Is dismissable'
end end
put ':id' do put ':id' do
authenticated_as_admin! authenticated_as_admin!
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module API module API
module Entities module Entities
class BroadcastMessage < Grape::Entity class BroadcastMessage < Grape::Entity
expose :id, :message, :starts_at, :ends_at, :color, :font, :target_path, :broadcast_type expose :id, :message, :starts_at, :ends_at, :color, :font, :target_path, :broadcast_type, :dismissable
expose :active?, as: :active expose :active?, as: :active
end end
end end
......
...@@ -1666,6 +1666,9 @@ msgstr "" ...@@ -1666,6 +1666,9 @@ msgstr ""
msgid "Allow this secondary node to replicate content on Object Storage" msgid "Allow this secondary node to replicate content on Object Storage"
msgstr "" msgstr ""
msgid "Allow users to dismiss the broadcast message"
msgstr ""
msgid "Allow users to register any application to use GitLab as an OAuth provider" msgid "Allow users to register any application to use GitLab as an OAuth provider"
msgstr "" msgstr ""
...@@ -6910,6 +6913,9 @@ msgstr "" ...@@ -6910,6 +6913,9 @@ msgstr ""
msgid "Dismiss trial promotion" msgid "Dismiss trial promotion"
msgstr "" msgstr ""
msgid "Dismissable"
msgstr ""
msgid "Dismissed" msgid "Dismissed"
msgstr "" msgstr ""
......
...@@ -3,14 +3,15 @@ ...@@ -3,14 +3,15 @@
require 'spec_helper' require 'spec_helper'
describe 'Broadcast Messages' do describe 'Broadcast Messages' do
let!(:broadcast_message) { create(:broadcast_message, broadcast_type: 'notification', message: 'SampleMessage') } shared_examples 'a Broadcast Messages' do
it 'shows broadcast message' do it 'shows broadcast message' do
visit root_path visit root_path
expect(page).to have_content 'SampleMessage' expect(page).to have_content 'SampleMessage'
end end
end
shared_examples 'a dismissable Broadcast Messages' do
it 'hides broadcast message after dismiss', :js do it 'hides broadcast message after dismiss', :js do
visit root_path visit root_path
...@@ -27,4 +28,33 @@ describe 'Broadcast Messages' do ...@@ -27,4 +28,33 @@ describe 'Broadcast Messages' do
expect(page).not_to have_content 'SampleMessage' expect(page).not_to have_content 'SampleMessage'
end end
end
describe 'banner type' do
let!(:broadcast_message) { create(:broadcast_message, message: 'SampleMessage') }
it_behaves_like 'a Broadcast Messages'
it 'shows broadcast message' do
visit root_path
expect(page).not_to have_selector('.js-dismiss-current-broadcast-notification')
end
end
describe 'dismissable banner type' do
let!(:broadcast_message) { create(:broadcast_message, dismissable: true, message: 'SampleMessage') }
it_behaves_like 'a Broadcast Messages'
it_behaves_like 'a dismissable Broadcast Messages'
end
describe 'notification type' do
let!(:broadcast_message) { create(:broadcast_message, broadcast_type: 'notification', message: 'SampleMessage') }
it_behaves_like 'a Broadcast Messages'
it_behaves_like 'a dismissable Broadcast Messages'
end
end end
...@@ -14,7 +14,7 @@ describe BroadcastMessagesHelper do ...@@ -14,7 +14,7 @@ describe BroadcastMessagesHelper do
context 'when last broadcast message is hidden' do context 'when last broadcast message is hidden' do
before do before do
helper.request.cookies["hide_broadcast_notification_message_#{broadcast_message_2.id}"] = 'true' helper.request.cookies["hide_broadcast_message_#{broadcast_message_2.id}"] = 'true'
end end
it { is_expected.to eq broadcast_message_1 } it { is_expected.to eq broadcast_message_1 }
...@@ -29,6 +29,10 @@ describe BroadcastMessagesHelper do ...@@ -29,6 +29,10 @@ describe BroadcastMessagesHelper do
describe 'broadcast_message' do describe 'broadcast_message' do
let(:current_broadcast_message) { BroadcastMessage.new(message: 'Current Message') } let(:current_broadcast_message) { BroadcastMessage.new(message: 'Current Message') }
before do
allow(helper).to receive(:current_user).and_return(create(:user))
end
it 'returns nil when no current message' do it 'returns nil when no current message' do
expect(helper.broadcast_message(nil)).to be_nil expect(helper.broadcast_message(nil)).to be_nil
end end
......
...@@ -17,7 +17,7 @@ describe API::BroadcastMessages do ...@@ -17,7 +17,7 @@ describe API::BroadcastMessages do
expect(response).to include_pagination_headers expect(response).to include_pagination_headers
expect(json_response).to be_kind_of(Array) expect(json_response).to be_kind_of(Array)
expect(json_response.first.keys) expect(json_response.first.keys)
.to match_array(%w(id message starts_at ends_at color font active target_path broadcast_type)) .to match_array(%w(id message starts_at ends_at color font active target_path broadcast_type dismissable))
end end
end end
...@@ -28,7 +28,7 @@ describe API::BroadcastMessages do ...@@ -28,7 +28,7 @@ describe API::BroadcastMessages do
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq message.id expect(json_response['id']).to eq message.id
expect(json_response.keys) expect(json_response.keys)
.to match_array(%w(id message starts_at ends_at color font active target_path broadcast_type)) .to match_array(%w(id message starts_at ends_at color font active target_path broadcast_type dismissable))
end end
end end
...@@ -111,6 +111,15 @@ describe API::BroadcastMessages do ...@@ -111,6 +111,15 @@ describe API::BroadcastMessages do
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
end end
it 'accepts an active dismissable value ' do
attrs = { message: 'new message', dismissable: true }
post api('/broadcast_messages', admin), params: attrs
expect(response).to have_gitlab_http_status(:created)
expect(json_response['dismissable']).to eq true
end
end end
end end
...@@ -187,6 +196,15 @@ describe API::BroadcastMessages do ...@@ -187,6 +196,15 @@ describe API::BroadcastMessages do
expect(response).to have_gitlab_http_status(:bad_request) expect(response).to have_gitlab_http_status(:bad_request)
end end
it 'accepts a new dismissable value ' do
attrs = { message: 'new message', dismissable: true }
put api("/broadcast_messages/#{message.id}", admin), params: attrs
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['dismissable']).to eq true
end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment