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 351 @extend .btn-new;
352 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 49 font-size: 16px;
50 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 21 .controls { margin-left: 130px; }
22 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 @@
  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 208 line += "..." if lines.size > 1
209 209 line
210 210 end
  211 +
  212 + def broadcast_message
  213 + BroadcastMessage.current
  214 + end
211 215 end
... ...
app/models/broadcast_message.rb 0 → 100644
... ... @@ -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 @@
  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 @@
  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 2 %html{ lang: "en"}
3 3 = render "layouts/head", title: "Dashboard"
4 4 %body{class: "#{app_theme} application", :'data-page' => body_data_page }
  5 + = render "layouts/broadcast"
5 6 = render "layouts/head_panel", title: "Dashboard"
6 7 = render "layouts/flash"
7 8 %nav.main-nav
... ...
app/views/layouts/nav/_admin.html.haml
... ... @@ -10,6 +10,8 @@
10 10 = link_to "Users", admin_users_path
11 11 = nav_link(controller: :logs) do
12 12 = link_to "Logs", admin_logs_path
  13 + = nav_link(controller: :broadcast_messages) do
  14 + = link_to "Messages", admin_broadcast_messages_path
13 15 = nav_link(controller: :hooks) do
14 16 = link_to "Hooks", admin_hooks_path
15 17 = nav_link(controller: :background_jobs) do
... ...
app/views/layouts/projects.html.haml
... ... @@ -2,6 +2,7 @@
2 2 %html{ lang: "en"}
3 3 = render "layouts/head", title: @project.name_with_namespace
4 4 %body{class: "#{app_theme} project", :'data-page' => body_data_page, :'data-project-id' => @project.id }
  5 + = render "layouts/broadcast"
5 6 = render "layouts/head_panel", title: project_title(@project)
6 7 = render "layouts/init_auto_complete"
7 8 = render "layouts/flash"
... ...
config/routes.rb
... ... @@ -86,6 +86,7 @@ Gitlab::Application.routes.draw do
86 86 get :test
87 87 end
88 88  
  89 + resources :broadcast_messages, only: [:index, :create, :destroy]
89 90 resource :logs, only: [:show]
90 91 resource :background_jobs, controller: 'background_jobs', only: [:show]
91 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 @@
  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
... ...
db/schema.rb
... ... @@ -11,7 +11,16 @@
11 11 #
12 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 25 create_table "deploy_keys_projects", :force => true do |t|
17 26 t.integer "deploy_key_id", :null => false
... ...
features/admin/active_tab.feature
... ... @@ -27,6 +27,11 @@ Feature: Admin active tab
27 27 Then the active main tab should be Logs
28 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 35 Scenario: On Admin Hooks
31 36 Given I visit admin hooks page
32 37 Then the active main tab should be Hooks
... ...
features/admin/broadcast_messages.feature 0 → 100644
... ... @@ -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 30 Then 'the active main tab should be Resque' do
31 31 ensure_active_main_tab('Background Jobs')
32 32 end
  33 +
  34 + Then 'the active main tab should be Messages' do
  35 + ensure_active_main_tab('Messages')
  36 + end
33 37 end
... ...
features/steps/admin/admin_broadcast_messages.rb 0 → 100644
... ... @@ -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 105 visit admin_logs_path
106 106 end
107 107  
  108 + step 'I visit admin messages page' do
  109 + visit admin_broadcast_messages_path
  110 + end
  111 +
108 112 step 'I visit admin hooks page' do
109 113 visit admin_hooks_path
110 114 end
... ...
spec/factories/broadcast_messages.rb 0 → 100644
... ... @@ -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 @@
  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
... ...