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

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>

View file

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

View file

@ -0,0 +1,57 @@
.container-fluid
.row-fluid
.span12
%table.table.table-striped.table-bordered.table-hover
%thead
%th
%b Email
%th
%b Last Name
%th
%b First Name
%th
%b Public Name
%th
%b Roles
%th
%th
- @users.each do |user|
%tr
%td
= user.email
%td
= user.last_name
%td
= user.first_name
%td
= user.public_name
%td
= user.roles.map { |role| role.name }.join ','
%td
.modal.hide.fade{:id => "user-role-selection-#{user.id}", "role" => "dialog", "aria-hidden" => "true"}
.modal-header
%button{"type"=>"button", :class=>"close", "data-dismiss"=>"modal", "aria-hidden"=>"true"}
×
%h3{:id => "role-selector-header-#{user.id}"}
Modifying Roles
.modal-body
- if current_user == user
You cannot modify your own role!
%br
%button{:class=> "btn btn-danger", "data-dismiss"=> "modal", "aria-hidden"=>"true"}
Cancel
- else
= "Give #{user.public_name} (#{user.email}) the following roles:"
= semantic_form_for(user, :url => admin_user_path(user), :method => :put) do |f|
= f.input :roles, :label => false
%button{:class=> "btn btn-danger", "data-dismiss"=> "modal", "aria-hidden"=>"true"}
Cancel
= f.action :submit, :as => :button, :button_html => {:value => "Save", :class => "btn btn-primary"}
=link_to "Modify Roles", "#", "data-toggle" => "modal", "data-target" => "#user-role-selection-#{user.id}}"
%td
=link_to "Details", "#", :class => "user-details-popover", "data-trigger" => "click", "data-placement" => "bottom",
"data-html" => "true",
"data-content" => user.popup_details,
"data-original-title" => ""

View file

@ -0,0 +1,11 @@
.container-fluid
.row-fluid
.span3
= render 'admin/conference/sidebar', :activated => "Venue"
.span9
= semantic_form_for(@venue, :url => admin_conference_venue_update_path(@conference.short_title),:html => {:multipart => true}) do |f|
= f.input :name
= f.input :address
= f.input :website
= f.input :description, :input_html => { :rows => 10, :cols => 20 }
= f.action :submit, :as => :button, :button_html => {:class => "btn btn-primary"}

View file

@ -0,0 +1,22 @@
.container-fluid
.row-fluid
.span12
%h3.pull-left
Registration for
= @conference.title
.row-fluid
.span12
= semantic_form_for(@registration, :url => register_conference_path(@conference.short_title), :html => { :method => :put }) do |f|
= f.fields_for :person do
= f.inputs :public_name, :for => :person
= f.input :attending_social_events, :label => false
= f.input :attending_social_events_with_partner, :label => false
= f.input :using_affiliated_lodging, :label => false
= f.input :arrival, :as => :string, :input_html => { :id => "conference-start-datepicker", :readonly => "readonly" }
= f.input :departure, :as => :string, :input_html => { :id => "conference-end-datepicker", :readonly => "readonly" }
- if @registered
= f.action :submit, :button_html => { :value => "Update Registration", :class => "btn btn-primary" }
= link_to "Unregister", register_conference_path(@conference.short_title),:method => :delete, :class => "btn btn-danger",
:confirm => "Are you sure you want to unregister?"
- else
= f.action :submit, :button_html => { :value => "Register", :class => "btn btn-primary" }

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