mirror of
https://github.com/openSUSE/osem.git
synced 2026-08-13 19:54:02 +00:00
Use chartkick globally
* Clean up legacy charting imports * Update existing donut and line charts * Create helpers for parsing out existing chart data * Move chart partials to a more common path
This commit is contained in:
parent
3bbac3667f
commit
516e53d9df
29 changed files with 331 additions and 577 deletions
1
Gemfile
1
Gemfile
|
|
@ -128,7 +128,6 @@ gem 'ajax-datatables-rails'
|
|||
gem 'jquery-datatables-rails'
|
||||
|
||||
# for charts
|
||||
gem 'chart-js-rails'
|
||||
gem 'chartkick'
|
||||
|
||||
# for displaying maps
|
||||
|
|
|
|||
|
|
@ -111,8 +111,6 @@ GEM
|
|||
fastimage
|
||||
case_transform (0.2)
|
||||
activesupport
|
||||
chart-js-rails (0.1.6)
|
||||
railties (> 3.1)
|
||||
chartkick (3.0.1)
|
||||
childprocess (0.9.0)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
|
|
@ -633,7 +631,6 @@ DEPENDENCIES
|
|||
capybara
|
||||
carrierwave
|
||||
carrierwave-bombshelter
|
||||
chart-js-rails
|
||||
chartkick
|
||||
chromedriver-helper
|
||||
climate_control
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@
|
|||
//= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
|
||||
//= require cocoon
|
||||
//= require bootstrap
|
||||
//= require Chart.bundle
|
||||
//= require chartkick
|
||||
//= require osem
|
||||
//= require osem-dashboard
|
||||
//= require jquery-smooth-scroll
|
||||
//= require trianglify
|
||||
//= require tinycolor
|
||||
|
|
|
|||
|
|
@ -1,146 +0,0 @@
|
|||
$(function() {
|
||||
var t;
|
||||
function size(animate){
|
||||
if (animate == undefined){
|
||||
animate = false;
|
||||
}
|
||||
clearTimeout(t);
|
||||
t = setTimeout(function(){
|
||||
$("canvas").each(function(i,el){
|
||||
$(el).attr({
|
||||
"width":$(el).parent().width()
|
||||
});
|
||||
});
|
||||
|
||||
$(".line_chart").each(function(){
|
||||
draw_line_chart(animate, $(this));
|
||||
});
|
||||
|
||||
$(".doughnut_chart").each(function(){
|
||||
if($(this).is(":visible")){
|
||||
draw_doughnut_chart(animate, $(this));
|
||||
}
|
||||
});
|
||||
|
||||
}, 30);
|
||||
}
|
||||
|
||||
function draw_doughnut_chart(animation, $this){
|
||||
var options = get_animation({}, animation);
|
||||
var tmp = $this.data('chart');
|
||||
|
||||
if(jQuery.isEmptyObject(tmp)){
|
||||
// Append error message if there is no data
|
||||
$this.parent().append("<h4 class=\"text-warning\">No data!</h4>");
|
||||
// Remove canvas
|
||||
$this.remove();
|
||||
}else{
|
||||
var data = [];
|
||||
for (var key in tmp) {
|
||||
data.push(tmp[key]);
|
||||
}
|
||||
|
||||
var ctx = $this.get(0).getContext("2d");
|
||||
new Chart(ctx).Doughnut(data, options);
|
||||
}
|
||||
}
|
||||
|
||||
function get_animation(options, animation){
|
||||
if (!animation){
|
||||
options.animation = false;
|
||||
} else {
|
||||
options.animation = true;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function draw_line_chart(animation, $canvas){
|
||||
var chart_data = create_dataset($canvas);
|
||||
var weeks = $canvas.parent().data('weeks');
|
||||
var data = {
|
||||
labels : weeks,
|
||||
datasets : chart_data
|
||||
}
|
||||
|
||||
var options = get_animation(wholeNumberAxisFix(data), animation);
|
||||
var ctx = $canvas.get(0).getContext("2d");
|
||||
new Chart(ctx).Line(data, options);
|
||||
}
|
||||
|
||||
function wholeNumberAxisFix(data){
|
||||
var maxValue = false;
|
||||
for(datasetIndex = 0; datasetIndex < data.datasets.length; ++datasetIndex){
|
||||
var setMax = Math.max.apply(null, data.datasets[datasetIndex].data);
|
||||
if (maxValue === false || setMax > maxValue) maxValue = setMax;
|
||||
}
|
||||
|
||||
var steps = maxValue;
|
||||
var stepWidth = 1;
|
||||
if (maxValue > 10) {
|
||||
stepWidth = Math.floor(maxValue / 10);
|
||||
steps = Math.ceil(maxValue / stepWidth);
|
||||
}
|
||||
return { scaleOverride: true, scaleSteps: steps, scaleStepWidth: stepWidth, scaleStartValue: 0 };
|
||||
}
|
||||
|
||||
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){
|
||||
if(selected.indexOf(conferences[i].short_title) >= 0){
|
||||
var options = {};
|
||||
options.fillColor = "rgba(255,255,255,0.0)";
|
||||
options.strokeColor = conferences[i].color;
|
||||
options.data = chart_data[conferences[i].short_title];
|
||||
if(options.data == null || options.data.length == 0){
|
||||
options.data = [0];
|
||||
}
|
||||
result.push(options)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function getSelectedConferences($canvas){
|
||||
var name = $canvas.data('name');
|
||||
var id = '#' + name + 'Checkboxes'
|
||||
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_name = $(this).parent().data('chart');
|
||||
var $canvas = $('#line_chart_' + chart_name);
|
||||
draw_line_chart(false, $canvas);
|
||||
});
|
||||
|
||||
$(window).on('resize', function(){
|
||||
size(false);
|
||||
});
|
||||
|
||||
$('#doughnut_tabs a').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).tab('show');
|
||||
size(false);
|
||||
});
|
||||
|
||||
size(true);
|
||||
});
|
||||
|
|
@ -37,43 +37,33 @@ module Admin
|
|||
|
||||
@top_submitter = Conference.get_top_submitter
|
||||
|
||||
@submissions = {}
|
||||
@cfp_weeks = [0]
|
||||
|
||||
@registrations = {}
|
||||
@registration_weeks = [0]
|
||||
|
||||
@tickets = {}
|
||||
@ticket_weeks = [0]
|
||||
@registrations = []
|
||||
@submissions = []
|
||||
@tickets = []
|
||||
|
||||
@conferences.each do |c|
|
||||
# Event submissions over time chart
|
||||
@submissions[c.short_title] = c.get_submissions_per_week
|
||||
@cfp_weeks.push(@submissions[c.short_title].length)
|
||||
|
||||
# Conference registrations over time chart
|
||||
@registrations[c.short_title] = c.get_registrations_per_week
|
||||
@registration_weeks.push(@registrations[c.short_title].length)
|
||||
|
||||
@registrations << {
|
||||
name: c.short_title,
|
||||
data: c.get_registrations_per_week
|
||||
}
|
||||
# Event submissions over time chart
|
||||
@submissions << {
|
||||
name: c.short_title,
|
||||
data: c.get_submissions_per_week
|
||||
}
|
||||
# Tickets sold over time chart
|
||||
@tickets[c.short_title] = c.get_tickets_sold_per_week
|
||||
@ticket_weeks.push(@tickets[c.short_title].length)
|
||||
@tickets << {
|
||||
name: c.short_title,
|
||||
data: c.get_tickets_sold_per_week
|
||||
}
|
||||
end
|
||||
|
||||
@cfp_weeks = @cfp_weeks.max
|
||||
@submissions = normalize_array_length(@submissions, @cfp_weeks)
|
||||
@cfp_weeks = @cfp_weeks > 0 ? (1..@cfp_weeks).to_a : 1
|
||||
|
||||
@registration_weeks = @registration_weeks.max
|
||||
@registrations = normalize_array_length(@registrations, @registration_weeks)
|
||||
@registration_weeks = @registration_weeks > 0 ? (1..@registration_weeks).to_a : 1
|
||||
|
||||
@ticket_weeks = @ticket_weeks.max
|
||||
@tickets = normalize_array_length(@tickets, @ticket_weeks)
|
||||
@ticket_weeks = @ticket_weeks > 0 ? (1..@ticket_weeks).to_a : 1
|
||||
|
||||
@event_distribution = Conference.event_distribution
|
||||
@user_distribution = Conference.user_distribution
|
||||
@event_distribution_colors = Event::COLORS.values
|
||||
|
||||
@user_distribution = User.distribution
|
||||
@user_distribution_colors = User::DISTRIBUTION_COLORS.values
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
@ -138,35 +128,9 @@ module Admin
|
|||
@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 = @conference.get_submissions_data
|
||||
@cfp_weeks = 0
|
||||
if @submissions_data['Weeks']
|
||||
@cfp_weeks = @submissions_data['Weeks']
|
||||
@submissions_data = @submissions_data.except('Weeks')
|
||||
end
|
||||
|
||||
@tickets_data = @conference.get_tickets_data
|
||||
@ticket_weeks = 0
|
||||
if @tickets_data['Weeks']
|
||||
@ticket_weeks = @tickets_data['Weeks']
|
||||
@tickets_data = @tickets_data.except('Weeks')
|
||||
end
|
||||
|
||||
# Set line color using a hash function
|
||||
@tickets = []
|
||||
@tickets_data.each_key do |title|
|
||||
@tickets.append(short_title: title, color: "\##{Digest::MD5.hexdigest(title)[0..5]}")
|
||||
end
|
||||
@registrations = @conference.get_registrations_per_week
|
||||
@submissions = @conference.get_submissions_data
|
||||
@tickets = @conference.get_tickets_data
|
||||
|
||||
# Doughnut charts
|
||||
@event_type_distribution = @conference.event_type_distribution
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ module Admin
|
|||
@event_types = @program.event_types
|
||||
@tracks_distribution_confirmed = @conference.tracks_distribution(:confirmed)
|
||||
@event_distribution = @conference.event_distribution
|
||||
@event_distribution_colors = Event::COLORS.values
|
||||
@scheduled_event_distribution = @conference.scheduled_event_distribution
|
||||
@file_name = "events_for_#{@conference.short_title}"
|
||||
@event_export_option = params[:event_export_option]
|
||||
|
|
|
|||
17
app/helpers/chart_helper.rb
Normal file
17
app/helpers/chart_helper.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ChartHelper
|
||||
def chart_values(distribution_hash)
|
||||
Hash[
|
||||
distribution_hash.collect do |key, data|
|
||||
[key, data['value']]
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
def chart_colors(distribution_hash)
|
||||
distribution_hash.collect do |_key, data|
|
||||
data['color']
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -176,24 +176,22 @@ class Conference < ApplicationRecord
|
|||
# ====Returns
|
||||
# * +Array+ -> e.g. 'Submitted' => [0, 3, 3, 5] -> first week 0 events, second week 3 events.
|
||||
def get_submissions_data
|
||||
result = {}
|
||||
if program&.cfp && program&.events
|
||||
result = get_events_per_week_by_state
|
||||
return [] unless program&.cfp && program&.events
|
||||
|
||||
start_week = program.cfp.start_week
|
||||
end_week = end_date.strftime('%W').to_i
|
||||
weeks = weeks(start_week, end_week)
|
||||
|
||||
result.each do |state, values|
|
||||
if state == 'Submitted'
|
||||
result['Submitted'] = pad_array_left_kumulative(start_week, values)
|
||||
else
|
||||
result[state] = pad_array_left_not_kumulative(start_week, values)
|
||||
end
|
||||
start_week = program.cfp.start_week
|
||||
get_events_per_week_by_state.collect do |state, values|
|
||||
if state == 'Submitted'
|
||||
{
|
||||
name: 'Submitted',
|
||||
data: add_week_indices(pad_array_left_kumulative(start_week, values))
|
||||
}
|
||||
else
|
||||
{
|
||||
name: state,
|
||||
data: add_week_indices(pad_array_left_not_kumulative(start_week, values))
|
||||
}
|
||||
end
|
||||
result['Weeks'] = weeks > 0 ? (1..weeks).to_a : 0
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -202,19 +200,15 @@ class Conference < ApplicationRecord
|
|||
# ====Returns
|
||||
# * +Array+ -> e.g. [0, 3, 3, 5] -> first week 0, second week 3 registrations
|
||||
def get_registrations_per_week
|
||||
result = []
|
||||
return [] unless registrations &&
|
||||
registration_period &&
|
||||
registration_period.start_date &&
|
||||
registration_period.end_date
|
||||
|
||||
if registrations &&
|
||||
registration_period &&
|
||||
registration_period.start_date &&
|
||||
registration_period.end_date
|
||||
|
||||
reg = registrations.group(:week).order(:week).count
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
result = calculate_items_per_week(start_week, weeks, reg)
|
||||
end
|
||||
result
|
||||
reg = registrations.group(:week).order(:week).count
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
calculate_items_per_week(start_week, weeks, reg)
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -223,15 +217,12 @@ class Conference < ApplicationRecord
|
|||
# ====Returns
|
||||
# * +Array+ -> e.g. [0, 3, 3, 5] -> first week 0, second week 3 tickets sold
|
||||
def get_tickets_sold_per_week
|
||||
result = []
|
||||
return [] unless tickets && ticket_purchases && registration_period
|
||||
|
||||
if tickets && ticket_purchases && registration_period
|
||||
tickets_sold = ticket_purchases.paid.group(:week).sum(:quantity)
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
result = calculate_items_per_week(start_week, weeks, tickets_sold)
|
||||
end
|
||||
result
|
||||
tickets_sold = ticket_purchases.paid.group(:week).sum(:quantity)
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
calculate_items_per_week(start_week, weeks, tickets_sold)
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -241,33 +232,32 @@ class Conference < ApplicationRecord
|
|||
# ====Returns
|
||||
# * +Array+ -> e.g. 'Free Access' => [0, 3, 3, 5] -> first week 0 tickets sold, second week 3 tickets sold.
|
||||
def get_tickets_data
|
||||
result = {}
|
||||
if tickets && ticket_purchases && registration_period
|
||||
tickets_per_ticket_id_and_week = ticket_purchases.paid.group(:ticket_id, :week).sum(:quantity)
|
||||
return [] unless tickets && ticket_purchases && registration_period
|
||||
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
tickets_per_ticket_id_and_week = ticket_purchases.paid.group(:ticket_id, :week).sum(:quantity)
|
||||
|
||||
tickets_by_id_per_week = {}
|
||||
start_week = get_registration_start_week
|
||||
weeks = registration_weeks
|
||||
|
||||
tickets.each do |ticket|
|
||||
tickets_by_id_per_week[ticket.id] = {}
|
||||
(start_week...(start_week + weeks)).each do |week|
|
||||
tickets_by_id_per_week[ticket.id][week] = 0
|
||||
end
|
||||
tickets_by_id_per_week = {}
|
||||
|
||||
tickets.each do |ticket|
|
||||
tickets_by_id_per_week[ticket.id] = {}
|
||||
(start_week...(start_week + weeks)).each do |week|
|
||||
tickets_by_id_per_week[ticket.id][week] = 0
|
||||
end
|
||||
|
||||
tickets_per_ticket_id_and_week.each do |ticket_week, value|
|
||||
tickets_by_id_per_week[ticket_week[0]][ticket_week[1]] = value
|
||||
end
|
||||
|
||||
tickets_by_id_per_week.each do |ticket, values|
|
||||
result[Ticket.find(ticket).title] = pad_array_left_not_kumulative(start_week, values)
|
||||
end
|
||||
|
||||
result['Weeks'] = weeks > 0 ? (1..weeks).to_a : 0
|
||||
end
|
||||
result
|
||||
|
||||
tickets_per_ticket_id_and_week.each do |ticket_week, value|
|
||||
tickets_by_id_per_week[ticket_week[0]][ticket_week[1]] = value
|
||||
end
|
||||
|
||||
tickets_by_id_per_week.collect do |ticket, values|
|
||||
{
|
||||
name: Ticket.find(ticket).title,
|
||||
data: add_week_indices(pad_array_left_not_kumulative(start_week, values))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -400,7 +390,9 @@ class Conference < ApplicationRecord
|
|||
# ====Returns
|
||||
# * +hash+ -> hash
|
||||
def event_distribution
|
||||
Conference.calculate_event_distribution_hash(program.events.select(:state).group(:state).count)
|
||||
Conference.calculate_event_distribution_hash(
|
||||
program.events.select(:state).group(:state).count
|
||||
)
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -465,22 +457,6 @@ class Conference < ApplicationRecord
|
|||
result
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a hash with user distribution => {value: count of user state, color: color}
|
||||
# active: signed in during the last 3 months
|
||||
# unconfirmed: registered but not confirmed
|
||||
# dead: not signed in during the last year
|
||||
#
|
||||
# ====Returns
|
||||
# * +hash+ -> hash
|
||||
def self.user_distribution
|
||||
active_user = User.where('last_sign_in_at > ?', Date.today - 3.months).count
|
||||
unconfirmed_user = User.where('confirmed_at IS NULL').count
|
||||
dead_user = User.where('last_sign_in_at < ?', Date.today - 1.year).count
|
||||
|
||||
calculate_user_distribution_hash(active_user, unconfirmed_user, dead_user)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a hash with per ticket sales => { "Title" => { value: number of tickets sold,
|
||||
# color: generated from the title using a hash function }, ...}
|
||||
|
|
@ -1110,20 +1086,19 @@ class Conference < ApplicationRecord
|
|||
end
|
||||
|
||||
##
|
||||
# Helper method. Calculates hash with corresponding colors of event state distribution.
|
||||
# Helper method. Calculates hash of all event states in a consistent order.
|
||||
#
|
||||
# ====Returns
|
||||
# * +hash+ -> hash
|
||||
def self.calculate_event_distribution_hash(states)
|
||||
result = {}
|
||||
states.each do |key, value|
|
||||
result[key.capitalize] =
|
||||
{
|
||||
'value' => value,
|
||||
'color' => Event.get_state_color(key)
|
||||
}
|
||||
end
|
||||
result
|
||||
def self.calculate_event_distribution_hash(counts)
|
||||
return {} if counts.values.sum == 0
|
||||
|
||||
Hash[
|
||||
Event.state_machine.states.collect do |state|
|
||||
state_name = state.name.to_s
|
||||
[state_name.capitalize, counts[state_name] || 0]
|
||||
end
|
||||
]
|
||||
end
|
||||
|
||||
##
|
||||
|
|
@ -1211,6 +1186,12 @@ class Conference < ApplicationRecord
|
|||
result += Array.new(weeks - result.length, sum)
|
||||
end
|
||||
|
||||
result
|
||||
add_week_indices(result)
|
||||
end
|
||||
|
||||
def add_week_indices(values)
|
||||
Hash[
|
||||
values.collect.with_index { |value, index| ["Wk #{index + 1}", value] }
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -83,6 +83,15 @@ class Event < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
COLORS = {
|
||||
new: '#0000FF', # blue
|
||||
withdrawn: '#FF8000', # orange
|
||||
unconfirmed: '#FFFF00', # yellow
|
||||
confirmed: '#00FF00', # green
|
||||
canceled: '#848484', # grey
|
||||
rejected: '#FF0000' # red
|
||||
}.freeze
|
||||
|
||||
##
|
||||
# Checkes if the event has a start_time and a room for the selected schedule if there is any
|
||||
# ====Returns
|
||||
|
|
@ -176,16 +185,7 @@ class Event < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.get_state_color(state)
|
||||
color = {
|
||||
new: '#0000FF', # blue
|
||||
withdrawn: '#FF8000', # orange
|
||||
confirmed: '#00FF00', # green
|
||||
unconfirmed: '#FFFF00', # yellow
|
||||
rejected: '#FF0000', # red
|
||||
canceled: '#848484' # grey
|
||||
}[state.to_sym]
|
||||
|
||||
color || '#00FFFF' # azure
|
||||
COLORS[state.to_sym] || '#00FFFF' # azure
|
||||
end
|
||||
|
||||
def update_state(transition, mail = false, subject = false, send_mail = false, send_mail_param)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,13 @@ class User < ApplicationRecord
|
|||
# add scope
|
||||
scope :comment_notifiable, ->(conference) {joins(:roles).where('roles.name IN (?)', [:organizer, :cfp]).where('roles.resource_type = ? AND roles.resource_id = ?', 'Conference', conference.id)}
|
||||
|
||||
# scopes for user distributions
|
||||
scope :active, lambda {
|
||||
where('last_sign_in_at > ?', Date.today - 3.months).where(is_disabled: false)
|
||||
}
|
||||
scope :unconfirmed, -> { where('confirmed_at IS NULL') }
|
||||
scope :dead, -> { where('last_sign_in_at < ?', Date.today - 1.year) }
|
||||
|
||||
# Include default devise modules. Others available are:
|
||||
# :token_authenticatable, :confirmable,
|
||||
# :lockable, :timeoutable and :omniauthable
|
||||
|
|
@ -79,7 +86,6 @@ class User < ApplicationRecord
|
|||
accepts_nested_attributes_for :roles
|
||||
|
||||
scope :admin, -> { where(is_admin: true) }
|
||||
scope :active, -> { where(is_disabled: false) }
|
||||
|
||||
validates :email, presence: true
|
||||
|
||||
|
|
@ -91,6 +97,12 @@ class User < ApplicationRecord
|
|||
|
||||
validate :biography_limit
|
||||
|
||||
DISTRIBUTION_COLORS = {
|
||||
'Active' => 'green',
|
||||
'Unconfirmed' => 'red',
|
||||
'Dead' => 'black'
|
||||
}.freeze
|
||||
|
||||
##
|
||||
# Checkes if the user attended the event
|
||||
# This is used for events that require registration
|
||||
|
|
@ -152,6 +164,22 @@ class User < ApplicationRecord
|
|||
user
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a hash with user distribution => {value: count of user state, color: color}
|
||||
# active: signed in during the last 3 months
|
||||
# unconfirmed: registered but not confirmed
|
||||
# dead: not signed in during the last year
|
||||
#
|
||||
# ====Returns
|
||||
# * +hash+ -> hash
|
||||
def self.distribution
|
||||
{
|
||||
'Active' => User.active.count,
|
||||
'Unconfirmed' => User.unconfirmed.count,
|
||||
'Dead' => User.dead.count
|
||||
}
|
||||
end
|
||||
|
||||
def self.find_for_database_authentication(warden_conditions)
|
||||
conditions = warden_conditions.dup
|
||||
login = conditions.delete(:login)
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
.text-center
|
||||
%h4 #{title}
|
||||
%canvas.doughnut_chart{ id: "dough_#{title.parameterize.underscore}", 'data-chart' => data.to_json }
|
||||
- if data
|
||||
- data.each do |key, value|
|
||||
%span{ 'style' => "border-bottom: 3px solid #{value['color']}" } #{key}: #{value['value']}
|
||||
|
||||
:javascript
|
||||
$(document).ready( function(){
|
||||
|
||||
var d = $("#dough_#{title.parameterize.underscore}");
|
||||
var dt = d.get(0).getContext('2d');
|
||||
|
||||
$(window).resize( respondCanvas );
|
||||
|
||||
function respondCanvas(){
|
||||
dt.canvas.width = 150;
|
||||
dt.canvas.height = 150;
|
||||
}
|
||||
|
||||
respondCanvas();
|
||||
|
||||
});
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
.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]}
|
||||
|
||||
:javascript
|
||||
$(document).ready( function(){
|
||||
|
||||
var c = $("#line_chart_#{name}");
|
||||
var ct = c.get(0).getContext('2d');
|
||||
var container = $(c).parent();
|
||||
|
||||
$(window).resize( respondCanvas );
|
||||
|
||||
function respondCanvas(){
|
||||
c.attr('width', $(container).width() );
|
||||
c.attr('height', $(container).height() );
|
||||
}
|
||||
|
||||
respondCanvas();
|
||||
|
||||
});
|
||||
|
|
@ -1,52 +1,32 @@
|
|||
= javascript_include_tag 'Chart.min'
|
||||
.row
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "user", subtitle: "User", value: @total_user, delta: @new_user
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "check-square", subtitle: "Registration", value: @total_reg, delta: @new_reg
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "file-text", subtitle: "Submission", value: @total_submissions, delta: @new_submissions
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "archive", subtitle: "Withdrawn", value: @total_withdrawn, delta: @new_withdrawn, reverse: true
|
||||
|
||||
.row#registrations
|
||||
.col-md-8
|
||||
= 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' }
|
||||
= render 'line_chart', title: 'Registrations per week', data: @registrations
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: { title: 'Events', data: @event_distribution }
|
||||
= render 'donut_chart', title: 'Events',
|
||||
data: @event_distribution, colors: @event_distribution_colors
|
||||
.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' }
|
||||
= render 'line_chart', title: 'Submissions per week', data: @submissions
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: { title: 'User', data: @user_distribution }
|
||||
= render 'donut_chart', title: 'Users',
|
||||
data: @user_distribution, colors: @user_distribution_colors
|
||||
.row#tickets
|
||||
.col-md-8
|
||||
= render partial: 'line_chart', locals: { title: 'Tickets sold over time',
|
||||
name: 'tickets',
|
||||
conferences: @conferences,
|
||||
active_conferences: @active_conferences,
|
||||
deactive_conferences: @deactive_conferences,
|
||||
y: @tickets,
|
||||
x: @ticket_weeks,
|
||||
unit: 'weeks' }
|
||||
= render 'line_chart', title: 'Tickets sold per week', data: @tickets
|
||||
%br
|
||||
.row
|
||||
.col-md-8
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
= javascript_include_tag 'Chart.min'
|
||||
|
||||
%h1
|
||||
%span.fa.fa-tachometer
|
||||
Dashboard for #{@conference.title}
|
||||
%hr
|
||||
.row
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "user", subtitle: "Registration", value: @total_reg, delta: @new_reg
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "check-square", subtitle: "Submission", value: @total_submissions, delta: @new_submissions
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "file-text", subtitle: "Hour", value: @program_length, delta: @new_program_length
|
||||
.col-sm-3.col-xs-3
|
||||
= render "shared/big_statistic",
|
||||
= render "big_statistic",
|
||||
icon: "archive", subtitle: "Withdrawn", value: @total_withdrawn, delta: @new_withdrawn
|
||||
|
||||
.row
|
||||
|
|
@ -24,37 +22,19 @@
|
|||
.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' }
|
||||
= render 'line_chart',
|
||||
title: 'Registrations per week', data: @registrations
|
||||
.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' }
|
||||
= render 'line_chart',
|
||||
title: 'Submissions per week', data: @submissions
|
||||
.col-md-4
|
||||
= render partial: 'todo_list', locals: { conference_progress: @conference_progress,
|
||||
conference: @conference }
|
||||
= render 'todo_list',
|
||||
conference_progress: @conference_progress, conference: @conference
|
||||
.row#tickets
|
||||
.col-md-8
|
||||
= render partial: 'line_chart', locals: { title: 'Tickets sold over time',
|
||||
name: 'tickets',
|
||||
conferences: @tickets,
|
||||
active_conferences: @tickets,
|
||||
deactive_conferences: [],
|
||||
y: @tickets_data,
|
||||
x: @ticket_weeks,
|
||||
unit: 'weeks' }
|
||||
= render 'line_chart',
|
||||
title: 'Tickets sold per week', data: @tickets
|
||||
%br
|
||||
.row
|
||||
.col-md-12#doughnut
|
||||
|
|
@ -75,27 +55,36 @@
|
|||
.tab-pane.active#distribution_all
|
||||
.row
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution}
|
||||
= render 'donut_chart', title: 'Event types',
|
||||
combined_data: @event_type_distribution
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution}
|
||||
= render 'donut_chart', title: 'Difficulty levels',
|
||||
combined_data: @difficulty_levels_distribution
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution}
|
||||
= render 'donut_chart', title: 'Tracks',
|
||||
combined_data: @tracks_distribution
|
||||
.tab-pane#distribution_confirmed
|
||||
.row
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution_confirmed}
|
||||
= render 'donut_chart', title: 'Event types',
|
||||
combined_data: @event_type_distribution_confirmed
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_confirmed}
|
||||
= render 'donut_chart', title: 'Difficulty levels',
|
||||
combined_data: @difficulty_levels_distribution_confirmed
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_confirmed}
|
||||
= render 'donut_chart', title: 'Tracks',
|
||||
combined_data: @tracks_distribution_confirmed
|
||||
.tab-pane#distribution_withdrawn
|
||||
.row
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution_withdrawn}
|
||||
= render 'donut_chart', title: 'Event types',
|
||||
combined_data: @event_type_distribution_withdrawn
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_withdrawn}
|
||||
= render 'donut_chart', title: 'Difficulty levels',
|
||||
combined_data: @difficulty_levels_distribution_withdrawn
|
||||
.col-md-4
|
||||
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_withdrawn}
|
||||
= render 'donut_chart', title: 'Tracks',
|
||||
combined_data: @tracks_distribution_withdrawn
|
||||
|
||||
.row
|
||||
.col-md-8
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
= javascript_include_tag 'Chart.min'
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
.page-header
|
||||
|
|
@ -47,17 +45,14 @@
|
|||
= f.submit 'Add', class: 'btn btn-primary'
|
||||
.row
|
||||
.col-md-4
|
||||
= render 'admin/conferences/doughnut_chart',
|
||||
title: 'Events state',
|
||||
data: @event_distribution
|
||||
= render 'donut_chart', title: 'Events state',
|
||||
data: @event_distribution, colors: @event_distribution_colors
|
||||
.col-md-4
|
||||
= render 'admin/conferences/doughnut_chart',
|
||||
title: 'Confirmed events scheduled',
|
||||
data: @scheduled_event_distribution
|
||||
= render 'donut_chart', title: 'Confirmed events scheduled',
|
||||
combined_data: @scheduled_event_distribution
|
||||
.col-md-4
|
||||
= render 'admin/conferences/doughnut_chart',
|
||||
title: 'Tracks of confirmed events',
|
||||
data: @tracks_distribution_confirmed
|
||||
= render 'donut_chart', title: 'Tracks of confirmed events',
|
||||
combined_data: @tracks_distribution_confirmed
|
||||
.row
|
||||
.col-md-12
|
||||
.margin-event-table
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
= javascript_include_tag 'Chart.min'
|
||||
|
||||
.container
|
||||
.row
|
||||
.col-md-12.page-header
|
||||
|
|
@ -9,11 +7,11 @@
|
|||
Tickets sold for the conference
|
||||
.row
|
||||
.col-md-4
|
||||
= render partial: 'admin/conferences/doughnut_chart',
|
||||
locals: { title: 'Tickets sold', data: @tickets_sold_distribution }
|
||||
= render 'donut_chart', title: 'Tickets sold',
|
||||
combined_data: @tickets_sold_distribution
|
||||
.col-md-4
|
||||
= render partial: 'admin/conferences/doughnut_chart',
|
||||
locals: {title: 'Tickets turnover', data: @tickets_turnover_distribution}
|
||||
= render 'donut_chart', title: 'Tickets turnover',
|
||||
combined_data: @tickets_turnover_distribution
|
||||
%br
|
||||
- if @physical_tickets.any?
|
||||
.row
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
= javascript_include_tag 'Chart.min'
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
.page-header
|
||||
|
|
@ -14,10 +12,12 @@
|
|||
%p.text-muted
|
||||
All the people who registered to your event
|
||||
.col-md-4
|
||||
= render partial: 'admin/conferences/doughnut_chart', locals: {title: 'Affiliation', data: @affiliation_distribution}
|
||||
= render 'donut_chart', title: 'Affiliation',
|
||||
combined_data: @affiliation_distribution
|
||||
- unless @conference.pending?
|
||||
.col-md-4
|
||||
= render partial: 'admin/conferences/doughnut_chart', locals: {title: 'Attended registrations', data: @registration_distribution}
|
||||
= render 'donut_chart', title: 'Attended registrations',
|
||||
combined_data: @registration_distribution
|
||||
.row
|
||||
.col-md-12
|
||||
%div.margin-event-table
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
= javascript_include_tag "//www.google.com/jsapi", "chartkick"
|
||||
= javascript_include_tag 'chartkick'
|
||||
|
||||
= bar_chart @survey.survey_questions.map{ |q| [q.title, q.survey_replies.count] }
|
||||
|
||||
- @survey.survey_questions.each.with_index(1) do |survey_question, question_index|
|
||||
|
|
|
|||
16
app/views/application/_donut_chart.haml
Normal file
16
app/views/application/_donut_chart.haml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
:ruby
|
||||
combined_data ||= {}
|
||||
data ||= chart_values(combined_data)
|
||||
colors ||= chart_colors(combined_data)
|
||||
|
||||
options = {
|
||||
donut: true,
|
||||
legend: 'bottom',
|
||||
download: true,
|
||||
messages: { empty: 'No data' }
|
||||
}
|
||||
options[:colors] = colors if colors.present?
|
||||
|
||||
.text-center
|
||||
%h4= title
|
||||
= pie_chart data, options
|
||||
15
app/views/application/_line_chart.html.haml
Normal file
15
app/views/application/_line_chart.html.haml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
:ruby
|
||||
options = {
|
||||
legend: 'bottom',
|
||||
download: true,
|
||||
messages: { empty: 'No data' }
|
||||
}
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
.text-center
|
||||
%h4
|
||||
= title
|
||||
.row
|
||||
.col-md-12
|
||||
= line_chart data, options
|
||||
|
|
@ -50,4 +50,5 @@
|
|||
Performance data is available on
|
||||
#{link_to "Skylight", ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"]}.
|
||||
= yield :script_body
|
||||
= yield :charts_js
|
||||
= piwik_tracking_tag
|
||||
|
|
|
|||
|
|
@ -9,4 +9,3 @@ Rails.application.config.assets.version = '1.0'
|
|||
# Precompile additional assets.
|
||||
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
|
||||
# Rails.application.config.assets.precompile += %w( search.js )
|
||||
Rails.application.config.assets.precompile += %w( Chart.min.js )
|
||||
|
|
|
|||
4
config/initializers/chartkick.rb
Normal file
4
config/initializers/chartkick.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Chartkick.options = {
|
||||
height: '150px',
|
||||
content_for: :charts_js
|
||||
}
|
||||
|
|
@ -177,17 +177,6 @@ describe Admin::ConferencesController do
|
|||
expect(assigns(:conferences)).to match_array([conference, con2])
|
||||
end
|
||||
|
||||
it 'assigns cfp_max an array with maximum weeks' do
|
||||
conference
|
||||
date = Date.new(2014, 05, 26)
|
||||
create(:cfp,
|
||||
program: conference.program,
|
||||
start_date: date,
|
||||
end_date: date + 14)
|
||||
get :index
|
||||
expect(assigns(:cfp_weeks)).to match_array([1, 2, 3])
|
||||
end
|
||||
|
||||
it 'renders the index template' do
|
||||
conference
|
||||
get :index
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ FactoryBot.define do
|
|||
Quisque cursus facilisis consequat. Etiam volutpat ligula turpis, at
|
||||
gravida.
|
||||
EOS
|
||||
last_sign_in_at { Date.today }
|
||||
is_disabled { false }
|
||||
|
||||
after(:create) do |user|
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@ require 'spec_helper'
|
|||
describe Commercial do
|
||||
|
||||
describe '.find_since_last_login' do
|
||||
let!(:user) do
|
||||
create(:user, last_sign_in_at: nil)
|
||||
end
|
||||
|
||||
it 'returns none if last_sign_in_at is nil' do
|
||||
expect(Comment.find_since_last_login(create(:user))).to eq(Comment.none)
|
||||
expect(Comment.find_since_last_login(user)).to eq(Comment.none)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ describe Conference do
|
|||
|
||||
describe '#get_submissions_data' do
|
||||
it 'returns emtpy hash if there is no cfp or events' do
|
||||
expect(subject.get_submissions_data).to eq({})
|
||||
expect(subject.get_submissions_data).to eq []
|
||||
end
|
||||
|
||||
it 'calculates the correct result with data from database' do
|
||||
|
|
@ -191,12 +191,7 @@ describe Conference do
|
|||
|
||||
create(:event, program: subject.program, created_at: Date.today - 2.weeks)
|
||||
|
||||
result = {
|
||||
'Submitted' => [1, 1, 1],
|
||||
'Confirmed' => [1, 3, 0],
|
||||
'Unconfirmed' => [2, 4, 0],
|
||||
'Weeks' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
}
|
||||
result = [{ name: 'Submitted', data: { 'Wk 1' => 1, 'Wk 2' => 1, 'Wk 3' => 1 } }, { name: 'Confirmed', data: { 'Wk 1' => 1, 'Wk 2' => 3, 'Wk 3' => 0 } }, { name: 'Unconfirmed', data: { 'Wk 1' => 2, 'Wk 2' => 4, 'Wk 3' => 0 } }]
|
||||
expect(subject.get_submissions_data).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -207,12 +202,11 @@ describe Conference do
|
|||
create(:cfp, start_date: Date.today, program: subject.program)
|
||||
create(:event, program: subject.program)
|
||||
|
||||
result = {
|
||||
'Submitted' => [1],
|
||||
'Confirmed' => [0],
|
||||
'Unconfirmed' => [0],
|
||||
'Weeks' => [1, 2, 3, 4, 5, 6, 7, 8]
|
||||
}
|
||||
result = [
|
||||
{ name: 'Submitted', data: { 'Wk 1'=>1 } },
|
||||
{ name: 'Confirmed', data: { 'Wk 1'=>0 } },
|
||||
{ name: 'Unconfirmed', data: { 'Wk 1'=>0 } }
|
||||
]
|
||||
expect(subject.get_submissions_data).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -232,12 +226,20 @@ describe Conference do
|
|||
confirmed.accept!(options)
|
||||
confirmed.confirm!
|
||||
|
||||
result = {
|
||||
'Submitted' => [0, 0, 3],
|
||||
'Confirmed' => [0, 0, 1],
|
||||
'Unconfirmed' => [0, 0, 1],
|
||||
'Weeks' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
}
|
||||
result = [
|
||||
{
|
||||
name: 'Submitted',
|
||||
data: { 'Wk 1' => 0, 'Wk 2' => 0, 'Wk 3' => 3 }
|
||||
},
|
||||
{
|
||||
name: 'Confirmed',
|
||||
data: { 'Wk 1' => 0, 'Wk 2' => 0, 'Wk 3' => 1 }
|
||||
},
|
||||
{
|
||||
name: 'Unconfirmed',
|
||||
data: { 'Wk 1' => 0, 'Wk 2' => 0, 'Wk 3' => 1 }
|
||||
}
|
||||
]
|
||||
expect(subject.get_submissions_data).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -263,12 +265,20 @@ describe Conference do
|
|||
|
||||
create(:event, program: subject.program, created_at: Date.today - 3.weeks)
|
||||
|
||||
result = {
|
||||
'Submitted' => [1, 1, 1, 1],
|
||||
'Confirmed' => [1, 0, 3, 0],
|
||||
'Unconfirmed' => [2, 0, 4, 0],
|
||||
'Weeks' => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
||||
}
|
||||
result = [
|
||||
{
|
||||
name: 'Submitted',
|
||||
data: { 'Wk 1' => 1, 'Wk 2' => 1, 'Wk 3' => 1, 'Wk 4' => 1 }
|
||||
},
|
||||
{
|
||||
name: 'Confirmed',
|
||||
data: { 'Wk 1' => 1, 'Wk 2' => 0, 'Wk 3' => 3, 'Wk 4' => 0 }
|
||||
},
|
||||
{
|
||||
name: 'Unconfirmed',
|
||||
data: { 'Wk 1' => 2, 'Wk 2' => 0, 'Wk 3' => 4, 'Wk 4' => 0 }
|
||||
}
|
||||
]
|
||||
expect(subject.get_submissions_data).to eq(result)
|
||||
end
|
||||
end
|
||||
|
|
@ -768,13 +778,7 @@ describe Conference do
|
|||
canceled.accept!(@options)
|
||||
canceled.cancel!
|
||||
|
||||
@result = {}
|
||||
@result['New'] = { 'value' => 1, 'color' => '#0000FF' }
|
||||
@result['Withdrawn'] = { 'value' => 1, 'color' => '#FF8000' }
|
||||
@result['Unconfirmed'] = { 'value' => 1, 'color' => '#FFFF00' }
|
||||
@result['Rejected'] = { 'value' => 1, 'color' => '#FF0000' }
|
||||
@result['Confirmed'] = { 'value' => 1, 'color' => '#00FF00' }
|
||||
@result['Canceled'] = { 'value' => 1, 'color' => '#848484' }
|
||||
@result = { 'New' => 1, 'Withdrawn' => 1, 'Unconfirmed' => 1, 'Confirmed' => 1, 'Canceled' => 1, 'Rejected' => 1 }
|
||||
end
|
||||
|
||||
it '#event_distribution does calculate correct values with events' do
|
||||
|
|
@ -789,7 +793,7 @@ describe Conference do
|
|||
it 'event_distribution does calculate correct values with just a new event' do
|
||||
conference = create(:conference)
|
||||
create(:event, program: conference.program)
|
||||
result = { 'New' => { 'value' => 1, 'color' => '#0000FF' } }
|
||||
result = { 'New' => 1, 'Withdrawn' => 0, 'Unconfirmed' => 0, 'Confirmed' => 0, 'Canceled' => 0, 'Rejected' => 0 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -797,7 +801,7 @@ describe Conference do
|
|||
conference = create(:conference)
|
||||
event = create(:event, program: conference.program)
|
||||
event.withdraw!
|
||||
result = { 'Withdrawn' => { 'value' => 1, 'color' => '#FF8000' } }
|
||||
result = { 'New' => 0, 'Withdrawn' => 1, 'Unconfirmed' => 0, 'Confirmed' => 0, 'Canceled' => 0, 'Rejected' => 0 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -805,7 +809,7 @@ describe Conference do
|
|||
conference = create(:conference)
|
||||
event = create(:event, program: conference.program)
|
||||
event.accept!(@options)
|
||||
result = { 'Unconfirmed' => { 'value' => 1, 'color' => '#FFFF00' } }
|
||||
result = { 'New' => 0, 'Withdrawn' => 0, 'Unconfirmed' => 1, 'Confirmed' => 0, 'Canceled' => 0, 'Rejected' => 0 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -813,7 +817,7 @@ describe Conference do
|
|||
conference = create(:conference)
|
||||
event = create(:event, program: conference.program)
|
||||
event.reject!(@options)
|
||||
result = { 'Rejected' => { 'value' => 1, 'color' => '#FF0000' } }
|
||||
result = { 'New' => 0, 'Withdrawn' => 0, 'Unconfirmed' => 0, 'Confirmed' => 0, 'Canceled' => 0, 'Rejected' => 1 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -823,7 +827,7 @@ describe Conference do
|
|||
event = create(:event, program: conference.program)
|
||||
event.accept!(@options)
|
||||
event.confirm!
|
||||
result = { 'Confirmed' => { 'value' => 1, 'color' => '#00FF00' } }
|
||||
result = { 'New' => 0, 'Withdrawn' => 0, 'Unconfirmed' => 0, 'Confirmed' => 1, 'Canceled' => 0, 'Rejected' => 0 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -832,7 +836,7 @@ describe Conference do
|
|||
event = create(:event, program: conference.program)
|
||||
event.accept!(@options)
|
||||
event.cancel!
|
||||
result = { 'Canceled' => { 'value' => 1, 'color' => '#848484' } }
|
||||
result = { 'New' => 0, 'Withdrawn' => 0, 'Unconfirmed' => 0, 'Confirmed' => 0, 'Canceled' => 1, 'Rejected' => 0 }
|
||||
expect(conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
|
|
@ -848,15 +852,15 @@ describe Conference do
|
|||
it 'self#event_distribution does calculate correct values with just a new event' do
|
||||
@conference.program.events.clear
|
||||
create(:event, program: @conference.program)
|
||||
result = { 'New' => { 'value' => 1, 'color' => '#0000FF' } }
|
||||
result = { 'New' => 1, 'Withdrawn' => 0, 'Unconfirmed' => 0, 'Confirmed' => 0, 'Canceled' => 0, 'Rejected' => 0 }
|
||||
expect(Conference.event_distribution).to eq(result)
|
||||
end
|
||||
|
||||
it 'self#event_distribution does calculate correct values
|
||||
with just a new events from different conferences' do
|
||||
create(:event, program: @conference.program)
|
||||
@result['New'] = { 'value' => 2, 'color' => '#0000FF' }
|
||||
expect(Conference.event_distribution).to eq(@result)
|
||||
result = { 'New' => 2, 'Withdrawn' => 1, 'Unconfirmed' => 1, 'Confirmed' => 1, 'Canceled' => 1, 'Rejected' => 1 }
|
||||
expect(Conference.event_distribution).to eq(result)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -865,44 +869,15 @@ describe Conference do
|
|||
let!(:organizer_role) { Role.find_by(name: 'organizer', resource: conference) }
|
||||
let!(:organizer) { create(:user, role_ids: [organizer_role.id]) }
|
||||
|
||||
it 'self#event_distribution calculates correct values with user' do
|
||||
create(:user, last_sign_in_at: Date.today - 3.months + 1.day) # active
|
||||
create(:user, confirmed_at: nil) # unconfirmed
|
||||
create(:user, last_sign_in_at: Date.today - 1.year - 1.day) # dead
|
||||
it 'self#user_distribution calculates correct values with user' do
|
||||
result = {}
|
||||
result['Active'] = { 'color' => 'green', 'value' => 1 }
|
||||
result['Unconfirmed'] = { 'color' => 'red', 'value' => 1 }
|
||||
result['Dead'] = { 'color' => 'black', 'value' => 1 }
|
||||
|
||||
expect(Conference.user_distribution).to eq(result)
|
||||
end
|
||||
|
||||
it 'self#event_distribution calculates correct with only active user' do
|
||||
create(:user, last_sign_in_at: Date.today - 3.months + 1.day) # active
|
||||
result = {}
|
||||
result['Active'] = { 'color' => 'green', 'value' => 1 }
|
||||
|
||||
expect(Conference.user_distribution).to eq(result)
|
||||
end
|
||||
|
||||
it 'self#event_distribution calculates correct values with only unconfirmed user' do
|
||||
create(:user, confirmed_at: nil) # unconfirmed
|
||||
result = {}
|
||||
result['Unconfirmed'] = { 'color' => 'red', 'value' => 1 }
|
||||
|
||||
expect(Conference.user_distribution).to eq(result)
|
||||
end
|
||||
|
||||
it 'self#event_distribution calculates correct values with only dead user' do
|
||||
create(:user, last_sign_in_at: Time.now - 1.year - 1.day) # dead
|
||||
result = {}
|
||||
result['Dead'] = { 'color' => 'black', 'value' => 1 }
|
||||
|
||||
expect(Conference.user_distribution).to eq(result)
|
||||
end
|
||||
|
||||
it 'self#event_distribution calculates correct values without user' do
|
||||
expect(Conference.user_distribution).to eq({})
|
||||
expect(
|
||||
Conference.calculate_user_distribution_hash(1, 1, 1)
|
||||
).to eq(result)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1152,7 +1127,7 @@ describe Conference do
|
|||
cfp.end_date = Date.new(2014, 05, 26) + 21
|
||||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) - 7)]
|
||||
expect(subject.get_submissions_per_week).to eq([1, 1, 1, 1, 1])
|
||||
expect(subject.get_submissions_per_week.values).to eq([1, 1, 1, 1, 1])
|
||||
end
|
||||
|
||||
it 'does calculate correct if cfp end date is altered' do
|
||||
|
|
@ -1161,7 +1136,7 @@ describe Conference do
|
|||
cfp.end_date = Date.new(2014, 05, 26) + 21
|
||||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 28)]
|
||||
expect(subject.get_submissions_per_week).to eq([0, 0, 0, 0, 1])
|
||||
expect(subject.get_submissions_per_week.values).to eq([0, 0, 0, 0, 1])
|
||||
end
|
||||
|
||||
it 'pads with zeros if there are no submissions' do
|
||||
|
|
@ -1169,7 +1144,7 @@ describe Conference do
|
|||
cfp.start_date = Date.new(2014, 05, 26)
|
||||
cfp.end_date = Date.new(2014, 05, 26) + 21
|
||||
cfp.save!
|
||||
expect(subject.get_submissions_per_week).to eq([0, 0, 0, 0])
|
||||
expect(subject.get_submissions_per_week.values).to eq([0, 0, 0, 0])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are no submissions in one week' do
|
||||
|
|
@ -1180,7 +1155,7 @@ describe Conference do
|
|||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 7)]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 14)]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 28)]
|
||||
expect(subject.get_submissions_per_week).to eq([0, 1, 2, 2, 3])
|
||||
expect(subject.get_submissions_per_week.values).to eq([0, 1, 2, 2, 3])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are submissions every week except the first' do
|
||||
|
|
@ -1190,7 +1165,7 @@ describe Conference do
|
|||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 7)]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 14)]
|
||||
expect(subject.get_submissions_per_week).to eq([0, 1, 2, 2])
|
||||
expect(subject.get_submissions_per_week.values).to eq([0, 1, 2, 2])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are submissions every week' do
|
||||
|
|
@ -1201,7 +1176,9 @@ describe Conference do
|
|||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26))]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 7)]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 14)]
|
||||
expect(subject.get_submissions_per_week).to eq([1, 2, 3, 3])
|
||||
expect(subject.get_submissions_per_week).to eq(
|
||||
'Wk 1' => 1, 'Wk 2' => 2, 'Wk 3' => 3, 'Wk 4' => 3
|
||||
)
|
||||
end
|
||||
|
||||
it 'pads left' do
|
||||
|
|
@ -1210,7 +1187,7 @@ describe Conference do
|
|||
cfp.end_date = Date.new(2014, 05, 26) + 21
|
||||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 21)]
|
||||
expect(subject.get_submissions_per_week).to eq([0, 0, 0, 1])
|
||||
expect(subject.get_submissions_per_week.values).to eq([0, 0, 0, 1])
|
||||
end
|
||||
|
||||
it 'pads middle' do
|
||||
|
|
@ -1220,7 +1197,7 @@ describe Conference do
|
|||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26))]
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26) + 21)]
|
||||
expect(subject.get_submissions_per_week).to eq([1, 1, 1, 2])
|
||||
expect(subject.get_submissions_per_week.values).to eq([1, 1, 1, 2])
|
||||
end
|
||||
|
||||
it 'pads right' do
|
||||
|
|
@ -1229,7 +1206,7 @@ describe Conference do
|
|||
cfp.end_date = Date.new(2014, 05, 26) + 21
|
||||
cfp.save!
|
||||
subject.program.events += [create(:event, created_at: Date.new(2014, 05, 26))]
|
||||
expect(subject.get_submissions_per_week).to eq([1, 1, 1, 1])
|
||||
expect(subject.get_submissions_per_week.values).to eq([1, 1, 1, 1])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1240,7 +1217,7 @@ describe Conference do
|
|||
start_date: Date.new(2014, 05, 26),
|
||||
end_date: Date.new(2014, 05, 26) + 21, conference: subject)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([0, 0, 0, 0])
|
||||
expect(subject.get_registrations_per_week.values).to eq([0, 0, 0, 0])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are no registrations in one week' do
|
||||
|
|
@ -1255,7 +1232,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 28)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([0, 1, 2, 2, 3])
|
||||
expect(subject.get_registrations_per_week.values).to eq([0, 1, 2, 2, 3])
|
||||
end
|
||||
|
||||
it 'returns [1] if there is one registration on the first day' do
|
||||
|
|
@ -1265,7 +1242,7 @@ describe Conference do
|
|||
|
||||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26))
|
||||
expect(subject.get_registrations_per_week).to eq([1, 1])
|
||||
expect(subject.get_registrations_per_week.values).to eq([1, 1])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are registrations every week' do
|
||||
|
|
@ -1279,7 +1256,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 14)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([1, 2, 3, 3])
|
||||
expect(subject.get_registrations_per_week.values).to eq([1, 2, 3, 3])
|
||||
end
|
||||
|
||||
it 'summarized correct if there are registrations every week except the first' do
|
||||
|
|
@ -1294,7 +1271,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 28)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([0, 1, 2, 2, 3])
|
||||
expect(subject.get_registrations_per_week.values).to eq([0, 1, 2, 2, 3])
|
||||
end
|
||||
|
||||
it 'pads left' do
|
||||
|
|
@ -1309,7 +1286,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 35)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([0, 0, 0, 1, 2, 3])
|
||||
expect(subject.get_registrations_per_week.values).to eq([0, 0, 0, 1, 2, 3])
|
||||
end
|
||||
|
||||
it 'pads middle' do
|
||||
|
|
@ -1322,7 +1299,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 35)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([1, 1, 1, 1, 1, 2])
|
||||
expect(subject.get_registrations_per_week.values).to eq([1, 1, 1, 1, 1, 2])
|
||||
end
|
||||
|
||||
it 'pads right' do
|
||||
|
|
@ -1335,7 +1312,7 @@ describe Conference do
|
|||
create(:registration, conference: subject,
|
||||
created_at: Date.new(2014, 05, 26) + 7)
|
||||
|
||||
expect(subject.get_registrations_per_week).to eq([1, 2, 2, 2, 2, 2])
|
||||
expect(subject.get_registrations_per_week.values).to eq([1, 2, 2, 2, 2, 2])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,23 @@ describe User do
|
|||
expect(User.comment_notifiable(conference)).not_to include(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user distribution scopes' do
|
||||
it 'scopes active users' do
|
||||
create(:user, last_sign_in_at: Date.today - 3.months + 1.day) # active
|
||||
expect(User.active.count).to eq(1)
|
||||
end
|
||||
|
||||
it 'scopes unconfirmed users' do
|
||||
create(:user, confirmed_at: nil) # unconfirmed
|
||||
expect(User.unconfirmed.count).to eq(1)
|
||||
end
|
||||
|
||||
it 'scopes dead users' do
|
||||
create(:user, last_sign_in_at: Time.zone.now - 1.year - 1.day) # dead
|
||||
expect(User.dead.count).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'methods' do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue