From 65a73f876aa6a947f9c8c87ad538983af69cf73c Mon Sep 17 00:00:00 2001 From: Chrisbr Date: Tue, 3 Jun 2014 16:27:10 +0200 Subject: [PATCH] Implements todo list for instance dashboard --- app/assets/stylesheets/osem.css | 18 +- .../admin/conference_controller.rb | 9 +- app/helpers/application_helper.rb | 16 ++ app/models/conference.rb | 19 +++ .../admin/conference/_registrations.html.haml | 20 +++ .../admin/conference/_submissions.html.haml | 20 +++ .../admin/conference/_todo_list.html.haml | 29 ++++ .../admin/conference/_top_boxes.html.haml | 21 +++ app/views/admin/conference/index.html.haml | 100 ++--------- app/views/admin/conference/show.html.haml | 8 +- spec/factories/venues.rb | 8 + spec/models/conference_spec.rb | 160 ++++++++++++++++++ .../admin/conference/show.html.haml_spec.rb | 7 +- 13 files changed, 333 insertions(+), 102 deletions(-) create mode 100644 app/views/admin/conference/_registrations.html.haml create mode 100644 app/views/admin/conference/_submissions.html.haml create mode 100644 app/views/admin/conference/_todo_list.html.haml create mode 100644 app/views/admin/conference/_top_boxes.html.haml create mode 100644 spec/factories/venues.rb diff --git a/app/assets/stylesheets/osem.css b/app/assets/stylesheets/osem.css index de966a75..251f9503 100644 --- a/app/assets/stylesheets/osem.css +++ b/app/assets/stylesheets/osem.css @@ -64,12 +64,22 @@ body > #messages { .dashbox .icon { padding-left: 8px; display: block; - font-size: 2.3em; + font-size: 3.8em; } -.dashbox var { +.dashbox label { display: block; - font-size: 2em; - font-style: normal; + font-size: 1.1em; } +.todolist-missing span { + color: #ff0000; +} + +.todolist-ok { + text-decoration: line-through; +} + +.todolist-ok span { + color: #02A10F; +} diff --git a/app/controllers/admin/conference_controller.rb b/app/controllers/admin/conference_controller.rb index d34ee1ed..618513eb 100644 --- a/app/controllers/admin/conference_controller.rb +++ b/app/controllers/admin/conference_controller.rb @@ -4,10 +4,12 @@ class Admin::ConferenceController < ApplicationController def index @total_user = User.count @new_user = User.where('created_at > ?', current_user.last_sign_in_at).count - @new_reg = Registration.where('created_at > ?', current_user.last_sign_in_at).count + @total_reg = Registration.count - @active_user = User.where('last_sign_in_at > ?', Date.today - 3.months).count - @submissions_count = Event.count + @new_reg = Registration.where('created_at > ?', current_user.last_sign_in_at).count + + @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') @@ -75,6 +77,7 @@ class Admin::ConferenceController < ApplicationController def show @conference = Conference.find_by(short_title: params[:id]) + @conference_progress = @conference.get_status respond_to do |format| format.html format.json { render json: @conference.to_json } diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a68e06ac..70366714 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -15,6 +15,22 @@ module ApplicationHelper end end + def icon_for_todo(bool) + if bool + return 'glyphicon glyphicon-ok' + else + return 'glyphicon glyphicon-remove' + end + end + + def class_for_todo(bool) + if bool + return 'list-group-item todolist-ok' + else + return 'list-group-item todolist-missing' + end + end + def normalize_array_length(hashmap, length) hashmap.each do |key, value| if value.length < length diff --git a/app/models/conference.rb b/app/models/conference.rb index cdbd26fd..b1ee2b32 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -220,6 +220,25 @@ class Conference < ActiveRecord::Base start_date > Date.today end + ## + # Returns a hash with booleans with the required conference options. + # + # ====Returns + # * +hash+ -> true -> filled / false -> missing + def get_status + result = {} + result['registration'] = !!registration_start_date && !!registration_end_date + result['cfp'] = !!call_for_papers + result['venue'] = !!venue && !!venue.name && !!venue.address && !!venue.website + result['rooms'] = rooms.count > 0 + result['tracks'] = tracks.count > 0 + result['event_types'] = event_types.count > 0 + result['difficulty_levels'] = difficulty_levels.count > 0 + result['process'] = (result.select { |k, v| v }.length / result.length.to_f * 100).round(0).to_s + result['short_title'] = short_title + result + end + private ## diff --git a/app/views/admin/conference/_registrations.html.haml b/app/views/admin/conference/_registrations.html.haml new file mode 100644 index 00000000..c08017b4 --- /dev/null +++ b/app/views/admin/conference/_registrations.html.haml @@ -0,0 +1,20 @@ +.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#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} diff --git a/app/views/admin/conference/_submissions.html.haml b/app/views/admin/conference/_submissions.html.haml new file mode 100644 index 00000000..3593d0a9 --- /dev/null +++ b/app/views/admin/conference/_submissions.html.haml @@ -0,0 +1,20 @@ +.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#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} diff --git a/app/views/admin/conference/_todo_list.html.haml b/app/views/admin/conference/_todo_list.html.haml new file mode 100644 index 00000000..db6cf8db --- /dev/null +++ b/app/views/admin/conference/_todo_list.html.haml @@ -0,0 +1,29 @@ +.list-group + %li.list-group-item + %h4 + Conference progress + .progress + .progress-bar{ 'role'=>'progressbar', 'aria-valuenow'=>"#{conference_progress['process']}", 'aria-valuemin'=>'0', + 'aria-valuemax'=>'100', 'style'=>"width: #{conference_progress['process']}%;" } + = conference_progress['process'] + '%' + %li{'class'=>class_for_todo(conference_progress['registration'])} + %span{'class'=>icon_for_todo(conference_progress['registration'])} + = link_to 'Set up registration period', edit_admin_conference_path(conference_progress['short_title'], :anchor => 'conference-end-datepicker') + %li{'class'=>class_for_todo(conference_progress['cfp'])} + %span{'class'=>icon_for_todo(conference_progress['cfp'])} + = link_to 'Set up call for papers', admin_conference_callforpapers_path(conference_progress['short_title']) + %li{'class'=>class_for_todo(conference_progress['venue'])} + %span{'class'=>icon_for_todo(conference_progress['venue'])} + = link_to 'Add venue', admin_conference_venue_info_path(conference_progress['short_title']) + %li{'class'=>class_for_todo(conference_progress['rooms'])} + %span{'class'=>icon_for_todo(conference_progress['rooms'])} + = link_to 'Add rooms', admin_conference_rooms_path(conference_progress['short_title']) + %li{'class'=>class_for_todo(conference_progress['tracks'])} + %span{'class'=>icon_for_todo(conference_progress['tracks'])} + = link_to 'Add tracks', admin_conference_tracks_path(conference_progress['short_title']) + %li{'class'=>class_for_todo(conference_progress['event_types'])} + %span{'class'=>icon_for_todo(conference_progress['event_types'])} + = link_to 'Add event types', admin_conference_eventtypes_path(conference_progress['short_title']) + %li{'class'=>class_for_todo(conference_progress['difficulty_levels'])} + %span{'class'=>icon_for_todo(conference_progress['difficulty_levels'])} + = link_to 'Add difficulty levels', admin_conference_difficulty_levels_path(conference_progress['short_title']) diff --git a/app/views/admin/conference/_top_boxes.html.haml b/app/views/admin/conference/_top_boxes.html.haml new file mode 100644 index 00000000..a5a26000 --- /dev/null +++ b/app/views/admin/conference/_top_boxes.html.haml @@ -0,0 +1,21 @@ +.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} \ No newline at end of file diff --git a/app/views/admin/conference/index.html.haml b/app/views/admin/conference/index.html.haml index 136ceecb..d4f8fd15 100644 --- a/app/views/admin/conference/index.html.haml +++ b/app/views/admin/conference/index.html.haml @@ -1,93 +1,13 @@ .row - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-user - .text - %var - = @total_user - %label.text-muted total user - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-thumbs-up - .text - %var - = @new_user - %label.text-muted new user - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-heart-empty - .text - %var - = @active_user - %label.text-muted active user - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-star - .text - %var - = @total_reg - %label.text-muted total registrations - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-usd - .text - %var - = @new_reg - %label.text-muted new registrations - .col-sm-2 - .dashbox.well.well-sm.text-center - .icon - %i.glyphicon.glyphicon-comment - .text - %var - = @submissions_count - %label.text-muted submissions + = 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-md-12 - .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#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} + .col-md-8 + = render partial: 'submissions', locals: { conferences: @conferences, submissions: @submissions, + cfp_weeks: @cfp_weeks } + .col-md-4 .row - .col-md-12 - .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#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} + .col-md-8 + = render partial: 'registrations', locals: { conferences: @conferences, registrations: @registrations, + registration_weeks: @registration_weeks } + .col-md-4 \ No newline at end of file diff --git a/app/views/admin/conference/show.html.haml b/app/views/admin/conference/show.html.haml index f78d0597..5ea86ffe 100644 --- a/app/views/admin/conference/show.html.haml +++ b/app/views/admin/conference/show.html.haml @@ -1,3 +1,7 @@ +%h1 + %span.glyphicon.glyphicon-dashboard + Dashboard for #{@conference.title} +%hr .row - .col-md-8 - %h1 Dashboard for #{@conference.title} \ No newline at end of file + .col-md-4 + = render partial: 'todo_list', locals: { conference_progress: @conference_progress } diff --git a/spec/factories/venues.rb b/spec/factories/venues.rb new file mode 100644 index 00000000..fca4e1f5 --- /dev/null +++ b/spec/factories/venues.rb @@ -0,0 +1,8 @@ +# Read about factories at https://github.com/thoughtbot/factory_girl +FactoryGirl.define do + factory :venue do + name 'Suse Office' + address 'Maxfeldstrasse 5 \n90409 Nuremberg' + website 'www.opensuse.org' + end +end diff --git a/spec/models/conference_spec.rb b/spec/models/conference_spec.rb index 2f947160..425b8919 100644 --- a/spec/models/conference_spec.rb +++ b/spec/models/conference_spec.rb @@ -6,6 +6,166 @@ describe Conference do let(:subject) { create(:conference) } + describe '#get_status' do + + before(:each) do + # Setup positive result hash + @result = {} + @result['registration'] = true + @result['cfp'] = true + @result['venue'] = true + @result['rooms'] = true + @result['tracks'] = true + @result['event_types'] = true + @result['difficulty_levels'] = true + + # Setup negative result hash + @result_false = Hash.new + @result.each { |key, value| @result_false[key] = !value } + + @result['short_title'] = @result_false['short_title'] = subject.short_title + @result['process'] = 100.to_s + @result_false['process'] = 0.to_s + end + + it 'calculates correct for new conference' do + subject.registration_start_date = nil + subject.registration_end_date = nil + subject.call_for_papers = nil + subject.venue = nil + subject.rooms = [] + subject.tracks = [] + subject.event_types = [] + subject.difficulty_levels = [] + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration' do + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = nil + subject.rooms = [] + subject.tracks = [] + subject.event_types = [] + subject.difficulty_levels = [] + + @result_false['registration'] = true + @result_false['process'] = 14.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration, cfp' do + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = create(:call_for_papers) + subject.rooms = [] + subject.tracks = [] + subject.event_types = [] + subject.difficulty_levels = [] + + @result_false['cfp'] = true + @result_false['registration'] = true + @result_false['process'] = 29.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration, cfp, venue' do + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = create(:call_for_papers) + subject.venue = create(:venue) + subject.rooms = [] + subject.tracks = [] + subject.event_types = [] + subject.difficulty_levels = [] + + @result_false['cfp'] = true + @result_false['registration'] = true + @result_false['venue'] = true + @result_false['process'] = 43.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration, cfp, venue, rooms' do + subject.rooms = [create(:room)] + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = create(:call_for_papers) + subject.venue = create(:venue) + subject.tracks = [] + subject.event_types = [] + subject.difficulty_levels = [] + + @result_false['cfp'] = true + @result_false['registration'] = true + @result_false['venue'] = true + @result_false['rooms'] = true + @result_false['process'] = 57.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration, cfp, venue, rooms, tracks' do + subject.rooms = [create(:room)] + subject.tracks = [create(:track)] + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = create(:call_for_papers) + subject.venue = create(:venue) + subject.event_types = [] + subject.difficulty_levels = [] + + @result_false['cfp'] = true + @result_false['registration'] = true + @result_false['venue'] = true + @result_false['rooms'] = true + @result_false['tracks'] = true + @result_false['process'] = 71.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with registration, cfp, + venue, rooms, tracks, event_types' do + subject.rooms = [create(:room)] + subject.tracks = [create(:track)] + subject.event_types = [create(:event_type)] + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.call_for_papers = create(:call_for_papers) + subject.venue = create(:venue) + subject.difficulty_levels = [] + + @result_false['cfp'] = true + @result_false['registration'] = true + @result_false['venue'] = true + @result_false['rooms'] = true + @result_false['tracks'] = true + @result_false['event_types'] = true + @result_false['process'] = 86.to_s + + expect(subject.get_status).to eq(@result_false) + end + + it 'calculates correct for conference with all mandatory options' do + subject.rooms = [create(:room)] + subject.tracks = [create(:track)] + subject.event_types = [create(:event_type)] + subject.difficulty_levels = [create(:difficulty_level)] + subject.registration_start_date = Date.today + subject.registration_end_date = Date.today + 14 + subject.venue = create(:venue) + subject.call_for_papers = create(:call_for_papers) + subject.venue = create(:venue) + + expect(subject.get_status).to eq(@result) + end + end + describe '#registration_weeks' do it 'calculates new year' do diff --git a/spec/views/admin/conference/show.html.haml_spec.rb b/spec/views/admin/conference/show.html.haml_spec.rb index 6c0be344..fa747370 100644 --- a/spec/views/admin/conference/show.html.haml_spec.rb +++ b/spec/views/admin/conference/show.html.haml_spec.rb @@ -3,9 +3,10 @@ require 'spec_helper' describe 'admin/conference/show' do it 'renders conference dashboard' do - @conference = create(:conference, title: 'OpenSUSE') - assign :conference, @conference + conference = create(:conference, title: 'OpenSUSE') + assign :conference, conference + assign :conference_progress, conference.get_status render - expect(rendered).to include("Dashboard for #{@conference.title}") + expect(rendered).to include("Dashboard for #{conference.title}") end end