Merge pull request #238 from ChrisBr/instance_dashboard

Implements instance dashboard
This commit is contained in:
Christian Bruckmayer 2014-06-16 14:03:14 +02:00
commit 7c35e39531
18 changed files with 970 additions and 217 deletions

View file

@ -7,10 +7,9 @@ $(function() {
clearTimeout(t);
t = setTimeout(function(){
$("canvas").each(function(i,el){
$(el).attr({
"width":$(el).parent().width(),
"height":$(el).parent().outerHeight()
});
$(el).attr({
"width":$(el).parent().width()
});
});
$(".line_chart").each(function(){
@ -18,13 +17,11 @@ $(function() {
});
$(".doughnut_chart").each(function(){
draw_doughnut_chart(animate, $(this));
if($(this).is(":visible")){
draw_doughnut_chart(animate, $(this));
}
});
var m = 0;
$(".widget").height("");
$(".widget").each(function(i,el){ m = Math.max(m,$(el).height()); });
$(".widget").height(m);
}, 30);
}
@ -57,24 +54,23 @@ $(function() {
return options;
}
function draw_line_chart(animation, $this){
function draw_line_chart(animation, $canvas){
var options = get_animation({}, animation);
var chart_data = create_dataset($this);
var weeks = $this.parent().data('weeks');
var chart_data = create_dataset($canvas);
var weeks = $canvas.parent().data('weeks');
var data = {
labels : weeks,
datasets : chart_data
}
var ctx = $this.get(0).getContext("2d");
var ctx = $canvas.get(0).getContext("2d");
new Chart(ctx).Line(data, options);
}
function create_dataset($this){
var selected = getSelectedConferences($this);
var chart_data = $this.parent().data('chart');
var conferences = $this.parent().data('conferences');
function create_dataset($canvas){
var selected = getSelectedConferences($canvas);
var chart_data = $canvas.parent().data('chart');
var conferences = $canvas.parent().data('conferences');
var result = [];
for(var i in conferences){
@ -89,25 +85,43 @@ $(function() {
return result
}
function getSelectedConferences($this){
var name = $this.data('name');
function getSelectedConferences($canvas){
var name = $canvas.data('name');
var id = '#' + name + 'Checkboxes'
var selected = []
$(id + ' input').each(function(){
if($(this).is(":checked")) {
selected.push($(this).attr('name'));
var selected = [];
var $checkboxes = $(id + ' input');
// If there are checkboxes -> get selected
// Else -> use the active conference
if($checkboxes.length){
$(id + ' input').each(function(){
if($(this).is(":checked")) {
selected.push($(this).attr('name'));
}
});
}else{
var active = $canvas.parent().data('active');
for(i in active){
selected.push(active[i].short_title)
}
})
}
return selected;
}
$('.conferenceCheckboxes input').change(function(){
var chart = $(this).parent().data('chart');
var $canvas = $('#' + chart + 'Chart');
var chart_name = $(this).parent().data('chart');
var $canvas = $('#line_chart_' + chart_name);
draw_line_chart(false, $canvas);
});
$(window).on('resize', function(){ size(false); });
$(window).on('resize', function(){
size(false);
});
$('#doughnut_tabs a').click(function (e) {
e.preventDefault();
$(this).tab('show');
size(false);
});
size(true);
});

View file

@ -83,3 +83,11 @@ body {
.top-submitter img {
margin: 0 auto;
}
#doughnut .tab-content {
padding-bottom: 20px;
}
#submissions {
padding-bottom: 20px;
}

View file

@ -17,8 +17,10 @@ class Admin::ConferenceController < ApplicationController
@total_submissions = Event.count
@new_submissions = Event.where('created_at > ?', current_user.last_sign_in_at).count
@conferences = Conference.select('id, short_title, color, start_date,
registration_end_date, registration_start_date')
@active_conferences = Conference.get_active_conferences_for_dashboard # pending or the last two
@deactive_conferences = Conference.
get_conferences_without_active_for_dashboard(@active_conferences) # conferences without active
@conferences = @active_conferences + @deactive_conferences
@recent_users = User.limit(5).order(created_at: :desc)
@recent_events = Event.limit(5).order(created_at: :desc)
@ -86,9 +88,63 @@ class Admin::ConferenceController < ApplicationController
def show
@conference = Conference.find_by(short_title: params[:id])
# Overview and since last login information
@total_reg = @conference.registrations.count
@new_reg = @conference.registrations.where('created_at > ?', current_user.last_sign_in_at).count
@total_submissions = @conference.events.count
@new_submissions = @conference.events.
where('created_at > ?', current_user.last_sign_in_at).count
@program_length = @conference.current_program_hours
@new_program_length = @conference.new_program_hours(current_user.last_sign_in_at)
# Step by step list
@conference_progress = @conference.get_status
# Line charts
@registrations = { @conference.short_title => @conference.get_registrations_per_week }
@registration_weeks = [0]
@registration_weeks.push(@registrations[@conference.short_title].length)
@registration_weeks = @registration_weeks.max
@registrations = normalize_array_length(@registrations, @registration_weeks)
@registration_weeks = @registration_weeks > 0 ? (1..@registration_weeks).to_a : 1
@submissions = Conference.get_event_state_line_colors
@submissions_data = {}
@cfp_weeks = [0]
@submissions_data['Submitted'] = @conference.get_submissions_per_week
@cfp_weeks.push(@submissions_data['Submitted'].length)
@submissions_data['Confirmed'] = @conference.get_submissions_per_week_by_status('confirmed')
@cfp_weeks.push(@submissions_data['Confirmed'].length)
@submissions_data['Unconfirmed'] = @conference.get_submissions_per_week_by_status('unconfirmed')
@cfp_weeks.push(@submissions_data['Unconfirmed'].length)
@cfp_weeks = @cfp_weeks.max
@submissions_data = normalize_array_length(@submissions_data, @cfp_weeks)
@cfp_weeks = @cfp_weeks > 0 ? (1..@cfp_weeks).to_a : 1
# Doughnut charts
@event_type_distribution = @conference.event_type_distribution
@event_type_distribution_confirmed = @conference.event_type_distribution(:confirmed)
@difficulty_levels_distribution = @conference.difficulty_levels_distribution
@difficulty_levels_distribution_confirmed = @conference.
difficulty_levels_distribution(:confirmed)
@tracks_distribution = @conference.tracks_distribution
@tracks_distribution_confirmed = @conference.tracks_distribution(:confirmed)
# Recent actions information
@recent_events = @conference.events.limit(5).order(created_at: :desc)
@recent_registrations = @conference.registrations.limit(5).order(created_at: :desc)
@top_submitter = @conference.get_top_submitter
@event_distribution = @conference.event_distribution
respond_to do |format|
format.html

View file

@ -169,6 +169,23 @@ class Conference < ActiveRecord::Base
result
end
##
# Returns an array with the summarized event submissions per week.
#
# ====Returns
# * +Array+ -> e.g. [0, 3, 3, 5] -> first week 0 events, second week 3 events.
def get_submissions_per_week_by_status(state)
result = []
if call_for_papers && events
submissions = events.where('state = ?', state).group("strftime('%W', created_at)").count
start_week = call_for_papers.start_week
weeks = call_for_papers.weeks
result = calculate_items_per_week(start_week, weeks, submissions)
end
result
end
##
# Returns an array with the summarized registrations per week.
#
@ -326,6 +343,106 @@ class Conference < ActiveRecord::Base
calculate_user_distribution_hash(active_user, unconfirmed_user, dead_user)
end
##
# Calculates the overall programm hours
#
# ====Returns
# * +hash+ -> Fixnum hours
def current_program_hours
events_grouped = events.group(:event_type_id)
events_counted = events_grouped.count
calculate_program_hours(events_grouped, events_counted)
end
##
# Calculates the overall programm hours since date
#
# ====Returns
# * +hash+ -> Fixnum hours
def new_program_hours(date)
events_grouped = events.where('created_at > ?', date).group(:event_type_id)
events_counted = events_grouped.count
calculate_program_hours(events_grouped, events_counted)
end
##
# Calculates the difficulty level distribution from all events.
#
# ====Returns
# * +hash+ -> difficulty level => {color, value}
def difficulty_levels_distribution(state = nil)
calculate_event_distribution(:difficulty_level_id, :difficulty_level, state)
end
##
# Calculates the event_type distribution from all events.
#
# ====Returns
# * +hash+ -> event_type => {color, value}
def event_type_distribution(state = nil)
calculate_event_distribution(:event_type_id, :event_type, state)
end
##
# Calculates the track distribution from all events.
#
# ====Returns
# * +hash+ -> track => {color, value}
def tracks_distribution(state = nil)
if state
tracks_grouped = events.where('state = ?', state).group(:track_id)
else
tracks_grouped = events.group(:track_id)
end
tracks_counted = tracks_grouped.count
calculate_track_distribution_hash(tracks_grouped, tracks_counted)
end
##
# Return all pending conferences. If there are no pending conferences, the last two
# past conferences are returned
#
# ====Returns
# * +ActiveRecord+
def self.get_active_conferences_for_dashboard
result = Conference.where('start_date > ?', Time.now).
select('id, short_title, color, start_date,
registration_end_date, registration_start_date')
if result.length == 0
result = Conference.
select('id, short_title, color, start_date, registration_end_date,
registration_start_date').limit(2).
order(start_date: :desc)
end
result
end
##
# Return all conferences minus the active conferences
#
# ====Returns
# * +ActiveRecord+
def self.get_conferences_without_active_for_dashboard(active_conferences)
result = Conference.select('id, short_title, color, start_date,
registration_end_date, registration_start_date').order(start_date: :desc)
result - active_conferences
end
##
# A list with the three event states submitted, confirmed, unconfirmed with corresponding colors
#
# ====Returns
# * +List+
def self.get_event_state_line_colors
result = []
result.push(short_title: 'Submitted', color: 'blue')
result.push(short_title: 'Confirmed', color: 'green')
result.push(short_title: 'Unconfirmed', color: 'orange')
result
end
private
##
@ -407,6 +524,73 @@ class Conference < ActiveRecord::Base
!!registration_start_date && !!registration_end_date
end
# Calculates the distribution from events.
#
# ====Returns
# * +hash+ -> object_type => {color, value}
def calculate_event_distribution(group_by_id, association_symbol, state = nil)
if state
grouped = events.where('state = ?', 'confirmed').group(group_by_id)
else
grouped = events.group(group_by_id)
end
counted = grouped.count
calculate_distribution_hash(grouped, counted, association_symbol)
end
##
# Helper method to calculate the correct data format for the doughnut charts.
#
# ====Returns
# * +hash+ -> object_type => {color, value}
def calculate_distribution_hash(grouped, counter, symbol)
result = {}
grouped.each do |event|
object = event.send(symbol)
if object
result[object.title] = {
'value' => counter[object.id],
'color' => object.color
}
end
end
result
end
##
# Helper method to calculate the correct data format for the doughnut charts
# for track distribution of events.
#
# ====Returns
# * +hash+ -> object_type => {color, value}
def calculate_track_distribution_hash(tracks_grouped, tracks_counter)
result = {}
tracks_grouped.each do |event|
if event.track
result[event.track.name] = {
'value' => tracks_counter[event.track_id],
'color' => event.track.color
}
end
end
result
end
##
# Helper method to calculate the program hours.
#
# ====Returns
# * +Fixnums+ summed programm hours
def calculate_program_hours(events_grouped, events_counted)
result = 0
events_grouped.each do |event|
result += events_counted[event.event_type_id] * event.event_type.length
end
result
end
##
# Helper method for calculating hash with corresponding colors of user distribution states.
#
@ -496,14 +680,18 @@ class Conference < ActiveRecord::Base
#
def add_color
if !color
self.color = %w(
self.color = get_color
end
end
def get_color
%w(
#000000 #0000FF #00FF00 #FF0000 #FFFF00 #9900CC
#CC0066 #00FFFF #FF00FF #C0C0C0 #00008B #FFD700
#FFA500 #FF1493 #FF00FF #F0FFFF #EE82EE #D2691E
#C0C0C0 #A52A2A #9ACD32 #9400D3 #8B008B #8B0000
#87CEEB #808080 #800080 #008B8B #006400
).sample
end
end
# Calculates items per week from a hash.

View file

@ -0,0 +1,6 @@
.text-center
%h4 #{title}
%canvas.doughnut_chart{"data-chart"=>data.to_json}
- if data
- data.each do |key, value|
%span{"style"=>"border-bottom: 3px solid #{value['color']}"} #{key}: #{value['value']}

View file

@ -1,8 +0,0 @@
.well
.text-center
%h4 Event distribution
%canvas.doughnut_chart{"data-chart"=>@event_distribution.to_json}
.row
- if @event_distribution
- @event_distribution.each do |key, value|
%span{"style"=>"border-bottom: 3px solid #{value['color']}"} #{key}: #{value['value']}

View file

@ -0,0 +1,29 @@
.row
.col-md-12
.text-center
%h4
= title
.row
.col-md-12
.chart_data{ "data-chart"=>"#{y.to_json}", "data-conferences"=>"#{conferences.to_json}",
"data-deactive"=>"#{deactive_conferences.to_json}", "data-weeks"=>"#{x.to_json}",
"data-active"=>"#{active_conferences.to_json}"}
%canvas.line_chart{ :id => "line_chart_#{name}", "data-name"=>"#{name}" }
.row
.col-md-12
.text-center
= unit
.row
.col-md-12
.conferenceCheckboxes{ :id => "#{name}Checkboxes", "data-name"=>"#{name}" }
- if active_conferences && deactive_conferences && conferences && conferences.length > 1
- active_conferences.each do |conference|
%div
%span{ "style"=>"border-bottom: 3px solid #{conference[:color]};", "data-chart"=> "#{name}" }
%input{ "type"=>"checkbox", "name"=>"#{conference[:short_title]}", "checked"=>"checked"}
#{conference[:short_title]}
- deactive_conferences.each do |conference|
%div
%span{"style"=>"border-bottom: 3px solid #{conference[:color]};", "data-chart"=> "#{name}" }
%input{"type"=>"checkbox", "name"=>"#{conference[:short_title]}" }
#{conference[:short_title]}

View file

@ -1,18 +1,19 @@
- if recent_registrations && !recent_registrations.empty?
%table.table
%thead
%tr
%th #
%th Public Name
%th Conference
%th Date
- recent_registrations.each_with_index do |registration, index|
%tbody
%tr
%td #{index + 1}
%td #{registration.public_name}
%td #{registration.conference.title}
%td #{registration.created_at.strftime('%m/%d/%Y')}
.table-responsive
%table.table
%thead
%tr
%th #
%th Public Name
%th Conference
%th Date
- recent_registrations.each_with_index do |registration, index|
%tbody
%tr
%td #{index + 1}
%td #{registration.public_name}
%td #{registration.conference.title}
%td #{registration.created_at.strftime('%m/%d/%Y')}
- else
%h5.text-warning.text-center
No registrations!

View file

@ -1,21 +1,22 @@
- if recent_events && !recent_events.empty?
%table.table
%thead
%tr
%th #
%th Submitter
%th Title
%th Conference
%th Status
- recent_events.each_with_index do |event, index|
%tbody
%tr
%td #{index + 1}
%td #{event.submitter}
%td #{event.title}
%td #{event.conference.title}
%td
.span{'class'=>label_for(event.state)} #{event.state.humanize}
.table-responsive
%table.table
%thead
%tr
%th #
%th Submitter
%th Title
%th Conference
%th Status
- recent_events.each_with_index do |event, index|
%tbody
%tr
%td #{index + 1}
%td #{event.submitter}
%td #{event.title}
%td #{event.conference.title}
%td
.span{'class'=>label_for(event.state)} #{event.state.humanize}
- else
%h5.text-warning.text-center
No submissions!

View file

@ -1,22 +1,23 @@
- if recent_users && !recent_users.empty?
%table.table
%thead
%tr
%th #
%th E-Mail
%th Date registered
%th Status
- recent_users.each_with_index do |user, index|
%tbody
.table-responsive
%table.table
%thead
%tr
%td #{index}
%td #{user.email}
%td #{user.created_at.strftime('%m/%d/%Y')}
%td
- if user.confirmed?
%span.label.label-success Confirmed
-else
%span.label.label-danger Unconfirmed
%th #
%th E-Mail
%th Date registered
%th Status
- recent_users.each_with_index do |user, index|
%tbody
%tr
%td #{index}
%td #{user.email}
%td #{user.created_at.strftime('%m/%d/%Y')}
%td
- if user.confirmed?
%span.label.label-success Confirmed
-else
%span.label.label-danger Unconfirmed
- else
%h5.text-warning.text-center
No sign ups!

View file

@ -1,20 +0,0 @@
.well#registrations
.row
.text-center
%h4 Conference registrations over time
.row
.registrationsChart{"data-chart"=>"#{registrations.to_json}", "data-conferences"=>"#{conferences.to_json}", "data-weeks"=>"#{registration_weeks.to_json}"}
%canvas.line_chart#registrationsChart{"data-name"=>"registrations"}
.row
.text-center
weeks
.row
.conferenceCheckboxes#registrationsCheckboxes
- conferences.each do |conference|
%div
%span{"style"=>"border-bottom: 3px solid #{conference.color};", "data-chart"=> "registrations"}
- if conference.pending?
%input{"type"=>"checkbox", "name"=>"#{conference.short_title}", "checked"=>"checked"}
- else
%input{"type"=>"checkbox", "name"=>"#{conference.short_title}"}
#{conference.short_title}

View file

@ -1,20 +0,0 @@
.well#submissions
.row
.text-center
%h4 Event submissions over time
.row
.submissionsChart{"data-chart"=>"#{submissions.to_json}", "data-conferences"=>"#{conferences.to_json}", "data-weeks"=>"#{cfp_weeks.to_json}"}
%canvas.line_chart#submissionsChart{"data-name"=>"submissions"}
.row
.text-center
weeks
.row
.conferenceCheckboxes#submissionsCheckboxes
- conferences.each do |conference|
%div
%span{"style"=>"border-bottom: 3px solid #{conference.color};", "data-chart"=> "submissions"}
- if conference.pending?
%input{"type"=>"checkbox", "name"=>"#{conference.short_title}", "checked"=>"checked"}
- else
%input{"type"=>"checkbox", "name"=>"#{conference.short_title}"}
#{conference.short_title}

View file

@ -1,21 +0,0 @@
.col-sm-4
.dashbox.well.well-sm.text-center
.icon
%i.glyphicon.glyphicon-user
.text
%label.text-muted total user: #{@total_user}
%label.text-muted new user: #{@new_user}
.col-sm-4
.dashbox.well.well-sm.text-center
.icon
%i.glyphicon.glyphicon-star
.text
%label.text-muted total registrations: #{@total_reg}
%label.text-muted new registrations: #{@new_reg}
.col-sm-4
.dashbox.well.well-sm.text-center
.icon
%i.glyphicon.glyphicon-comment
.text
%label.text-muted total submissions: #{@total_submissions}
%label.text-muted new submissions: #{@new_submissions}

View file

@ -1,17 +1,18 @@
.row
%h3
Top Submitter
- if @top_submitter && !@top_submitter.empty?
- @top_submitter.each do |key, value|
.row.top-submitter
.col-md-2
= image_tag(key.gravatar_url(size: '25'), title: "Yo #{key.public_name}!", :alt => '', 'class'=>'img-circle img-responsive text-center')
.col-md-10
%h4
#{key}
%div
%small
#{pluralize(value, 'submission')}
- else
%h4.text-warning
No submissions!
.col-md-12
%h3
Top Submitter
- if @top_submitter && !@top_submitter.empty?
- @top_submitter.each do |key, value|
.row.top-submitter
.col-md-2
= image_tag(key.gravatar_url(size: '25'), title: "Yo #{key.public_name}!", :alt => '', 'class'=>'img-circle img-responsive text-center')
.col-md-10
%h4
#{key}
%div
%small
#{pluralize(value, 'submission')}
- else
%h4.text-warning
No submissions!

View file

@ -1,8 +0,0 @@
.well
.text-center
%h4 User distribution
%canvas.doughnut_chart{"data-chart"=>user_distribution.to_json}
.row
- if user_distribution
- user_distribution.each do |key, value|
%span{"style"=>"border-bottom: 3px solid #{value['color']}"} #{key}: #{value['value']}

View file

@ -1,46 +1,70 @@
.row
= render partial: 'top_boxes', locals: { total_user: @total_user, new_user: @new_user, active_user: @active_user,
total_reg: @total_reg, new_reg: @new_reg, submissions_count: @submissions_count }
.row
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-user
.text
%label.text-muted total user: #{@total_user}
%label.text-muted new user: #{@new_user}
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-star
.text
%label.text-muted total registrations: #{@total_reg}
%label.text-muted new registrations: #{@new_reg}
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-comment
.text
%label.text-muted total submissions: #{@total_submissions}
%label.text-muted new submissions: #{@new_submissions}
.row#registrations
.col-md-8
= render partial: 'submissions', locals: { conferences: @conferences, submissions: @submissions,
cfp_weeks: @cfp_weeks }
= render partial: 'line_chart', locals: { title: 'Registrations over time',
name: 'registrations',
conferences: @conferences,
active_conferences: @active_conferences,
deactive_conferences: @deactive_conferences,
y: @registrations,
x: @registration_weeks,
unit: 'weeks' }
.col-md-4
= render partial: 'event_distribution', locals: { event_distribution: @event_distribution }
= render partial: 'doughnut_chart', locals: { title: 'Events',data: @event_distribution }
.row#submissions
.col-md-8
= render partial: 'line_chart', locals: { title: 'Submissions over time',
name: 'submissions',
conferences: @conferences,
active_conferences: @active_conferences,
deactive_conferences: @deactive_conferences,
y: @submissions,
x: @cfp_weeks,
unit: 'weeks' }
.col-md-4
= render partial: 'doughnut_chart', locals: { title: 'User',data: @user_distribution }
.row
.col-md-8
= render partial: 'registrations', locals: { conferences: @conferences, registrations: @registrations,
registration_weeks: @registration_weeks }
.col-md-4
= render partial: 'user_distribution', locals: { user_distribution: @user_distribution }
.col-md-8
.row
%ul.nav.nav-tabs#recentTable
%li.active
%a{:href=>"#recent_user", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-user
Recent Users
%li
%a{:href=>"#recent_reg", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-star
Recent Registrations
%li
%a{:href=>"#recent_submissions", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-comment
Recent Submissions
.tab-content
.tab-pane.active#recent_user
= render partial: 'recent_users', locals: {recent_users: @recent_users}
.tab-pane#recent_reg
= render partial: 'recent_registrations', locals: {recent_registrations: @recent_registrations}
.tab-pane#recent_submissions
= render partial: 'recent_submissions', locals: {recent_events: @recent_events}
%ul.nav.nav-tabs#recentTable
%li.active
%a{:href=>"#recent_user", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-user
Recent Users
%li
%a{:href=>"#recent_reg", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-star
Recent Registrations
%li
%a{:href=>"#recent_submissions", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-comment
Recent Submissions
.tab-content
.tab-pane.active#recent_user
= render partial: 'recent_users', locals: {recent_users: @recent_users}
.tab-pane#recent_reg
= render partial: 'recent_registrations', locals: {recent_registrations: @recent_registrations}
.tab-pane#recent_submissions
= render partial: 'recent_submissions', locals: {recent_events: @recent_events}
.col-md-4
= render partial: 'top_submitter', locals: {top_submitter: @top_submitter}
:javascript
$('#recentTable a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})

View file

@ -3,9 +3,103 @@
Dashboard for #{@conference.title}
%hr
.row
.col-md-4
= render partial: 'todo_list', locals: { conference_progress: @conference_progress }
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-star
.text
%label.text-muted total registrations: #{@total_reg}
%label.text-muted new registrations: #{@new_reg}
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-comment
.text
%label.text-muted total submissions: #{@total_submissions}
%label.text-muted new submissions: #{@new_submissions}
.col-sm-4
.dashbox.text-center
.icon
%i.glyphicon.glyphicon-user
.text
%label.text-muted programm hours: #{@program_length} h
%label.text-muted new programm hours: #{@new_program_length} h
.row
.col-md-12
.row
.col-md-8
.row#registrations
.col-md-12
= render partial: 'line_chart', locals: { title: 'Registrations over time',
name: 'registrations',
conferences: [@conference],
active_conferences: [@conference],
deactive_conferences: [],
y: @registrations,
x: @registration_weeks,
unit: 'weeks' }
.row#submissions
.col-md-12
= render partial: 'line_chart', locals: { title: 'Submissions over time',
name: 'submissions',
conferences: @submissions,
active_conferences: @submissions,
deactive_conferences: [],
y: @submissions_data,
x: @cfp_weeks,
unit: 'weeks' }
.col-md-4
= render partial: 'todo_list', locals: { conference_progress: @conference_progress }
.row
.col-md-12#doughnut
%ul.nav.nav-tabs#doughnut_tabs
%li.active
%a{:href=>"#distribution_all", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-star
All
%li
%a{:href=>"#distribution_confirmed", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-comment
Confirmed
.tab-content
.tab-pane.active#distribution_all
.row
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution}
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution}
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution}
.tab-pane#distribution_confirmed
.row
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution_confirmed}
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_confirmed}
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_confirmed}
.row
.col-md-8
%ul.nav.nav-tabs#recentTable
%li.active
%a{:href=>"#recent_reg", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-star
Recent Registrations
%li
%a{:href=>"#recent_submissions", "data-toggle"=>"tab"}
%span.glyphicon.glyphicon-comment
Recent Submissions
.tab-content
.tab-pane.active#recent_reg
= render partial: 'recent_registrations', locals: {recent_registrations: @recent_registrations}
.tab-pane#recent_submissions
= render partial: 'recent_submissions', locals: {recent_events: @recent_events}
.col-md-4
= render partial: 'top_submitter', locals: {top_submitter: @top_submitter}
.col-md-4
= render partial: 'event_distribution', locals: { event_distribution: @event_distribution }
:javascript
$('#recentTable a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})

View file

@ -6,6 +6,413 @@ describe Conference do
let(:subject) { create(:conference) }
describe 'program hours' do
before(:each) do
@long = create(:event_type, length: 100)
@short = create(:event_type, length: 10)
end
describe '#actual_program_hours' do
it 'calculates correct values with events' do
create(:event, conference: subject, event_type: @long)
create(:event, conference: subject, event_type: @long)
create(:event, conference: subject, event_type: @short)
create(:event, conference: subject, event_type: @short)
result = 220
expect(subject.current_program_hours).to eq(result)
end
it 'calculates correct values without events' do
result = 0
expect(subject.current_program_hours).to eq(result)
end
end
describe '#new_program_hours' do
it 'calculates correct values with events' do
create(:event, conference: subject, event_type: @long, created_at: Time.now - 3.days)
create(:event, conference: subject, event_type: @long)
create(:event, conference: subject, event_type: @short, created_at: Time.now - 3.days)
create(:event, conference: subject, event_type: @short)
result = 110
expect(subject.new_program_hours(Time.now - 5.minutes)).to eq(result)
end
it 'calculates correct values without events' do
result = 0
expect(subject.new_program_hours(Time.now - 5.minutes)).to eq(result)
end
end
end
describe '#difficulty_levels' do
before (:each) do
subject.email_settings = create(:email_settings)
@easy = create(:difficulty_level, title: 'Easy', color: '#000000')
@hard = create(:difficulty_level, title: 'Hard', color: '#ffffff')
end
describe '#difficulty_levels_distribution' do
it 'calculates correct for different difficulty levels' do
create(:event, conference: subject, difficulty_level: @easy)
create(:event, conference: subject, difficulty_level: @easy)
create(:event, conference: subject, difficulty_level: @hard)
result = {}
result['Hard'] = {
'value' => 1,
'color' => '#ffffff',
}
result['Easy'] = {
'value' => 2,
'color' => '#000000',
}
expect(subject.difficulty_levels_distribution).to eq(result)
end
it 'calculates correct for one difficulty levels' do
create(:event, conference: subject, difficulty_level: @easy)
result = {}
result['Easy'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.difficulty_levels_distribution).to eq(result)
end
it 'calculates correct for no difficulty levels' do
result = {}
expect(subject.difficulty_levels_distribution).to eq(result)
end
end
describe '#difficulty_levels_distribution_confirmed' do
it 'calculates correct for different difficulty levels without confirmed' do
create(:event, conference: subject, difficulty_level: @easy)
create(:event, conference: subject, difficulty_level: @easy)
create(:event, conference: subject, difficulty_level: @hard)
result = {}
expect(subject.difficulty_levels_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for different difficulty levels with confirmed' do
confirmed_easy = create(:event, conference: subject, difficulty_level: @easy)
create(:event, conference: subject, difficulty_level: @easy)
confirmed_hard = create(:event, conference: subject, difficulty_level: @hard)
options = {}
options[:send_mail] = 'false'
confirmed_easy.accept!(options)
confirmed_hard.accept!(options)
confirmed_easy.confirm!
confirmed_hard.confirm!
result = {}
result['Hard'] = {
'value' => 1,
'color' => '#ffffff'
}
result['Easy'] = {
'value' => 1,
'color' => '#000000'
}
expect(subject.difficulty_levels_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for one difficulty levels' do
confirmed = create(:event, conference: subject, difficulty_level: @easy)
options = {}
options[:send_mail] = 'false'
confirmed.accept!(options)
confirmed.confirm!
result = {}
result['Easy'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.difficulty_levels_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for no difficulty levels' do
result = {}
expect(subject.difficulty_levels_distribution(:confirmed)).to eq(result)
end
end
end
describe 'event type distribution' do
before (:each) do
subject.email_settings = create(:email_settings)
@workshop = create(:event_type, title: 'Workshop', color: '#000000')
@lecture = create(:event_type, title: 'Lecture', color: '#ffffff')
end
describe '#event_type_distribution' do
it 'calculates correct for different event types' do
create(:event, conference: subject, event_type: @workshop)
create(:event, conference: subject, event_type: @workshop)
create(:event, conference: subject, event_type: @lecture)
result = {}
result['Workshop'] = {
'value' => 2,
'color' => '#000000',
}
result['Lecture'] = {
'value' => 1,
'color' => '#ffffff',
}
expect(subject.event_type_distribution).to eq(result)
end
it 'calculates correct for one event types' do
create(:event, conference: subject, event_type: @workshop)
result = {}
result['Workshop'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.event_type_distribution).to eq(result)
end
it 'calculates correct for no event types' do
result = {}
expect(subject.event_type_distribution).to eq(result)
end
end
describe '#event_type_distribution_confirmed' do
it 'calculates correct for different event types without confirmed' do
create(:event, conference: subject, event_type: @workshop)
create(:event, conference: subject, event_type: @workshop)
create(:event, conference: subject, event_type: @lecture)
result = {}
expect(subject.event_type_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for different event types with confirmed' do
confirmed_ws = create(:event, conference: subject, event_type: @workshop)
create(:event, conference: subject, event_type: @workshop)
confirmed_lt = create(:event, conference: subject, event_type: @lecture)
options = {}
options[:send_mail] = 'false'
confirmed_ws.accept!(options)
confirmed_lt.accept!(options)
confirmed_ws.confirm!
confirmed_lt.confirm!
result = {}
result['Lecture'] = {
'value' => 1,
'color' => '#ffffff'
}
result['Workshop'] = {
'value' => 1,
'color' => '#000000'
}
expect(subject.event_type_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for one event types' do
confirmed = create(:event, conference: subject, event_type: @workshop)
options = {}
options[:send_mail] = 'false'
confirmed.accept!(options)
confirmed.confirm!
result = {}
result['Workshop'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.event_type_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for no event types' do
result = {}
expect(subject.event_type_distribution(:confirmed)).to eq(result)
end
end
end
describe 'tracks_distribution' do
before (:each) do
subject.email_settings = create(:email_settings)
@track_one = create(:track, name: 'Track One', color: '#000000')
@track_two = create(:track, name: 'Track Two', color: '#ffffff')
end
describe '#tracks_distribution' do
it 'calculates correct for different tracks' do
create(:event, conference: subject, track: @track_one)
create(:event, conference: subject, track: @track_one)
create(:event, conference: subject, track: @track_two)
result = {}
result['Track One'] = {
'value' => 2,
'color' => '#000000',
}
result['Track Two'] = {
'value' => 1,
'color' => '#ffffff',
}
expect(subject.tracks_distribution).to eq(result)
end
it 'calculates correct for one track' do
create(:event, conference: subject, track: @track_one)
result = {}
result['Track One'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.tracks_distribution).to eq(result)
end
it 'calculates correct for no track' do
result = {}
expect(subject.tracks_distribution).to eq(result)
end
end
describe '#tracks_distribution_confirmed' do
it 'calculates correct for different tracks without confirmed' do
create(:event, conference: subject, track: @track_one)
create(:event, conference: subject, track: @track_one)
create(:event, conference: subject, track: @track_two)
result = {}
expect(subject.tracks_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for different tracks with confirmed' do
confirmed_one = create(:event, conference: subject, track: @track_one)
create(:event, conference: subject, track: @track_one)
confirmed_two = create(:event, conference: subject, track: @track_two)
options = {}
options[:send_mail] = 'false'
confirmed_one.accept!(options)
confirmed_two.accept!(options)
confirmed_one.confirm!
confirmed_two.confirm!
result = {}
result['Track One'] = {
'value' => 1,
'color' => '#000000'
}
result['Track Two'] = {
'value' => 1,
'color' => '#ffffff'
}
expect(subject.tracks_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for one track' do
confirmed = create(:event, conference: subject, track: @track_one)
options = {}
options[:send_mail] = 'false'
confirmed.accept!(options)
confirmed.confirm!
result = {}
result['Track One'] = {
'value' => 1,
'color' => '#000000',
}
expect(subject.tracks_distribution(:confirmed)).to eq(result)
end
it 'calculates correct for no track' do
result = {}
expect(subject.tracks_distribution(:confirmed)).to eq(result)
end
end
end
describe '#get_active_conferences' do
it 'returns pending conferences' do
a = create(:conference,
short_title: 'a', start_date: Time.now + 14.days,
end_date: Time.now + 21.days)
b = create(:conference,
short_title: 'b', start_date: Time.now + 21.days,
end_date: Time.now + 28.days)
c = create(:conference,
short_title: 'c', start_date: Time.now + 21.days,
end_date: Time.now + 28.days)
create(:conference,
short_title: 'd', start_date: Time.now - 1.year,
end_date: Time.now - 360.days)
result = [a, b, c]
expect(Conference.get_active_conferences_for_dashboard).to match_array(result)
end
it 'returns the last two past conferences if there are no pending conferences' do
subject.start_date = Time.now - 10.days
subject.end_date = Time.now - 5.days
c = create(:conference,
short_title: 'c', start_date: Time.now - 1.year,
end_date: Time.now - 360.days)
result = [subject, c]
expect(Conference.get_active_conferences_for_dashboard).to match_array(result)
end
it 'returns empty array if there are no conferences' do
expect(Conference.get_active_conferences_for_dashboard).to match_array([])
end
end
describe '#get_deactive_conferences' do
it 'returns all conferences without the active conferences' do
a = create(:conference, start_date: Time.now - 3.year, end_date: Time.now - 1080.days)
b = create(:conference, start_date: Time.now - 2.year, end_date: Time.now - 720.days)
c = create(:conference, start_date: Time.now - 1.year, end_date: Time.now - 360.days)
result = [a, b, c]
expect(Conference.get_conferences_without_active_for_dashboard([subject])).
to match_array(result)
end
it 'returns all conferences if there are no active conferences' do
subject.start_date = Time.now - 10.days
subject.end_date = Time.now - 5.days
expect(Conference.get_conferences_without_active_for_dashboard([])).to match_array([subject])
end
it 'returns empty array if there are no conferences' do
expect(Conference.get_conferences_without_active_for_dashboard([])).to match_array([])
end
it 'returns no conferences if all conferences are pending' do
expect(Conference.get_conferences_without_active_for_dashboard([subject])).to match_array([])
end
it 'return no conferences if there are only two conferences and no pending' do
a = create(:conference, start_date: Time.now - 2.year, end_date: Time.now - 720.days)
b = create(:conference, start_date: Time.now - 1.year, end_date: Time.now - 360.days)
expect(Conference.get_conferences_without_active_for_dashboard([a, b])).to match_array([])
end
end
describe '#get_submission_line_colors' do
it ' returns correct values' do
result = []
result.push(short_title: 'Submitted', color: 'blue')
result.push(short_title: 'Confirmed', color: 'green')
result.push(short_title: 'Unconfirmed', color: 'orange')
expect(Conference.get_event_state_line_colors).to eq(result)
end
end
describe '#event_distribution' do
before(:each) do