Commit 99334d4b57b6f07e002eaa5145f529d6b63fdce2

Authored by Dmitriy Zaporozhets
2 parents 0a08c775 3397361f

Merge branch 'feature/broadcast_messages' of /home/git/repositories/gitlab/gitlabhq

app/assets/stylesheets/common.scss
@@ -351,3 +351,10 @@ table { @@ -351,3 +351,10 @@ table {
351 @extend .btn-new; 351 @extend .btn-new;
352 padding: 5px 15px; 352 padding: 5px 15px;
353 } 353 }
  354 +
  355 +.broadcast-message {
  356 + padding: 10px;
  357 + text-align: center;
  358 + background: #555;
  359 + color: #BBB;
  360 +}
app/assets/stylesheets/gitlab_bootstrap/forms.scss
@@ -49,3 +49,9 @@ fieldset legend { @@ -49,3 +49,9 @@ fieldset legend {
49 font-size: 16px; 49 font-size: 16px;
50 margin-bottom: 10px; 50 margin-bottom: 10px;
51 } 51 }
  52 +
  53 +.datetime-controls {
  54 + select {
  55 + width: 100px;
  56 + }
  57 +}
app/assets/stylesheets/sections/admin.scss
@@ -21,3 +21,9 @@ @@ -21,3 +21,9 @@
21 .controls { margin-left: 130px; } 21 .controls { margin-left: 130px; }
22 .form-actions { padding-left: 130px; background: #fff } 22 .form-actions { padding-left: 130px; background: #fff }
23 } 23 }
  24 +
  25 +.broadcast-messages {
  26 + .message {
  27 + line-height: 2;
  28 + }
  29 +}
app/controllers/admin/broadcast_messages_controller.rb 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +class Admin::BroadcastMessagesController < Admin::ApplicationController
  2 + before_filter :broadcast_messages
  3 +
  4 + def index
  5 + @broadcast_message = BroadcastMessage.new
  6 + end
  7 +
  8 + def create
  9 + @broadcast_message = BroadcastMessage.new(params[:broadcast_message])
  10 +
  11 + if @broadcast_message.save
  12 + redirect_to admin_broadcast_messages_path, notice: 'Broadcast Message was successfully created.'
  13 + else
  14 + render :index
  15 + end
  16 + end
  17 +
  18 + def destroy
  19 + BroadcastMessage.find(params[:id]).destroy
  20 +
  21 + respond_to do |format|
  22 + format.html { redirect_to :back }
  23 + format.js { render nothing: true }
  24 + end
  25 + end
  26 +
  27 + protected
  28 +
  29 + def broadcast_messages
  30 + @broadcast_messages ||= BroadcastMessage.order("starts_at DESC").page(params[:page])
  31 + end
  32 +end
app/helpers/application_helper.rb
@@ -208,4 +208,8 @@ module ApplicationHelper @@ -208,4 +208,8 @@ module ApplicationHelper
208 line += "..." if lines.size > 1 208 line += "..." if lines.size > 1
209 line 209 line
210 end 210 end
  211 +
  212 + def broadcast_message
  213 + BroadcastMessage.current
  214 + end
211 end 215 end
app/models/broadcast_message.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class BroadcastMessage < ActiveRecord::Base
  2 + attr_accessible :alert_type, :ends_at, :message, :starts_at
  3 +
  4 + validates :message, presence: true
  5 + validates :starts_at, presence: true
  6 + validates :ends_at, presence: true
  7 +
  8 + def self.current
  9 + where("ends_at > :now AND starts_at < :now", now: Time.zone.now).last
  10 + end
  11 +end
app/views/admin/broadcast_messages/index.html.haml 0 → 100644
@@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
  1 +%h3.page-title
  2 + Broadcast Messages
  3 +%p.light
  4 + Broadcast messages displayed for every user and can be used to notify application about scheduled maintenance.
  5 +%hr
  6 +
  7 += form_for [:admin, @broadcast_message] do |f|
  8 + -if @broadcast_message.errors.any?
  9 + .alert.alert-error
  10 + - @broadcast_message.errors.full_messages.each do |msg|
  11 + %p= msg
  12 + .control-group
  13 + = f.label :message
  14 + .controls
  15 + = f.text_area :message, class: "input-xxlarge", rows: 2, required: true
  16 + .control-group
  17 + = f.label :starts_at
  18 + .controls.datetime-controls
  19 + = f.datetime_select :starts_at
  20 + .control-group
  21 + = f.label :ends_at
  22 + .controls.datetime-controls
  23 + = f.datetime_select :ends_at
  24 + .form-actions
  25 + = f.submit "Add broadcast message", class: "btn btn-create"
  26 +
  27 +-if @broadcast_messages.any?
  28 + %ul.bordered-list.broadcast-messages
  29 + - @broadcast_messages.each do |broadcast_message|
  30 + %li
  31 + .pull-right
  32 + - if broadcast_message.starts_at
  33 + %strong
  34 + #{broadcast_message.starts_at.to_s(:short)}
  35 + \...
  36 + - if broadcast_message.ends_at
  37 + %strong
  38 + #{broadcast_message.ends_at.to_s(:short)}
  39 + &nbsp;
  40 + = link_to [:admin, broadcast_message], method: :delete, remote: true, class: 'remove-row btn btn-tiny' do
  41 + %i.icon-remove.cred
  42 +
  43 + .message= broadcast_message.message
  44 +
  45 +
  46 + = paginate @broadcast_messages
app/views/layouts/_broadcast.html.haml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +- if broadcast_message.present?
  2 + .broadcast-message
  3 + %i.icon-bullhorn
  4 + = broadcast_message.message
app/views/layouts/application.html.haml
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: "Dashboard" 3 = render "layouts/head", title: "Dashboard"
4 %body{class: "#{app_theme} application", :'data-page' => body_data_page } 4 %body{class: "#{app_theme} application", :'data-page' => body_data_page }
  5 + = render "layouts/broadcast"
5 = render "layouts/head_panel", title: "Dashboard" 6 = render "layouts/head_panel", title: "Dashboard"
6 = render "layouts/flash" 7 = render "layouts/flash"
7 %nav.main-nav 8 %nav.main-nav
app/views/layouts/nav/_admin.html.haml
@@ -10,6 +10,8 @@ @@ -10,6 +10,8 @@
10 = link_to "Users", admin_users_path 10 = link_to "Users", admin_users_path
11 = nav_link(controller: :logs) do 11 = nav_link(controller: :logs) do
12 = link_to "Logs", admin_logs_path 12 = link_to "Logs", admin_logs_path
  13 + = nav_link(controller: :broadcast_messages) do
  14 + = link_to "Messages", admin_broadcast_messages_path
13 = nav_link(controller: :hooks) do 15 = nav_link(controller: :hooks) do
14 = link_to "Hooks", admin_hooks_path 16 = link_to "Hooks", admin_hooks_path
15 = nav_link(controller: :background_jobs) do 17 = nav_link(controller: :background_jobs) do
app/views/layouts/projects.html.haml
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 %html{ lang: "en"} 2 %html{ lang: "en"}
3 = render "layouts/head", title: @project.name_with_namespace 3 = render "layouts/head", title: @project.name_with_namespace
4 %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id } 4 %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
  5 + = render "layouts/broadcast"
5 = render "layouts/head_panel", title: project_title(@project) 6 = render "layouts/head_panel", title: project_title(@project)
6 = render "layouts/init_auto_complete" 7 = render "layouts/init_auto_complete"
7 = render "layouts/flash" 8 = render "layouts/flash"
config/routes.rb
@@ -86,6 +86,7 @@ Gitlab::Application.routes.draw do @@ -86,6 +86,7 @@ Gitlab::Application.routes.draw do
86 get :test 86 get :test
87 end 87 end
88 88
  89 + resources :broadcast_messages, only: [:index, :create, :destroy]
89 resource :logs, only: [:show] 90 resource :logs, only: [:show]
90 resource :background_jobs, controller: 'background_jobs', only: [:show] 91 resource :background_jobs, controller: 'background_jobs', only: [:show]
91 resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] 92 resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show]
db/migrate/20131112114325_create_broadcast_messages.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class CreateBroadcastMessages < ActiveRecord::Migration
  2 + def change
  3 + create_table :broadcast_messages do |t|
  4 + t.text :message, null: false
  5 + t.datetime :starts_at
  6 + t.datetime :ends_at
  7 + t.integer :alert_type
  8 +
  9 + t.timestamps
  10 + end
  11 + end
  12 +end
@@ -11,7 +11,16 @@ @@ -11,7 +11,16 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20131106151520) do 14 +ActiveRecord::Schema.define(:version => 20131112114325) do
  15 +
  16 + create_table "broadcast_messages", :force => true do |t|
  17 + t.text "message", :null => false
  18 + t.datetime "starts_at"
  19 + t.datetime "ends_at"
  20 + t.integer "alert_type"
  21 + t.datetime "created_at", :null => false
  22 + t.datetime "updated_at", :null => false
  23 + end
15 24
16 create_table "deploy_keys_projects", :force => true do |t| 25 create_table "deploy_keys_projects", :force => true do |t|
17 t.integer "deploy_key_id", :null => false 26 t.integer "deploy_key_id", :null => false
features/admin/active_tab.feature
@@ -27,6 +27,11 @@ Feature: Admin active tab @@ -27,6 +27,11 @@ Feature: Admin active tab
27 Then the active main tab should be Logs 27 Then the active main tab should be Logs
28 And no other main tabs should be active 28 And no other main tabs should be active
29 29
  30 + Scenario: On Admin Messages
  31 + Given I visit admin messages page
  32 + Then the active main tab should be Messages
  33 + And no other main tabs should be active
  34 +
30 Scenario: On Admin Hooks 35 Scenario: On Admin Hooks
31 Given I visit admin hooks page 36 Given I visit admin hooks page
32 Then the active main tab should be Hooks 37 Then the active main tab should be Hooks
features/admin/broadcast_messages.feature 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +Feature: Admin Broadcast Messages
  2 + Background:
  3 + Given I sign in as an admin
  4 + And application already has admin messages
  5 + And I visit admin messages page
  6 +
  7 + Scenario: See broadcast messages list
  8 + Then I should be all broadcast messages
  9 +
  10 + Scenario: Create a broadcast message
  11 + When submit form with new broadcast message
  12 + Then I should be redirected to admin messages page
  13 + And I should see newly created broadcast message
features/steps/admin/admin_active_tab.rb
@@ -30,4 +30,8 @@ class AdminActiveTab &lt; Spinach::FeatureSteps @@ -30,4 +30,8 @@ class AdminActiveTab &lt; Spinach::FeatureSteps
30 Then 'the active main tab should be Resque' do 30 Then 'the active main tab should be Resque' do
31 ensure_active_main_tab('Background Jobs') 31 ensure_active_main_tab('Background Jobs')
32 end 32 end
  33 +
  34 + Then 'the active main tab should be Messages' do
  35 + ensure_active_main_tab('Messages')
  36 + end
33 end 37 end
features/steps/admin/admin_broadcast_messages.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedPaths
  4 + include SharedAdmin
  5 +
  6 + step 'application already has admin messages' do
  7 + FactoryGirl.create(:broadcast_message, message: "Migration to new server")
  8 + end
  9 +
  10 + step 'I should be all broadcast messages' do
  11 + page.should have_content "Migration to new server"
  12 + end
  13 +
  14 + step 'submit form with new broadcast message' do
  15 + fill_in 'broadcast_message_message', with: 'Application update from 4:00 CST to 5:00 CST'
  16 + select '2018', from: "broadcast_message_ends_at_1i"
  17 + click_button "Add broadcast message"
  18 + end
  19 +
  20 + step 'I should be redirected to admin messages page' do
  21 + current_path.should == admin_broadcast_messages_path
  22 + end
  23 +
  24 + step 'I should see newly created broadcast message' do
  25 + page.should have_content 'Application update from 4:00 CST to 5:00 CST'
  26 + end
  27 +end
features/steps/shared/paths.rb
@@ -105,6 +105,10 @@ module SharedPaths @@ -105,6 +105,10 @@ module SharedPaths
105 visit admin_logs_path 105 visit admin_logs_path
106 end 106 end
107 107
  108 + step 'I visit admin messages page' do
  109 + visit admin_broadcast_messages_path
  110 + end
  111 +
108 step 'I visit admin hooks page' do 112 step 'I visit admin hooks page' do
109 visit admin_hooks_path 113 visit admin_hooks_path
110 end 114 end
spec/factories/broadcast_messages.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +# Read about factories at https://github.com/thoughtbot/factory_girl
  2 +
  3 +FactoryGirl.define do
  4 + factory :broadcast_message do
  5 + message "MyText"
  6 + starts_at "2013-11-12 13:43:25"
  7 + ends_at "2013-11-12 13:43:25"
  8 + alert_type 1
  9 + end
  10 +end
spec/models/broadcast_message_spec.rb 0 → 100644
@@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
  1 +require 'spec_helper'
  2 +
  3 +describe BroadcastMessage do
  4 + subject { create(:broadcast_message) }
  5 +
  6 + it { should be_valid }
  7 +
  8 + describe :current do
  9 + it "should return last message if time match" do
  10 + broadcast_message = create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow)
  11 + BroadcastMessage.current.should == broadcast_message
  12 + end
  13 +
  14 + it "should return nil if time not come" do
  15 + broadcast_message = create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days)
  16 + BroadcastMessage.current.should be_nil
  17 + end
  18 +
  19 + it "should return nil if time has passed" do
  20 + broadcast_message = create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday)
  21 + BroadcastMessage.current.should be_nil
  22 + end
  23 + end
  24 +end