Enable blind voting
This commit is contained in:
parent
8388385b51
commit
59eeb7edbd
17 changed files with 391 additions and 108 deletions
|
|
@ -1,6 +1,14 @@
|
||||||
// get current_date
|
// get current_date
|
||||||
var today = new Date().toISOString().slice(0, 10);
|
var today = new Date().toISOString().slice(0, 10);
|
||||||
$(function () {
|
$(function () {
|
||||||
|
$("input[id^='datetimepicker']").datetimepicker({
|
||||||
|
pickTime: true,
|
||||||
|
useCurrent: false,
|
||||||
|
sideBySide: true,
|
||||||
|
autoclose: true,
|
||||||
|
format: 'YYYY-MM-DD HH:mm'
|
||||||
|
});
|
||||||
|
|
||||||
$("#registration-arrival-datepicker").datetimepicker({
|
$("#registration-arrival-datepicker").datetimepicker({
|
||||||
pickTime: true,
|
pickTime: true,
|
||||||
useCurrent: false,
|
useCurrent: false,
|
||||||
|
|
@ -12,7 +20,7 @@ $(function () {
|
||||||
minDate : today,
|
minDate : today,
|
||||||
defaultDate : $("#registration-arrival-datepicker").attr('start_date'),
|
defaultDate : $("#registration-arrival-datepicker").attr('start_date'),
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#registration-departure-datepicker").datetimepicker({
|
$("#registration-departure-datepicker").datetimepicker({
|
||||||
pickTime: true,
|
pickTime: true,
|
||||||
useCurrent: false,
|
useCurrent: false,
|
||||||
|
|
@ -23,7 +31,7 @@ $(function () {
|
||||||
minDate : $("#registration-arrival-datepicker").attr('start_date'),
|
minDate : $("#registration-arrival-datepicker").attr('start_date'),
|
||||||
defaultDate : $("#registration-arrival-datepicker").attr('end_date'),
|
defaultDate : $("#registration-arrival-datepicker").attr('end_date'),
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#registration-arrival-datepicker").on("dp.change",function (e) {
|
$("#registration-arrival-datepicker").on("dp.change",function (e) {
|
||||||
// departure_date > start_date,arrival_date
|
// departure_date > start_date,arrival_date
|
||||||
if ((new Date(e.date).getTime()) > (new Date($("#registration-arrival-datepicker").attr('start_date')).getTime())){
|
if ((new Date(e.date).getTime()) > (new Date($("#registration-arrival-datepicker").attr('start_date')).getTime())){
|
||||||
|
|
@ -52,7 +60,7 @@ $(function () {
|
||||||
useCurrent: false,
|
useCurrent: false,
|
||||||
format: "YYYY-MM-DD",
|
format: "YYYY-MM-DD",
|
||||||
});
|
});
|
||||||
|
|
||||||
// end_date_conference >= registration-period-Start_date >= Current_date
|
// end_date_conference >= registration-period-Start_date >= Current_date
|
||||||
// registration-period-Start_date <= registration-period-End_date <= End_date (of conference)
|
// registration-period-Start_date <= registration-period-End_date <= End_date (of conference)
|
||||||
$("#registration-period-start-datepicker").datetimepicker({
|
$("#registration-period-start-datepicker").datetimepicker({
|
||||||
|
|
@ -62,7 +70,7 @@ $(function () {
|
||||||
minDate : today,
|
minDate : today,
|
||||||
maxDate : $("#registration-period-start-datepicker").attr('end_date'),
|
maxDate : $("#registration-period-start-datepicker").attr('end_date'),
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#registration-period-end-datepicker").datetimepicker({
|
$("#registration-period-end-datepicker").datetimepicker({
|
||||||
pickTime: false,
|
pickTime: false,
|
||||||
useCurrent: false,
|
useCurrent: false,
|
||||||
|
|
@ -70,7 +78,7 @@ $(function () {
|
||||||
minDate: today,
|
minDate: today,
|
||||||
maxDate : $("#registration-period-start-datepicker").attr('end_date'),
|
maxDate : $("#registration-period-start-datepicker").attr('end_date'),
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#conference-start-datepicker").on("dp.change",function (e) {
|
$("#conference-start-datepicker").on("dp.change",function (e) {
|
||||||
$('#conference-end-datepicker').data("DateTimePicker").setMinDate(e.date);
|
$('#conference-end-datepicker').data("DateTimePicker").setMinDate(e.date);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ module Admin
|
||||||
private
|
private
|
||||||
|
|
||||||
def program_params
|
def program_params
|
||||||
params.require(:program).permit(:rating, :schedule_public, :schedule_fluid, :languages)
|
params.require(:program).permit(:rating, :schedule_public, :schedule_fluid, :languages, :blind_voting, :voting_start_date, :voting_end_date)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
##
|
||||||
|
# Checks if the voting has already started, or if it has already ended
|
||||||
|
#
|
||||||
|
def voting_open_or_close(program)
|
||||||
|
return if program.voting_period?
|
||||||
|
if program.voting_start_date > Date.today
|
||||||
|
return 'Voting period has not started yet!'
|
||||||
|
else # voting_end_date > Date.today because voting_start_date < voting_end_date
|
||||||
|
return 'Voting period is over!'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Gets an EventType object, and returns its length in timestamp format (HH:MM)
|
# Gets an EventType object, and returns its length in timestamp format (HH:MM)
|
||||||
# ====Gets
|
# ====Gets
|
||||||
|
|
@ -9,6 +21,15 @@ module ApplicationHelper
|
||||||
[length / 60, length % 60].map { |t| t.to_s.rjust(2, '0') }.join(':')
|
[length / 60, length % 60].map { |t| t.to_s.rjust(2, '0') }.join(':')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Gets a datetime object
|
||||||
|
# ====Returns
|
||||||
|
# * +String+ -> formated datetime object
|
||||||
|
def format_datetime(obj)
|
||||||
|
return unless obj
|
||||||
|
obj.strftime('%Y-%m-%d %H:%M')
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# ====Returns
|
# ====Returns
|
||||||
# * +String+ -> number of registrations / max allowed registrations
|
# * +String+ -> number of registrations / max allowed registrations
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,24 @@ class Event < ActiveRecord::Base
|
||||||
registrations.count < max_attendees
|
registrations.count < max_attendees
|
||||||
end
|
end
|
||||||
|
|
||||||
def voted?(event, user)
|
##
|
||||||
event.votes.where('user_id = ?', user).first
|
# Finds the rating of the user for the event
|
||||||
|
# ====Returns
|
||||||
|
# * +integer+ -> the rating of the user for the event
|
||||||
|
def user_rating(user)
|
||||||
|
(vote = votes.find_by(user: user)) ? vote.rating : 0
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if the event has votes
|
||||||
|
# If a user is provided, it checks if the event has votes by the user
|
||||||
|
# ====Returns
|
||||||
|
# * +true+ -> If the event has votes (optionally, by the user)
|
||||||
|
# * +false+ -> If the event does not have any votes (optionally, by the user)
|
||||||
|
def voted?(user=nil)
|
||||||
|
return votes.where(user: user).any? if user
|
||||||
|
|
||||||
|
votes.any?
|
||||||
end
|
end
|
||||||
|
|
||||||
def average_rating
|
def average_rating
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,58 @@ class Program < ActiveRecord::Base
|
||||||
accepts_nested_attributes_for :difficulty_levels, allow_destroy: true
|
accepts_nested_attributes_for :difficulty_levels, allow_destroy: true
|
||||||
|
|
||||||
# validates :conference_id, presence: true, uniqueness: true
|
# validates :conference_id, presence: true, uniqueness: true
|
||||||
validates :rating, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 10 }
|
validates :rating, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 10, only_integer: true }
|
||||||
|
validate :voting_start_date_before_end_date
|
||||||
|
validate :voting_dates_exist
|
||||||
|
|
||||||
before_create :create_event_types
|
before_create :create_event_types
|
||||||
before_create :create_difficulty_levels
|
before_create :create_difficulty_levels
|
||||||
validate :check_languages_format
|
validate :check_languages_format
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if blind_voting is enabled and if voting period is over
|
||||||
|
# ====Returns
|
||||||
|
# * +true+ -> If we can show voting details
|
||||||
|
# * +false+ -> If we cannot show voting details
|
||||||
|
def show_voting?
|
||||||
|
return true unless blind_voting
|
||||||
|
|
||||||
|
Date.today > voting_end_date
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if we are still in voting period
|
||||||
|
# ====Returns
|
||||||
|
# * +true+ -> If the voting period is not over yet
|
||||||
|
# * +false+ -> If the voting period is over
|
||||||
|
def voting_period?
|
||||||
|
return false unless voting_start_date && voting_end_date
|
||||||
|
|
||||||
|
(voting_start_date.to_datetime..voting_end_date.to_datetime).cover? Time.current
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if both voting_start_date and voting_end_date are set
|
||||||
|
# ====Returns
|
||||||
|
# Errors when the condition is not true
|
||||||
|
def voting_dates_exist
|
||||||
|
errors.add(:voting_start_date, 'must be set, when blind voting is enabled') if blind_voting && !voting_start_date && !voting_end_date
|
||||||
|
|
||||||
|
errors.add(:voting_end_date, 'must be set, when blind voting is enabled') if blind_voting && !voting_start_date && !voting_end_date
|
||||||
|
|
||||||
|
errors.add(:voting_end_date, 'must be set, when voting_start_date is set') if voting_start_date && !voting_end_date
|
||||||
|
|
||||||
|
errors.add(:voting_start_date, 'must be set, when voting_end_date is set') if voting_end_date && !voting_start_date
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Checks if voting_start_date is before voting_end_date
|
||||||
|
# ====Returns
|
||||||
|
# Errors when the condition is not true
|
||||||
|
def voting_start_date_before_end_date
|
||||||
|
errors.add(:voting_start_date, 'must be before voting end date') if voting_start_date && voting_end_date && voting_start_date > voting_end_date
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Checcks if the program has rating enabled
|
# Checcks if the program has rating enabled
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -122,10 +122,13 @@
|
||||||
%td
|
%td
|
||||||
%b Submitter
|
%b Submitter
|
||||||
%td
|
%td
|
||||||
= link_to @event.submitter.name, admin_user_path(@event.submitter)
|
- if @program.show_voting?
|
||||||
(
|
= link_to @event.submitter.name, admin_user_path(@event.submitter)
|
||||||
= link_to @event.submitter.email, "mailto: #{@event.submitter.email}"
|
(
|
||||||
)
|
= link_to @event.submitter.email, "mailto: #{@event.submitter.email}"
|
||||||
|
)
|
||||||
|
- else
|
||||||
|
%i Hidden
|
||||||
%tr
|
%tr
|
||||||
%td
|
%td
|
||||||
%b Biography
|
%b Biography
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,64 @@
|
||||||
%table.table#myrating
|
%table.table#myrating
|
||||||
|
- if @program.show_voting?
|
||||||
|
%tr
|
||||||
|
%td.col-md-2
|
||||||
|
%b Rating
|
||||||
|
%td
|
||||||
|
- if @event.average_rating.to_f > 0
|
||||||
|
#{@event.average_rating}/#{@program.rating}
|
||||||
|
- else
|
||||||
|
Rating: 0/#{@program.rating}
|
||||||
|
|
||||||
|
- @program.rating.times do |counter|
|
||||||
|
- if @event.average_rating.to_f.round == counter+1
|
||||||
|
= label_tag 'label_rating', '', class: 'avgrating', avgrate: true
|
||||||
|
= javascript_tag "$('label[avgrate=true]').prevAll().andSelf().addClass('bright');"
|
||||||
|
- else
|
||||||
|
= label_tag 'label_rating', '', class: 'avgrating'
|
||||||
|
%tr
|
||||||
|
%td
|
||||||
|
%b Voters
|
||||||
|
%td
|
||||||
|
= @event.voters.length
|
||||||
|
- if @event.voters.length > 0
|
||||||
|
(
|
||||||
|
= @ratings.map {|x| "#{x.name}"}.join ', '
|
||||||
|
)
|
||||||
%tr
|
%tr
|
||||||
%td.col-md-2
|
%td.col-md-2
|
||||||
%b Rating
|
|
||||||
%td
|
|
||||||
- if @event.average_rating.to_f > 0
|
|
||||||
#{@event.average_rating}/#{@conference.program.rating}
|
|
||||||
- else
|
|
||||||
Rating: 0/#{@conference.program.rating}
|
|
||||||
|
|
||||||
- @conference.program.rating.times do |counter|
|
|
||||||
- if @event.average_rating.to_f.round == counter+1
|
|
||||||
= label_tag "label_rating", "", :class => "avgrating", :avgrate => true
|
|
||||||
= javascript_tag "$('label[avgrate=true]').prevAll().andSelf().addClass('bright');"
|
|
||||||
- else
|
|
||||||
= label_tag "label_rating", "", :class => "avgrating"
|
|
||||||
%tr
|
|
||||||
%td
|
|
||||||
%b Voters
|
|
||||||
%td
|
|
||||||
= @event.voters.length
|
|
||||||
- if @event.voters.length > 0
|
|
||||||
(
|
|
||||||
= @ratings.map {|x| "#{x.name}"}.join ', '
|
|
||||||
)
|
|
||||||
%tr
|
|
||||||
%td
|
|
||||||
%b Your vote
|
%b Your vote
|
||||||
%td
|
%td
|
||||||
- @conference.program.rating.times do |counter|
|
- if @program.voting_period?
|
||||||
- voted = @event.voted?(@event, current_user)
|
- @program.rating.times do |counter|
|
||||||
- if voted && voted.rating == counter+1
|
- if @event.voted?(current_user) && @event.user_rating(current_user) == counter+1
|
||||||
= link_to "", vote_admin_conference_program_event_path(@conference.short_title, @event, :rating => counter+1), :remote => true, :id =>"label#{counter+1}", :class => "myrating", :voted => true
|
= link_to "", vote_admin_conference_program_event_path(@conference.short_title, @event, :rating => counter+1), :remote => true, :id =>"label#{counter+1}", :class => "myrating", :voted => true
|
||||||
- else
|
- else
|
||||||
= link_to "", vote_admin_conference_program_event_path(@conference.short_title, @event, :rating => counter+1), :remote => true, :id =>"label#{counter+1}", :class => "myrating"
|
= link_to "", vote_admin_conference_program_event_path(@conference.short_title, @event, :rating => counter+1), :remote => true, :id =>"label#{counter+1}", :class => "myrating"
|
||||||
%br
|
%br
|
||||||
|
- else
|
||||||
|
- @conference.program.rating.times do |counter|
|
||||||
|
- if @event.voted?(current_user) && @event.user_rating(current_user) == counter+1
|
||||||
|
= label_tag "label#{counter+1}", '', class: 'othersrating', voted: true
|
||||||
|
= javascript_tag "$('label[voted=true]').prevAll().andSelf().addClass('bright');"
|
||||||
|
- else
|
||||||
|
= label_tag "label#{counter+1}", '', class: 'othersrating'
|
||||||
|
(#{voting_open_or_close(@program)})
|
||||||
|
|
||||||
- if @ratings.length > 0
|
- if @program.show_voting?
|
||||||
- @ratings.each do |rate|
|
- if @ratings.length > 0
|
||||||
- unless rate.user_id == current_user.id
|
- @ratings.each do |rate|
|
||||||
%tr
|
- unless rate.user_id == current_user.id
|
||||||
%td
|
%tr
|
||||||
= rate.name
|
%td
|
||||||
%td
|
= rate.name
|
||||||
- @conference.program.rating.times do |counter|
|
%td
|
||||||
- voted = @event.voted?(@event, rate.user)
|
- @conference.program.rating.times do |counter|
|
||||||
- if voted && voted.rating == counter+1
|
|
||||||
= label_tag "label#{counter+1}", "", :class => "othersrating", :voted => true
|
- if @event.voted?(rate.user) && @event.user_rating(rate.user) == counter+1
|
||||||
= javascript_tag "$('label[voted=true]').prevAll().andSelf().addClass('bright');"
|
= label_tag "label#{counter+1}", "", :class => "othersrating", :voted => true
|
||||||
- else
|
= javascript_tag "$('label[voted=true]').prevAll().andSelf().addClass('bright');"
|
||||||
= label_tag "label#{counter+1}", "", :class => "othersrating"
|
- else
|
||||||
|
= label_tag "label#{counter+1}", "", :class => "othersrating"
|
||||||
:javascript
|
:javascript
|
||||||
$(function () {
|
$(function () {
|
||||||
var checkedId = $("a[voted='true']").attr('id');
|
var checkedId = $("a[voted='true']").attr('id');
|
||||||
|
|
|
||||||
19
app/views/admin/events/_voting_index.html.haml
Normal file
19
app/views/admin/events/_voting_index.html.haml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
- if @program.show_voting?
|
||||||
|
#{event.average_rating}/#{@program.rating}
|
||||||
|
%br
|
||||||
|
#{pluralize(event.voters.length, 'voter')}
|
||||||
|
%br
|
||||||
|
- @program.rating.times do |counter|
|
||||||
|
- if event.average_rating.to_f.round == counter+1
|
||||||
|
= label_tag 'label_rating', '', class: 'avgrating', avgrate: true
|
||||||
|
= javascript_tag "$('label[avgrate=true]').prevAll().andSelf().addClass('bright');"
|
||||||
|
- else
|
||||||
|
= label_tag 'label_rating', '', class: 'avgrating'
|
||||||
|
%br
|
||||||
|
|
||||||
|
- if event.voted?(current_user)
|
||||||
|
%span.label.label-success
|
||||||
|
Your rating: #{ event.user_rating(current_user) }
|
||||||
|
- else
|
||||||
|
%span.label.label-danger
|
||||||
|
Not rated
|
||||||
|
|
@ -50,49 +50,34 @@
|
||||||
%td
|
%td
|
||||||
= event.id
|
= event.id
|
||||||
%td
|
%td
|
||||||
=link_to event.title, admin_conference_program_event_path(@conference.short_title, event)
|
= link_to event.title, admin_conference_program_event_path(@conference.short_title, event)
|
||||||
|
|
||||||
- if @program.rating_enabled?
|
- if @program.rating_enabled?
|
||||||
%td.col-md-1{'data-order' => "#{event.average_rating}"}
|
%td.col-md-1{'data-order' => "#{event.average_rating}"}
|
||||||
- if event.average_rating.to_f > 0
|
= render partial: 'voting_index', locals: { event: event }
|
||||||
#{event.average_rating}/#{@program.rating}
|
|
||||||
%br
|
|
||||||
#{pluralize(event.voters.length, 'voter')}
|
|
||||||
%br
|
|
||||||
- @program.rating.times do |counter|
|
|
||||||
- if event.average_rating.to_f.round == counter+1
|
|
||||||
= label_tag "label_rating", "", :class => "avgrating", :avgrate => true
|
|
||||||
= javascript_tag "$('label[avgrate=true]').prevAll().andSelf().addClass('bright');"
|
|
||||||
- else
|
|
||||||
= label_tag "label_rating", "", :class => "avgrating"
|
|
||||||
%br
|
|
||||||
- voted = event.voted?(event, current_user)
|
|
||||||
- if voted
|
|
||||||
%span.label.label-success
|
|
||||||
Your rating: #{voted.rating}
|
|
||||||
- else
|
|
||||||
%span.label.label-danger
|
|
||||||
Not rated
|
|
||||||
- else
|
|
||||||
0/#{@program.rating}
|
|
||||||
%br
|
|
||||||
|
|
||||||
- if event.submitter && event.submitter.registrations && event.submitter.registrations.count < 1
|
- if event.submitter && event.submitter.registrations && event.submitter.registrations.count < 1
|
||||||
- bgcolor="#F7819F"
|
- bgcolor="#F7819F"
|
||||||
- else
|
- else
|
||||||
- bgcolor=""
|
- bgcolor=""
|
||||||
%td{:style=>"background-color: #{bgcolor}"}
|
%td{:style=>"background-color: #{bgcolor}"}
|
||||||
- if !event.submitter.nil?
|
- if @program.show_voting?
|
||||||
=link_to event.submitter.name, admin_user_path(event.submitter)
|
- if !event.submitter.nil?
|
||||||
- if event.submitter.registrations.count < 1
|
=link_to event.submitter.name, admin_user_path(event.submitter)
|
||||||
(Unregistered!)
|
- if event.submitter.registrations.count < 1
|
||||||
|
(Unregistered!)
|
||||||
|
- else
|
||||||
|
Unknown submitter
|
||||||
- else
|
- else
|
||||||
Unknown submitter
|
%i Hidden
|
||||||
%td
|
%td
|
||||||
- if speaker = event.speakers.first
|
- if @program.show_voting?
|
||||||
= link_to speaker.name, admin_user_path(speaker)
|
- if speaker = event.speakers.first
|
||||||
|
= link_to speaker.name, admin_user_path(speaker)
|
||||||
|
- else
|
||||||
|
Unknown speaker
|
||||||
- else
|
- else
|
||||||
Unknown speaker
|
%i Hidden
|
||||||
|
|
||||||
-if @program.languages.present?
|
-if @program.languages.present?
|
||||||
%td
|
%td
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,8 @@
|
||||||
= f.input :schedule_fluid, label: "Allow submitters to change their event after it is scheduled"
|
= f.input :schedule_fluid, label: "Allow submitters to change their event after it is scheduled"
|
||||||
= f.input :rating, hint: 'Enter the number of different rating levels you want to have for voting on proposals. Enter 0 if you do not want to vote on proposals.'
|
= f.input :rating, hint: 'Enter the number of different rating levels you want to have for voting on proposals. Enter 0 if you do not want to vote on proposals.'
|
||||||
= f.input :languages, hint: "Enter the languages allowed for events as values of #{link_to('ISO 639-1', 'http://www.loc.gov/standards/iso639-2/php/code_list.php', target: "_blank")} language codes separated with commas. The first language would be the default language. Leave it blank if you do not want to specify languages.".html_safe
|
= f.input :languages, hint: "Enter the languages allowed for events as values of #{link_to('ISO 639-1', 'http://www.loc.gov/standards/iso639-2/php/code_list.php', target: "_blank")} language codes separated with commas. The first language would be the default language. Leave it blank if you do not want to specify languages.".html_safe
|
||||||
|
= f.input :blind_voting, hint: 'Enable this feature if you do not want to show voting results and voters prior to user submitting a vote. For the feature to work you need to set the voting dates below as well'
|
||||||
|
= f.input :voting_start_date, as: :string, input_html: { id: 'datetimepicker-voting_start_date', readonly: true, value: (f.object.voting_start_date.to_formatted_s(:db_without_seconds) unless f.object.voting_start_date.nil?) }
|
||||||
|
= f.input :voting_end_date, as: :string, input_html: { id: 'datetimepicker-voting_start_date', readonly: true, value: (f.object.voting_end_date.to_formatted_s(:db_without_seconds) unless f.object.voting_end_date.nil?) }
|
||||||
%p.text-right
|
%p.text-right
|
||||||
= f.action :submit, as: :button, button_html: {class: 'btn btn-primary'}
|
= f.action :submit, as: :button, button_html: {class: 'btn btn-primary'}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
%h1 Program
|
%h1 Program
|
||||||
- if @program
|
- if @program
|
||||||
.row
|
.row
|
||||||
.col-md-8
|
.col-md-12
|
||||||
%dl.dl-horizontal
|
%dl.dl-horizontal
|
||||||
- if @cfp
|
- if @cfp
|
||||||
%dt
|
%dt
|
||||||
|
|
@ -49,11 +49,23 @@
|
||||||
Yes
|
Yes
|
||||||
- else
|
- else
|
||||||
No
|
No
|
||||||
|
|
||||||
|
%h3 Voting Options
|
||||||
|
%hr
|
||||||
%dt
|
%dt
|
||||||
Rating Levels
|
Rating Levels
|
||||||
%dd#rating
|
%dd#rating
|
||||||
= @program.rating
|
= @program.rating
|
||||||
|
|
||||||
|
%dt Blind Voting
|
||||||
|
%dd#blind_voting
|
||||||
|
= @program.blind_voting
|
||||||
|
|
||||||
|
%dt Voting Start Date
|
||||||
|
%dd= format_datetime(@program.voting_start_date)
|
||||||
|
|
||||||
|
%dt Voting End Date
|
||||||
|
%dd= format_datetime(@program.voting_end_date)
|
||||||
|
|
||||||
.row
|
.row
|
||||||
.col-md-12.text-right
|
.col-md-12.text-right
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddBlindVotingToPrograms < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :programs, :blind_voting, :boolean, default: false
|
||||||
|
end
|
||||||
|
end
|
||||||
6
db/migrate/20160427104238_add_voting_dates_to_program.rb
Normal file
6
db/migrate/20160427104238_add_voting_dates_to_program.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
class AddVotingDatesToProgram < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :programs, :voting_start_date, :datetime
|
||||||
|
add_column :programs, :voting_end_date, :datetime
|
||||||
|
end
|
||||||
|
end
|
||||||
27
db/schema.rb
27
db/schema.rb
|
|
@ -80,23 +80,23 @@ ActiveRecord::Schema.define(version: 20160624151257) do
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "conferences", force: :cascade do |t|
|
create_table "conferences", force: :cascade do |t|
|
||||||
t.string "guid", null: false
|
t.string "guid", null: false
|
||||||
t.string "title", null: false
|
t.string "title", null: false
|
||||||
t.string "short_title", null: false
|
t.string "short_title", null: false
|
||||||
t.string "timezone", null: false
|
t.string "timezone", null: false
|
||||||
t.date "start_date", null: false
|
t.date "start_date", null: false
|
||||||
t.date "end_date", null: false
|
t.date "end_date", null: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "logo_file_name"
|
t.string "logo_file_name"
|
||||||
t.integer "revision"
|
t.integer "revision"
|
||||||
t.boolean "use_vpositions", default: false
|
t.boolean "use_vpositions", default: false
|
||||||
t.boolean "use_vdays", default: false
|
t.boolean "use_vdays", default: false
|
||||||
t.boolean "use_volunteers"
|
t.boolean "use_volunteers"
|
||||||
t.string "color"
|
t.string "color"
|
||||||
t.text "events_per_week"
|
t.text "events_per_week"
|
||||||
t.text "description"
|
t.text "description"
|
||||||
t.integer "registration_limit", default: 0
|
t.integer "registration_limit", default: 0
|
||||||
t.string "picture"
|
t.string "picture"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -252,12 +252,15 @@ ActiveRecord::Schema.define(version: 20160624151257) do
|
||||||
|
|
||||||
create_table "programs", force: :cascade do |t|
|
create_table "programs", force: :cascade do |t|
|
||||||
t.integer "conference_id"
|
t.integer "conference_id"
|
||||||
t.integer "rating", default: 0
|
t.integer "rating", default: 0
|
||||||
t.boolean "schedule_public", default: false
|
t.boolean "schedule_public", default: false
|
||||||
t.boolean "schedule_fluid", default: false
|
t.boolean "schedule_fluid", default: false
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.datetime "updated_at"
|
t.datetime "updated_at"
|
||||||
t.string "languages"
|
t.string "languages"
|
||||||
|
t.boolean "blind_voting", default: false
|
||||||
|
t.datetime "voting_start_date"
|
||||||
|
t.datetime "voting_end_date"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "qanswers", force: :cascade do |t|
|
create_table "qanswers", force: :cascade do |t|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,17 @@ describe ApplicationHelper, type: :helper do
|
||||||
let(:conference) { create(:conference) }
|
let(:conference) { create(:conference) }
|
||||||
let(:event) { create(:event, program: conference.program) }
|
let(:event) { create(:event, program: conference.program) }
|
||||||
|
|
||||||
|
describe 'format_datetme' do
|
||||||
|
it 'returns nothing if there is no parameter' do
|
||||||
|
expect(format_datetime(nil)).to eq nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns formatted string' do
|
||||||
|
datetime = Time.zone.local(2016, 05, 04, 11, 30)
|
||||||
|
expect(format_datetime(datetime)).to eq '2016-05-04 11:30'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'show_roles' do
|
describe 'show_roles' do
|
||||||
it 'formats the hash passed' do
|
it 'formats the hash passed' do
|
||||||
roles = { 'organizer' => ['oSC16', 'oSC15'], 'cfp' => ['oSC16'] }
|
roles = { 'organizer' => ['oSC16', 'oSC15'], 'cfp' => ['oSC16'] }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ describe Event do
|
||||||
let(:event) { create(:event, program: conference.program) }
|
let(:event) { create(:event, program: conference.program) }
|
||||||
let(:new_event) { create(:event) }
|
let(:new_event) { create(:event) }
|
||||||
let(:user) { create(:user) }
|
let(:user) { create(:user) }
|
||||||
|
let(:another_user) { create(:user) }
|
||||||
|
|
||||||
describe 'association' do
|
describe 'association' do
|
||||||
it { is_expected.to belong_to :program }
|
it { is_expected.to belong_to :program }
|
||||||
|
|
@ -166,14 +167,41 @@ describe Event do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#voted?' do
|
describe '#user_rating' do
|
||||||
it 'returns nil if the event has no votes' do
|
it 'returns 0 if the event has no votes' do
|
||||||
expect(event.voted?(event, user)).to eq nil
|
expect(event.user_rating(user)).to eq 0
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the first vote when the event has votes' do
|
it 'returns 0 if the event has no votes from that user' do
|
||||||
vote = create(:vote, user: user, event: event)
|
create(:vote, user: another_user, event: event)
|
||||||
expect(event.voted?(event, user)).to eq vote
|
expect(event.user_rating(user)).to eq 0
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the rating if the event has votes from that user' do
|
||||||
|
create(:vote, user: another_user, event: event, rating: 3)
|
||||||
|
create(:vote, user: user, event: event, rating: 2)
|
||||||
|
expect(event.user_rating(user)).to eq 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#voted?' do
|
||||||
|
it 'returns false if the event has no votes' do
|
||||||
|
expect(event.voted?).to eq false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if the event has no votes by that user' do
|
||||||
|
create(:vote, user: another_user, event: event)
|
||||||
|
expect(event.voted?(user)).to eq false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true when the event has votes' do
|
||||||
|
create(:vote, user: another_user, event: event)
|
||||||
|
expect(event.voted?).to eq true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true when the event has votes by that user' do
|
||||||
|
create(:vote, user: user, event: event)
|
||||||
|
expect(event.voted?(user)).to eq true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,116 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Program do
|
describe Program do
|
||||||
|
subject { create(:program) }
|
||||||
let!(:conference) { create(:conference, end_date: Date.today + 3) }
|
let!(:conference) { create(:conference, end_date: Date.today + 3) }
|
||||||
let!(:program) { conference.program }
|
let!(:program) { conference.program }
|
||||||
|
|
||||||
|
describe 'association' do
|
||||||
|
it { is_expected.to belong_to :conference }
|
||||||
|
it { is_expected.to have_one(:cfp).dependent(:destroy) }
|
||||||
|
it { is_expected.to have_many(:event_types).dependent(:destroy) }
|
||||||
|
it { is_expected.to have_many(:tracks).dependent(:destroy) }
|
||||||
|
it { is_expected.to have_many(:difficulty_levels).dependent(:destroy) }
|
||||||
|
it { is_expected.to have_many(:events).dependent(:destroy) }
|
||||||
|
it { is_expected.to have_many(:event_users).through(:events) }
|
||||||
|
it { is_expected.to have_many(:speakers).through(:event_users).source(:user) }
|
||||||
|
|
||||||
|
it { is_expected.to accept_nested_attributes_for(:event_types) }
|
||||||
|
it { is_expected.to accept_nested_attributes_for(:tracks) }
|
||||||
|
it { is_expected.to accept_nested_attributes_for(:difficulty_levels) }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'validation' do
|
||||||
|
it 'has a valid factory' do
|
||||||
|
expect(build(:program)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is valid for rating of 5' do
|
||||||
|
expect(build(:program, rating: 5)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to validate_numericality_of(:rating).is_greater_than_or_equal_to(0).is_less_than_or_equal_to(10).only_integer }
|
||||||
|
|
||||||
|
describe 'voting_start_date_before_end_date' do
|
||||||
|
it 'is valid, when voting_start_date is the same day as voting_end_date' do
|
||||||
|
expect(build(:program, voting_start_date: Date.today, voting_end_date: Date.today)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is valid, when voting_start_date is before voting_end_date' do
|
||||||
|
expect(build(:program, voting_start_date: Date.today, voting_end_date: Date.today + 1)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is not valid, when voting_start_date is after voting_end_date' do
|
||||||
|
expect(build(:program, voting_start_date: Date.today, voting_end_date: Date.today - 1)).to_not be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'voting_dates_exist' do
|
||||||
|
it 'is valid, when both voting_start_date and voting_end_date are set' do
|
||||||
|
expect(build(:program, voting_start_date: Date.today, voting_end_date: Date.today + 1)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid, when voting_start_date is not set' do
|
||||||
|
expect(build(:program, voting_end_date: Date.today)).to_not be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is invalid, when voting_end_date is not set' do
|
||||||
|
expect(build(:program, voting_start_date: Date.today)).to_not be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#show_voting?' do
|
||||||
|
context 'blind voting is disabled' do
|
||||||
|
before :each do
|
||||||
|
program.blind_voting = false
|
||||||
|
end
|
||||||
|
it 'returns true if blind_voting is disabled' do
|
||||||
|
program.blind_voting = false
|
||||||
|
expect(program.show_voting?).to eq true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'blind voting is enabled' do
|
||||||
|
before :each do
|
||||||
|
program.blind_voting = true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true if voting period is over' do
|
||||||
|
program.voting_end_date = Date.today - 1
|
||||||
|
expect(program.show_voting?).to eq true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns false if we are still in votig period' do
|
||||||
|
program.voting_end_date = Date.today + 1
|
||||||
|
expect(program.show_voting?).to eq false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'voting_period?' do
|
||||||
|
it 'retuns false when voting dates are not set' do
|
||||||
|
expect(program.voting_period?).to eq false
|
||||||
|
end
|
||||||
|
|
||||||
|
shared_examples 'voting period' do |voting_start_date, voting_end_date, returns|
|
||||||
|
scenario 'returns true or false' do
|
||||||
|
program.voting_start_date = voting_start_date
|
||||||
|
program.voting_end_date = voting_end_date
|
||||||
|
program.save!
|
||||||
|
|
||||||
|
expect(program.voting_period?).to eq returns
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'voting dates are set' do
|
||||||
|
it_behaves_like 'voting period', Date.today - 1, Date.today + 1, true
|
||||||
|
it_behaves_like 'voting period', Date.today - 1, Time.current + 1.hour, true
|
||||||
|
it_behaves_like 'voting period', Date.today - 2, Date.today - 1, false
|
||||||
|
it_behaves_like 'voting period', Date.today - 1, Time.current - 1.minute, false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#rating_enabled?' do
|
describe '#rating_enabled?' do
|
||||||
it 'returns true if proposals can be rated (program.rating > 0)' do
|
it 'returns true if proposals can be rated (program.rating > 0)' do
|
||||||
program.rating = 3
|
program.rating = 3
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue