First checkin

This commit is contained in:
Matt Barringer 2013-01-07 09:04:09 +01:00
parent f207e2c8b7
commit 90b30db9e8
260 changed files with 37349 additions and 0 deletions

50
Gemfile Normal file
View file

@ -0,0 +1,50 @@
source 'https://rubygems.org'
gem 'rails', '3.2.9'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3'
# 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'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', :platforms => :ruby
gem 'uglifier', '>= 1.0.3'
end
gem 'paperclip', '~> 3.0'
gem 'jquery-rails'
gem 'jquery_datepicker'
gem 'jquery-fileupload-rails'
gem 'devise'
gem 'cancan'
gem "haml"
gem 'bcrypt-ruby', '~> 3.0.0'
gem 'node'
gem 'twitter-bootstrap-rails'
gem 'formtastic-bootstrap'
gem 'cocoon'
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'

183
Gemfile.lock Normal file
View file

@ -0,0 +1,183 @@
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.0.2)
actionmailer (3.2.9)
actionpack (= 3.2.9)
mail (~> 2.4.4)
actionpack (3.2.9)
activemodel (= 3.2.9)
activesupport (= 3.2.9)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.9)
activesupport (= 3.2.9)
builder (~> 3.0.0)
activerecord (3.2.9)
activemodel (= 3.2.9)
activesupport (= 3.2.9)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.9)
activemodel (= 3.2.9)
activesupport (= 3.2.9)
activesupport (3.2.9)
i18n (~> 0.6)
multi_json (~> 1.0)
acts_as_commentable_with_threading (1.1.2)
activerecord (>= 3.0)
activesupport (~> 3.0)
awesome_nested_set (>= 2.0)
arel (3.0.2)
awesome_nested_set (2.1.5)
activerecord (>= 3.0.0)
bcrypt-ruby (3.0.1)
builder (3.0.4)
cancan (1.6.8)
cocaine (0.4.2)
cocoon (1.1.1)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.4.0)
devise (2.1.2)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
erubis (2.7.0)
eventmachine (1.0.0)
execjs (1.4.0)
multi_json (~> 1.0)
formtastic (2.2.1)
actionpack (>= 3.0)
formtastic-bootstrap (2.0.0)
formtastic (~> 2.2)
formtastic-bootstrap
haml (3.1.7)
hashery (2.1.0)
hike (1.2.1)
i18n (0.6.1)
journey (1.0.4)
jquery-fileupload-rails (0.4.0)
actionpack (>= 3.1)
railties (>= 3.1)
jquery-rails (2.1.4)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
jquery_datepicker (0.4)
json (1.7.5)
mail (2.4.4)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.19)
multi_json (1.5.0)
node (0.0.2)
eventmachine
orm_adapter (0.4.0)
paperclip (3.4.0)
activemodel (>= 3.0.0)
activerecord (>= 3.0.0)
activesupport (>= 3.0.0)
cocaine (~> 0.4.0)
mime-types
pdf-reader (1.2.0)
Ascii85 (~> 1.0.0)
hashery (~> 2.0)
ruby-rc4
polyglot (0.3.3)
prawn (0.12.0)
pdf-reader (>= 0.9.0)
ttfunk (~> 1.0.2)
prawn_rails (0.0.11)
prawn (>= 0.11.1)
railties (>= 3.0.0)
rack (1.4.1)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.2)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.9)
actionmailer (= 3.2.9)
actionpack (= 3.2.9)
activerecord (= 3.2.9)
activeresource (= 3.2.9)
activesupport (= 3.2.9)
bundler (~> 1.0)
railties (= 3.2.9)
railties (3.2.9)
actionpack (= 3.2.9)
activesupport (= 3.2.9)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rake (10.0.3)
rdoc (3.12)
json (~> 1.4)
ruby-rc4 (0.1.5)
sass (3.2.4)
sass-rails (3.2.5)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.6)
thor (0.16.0)
tilt (1.3.3)
transitions (0.1.4)
treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
ttfunk (1.0.3)
twitter-bootstrap-rails (2.1.9)
actionpack (>= 3.1)
execjs
railties (>= 3.1)
tzinfo (0.3.35)
uglifier (1.3.0)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
warden (1.2.1)
rack (>= 1.0)
PLATFORMS
ruby
DEPENDENCIES
acts_as_commentable_with_threading
bcrypt-ruby (~> 3.0.0)
cancan
cocoon
coffee-rails (~> 3.2.1)
devise
formtastic-bootstrap
haml
jquery-fileupload-rails
jquery-rails
jquery_datepicker
node
paperclip (~> 3.0)
prawn
prawn_rails
rails (= 3.2.9)
sass-rails (~> 3.2.3)
sqlite3
transitions
twitter-bootstrap-rails
uglifier (>= 1.0.3)

261
README.rdoc Normal file
View file

@ -0,0 +1,261 @@
== Welcome to Rails
Rails is a web-application framework that includes everything needed to create
database-backed web applications according to the Model-View-Control pattern.
This pattern splits the view (also called the presentation) into "dumb"
templates that are primarily responsible for inserting pre-built data in between
HTML tags. The model contains the "smart" domain objects (such as Account,
Product, Person, Post) that holds all the business logic and knows how to
persist themselves to a database. The controller handles the incoming requests
(such as Save New Account, Update Product, Show Post) by manipulating the model
and directing data to the view.
In Rails, the model is handled by what's called an object-relational mapping
layer entitled Active Record. This layer allows you to present the data from
database rows as objects and embellish these data objects with business logic
methods. You can read more about Active Record in
link:files/vendor/rails/activerecord/README.html.
The controller and view are handled by the Action Pack, which handles both
layers by its two parts: Action View and Action Controller. These two layers
are bundled in a single package due to their heavy interdependence. This is
unlike the relationship between the Active Record and Action Pack that is much
more separate. Each of these packages can be used independently outside of
Rails. You can read more about Action Pack in
link:files/vendor/rails/actionpack/README.html.
== Getting Started
1. At the command prompt, create a new Rails application:
<tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
2. Change directory to <tt>myapp</tt> and start the web server:
<tt>cd myapp; rails server</tt> (run with --help for options)
3. Go to http://localhost:3000/ and you'll see:
"Welcome aboard: You're riding Ruby on Rails!"
4. Follow the guidelines to start developing your application. You can find
the following resources handy:
* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
== Debugging Rails
Sometimes your application goes wrong. Fortunately there are a lot of tools that
will help you debug it and get it back on the rails.
First area to check is the application log files. Have "tail -f" commands
running on the server.log and development.log. Rails will automatically display
debugging and runtime information to these files. Debugging info will also be
shown in the browser on requests from 127.0.0.1.
You can also log your own messages directly into the log file from your code
using the Ruby logger class from inside your controllers. Example:
class WeblogController < ActionController::Base
def destroy
@weblog = Weblog.find(params[:id])
@weblog.destroy
logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
end
end
The result will be a message in your log file along the lines of:
Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
More information on how to use the logger is at http://www.ruby-doc.org/core/
Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
several books available online as well:
* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
These two books will bring you up to speed on the Ruby language and also on
programming in general.
== Debugger
Debugger support is available through the debugger command when you start your
Mongrel or WEBrick server with --debugger. This means that you can break out of
execution at any point in the code, investigate and change the model, and then,
resume execution! You need to install ruby-debug to run the server in debugging
mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
class WeblogController < ActionController::Base
def index
@posts = Post.all
debugger
end
end
So the controller will accept the action, run the first line, then present you
with a IRB prompt in the server window. Here you can do things like:
>> @posts.inspect
=> "[#<Post:0x14a6be8
@attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
#<Post:0x14a6620
@attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
>> @posts.first.title = "hello from a debugger"
=> "hello from a debugger"
...and even better, you can examine how your runtime objects actually work:
>> f = @posts.first
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
>> f.
Display all 152 possibilities? (y or n)
Finally, when you're ready to resume execution, you can enter "cont".
== Console
The console is a Ruby shell, which allows you to interact with your
application's domain model. Here you'll have all parts of the application
configured, just like it is when the application is running. You can inspect
domain models, change values, and save to the database. Starting the script
without arguments will launch it in the development environment.
To start the console, run <tt>rails console</tt> from the application
directory.
Options:
* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
made to the database.
* Passing an environment name as an argument will load the corresponding
environment. Example: <tt>rails console production</tt>.
To reload your controllers and models after launching the console run
<tt>reload!</tt>
More information about irb can be found at:
link:http://www.rubycentral.org/pickaxe/irb.html
== dbconsole
You can go to the command line of your database directly through <tt>rails
dbconsole</tt>. You would be connected to the database with the credentials
defined in database.yml. Starting the script without arguments will connect you
to the development database. Passing an argument will connect you to a different
database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
PostgreSQL and SQLite 3.
== Description of Contents
The default directory structure of a generated Ruby on Rails application:
|-- app
| |-- assets
| |-- images
| |-- javascripts
| `-- stylesheets
| |-- controllers
| |-- helpers
| |-- mailers
| |-- models
| `-- views
| `-- layouts
|-- config
| |-- environments
| |-- initializers
| `-- locales
|-- db
|-- doc
|-- lib
| `-- tasks
|-- log
|-- public
|-- script
|-- test
| |-- fixtures
| |-- functional
| |-- integration
| |-- performance
| `-- unit
|-- tmp
| |-- cache
| |-- pids
| |-- sessions
| `-- sockets
`-- vendor
|-- assets
`-- stylesheets
`-- plugins
app
Holds all the code that's specific to this particular application.
app/assets
Contains subdirectories for images, stylesheets, and JavaScript files.
app/controllers
Holds controllers that should be named like weblogs_controller.rb for
automated URL mapping. All controllers should descend from
ApplicationController which itself descends from ActionController::Base.
app/models
Holds models that should be named like post.rb. Models descend from
ActiveRecord::Base by default.
app/views
Holds the template files for the view that should be named like
weblogs/index.html.erb for the WeblogsController#index action. All views use
eRuby syntax by default.
app/views/layouts
Holds the template files for layouts to be used with views. This models the
common header/footer method of wrapping views. In your views, define a layout
using the <tt>layout :default</tt> and create a file named default.html.erb.
Inside default.html.erb, call <% yield %> to render the view using this
layout.
app/helpers
Holds view helpers that should be named like weblogs_helper.rb. These are
generated for you automatically when using generators for controllers.
Helpers can be used to wrap functionality for your views into methods.
config
Configuration files for the Rails environment, the routing map, the database,
and other dependencies.
db
Contains the database schema in schema.rb. db/migrate contains all the
sequence of Migrations for your schema.
doc
This directory is where your application documentation will be stored when
generated using <tt>rake doc:app</tt>
lib
Application specific libraries. Basically, any kind of custom code that
doesn't belong under controllers, models, or helpers. This directory is in
the load path.
public
The directory available for the web server. Also contains the dispatchers and the
default HTML files. This should be set as the DOCUMENT_ROOT of your web
server.
script
Helper scripts for automation and generation.
test
Unit and functional tests along with fixtures. When using the rails generate
command, template test files will be generated for you and placed in this
directory.
vendor
External libraries that the application depends on. Also includes the plugins
subdirectory. If the app has frozen rails, those gems also go here, under
vendor/rails/. This directory is in the load path.

7
Rakefile Normal file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
Osem::Application.load_tasks

BIN
app/assets/images/rails.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,74 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require jquery-fileupload
//= require twitter/bootstrap
//= require cocoon
$(function() {
$('.dropdown-toggle').dropdown();
$("#conference-start-datepicker").datepicker({
dateFormat: 'yy/mm/dd',
numberOfMonths: 2,
onSelect: function(selected) {
$("#conference-end-datepicker").datepicker("option","minDate", selected)
}
});
$("#conference-end-datepicker").datepicker({
dateFormat: 'yy/mm/dd',
numberOfMonths: 2,
onSelect: function(selected) {
$("#conference-start-datepicker").datepicker("option","maxDate", selected)
$("#cfp-hard-datepicker").datepicker("option","minDate", selected)
}
});
$("#cfp-hard-datepicker").datepicker({
dateFormat: 'yy/mm/dd',
numberOfMonths: 2,
onSelect: function(selected) {
$("#conference-end-datepicker").datepicker("option","maxDate", selected)
$("#conference-start-datepicker").datepicker("option","maxDate", selected)
}
});
$(".comment-reply-link").click(function(){
$(".comment-reply", $(this).parent()).toggle();
return false;
});
$("#event-comment-link").click(function(){
$("#comments-div").toggle();
return false;
});
$(".comment-reply").hide();
$(".user-details-popover").popover();
$("#comments-div").hide();
});
function word_count(text, divId){
var r = 0;
var input = text.value.replace(/\s/g,' ');
var word_array = input.split(' ');
for (var i=0; i < word_array.length; i++) {
if (word_array[i].length > 0) r++;
}
$('#' + divId).text(r);
}

View file

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

View file

@ -0,0 +1,3 @@
# 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,3 @@
// 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

@ -0,0 +1,7 @@
/*
*= require formtastic-bootstrap
*= require bootstrap_and_overrides
*= require osem
*= require jquery-ui-1.9.2.custom
*= require jquery.fileupload-ui
*/

View file

@ -0,0 +1,7 @@
/*
=require twitter-bootstrap-static/bootstrap
Use Font Awesome icons (default)
To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
=require twitter-bootstrap-static/fontawesome
*/

View file

@ -0,0 +1,33 @@
@import "twitter/bootstrap/bootstrap";
@import "twitter/bootstrap/responsive";
// Set the correct sprite paths
@iconSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings");
@iconWhiteSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings-white");
// Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines)
// Note: If you use asset_path() here, your compiled bootstrap_and_overrides.css will not
// have the proper paths. So for now we use the absolute path.
@fontAwesomeEotPath: asset-path("fontawesome-webfont.eot");
@fontAwesomeEotPath_iefix: asset-path("fontawesome-webfont.eot#iefix");
@fontAwesomeWoffPath: asset-path("fontawesome-webfont.woff");
@fontAwesomeTtfPath: asset-path("fontawesome-webfont.ttf");
@fontAwesomeSvgPath: asset-path("fontawesome-webfont.svg");
// Font Awesome
@import "fontawesome";
// Glyphicons
//@import "twitter/bootstrap/sprites.less";
// Your custom LESS stylesheets goes here
//
// Since bootstrap was imported above you have access to its mixins which
// you may use and inherit here
//
// If you'd like to override bootstrap's own variables, you can do so here as well
// See http://twitter.github.com/bootstrap/customize.html#variables for their names and documentation
//
// Example:
// @linkColor: #ff0000;
@navbarBackground: #000000;

View file

@ -0,0 +1,3 @@
// 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,325 @@
/*! jQuery UI - v1.9.2 - 2012-12-28
* http://jqueryui.com
* Includes: jquery.ui.core.css, jquery.ui.datepicker.css
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}
/* Component containers
----------------------------------*/
.ui-widget { font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; }
.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #1d5987; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; text-decoration: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -khtml-border-top-left-radius: 5px; border-top-left-radius: 5px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -khtml-border-top-right-radius: 5px; border-top-right-radius: 5px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -khtml-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; -khtml-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }

View file

@ -0,0 +1,102 @@
html, body,.container,.content {
height: 100%;
}
#push,
#footer {
height: 60px;
}
.container, .content {
position: relative;
}
#inner-content {
padding-top: 60px;
}
#wrap {
min-height: 100%;
height: auto !important;
height: 100%;
margin: 0 auto -60px;
}
#footer {
position: relative;
background-color: #ffffff;
}
.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 */
}
.navbar .nav .active > a, .navbar .nav .active > a:hover {
background-color: #DFE0DF;
}
.navbar .divider-vertical {
background-color: #b4e391;
border-right: 1px solid #eab92d;
}
.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;
}
.center {
margin:0 auto;
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 */
box-sizing: border-box; /* Opera/IE 8+ */
width:100%;
}
.mainbutton {
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #9dce2c), color-stop(1, #8cb82b) );
background:-moz-linear-gradient( center top, #9dce2c 5%, #8cb82b 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#9dce2c', endColorstr='#8cb82b');
background-color:#9dce2c;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #83c41a;
display:inline-block;
color:#ffffff;
font-family:Arial;
font-size:20px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:1px 1px 9px #689324;
}.mainbutton:hover {
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #8cb82b), color-stop(1, #9dce2c) );
background:-moz-linear-gradient( center top, #8cb82b 5%, #9dce2c 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#8cb82b', endColorstr='#9dce2c');
background-color:#8cb82b;
}.mainbutton:active {
position:relative;
top:1px;
}

View file

@ -0,0 +1,28 @@
class Admin::CallforpapersController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
@cfp = @conference.call_for_papers
if @cfp.nil?
@cfp = CallForPapers.new
end
end
def update
@cfp = @conference.call_for_papers
@cfp.update_attributes(params[:call_for_papers])
redirect_to(admin_conference_cfp_info_path(:id => @conference.short_title), :notice => 'Call for Papers was successfully updated.')
end
def create
@cfp = CallForPapers.new(params[:call_for_papers])
@conference.call_for_papers = @cfp
if @cfp.save
redirect_to(admin_conference_cfp_info_path(:id => @conference.short_title), :notice => 'Call for Papers was successfully updated.')
else
redirect_to(admin_conference_cfp_info_path(:id => @conference.short_title), :error => 'Call for Papers failed.')
end
end
end

View file

@ -0,0 +1,36 @@
class Admin::ConferenceController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
@conferences = Conference.all
if @conferences.count == 0
redirect_to new_admin_conference_path
return
end
end
def new
@conference = Conference.new
end
def create
@conference = Conference.new(params[:conference])
if @conference.save
redirect_to(admin_conference_path(:id => @conference.short_title), :notice => 'Conference was successfully created.')
else
render :action => "new"
end
end
def update
@conference = Conference.find_all_by_short_title(params[:id]).first
@conference.update_attributes(params[:conference])
flash[:notice] = "Updated Conference"
redirect_to(admin_conference_path(:id => @conference.short_title), :notice => 'Conference was successfully updated.')
end
def show
@conference = Conference.find_all_by_short_title(params[:id]).first
end
end

View file

@ -0,0 +1,41 @@
class Admin::EventsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
@events = @conference.events
end
def show
@event = @conference.events.find(params[:id])
@comments = @event.root_comments
@comment_count = @event.comment_threads.count
end
def edit
@event_types = @conference.event_types
@event = Event.find_by_id(params[:id])
@person = @event.submitter
@url = edit_admin_conference_event_path(@conference.short_title, @event)
end
def comment
event = @conference.events.find_by_id(params[:id])
comment = Comment.build_from(event, current_user.id, params[:comment])
comment.save!
if !params[:parent].nil?
comment.move_to_child_of(params[:parent])
end
redirect_to admin_conference_event_path(:conference_id => @conference.short_title, :id => params[:id])
end
def create
end
def update_state
event = Event.find(params[:id])
event.send(:"#{params[:transition]}!", :send_mail => params[:send_mail])
redirect_to(admin_conference_events_path(:conference_id => @conference.short_title), :notice => "Updated state")
end
end

View file

@ -0,0 +1,17 @@
class Admin::EventtypeController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :event_type_list
end
def update
begin
@conference.update_attributes!(params[:conference])
redirect_to(admin_conference_eventtype_list_path(:conference_id => @conference.short_title), :notice => 'Event types were successfully updated.')
rescue Exception => e
redirect_to(admin_conference_eventtype_list_path(:conference_id => @conference.short_title), :alert => 'Event types update failed: #{e.message}')
end
end
end

View file

@ -0,0 +1,24 @@
class Admin::PeopleController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
@people = Person.all
end
def create
end
def show
@person = Person.find(params[:id])
end
def update
end
def delete
end
end

View file

@ -0,0 +1,16 @@
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")
end
end

View file

@ -0,0 +1,18 @@
class Admin::RoomsController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :rooms_list
end
def update
if @conference.update_attributes(params[:conference])
redirect_to(admin_conference_rooms_list_path(:conference_id => @conference.short_title), :notice => 'Rooms were successfully updated.')
else
redirect_to(admin_conference_rooms_list_path(:conference_id => @conference.short_title), :notice => 'Room update failed.')
end
end
end

View file

@ -0,0 +1,18 @@
class Admin::TracksController < ApplicationController
before_filter :verify_organizer
layout "admin"
def show
render :tracks_list
end
def update
if @conference.update_attributes(params[:conference])
redirect_to(admin_conference_tracks_list_path(:conference_id => @conference.short_title), :notice => 'Tracks were successfully updated.')
else
redirect_to(admin_conference_tracks_list_path(:conference_id => @conference.short_title), :notice => 'Tracks update failed.')
end
end
end

View file

@ -0,0 +1,20 @@
class Admin::UsersController < ApplicationController
before_filter :verify_admin
layout "admin"
def index
@users = User.all(:joins => :person,
:order => "people.last_name ASC",
:select => "users.*,
people.last_name AS last_name,
people.first_name AS first_name,
people.public_name AS public_name,
people.email AS email")
end
def update
user = User.find(params[:id])
user.update_attributes!(params[:user])
redirect_to admin_users_path, :notice => "Updated #{user.email}"
end
end

View file

@ -0,0 +1,24 @@
class Admin::VenueController < ApplicationController
before_filter :verify_organizer
layout "admin"
def index
end
def update
@venue = @conference.venue
venue_params = params[:venue]
@venue.name = venue_params[:name]
@venue.address= venue_params[:address]
@venue.website = venue_params[:website]
@venue.description = venue_params[:description]
@venue.save
redirect_to(admin_conference_venue_info_path(:conference_id => @conference.short_title), :notice => 'Venue was successfully updated.')
end
def show
@venue = @conference.venue
render :venue_info
end
end

View file

@ -0,0 +1,42 @@
class ApplicationController < ActionController::Base
include ApplicationHelper
protect_from_forgery
def verify_user
:authenticate_user!
if (current_user.nil?)
redirect_to '/accounts/sign_in'
return
end
@conference = Conference.find_all_by_short_title(params[:conference_id]).first
end
def organizer_or_admin?
has_role?(current_user, 'admin') || has_role?(current_user, 'organizer')
end
def verify_organizer
verify_user
## Todo simplify this
redirect_to '/' unless has_role?(current_user, 'admin') || has_role?(current_user, 'organizer')
end
def verify_admin
verify_user
redirect_to '/' unless has_role?(current_user, 'admin')
end
def current_ability
@current_ability ||= AdminAbility.new(current_user)
end
rescue_from CanCan::AccessDenied do |exception|
Rails.logger.debug("Access denied!")
redirect_to '/', :alert => exception.message
end
end

View file

@ -0,0 +1,51 @@
class ConferenceRegistrationController < ApplicationController
before_filter :verify_user
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
@person = current_user.person
@registration = @person.registrations.where(:conference_id => @conference.id).first
@registered = true
if @registration.nil?
@registered = false
@registration = @person.registrations.new(:conference_id => @conference.id)
end
end
def update
conference = Conference.find_all_by_short_title(params[:id]).first
person = current_user.person
registration = person.registrations.where(:conference_id => conference.id).first
update_registration = true
begin
if registration.nil?
update_registration = false
person.update_attributes(params[:registration][:person_attributes])
params[:registration].delete :person_attributes
registration = person.registrations.new(params[:registration])
registration.conference_id = conference.id
registration.save!
else
registration.update_attributes!(params[:registration])
end
rescue Exception => e
redirect_to(register_conference_path(:id => conference.short_title), :alert => 'Registration failed:' + e.message)
return
end
redirect_message = "You are now registered."
if update_registration
redirect_message = "Registration updated."
end
redirect_to(register_conference_path(:id => conference.short_title), :notice => redirect_message)
end
def unregister
conference = Conference.find_all_by_short_title(params[:id]).first
person = current_user.person
registration = person.registrations.where(:conference_id => conference.id).first
registration.destroy
redirect_to :root
end
end

View file

@ -0,0 +1,97 @@
class EventAttachmentsController < ApplicationController
before_filter :verify_user
skip_before_filter :verify_user, :only => [:show]
def index
@proposal = current_user.person.events.find(params[:proposal_id])
@uploads = @proposal.event_attachments
respond_to do |format|
format.html # index.html.erb
format.json { render json: @uploads.map{|upload| upload.to_jq_upload } }
end
end
def show
upload = EventAttachment.find(params[:id])
if upload.public?
send_file upload.attachment.path
return
end
if current_user.nil?
verify_user
return
end
if organizer_or_admin? || current_user.person == upload.event.submitter
send_file upload.attachment.path
else
raise ActionController::RoutingError.new('Not Found')
end
end
def new
@upload = EventAttachment.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @upload }
end
end
def edit
@upload = EventAttachment.find(params[:id])
end
def create
params[:event_attachment][:title] = params[:title][0]
params[:event_attachment][:public] = false
params[:event_attachment][:event_id] = params[:proposal_id]
if params.has_key?(:public)
params[:event_attachment][:public] = true
end
@upload = EventAttachment.new(params[:event_attachment])
respond_to do |format|
if @upload.save
format.html {
render :json => [@upload.to_jq_upload].to_json,
:content_type => 'text/html',
:layout => false
}
format.json { render json: [@upload.to_jq_upload].to_json, status: :created,
location: conference_proposal_event_attachment_path(@upload.event.conference.short_title, @upload.event, @upload) }
else
format.html { render action: "new" }
format.json { render json: @upload.errors, status: :unprocessable_entity }
end
end
end
def update
@upload = EventAttachment.find(params[:proposal_id])
respond_to do |format|
if @upload.update_attributes(params[:upload])
format.html { redirect_to @upload, notice: 'Upload was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @upload.errors, status: :unprocessable_entity }
end
end
end
def destroy
@proposal = current_user.person.events.find(params[:proposal_id])
@upload = @proposal.event_attachments.find(params[:id])
@upload.destroy
respond_to do |format|
format.html { redirect_to uploads_url }
format.json { head :no_content }
end
end
end

View file

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

View file

@ -0,0 +1,97 @@
class ProposalController < ApplicationController
before_filter :verify_user
def index
@person = current_user.person
@events = @person.proposals @conference
end
def destroy
current_user.person.withdraw_proposal(params[:id])
redirect_to(conference_proposal_index_path(:conference_id => @conference.short_title), :alert => 'Proposal withdrawn.')
end
def new
@url = conference_proposal_index_path(@conference.short_title)
@event = Event.new
@event_types = @conference.event_types
@person = current_user.person
end
def edit
@url = conference_proposal_path(@conference.short_title, params[:id])
@person = current_user.person
@event_types = @conference.event_types
@event = @person.events.find_by_id(params[:id])
@attachments = @event.event_attachments
if @event.nil?
redirect_to(conference_proposal_index_path(:conference_id => @conference.short_title), :alert => 'Invalid proposal.')
end
end
def update
person = current_user.person
session[:return_to] ||= request.referer
submitter = params[:person]
params[:event].delete :people_attributes
params[:event].delete :person
if submitter[:public_name] != person.public_name || submitter[:biography] != person.biography
person.update_attributes(submitter)
end
event = Event.find_by_id(params[:id])
if event.update_attributes!(params[:event])
redirect_to(conference_proposal_index_path(:conference_id => @conference.short_title), :notice => "'#{event.title}' was successfully updated.")
else
redirect_to session[:return_to], :alert => "'#{event.title}' was NOT updated!"
end
end
def create
person = current_user.person
session[:return_to] ||= request.referer
event_params = params[:event]
submitter = params[:person]
params[:event].delete :person
# First, update the submitter's info, if they've changed anything
if submitter[:public_name] != person.public_name || submitter[:biography] != person.biography
person.update_attributes(submitter)
end
@event = Event.new(event_params)
@event.conference = @conference
@event.event_people.new(:person => person,
:event_role => "submitter")
@event.event_people.new(:person => person,
:event_role => "speaker")
begin
@event.save!
rescue Exception => e
@url = conference_proposal_index_path(@conference.short_title)
@event_types = @conference.event_types
@person = current_user.person
flash[:error] = "Could not submit proposal: #{e.message}"
render :action => 'new'
return
end
registration = person.registrations.where(:conference_id => @conference.id).first
if registration.nil?
redirect_to(register_conference_path(@conference.short_title), :notice => 'Event was successfully submitted. You probably want to register for the conference now!')
else
redirect_to(conference_proposal_index_path(:conference_id => @conference.short_title), :notice => 'Event was successfully submitted.')
end
end
def show
end
end

View file

@ -0,0 +1,52 @@
class RegistrationsController < Devise::RegistrationsController
def update
@user = User.find(current_user.id)
email_changed = false
if !params[:user][:email].nil?
if @user.email != params[:user][:email]
email_changed = true
else
params[:user].delete :email
end
end
password_changed = false
if !params[:user][:password].nil?
if !params[:user][:password].empty?
password_changed = true
else
params[:user].delete :password
params[:user].delete :password_confirmation
params[:user].delete :current_password
end
end
successfully_updated = if email_changed or password_changed
@user.update_with_password(params[:user])
else
@user.update_without_password(params[:user])
end
if successfully_updated
set_flash_message :notice, :updated
# Sign in the user bypassing validation in case his password changed
sign_in @user, :bypass => true
redirect_to after_update_path_for(@user)
else
render "edit"
end
end
protected
def after_update_path_for(resource)
edit_user_registration_path(resource)
end
def after_sign_up_path_for(resource)
edit_user_registration_path(resource)
end
end

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,43 @@
module ApplicationHelper
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")
end
def remove_association_link(association_name, form_builder)
link_to_remove_association("Remove " + association_name.to_s.singularize, form_builder, :class => "assoc btn btn-danger") + tag(:hr)
end
def dynamic_association(association_name, title, form_builder, options = {})
render "shared/dynamic_association", :association_name => association_name, :title => title, :f => form_builder, :hint => options[:hint]
end
def has_role?(current_user, role)
return !!current_user.role?(role.to_s.camelize)
end
# TODO Output better html
def format_comments(comment, padding = 0)
result = ""
result += "<div style='padding-left:#{padding}px'>"
result += "<div class='well'>"
result += "<b>#{comment.user.person.public_name}</b> <i>#{comment.created_at}</i><br><br>"
result += comment.body
result += "<br><div><a href='#' class='pull-right comment-reply-link'>Reply</a><br><br>"
result += "<div class='comment-reply'>"
result += "<form method='post' action='#{comment_admin_conference_event_path(@conference.short_title, comment.commentable_id)}'>"
result += "<input type=hidden name=parent value='#{comment.id}'/>"
result += "<input name='authenticity_token' type='hidden' value='#{form_authenticity_token}' />"
result += "<textarea name='comment'></textarea>"
result += "<button class='btn btn-primary pull-right' name='button' type='submit'>Add Reply</button>"
result += "</form></div></div>"
result += "</div>"
#result += edit_admin_conference_event_path(@conference.short_title, @event)
comment.children.each do |child|
result += format_comments(child, 50)
result += "</div>"
end
result
end
end

View file

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

0
app/mailers/.gitkeep Normal file
View file

0
app/models/.gitkeep Normal file
View file

28
app/models/ability.rb Normal file
View file

@ -0,0 +1,28 @@
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
#
# user ||= User.new # guest user (not logged in)
# if user.admin?
# can :manage, :all
# else
# can :read, :all
# end
#
# The first argument to `can` is the action you are giving the user permission to do.
# If you pass :manage it will apply to every action. Other common actions here are
# :read, :create, :update and :destroy.
#
# The second argument is the resource the user can perform the action on. If you pass
# :all it will apply to every resource. Otherwise pass a Ruby class of the resource.
#
# The third argument is an optional hash of conditions to further filter the objects.
# For example, here the user can only update published articles.
#
# can :update, Article, :published => true
#
# See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities
end
end

View file

@ -0,0 +1,17 @@
class AdminAbility
include CanCan::Ability
def initialize(user)
@user = user || User.new # for guest
@user.get_roles.each { |role| send(role.name.downcase) }
end
def organizer
can :manage, Event
end
def admin
organizer
can :manage, :all
end
end

View file

@ -0,0 +1,7 @@
class CallForPapers < ActiveRecord::Base
attr_accessible :start_date, :end_date, :hard_deadline, :description
belongs_to :conference
validates_presence_of :start_date, :end_date, :hard_deadline
end

48
app/models/comment.rb Normal file
View file

@ -0,0 +1,48 @@
class Comment < ActiveRecord::Base
acts_as_nested_set :scope => [:commentable_id, :commentable_type]
attr_accessible :commentable, :body, :user_id
validates_presence_of :body
validates_presence_of :user
# NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments.
#acts_as_votable
belongs_to :commentable, :polymorphic => true
# NOTE: Comments belong to a user
belongs_to :user
# Helper class method that allows you to build a comment
# by passing a commentable object, a user_id, and comment text
# example in readme
def self.build_from(obj, user_id, comment)
new \
:commentable => obj,
:body => comment,
:user_id => user_id
end
#helper method to check if a comment has children
def has_children?
self.children.any?
end
# Helper class method to lookup all comments assigned
# to all commentable types for a given user.
scope :find_comments_by_user, lambda { |user|
where(:user_id => user.id).order('created_at DESC')
}
# Helper class method to look up all comments for
# commentable class name and commentable id.
scope :find_comments_for_commentable, lambda { |commentable_str, commentable_id|
where(:commentable_type => commentable_str.to_s, :commentable_id => commentable_id).order('created_at DESC')
}
# Helper class method to look up a commentable object
# given the commentable class name and id
def self.find_commentable(commentable_str, commentable_id)
commentable_str.constantize.find(commentable_id)
end
end

87
app/models/conference.rb Normal file
View file

@ -0,0 +1,87 @@
class Conference < ActiveRecord::Base
attr_accessible :title, :short_title, :social_tag, :contact_email, :timezone, :html_export_path,
:start_date, :end_date, :rooms_attributes, :tracks_attributes, :cfp_open, :registration_open,
:event_types_attributes
has_one :call_for_papers, :dependent => :destroy
has_many :events, :dependent => :destroy
has_many :event_types, :dependent => :destroy
has_many :tracks, :dependent => :destroy
has_many :rooms, :dependent => :destroy
has_many :registrations, :dependent => :destroy
belongs_to :venue
accepts_nested_attributes_for :rooms, :reject_if => proc {|r| r["name"].blank?}, :allow_destroy => true
accepts_nested_attributes_for :tracks, :reject_if => proc {|r| r["name"].blank?}, :allow_destroy => true
accepts_nested_attributes_for :venue
accepts_nested_attributes_for :event_types, :allow_destroy => true
validates_presence_of :title,
:short_title,
:social_tag
validates_uniqueness_of :short_title
validates_format_of :short_title, :with => /^[a-zA-Z0-9_-]*$/
before_create :generate_guid
before_create :create_venue
def self.current
self.order("created_at DESC").first
end
def date_range_string
startstr = "Unknown - "
endstr = "Unknown"
if start_date.month == end_date.month && start_date.year == end_date.year
startstr = start_date.strftime("%B %d - ")
endstr = end_date.strftime("%d, %Y")
elsif start_date.month != end_date.month && start_date.year == end_date.year
startstr = start_date.strftime("%B %d - ")
endstr = end_date.strftime("%B %d, %Y")
else
startstr = start_date.strftime("%B %d, %Y - ")
endstr = end_date.strftime("%B %d, %Y")
end
result = startstr + endstr
result
end
def user_registered? user
return nil if user.nil?
return nil if user.person.nil?
if self.registrations.where(:person_id => user.person.id).count == 0
Rails.logger.debug("Returning false")
false
else
Rails.logger.debug("Returning true")
true
end
end
def cfp_open?
today = Date.current
cfp = self.call_for_papers
if !cfp.nil? && (cfp.start_date.. cfp.end_date).cover?(today)
return true
end
return false
end
private
def create_venue
self.venue_id = Venue.create.id
true
end
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while Person.where(:guid => guid).exists?
self.guid = guid
end
end

101
app/models/event.rb Normal file
View file

@ -0,0 +1,101 @@
class Event < ActiveRecord::Base
include ActiveRecord::Transitions
attr_accessible :title, :subtitle, :abstract, :description, :event_type_id, :people_attributes, :person,
:proposal_additional_speakers
acts_as_commentable
has_many :event_people, :dependent => :destroy
has_many :event_attachments, :dependent => :destroy
has_many :people, :through => :event_people
belongs_to :event_type
belongs_to :track
belongs_to :room
belongs_to :conference
accepts_nested_attributes_for :event_people
accepts_nested_attributes_for :event_attachments, :allow_destroy => true, :reject_if => :all_blank
accepts_nested_attributes_for :people
before_create :generate_guid
validate :abstract_limit
state_machine :initial => :new do
state :new
state :review
state :withdrawn
state :accepted
state :unconfirmed
state :confirmed
state :canceled
state :rejected
event :start_review do
transitions :to => :review, :from => [:new, :rejected]
end
event :withdraw do
transitions :to => :withdrawn, :from => [:new, :review, :unconfirmed]
end
event :accept do
transitions :to => :unconfirmed, :from => [:new, :review], :on_transition => :process_acceptance
end
event :unconfirm do
transitions :to => :review, :from=>[:confirmed]
end
event :confirm do
transitions :to => :confirmed, :from => :unconfirmed
end
event :cancel do
transitions :to => :canceled, :from => [:unconfirmed, :confirmed]
end
event :reject do
transitions :to => :rejected, :from => [:new, :review], :on_transition => :process_rejection
end
end
def submitter
result = self.event_people.where(:event_role => "submitter").first
if !result.nil?
result.person
else
nil
end
end
def transition_possible?(transition)
self.class.state_machine.events_for(self.current_state).include?(transition)
end
def process_acceptance(options)
# if options[:send_mail]
# self.event_people.presenter.each do |event_person|
# event_person.generate_token!
# SelectionNotification.acceptance_notification(event_person).deliver
# end
# end
end
def abstract_word_count
if self.abstract.nil?
0
else
self.abstract.split.size
end
end
private
def abstract_limit
if self.abstract.split.size > 250
errors.add(:abstract, "cannot have more than 250 words")
end
end
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while self.class.where(:guid => guid).exists?
self.guid = guid
end
end

View file

@ -0,0 +1,28 @@
class EventAttachment < ActiveRecord::Base
belongs_to :event
scope :public, where(:public => true)
attr_accessible :public, :attachment, :event_id, :title
has_attached_file :attachment, :path => ":rails_root/storage/:rails_env/attachments/:id/:style/:basename.:extension"
include Rails.application.routes.url_helpers
def to_jq_upload
{
"name" => read_attribute(:attachment_file_name),
"size" => read_attribute(:attachment_file_size),
"title" => read_attribute(:title),
"public" => read_attribute(:public),
#"url" => attachment.url(:original),
"url" => conference_proposal_event_attachment_path(self.event.conference.short_title, self.event_id, self.id),
"delete_url" => conference_proposal_event_attachment_path(self.event.conference.short_title, self.event_id, self.id),
"delete_type" => "DELETE"
}
end
#:path => ":rails_root/public/system/:attachment/:id/:style/:filename",
# :url => "/system/:attachment/:id/:style/:filename"
#has_paper_trail :meta => {:associated_id => :event_id, :associated_type => "Event"}
end

View file

@ -0,0 +1,8 @@
class EventPerson < ActiveRecord::Base
attr_accessible :event, :person, :person_id, :event_role
# TODO Do we need these roles?
ROLES = [["Speaker","speaker"], ["Submitter","submitter"], ["Moderator","moderator"]]
belongs_to :event
belongs_to :person
end

5
app/models/event_type.rb Normal file
View file

@ -0,0 +1,5 @@
class EventType < ActiveRecord::Base
attr_accessible :title, :length
belongs_to :conference
end

71
app/models/person.rb Normal file
View file

@ -0,0 +1,71 @@
class Person < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :public_name, :biography, :company
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
validate :biography_limit
before_create :generate_guid
before_save :set_public_name
def to_s
if self.public_name.empty?
self.first_name + " " + self.last_name
else
self.public_name
end
end
def withdraw_proposal id
proposal = self.events.find_by_id(id)
if !proposal.nil?
proposal.withdraw
proposal.save
end
end
def attending_conference? conference
Registration.where(:conference_id => conference.id,
:person_id => self.id).count
end
def proposals conference
self.events.where("conference_id = ? AND state != ? AND state != ?", conference.id, "withdrawn", "rejected")
end
def proposal_count conference
proposals(conference).count
end
def biography_word_count
if self.biography.nil?
0
else
self.biography.split.size
end
end
private
def biography_limit
if self.biography.split.size > 150
errors.add(:abstract, "cannot have more than 150 words")
end
end
def set_public_name
if public_name.empty?
self.public_name = "#{first_name} #{last_name}"
end
end
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while Person.where(:guid => guid).exists?
self.guid = guid
end
end

View file

@ -0,0 +1,9 @@
class Registration < ActiveRecord::Base
belongs_to :person
belongs_to :conference
attr_accessible :person_id, :conference_id, :attending_social_events, :attending_social_events_with_partner,
:using_affiliated_lodging, :arrival, :departure, :person_attributes
accepts_nested_attributes_for :person
end

4
app/models/role.rb Normal file
View file

@ -0,0 +1,4 @@
class Role < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :users
end

18
app/models/room.rb Normal file
View file

@ -0,0 +1,18 @@
class Room < ActiveRecord::Base
attr_accessible :name, :size, :public
belongs_to :conference
has_many :events
before_create :generate_guid
private
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while Person.where(:guid => guid).exists?
self.guid = guid
end
end

17
app/models/track.rb Normal file
View file

@ -0,0 +1,17 @@
class Track < ActiveRecord::Base
attr_accessible :name, :description, :color
belongs_to :conference
before_create :generate_guid
private
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while Person.where(:guid => guid).exists?
self.guid = guid
end
end

55
app/models/user.rb Normal file
View file

@ -0,0 +1,55 @@
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_and_belongs_to_many :roles
has_one :person
attr_accessible :email, :password, :password_confirmation, :remember_me, :role_id, :role_ids, :person_attributes
accepts_nested_attributes_for :person
accepts_nested_attributes_for :roles
before_save :setup_role
before_create :create_person
def role?(role)
Rails.logger.debug("Checking role in user")
return !!self.roles.find_by_name(role.to_s.camelize)
end
def get_roles
return self.roles
end
def setup_role
if self.role_ids.empty?
self.role_ids = [1]
end
end
def popup_details
details = "<b>Sign-in Count</b><br>"
details += "#{self.sign_in_count}<br>"
details += "<b>Current Sign-in</b><br>"
details += "#{self.current_sign_in_at}<br>"
details += "<b>Last Sign-in</b><br>"
details += "#{self.last_sign_in_at}<br>"
details += "<b>Current Sign-in IP</b><br>"
details += "#{self.current_sign_in_ip}<br>"
details += "<b>Last Sign-in IP</b><br>"
details += "#{self.last_sign_in_ip}<br>"
details += "<b>Created at</b><br>"
details += "#{self.created_at}<br>"
end
private
def create_person
# TODO Search people for existing email address, add to their account
build_person(:email => self.email)
true
end
end

14
app/models/venue.rb Normal file
View file

@ -0,0 +1,14 @@
class Venue < ActiveRecord::Base
has_many :conferences
before_create :generate_guid
private
def generate_guid
begin
guid = SecureRandom.urlsafe_base64
end while Venue.where(:guid => guid).exists?
self.guid = guid
end
end

View file

@ -0,0 +1,11 @@
.container-fluid
.row-fluid
.span3
= render 'admin/conference/sidebar', :activated => "Call for Papers"
.span9
= semantic_form_for(@cfp, :url => admin_conference_cfp_update_path(@conference.short_title),:html => {:multipart => true}) do |f|
= 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 :hard_deadline, :as => :string, :input_html => { :id => "cfp-hard-datepicker", :readonly => "readonly" }
= f.input :description, :hint => "Welcome text for the Call for Papers"
= f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"}

View file

@ -0,0 +1,26 @@
.well.sidebar-nav
%ul.nav.nav-list
- if activated == "Conference"
%li.active= link_to "Conference", "#"
- else
%li= link_to "Conference", admin_conference_path(@conference.short_title)
- if activated == "Call for Papers"
%li.active= link_to "Call for Papers", "#"
- else
%li= link_to "Call for Papers", admin_conference_cfp_info_path(@conference.short_title)
- if activated == "Venue"
%li.active= link_to "Venue", "#"
- else
%li= link_to "Venue", admin_conference_venue_info_path(@conference.short_title)
- if activated == "Rooms"
%li.active= link_to "Rooms", "#"
- else
%li= link_to "Rooms", admin_conference_rooms_list_path(@conference.short_title)
- if activated == "Tracks"
%li.active= link_to "Tracks", "#"
- else
%li= link_to "Tracks", admin_conference_tracks_list_path(@conference.short_title)
- if activated == "Event Types"
%li.active= link_to "Event Types", "#"
- else
%li= link_to "Event Types", admin_conference_eventtype_list_path(@conference.short_title)

View file

@ -0,0 +1,3 @@
%ul
- @conferences.each do |conference|
%li= link_to conference.title, admin_conference_path(conference.short_title)

View file

@ -0,0 +1,13 @@
= semantic_form_for(@conference, :url => admin_conference_index_path) do |f|
= f.inputs "Basic Information" do
= f.input :title, :hint => "The name of your conference as it shall appear throughout the site. Example: 'OpenSUSE Conference 2013'"
= f.input :short_title, :hint => "A short and unique handle for your conference, using only lower-case letters, numbers and underscores. This will be used to identify your conference in URLs etc. Example: 'froscon2011'"
= f.input :social_tag, :hint => "The hashtag you'll use on Twitter and Google+. Don't include the '#' sign!'"
= f.input :contact_email, :hint => "Contact email address for your conference. Will be used as reply-to address in emails sent out by the system."
= f.inputs "Scheduling" do
= f.input :timezone, :as => :time_zone, :hint => "Please select in what time zone your conference will take place. This is needed to correctly display times for your events."
= 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 :html_export_path, :hint => "The path for static HTML exports"
= f.actions do
= f.action :submit, :button_html => {:class => "btn primary"}

View file

@ -0,0 +1,17 @@
.container-fluid
.row-fluid
.span3
= render 'admin/conference/sidebar', :activated => "Conference"
.span9
= semantic_form_for(@conference, :url => admin_conference_path(@conference.short_title),:html => {:multipart => true}) do |f|
= f.input :title, :hint => "The full name of the conference, such as 'OpenSUSE Conference 2013'"
= f.input :short_title, :hint => "A short title, such as 'osc2013', to be used in URLs"
= f.input :social_tag, :hint => "The hashtag you'll use on Twitter and Google+. Don't include the '#' sign!'"
= f.input :contact_email, :hint => "Contact email address for your conference. Will be used as reply-to address in emails sent out by the system."
= 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 :html_export_path, :hint => "The path for static HTML exports"
= f.input :cfp_open, :label => false, :hint => "Allow people to submit papers?"
= f.input :registration_open, :label => false, :hint => "Allow people to register as attendees?"
= f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"}

View file

@ -0,0 +1,6 @@
.nested-fields
= f.inputs do
= f.input :email
= f.input :public_name
= remove_association_link :person, f

View file

@ -0,0 +1,2 @@
.container
= render 'proposal/form'

View file

@ -0,0 +1,48 @@
.row-fluid
.span12
%table.table.table-striped.table-bordered.table-hover
%thead
%th
%b Title
%th
%b Submitter
%th
%b Type
%th
%b State
- @events.each do |event|
%tr
%td
=link_to event.title, admin_conference_event_path(@conference.short_title, event)
%td
- if !event.submitter.nil?
=link_to event.submitter.public_name, admin_person_path(event.submitter)
- else
Unknown submitter
%td
= event.event_type.title
%td
- if event.state == "withdrawn"
Withdrawn
- else
.dropdown
= link_to "#", :class => "dropdown-toggle" do
= event.state.humanize
<b class="caret"></b>
%ul.dropdown-menu
- if event.transition_possible? :accept
%li= link_to "Accept event (no email)", update_state_admin_conference_event_path(@conference.short_title, event, :transition => :accept, :send_mail => false),
:method => :put, :hint => "Accept this event without sending an automated email."
- if event.transition_possible? :reject
%li= link_to "Reject event (no email)", update_state_admin_conference_event_path(@conference.short_title, event, :transition => :reject, :send_mail => false),
:method => :put, :confirm => "Are you sure?",
:hint => "Reject this event without sending an automated email."
- if event.transition_possible? :start_review
%li= link_to "Start review", update_state_admin_conference_event_path(@conference.short_title, event, :transition => :start_review),
:method => :put
- if event.transition_possible? :confirm
%li= link_to "Confirm event", update_state_admin_conference_event_path(@conference.short_title, event, :transition => :confirm),
:method => :put, :hint => "Confirm that the speaker(s) will be present and that the event will actually take place."
- if event.transition_possible? :cancel
%li= link_to "Cancel event", update_state_admin_conference_event_path(@conference.short_title, event, :transition => :cancel),
:method => :put, :hint => "Mark this event as cancelled. Usually this means that the speakers had to cancel their appearance."

View file

@ -0,0 +1,112 @@
.row-fluid
.span10
%h3
= @event.title
%i= @event.subtitle
.span2
= link_to "Edit Submission", edit_admin_conference_event_path(@conference.short_title, @event),
:class => "btn btn-mini btn-primary pull-right", :style => "margin-top:20px;"
.row-fluid
.span12
%table.table
%tr
%td
%b State
%td
.dropdown
= link_to "#", :class => "dropdown-toggle" do
= @event.state.humanize
<b class="caret"></b>
%ul.dropdown-menu
- if @event.transition_possible? :accept
%li= link_to "Accept event (no email)", update_state_admin_conference_event_path(@conference.short_title, @event, :transition => :accept, :send_mail => false),
:method => :put, :hint => "Accept this event without sending an automated email."
- if @event.transition_possible? :reject
%li= link_to "Reject event (no email)", update_state_admin_conference_event_path(@conference.short_title, @event, :transition => :reject, :send_mail => false),
:method => :put, :confirm => "Are you sure?",
:hint => "Reject this event without sending an automated email."
- if @event.transition_possible? :start_review
%li= link_to "Start review", update_state_admin_conference_event_path(@conference.short_title, @event, :transition => :start_review),
:method => :put
- if @event.transition_possible? :confirm
%li= link_to "Confirm event", update_state_admin_conference_event_path(@conference.short_title, @event, :transition => :confirm),
:method => :put, :hint => "Confirm that the speaker(s) will be present and that the event will actually take place."
- if @event.transition_possible? :cancel
%li= link_to "Cancel event", update_state_admin_conference_event_path(@conference.short_title, @event, :transition => :cancel),
:method => :put, :hint => "Mark this event as cancelled. Usually this means that the speakers had to cancel their appearance."
%tr
%td
%b Submitter
%td
= link_to @event.submitter.public_name, admin_person_path(@conference.short_title, @event.submitter)
(
= link_to @event.submitter.email, "mailto: #{@event.submitter.email}"
)
%tr
%td
%b Biography
%td
= simple_format(@event.submitter.biography)
%tr
%td
%b Submitted on
%td= @event.created_at
%tr
%td
%b Last updated on
%td= @event.updated_at
%tr
%td
%b Abstract
%td= simple_format(@event.abstract)
%tr
%td
%b Description
%td= simple_format(@event.description)
- if @event.event_attachments.size > 0
%table.table
%thead
%th
%b Filename
%th
%b Title
%th
%b Size
%th
%b Public?
%th
%tbody
- @event.event_attachments.each do |a|
%tr
%td
= link_to a.attachment_file_name, conference_proposal_event_attachment_path(@conference.short_title, @event.id, a.id)
%td
= a.title
%td
= number_to_human_size a.attachment_file_size
%td
- if a.public?
Public
- else
Not Public
%td
= link_to "Delete", conference_proposal_event_attachment_path(@conference.short_title, @event.id, a.id),
:method => :delete, :confirm => "Are you sure you want to delete this attachment? It's permanant!"
.row-fluid
= link_to "Comments (#{@comment_count})", "#", :id => "event-comment-link"
#comments-div
%hr
%ul.media
%div
.row-fluid
= form_tag(comment_admin_conference_event_path(@conference.short_title, @event.id), :method => :post) do
= text_area_tag(:comment, "")
= submit_tag "Add Comment", :class => "btn btn-primary pull-right"
%br
- @comments.each do |comment|
%div
= raw format_comments(comment)

View file

@ -0,0 +1,7 @@
<div class="nested-fields">
<%= f.inputs do %>
<%= f.input :title %>
<%= f.input :length, :input_html => {:size => 3} %>
<%= remove_association_link :event_type, f %>
<% end %>
</div>

View file

@ -0,0 +1,8 @@
.container-fluid
.row-fluid
.span3
= render 'admin/conference/sidebar', :activated => "Event Types"
.span9
= semantic_form_for(@conference, :url => admin_conference_eventtype_update_path(@conference.short_title)) do |f|
= dynamic_association :event_types, "Event Types", f
= f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"}

View file

@ -0,0 +1,18 @@
%table.table.table-striped.table-bordered.table-hover
%thead
%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.last_name
%td= person.first_name
%td= person.public_name
%td= person.registrations.count
%td= link_to "View", admin_person_path(person)

View file

@ -0,0 +1,49 @@
%table.table
%tr
%td
%b First Name
%td
= @person.first_name
%tr
%td
%b Last Name
%td
= @person.last_name
%tr
%td
%b Public Name
%td
= @person.public_name
%tr
%td
%b Company
%td
= @person.company
%tr
%td
%b Email
%td
= @person.email
%tr
%td
%b Created At
%td
= @person.created_at
%tr
%td
%b Updated At
%td
= @person.updated_at
%tr
%td
%b Biography
%td
= @person.biography
%tr
%td
%b Registered to attend
%td
- if @person.registrations.count == 0
None
- else
= @person.registrations.map { |r| r.conference.title }.join ','

View file

@ -0,0 +1,48 @@
.row-fluid
.span12
.pull-right{:style=>"margin-top:20px; margin-bottom:20px;"}
= link_to "Export PDF", admin_conference_registrations_path(@conference.short_title, :format => :pdf), :class => "btn btn-success"
.row-fluid
.span12
%table.table.table-striped.table-bordered.table-hover
%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
%th
%th
- @registrations.each do |registration|
%tr
%td
= registration.last_name
%td
= registration.first_name
%td
= registration.public_name
%td
= registration.email
%td
= registration.attending_social_events
%td
= registration.attending_social_events_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}?"

View file

@ -0,0 +1,38 @@
prawn_document(:force_download=>true, :filename => @pdf_filename) do |pdf|
table_array = []
header_array = [" ",
"Last Name",
"First Name",
"Public Name",
"Email",
"Attending Social Events",
"Attending With Partner",
"Arrival Date",
"Departure Date"]
table_array << header_array
@registrations.each do |registration|
row = []
row << ""
row << registration.last_name
row << registration.first_name
row << registration.public_name
row << registration.email
if registration.attending_social_events
row << "X"
else
row << " "
end
if registration.attending_social_events_with_partner.to_s
row << "X"
else
row << " "
end
row << registration.arrival
row << registration.departure
table_array << row
end
pdf.text "#{@conference.title} Registrations", :font_size => 25
pdf.table table_array, :header => true, :cell_style => {:size => 5, :border_width => 1}
end

View file

@ -0,0 +1,8 @@
<div class="nested-fields">
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :size, :input_html => {:size => 5} %>
<%= f.input :public, :as => :boolean %>
<%= remove_association_link :room, f %>
<% end %>
</div>

View file

@ -0,0 +1,8 @@
.container-fluid
.row-fluid
.span3
= render 'admin/conference/sidebar', :activated => "Rooms"
.span9
= semantic_form_for(@conference, :url => admin_conference_rooms_update_path(@conference.short_title)) do |f|
= dynamic_association :rooms, "Rooms", f
= f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"}

View file

@ -0,0 +1,8 @@
<div class="nested-fields">
<%= f.inputs do %>
<%= f.input :name %>
<%= f.input :color, :input_html => {:size => 6} %>
<%= f.input :description, :input_html => {:rows => 2 } %>
<%= remove_association_link :track, f %>
<% end %>
</div>

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