diff options
-rw-r--r-- | lib/mauve/web_interface.rb | 102 | ||||
-rw-r--r-- | views/_alerts_table.haml | 31 | ||||
-rw-r--r-- | views/_head.haml | 1 | ||||
-rw-r--r-- | views/_navbar.haml | 15 | ||||
-rw-r--r-- | views/alert.haml | 156 | ||||
-rw-r--r-- | views/alerts.haml | 41 | ||||
-rw-r--r-- | views/login.haml | 28 | ||||
-rw-r--r-- | views/not_implemented.haml | 8 |
8 files changed, 218 insertions, 164 deletions
diff --git a/lib/mauve/web_interface.rb b/lib/mauve/web_interface.rb index 721fc3f..d999554 100644 --- a/lib/mauve/web_interface.rb +++ b/lib/mauve/web_interface.rb @@ -44,7 +44,23 @@ module Mauve set :dump_errors, true # ...will dump errors to the log set :raise_errors, false # ...will not let exceptions out to main program set :show_exceptions, false # ...will not show exceptions - + + # + # Default template. + # + template :layout do + <<EOF +!!! 5 +%html + = partial('head') + %body + =partial("navbar") + =yield +EOF + end + + + ###########################################/alert############################# before do @@ -65,6 +81,11 @@ module Mauve env['REMOTE_USER'] = @person.username # + # Don't cache ajax requests + # + cache_control :no_cache if request.xhr? + + # # Set up some defaults. # @group_by = "subject" @@ -147,33 +168,12 @@ module Mauve end get '/alerts/:alert_type/:group_by' do - find_active_alerts - if %w(raised cleared acknowledged).include?(params[:alert_type]) - @alert_type = params[:alert_type] - else - @alert_type = "raised" - end - - if %w(subject source summary id alert_id level).include?(params[:group_by]) - @group_by = params[:group_by] - else - @group_by = "subject" - end - - @title += " Alerts " + return haml(:not_implemented) unless %w(raised acknowledged).include?(params[:alert_type]) + alerts_table(params) - case @alert_type - when "raised" - @grouped_alerts = group_by(@alerts_raised, @group_by) - haml(:alerts) - when "acknowledged" - @grouped_alerts = group_by(@alerts_ackd, @group_by) - haml(:alerts) - else - haml(:not_implemented) - end + haml(:alerts) end post '/alerts/acknowledge' do @@ -216,7 +216,7 @@ module Mauve redirect "/alerts/raised" end - # + ###################################################### # AJAX methods for returning snippets of stuff. # @@ -246,10 +246,30 @@ module Mauve get '/ajax/time_to_s_human/:seconds' do content_type :text + secs = params[:seconds].to_i Time.at(secs).to_s_human end + # + # This returns an array of 5 numbers. + # + get '/ajax/alert_counts' do + content_type :json + + counts = Hash.new{|h,k| h[k] = 0} + + Alert.all_raised.each{|a| counts[a.level] += 1} + + (AlertGroup::LEVELS.reverse.collect{|l| counts[l]}+ + [Alert.all_acknowledged.length, Alert.all_cleared.length]).to_json + end + + get '/ajax/alerts_table/:alert_type/:group_by' do + alerts_table(params) + haml(:_alerts_table) + end + get '/ajax/alerts_table_alert/:alert_id' do content_type "text/html" alert = Alert.get(params[:alert_id].to_i) @@ -361,7 +381,6 @@ module Mauve results = Hash.new{|h,k| h[k] = Array.new} things.sort.each do |thing| - self.class._logger.debug [AlertGroup::LEVELS.index(thing.level), (thing.raised_at || thing.cleared_at) ].inspect results[thing.__send__(meth)] << thing end @@ -369,6 +388,35 @@ module Mauve [a[1].first, a[0]] <=> [b[1].first, b[0]] end end + + def alerts_table(params) + find_active_alerts + + if %w(raised cleared acknowledged).include?(params[:alert_type]) + @alert_type = params[:alert_type] + else + @alert_type = "raised" + end + + if %w(subject source summary id alert_id level).include?(params[:group_by]) + @group_by = params[:group_by] + else + @group_by = "subject" + end + + @title += " Alerts " + + + case @alert_type + when "raised" + @grouped_alerts = group_by(@alerts_raised, @group_by) + when "acknowledged" + @grouped_alerts = group_by(@alerts_ackd, @group_by) + haml(:alerts) + else + haml(:not_implemented) + end + end def find_active_alerts @alerts_raised = Alert.all_raised diff --git a/views/_alerts_table.haml b/views/_alerts_table.haml index f413c30..99a4e13 100644 --- a/views/_alerts_table.haml +++ b/views/_alerts_table.haml @@ -1,19 +1,14 @@ -%form#alerts{:method => :post, :action => '/alerts/acknowledge'} - %table - %tr - %th#selector - %input#toggle_all{ :type => "checkbox" } - :javascript - // This just toggles all the checkboxes. - $('#toggle_all').change( function() { - $('input.alert').each( function(index) { - this.checked = !this.checked; - }); +%table#alerts_table + %tr + %th#selector + %input#toggle_all{ :type => "checkbox" } + :javascript + // This just toggles all the checkboxes. + $('#toggle_all').change( function() { + $('input.alert').each( function(index) { + this.checked = !this.checked; }); - %th#summary Summary - %th#time At - = partial("alerts_table_group", :collection => @grouped_alerts) - %tr - %td - %td{:colspan => 2} - = partial("acknowledge_input") + }); + %th#summary Summary + %th#time At + = partial("alerts_table_group", :collection => @grouped_alerts) diff --git a/views/_head.haml b/views/_head.haml index 981aaf1..642d408 100644 --- a/views/_head.haml +++ b/views/_head.haml @@ -5,4 +5,5 @@ %link{:rel => "stylesheet", :href => "/stylesheets/mauve.css", :media => "all", :type => "text/css"}/ %link{:rel => "stylesheet", :href => "/stylesheets/mauve-handheld.css", :media => "handheld, only screen and (max-width: 1000px), only screen and (max-device-width: 1000px)", :type => "text/css" }/ %script{:src => '/javascript/jquery/jquery.min.js', :type => 'text/javascript'} + %script{:src => '/javascript/jquery.periodicalupdater.js', :type => 'text/javascript'} %script{:src => '/javascript/mauve_utils.js', :type => 'text/javascript'} diff --git a/views/_navbar.haml b/views/_navbar.haml index 4f81450..5df4991 100644 --- a/views/_navbar.haml +++ b/views/_navbar.haml @@ -4,11 +4,20 @@ %a{:href => "/"} Mauve - if @person %li{:class => [ @alert_type == "raised" && "nav_selected"]} - %a{:href => '/alerts/raised/'+@group_by} Raised (#{@alerts_raised.length}) + %a{:href => '/alerts/raised/'+@group_by} + Raised ( + %span#count_raised><= @alerts_raised.length + ) %li{:class => [ @alert_type == "acknowledged" && "nav_selected"]} - %a{:href => '/alerts/acknowledged/'+@group_by} Ack'd (#{@alerts_ackd.length}) + %a{:href => '/alerts/acknowledged/'+@group_by} + Ack'd ( + %span#count_ackd><= @alerts_ackd.length + ) %li{:class => [ @alert_type == "cleared" && "nav_selected"]} - %a{:href => '/alerts/cleared/'+@group_by} Cleared (#{@alerts_cleared.length}) + %a{:href => '/alerts/cleared/'+@group_by} + Cleared ( + %span#count_cleared><= @alerts_cleared.length + ) %li %a{:href => '/logout'} Log out %br diff --git a/views/alert.haml b/views/alert.haml index 0486770..b752f35 100644 --- a/views/alert.haml +++ b/views/alert.haml @@ -1,82 +1,76 @@ -!!!5 -%html - = partial('head') - %body - =partial("navbar") - .container - %h1 Alert detail - %table - %tr - %th.summary{:title => "Text for humans describing the nature of the alert, first 100 characters are only ones guaranteed to make it to pagers, twitter, SMS etc."} Summary - %td= @alert.summary - %tr - %th.summary{:title => "The server/entity that this alert concerns"} Subject - %td= @alert.subject - %tr - %th{:title => "The server/entitiy that originated the alert"} Source - %td= @alert.source - %tr - %th{:title => "HTML fragment describing the alert in more detail, no limit on length."} Detail - %td - :textile - #{@alert.detail} - %tr - %th{:title => "ID set by the source of the alert."} Alert ID - %td= @alert.alert_id - %tr - %th{:title => "The groups in the Mauve server configuration that match this alert"} Alert groups - %td= Mauve::AlertGroup.matches(@alert).map{|g| g.name}.join("; ") - %tr - %th{:title => "The level of the first group in the Mauve server configuration that matched this alert"} Alert level - %td= @alert.level.to_s.upcase - -if @alert.raised? - %tr - %th{:title => "The time at which the alert was raised"} Raised at - %td= @alert.raised_at.to_s_human - -if @alert.acknowledged? - %tr - %th{:title => "The time at which the alert was acknowledged"} Acknowledged at - %td= @alert.acknowledged_at.to_s_human + " by " + @alert.acknowledged_by + " until " + @alert.will_unacknowledge_at.to_s_human - -if @alert.will_raise_at - %tr - %th{:title => "The time at which the alert will be automatically raised"} Will raise at - %td= @alert.will_raise_at.to_s_human - -if @alert.cleared_at - %tr - %th{:title => "The time at which the alert was last cleared"} Last cleared at - %td= @alert.cleared_at.to_s_human - -if @alert.will_clear_at - %tr - %th{:title => "The time at which the alert will be automatically cleared"} Will clear - %td= @alert.will_raise_at.to_s_human - %tr - %th Notifications sent out - %td - %ul - - @alert.changes.each do |change| - - if change.was_relevant? - %li - %strong= change.level - = change.update_type - notification to - = change.person - at - = change.at.to_s_human - - %h2 Actions - - if !@alert.acknowledged? - %form{:method => :post, :action => "/alert/#{@alert.id}/acknowledge"} - =partial("acknowledge_input") - - else - %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/unacknowledge"} - %input{:type => :submit, :value => "Unacknowledge this alert"} - %a#hide{:onclick => "$('form.hidden').toggle(); return false", :href=>"#"} Show other actions - - if @alert.cleared? - %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/raise"} - %input{:type => :submit, :value => "Raise this alert"} - - if @alert.raised? - %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/clear"} - %input{:type => :submit, :value => "Clear this alert"} - %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/destroy"} - %input{:type => :submit, :value => "Destroy this alert"} +%h1 Alert detail +%table + %tr + %th.summary{:title => "Text for humans describing the nature of the alert, first 100 characters are only ones guaranteed to make it to pagers, twitter, SMS etc."} Summary + %td= @alert.summary + %tr + %th.summary{:title => "The server/entity that this alert concerns"} Subject + %td= @alert.subject + %tr + %th{:title => "The server/entitiy that originated the alert"} Source + %td= @alert.source + %tr + %th{:title => "HTML fragment describing the alert in more detail, no limit on length."} Detail + %td + :textile + #{@alert.detail} + %tr + %th{:title => "ID set by the source of the alert."} Alert ID + %td= @alert.alert_id + %tr + %th{:title => "The groups in the Mauve server configuration that match this alert"} Alert groups + %td= Mauve::AlertGroup.matches(@alert).map{|g| g.name}.join("; ") + %tr + %th{:title => "The level of the first group in the Mauve server configuration that matched this alert"} Alert level + %td= @alert.level.to_s.upcase + -if @alert.raised? + %tr + %th{:title => "The time at which the alert was raised"} Raised at + %td= @alert.raised_at.to_s_human + -if @alert.acknowledged? + %tr + %th{:title => "The time at which the alert was acknowledged"} Acknowledged at + %td= @alert.acknowledged_at.to_s_human + " by " + @alert.acknowledged_by + " until " + @alert.will_unacknowledge_at.to_s_human + -if @alert.will_raise_at + %tr + %th{:title => "The time at which the alert will be automatically raised"} Will raise at + %td= @alert.will_raise_at.to_s_human + -if @alert.cleared_at + %tr + %th{:title => "The time at which the alert was last cleared"} Last cleared at + %td= @alert.cleared_at.to_s_human + -if @alert.will_clear_at + %tr + %th{:title => "The time at which the alert will be automatically cleared"} Will clear + %td= @alert.will_raise_at.to_s_human + %tr + %th Notifications sent out + %td + %ul + - @alert.changes.each do |change| + - if change.was_relevant? + %li + %strong= change.level + = change.update_type + notification to + = change.person + at + = change.at.to_s_human + +%h2 Actions +- if !@alert.acknowledged? + %form{:method => :post, :action => "/alert/#{@alert.id}/acknowledge"} + =partial("acknowledge_input") +- else + %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/unacknowledge"} + %input{:type => :submit, :value => "Unacknowledge this alert"} +%a#hide{:onclick => "$('form.hidden').toggle(); return false", :href=>"#"} Show other actions +- if @alert.cleared? + %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/raise"} + %input{:type => :submit, :value => "Raise this alert"} +- if @alert.raised? + %form.hidden{:method => :post, :action => "/alert/#{@alert.id}/clear"} + %input{:type => :submit, :value => "Clear this alert"} +%form.hidden{:method => :post, :action => "/alert/#{@alert.id}/destroy"} + %input{:type => :submit, :value => "Destroy this alert"} diff --git a/views/alerts.haml b/views/alerts.haml index 2d871cc..aedbc72 100644 --- a/views/alerts.haml +++ b/views/alerts.haml @@ -1,12 +1,31 @@ -!!! 5 -%html - = partial('head') - %body - =partial("navbar") - .container - - if @grouped_alerts.length > 0 - = partial('alerts_table') - - else - .notice - %p No alerts to display. +- if @grouped_alerts.length > 0 + %form#alerts{:method => :post, :action => '/alerts/acknowledge'} + = partial('alerts_table') + %h2 Actions + %p= partial('acknowledge_input') +- else + .notice#alerts_table + %p No alerts to display. +:javascript + $(document).ready( function() { + $.PeriodicalUpdater({ + url: '/ajax/alerts_table/#{@alert_type}/#{@group_by}', + minTimeout: 10000, + maxTimeout: 30000, + }, function(alerts_table, success, xhr, handle){ + $('#alerts_table').replaceWith(alerts_table); + }); + $.PeriodicalUpdater({ + url: '/ajax/alert_counts', + minTimeout: 10000, + maxTimeout: 30000, + }, function(alert_counts, success, xhr, handle){ + var counts = jQuery.parseJSON( alert_counts ); + $('#count_raised').html(counts[0]+counts[1]+counts[2]); + $('#count_ackd').html(counts[3]); + $('#count_cleared').html(counts[4]); + return false; + }); + + }); diff --git a/views/login.haml b/views/login.haml index 06e5320..3deee76 100644 --- a/views/login.haml +++ b/views/login.haml @@ -1,17 +1,11 @@ -!!! 5 -%html - =partial("head") - %body - = partial('navbar') - .container - %form{:action => '/login', :method => :POST} - %fieldset - %legend Please log in - %label{:for => "username"} Username - %input{:name => 'username', :type => 'text', :autocorrect => "off", :autocapitalize => "off"}/ - %br - %label{:for => "password", :title => "This is either your Single Sign On password or a PIN."} Password / PIN - %input{:name => 'password', :type => 'password'}/ - %br - %input{:type => 'hidden', :name => 'next_page', :value => @next_page}/ - %input{:type => 'submit', :value => 'Log in'}/ +%form{:action => '/login', :method => :POST} + %fieldset + %legend Please log in + %label{:for => "username"} Username + %input{:name => 'username', :type => 'text', :autocorrect => "off", :autocapitalize => "off"}/ + %br + %label{:for => "password", :title => "This is either your Single Sign On password or a PIN."} Password / PIN + %input{:name => 'password', :type => 'password'}/ + %br + %input{:type => 'hidden', :name => 'next_page', :value => @next_page}/ + %input{:type => 'submit', :value => 'Log in'}/ diff --git a/views/not_implemented.haml b/views/not_implemented.haml index a07b00d..dd3fe15 100644 --- a/views/not_implemented.haml +++ b/views/not_implemented.haml @@ -1,7 +1 @@ -!!! 5 -%html - = partial('head') - %body - =partial("navbar") - .container - .error Not implemented +.error Not implemented |