diff --git a/CHANGELOG b/CHANGELOG index b430d4981a9428bc77b5d52d4455888197e66cbd..f728da757207d27411d2ad99a6488440e497f2e0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -43,6 +43,7 @@ v 8.4.0 (unreleased) - API: Add support for deleting a tag via the API (Robert Schilling) - Allow subsequent validations in CI Linter - Fix Encoding::CompatibilityError bug when markdown content has some complex URL (Jason Lee) + - Allow broadcast messages to be edited v 8.3.4 - Use gitlab-workhorse 0.5.4 (fixes API routing bug) diff --git a/app/assets/javascripts/admin.js.coffee b/app/assets/javascripts/admin.js.coffee index bcb2e6df7c01450cc9bccd1a530f8811d2ae6976..eb951f717112e3160a876a0385a160832231b0ee 100644 --- a/app/assets/javascripts/admin.js.coffee +++ b/app/assets/javascripts/admin.js.coffee @@ -10,19 +10,19 @@ class @Admin $('body').on 'click', '.js-toggle-colors-link', (e) -> e.preventDefault() - $('.js-toggle-colors-link').hide() - $('.js-toggle-colors-container').show() + $('.js-toggle-colors-container').toggle() $('input#broadcast_message_color').on 'input', -> - previewColor = $('input#broadcast_message_color').val() + previewColor = $(@).val() $('div.broadcast-message-preview').css('background-color', previewColor) $('input#broadcast_message_font').on 'input', -> - previewColor = $('input#broadcast_message_font').val() + previewColor = $(@).val() $('div.broadcast-message-preview').css('color', previewColor) $('textarea#broadcast_message_message').on 'input', -> - previewMessage = $('textarea#broadcast_message_message').val() + previewMessage = $(@).val() + previewMessage = "Your message here" if previewMessage.trim() == '' $('div.broadcast-message-preview span').text(previewMessage) $('.log-tabs a').click (e) -> diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 032d343df44e3060ec5fc66499904856839b841d..d0cb91a5b64804d9b80e2423270c9539a8144a07 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -78,6 +78,10 @@ label { padding: 8px $gl-padding; } +.form-control-inline { + display: inline; +} + .wiki-content { margin-top: 35px; } diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb index 497c34f8f493bd9dfa31dc67656dbf5deb6b5151..4735b27c65d31b21a40fec21bf11aded11cd57f7 100644 --- a/app/controllers/admin/broadcast_messages_controller.rb +++ b/app/controllers/admin/broadcast_messages_controller.rb @@ -1,8 +1,12 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController - before_action :broadcast_messages + before_action :finder, only: [:edit, :update, :destroy] def index - @broadcast_message = BroadcastMessage.new + @broadcast_messages = BroadcastMessage.reorder("starts_at ASC").page(params[:page]) + @broadcast_message = BroadcastMessage.new + end + + def edit end def create @@ -15,8 +19,16 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController end end + def update + if @broadcast_message.update(broadcast_message_params) + redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully updated.' + else + render :edit + end + end + def destroy - BroadcastMessage.find(params[:id]).destroy + @broadcast_message.destroy respond_to do |format| format.html { redirect_back_or_default(default: { action: 'index' }) } @@ -26,14 +38,17 @@ class Admin::BroadcastMessagesController < Admin::ApplicationController protected - def broadcast_messages - @broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page]) + def finder + @broadcast_message = BroadcastMessage.find(params[:id]) end def broadcast_message_params - params.require(:broadcast_message).permit( - :alert_type, :color, :ends_at, :font, - :message, :starts_at - ) + params.require(:broadcast_message).permit(%i( + color + ends_at + font + message + starts_at + )) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 436fbcd41386f4b88f0173c603cab838777348a4..f3a2723ee0d1d4b496aadeeea8570e89889f0509 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -181,10 +181,6 @@ module ApplicationHelper end end - def broadcast_message - BroadcastMessage.current - end - # Render a `time` element with Javascript-based relative date and tooltip # # time - Time object diff --git a/app/helpers/broadcast_messages_helper.rb b/app/helpers/broadcast_messages_helper.rb index 6484dca6b5539dd97016fa2403bf87de5b6286a3..1ed8c710f771566dd6ba3b5511911a16704dd93f 100644 --- a/app/helpers/broadcast_messages_helper.rb +++ b/app/helpers/broadcast_messages_helper.rb @@ -1,16 +1,34 @@ module BroadcastMessagesHelper - def broadcast_styling(broadcast_message) - styling = '' + def broadcast_message(message = BroadcastMessage.current) + return unless message.present? + + content_tag :div, class: 'broadcast-message', style: broadcast_message_style(message) do + icon('bullhorn') << ' ' << message.message + end + end + + def broadcast_message_style(broadcast_message) + style = '' if broadcast_message.color.present? - styling << "background-color: #{broadcast_message.color}" - styling << '; ' if broadcast_message.font.present? + style << "background-color: #{broadcast_message.color}" + style << '; ' if broadcast_message.font.present? end if broadcast_message.font.present? - styling << "color: #{broadcast_message.font}" + style << "color: #{broadcast_message.font}" end - styling + style + end + + def broadcast_message_status(broadcast_message) + if broadcast_message.active? + 'Active' + elsif broadcast_message.ended? + 'Expired' + else + 'Pending' + end end end diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb index ad514706160bd49b15f20d3226943b738ee11cee..611196337170ad2fb8b12c07f7c90fa697179f26 100644 --- a/app/models/broadcast_message.rb +++ b/app/models/broadcast_message.rb @@ -6,7 +6,6 @@ # message :text not null # starts_at :datetime # ends_at :datetime -# alert_type :integer # created_at :datetime # updated_at :datetime # color :string(255) @@ -23,7 +22,22 @@ class BroadcastMessage < ActiveRecord::Base validates :color, allow_blank: true, color: true validates :font, allow_blank: true, color: true + default_value_for :color, '#E75E40' + default_value_for :font, '#FFFFFF' + def self.current - where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last + where("ends_at > :now AND starts_at <= :now", now: Time.zone.now).last + end + + def active? + started? && !ended? + end + + def started? + Time.zone.now >= starts_at + end + + def ended? + ends_at < Time.zone.now end end diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..953b8b693684a47a9454ab3c1411b72515f94154 --- /dev/null +++ b/app/views/admin/broadcast_messages/_form.html.haml @@ -0,0 +1,37 @@ +.broadcast-message-preview{ style: broadcast_message_style(@broadcast_message) } + = icon('bullhorn') + %span= @broadcast_message.message || "Your message here" + += form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal js-requires-input'} do |f| + -if @broadcast_message.errors.any? + .alert.alert-danger + - @broadcast_message.errors.full_messages.each do |msg| + %p= msg + .form-group + = f.label :message, class: 'control-label' + .col-sm-10 + = f.text_area :message, class: "form-control js-quick-submit", rows: 2, required: true + .form-group.js-toggle-colors-container + .col-sm-10.col-sm-offset-2 + = link_to 'Customize colors', '#', class: 'js-toggle-colors-link' + .form-group.js-toggle-colors-container.hide + = f.label :color, "Background Color", class: 'control-label' + .col-sm-10 + = f.color_field :color, class: "form-control" + .form-group.js-toggle-colors-container.hide + = f.label :font, "Font Color", class: 'control-label' + .col-sm-10 + = f.color_field :font, class: "form-control" + .form-group + = f.label :starts_at, class: 'control-label' + .col-sm-10.datetime-controls + = f.datetime_select :starts_at, {}, class: 'form-control form-control-inline' + .form-group + = f.label :ends_at, class: 'control-label' + .col-sm-10.datetime-controls + = f.datetime_select :ends_at, {}, class: 'form-control form-control-inline' + .form-actions + - if @broadcast_message.persisted? + = f.submit "Update broadcast message", class: "btn btn-create" + - else + = f.submit "Add broadcast message", class: "btn btn-create" diff --git a/app/views/admin/broadcast_messages/edit.html.haml b/app/views/admin/broadcast_messages/edit.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..45e053eb31d6c3e724b0492aec153c7c198c74c4 --- /dev/null +++ b/app/views/admin/broadcast_messages/edit.html.haml @@ -0,0 +1,3 @@ +- page_title "Broadcast Messages" + += render 'form' diff --git a/app/views/admin/broadcast_messages/index.html.haml b/app/views/admin/broadcast_messages/index.html.haml index 17dffebd360cae080004c6ba7d3939fadbbd4109..49e33698b635b09b14c5a17236656cb79ecc4a7c 100644 --- a/app/views/admin/broadcast_messages/index.html.haml +++ b/app/views/admin/broadcast_messages/index.html.haml @@ -1,60 +1,37 @@ - page_title "Broadcast Messages" + %h3.page-title Broadcast Messages %p.light - Broadcast messages are displayed for every user and can be used to notify users about scheduled maintenance, recent upgrades and more. -.broadcast-message-preview - %i.fa.fa-bullhorn - %span Your message here - -= form_for [:admin, @broadcast_message], html: { class: 'broadcast-message-form form-horizontal'} do |f| - -if @broadcast_message.errors.any? - .alert.alert-danger - - @broadcast_message.errors.full_messages.each do |msg| - %p= msg - .form-group - = f.label :message, class: 'control-label' - .col-sm-10 - = f.text_area :message, class: "form-control", rows: 2, required: true - %div - = link_to '#', class: 'js-toggle-colors-link' do - Customize colors - .form-group.js-toggle-colors-container.hide - = f.label :color, "Background Color", class: 'control-label' - .col-sm-10 - = f.color_field :color, value: "#eb9532", class: "form-control" - .form-group.js-toggle-colors-container.hide - = f.label :font, "Font Color", class: 'control-label' - .col-sm-10 - = f.color_field :font, value: "#FFFFFF", class: "form-control" - .form-group - = f.label :starts_at, class: 'control-label' - .col-sm-10.datetime-controls - = f.datetime_select :starts_at - .form-group - = f.label :ends_at, class: 'control-label' - .col-sm-10.datetime-controls - = f.datetime_select :ends_at - .form-actions - = f.submit "Add broadcast message", class: "btn btn-create" + Broadcast messages are displayed for every user and can be used to notify + users about scheduled maintenance, recent upgrades and more. --if @broadcast_messages.any? - %ul.bordered-list.broadcast-messages - - @broadcast_messages.each do |broadcast_message| - %li - .pull-right - - if broadcast_message.starts_at - %strong - #{broadcast_message.starts_at.to_s(:short)} - \... - - if broadcast_message.ends_at - %strong - #{broadcast_message.ends_at.to_s(:short)} -   - = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-xs' do - %i.fa.fa-times.cred += render 'form' - .message= broadcast_message.message +%br.clearfix +-if @broadcast_messages.any? + %table.table + %thead + %tr + %th Status + %th Preview + %th Starts + %th Ends + %th   + %tbody + - @broadcast_messages.each do |message| + %tr + %td + = broadcast_message_status(message) + %td + = broadcast_message(message) + %td + = message.starts_at + %td + = message.ends_at + %td + = link_to icon('pencil-square-o'), edit_admin_broadcast_message_path(message), title: 'Edit', class: 'btn btn-xs' + = link_to icon('times'), admin_broadcast_message_path(message), method: :delete, remote: true, title: 'Remove', class: 'js-remove-tr btn btn-xs btn-danger' = paginate @broadcast_messages diff --git a/app/views/layouts/_broadcast.html.haml b/app/views/layouts/_broadcast.html.haml index e7d477c225eb35e812b6a592510b862f7e949eee..3a7e0929c167f5581ba41785cdc65aac86841640 100644 --- a/app/views/layouts/_broadcast.html.haml +++ b/app/views/layouts/_broadcast.html.haml @@ -1,4 +1 @@ -- if broadcast_message.present? - .broadcast-message{ style: broadcast_styling(broadcast_message) } - %i.fa.fa-bullhorn - = broadcast_message.message += broadcast_message diff --git a/config/routes.rb b/config/routes.rb index 3d5c70987c8939f676666c8dc3dd0748689374d0..05d6ff1e884c84e3a14276dd24ee106b7f81d14e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -219,7 +219,7 @@ Rails.application.routes.draw do get :test end - resources :broadcast_messages, only: [:index, :create, :destroy] + resources :broadcast_messages, only: [:index, :edit, :create, :update, :destroy] resource :logs, only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show] diff --git a/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb b/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb new file mode 100644 index 0000000000000000000000000000000000000000..78fdfeaf5cf9a2ef0cbc90b3e043970cf3c4c077 --- /dev/null +++ b/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb @@ -0,0 +1,5 @@ +class RemoveAlertTypeFromBroadcastMessages < ActiveRecord::Migration + def change + remove_column :broadcast_messages, :alert_type, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index ecbe575bf83e1619b631bf509afb625a5871fba4..42c3e79f9d733d7e61d796fdc7fb07ef7ca2b8b7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -82,7 +82,6 @@ ActiveRecord::Schema.define(version: 20160113111034) do t.text "message", null: false t.datetime "starts_at" t.datetime "ends_at" - t.integer "alert_type" t.datetime "created_at" t.datetime "updated_at" t.string "color" diff --git a/features/admin/broadcast_messages.feature b/features/admin/broadcast_messages.feature index b2c3112320ad2bc81c434ccd717250f83e7f2bd8..fd3bac77f867e4c619ad408c81a9174ff9f4722b 100644 --- a/features/admin/broadcast_messages.feature +++ b/features/admin/broadcast_messages.feature @@ -2,16 +2,11 @@ Feature: Admin Broadcast Messages Background: Given I sign in as an admin - And application already has admin messages + And application already has a broadcast message And I visit admin messages page Scenario: See broadcast messages list - Then I should be all broadcast messages - - Scenario: Create a broadcast message - When submit form with new broadcast message - Then I should be redirected to admin messages page - And I should see newly created broadcast message + Then I should see all broadcast messages Scenario: Create a customized broadcast message When submit form with new customized broadcast message @@ -19,3 +14,14 @@ Feature: Admin Broadcast Messages And I should see newly created broadcast message Then I visit dashboard page And I should see a customized broadcast message + + Scenario: Edit an existing broadcast message + When I edit an existing broadcast message + And I change the broadcast message text + Then I should be redirected to admin messages page + And I should see the updated broadcast message + + Scenario: Remove an existing broadcast message + When I remove an existing broadcast message + Then I should be redirected to admin messages page + And I should not see the removed broadcast message diff --git a/features/steps/admin/broadcast_messages.rb b/features/steps/admin/broadcast_messages.rb index f6daf8529775238a8d76c80fa797be26dbf689d4..6cacdf4764c39bbe201822a15fc647392695bae8 100644 --- a/features/steps/admin/broadcast_messages.rb +++ b/features/steps/admin/broadcast_messages.rb @@ -1,22 +1,15 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps include SharedAuthentication include SharedPaths - include SharedAdmin - step 'application already has admin messages' do - FactoryGirl.create(:broadcast_message, message: "Migration to new server") + step 'application already has a broadcast message' do + FactoryGirl.create(:broadcast_message, :expired, message: "Migration to new server") end - step 'I should be all broadcast messages' do + step 'I should see all broadcast messages' do expect(page).to have_content "Migration to new server" end - step 'submit form with new broadcast message' do - fill_in 'broadcast_message_message', with: 'Application update from 4:00 CST to 5:00 CST' - select '2018', from: "broadcast_message_ends_at_1i" - click_button "Add broadcast message" - end - step 'I should be redirected to admin messages page' do expect(current_path).to eq admin_broadcast_messages_path end @@ -27,10 +20,9 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps step 'submit form with new customized broadcast message' do fill_in 'broadcast_message_message', with: 'Application update from 4:00 CST to 5:00 CST' - click_link "Customize colors" fill_in 'broadcast_message_color', with: '#f2dede' fill_in 'broadcast_message_font', with: '#b94a48' - select '2018', from: "broadcast_message_ends_at_1i" + select Date.today.next_year.year, from: "broadcast_message_ends_at_1i" click_button "Add broadcast message" end @@ -38,4 +30,25 @@ class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps expect(page).to have_content 'Application update from 4:00 CST to 5:00 CST' expect(page).to have_selector %(div[style="background-color: #f2dede; color: #b94a48"]) end + + step 'I edit an existing broadcast message' do + click_link 'Edit' + end + + step 'I change the broadcast message text' do + fill_in 'broadcast_message_message', with: 'Application update RIGHT NOW' + click_button 'Update broadcast message' + end + + step 'I should see the updated broadcast message' do + expect(page).to have_content "Application update RIGHT NOW" + end + + step 'I remove an existing broadcast message' do + click_link 'Remove' + end + + step 'I should not see the removed broadcast message' do + expect(page).not_to have_content 'Migration to new server' + end end diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb index ea0039d39e67e1d4cf53c213a417a88869a03f27..978a7d4cecb978fe1a53b44d16cf51aa6c0f8fb0 100644 --- a/spec/factories/broadcast_messages.rb +++ b/spec/factories/broadcast_messages.rb @@ -6,7 +6,6 @@ # message :text not null # starts_at :datetime # ends_at :datetime -# alert_type :integer # created_at :datetime # updated_at :datetime # color :string(255) @@ -18,10 +17,17 @@ FactoryGirl.define do factory :broadcast_message do message "MyText" - starts_at "2013-11-12 13:43:25" - ends_at "2013-11-12 13:43:25" - alert_type 1 - color "#555555" - font "#BBBBBB" + starts_at Date.today + ends_at Date.tomorrow + + trait :expired do + starts_at 5.days.ago + ends_at 3.days.ago + end + + trait :future do + starts_at 5.days.from_now + ends_at 6.days.from_now + end end end diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb index c7c6f45d14439886bac8b57f17caf5bfad9b1a99..157cc4665a2b61d7f033b5dec2a47f3a55f67a17 100644 --- a/spec/helpers/broadcast_messages_helper_spec.rb +++ b/spec/helpers/broadcast_messages_helper_spec.rb @@ -1,22 +1,60 @@ require 'spec_helper' describe BroadcastMessagesHelper do - describe 'broadcast_styling' do - let(:broadcast_message) { double(color: '', font: '') } + describe 'broadcast_message' do + it 'returns nil when no current message' do + expect(helper.broadcast_message(nil)).to be_nil + end + + it 'includes the current message' do + current = double(message: 'Current Message') + + allow(helper).to receive(:broadcast_message_style).and_return(nil) + + expect(helper.broadcast_message(current)).to include 'Current Message' + end + + it 'includes custom style' do + current = double(message: 'Current Message') + + allow(helper).to receive(:broadcast_message_style).and_return('foo') + + expect(helper.broadcast_message(current)).to include 'style="foo"' + end + end + + describe 'broadcast_message_style' do + it 'defaults to no style' do + broadcast_message = spy + + expect(helper.broadcast_message_style(broadcast_message)).to eq '' + end + + it 'allows custom style' do + broadcast_message = double(color: '#f2dede', font: '#b94a48') + + expect(helper.broadcast_message_style(broadcast_message)). + to match('background-color: #f2dede; color: #b94a48') + end + end + + describe 'broadcast_message_status' do + it 'returns Active' do + message = build(:broadcast_message) + + expect(helper.broadcast_message_status(message)).to eq 'Active' + end + + it 'returns Expired' do + message = build(:broadcast_message, :expired) - context "default style" do - it "should have no style" do - expect(broadcast_styling(broadcast_message)).to eq '' - end + expect(helper.broadcast_message_status(message)).to eq 'Expired' end - context "customized style" do - let(:broadcast_message) { double(color: "#f2dede", font: '#b94a48') } + it 'returns Pending' do + message = build(:broadcast_message, :future) - it "should have a customized style" do - expect(broadcast_styling(broadcast_message)). - to match('background-color: #f2dede; color: #b94a48') - end + expect(helper.broadcast_message_status(message)).to eq 'Pending' end end end diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index e4cac105110ed86113df1bcb0e6dbfc355744f96..f6f84db57e615d69b912976fd38aac6d3038ea6c 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -6,7 +6,6 @@ # message :text not null # starts_at :datetime # ends_at :datetime -# alert_type :integer # created_at :datetime # updated_at :datetime # color :string(255) @@ -16,6 +15,8 @@ require 'spec_helper' describe BroadcastMessage, models: true do + include ActiveSupport::Testing::TimeHelpers + subject { create(:broadcast_message) } it { is_expected.to be_valid } @@ -35,20 +36,79 @@ describe BroadcastMessage, models: true do it { is_expected.not_to allow_value('000').for(:font) } end - describe :current do + describe '.current' do it "should return last message if time match" do - broadcast_message = create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow) - expect(BroadcastMessage.current).to eq(broadcast_message) + message = create(:broadcast_message) + + expect(BroadcastMessage.current).to eq message end it "should return nil if time not come" do - create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days) + create(:broadcast_message, :future) + expect(BroadcastMessage.current).to be_nil end it "should return nil if time has passed" do - create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday) + create(:broadcast_message, :expired) + expect(BroadcastMessage.current).to be_nil end end + + describe '#active?' do + it 'is truthy when started and not ended' do + message = build(:broadcast_message) + + expect(message).to be_active + end + + it 'is falsey when ended' do + message = build(:broadcast_message, :expired) + + expect(message).not_to be_active + end + + it 'is falsey when not started' do + message = build(:broadcast_message, :future) + + expect(message).not_to be_active + end + end + + describe '#started?' do + it 'is truthy when starts_at has passed' do + message = build(:broadcast_message) + + travel_to(3.days.from_now) do + expect(message).to be_started + end + end + + it 'is falsey when starts_at is in the future' do + message = build(:broadcast_message) + + travel_to(3.days.ago) do + expect(message).not_to be_started + end + end + end + + describe '#ended?' do + it 'is truthy when ends_at has passed' do + message = build(:broadcast_message) + + travel_to(3.days.from_now) do + expect(message).to be_ended + end + end + + it 'is falsey when ends_at is in the future' do + message = build(:broadcast_message) + + travel_to(3.days.ago) do + expect(message).not_to be_ended + end + end + end end