This commit is contained in:
Henne Vogelsang 2013-07-26 05:14:55 -07:00
commit 36c9f20e65
200 changed files with 2019 additions and 1696 deletions

3
.gitignore vendored
View file

@ -22,3 +22,6 @@ capybara-*.html
**.orig
rerun.txt
pickle-email-*.html
*~
/public/assets
/bundle

38
Gemfile
View file

@ -5,19 +5,32 @@ gem 'rails', '3.2.11'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
gem 'mysql2'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'sass-rails', '~> 3.2.3'
# gem 'coffee-rails', '~> 3.2.1'
gem 'bootstrap-sass'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'therubyracer', :platforms => :ruby
# gem 'uglifier', '>= 1.0.3'
gem 'uglifier', '>= 1.2.2'
end
group :development, :test do
gem 'pry'
gem 'sqlite3'
gem 'thin'
gem 'rspec-rails', '2.11.0'
end
group :production do
gem 'mysql2'
end
group :test do
gem 'capybara', '1.1.2'
end
gem 'will_paginate'
@ -36,15 +49,6 @@ gem 'transitions', :require => ["transitions", "active_record/transitions"]
gem 'acts_as_commentable_with_threading'
gem 'prawn'
gem 'prawn_rails'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'debugger'
gem 'gravtastic'
gem 'active_model_serializers'
gem 'axlsx_rails'

View file

@ -15,6 +15,8 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
active_model_serializers (0.8.1)
activemodel (>= 3.0)
activemodel (3.2.11)
activesupport (= 3.2.11)
builder (~> 3.0.0)
@ -37,28 +39,55 @@ GEM
arel (3.0.2)
awesome_nested_set (2.1.6)
activerecord (>= 3.0.0)
axlsx (1.3.6)
htmlentities (~> 4.3.1)
nokogiri (>= 1.4.1)
rubyzip (>= 0.9.5)
axlsx_rails (0.1.4)
axlsx
rails (>= 3.1)
bcrypt-ruby (3.0.1)
bootstrap-sass (2.3.2.0)
sass (~> 3.2)
builder (3.0.4)
cancan (1.6.10)
capybara (1.1.2)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11)
climate_control (0.0.3)
activesupport (>= 3.0)
cocaine (0.5.1)
climate_control (>= 0.0.3, < 1.0)
cocoon (1.1.2)
coderay (1.0.9)
daemons (1.1.9)
devise (2.2.4)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
diff-lcs (1.1.3)
erubis (2.7.0)
eventmachine (1.0.3)
execjs (1.4.0)
multi_json (~> 1.0)
ffi (1.9.0)
formtastic (2.2.1)
actionpack (>= 3.0)
formtastic-bootstrap (2.1.1)
formtastic (~> 2.2)
gravtastic (3.2.6)
haml (4.0.2)
tilt
hashery (2.1.0)
hike (1.2.2)
htmlentities (4.3.1)
i18n (0.6.4)
journey (1.0.4)
jquery-fileupload-rails (0.4.1)
@ -68,13 +97,18 @@ GEM
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.8.0)
libv8 (3.11.8.17)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
method_source (0.8.1)
mime-types (1.23)
mini_portile (0.5.0)
multi_json (1.7.3)
mysql2 (0.3.11)
nokogiri (1.6.0)
mini_portile (~> 0.5.0)
orm_adapter (0.4.0)
paper_trail (2.7.1)
activerecord (~> 3.0)
@ -98,6 +132,10 @@ GEM
prawn_rails (0.0.11)
prawn (>= 0.11.1)
railties (>= 3.0.0)
pry (0.9.12.2)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
@ -123,18 +161,46 @@ GEM
rake (10.0.4)
rdoc (3.12.2)
json (~> 1.4)
ref (1.0.5)
rspec (2.11.0)
rspec-core (~> 2.11.0)
rspec-expectations (~> 2.11.0)
rspec-mocks (~> 2.11.0)
rspec-core (2.11.1)
rspec-expectations (2.11.3)
diff-lcs (~> 1.1.3)
rspec-mocks (2.11.3)
rspec-rails (2.11.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec (~> 2.11.0)
ruby-rc4 (0.1.5)
rubyzip (0.9.9)
sass (3.2.5)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
selenium-webdriver (2.33.0)
childprocess (>= 0.2.5)
multi_json (~> 1.0)
rubyzip
websocket (~> 1.0.4)
slop (3.4.5)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.7)
therubyracer (0.11.4)
libv8 (~> 3.11.8.12)
ref
thin (1.5.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.18.1)
tilt (1.4.1)
transitions (0.1.8)
@ -143,20 +209,31 @@ GEM
polyglot (>= 0.3.1)
ttfunk (1.0.3)
tzinfo (0.3.37)
uglifier (2.1.1)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
warden (1.2.1)
rack (>= 1.0)
websocket (1.0.7)
will_paginate (3.0.4)
xpath (0.1.4)
nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
active_model_serializers
acts_as_commentable_with_threading
axlsx_rails
bcrypt-ruby (~> 3.0.0)
bootstrap-sass
cancan
capybara (= 1.1.2)
cocoon
devise
formtastic-bootstrap
gravtastic
haml
jquery-fileupload-rails
jquery-rails
@ -165,8 +242,13 @@ DEPENDENCIES
paperclip (~> 3.0)
prawn
prawn_rails
pry
rails (= 3.2.11)
rspec-rails (= 2.11.0)
sass-rails (~> 3.2.3)
sqlite3
therubyracer
thin
transitions
uglifier (>= 1.2.2)
will_paginate

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -17,5 +17,5 @@
//= require jquery-ui-timepicker-addon
//= require jquery.dataTables
//= require cocoon
//= require bootstrap.min
//= require bootstrap
//= require osem

View file

@ -1,4 +0,0 @@
jQuery ->
$("a[rel=popover]").popover()
$(".tooltip").tooltip()
$("a[rel=tooltip]").tooltip()

File diff suppressed because one or more lines are too long

View file

@ -1,3 +0,0 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View file

@ -242,3 +242,13 @@ $.extend( $.fn.dataTableExt.oPagination, {
}
} );
/* Commodity function for modal windows */
window.build_dialog = function(selector, content) {
// Close it and remove content if it's already open
$("#" + selector).modal('hide');
$("#" + selector).remove();
// Add new content and pops it up
$("body").append("<div id=\"" + selector + "\" class=\"modal fade\" role=\"dialog\">\n" + content + "</div>");
$("#" + selector).modal();
}

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/admin controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/call_for_papers controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/conference controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/people controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/supporters controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/users controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,3 +0,0 @@
// Place all the styles related to the admin/venue controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -1,9 +1,10 @@
/*
*= require bootstrap.min
*= require strap-on.css.scss
*= require formtastic-bootstrap
*= require osem
*= require jquery-ui-1.9.2.custom
*= require jquery.fileupload-ui
*= require jquery-ui-timepicker-addon
*= require jquery.dataTables_themeroller
*= require osem-schedule-print
*/

File diff suppressed because one or more lines are too long

View file

@ -1,3 +0,0 @@
// Place all the styles related to the home controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View file

@ -0,0 +1,64 @@
@media print {
.navbar {
display: none;
}
.nav li, .tab-pane, #messages, #footer, h2, .text-error, br, .label, .schedule-subtitle, .schedule-track {
display: none;
}
.nav li.active, .tab-pane .active {
display: block;
width: 100%;
text-align: center;
text-size: 12px;
border-style: none;
font-weight: bold;
}
.nav-tabs {
border-bottom-style: none;
}
.nav-tabs > .active > a {
border-style: none;
}
#wrap {
min-height:0px;
height:auto;
margin:0px;
line-height: 12px;
font-size: 10px;
}
#content {
position: absolute;
top: 0px;
left: 0px;
max-width: 210mm !important;
max-height: 297mm !important;
padding: 10px;
}
#schedule td.event {
background-image: none;
border-style:solid;
border-width: 2px;
border-color: black;
line-height: auto;
font-size: 10px;
}
.event img, .img-circle {
display: none;
}
h5 {
font-size: 10px;
line-height: 12px;
margin: 0px;
}
.table th, .table td {
line-height: 12px;
padding: 3px;
}
.schedule-speaker {
font-weight: normal;
font-style: italic;
}
}

View file

@ -1,65 +1,45 @@
html, body,.container,.content {
/* Sticky footer styles
-------------------------------------------------- */
html,
body {
height: 100%;
/* The html and body elements cannot have any padding or margin. */
}
#push,
#footer {
height: 60px;
}
.well {
background-color: white;
border: 1px solid #299A0B;
}
.container, .content {
position: relative;
}
#inner-content {
padding-top: 60px;
}
/* Wrapper for page content to push down footer */
#wrap {
min-height: 100%;
height: auto !important;
height: 100%;
/* Negative indent footer by it's height */
margin: 0 auto -60px;
}
/* Set the fixed height of the footer here */
#push,
#footer {
position: relative;
background-color: #ffffff;
height: 60px;
}
.navbar-inner {
background: #299a0b; /* Old browsers */
background: -moz-linear-gradient(top, #299a0b 0%, #299a0b 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#299a0b), color-stop(100%,#299a0b)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #299a0b 0%,#299a0b 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #299a0b 0%,#299a0b 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #299a0b 0%,#299a0b 100%); /* IE10+ */
background: linear-gradient(to bottom, #299a0b 0%,#299a0b 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#299a0b', endColorstr='#299a0b',GradientType=0 ); /* IE6-9 */
#footer {
background-color: #f5f5f5;
}
.navbar .nav .active > a, .navbar .nav .active > a:hover {
background-color: #DFE0DF;
.container .credit {
margin: 20px 0;
}
.navbar .divider-vertical {
background-color: #b4e391;
border-right: 1px solid #eab92d;
/* Lastly, apply responsive CSS fixes as necessary */
@media (max-width: 767px) {
#footer {
margin-left: -20px;
margin-right: -20px;
padding-left: 20px;
padding-right: 20px;
}
}
.navbar-fixed-top .brand {
color: #ffffff;
text-shadow:none;
}
.navbar .nav > li > a {
float: none;
padding: 10px 15px 10px;
color: white;
text-decoration: none;
text-shadow: none;
@media screen and (min-width: 980px) {
body { padding-top: 60px; }
}
.center {
@ -67,10 +47,6 @@ html, body,.container,.content {
float:none;
}
.center-text {
text-align: center
}
textarea {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
@ -153,3 +129,62 @@ div.dataTables_scrollFoot table {
border-top: none;
}
#schedule td.event {
background-image: linear-gradient(bottom, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
background-image: -o-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
background-image: -moz-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
background-image: -webkit-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
background-image: -ms-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.24, rgb(247,250,242)),
color-stop(0.97, rgb(194,232,190)),
color-stop(1, rgb(194,232,190))
);
}
#schedule td.event:hover
{
background-image: linear-gradient(bottom, rgb(247,250,242) 24%, rgb(83,171,74) 97%, rgb(83,171,74) 100%);
background-image: -o-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(83,171,74) 97%, rgb(83,171,74) 100%);
background-image: -moz-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(83,171,74) 97%, rgb(83,171,74) 100%);
background-image: -webkit-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(83,171,74) 97%, rgb(83,171,74) 100%);
background-image: -ms-linear-gradient(bottom, rgb(247,250,242) 24%, rgb(83,171,74) 97%, rgb(83,171,74) 100%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.24, rgb(247,250,242)),
color-stop(0.97, rgb(83,171,74)),
color-stop(1, rgb(83,171,74))
);
}
.flexvideo {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
}
.flexvideo iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.schedule-title, .schedule-subtitle, .schedule-speaker, .schedule-track {
clear: none;
display: block;
}
.schedule-subtitle {
color: rgb(185, 74, 72);
}

View file

@ -0,0 +1,15 @@
$navbarBackground: #299a0b;
$navbarBackgroundHighlight: #299a0b;
$navbarBorder: 1px solid #d4d4d4;
$navbarText: #ffffff;
$navbarLinkColor: white;
$navbarLinkColorHover: black;
$navbarLinkBackgroundActive: #DFE0DF;
@import "bootstrap";
@import "bootstrap-responsive";
/* Set to navbarBackgroundHighlight otherwise */
.navbar .nav > li > a {
text-shadow: none;
}

View file

@ -1,6 +1,5 @@
class Admin::CallforpapersController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
@cfp = @conference.call_for_papers

View file

@ -1,6 +1,5 @@
class Admin::ConferenceController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
@conferences = Conference.all
@ -31,6 +30,7 @@ class Admin::ConferenceController < ApplicationController
end
def show
@conferences = Conference.all
@conference = Conference.find_all_by_short_title(params[:id]).first
respond_to do |format|
format.html

View file

@ -1,6 +1,5 @@
class Admin::DietchoicesController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :diets_list

View file

@ -1,6 +1,5 @@
class Admin::EmailsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def update
@conference.email_settings.update_attributes(params[:email_settings])

View file

@ -1,6 +1,5 @@
class Admin::EventsController < ApplicationController
before_filter :verify_organizer
layout "admin"
# FIXME: The timezome should only be applied on output, otherwise
# you get lost in timezone conversions...
# around_filter :set_timezone_for_this_request
@ -12,15 +11,18 @@ class Admin::EventsController < ApplicationController
def index
@events = @conference.events
@tracks = @conference.tracks
@event_states = @events.state_machine.states.map
respond_to do |format|
format.html
format.json { render :json => Event.where(:state => :confirmed) }
# Explicity call #to_json to avoid the use of EventSerializer
format.json { render :json => Event.where(:state => :confirmed).to_json }
end
end
def show
@event = @conference.events.find(params[:id])
@tracks = @conference.tracks
@event_types = @conference.event_types
@comments = @event.root_comments
@comment_count = @event.comment_threads.count
end
@ -53,16 +55,21 @@ class Admin::EventsController < ApplicationController
if params.has_key? :track_id
@event.update_attribute(:track_id, params[:track_id])
end
if params.has_key? :event_type_id
@event.update_attribute(:event_type_id, params[:event_type_id])
end
expire_page :controller => '/schedule', :action => :index
redirect_back_or_to(admin_conference_event_path(@conference.short_title, @event), :notice => "Updated")
end
def create
expire_page :controller => '/schedule', :action => :index
end
def update_state
event = Event.find(params[:id])
event.send(:"#{params[:transition]}!", :send_mail => params[:send_mail])
expire_page :controller => '/schedule', :action => :index
redirect_to(admin_conference_events_path(:conference_id => @conference.short_title), :notice => "Updated state")
end
end

View file

@ -1,6 +1,5 @@
class Admin::EventtypeController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :event_type_list

View file

@ -1,6 +1,6 @@
class Admin::PeopleController < ApplicationController
before_filter :verify_organizer
layout "admin"
respond_to :html
def index
@people = Person.all
@ -16,16 +16,28 @@ class Admin::PeopleController < ApplicationController
end
end
def create
def new
@person = Person.new
end
def create
@person = Person.new(params[:person])
flash[:notice] = 'Person was successfully created.' if @person.save
respond_with @person, :location => admin_people_path
end
def show
@person = Person.find(params[:id])
end
def update
def edit
@person = Person.find(params[:id])
end
def update
@person = Person.find(params[:id])
flash[:notice] = 'Person was successfully updated' if @person.update_attributes(params[:person])
respond_with @person, :location => admin_people_path
end
def delete

View file

@ -1,16 +1,131 @@
class Admin::RegistrationsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
session[:return_to] ||= request.referer
@pdf_filename = "#{@conference.title}.pdf"
@registrations = @conference.registrations.all(:joins => :person,
:order => "people.last_name ASC",
:select => "registrations.*,
people.last_name AS last_name,
people.first_name AS first_name,
people.public_name AS public_name,
people.email AS email")
@registrations = @conference.registrations.includes(:person).order("registrations.created_at ASC")
@attended = @conference.registrations.where("attended = ?", true).count
@headers = %w[name email attending_social_events attending_with_partner need_access other_needs arrival departure attended]
end
def change_field
@registration = Registration.find(params[:id])
field = params[:view_field]
if @registration.send(field.to_sym)
@registration.update_attribute(:"#{field}",0)
else
@registration.update_attribute(:"#{field}",1)
end
redirect_to admin_conference_registrations_path(@conference.short_title, @registration)
flash[:notice] = "Updated '#{params[:view_field]}' for #{(Person.where("id = ?", @registration.person_id).first).email}"
end
def edit
@registration = @conference.registrations.where("id = ?", params[:id]).first
@person = Person.where("id = ?", @registration.person_id).first
end
def update
reg_id = params[:format]
@registration = @conference.registrations.where("id = ?", reg_id).first
@person = Person.where("id = ?", @registration.person_id).first
begin
@person.update_attributes!(params[:registration][:person_attributes])
params[:registration].delete :person_attributes
if params[:registration][:supporter_registration]
@registration.supporter_registration.update_attributes(params[:registration][:supporter_registration_attributes])
params[:registration].delete :supporter_registration_attributes
end
@registration.update_attributes!(params[:registration])
flash[:notice] = "Successfully updated registration for #{@person.public_name} #{@person.email}"
redirect_to(admin_conference_registrations_path(@conference.short_title))
rescue Exception => e
Rails.logger.debug e.backtrace.join("\n")
redirect_to(admin_conference_registrations_path(@conference.short_title), :alert => 'Failed to update registration:' + e.message)
return
end
end
def new
@user = User.new
@person = Person.new
@registration = @person.registrations.new
@supporter_registration = @conference.supporter_registrations.new
@conference = Conference.find_all_by_short_title(params[:conference_id]).first
end
def create
@conference = Conference.find_all_by_short_title(params[:conference_id]).first
email = params[:registration][:person].delete(:user)[:email]
@person = Person.find_by_email email
@registration = nil
@user = nil
if @person
if @person.registrations.where(conference_id: @conference).empty?
@person.attributes = params[:registration][:person] # Should we really modify person information?
else
redirect_to admin_conference_registrations_path(@conference.short_title)
flash[:notice] = "#{@person.email} is already registred!"
return
end
else
@person = Person.new params[:registration][:person]
end
@person.email = email
@user = @person.user
if @user.nil?
@user = @person.build_user
@user.password = rand(36**6).to_s(36)
@user.skip_confirmation!
end
@user.email = @person.email
@registration = @person.registrations.build
if params[:registration][:supporter_registration]
@supporter_registration = @registration.build_supporter_registration
@supporter_registration.attributes = params[:registration][:supporter_registration]
@supporter_registration.conference_id = @conference.id
else
@supporter_registration = @conference.supporter_registrations.new
end
params[:registration].delete :person
params[:registration].delete :user
params[:registration].delete :supporter_registration
@registration.attributes = params[:registration]
@registration.conference_id = @conference.id
@registration.attended = true
begin
Registration.transaction do
@person.save!
@user.save!
@registration.save!
end
flash[:notice] = "Successfully created new registration for #{@person.email}."
redirect_to admin_conference_registrations_path(@conference.short_title)
rescue ActiveRecord::RecordInvalid
render action: "new"
end
end
def delete
if has_role?(current_user, "Admin")
registration = @conference.registrations.where(:id => params[:id]).first
person = Person.where("id = ?", registration.person_id).first
begin registration.destroy
redirect_to admin_conference_registrations_path
flash[:notice] = "Deleted registration for #{person.public_name} #{person.email}"
rescue Exception => e
Rails.logger.debug e.backtrace.join("\n")
redirect_to(admin_conference_registrations_path(@conference.short_title), :alert => 'Failed to delete registration:' + e.message)
return
end
else
redirect_to(admin_conference_registrations_path(@conference.short_title), :alert => 'You must be an admin to delete a registration.')
end
end
end

View file

@ -1,6 +1,5 @@
class Admin::RoomsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :rooms_list

View file

@ -47,6 +47,7 @@ class Admin::ScheduleController < ApplicationController
startTime = DateTime.strptime(time, "%Y-%m-%d %k:%M")
event.start_time = startTime
event.save!
expire_page :controller => '/schedule', :action => :index
render :json => {"status" => "ok"}
end

View file

@ -1,6 +1,5 @@
class Admin::SocialEventsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :social_events_list

View file

@ -0,0 +1,17 @@
class Admin::SpeakersController < ApplicationController
before_filter :verify_organizer
respond_to :js, :html
def edit
@event = @conference.events.find(params[:event_id])
@speaker = @event.event_people.where(:event_role => "speaker").first
end
def update
@event = @conference.events.find(params[:event_id])
@speaker = @event.event_people.where(:event_role => "speaker").first
@speaker.person_id = params[:speaker][:person_id]
@speaker.save
respond_with @speaker, :location => admin_conference_events_path(@conference.short_title)
end
end

View file

@ -0,0 +1,32 @@
class Admin::StatsController < ApplicationController
before_filter :verify_organizer
def index
@registrations = @conference.registrations.includes(:person).order("registrations.created_at ASC")
@attendees = @conference.registrations.where("attended = ?", true).count
@registered = @conference.registrations.count
@registered_with_partner = @conference.registrations.where("attending_with_partner = ?", true).count
@attended_with_partner = @conference.registrations.where("attending_with_partner = ? AND attended = ?", true, true).count
@speakers = Person.joins(:events).where("events.conference_id = ? AND events.state LIKE ?", @conference.id, 'confirmed').uniq
@speaker_fields_person = %w[name email affiliation]
@speaker_fields_reg = %w[with_partner need_access other_needs diet arrival departure]
@supporter_levels = @conference.supporter_levels
@tickets = @conference.registrations.joins(:supporter_registration => :supporter_level)
@tickets = @tickets.where("registrations.conference_id" => @conference).count
end
def speaker_reg(speaker)
speaker.registrations.where("conference_id = ? AND person_id = ?", @conference.id, speaker.id).first
end
def speaker_diet(reg)
@conference.dietary_choices.find(reg.dietary_choice_id)
end
helper_method :speaker_reg
helper_method :speaker_diet
end

View file

@ -1,6 +1,5 @@
class Admin::SupporterLevelsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :supporter_levels

View file

@ -1,6 +1,5 @@
class Admin::SupportersController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
respond_to do |format|

View file

@ -1,6 +1,5 @@
class Admin::TracksController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
respond_to do |format|

View file

@ -1,6 +1,5 @@
class Admin::UsersController < ApplicationController
before_filter :verify_admin
layout "admin"
def index
@users = User.all(:joins => :person,

View file

@ -1,6 +1,5 @@
class Admin::VenueController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
end

View file

@ -0,0 +1,3 @@
class Api::BaseController < ActionController::Base
protect_from_forgery
end

View file

@ -0,0 +1,12 @@
class Api::V1::ConferencesController < Api::BaseController
respond_to :json
def index
if params[:conference_id].blank?
conferences = Conference.all
else
conferences = Conference.find_all_by_guid(params[:conference_id])
end
render :json => conferences, :serializer => ConferencesArraySerializer
end
end

View file

@ -0,0 +1,11 @@
class Api::V1::EventsController < Api::BaseController
respond_to :json
def index
events = Event.includes(:conference, :track, :room, :event_type, {:event_people => :person})
unless params[:conference_id].blank?
events = events.where("conferences.guid" => params[:conference_id])
end
respond_with events.confirmed
end
end

View file

@ -0,0 +1,13 @@
class Api::V1::RoomsController < Api::BaseController
respond_to :json
def index
if params[:conference_id].blank?
rooms = Room.all
else
conference = Conference.find_by_guid(params[:conference_id])
rooms = conference.rooms
end
respond_with rooms
end
end

View file

@ -0,0 +1,14 @@
class Api::V1::SpeakersController < Api::BaseController
respond_to :json
def index
if params[:conference_id].blank?
people = Person.joins(:event_people)
else
people = Person.joins(:event_people => {:event => :conference})
people = people.where("conferences.guid" => params[:conference_id])
end
people = people.where("event_people.event_role" => "speaker")
render :json => people, :each_serializer => SpeakerSerializer
end
end

View file

@ -0,0 +1,13 @@
class Api::V1::TracksController < Api::BaseController
respond_to :json
def index
if params[:conference_id].blank?
tracks = Track.all
else
tracks = Track.joins(:conference)
tracks = tracks.where("conferences.guid" => params[:conference_id])
end
respond_with tracks
end
end

View file

@ -1,6 +1,11 @@
class ApplicationController < ActionController::Base
include ApplicationHelper
protect_from_forgery
before_filter :get_conferences
def get_conferences
@conferences =Conference.all
end
def verify_user
:authenticate_user!

View file

@ -4,6 +4,7 @@ class ConferenceRegistrationController < ApplicationController
def register
# TODO Figure out how to change the route's id from :id to :conference_id
@conference = Conference.find_all_by_short_title(params[:id]).first
@workshops = @conference.events.where("require_registration = ? AND state LIKE ?", true, 'confirmed')
@person = current_user.person
if @person.first_name.blank? || @person.last_name.blank?
redirect_to(edit_user_registration_path, :alert => "Please fill in your first and last name before registering.")

View file

@ -1,7 +1,6 @@
class HomeController < ApplicationController
def index
@today = Date.current
@conferences = Conference.where("start_date >= ?", @today)
@current = Conference.where("start_date >= ?", @today)
end
end

View file

@ -1,10 +1,13 @@
class ProposalController < ApplicationController
before_filter :verify_user
before_filter :verify_user, :except => [:show]
before_filter :setup
before_filter :verify_access, :only => [:edit, :update, :destroy, :confirm]
def setup
@person = current_user.person
@person = current_user.person if current_user
#FIXME: @conference also comes from verify_user, but we need setup also in show
# which can be accessed anonymusly
@conference = Conference.find_all_by_short_title(params[:conference_id]).first
@url = conference_proposal_index_path(@conference.short_title)
@event_types = @conference.event_types
end
@ -44,7 +47,7 @@ class ProposalController < ApplicationController
@event_types = @conference.event_types
@attachments = @event.event_attachments
if @event.nil? || !@conference.cfp_open? || @event.unconfirmed? || @event.confirmed?
if @event.nil?
redirect_to(conference_proposal_index_path(:conference_id => @conference.short_title), :alert => 'Invalid or uneditable proposal.')
end
end
@ -135,6 +138,7 @@ class ProposalController < ApplicationController
def show
@event = Event.find(params[:id])
@speaker = @event.speakers.first || @event.submitter
end
def confirm

View file

@ -0,0 +1,12 @@
class ScheduleController < ApplicationController
layout "application"
def index
@conference = Conference.includes(:rooms, {:events => [:speakers, :track, :event_type]}).where("conferences.short_title" => params[:conference_id]).first
@rooms = @conference.rooms
@events = @conference.events
@dates = @conference.start_date..@conference.end_date
end
end

View file

@ -1,2 +0,0 @@
module Admin::CallForPapersHelper
end

View file

@ -1,2 +0,0 @@
module Admin::ConferenceHelper
end

View file

@ -1,2 +0,0 @@
module Admin::PeopleHelper
end

View file

@ -1,2 +0,0 @@
module Admin::SupportersHelper
end

View file

@ -1,2 +0,0 @@
module Admin::UsersHelper
end

View file

@ -1,2 +0,0 @@
module Admin::VenueHelper
end

View file

@ -1,4 +1,19 @@
module ApplicationHelper
def getdatetime(registration, field)
if registration.send(field.to_sym).kind_of?(String)
DateTime.parse(registration.send(field.to_sym)).strftime("%d %b %H:%M") if registration.send(field.to_sym)
else
registration.send(field.to_sym).strftime("%d %b %H:%M") if registration.send(field.to_sym)
end
end
def getdate(var)
if var.kind_of?(String)
DateTime.parse(var).strftime("%a, %d %b")
else
var.strftime("%a, %d %b")
end
end
def add_association_link(association_name, form_builder, div_class, html_options = {})
link_to_add_association "Add " + association_name.to_s.singularize, form_builder, div_class, html_options.merge(:class => "assoc btn btn-success")

View file

@ -1,2 +0,0 @@
module HomeHelper
end

View file

@ -2,14 +2,17 @@ class Event < ActiveRecord::Base
include ActiveRecord::Transitions
has_paper_trail
attr_accessible :title, :subtitle, :abstract, :description, :event_type_id, :people_attributes, :person,
:proposal_additional_speakers, :track_id
:proposal_additional_speakers, :track_id, :video_id, :video_type, :require_registration
acts_as_commentable
has_many :event_people, :dependent => :destroy
has_many :event_attachments, :dependent => :destroy
has_many :people, :through => :event_people
has_many :speakers, :through => :event_people, :source => :person, :conditions => {"event_people.event_role" => "speaker"}
belongs_to :event_type
has_and_belongs_to_many :registrations
belongs_to :track
belongs_to :room
belongs_to :conference
@ -24,6 +27,8 @@ class Event < ActiveRecord::Base
validates :title, :presence => true
validates :abstract, :presence => true
scope :confirmed, where(:state => "confirmed")
state_machine :initial => :new do
state :new
state :review

View file

@ -1,12 +1,17 @@
class Person < ActiveRecord::Base
include Gravtastic
gravtastic :size => 32
attr_accessible :email, :first_name, :last_name, :public_name, :biography, :company, :avatar, :irc_nickname
belongs_to :user, :inverse_of => :person
has_many :event_people, :dependent => :destroy
has_many :events, :through => :event_people, :uniq => true
has_many :registrations, :dependent => :destroy
validates :first_name, :presence => true
validates :last_name, :presence => true
validates :email, :presence => true
validate :biography_limit
before_create :generate_guid
@ -16,6 +21,9 @@ class Person < ActiveRecord::Base
:styles => {:tiny => "16x16>", :small => "32x32>", :large => "128x128>"},
:default_url => "person_:style.png"
validates_attachment_content_type :avatar, :content_type => [/jpg/, /jpeg/, /png/, /gif/]
alias_attribute :affiliation, :company
def to_s
if self.public_name.empty?
self.first_name + " " + self.last_name
@ -58,6 +66,19 @@ class Person < ActiveRecord::Base
Person.where(:user_id => user_id).first
end
def confirmed?
if User.exists?(self.user_id)
user = User.find(self.user_id)
if user.confirmed?
true
else
false
end
else
false
end
end
private
def biography_limit
if !self.biography.nil? && self.biography.split.size > 150
@ -79,17 +100,4 @@ class Person < ActiveRecord::Base
self.guid = guid
end
def confirmed?
if User.exists?(self.user_id)
user = User.find(self.user_id)
if user.confirmed?
true
else
false
end
else
false
end
end
end

View file

@ -4,13 +4,27 @@ class Registration < ActiveRecord::Base
belongs_to :dietary_choice
has_one :supporter_registration
has_one :supporter_level, :through => :supporter_registration
has_and_belongs_to_many :social_events
has_and_belongs_to_many :events
attr_accessible :person_id, :conference_id, :attending_social_events, :attending_with_partner,
:using_affiliated_lodging, :arrival, :departure, :person_attributes, :other_dietary_choice, :dietary_choice_id,
:handicapped_access_required, :supporter_registration_attributes, :social_event_ids, :other_special_needs
:handicapped_access_required, :supporter_registration_attributes, :social_event_ids, :other_special_needs,
:event_ids, :attended
accepts_nested_attributes_for :person
accepts_nested_attributes_for :supporter_registration
accepts_nested_attributes_for :social_events
delegate :first_name, :to => :person
delegate :last_name, :to => :person
delegate :public_name, :to => :person
delegate :email, :to => :person
delegate :irc_nickname, :to => :person
delegate :company, :to => :person
alias_attribute :with_partner, :attending_with_partner
alias_attribute :need_access, :handicapped_access_required
alias_attribute :other_needs, :other_special_needs
end

View file

@ -0,0 +1,26 @@
#
# suseconferenceclient relies on a 'revision' attribute for caching and
# doing some calculations.
#
# It should be incremented after any change in the conference or in any
# associated models
#
# This observer updates the revision column in a non-intrusive way,
# preventing validations, callbacks or exceptions to be triggered
#
# Relying on paper_trail could also be an option, but a 'revision' column
# in table 'conferences' looks like a more simple and straightforward solution
#
class RevisionObserver < ActiveRecord::Observer
observe :conference, :event, :room, :social_event, :track
def after_save(model)
begin
conference = model.kind_of?(Conference) ? model : model.conference
conference.reload.increment(:revision)
conference.update_column(:revision, conference.revision)
rescue
nil
end
end
end

View file

@ -1,7 +1,13 @@
class SupporterRegistration < ActiveRecord::Base
belongs_to :supporter_level
belongs_to :registration
before_save :set_attributes_from_person
attr_accessible :registration, :supporter_level_id, :name, :email, :supporter_level, :code, :code_is_valid, :conference_id
def set_attributes_from_person
self.name ||= registration.try(:person).try(:public_name)
self.email ||= registration.try(:person).try(:email)
true
end
end

View file

@ -8,7 +8,7 @@ class User < ActiveRecord::Base
:confirmable
has_and_belongs_to_many :roles
has_one :person
has_one :person, :inverse_of => :user
attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_ids, :person_attributes
accepts_nested_attributes_for :person
@ -50,7 +50,7 @@ class User < ActiveRecord::Base
private
def create_person
# TODO Search people for existing email address, add to their account
build_person(:email => self.email)
build_person(:email => self.email) if person.nil?
true
end
end

View file

@ -0,0 +1,35 @@
class ConferenceSerializer < ActiveModel::Serializer
attributes :guid, :name, :description, :year, :socialtag, :date_range, :url, :revision
def name
object.title
end
def year
object.start_date.try(:year)
end
def socialtag
object.social_tag
end
def revision
object.revision || 0
end
# FIXME: adjusting the format the DIRTY way, for oSC13.
# If you think this is ugly, don't look at the methods below
def date_range
object.date_range_string.try(:split, ",").try(:first)
end
# FIXME: just giving suseconferenceclient something to play with
def description
"openSUSE Conference 2013 - Power to the Geeko"
end
# FIXME: same than the former
def url
"https://conference.opensuse.org/"
end
end

View file

@ -0,0 +1,10 @@
#
# Needed in order to add the API version number to the conferences array
#
class ConferencesArraySerializer < ActiveModel::ArraySerializer
def as_json(*args)
json = super
json.merge!(:version => 1)
end
end

View file

@ -0,0 +1,42 @@
class EventSerializer < ActiveModel::Serializer
include ActionView::Helpers::TextHelper
attributes :guid, :title, :length, :date, :language, :abstract,
:speaker_ids, :type, :room, :track
def date
t = object.start_time
t.blank? ? "" : %(#{t.time.strftime("%Y-%m-%dT%H:%M:%S")}#{t.formatted_offset(false)})
end
def speaker_ids
speakers = object.event_people.select {|i| i.event_role == "speaker" }
speakers.map {|i| i.person.guid}
end
def type
object.event_type.try(:title)
end
def room
object.room.try(:guid)
end
def track
object.track.try(:guid)
end
def abstract
# This should never happen
if object.abstract.blank?
nil
else
simple_format(object.abstract).gsub("\n", "")
end
end
# FIXME: duplicated logic from Event#as_json
def length
object.event_type.try(:length) || 25
end
end

View file

@ -0,0 +1,8 @@
class RoomSerializer < ActiveModel::Serializer
attributes :guid, :name, :description
# FIXME: just giving suseconferenceclient something to play with
def description
""
end
end

View file

@ -0,0 +1,21 @@
class SpeakerSerializer < ActiveModel::Serializer
include ActionView::Helpers::TextHelper
attributes :guid, :name, :full_name, :company, :biography
def name
object.public_name
end
def full_name
[object.first_name, object.last_name].join(" ")
end
def biography
if object.biography.blank?
nil
else
simple_format(object.biography).gsub("\n", "")
end
end
end

View file

@ -0,0 +1,3 @@
class TrackSerializer < ActiveModel::Serializer
attributes :guid, :name, :color
end

View file

@ -1,5 +1,8 @@
.well.sidebar-nav
%ul.nav.nav-list
%li.nav-header
=@conference.short_title
Settings
- if activated == "Conference"
%li.active= link_to "Conference", "#"
- else

View file

@ -2,11 +2,12 @@
.span10
%h3
= @event.title
%i= @event.subtitle
%br
%span.muted
= @event.subtitle
.span2
= link_to "Edit Submission", "#",
:class => "btn btn-mini btn-primary pull-right", :style => "margin-top:20px;", :onclick => "javascript:alert('Not ready yet');"
= link_to "Edit", edit_conference_proposal_path(@conference.short_title, @event.id), :class => "btn btn-mini btn-primary"
.row-fluid
.span12
@ -15,7 +16,17 @@
%td
%b Type
%td
= @event.event_type.title
.dropdown
= link_to "#", :class => "dropdown-toggle", :id => "type-dropdown" do
- if @event.event_type.nil?
Track
- else
= @event.event_type.title
<b class="caret"></b>
%ul.dropdown-menu
- @event_types.each do |type|
%li= link_to type.title, admin_conference_event_path(@conference.short_title, @event, :event_type_id => type.id) ,
:method => :put, :event_type_id => type.id
%tr
%td
%b State

View file

@ -1,3 +1,91 @@
.row-fluid
.span
.row
%h5{:style=>"text-align: right"}
= link_to "Events Stats", "#", :id => "events-stats1-link", :class => "btn btn-success"
#events-stats1
%table.table.table-bordered.table-striped
%thead
%th
- @event_states.each do |state|
- totalstate = @events.where("state = ?", state.name).count
- if totalstate > 0
%th{:colspan => 2, :style => "text-align:center"}
Type "#{state.name}"
%th{:colspan => 2, :style => "text-align:center"}
Total
%br
No & Time
%tr
%td
%b Total
- @event_states.each do |state|
- totalstate = @events.where("state = ?", state.name).count
- if totalstate > 0
%td
%b= totalstate
%td
- length = 0
- @events.where("state = ?", state.name).each do |event|
- length += event.event_type.length
- length_hour = length / 60
%b
#{length_hour} h #{length-(length_hour*60)} m
%td
%b= @events.count
%td
- length = 0
- @events.each do |event|
- length += event.event_type.length
- length_hour = length / 60
%b
= length_hour
h
%b
= length-(length_hour*60)
m
- @conference.event_types.each do |type|
%tr
%td
%b= type.title
- @event_states.each do |state|
- totalstate = @events.where("state = ?", state.name).count
- if totalstate > 0
%td
- var = @events.where("event_type_id = ? AND state = ?", type.id, state.name)
- if var.count == 0
-
- else
= var.count
- length = 0
%td
- var.each do |e|
- length += e.event_type.length
- hour = length / 60
- min = length-(hour*60)
- if hour == 0 && min == 0
-
- else
= hour
h
= min
m
%td
= @events.where("event_type_id = ?", type.id).count
%td
- length = 0
- @events.where("event_type_id = ?", type.id).each do |event|
- length += event.event_type.length
- length_hour = length / 60
= length_hour
h
= length-(length_hour*60)
m
.row-fluid
.span12
%h2
@ -13,6 +101,8 @@
%b Title
%th
%b Submitter
%th
%b Speaker
%th
%b Type
%th
@ -36,6 +126,13 @@
(Unregistered!)
- else
Unknown submitter
%td
- if speaker = event.speakers.first
= link_to speaker.public_name, admin_person_path(speaker)
- else
Unknown speaker
- l = link_to "Change", edit_admin_conference_event_speaker_path(@conference.short_title, event), :remote => true
= "(#{l})".html_safe
%td
= event.event_type.title
%td
@ -87,3 +184,9 @@
"bPaginate": false
} );
} );
$(document).ready( function() {
$("#events-stats1-link").click(function() {
$("#events-stats1").toggle();
});
});

View file

@ -0,0 +1,10 @@
= semantic_form_for [:admin, @person] do |f|
= f.inputs "Basic Information" do
= f.input :first_name, :as => :string
= f.input :last_name, :as => :string
= f.input :public_name, :as => :string
= f.input :email
= f.input :company, :as => :string
= f.input :biography, :input_html => {:rows => 10}
= f.actions do
= f.action :submit, :button_html => {:class => "btn primary"}

View file

@ -1,29 +1,39 @@
%h2
People
- if @people
= "(#{@people.length})"
.well
%table.table.table-striped.table-bordered.table-hover#people
%thead
%th
%b Email
%th
%b Last Name
%th
%b First Name
%th
%b Public Name
%th
%b # of Conference Registrations
%th
- @people.each do |person|
%tr
%td= person.email
%td= person.last_name
%td= person.first_name
%td= person.public_name
%td= person.registrations.count
%td= link_to "View", admin_person_path(person)
.row-fluid
.span6
%h2
People
- if @people
= "(#{@people.length})"
.span6
.pull-right{:style=>"margin-top:20px; margin-bottom:20px;"}
= link_to "New person", new_admin_person_path, :class => "btn btn-success"
.row-fluid
.span12
.well
%table.table.table-striped.table-bordered.table-hover#people
%thead
%th
%b Email
%th
%b Last Name
%th
%b First Name
%th
%b Public Name
%th
%b # of Conference Registrations
%th
%th
- @people.each do |person|
%tr
%td= person.email
%td= person.last_name
%td= person.first_name
%td= person.public_name
%td= person.registrations.count
%td= link_to "Edit", edit_admin_person_path(person)
%td= link_to "View", admin_person_path(person)
:javascript
$(document).ready(function() {

View file

@ -0,0 +1,72 @@
.container-fluid
.row-fluid
.span12
%h3
Edit registration of #{@person.public_name} (#{@person.email}) for #{@conference.title}
%br
.row-fluid
.span12
= semantic_form_for(@registration, :url => admin_conference_registrations_edit_path(@conference.short_title, @registration.id), :html => { :method => :put }) do |f|
= f.inputs "Personal Information" do
= f.fields_for :person do |p|
= p.input :first_name, :as => :string
= p.input :last_name, :as => :string
= p.label :Nickname, :as => :string
= p.text_field :irc_nickname, :as => :string
= p.label :Affiliation
= p.text_field :company, :placeholder => "Company/User Group/nothing", :as => :string
= f.inputs "Registration Information" do
- if @conference.use_supporter_levels?
= f.semantic_fields_for :supporter_registration do |reg|
= reg.input :supporter_level, :as => :select, :collection => @conference.supporter_levels
= reg.input :code, :label => "Confirmation or registration code (if applicable)"
%span#supporter-link.help-block
= f.input :attending_with_partner, :label => false
= f.input :using_affiliated_lodging, :label => false
= f.input :handicapped_access_required, :label => false
= f.input :other_special_needs, :label => "Any other special needs?", :input_html => {:rows => 2, :class => "span6"}
- if @conference.social_events.count > 0
= f.inputs "Are you planning to attend any of the parties?" do
%br Yes, I'll be attending...
%br
= f.input :social_events, :as => :check_boxes, :label => false, :collection => @conference.social_events
- if @conference.use_dietary_choices?
= f.inputs "Food" do
= f.input :dietary_choice, :collection => [["None", nil]] + @conference.dietary_choices.map {|x| [x.title, x.id]},
:include_blank => false, :label => "Special Dietary Restriction"
= f.input :other_dietary_choice, :input_html => {:rows => "2", :class => "span6"}, :label => "Other Dietary Restictions (please describe)"
= f.action :submit, :button_html => { :value => "Edit Registration", :class => "btn btn-primary" }
:javascript
$("#registration_supporter_registration_attributes_supporter_level_id").change(function () {
var str = "";
#{generate_supporter_level_js @conference}
$("#supporter-link").html(str);
})
.trigger('change');
$("#registration-arrival-datepicker").datetimepicker({
dateFormat: "yy-mm-dd",
timeFormat: "HH:mm",
showSecond: false,
numberOfMonths: 1,
defaultDate: '#{@conference.start_date.yesterday.strftime('%Y-%m-%d')}',
onSelect: function(selected) {
$("#registration-departure-datepicker").datepicker("option","minDate", selected)
}
});
$("#registration-departure-datepicker").datetimepicker({
dateFormat: "yy-mm-dd",
timeFormat: "HH:mm",
showSecond: false,
numberOfMonths: 1,
defaultDate: '#{@conference.end_date.tomorrow.strftime('%Y-%m-%d')}',
onSelect: function(selected) {
$("#registration-arrival-datepicker").datepicker("option","maxDate", selected)
}
});

View file

@ -0,0 +1,74 @@
.row
.span12
%h3
Create new account and registration
.row
.span12
= semantic_form_for(@registration, :url => admin_conference_registrations_new_path(@conference.short_title), :html => { :method => :put }) do |f|
= f.inputs "Your details" do
= f.fields_for @person do |p|
= p.fields_for @user do |u|
= u.input :email, :as => :string, :hint => "Please enter a valid email address. You will need it to log in to OSEM later."
= p.input :first_name, :as => :string
= p.input :last_name, :as => :string
= p.input :public_name, :as => :string
= p.label :Nickname
= p.text_field :irc_nickname, :as => :string
= p.label :Affiliation
= p.text_field :company, :placeholder => "Company/User Group/nothing", :as => :string
= f.inputs "Registration Information" do
- if @conference.use_supporter_levels?
= f.semantic_fields_for @supporter_registration do |reg|
= reg.input :supporter_level, :as => :select, :collection => @conference.supporter_levels
= reg.input :code, :label => "Confirmation or registration code (if applicable)"
%span#supporter-link.help-block
= f.input :attending_with_partner, :label => false
= f.input :using_affiliated_lodging, :label => false
= f.input :handicapped_access_required, :label => false
= f.input :other_special_needs, :label => "Any other special needs?", :input_html => {:rows => 2, :class => "span6"}
- if @conference.social_events.count > 0
= f.inputs "Are you planning to attend any of the parties?" do
%br Yes, I'll be attending...
%br
= f.input :social_events, :as => :check_boxes, :label => false, :collection => @conference.social_events
- if @conference.use_dietary_choices?
= f.inputs "Food" do
= f.input :dietary_choice, :collection => [["None", nil]] + @conference.dietary_choices.map {|x| [x.title, x.id]},
:include_blank => false, :label => "Special Dietary Restriction"
= f.input :other_dietary_choice, :input_html => {:rows => "2", :class => "span6"}, :label => "Other Dietary Restictions (please describe)"
= f.action :submit, :button_html => { :value => "Create", :class => "btn btn-primary"}
:javascript
$("#registration_supporter_registration_attributes_supporter_level_id").change(function () {
var str = "";
#{generate_supporter_level_js @conference}
$("#supporter-link").html(str);
})
.trigger('change');
$("#registration-arrival-datepicker").datetimepicker({
dateFormat: "yy-mm-dd",
timeFormat: "HH:mm",
showSecond: false,
numberOfMonths: 1,
defaultDate: '#{@conference.start_date.yesterday.strftime('%Y-%m-%d')}',
onSelect: function(selected) {
$("#registration-departure-datepicker").datepicker("option","minDate", selected)
}
});
$("#registration-departure-datepicker").datetimepicker({
dateFormat: "yy-mm-dd",
timeFormat: "HH:mm",
showSecond: false,
numberOfMonths: 1,
defaultDate: '#{@conference.end_date.tomorrow.strftime('%Y-%m-%d')}',
onSelect: function(selected) {
$("#registration-arrival-datepicker").datepicker("option","maxDate", selected)
}
});

View file

@ -1,52 +1,60 @@
.row-fluid
.span12
.pull-right{:style=>"margin-top:20px; margin-bottom:20px;"}
= link_to "New", admin_conference_registrations_new_path(@conference.short_title), :class => "btn btn-primary"
= link_to "Export PDF", admin_conference_registrations_path(@conference.short_title, :format => :pdf), :class => "btn btn-success"
= link_to "Export xlsx", {:format => :xlsx}, :class => "btn btn-success"
.row-fluid
.span12
%h2
Registrations
- if @registrations
= "(#{@registrations.length})"
%table.table.table-striped.table-bordered.table-hover
= " - Attended (#{@attended})"
%table.table.table-striped.table-bordered.table-hover#registrations
%thead
%th
%b Last Name
%th
%b First Name
%th
%b Public Name
%th
%b Email
%th
%b Attending Social Events
%th
%b Attending With Partner
%th
%b Arrival Date
%th
%b Departure Date
No
- @headers.each do |h|
- h = h.gsub("_", " ")
%th
= h.capitalize
%th
%th
- counter = 0
- @registrations.each do |registration|
%tr
%td
= registration.last_name
= counter +=1
- @headers.each do |field|
%td
- if field == "name"
#{registration.last_name} #{registration.first_name} (#{registration.irc_nickname}) #{registration.company}
- if registration.supporter_level && registration.supporter_level.title != 'Free'
%p{:style => "color:red"}
= registration.supporter_level.title
-elsif field == 'attended'
= link_to "#{registration.send(field.to_sym)}", admin_conference_registrations_change_field_path(@conference.short_title, :id => registration.id, :view_field => "#{field}"), :method => :put, ":#{field}" => registration.send(field.to_sym), :class => "btn btn-success"
-elsif (registration.send(field.to_sym).class == TrueClass || registration.send(field.to_sym).class == FalseClass)
= link_to "#{registration.send(field.to_sym)}", admin_conference_registrations_change_field_path(@conference.short_title, :id => registration.id, :view_field => "#{field}"), :method => :put, ":#{field}" => registration.send(field.to_sym)
- elsif field == 'arrival' || field == 'departure'
= registration.send(field.to_sym).strftime("%d %b %H:%M") if registration.send(field.to_sym)
- else
= registration.send(field.to_sym)
%td
= registration.first_name
= link_to "Edit", admin_conference_registrations_edit_path(@conference.short_title, :id => registration.id), :method => :get, :class => "btn btn-primary"
%td
= registration.public_name
%td
= registration.email
%td
= registration.attending_social_events
%td
= registration.attending_with_partner
%td
= registration.arrival
%td
= registration.departure
%td
= link_to "Edit", "#", :class => "btn btn-primary"
%td
= link_to "Delete", "#", :class => "btn btn-danger", :confirm => "Really delete registration for #{registration.public_name}?"
= link_to "Delete", admin_conference_registrations_path(@conference.short_title, :id => registration.id), :method => :delete, :class => "btn btn-danger", :confirm => "Really delete registration for #{registration.public_name} #{registration.email}?"
:javascript
$(document).ready(function() {
$('#registrations').dataTable( {
"bPaginate": false,
"bLengthChange": false
} );
} );

View file

@ -0,0 +1,25 @@
wb = xlsx_package.workbook
wb.add_worksheet(:name => "registrations") do |sheet|
bold_style = wb.styles.add_style(:b => true)
row = ["Attended", "Name", "Nickname", "Affilation", "Email", "Social events",
"With partner", "Needs access", "Other needs", "Arrival", "Departure"]
sheet.add_row row, :style => bold_style
@registrations.each do |reg|
row = []
row << reg.attended
row << "#{reg.last_name} #{reg.first_name} (#{reg.public_name})"
row << reg.irc_nickname
row << reg.company
row << reg.email
row << reg.attending_social_events
row << reg.attending_with_partner
row << reg.need_access
row << reg.other_needs
row << reg.arrival
row << reg.departure
sheet.add_row row
end
sheet.column_info[8].width = [sheet.column_info[8].width, 30].min
end

View file

@ -0,0 +1,11 @@
.modal-header
%button.close{:type => "button", :data => {:dismiss => "modal"}} &times;
%h3
Assign speaker
= semantic_form_for @speaker, :as => :speaker, :url => admin_conference_event_speaker_path(@conference.short_title, @event), :method => :put do |f|
.form-inputs.form-horizontal.modal-body
= f.collection_select(:person_id, Person.order(:public_name), :id, :public_name)
.modal-footer
= link_to "Close", "#", :data => {:dismiss => "modal"}, :class => 'btn'
= f.button "Assign", :class => 'btn btn-primary'

View file

@ -0,0 +1,2 @@
build_dialog('edit_speaker', '<%= j render :partial => 'form' %>');

View file

@ -0,0 +1,72 @@
.row-fluid
.span12
%h3
Registered
- if @registered
= "(#{@registered})"
- if @attendees
= " - Attendees (#{@attendees})"
.row-fluid
.span3
%table.table.table-bordered.table-striped
%thead
%th General Stats
%th #
%tr
%td Registered attended
%td= @registered_attended
%tr
%td Registered not attended
%td= @registered_not_attended
%tr
%td Attended with partner
%td= @attended_with_partner
%tr
%td Registred to attend with partner
%td= @registered_with_partner
%tr
%td Handicapped Access for
%td= @conference.registrations.where("handicapped_access_required = ?", true).count
%tr
%td Staying at suggested hotel
%td= @conference.registrations.where("using_affiliated_lodging = ?", true).count
.span3
- if @conference.use_dietary_choices == true
- diet_choices = []
- @conference.dietary_choices.each do |d|
- count = @conference.registrations.where("dietary_choice_id = ?", d.id).count
- if count > 0
- diet_choices << [d.title, count]
- if diet_choices.any?
%table.table.table-bordered.table-striped
%thead
%th Dietary Choice
%th #
%th Percentage
- diet_choices.each do |d|
%tr
%td= d[0]
%td= d[1]
%td
- if @registered and @registered > 0
= "#{d[1] * 100 / @registered}% of registered"
- if @attendees and @attendees > 0
%br
= "#{d[1] * 100 / @attendees}% of attendees"
.span3
- if @conference.social_events.count > 0
- social_events = []
- @conference.social_events.each do |social_event|
- count = @conference.registrations.joins(:social_events).where("registrations_social_events.social_event_id = ?", social_event.id).count
- if count > 0
- social_events << [social_event.title, count]
- if social_events.any?
%table.table.table-bordered.table-striped
%thead
%th Social Event
%th #
- social_events.each do |s|
%tr
%td= s[0]
%td= s[1]

View file

@ -0,0 +1,43 @@
- count =0
%h3
Speakers (#{@speakers.length})
%table.table.table-striped.table-bordered.table-hover#speakertable
%thead
%th
ID
- (@speaker_fields_person + @speaker_fields_reg).each do |field|
%th
= field.capitalize
- @speakers.each do |speaker|
%tr
%td
= count +=1
- @speaker_fields_person.each do |field|
%td
- if field == 'name'
= speaker.first_name
= speaker.last_name
%br
(#{speaker.public_name})
- else
= speaker.send(field.to_sym)
- @speaker_fields_reg.each do |field|
%td
- reg = speaker_reg(speaker)
- if !reg.nil?
- if field == "diet"
- if reg.dietary_choice_id
= speaker_diet(reg).title
%br
= reg.other_dietary_choice
- elsif field == 'arrival' || field == 'departure'
= getdatetime(reg, field)
- else
= reg.send(field.to_sym)
:javascript
$(document).ready(function(){
$('#speakertable').dataTable({
"bPaginate": false
});
});

View file

@ -0,0 +1,28 @@
.row-fluid
.span12
%h3
Non-free Tickets (#{@tickets})
.row-fluid
.span5
- if @supporter_levels.count > 0
%table.table.table-bordered.table-striped
%thead
%th Support Level
%th #
%th %
- @supporter_levels.each do |level|
- reg_count = level.supporter_registrations.count
- if reg_count > 0
%tr
%td= level.title
%td
= reg_count
%td
- if @registered and @registered > 0
= "#{reg_count * 100 / @registered}% of registered"
- if @attendees and @attendees > 0
%br
= "#{reg_count * 100 / @attendees}% of attendees"
- else
%p
No tickets sold yet

View file

@ -0,0 +1,23 @@
.row-fluid
.span12
%ul.nav.nav-tabs#myTab
%li.active
%a{:href=>"#registrations", "data-toggle"=>"tab"} Registrations
%li
%a{:href=>"#speakers", "data-toggle"=>"tab"} Speakers
%li
%a{:href=>"#tickets", "data-toggle"=>"tab"} Tickets
.tab-content
.tab-pane.active#registrations
= render :partial => 'registrations'
.tab-pane#speakers
= render :partial => 'speakers'
.tab-pane#tickets
= render :partial => 'tickets'
:javascript
$('#myTab a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})

View file

@ -0,0 +1 @@
= render :partial => "form"

View file

@ -0,0 +1 @@
= render :partial => "form"

View file

@ -1,52 +1,55 @@
.container-fluid
.row-fluid
.row
.span12
%h3
Registration for
= @conference.title
- if @person.proposal_count(@conference) > 0
.row
.span12
%h3.pull-left
Registration for
= @conference.title
- if @person.proposal_count(@conference) > 0
.row-fluid
.span12
%i
Please note: Registration is not automatically performed for speakers. If you're scheduled to speak at the conference, you still need to register!
.row-fluid
.span12
= semantic_form_for(@registration, :url => register_conference_path(@conference.short_title), :html => { :method => :put }) do |f|
= f.inputs :name => "Your Details" do
%br
Your public name (required)
%br
= f.fields_for :person do |p|
= p.text_field :public_name, :for => :person
- if @conference.use_supporter_levels?
= f.semantic_fields_for :supporter_registration do |reg|
= reg.input :supporter_level, :as => :select, :collection => @conference.supporter_levels
= reg.input :code, :label => "Confirmation or registration code (if applicable)"
%span#supporter-link.help-block
%i
Please note: Registration is not automatically performed for speakers. If you're scheduled to speak at the conference, you still need to register!
.row
.span12
= semantic_form_for(@registration, :url => register_conference_path(@conference.short_title), :html => { :method => :put }) do |f|
= f.inputs :name => "Your Details" do
%br
Your public name (required)
%br
= f.fields_for :person do |p|
= p.text_field :public_name, :for => :person
- if @conference.use_supporter_levels?
= f.semantic_fields_for :supporter_registration do |reg|
= reg.input :supporter_level, :as => :select, :collection => @conference.supporter_levels
= reg.input :code, :label => "Confirmation or registration code (if applicable)"
%span#supporter-link.help-block
= f.input :attending_with_partner, :label => false
= f.input :using_affiliated_lodging, :label => false
= f.input :handicapped_access_required, :label => false
= f.input :other_special_needs, :label => "Any other special needs?", :input_html => {:rows => 2}
= f.input :attending_with_partner, :label => false
= f.input :using_affiliated_lodging, :label => false
= f.input :handicapped_access_required, :label => false
= f.input :other_special_needs, :label => "Any other special needs?", :input_html => {:rows => 2}
= f.inputs "Travel Info" do
= f.input :arrival, :as => :string, :input_html => {:value => (f.object.arrival.to_formatted_s(:db_without_seconds) unless f.object.arrival.nil?), :id => "registration-arrival-datepicker", :readonly => "readonly" }
= f.input :departure, :as => :string, :input_html => {:value => (f.object.departure.to_formatted_s(:db_without_seconds) unless f.object.departure.nil?), :id => "registration-departure-datepicker", :readonly => "readonly" }
- if @conference.social_events.count > 0
= f.inputs "Are you planning to attend any of the parties?" do
%br Yes, I'll be attending...
%br
= f.input :social_events, :as => :check_boxes, :label => false
- if @conference.use_dietary_choices?
= f.inputs "Food" do
= f.input :dietary_choice, :collection => [["None", nil]] + @conference.dietary_choices.map {|x| [x.title, x.id]},
:include_blank => false, :label => "Special Dietary Restriction"
= f.input :other_dietary_choice, :input_html => {:rows => "2"}, :label => "Other Dietary Restictions (please describe)"
- if @registered
= f.action :submit, :button_html => { :value => "Update Registration", :class => "btn btn-primary" }
= link_to "Unregister", register_conference_path(@conference.short_title),:method => :delete, :class => "btn btn-danger",
:confirm => "Are you sure you want to unregister?"
- else
= f.action :submit, :button_html => { :value => "Register", :class => "btn btn-primary" }
- if @workshops.count > 0
=f.inputs "Register to workshops" do
= f.input :events, :as => :check_boxes, :label => false, :collection => @workshops
= f.inputs "Travel Info" do
= f.input :arrival, :as => :string, :input_html => {:value => (f.object.arrival.to_formatted_s(:db_without_seconds) unless f.object.arrival.nil?), :id => "registration-arrival-datepicker", :readonly => "readonly" }
= f.input :departure, :as => :string, :input_html => {:value => (f.object.departure.to_formatted_s(:db_without_seconds) unless f.object.departure.nil?), :id => "registration-departure-datepicker", :readonly => "readonly" }
- if @conference.social_events.count > 0
= f.inputs "Are you planning to attend any of the parties?" do
%br Yes, I'll be attending...
%br
= f.input :social_events, :as => :check_boxes, :label => false
- if @conference.use_dietary_choices?
= f.inputs "Food" do
= f.input :dietary_choice, :collection => [["None", nil]] + @conference.dietary_choices.map {|x| [x.title, x.id]},
:include_blank => false, :label => "Special Dietary Restriction"
= f.input :other_dietary_choice, :input_html => {:rows => "2"}, :label => "Other Dietary Restictions (please describe)"
- if @registered
= f.action :submit, :button_html => { :value => "Update Registration", :class => "btn btn-primary" }
= link_to "Unregister", register_conference_path(@conference.short_title),:method => :delete, :class => "btn btn-danger",
:confirm => "Are you sure you want to unregister?"
- else
= f.action :submit, :button_html => { :value => "Register", :class => "btn btn-primary" }
:javascript
$("#registration_supporter_registration_attributes_supporter_level_id").change(function () {

View file

@ -1,5 +1,5 @@
.container
%h2.center-text
%h2.text-center
Sign Up
.row-fluid
.well.span3.offset2

View file

@ -1,5 +1,5 @@
.container
%h2.center-text
%h2.text-center
Sign In
.row-fluid
.well.span3.offset2

View file

@ -0,0 +1,52 @@
<div class="row">
<div class="span12">
<h2 class="text-center">Upcoming Conferences</h2>
</div>
</div>
<% @current.each do |conference| %>
<div class="row-fluid" style="margin-top: 30px;">
<div clas="span12">
<div class="well">
<div class="row">
<div class="span4 text-center">
<%= image_tag conference.logo(:original) %>
</div>
<div class="span6">
<h3>
<%= conference.title %>
<br>
<span class="muted"><%= conference.date_range_string %></span>
</h3>
<p>
<small>
<%= link_to conference.venue.name, conference.venue.website, :target => "_new" %>
,
<%= link_to conference.venue.address, "http://maps.google.com/maps?q=#{conference.venue.address}", :target => "_new" %>
</small>
<%= simple_format(conference.venue.description, class: 'lead') %>
</div>
<div class="span2">
<ul class="nav nav-tabs nav-stacked">
<% if conference.registration_open? %>
<%- if conference.user_registered?(current_user) %>
<li><%= link_to "Modify Registration", register_conference_path(conference.short_title) %></li>
<%- else %>
<li><%= link_to "Register", register_conference_path(conference.short_title) %></li>
<% end %>
<% end %>
<li><%= link_to "Schedule", conference_schedule_path(conference.short_title) %></li>
<%- if !current_user.nil? && current_user.person.proposal_count(conference) > 0 %>
<li><%= link_to "View My Proposals", conference_proposal_index_path(conference.short_title) %></li>
<%- elsif conference.cfp_open? %>
<li><%= link_to "Submit Proposal", conference_proposal_index_path(conference.short_title) %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
</div>
<% end %>

Some files were not shown because too many files have changed in this diff Show more