Intial event conflicts implementation
This commit is contained in:
parent
bb663ce853
commit
bcef815c08
|
@ -4,4 +4,5 @@
|
|||
//= require bootstrap-sprockets
|
||||
//= require raphael
|
||||
//= require morris
|
||||
//= require chroma-js/chroma
|
||||
//= require_directory .
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
conflictsScale=chroma.scale(['#469408', '#D9230F']).mode('lab');
|
||||
|
||||
$ ->
|
||||
$('.cfp-toggle').click ->
|
||||
$(this).addClass("disabled")
|
||||
if $('#submissions-chart').length > 0
|
||||
Morris.Line
|
||||
element: 'submissions-chart'
|
||||
data: $('#submissions-chart').data('submissions')
|
||||
|
@ -9,3 +12,9 @@ $ ->
|
|||
labels: ['Submissions', 'Confirmed submissions']
|
||||
lineColors: ['#D9230F', '#469408']
|
||||
resize: true
|
||||
$('[data-conflicts]').each (e) ->
|
||||
most_conflicts = parseInt($(this).data('most-conflicts'))
|
||||
conflicts = parseInt($(this).data('conflicts'))
|
||||
least_conflicts = parseInt($(this).data('least-conflicts'))
|
||||
console.log 1.0 * (conflicts - least_conflicts) / (most_conflicts - least_conflicts)
|
||||
$(this).css('background-color', conflictsScale(1.0 * (conflicts - least_conflicts) / (most_conflicts - least_conflicts)))
|
||||
|
|
|
@ -9,7 +9,7 @@ module EventsHelper
|
|||
link_to icon('user-plus', participant.email),
|
||||
new_management_conference_personal_profile_path(conference_id: event.conference.id,
|
||||
user_id: participant.id),
|
||||
title: t('.create_profile'), class: 'bg-danger'
|
||||
title: t('management.events.event.create_profile'), class: 'bg-danger'
|
||||
end
|
||||
end.join(', ').html_safe
|
||||
end
|
||||
|
|
|
@ -14,6 +14,9 @@ class Conference < ActiveRecord::Base
|
|||
has_many :halls
|
||||
has_many :event_types
|
||||
has_many :events
|
||||
has_many :approved_events,
|
||||
-> { joins(:proposition).where(propositions: {status: Proposition.statuses[:approved]}) }, class_name: 'Event'
|
||||
has_many :conflict_counts, through: :events
|
||||
has_many :volunteer_teams
|
||||
has_many :volunteers
|
||||
has_one :call_for_participation, dependent: :destroy
|
||||
|
@ -48,6 +51,28 @@ class Conference < ActiveRecord::Base
|
|||
vote_data_endpoint.present?
|
||||
end
|
||||
|
||||
def update_conflict_data!
|
||||
update_vote_data! or raise ActiveRecord::Rollback
|
||||
events.all? { |event| event.update_conflict_data(false) } or raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
def most_conflicts
|
||||
conflict_counts.order(number_of_conflicts: :desc).first.try(:number_of_conflicts) || 0
|
||||
end
|
||||
|
||||
def least_conflicts
|
||||
conflict_counts.unscoped.order(number_of_conflicts: :asc).first.try(:number_of_conflicts) || 0
|
||||
end
|
||||
|
||||
def most_conflicts_between_approved_events
|
||||
conflict_counts.unscoped.where(left: approved_events, right: approved_events).order(number_of_conflicts: :desc).first.try(:number_of_conflicts) || 0
|
||||
end
|
||||
|
||||
def least_conflicts_between_approved_events
|
||||
conflict_counts.unscoped.where(left: approved_events, right: approved_events).order(number_of_conflicts: :asc).first.try(:number_of_conflicts) || 0
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def planned_cfp_end_date_is_before_start_date
|
||||
|
@ -75,9 +100,14 @@ class Conference < ActiveRecord::Base
|
|||
@ranking ||= remote_summary_data['ranking'].map { |ranking_entry| EventRanking.new ranking_entry }
|
||||
end
|
||||
|
||||
def conflicts
|
||||
@conflicts ||= remote_summary_data['conflicts'].map { |conflicts_entry| ConflictsForEvent.new conflicts_entry }
|
||||
end
|
||||
|
||||
def save
|
||||
conference.transaction do
|
||||
conference.number_of_ballots_cast = number_of_ballots
|
||||
conflicts.all?(&:save) or raise ActiveRecord::Rollback
|
||||
ranking.all?(&:save) or raise ActiveRecord::Rollback
|
||||
conference.touch :vote_data_updated_at
|
||||
conference.save or raise ActiveRecord::Rollback
|
||||
|
@ -97,13 +127,28 @@ class Conference < ActiveRecord::Base
|
|||
end.body)
|
||||
end
|
||||
|
||||
class ConflictsForEvent
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :talk_id, :conflicts
|
||||
|
||||
def save
|
||||
@event = Event.find(talk_id)
|
||||
@event.conflict_counts.destroy_all or raise ActiveRecord::Rollback
|
||||
conflicts.all? do |right_event_id, number_of_conflicts|
|
||||
ConflictCount.create left_id: talk_id, right_id: right_event_id, number_of_conflicts: number_of_conflicts
|
||||
end or raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class EventRanking
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_accessor :talk_id, :votes, :place
|
||||
|
||||
def save
|
||||
Event.find(talk_id).update(number_of_votes: votes, rank: place)
|
||||
Event.where(id: talk_id).update_all(number_of_votes: votes, rank: place)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class ConflictCount < ActiveRecord::Base
|
||||
belongs_to :left, class_name: 'Event'
|
||||
belongs_to :right, class_name: 'Event'
|
||||
has_one :conference, through: :left
|
||||
end
|
|
@ -9,6 +9,7 @@ class Event < ActiveRecord::Base
|
|||
has_many :pending_participations, ->() { pending }, class_name: 'Participation'
|
||||
has_many :approved_participations, ->() { approved }, class_name: 'Participation'
|
||||
has_many :participants, through: :approved_participations
|
||||
has_many :conflict_counts, -> { order(number_of_conflicts: :desc) }, foreign_key: :left_id
|
||||
|
||||
belongs_to :event_type
|
||||
|
||||
|
|
|
@ -64,3 +64,51 @@
|
|||
.col-xs-12
|
||||
h3 = Event.human_attribute_name :participants
|
||||
= render partial: 'speaker', collection: @event.participants
|
||||
|
||||
- if @conference.has_vote_results? or @conference.has_voting_endpoint?
|
||||
.row
|
||||
.col-xs-12
|
||||
h2
|
||||
= t '.conflicts'
|
||||
small< = t '.between_approved_events'
|
||||
.panel.panel-default
|
||||
table.table.table-striped.table-hover.record-table
|
||||
- if @conference.has_vote_results? and @conference.approved_events.count > 2
|
||||
thead
|
||||
tr
|
||||
th.text-right
|
||||
= t '.percent'
|
||||
th
|
||||
= Event.model_name.human.mb_chars.capitalize
|
||||
th
|
||||
tbody
|
||||
- if @conference.has_vote_results?
|
||||
- if @conference.approved_events.count > 2
|
||||
- @event.conflict_counts.where(right_id: @conference.approved_events.pluck(:id)).includes(:right).each do |conflict_count|
|
||||
- conflict_percent = Rational(conflict_count.number_of_conflicts, @conference.number_of_ballots_cast)
|
||||
tr
|
||||
td.text-right
|
||||
.large
|
||||
span.label.label-success data-conflicts="#{conflict_count.number_of_conflicts}" data-most-conflicts="#{@conference.most_conflicts_between_approved_events}" data-least-conflicts="#{@conference.least_conflicts_between_approved_events}"
|
||||
= number_to_percentage(conflict_percent * 100, strip_insignificant_zeros: true, precision: 2)
|
||||
td
|
||||
h4 = conflict_count.right.title
|
||||
h5 = conflict_count.right.subtitle
|
||||
= links_to_event_participants_for(conflict_count.right)
|
||||
|
||||
td.actions
|
||||
= action_buttons @conference, conflict_count.right, [:show]
|
||||
- else
|
||||
tr
|
||||
td colspan="20"
|
||||
= t '.no_approved_events'
|
||||
- else
|
||||
tr
|
||||
td colspan="20"
|
||||
= t 'management.conferences.vote_results.vote_data_never_updated'
|
||||
= icon :refresh, t('management.conferences.vote_results.fetch_vote_results')
|
||||
- if @conference.has_vote_results?
|
||||
.panel-footer.text-right
|
||||
.btn-group
|
||||
= link_to update_vote_data_management_conference_path(@conference), method: :patch, class: ['btn', 'btn-primary'] do
|
||||
= icon :refresh, t('management.conferences.vote_results.fetch_vote_results')
|
||||
|
|
|
@ -51,8 +51,12 @@ bg:
|
|||
previous_event_propositions: 'Предишни предложения за събития'
|
||||
contacts: "Информация за контакт"
|
||||
show:
|
||||
between_approved_events: "Между одобрени събития"
|
||||
no_approved_events: "Няма достатъчно одобрени събития"
|
||||
rank: "Класиране"
|
||||
review: "Преглед на %{event_type} „%{event_title}“"
|
||||
conflicts: "Конфликти"
|
||||
percent: "Процент"
|
||||
index:
|
||||
all: "Всички"
|
||||
total: "%{current} от общо %{total}"
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
class CreateConflictCounts < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :conflict_counts do |t|
|
||||
t.references :left, index: true
|
||||
t.references :right, index: true
|
||||
t.integer :number_of_conflicts
|
||||
end
|
||||
|
||||
add_index :conflict_counts, [:left_id, :right_id], unique: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
chroma.js - JavaScript library for color conversions
|
||||
|
||||
Copyright (c) 2011-2015, Gregor Aisch
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name Gregor Aisch may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
chroma.js includes colors from colorbrewer2.org,
|
||||
which are released under the following license:
|
||||
|
||||
|
||||
Copyright (c) 2002 Cynthia Brewer, Mark Harrower,
|
||||
and The Pennsylvania State University.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
either express or implied. See the License for the specific
|
||||
language governing permissions and limitations under the License.
|
||||
|
||||
|
||||
Named colors are taken from X11 Color Names.
|
||||
http://www.w3.org/TR/css3-color/#svg-color
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue