This commit is contained in:
Kyriakos Zag 2017-11-16 18:26:44 +02:00
commit d65b139099
70 changed files with 807 additions and 71 deletions

View file

@ -44,6 +44,9 @@ gem 'omniauth-openid'
gem 'omniauth-google-oauth2'
gem 'omniauth-github'
# Bot-filtering
gem 'recaptcha', require: 'recaptcha/rails'
# as authorization framework
gem 'cancancan'
@ -182,6 +185,10 @@ gem 'cloudinary'
# for setting app configuration in the environment
gem 'dotenv-rails'
# configurable toggles for functionality
# https://github.com/mgsnova/feature
gem 'feature'
# For countable.js
gem "countable-rails", "~> 0.0.1"

View file

@ -179,6 +179,7 @@ GEM
multipart-post (>= 1.2, < 3)
fastimage (2.0.0)
addressable (~> 2)
feature (1.4.0)
ffi (1.9.18)
font-awesome-rails (4.7.0.2)
railties (>= 3.2, < 5.2)
@ -420,6 +421,8 @@ GEM
loggability (~> 0.12)
rdoc (~> 5.0)
yajl-ruby (~> 1.3)
recaptcha (4.6.2)
json
redcarpet (3.2.3)
referer-parser (0.2.1)
request_store (1.1.0)
@ -589,6 +592,7 @@ DEPENDENCIES
dotenv-rails
factory_girl_rails
faker
feature
font-awesome-rails
formtastic (~> 3.1.1)
formtastic-bootstrap
@ -636,6 +640,7 @@ DEPENDENCIES
rails-i18n (~> 4.0.0)
rails_12factor
rdoc-generator-fivefish
recaptcha
redcarpet
responders (~> 2.0)
rolify

View file

@ -1,3 +1,5 @@
@import "bootstrap/mixins";
html {
position: relative;
min-height: 100%;
@ -104,3 +106,12 @@ p.comment-body {
.qr-image{
margin-left: 120px;
}
.g-recaptcha {
@include clearfix;
padding-bottom: 12px;
div {
float: right;
}
}

View file

@ -3,7 +3,24 @@ module Admin
load_and_authorize_resource :conference, find_by: :short_title
load_and_authorize_resource through: :conference
def index; end
def index
@file_name = "booths_for_#{@conference.short_title}"
@booth_export_option = params[:booth_export_option]
respond_to do |format|
format.html
# Explicity call #to_json to avoid the use of EventSerializer
format.json { render json: Booth.where(state: :confirmed, program: @program).to_json }
format.xlsx do
response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.xlsx\""
render 'booths'
end
format.pdf { render 'booths' }
format.csv do
response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.csv\""
render 'booths'
end
end
end
def show; end

View file

@ -55,7 +55,7 @@ module Admin
private
def cfp_params
params.require(:cfp).permit(:start_date, :end_date, :cfp_type)
params.require(:cfp).permit(:start_date, :end_date, :description, :cfp_type)
end
end
end

View file

@ -193,6 +193,7 @@ module Admin
def edit
@conferences = Conference.all
@date_string = date_string(@conference.start_date, @conference.end_date)
@affected_event_count = @conference.program.events.scheduled(@conference.program.selected_schedule_id).count
respond_to do |format|
format.html
format.json { render json: @conference.to_json }

View file

@ -7,7 +7,25 @@ module Admin
# Show flash message with ajax calls
after_action :prepare_unobtrusive_flash, only: :toggle_cfp_inclusion
def index; end
def index
@file_name = "tracks_for_#{@conference.short_title}"
@track_export_option = params[:track_export_option]
respond_to do |format|
format.html
# Explicity call #to_json to avoid the use of EventSerializer
format.json { render json: Track.where(state: :confirmed, program: @program).to_json }
format.xlsx do
response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.xlsx\""
render 'tracks'
end
format.pdf { render 'tracks' }
format.csv do
response.headers['Content-Disposition'] = "attachment; filename=\"#{@file_name}.csv\""
render 'tracks'
end
end
end
def show
respond_to do |format|

View file

@ -4,4 +4,10 @@ class OrganizationsController < ApplicationController
def index
@organizations = Organization.all
end
def conferences
@current = @organization.conferences.upcoming.reorder(start_date: :asc)
@antiquated = @organization.conferences.past
render '/conferences/index'
end
end

View file

@ -1,5 +1,5 @@
class RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
prepend_before_action :check_captcha, only: [:create]
def edit
@openids = Openid.where(user_id: current_user.id).order(:provider)
@ -21,14 +21,34 @@ class RegistrationsController < Devise::RegistrationsController
edit_user_registration_path(resource)
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update) do |u|
u
.permit(:email, :password, :password_confirmation, :current_password, :username, :email_public)
end
devise_parameter_sanitizer.permit(:sign_up) do |u|
u
.permit(:email, :password, :password_confirmation, :name, :username)
private
def sign_up_params
params.require(:user).permit(
:email,
:password,
:password_confirmation,
:name,
:username
)
end
def account_update_params
params.require(:user).permit(
:email,
:password,
:password_confirmation,
:current_password,
:username,
:email_public
)
end
def check_captcha
unless Feature.inactive?(:recaptcha) || verify_recaptcha
self.resource = resource_class.new sign_up_params
resource.validate # Look for any other validation errors besides Recaptcha
respond_with_navigational(resource) { render :new }
end
end
end

View file

@ -163,6 +163,12 @@ module ApplicationHelper
end
end
def rescheduling_hint(affected_event_count)
if affected_event_count > 0
"You have #{affected_event_count} scheduled #{'event'.pluralize(affected_event_count)}. Changing the conference hours will unschedule those scheduled outside the conference hours."
end
end
##
# ====Gets
# a conference object
@ -171,4 +177,18 @@ module ApplicationHelper
def hidden_if_conference_over(conference)
'hidden' if Date.today > conference.end_date
end
def nav_root_link_for(conference)
link_text = (
conference.try(:organization).try(:name) ||
ENV['OSEM_NAME'] ||
'OSEM'
)
link_to(
link_text,
root_path,
class: 'navbar-brand',
title: 'Open Source Event Manager'
)
end
end

View file

@ -15,7 +15,7 @@ class Ability
# Abilities for not signed in users (guests)
def not_signed_in
can [:index], Organization
can [:index, :conferences], Organization
can [:index], Conference
can [:show], Conference do |conference|
conference.splashpage && conference.splashpage.public == true

View file

@ -204,11 +204,12 @@ class Event < ActiveRecord::Base
end
def speaker_names
result = Set.new
speakers.each do |speaker|
result.add(speaker.name)
end
result.to_a.to_sentence
speakers.map(&:name).join(', ')
end
# Returns emails of all the speaker belongs to a particular event
def speaker_emails
speakers.map(&:email).join(', ')
end
##

View file

@ -42,7 +42,8 @@ class Program < ActiveRecord::Base
has_many :event_schedules, through: :events
has_many :event_users, through: :events
has_many :speakers, -> { distinct }, through: :event_users, source: :user do
has_many :program_events_speakers, -> {where(event_role: 'speaker')}, through: :events, source: :event_users
has_many :speakers, -> { distinct }, through: :program_events_speakers, source: :user do
def confirmed
joins(:events).where(events: { state: :confirmed })
end

View file

@ -0,0 +1,19 @@
- headers = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
= CSV.generate_line ['All booths']
= CSV.generate_line headers
- @booths.each do |booth|
= CSV.generate_line([booth.id,
booth.title,
booth.description,
booth.reasoning,
booth.submitter.name,
booth.submitter_relationship,
booth.website_url,
booth.state]).html_safe

View file

@ -0,0 +1,26 @@
prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf|
booths_array = []
header_array = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
booths_array << header_array
@booths.each do |booth|
row = []
row << booth.id
row << booth.title
row << booth.description
row << booth.reasoning
row << booth.submitter.name
row << booth.submitter_relationship
row << booth.website_url
row << booth.state
booths_array << row
end
pdf.text "#{@conference.short_title} booths", font_size: 25, align: :center
pdf.table booths_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [45,70,153,152,70,80,105,45]
end

View file

@ -0,0 +1,27 @@
wb.add_worksheet(name: 'all booths') do |sheet|
bold_style = wb.styles.add_style(b: true)
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
sheet.add_row row, style: bold_style
@booths.each do |booth|
row = []
row << booth.id
row << booth.title
row << booth.description
row << booth.reasoning
row << booth.submitter.name
row << booth.submitter_relationship
row << booth.website_url
row << booth.state
sheet.add_row row , style: wrap_text
sheet.column_widths 10,20,35,35,20,30,35,10
end
end

View file

@ -0,0 +1,19 @@
- headers = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
= CSV.generate_line ['All booths']
= CSV.generate_line headers
- @booths.confirmed.each do |booth|
= CSV.generate_line([booth.id,
booth.title,
booth.description,
booth.reasoning,
booth.submitter.name,
booth.submitter_relationship,
booth.website_url,
booth.state]).html_safe

View file

@ -0,0 +1,26 @@
prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf|
booths_array = []
header_array = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
booths_array << header_array
@booths.confirmed.each do |booth|
row = []
row << booth.id
row << booth.title
row << booth.description
row << booth.reasoning
row << booth.submitter.name
row << booth.submitter_relationship
row << booth.website_url
row << booth.state
booths_array << row
end
pdf.text "#{@conference.short_title} booths", font_size: 25, align: :center
pdf.table booths_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [45,70,153,152,70,80,105,45]
end

View file

@ -0,0 +1,27 @@
wb.add_worksheet(name: 'all booths') do |sheet|
bold_style = wb.styles.add_style(b: true)
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Booth ID',
'Title',
'Description',
'Reasoning',
'Submitter Name',
'Submitter Relationship',
'Website Url',
'State']
sheet.add_row row, style: bold_style
@booths.confirmed.each do |booth|
row = []
row << booth.id
row << booth.title
row << booth.description
row << booth.reasoning
row << booth.submitter.name
row << booth.submitter_relationship
row << booth.website_url
row << booth.state
sheet.add_row row , style: wrap_text
sheet.column_widths 10,20,35,35,20,30,35,10
end
end

View file

@ -0,0 +1,4 @@
- if @booth_export_option == 'confirmed'
= render 'confirmed_booths'
- elsif @booth_export_option == 'all'
= render 'all_booths'

View file

@ -0,0 +1,5 @@
if @booth_export_option == 'confirmed'
render 'confirmed_booths'
elsif @booth_export_option == 'all'
render 'all_booths'
end

View file

@ -0,0 +1,7 @@
wb = xlsx_package.workbook
xlsx_package.use_autowidth = true
if @booth_export_option == 'confirmed'
render partial: 'confirmed_booths', locals: { wb: wb }
elsif @booth_export_option == 'all'
render partial: 'all_booths', locals: { wb: wb }
end

View file

@ -3,6 +3,30 @@
.page-header
%h1
Booths
.pull-right
- if can? :read, Booth
.btn-group
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export PDF
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All Booths', admin_conference_booths_path(@conference.short_title, format: :pdf, booth_export_option: 'all')
%li= link_to 'Confirmed Booths', admin_conference_booths_path(@conference.short_title, format: :pdf, booth_export_option: 'confirmed')
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export CSV
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All', admin_conference_booths_path(@conference.short_title, format: :csv, booth_export_option: 'all')
%li= link_to 'Confirmed', admin_conference_booths_path(@conference.short_title, format: :csv, booth_export_option: 'confirmed')
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export XLS
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All', admin_conference_booths_path(@conference.short_title, format: :xlsx, booth_export_option: 'all')
%li= link_to 'Confirmed', admin_conference_booths_path(@conference.short_title, format: :xlsx, booth_export_option: 'confirmed')
= "(#{@booths.length})" if @booths.any?
%p.text-muted
All the booth requests

View file

@ -11,6 +11,10 @@
%dd
= @cfp.end_date.strftime('%A, %B %e. %Y')
%dt
Days Left:
Description
%dd
= markdown(@cfp.description)
%dt
Days Left
%dd
= pluralize(@cfp.remaining_days, 'day')

View file

@ -10,6 +10,10 @@
End Date:
%dd#end_date
= @cfp.end_date.strftime('%A, %B %-d. %Y')
%dt
Description:
%dd#description
= markdown(@cfp.description)
%dt
Days Left:
%dd

View file

@ -8,5 +8,6 @@
= f.input :start_date, as: :string, input_html: { id: 'registration-period-start-datepicker', start_date: @conference.start_date, end_date: @conference.end_date, readonly: 'readonly' }
= f.input :end_date, as: :string, input_html: { id: 'registration-period-end-datepicker', readonly: 'readonly' }
= f.input :cfp_type, as: :select, collection: (@cfp.new_record? ? @program.remaining_cfp_types : [@cfp.cfp_type] + @program.remaining_cfp_types).map {|type| ["#{type.capitalize}", type]}, include_blank: false, label: 'Type', input_html: { class: 'select-help-toggle' }
= f.input :description, input_html: {rows: 2, data: { provide: 'markdown-editable' } }, hint: markdown_hint
%p.text-right
= f.action :submit, as: :button, button_html: { class: 'btn btn-primary' }

View file

@ -10,6 +10,10 @@
End Date:
%dd#end_date
= @cfp.end_date.strftime('%A, %B %-d. %Y')
%dt
Description:
%dd#description
= markdown(@cfp.description)
%dt
Days Left:
%dd

View file

@ -12,6 +12,7 @@
%th Type
%th Start Date
%th End Date
%th Description
%th Days Left
%th Actions
%tbody
@ -24,6 +25,9 @@
= cfp.start_date.strftime('%A, %B %-d. %Y')
%td
= cfp.end_date.strftime('%A, %B %-d. %Y')
%td
%p
= markdown(truncate(cfp.description))
%td
= pluralize(cfp.remaining_days, 'day')
%td

View file

@ -22,11 +22,11 @@
= f.input :timezone, as: :time_zone, hint: 'The conference time zone'
= f.input :start_date, as: :string, input_html: { id: 'conference-start-datepicker', readonly: 'readonly' }
= f.input :end_date, as: :string, input_html: { id: 'conference-end-datepicker', readonly: 'readonly' }
= f.input :start_hour, input_html: {size: 2, type: 'number', min: 0, max: 23}
= f.input :end_hour, input_html: {size: 2, type: 'number', min: 1, max: 24}
= f.input :start_hour, input_html: {size: 2, type: 'number', min: 0, max: 23}, hint: rescheduling_hint(@affected_event_count)
= f.input :end_hour, input_html: {size: 2, type: 'number', min: 1, max: 24}, hint: rescheduling_hint(@affected_event_count)
= f.inputs name: 'Registrations' do
= f.input :registration_limit, as: :number, in: 0..9999, hint: 'Limit the number of registrations to the conference (0 no limit). Please note that the registration limit doesn\'t apply to speakers of confirmed events (they will still be able to register even if it has been reached). You currently have ' + pluralize(@conference.registrations.count, 'registration')
= f.inputs name: 'Booths' do
= f.input :booth_limit, as: :number, in: 0..9999,
hint: 'Booth limit is the maximum number of booths that you can accept for this conference. By setting this number (0 no limit) you can be sure that you are not going to accept more booths than the conference can accommodate. You currently have ' + pluralize(@conference.booths.accepted.count, 'accepted booth') +'.'
= f.action :submit, as: :button, button_html: {class: 'btn btn-primary'}
= f.action :submit, as: :button, button_html: { class: 'btn btn-primary', data: { confirm: 'Are you sure you want to proceed?' } }

View file

@ -4,6 +4,7 @@
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -12,8 +13,15 @@
= CSV.generate_line ['All Events']
= CSV.generate_line headers
- @events.each do |event|
= CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name, event.speaker_names, event.event_type.title,
= CSV.generate_line([event.id,
event.title,
event.abstract,
(event.time.present? ? "#{event.time.strftime("%Y-%m-%d")}#{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name,
event.speaker_names,
event.speaker_emails,
event.event_type.title,
(event.track.present? ? event.track.name : ''),
(event.difficulty_level.present? ? event.difficulty_level.title : ''),
(event.room.present? ? event.room.name : ''), event.state]).html_safe
(event.room.present? ? event.room.name : ''),
event.state]).html_safe

View file

@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
@ -30,5 +32,5 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
end
pdf.text "#{@conference.short_title} Events", font_size: 25, align: :center
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1}
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45]
end

View file

@ -1,6 +1,18 @@
wb.add_worksheet(name: 'all events') do |sheet|
bold_style = wb.styles.add_style(b: true)
row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State']
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Event ID',
'Title',
'Abstract',
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
'Room',
'State']
sheet.add_row row, style: bold_style
@events.each do |event|
@ -11,11 +23,13 @@ wb.add_worksheet(name: 'all events') do |sheet|
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
row << (event.room.present? ? event.room.name : '')
row << event.state
sheet.add_row row
sheet.add_row row , style: wrap_text
sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10
end
end

View file

@ -4,6 +4,7 @@
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -16,8 +17,17 @@
- all_comments = ''
- event.root_comments.each do |comment|
- all_comments << "#{comment.created_at.strftime("%Y-%m-%d")} #{comment.created_at.strftime("%I:%M%p")} #{comment.user.name}: #{comment.body}\n"
= CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name, event.speaker_names, event.event_type.title,
= CSV.generate_line([event.id,
event.title,
event.abstract,
(event.time.present? ? "#{event.time.strftime("%Y-%m-%d")}#{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name,
event.speaker_names,
event.speaker_emails,
event.event_type.title,
(event.track.present? ? event.track.name : ''),
(event.difficulty_level.present? ? event.difficulty_level.title : ''),
(event.room.present? ? event.room.name : ''), event.state, all_comments]).html_safe
(event.room.present? ? event.room.name : ''),
event.state,
all_comments]).html_safe

View file

@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
@ -31,7 +33,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
pdf.text "#{@conference.short_title} Events", font_size: 25, align: :center
pdf.move_down 10
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1, position: :center}
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1, position: :center},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45]
pdf.start_new_page
pdf.text "#{@conference.short_title} Comments", font_size: 25, align: :center
pdf.move_down 20

View file

@ -1,8 +1,20 @@
wb.use_shared_strings = true
wb.add_worksheet(name: 'events with comments') do |sheet|
bold_style = wb.styles.add_style(b: true )
bold_style = wb.styles.add_style(b: true)
cell_style = wb.styles.add_style(alignment: { wrap_text: true, vertical: :top })
row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State', 'Comments']
row = ['Event ID',
'Title',
'Abstract',
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
'Room',
'State',
'Comments']
sheet.add_row row, style: bold_style
@events.each do |event|
@ -17,6 +29,7 @@ row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'E
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
@ -24,5 +37,6 @@ row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'E
row << event.state
row << all_comments.strip
sheet.add_row row, style: cell_style
sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10
end
end

View file

@ -4,6 +4,7 @@
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -12,8 +13,15 @@
= CSV.generate_line ["Confirmed Events"]
= CSV.generate_line headers
- @events.confirmed.each do |event|
= CSV.generate_line([event.id, event.title, event.abstract, (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name, event.speaker_names, event.event_type.title,
= CSV.generate_line([event.id,
event.title,
event.abstract,
(event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : ''),
event.submitter.name,
event.speaker_names,
event.speaker_emails,
event.event_type.title,
(event.track.present? ? event.track.name : ''),
(event.difficulty_level.present? ? event.difficulty_level.title : ''),
(event.room.present? ? event.room.name : ''), event.state]).html_safe
(event.room.present? ? event.room.name : ''),
event.state]).html_safe

View file

@ -6,6 +6,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
@ -21,6 +22,7 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
@ -30,6 +32,6 @@ prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout:
end
pdf.text "#{@conference.short_title} Confirmed Events", font_size: 25, align: :center
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1}
pdf.table events_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,60,90,50,70,65,85,50,55,50,60,45]
end

View file

@ -1,6 +1,18 @@
wb.add_worksheet(name: 'confirmed events') do |sheet|
bold_style = wb.styles.add_style(b: true)
row = ['Event ID', 'Title', 'Abstract', 'Start time', 'Submitter', 'Speaker', 'Event Type', 'Track', 'Difficulty Level', 'Room', 'State']
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Event ID',
'Title',
'Abstract',
'Start time',
'Submitter',
'Speaker',
'Speaker Email',
'Event Type',
'Track',
'Difficulty Level',
'Room',
'State']
sheet.add_row row, style: bold_style
@events.confirmed.each do |event|
@ -11,11 +23,13 @@ wb.add_worksheet(name: 'confirmed events') do |sheet|
row << (event.time.present? ? "#{event.time.strftime("%Y-%m-%d")} #{event.time.strftime("%I:%M%p")} " : '')
row << event.submitter.name
row << event.speaker_names
row << event.speaker_emails
row << event.event_type.title
row << (event.track.present? ? event.track.name : '')
row << (event.difficulty_level.present? ? event.difficulty_level.title : '')
row << (event.room.present? ? event.room.name : '')
row << event.state
sheet.add_row row
sheet.add_row row , style: wrap_text
sheet.column_widths 10,15,35,13,18,18,28,12,15,15,15,10
end
end

View file

@ -0,0 +1,21 @@
- headers = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'Start Date',
'Submitter Name',
'Included in Cfp',
'State']
= CSV.generate_line ['All Tracks']
= CSV.generate_line headers
- @tracks.each do |track|
= CSV.generate_line([track.id,
track.name,
track.description,
track.try(:room).try(:name),
track.start_date,
track.end_date,
track.try(:submitter).try(:name),
track.cfp_active? ? 'Yes' : 'No',
track.state]).html_safe

View file

@ -0,0 +1,28 @@
prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf|
tracks_array = []
header_array = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'End Date',
'Submitter Name',
'Included in Cfp',
'State']
tracks_array << header_array
@tracks.each do |track|
row = []
row << track.id
row << track.name.to_s
row << track.description.to_s
row << track.try(:room).try(:name)
row << track.start_date.to_s
row << track.end_date.to_s
row << track.try(:submitter).try(:name)
row << (track.cfp_active? ? 'Yes' : 'No')
row << track.state
tracks_array << row
end
pdf.text "#{@conference.short_title} tracks", font_size: 25, align: :center
pdf.table tracks_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,70,230,65,55,55,90,65,50]
end

View file

@ -0,0 +1,29 @@
wb.add_worksheet(name: 'all tracks') do |sheet|
bold_style = wb.styles.add_style(b: true)
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'End Date',
'Submitter Name',
'Included in Cfp',
'State']
sheet.add_row row, style: bold_style
@tracks.each do |track|
row = []
row << track.id
row << track.name.to_s
row << track.description.to_s
row << track.try(:room).try(:name)
row << track.start_date.to_s
row << track.end_date.to_s
row << track.try(:submitter).try(:name)
row << (track.cfp_active? ? 'Yes' : 'No')
row << track.state
sheet.add_row row , style: wrap_text
sheet.column_widths 10,20,50,20,12,12,20,15,10
end
end

View file

@ -0,0 +1,21 @@
- headers = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'Start Date',
'Submitter Name',
'Included in Cfp',
'State']
= CSV.generate_line ['Confirmed Tracks']
= CSV.generate_line headers
- @tracks.confirmed.each do |track|
= CSV.generate_line([track.id,
track.name,
track.description,
track.try(:room).try(:name),
track.start_date,
track.end_date,
track.try(:submitter).try(:name),
track.cfp_active? ? 'Yes' : 'No',
track.state]).html_safe

View file

@ -0,0 +1,28 @@
prawn_document(force_download: true, filename: "#{@file_name}.pdf", page_layout: :landscape) do |pdf|
tracks_array = []
header_array = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'End Date',
'Submitter Name',
'Included in Cfp',
'State']
tracks_array << header_array
@tracks.confirmed.each do |track|
row = []
row << track.id
row << track.name.to_s
row << track.description.to_s
row << track.try(:room).try(:name)
row << track.start_date.to_s
row << track.end_date.to_s
row << track.try(:submitter).try(:name)
row << (track.cfp_active? ? 'Yes' : 'No')
row << track.state
tracks_array << row
end
pdf.text "#{@conference.short_title} tracks", font_size: 25, align: :center
pdf.table tracks_array, header: true, cell_style: {size: 8, border_width: 1},column_widths: [40,70,230,65,55,55,90,65,50]
end

View file

@ -0,0 +1,29 @@
wb.add_worksheet(name: 'all tracks') do |sheet|
bold_style = wb.styles.add_style(b: true)
wrap_text = wb.styles.add_style alignment: {wrap_text: true}
row = ['Track ID',
'Name',
'Description',
'Room',
'Start Date',
'End Date',
'Submitter Name',
'Included in Cfp',
'State']
sheet.add_row row, style: bold_style
@tracks.confirmed.each do |track|
row = []
row << track.id
row << track.name.to_s
row << track.description.to_s
row << track.try(:room).try(:name)
row << track.start_date.to_s
row << track.end_date.to_s
row << track.try(:submitter).try(:name)
row << (track.cfp_active? ? 'Yes' : 'No')
row << track.state
sheet.add_row row , style: wrap_text
sheet.column_widths 10,20,50,20,12,12,20,15,10
end
end

View file

@ -2,7 +2,32 @@
.row
.col-md-12
.page-header
%h1 Tracks
%h1
Tracks
.pull-right
- if can? :read, Track
.btn-group
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export PDF
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All Tracks', admin_conference_program_tracks_path(@conference.short_title, format: :pdf, track_export_option: 'all')
%li= link_to 'Confirmed Tracks', admin_conference_program_tracks_path(@conference.short_title, format: :pdf, track_export_option: 'confirmed')
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export CSV
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All', admin_conference_program_tracks_path(@conference.short_title, format: :csv, track_export_option: 'all')
%li= link_to 'Confirmed', admin_conference_program_tracks_path(@conference.short_title, format: :csv, track_export_option: 'confirmed')
.btn-group
%button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' }
Export XLS
%span.caret
%ul.dropdown-menu{ role: 'menu' }
%li= link_to 'All', admin_conference_program_tracks_path(@conference.short_title, format: :xlsx, track_export_option: 'all')
%li= link_to 'Confirmed', admin_conference_program_tracks_path(@conference.short_title, format: :xlsx, track_export_option: 'confirmed')
%p.text-muted
Categorize events in your conference
.row

View file

@ -0,0 +1,4 @@
- if @track_export_option == 'confirmed'
= render 'confirmed_tracks'
- elsif @track_export_option == 'all'
= render 'all_tracks'

View file

@ -0,0 +1,5 @@
if @track_export_option == 'confirmed'
render 'confirmed_tracks'
elsif @track_export_option == 'all'
render 'all_tracks'
end

View file

@ -0,0 +1,6 @@
wb = xlsx_package.workbook
if @track_export_option == 'confirmed'
render partial: 'confirmed_tracks', locals: { wb: wb }
elsif @track_export_option == 'all'
render partial: 'all_tracks', locals: { wb: wb }
end

View file

@ -4,7 +4,7 @@
.page-header
%h2 Upcoming Conferences
- @current.each do |conference|
= render partial: 'conference_details', locals: { conference: conference }
= render '/conferences/conference_details', conference: conference
-if @antiquated and @antiquated.any?
.row
.col-md-12
@ -17,7 +17,7 @@
%i.fa.fa-chevron-down{ style: 'display: none' }
#antiquated.collapse
- @antiquated.each do |conference|
= render partial: 'conference_details', locals: { conference: conference}
= render '/conferences/conference_details', conference: conference
-content_for :script_body do
:javascript

View file

@ -12,6 +12,8 @@
= f.input :name, input_html: { required: true }, hint: 'This is your real name'
= f.input :password, input_html: { required: true }
= f.input :password_confirmation, input_html: { required: true }
- Feature.with(:recaptcha) do
= recaptcha_tags
%p.text-right
= f.action :submit, as: :button, label: 'Sign Up', button_html: { class: 'btn btn-success' }

View file

@ -13,10 +13,8 @@
%span.icon-bar
%span.icon-bar
%span.icon-bar
- if conference.nil? || conference.new_record?
= link_to (ENV['OSEM_NAME'] || 'OSEM'), root_path, class: 'navbar-brand', title: 'Open Source Event Manager'
- else
= link_to conference.organization.name, organizations_path, class: 'navbar-brand', title: 'Open Source Event Manager'
= nav_root_link_for conference
.collapse.navbar-collapse#main-nav
- if content_for :splash_nav
%ul.nav.navbar-nav#splash-nav

View file

@ -9,15 +9,16 @@
= javascript_include_tag "application"
= csrf_meta_tags
:javascript
window.liveSettings = {
api_key: "#{ENV['OSEM_TRANSIFEX_APIKEY']}",
picker: "bottom-right",
detectlang: true,
autocollect: true
};
= content_for(:script_head)
= javascript_include_tag "//cdn.transifex.com/live.js"
- if ENV['OSEM_TRANSIFEX_APIKEY']
:javascript
window.liveSettings = {
api_key: "#{ENV['OSEM_TRANSIFEX_APIKEY']}",
picker: "bottom-right",
detectlang: true,
autocollect: true
};
= javascript_include_tag "//cdn.transifex.com/live.js"
= yield(:head)
%body

View file

@ -12,5 +12,7 @@
.caption
%h4
= organization.name
%button.btn.btn-success Conferences
= link_to 'Conferences',
conferences_organization_path(organization),
class: 'btn btn-success'
/ = link_to 'Edit', edit_organization_path(organization), class: 'btn btn-mini btn-default'

View file

@ -6,6 +6,14 @@
%span.notranslate
= @conference.title
- if @program.cfp_open?
- if @program.cfp.description.present?
.row
.col-md-12
= markdown(@program.cfp.description)
.row
.col-md-12
= render partial: 'encouragement_text'
@ -67,7 +75,7 @@
%small.text-muted
= event.event_type.title
= "(#{event.event_type.length} min)"
= "in #{event.traistck.name}" if event.track
= "in #{event.track.name}" if event.track
- if event.require_registration
%br
= link_to registered_text(event), registrations_conference_program_proposal_path(@conference.short_title, event), class: 'btn btn-xs btn-danger'

View file

@ -3,6 +3,11 @@
.col-md-12
.page-header
%h1 New Proposal
- if @program.cfp_open?
- if @program.cfp.description.present?
.row
.col-md-12
= markdown(@program.cfp.description)
.row
.col-md-12
= render partial: 'encouragement_text'

View file

@ -36,7 +36,8 @@
.col-md-8
%h4
= link_to speaker.name, user_path(speaker.id)
= "(#{speaker.email})"
- if speaker.email_public?
= "(#{speaker.email})"
- if speaker.affiliation?
.text-muted
from

View file

@ -1,4 +1,10 @@
#!/bin/bash
# set env os release variables
. /etc/os-release
if [[ "$ID" == "opensuse" ]]; then
pushd /vagrant
echo -e "\ninstalling required software packages...\n"
@ -14,6 +20,42 @@ echo 'install: --no-format-executable' >> /etc/gemrc
echo -e "\ninstalling bundler...\n"
gem.ruby2.4 install bundler
elif [[ "$ID" == "centos" || "$VERSION" == "7" ]]; then
_YELLOW='\033[1;33m' # yellow color
_LRED='\033[1;31m' # Light red color
_NO_COLOUR='\033[0m' # no color
printf "${_YELLOW}CEntOS-7 Setup${_NO_COLOUR}\n"
printf "${_YELLOW}installing ruby-2.4${_NO_COLOUR}\n"
yum install -q -y https://github.com/feedforce/ruby-rpm/releases/download/2.4.2/ruby-2.4.2-1.el7.centos.x86_64.rpm
if [[ ! "$?" -eq 0 ]]; then
printf "${_LRED}Error trying to install ruby-2.4${_NO_COLOUR}\n"
fi
printf "${_YELLOW}installing ruby-2.4 gems dependencies${_NO_COLOUR}\n"
gem install bundler
if [[ ! "$?" -eq 0 ]]; then
printf "${_LRED}Error trying to install ruby-2.4 bundler${_NO_COLOUR}\n"
fi
printf "${_YELLOW}installing nodejs repo${_NO_COLOUR}\n"
curl -sL https://rpm.nodesource.com/setup_9.x | bash - > /dev/null
printf "${_YELLOW}installing nodejs and devel tools${_NO_COLOUR}\n"
yum install -q -y git make gcc gcc-c++ libxml2-devel libxslt-devel nodejs screen mariadb mariadb-devel sqlite-devel ImageMagick bzip2
# for production: bundle install --without test development
printf "${_YELLOW}Opening firewall port: 3000${_NO_COLOUR}\n"
iptables -I INPUT -p tcp --dport 3000 -j ACCEPT
printf "${_YELLOW}installing phantomjs${_NO_COLOUR}\n"
curl -L --silent https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 -o /tmp/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar jxvf /tmp/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C /tmp/ phantomjs-2.1.1-linux-x86_64/bin/phantomjs
mv /tmp/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin
fi
echo -e "\ninstalling your bundle...\n"
su - vagrant -c "cd /vagrant/; bundle install --quiet"

View file

@ -0,0 +1,10 @@
require 'feature'
repo = Feature::Repository::SimpleRepository.new
# configure features here
unless(ENV['RECAPTCHA_SITE_KEY'].blank? || ENV['RECAPTCHA_SECRET_KEY'].blank?)
repo.add_active_feature :recaptcha
end
Feature.set_repository repo

View file

@ -149,7 +149,11 @@ Osem::Application.routes.draw do
get '/revision_history/:id/revert_object' => 'versions#revert_object', as: 'revision_history_revert_object'
get '/revision_history/:id/revert_attribute' => 'versions#revert_attribute', as: 'revision_history_revert_attribute'
end
resources :organizations, only: [:index]
resources :organizations, only: [:index] do
member do
get :conferences
end
end
resources :conferences, only: [:index, :show] do
resources :booths do
member do

View file

@ -0,0 +1,5 @@
class AddDescriptionToCfps < ActiveRecord::Migration
def change
add_column :cfps, :description, :text
end
end

View file

@ -68,12 +68,13 @@ ActiveRecord::Schema.define(version: 20170924190528) do
end
create_table "cfps", force: :cascade do |t|
t.date "start_date", null: false
t.date "end_date", null: false
t.date "start_date", null: false
t.date "end_date", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "program_id"
t.string "cfp_type"
t.text "description"
end
create_table "comments", force: :cascade do |t|

View file

@ -63,3 +63,7 @@ OSEM_SMTP_OPENSSL_VERIFY_MODE=""
# Enable the usage of the devise ichain plugin
OSEM_ICHAIN_ENABLED=false
# ReCAPTCHA keys
RECAPTCHA_SITE_KEY=""
RECAPTCHA_SECRET_KEY=""

View file

@ -2,6 +2,26 @@ require 'spec_helper'
describe OrganizationsController do
let!(:organization) { create(:organization) }
let!(:conference) do
create(
:conference,
splashpage: create(:splashpage, public: true),
venue: create(:venue),
organization: organization
)
end
let!(:antiquated_conference) do
create(
:conference,
splashpage: create(:splashpage, public: true),
venue: create(:venue),
organization: organization,
start_date: 2.weeks.ago,
end_date: 1.week.ago
)
end
let!(:other_conference) { create(:conference) }
let!(:user) { create(:user) }
describe 'GET #index' do
@ -12,4 +32,27 @@ describe OrganizationsController do
it { expect(response).to render_template('index') }
end
describe 'GET #conferences' do
before :each do
get :conferences, id: organization.id
end
it 'loads the organization' do
expect(assigns(:organization)).to eq organization
end
it 'includes organization conferences' do
expect(assigns(:current)).to include conference
end
it 'does not include conferences outside organization' do
expect(assigns(:current)).not_to include other_conference
expect(assigns(:antiquated)).not_to include other_conference
end
it 'includes antiquated organization conferences' do
expect(assigns(:antiquated)).to include antiquated_conference
end
end
end

View file

@ -5,7 +5,7 @@ FactoryGirl.define do
start_date { 1.day.ago }
end_date { 2.days.from_now }
cfp_type 'events'
description 'This is a test description'
program
end
end

View file

@ -48,4 +48,12 @@ feature Organization do
it_behaves_like 'successfully updates an organization'
end
context 'anonymously' do
scenario 'index should link to conferences list' do
visit organizations_path
expect(page).to have_link('Conferences', href: "/organizations/#{organization.id}/conferences")
end
end
end

View file

@ -62,14 +62,18 @@ feature Splashpage do
end
end
context 'public splashpage already created' do
context 'navigation' do
let!(:splashpage) { create(:splashpage, conference: conference, public: true)}
scenario 'should have organization name', feature: true, js: true do
sign_in participant
visit conference_path(conference.short_title)
context 'multiple organizations' do
let!(:additional_organization) { create(:organization) }
expect(page).to have_text(conference.organization.name)
scenario 'should have organization name', feature: true, js: true do
sign_in participant
visit conference_path(conference.short_title)
expect(page).to have_text(conference.organization.name)
end
end
end
end

View file

@ -58,5 +58,21 @@ describe ApplicationHelper, type: :helper do
expect(concurrent_events(event).present?).to eq false
end
end
describe 'navigation title link' do
it 'should default to OSEM' do
ENV.delete('OSEM_NAME')
expect(nav_root_link_for(nil)).to match 'OSEM'
end
it 'should use the environment variable' do
ENV['OSEM_NAME'] = Faker::Company.name + "'"
expect(nav_root_link_for(nil)).to match h(ENV['OSEM_NAME'])
end
it 'should use the conference organization name' do
expect(nav_root_link_for(conference)).to match h(conference.organization.name)
end
end
end
end

View file

@ -362,7 +362,7 @@ describe Event do
new_event.submitter = submitter
new_event.speakers = [speaker1, speaker2]
expect(new_event.speaker_names).to eq 'user speaker 1 and user speaker 2'
expect(new_event.speaker_names).to eq 'user speaker 1, user speaker 2'
end
end
end

View file

@ -15,8 +15,8 @@ describe Program do
it { is_expected.to have_many(:events).dependent(:destroy) }
it { is_expected.to have_many(:event_schedules).through(:events) }
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 have_many(:program_events_speakers).through(:events).source(:event_users) }
it { is_expected.to have_many(:speakers).through(:program_events_speakers).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) }

View file

@ -26,6 +26,10 @@ require 'phantomjs'
# makes it easier to control when PaperTrail is enabled during testing.
require 'paper_trail/frameworks/rspec'
# Make htmlescape() available
require 'erb'
include ERB::Util
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end