Merge branch 'master' into michael/rm-start-restriction

This commit is contained in:
Michael Ball 2020-06-02 02:08:33 -07:00 committed by GitHub
commit 8d5c300639
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
109 changed files with 907 additions and 512 deletions

View file

@ -507,6 +507,7 @@ RSpec/AnyInstance:
Exclude:
- 'spec/controllers/admin/rooms_controller_spec.rb'
- 'spec/controllers/admin/sponsorship_levels_controller_spec.rb'
- 'spec/controllers/admin/tickets_controller_spec.rb'
- 'spec/controllers/admin/tracks_controller_spec.rb'
- 'spec/controllers/admin/users_controller_spec.rb'
- 'spec/controllers/conference_registration_controller_spec.rb'

View file

@ -1 +1 @@
2.5.0
2.5.5

View file

@ -4,6 +4,12 @@ Not release yet...
## Update from 1.0
### Dropped travel information
We have dropped input and storage of travel schedules for event registrants. If
you would like to continue to collect travel schedules, please create a custom
survey for this purpose.
_Please be aware that existing travel data will be destroyed during migration._
### Multiple Schedules
A conference can have multiple schedules now so it's easier for organizers to
test schedules and collaborate on different versions.

View file

@ -2,7 +2,7 @@
source 'https://rubygems.org'
ruby ENV['OSEM_RUBY_VERSION'] || '2.5.0'
ruby ENV['OSEM_RUBY_VERSION'] || '2.5.5'
# rails-assets requires >= 1.8.4
if Gem::Version.new(Bundler::VERSION) < Gem::Version.new('1.8.4')
@ -20,7 +20,6 @@ gem 'puma', '~> 3.0'
gem 'responders', '~> 2.0'
# as supported databases
gem 'mysql2'
gem 'pg'
# for tracking data changes
@ -38,8 +37,8 @@ gem 'rails-i18n'
gem 'devise'
gem 'devise_ichain_authenticatable'
# for openID authentication
gem 'omniauth'
gem 'omniauth-discourse'
gem 'omniauth-facebook'
gem 'omniauth-github'
gem 'omniauth-google-oauth2'
@ -143,8 +142,7 @@ gem 'rqrcode'
gem 'axlsx', git: 'https://github.com/randym/axlsx.git'
gem 'axlsx_rails'
# as error catcher
gem 'airbrake'
gem 'sentry-raven'
# to make links faster
gem 'turbolinks'

View file

@ -68,10 +68,6 @@ GEM
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
afm (0.2.2)
airbrake (9.2.2)
airbrake-ruby (~> 4.4)
airbrake-ruby (4.4.0)
rbtree3 (~> 0.5)
ajax-datatables-rails (0.4.3)
railties (>= 4.0)
archive-zip (0.12.0)
@ -130,7 +126,6 @@ GEM
url
coderay (1.1.1)
concurrent-ruby (1.1.5)
connection_pool (2.2.2)
countable-rails (0.0.1)
railties (>= 3.1)
countries (3.0.0)
@ -301,13 +296,10 @@ GEM
monetize (~> 1.9.0)
money (~> 6.13.2)
railties (>= 3.0)
multi_json (1.13.1)
multi_json (1.14.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
mysql2 (0.5.2)
nenv (0.3.0)
net-http-persistent (3.0.1)
connection_pool (~> 2.2)
netrc (0.11.0)
nio4r (2.5.2)
nokogiri (1.10.8)
@ -324,7 +316,9 @@ GEM
omniauth (1.9.0)
hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
omniauth-facebook (5.0.0)
omniauth-discourse (1.0.0)
omniauth (~> 1.0)
omniauth-facebook (6.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.3.0)
omniauth (~> 1.5)
@ -441,7 +435,6 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rbtree3 (0.5.0)
rdoc (6.0.4)
rdoc-generator-fivefish (0.4.0)
inversion (~> 1.1)
@ -525,6 +518,8 @@ GEM
selenium-webdriver (3.142.6)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
sentry-raven (2.13.0)
faraday (>= 0.7.6, < 1.0)
sexp_processor (4.11.0)
shellany (0.0.1)
shoulda-matchers (4.1.2)
@ -553,13 +548,11 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.4.2)
stripe (4.21.3)
faraday (~> 0.13)
net-http-persistent (~> 3.0)
stripe-ruby-mock (2.5.8)
stripe (5.14.0)
stripe-ruby-mock (3.0.1)
dante (>= 0.2.0)
multi_json (~> 1.0)
stripe (>= 2.0.3)
stripe (> 5, < 6)
sysexits (1.2.0)
temple (0.8.0)
thor (0.20.3)
@ -616,7 +609,6 @@ DEPENDENCIES
active_model_serializers
acts_as_commentable_with_threading
acts_as_list
airbrake
ajax-datatables-rails
autoprefixer-rails
awesome_nested_set
@ -665,9 +657,9 @@ DEPENDENCIES
mina
mini_magick
money-rails
mysql2
nokogiri (>= 1.8.1)
omniauth
omniauth-discourse
omniauth-facebook
omniauth-github
omniauth-google-oauth2
@ -707,6 +699,7 @@ DEPENDENCIES
ruby-oembed
sass-rails (>= 4.0.2)
selectize-rails
sentry-raven
shoulda-matchers
skylight
spring-commands-rspec
@ -726,7 +719,7 @@ DEPENDENCIES
whenever
RUBY VERSION
ruby 2.5.0p0
ruby 2.5.5p157
BUNDLED WITH
1.17.3

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View file

@ -11,39 +11,6 @@ $(function () {
format: 'YYYY-MM-DD HH:mm'
});
$("#registration-arrival-datepicker").datetimepicker({
useCurrent: false,
stepping: 15,
sideBySide: true,
format: "YYYY-MM-DD HH:mm",
// arrival_date <= end_date
maxDate : $("#registration-arrival-datepicker").attr('end_date')
});
$("#registration-departure-datepicker").datetimepicker({
useCurrent: false,
stepping: 15,
sideBySide: true,
format: "YYYY-MM-DD HH:mm",
// departure_date > start_date
minDate : $("#registration-arrival-datepicker").attr('start_date')
});
$("#registration-arrival-datepicker").on("dp.change",function (e) {
// departure_date > start_date,arrival_date
if ((new Date(e.date).getTime()) > (new Date($("#registration-arrival-datepicker").attr('start_date')).getTime())){
$('#registration-departure-datepicker').data("DateTimePicker").minDate(e.date);
}
else{
$('#registration-departure-datepicker').data("DateTimePicker").minDate($("#registration-arrival-datepicker").attr('start_date'));
}
});
// departure_date >= arrival_date
$("#registration-departure-datepicker").on("dp.change",function (e) {
$('#registration-arrival-datepicker').data("DateTimePicker").maxDate(e.date);
});
$("#conference-start-datepicker").datetimepicker({
useCurrent: false,
format: "YYYY-MM-DD"

View file

@ -2,6 +2,13 @@
*= require strap-on
*= require formtastic-bootstrap
*= require dataTables/bootstrap/3/jquery.dataTables.bootstrap
*= require selectize
*= require selectize.bootstrap3
*= require bootstrap-select
*= require bootstrap-markdown
*= require bootstrap-datetimepicker
*= require leaflet
*= require osem
*= require osem-rating
*= require osem-schedule
@ -10,15 +17,9 @@
*= require osem-splash
*= require font-awesome
*= require osem-fonts
*= require bootstrap-markdown
*= require bootstrap-datetimepicker
*= require leaflet
*= require bootstrap3-switch
*= require osem-payments
*= require osem-navbar
*= require selectize
*= require selectize.bootstrap3
*= require mastodon
*= require bootstrap-select
*= require conferences
*/

View file

@ -1,4 +1,6 @@
@import "breakpoints.scss";
@import "osem-variables.scss";
.nav-osem {
border: none;
@include breakpoint(xs) {
@ -29,7 +31,23 @@
}
}
.dropdown-menu {
padding: 17px;
min-width: 225px;
}
&.navbar-default {
.navbar-nav > .open > a {
&:hover, &:focus {
color: $navbar-default-link-color;
}
}
}
.navbar-brand img {
margin-top: -5px;
max-height: 100%;
}
.trapezoid {
border-top-color: $navbar-default-bg;
}
}

View file

@ -64,9 +64,8 @@
#schedule td.event {
background-image: linear-gradient(to top, rgb(247,250,242) 24%, rgb(194,232,190) 97%, rgb(194,232,190) 100%);
cursor: pointer;
padding: 3px 2px;
cursor: pointer;
padding: 3px 2px;
}
#schedule td.event:hover

View file

@ -1,4 +1,5 @@
@import "breakpoints.scss";
@import "osem-variables.scss";
#splash {
// Counter the general padding for #content
@ -6,18 +7,30 @@
section {
padding-top: 60px;
padding-bottom: 60px;
.trapezoid {
top: 60px + $trapezoid-height;
}
}
section:nth-child(even) {
background: none repeat scroll 0 0 #e0e0e0;
color: #555;
background: none repeat scroll 0 0 #eee;
color: #333;
.trapezoid {
border-top-color: #eee;
}
}
section:nth-child(odd) {
background: none repeat scroll 0 0 #ffffff;
color: #7b7b7b;
color: #333;
.thumbnail {
background: none repeat scroll 0 0 #e0e0e0;
}
.trapezoid {
border-top-color: #fff;
}
}
.cta-button {
@ -32,11 +45,15 @@
padding-top: 100px;
padding-bottom: 100px;
.container {
#header {
#header-no-image {
background-color: rgba(224, 224, 224,.80);
padding-top: 20px;
padding-bottom: 20px;
}
#header-image {
color: #FFF;
}
}
}
@ -67,6 +84,10 @@
#venue-pic {
margin-top: 20px;
}
// The venue section has less padding.
.trapezoid {
top: $trapezoid-height;
}
}
#lodging {
@ -93,6 +114,14 @@
}
}
#tickets {
a {
&:hover, &:focus {
text-decoration: none;
}
}
}
#sponsors {
.img-sponsor {
max-height: 100px;
@ -116,14 +145,13 @@
}
#social-media{
background: none repeat scroll 0 0 #2f2f2f;
padding-top: 60px;
padding-bottom: 60px;
background: none repeat scroll 0 0 #0C3559;
padding: 50px 20px;
i{
color: #4a4a4a;
color: #FFF;
}
i:hover{
color: #16a085;
color: #F2E205;
}
a{
padding-left: 100px;
@ -164,11 +192,11 @@
i.fa {
line-height: inherit;
}
&.show {
visibility:visible;
cursor:pointer;
opacity: 1.0;
}
// &.show {
// visibility:visible;
// cursor:pointer;
// opacity: 1.0;
// }
a {
color: white;
}

View file

@ -0,0 +1,14 @@
// This file is included *early* in CSS order!
// These variables change bootstrap defaults.
$navbar-default-bg: #0C3559;
$navbar-default-link-active-bg: rgb(8,8,8);
$navbar-default-border: 1px solid #d4d4d4;
$navbar-default-color: #FFF;
$navbar-default-link-color: #FFF;
$navbar-default-link-hover-color: #F2E205;
$navbar-default-link-active-hover-color: #FFF;
// The hiegh of the section tabs that are like Snap! blocks.
$trapezoid-height: 14px;

View file

@ -1,3 +1,4 @@
@import "osem-variables";
@import "bootstrap/mixins";
html {
@ -7,15 +8,31 @@ html {
body {
/* Margin bottom by 2 times the footer height */
margin-bottom: 60px;
margin-bottom: 85px;
/* Margin bottom by navbar height */
padding-top: 60px;
font-size: 16px;
}
#content {
padding-bottom: 60px;
}
// Designed to be the last element in a section / nav
// Makes a little "puzzle piece" connector.
.trapezoid {
position: relative;
margin-left: 60px;
border-top: $trapezoid-height solid;
border-left: 9px solid transparent;
border-right: 9px solid transparent;
height: 0;
width: 64px;
margin-top: -1 * $trapezoid-height;
top: $trapezoid-height;
z-index: 1000;
}
#footer {
position: absolute;
bottom: 0;

View file

@ -1,10 +1,5 @@
$navbar-default-bg: #299a0b;
$navbar-default-link-active-bg: #DFE0DF;
$navbar-default-border: 1px solid #d4d4d4;
$navbar-default-color: #ffffff;
$navbar-default-link-color: #ffffff;
$navbar-default-link-hover-color: #000000;
// Place bootstrap variable customizations in the file below.
@import "osem-variables";
@import 'bootstrap-datetimepicker';
@import "bootstrap-sprockets";

View file

@ -17,10 +17,10 @@ module Admin
if @commercial.save
redirect_to admin_conference_commercials_path,
notice: 'Commercial was successfully created.'
notice: 'Materials were successfully created.'
else
redirect_to admin_conference_commercials_path,
error: 'An error prohibited this Commercial from being saved: '\
error: 'An error prohibited materials from being saved: '\
"#{@commercial.errors.full_messages.join('. ')}."
end
@ -29,17 +29,17 @@ module Admin
def update
if @commercial.update(commercial_params)
redirect_to admin_conference_commercials_path,
notice: 'Commercial was successfully updated.'
notice: 'Materials were successfully updated.'
else
redirect_to admin_conference_commercials_path,
error: 'An error prohibited this Commercial from being saved: '\
error: 'An error prohibited materials from being saved: '\
"#{@commercial.errors.full_messages.join('. ')}."
end
end
def destroy
@commercial.destroy
redirect_to admin_conference_commercials_path, notice: 'Commercial was successfully destroyed.'
redirect_to admin_conference_commercials_path, notice: 'Materials were successfully removed.'
end
def render_commercial
@ -60,9 +60,9 @@ module Admin
errors = Commercial.read_file(params[:file]) if params[:file]
if !params[:file]
flash[:error] = 'Empty file detected while adding commercials to Event'
flash[:error] = 'Empty file detected while adding materials to Event'
elsif errors.all? { |_k, v| v.blank? }
flash[:notice] = 'Successfully added commercials.'
flash[:notice] = 'Successfully added materials.'
else
errors_text = ''
errors_text << 'Unable to find event with ID: ' + errors[:no_event].join(', ') + '. ' if errors[:no_event].any?

View file

@ -82,7 +82,7 @@ module Admin
def registration_params
params.require(:registration).permit(
:user_id, :conference_id, :arrival, :departure, :attended,
:user_id, :conference_id, :attended,
:volunteer, :other_special_needs, :accepted_code_of_conduct,
vchoice_ids: [], qanswer_ids: [], qanswers_attributes: [], event_ids: []
)

View file

@ -38,13 +38,30 @@ module Admin
end
end
def give
ticket_purchase = @ticket.ticket_purchases.new(gift_ticket_params)
recipient = ticket_purchase.user
if ticket_purchase.save
redirect_to(
admin_conference_ticket_path(@conference.short_title, @ticket),
notice: "#{recipient.name} was given a #{@ticket.title} ticket."
)
else
redirect_back(
fallback_location: admin_conference_ticket_path(@conference.short_title, @ticket),
error: "Unable to give #{recipient.name} a #{@ticket.title} ticket: " +
ticket_purchase.errors.full_messages.to_sentence
)
end
end
def destroy
if @ticket.destroy
redirect_to admin_conference_tickets_path(conference_id: @conference.short_title),
notice: 'Ticket successfully destroyed.'
notice: 'Ticket successfully deleted.'
else
redirect_to admin_conference_tickets_path(conference_id: @conference.short_title),
error: 'Ticket was successfully destroyed.' \
error: 'Deleting ticket failed! ' \
"#{@ticket.errors.full_messages.join('. ')}."
end
end
@ -52,7 +69,19 @@ module Admin
private
def ticket_params
params.require(:ticket).permit(:conference, :title, :url, :description, :conference_id, :price_cents, :price_currency, :price, :registration_ticket)
params.require(:ticket).permit(
:conference, :conference_id,
:title, :url, :description,
:price_cents, :price_currency, :price,
:registration_ticket, :visible
)
end
def gift_ticket_params
response = params.require(:ticket_purchase).permit(
:user_id
)
response.merge(paid: true, amount_paid: 0, conference: @conference)
end
end
end

View file

@ -12,10 +12,10 @@ module Admin
if @commercial.save
redirect_to admin_conference_venue_path,
notice: 'Commercial was successfully created.'
notice: 'Materials successfully created.'
else
redirect_to admin_conference_venue_path,
error: 'An error prohibited this Commercial from being saved: '\
error: 'An error prohibited materials from being saved: '\
"#{@commercial.errors.full_messages.join('. ')}."
end
@ -24,17 +24,17 @@ module Admin
def update
if @commercial.update(commercial_params)
redirect_to admin_conference_venue_path,
notice: 'Commercial was successfully updated.'
notice: 'Materials successfully updated.'
else
redirect_to admin_conference_venue_path,
error: 'An error prohibited this Commercial from being saved: '\
error: 'An error prohibited materials from being saved: '\
"#{@commercial.errors.full_messages.join('. ')}."
end
end
def destroy
@commercial.destroy
redirect_to admin_conference_venue_path, notice: 'Commercial was successfully destroyed.'
redirect_to admin_conference_venue_path, notice: 'Materials successfully destroyed.'
end
def render_commercial

View file

@ -12,27 +12,27 @@ class CommercialsController < ApplicationController
if @commercial.save
redirect_to edit_conference_program_proposal_path(conference_id: @conference.short_title, id: @event.id, anchor: 'commercials-content'),
notice: 'Commercial was successfully created.'
notice: 'Materials were successfully created.'
else
redirect_to edit_conference_program_proposal_path(conference_id: @conference.short_title, id: @event.id, anchor: 'commercials-content'),
error: "An error prohibited this Commercial from being saved: #{@commercial.errors.full_messages.join('. ')}."
error: "An error prohibited these materials from being saved: #{@commercial.errors.full_messages.join('. ')}."
end
end
def update
if @commercial.update(commercial_params)
redirect_to edit_conference_program_proposal_path(conference_id: @conference.short_title, id: @event.id, anchor: 'commercials-content'),
notice: 'Commercial was successfully updated.'
notice: 'Materials were successfully updated.'
else
redirect_to edit_conference_program_proposal_path(conference_id: @conference.short_title, id: @event.id, anchor: 'commercials-content'),
error: "An error prohibited this Commercial from being saved: #{@commercial.errors.full_messages.join('. ')}."
error: "An error prohibited materials from being saved: #{@commercial.errors.full_messages.join('. ')}."
end
end
def destroy
@commercial.destroy
redirect_to edit_conference_program_proposal_path(conference_id: @conference.short_title, id: @event.id),
notice: 'Commercial was successfully destroyed.'
notice: 'Materials were successfully destroyed.'
end
def render_commercial

View file

@ -57,7 +57,7 @@ class ConferenceRegistrationsController < ApplicationController
sign_in(@registration.user)
end
if @conference.tickets.any? && !current_user.supports?(@conference)
if @conference.tickets.visible.any? && !current_user.supports?(@conference)
redirect_to conference_tickets_path(@conference.short_title),
notice: 'You are now registered and will be receiving E-Mail notifications.'
else
@ -108,9 +108,9 @@ class ConferenceRegistrationsController < ApplicationController
end
def registration_params
params.require(:registration)
params.permit(:registration)
.permit(
:conference_id, :arrival, :departure,
:conference_id,
:volunteer, :accepted_code_of_conduct,
vchoice_ids: [], qanswer_ids: [],
qanswers_attributes: [],

View file

@ -51,10 +51,10 @@ class ConferencesController < ApplicationController
end
end
if splashpage.include_registrations || splashpage.include_tickets
@tickets = @conference.tickets.order('price_cents')
@tickets = @conference.tickets.visible.order('price_cents')
end
if splashpage.include_lodgings
@lodgings = @conference.lodgings.order('name')
@lodgings = @conference.lodgings.order('id')
end
if splashpage.include_sponsors
@sponsorship_levels = @conference.sponsorship_levels.eager_load(

View file

@ -3,7 +3,8 @@
class TicketsController < ApplicationController
before_action :authenticate_user!
load_resource :conference, find_by: :short_title
load_resource :ticket, through: :conference
before_action :load_tickets
authorize_resource :ticket, through: :conference
authorize_resource :conference_registrations, class: Registration
before_action :check_load_resource, only: :index
@ -14,4 +15,8 @@ class TicketsController < ApplicationController
redirect_to root_path, notice: "There are no tickets available for #{@conference.title}!"
end
end
def load_tickets
@tickets = @conference.tickets.visible
end
end

View file

@ -10,8 +10,6 @@ class RegistrationDatatable < AjaxDatatablesRails::Base
roles: { source: 'Role.name' },
email: { source: 'User.email' },
accepted_code_of_conduct: { source: 'Registration.accepted_code_of_conduct', searchable: false },
arrival: { source: 'Registration.arrival', searchable: false },
departure: { source: 'Registration.departure', searchable: false },
actions: { source: 'Registration.id', searchable: false, orderable: false }
}
end
@ -36,8 +34,6 @@ class RegistrationDatatable < AjaxDatatablesRails::Base
roles: conference_role_titles(record.user),
email: record.email,
accepted_code_of_conduct: !!record.accepted_code_of_conduct, # rubocop:disable Style/DoubleNegation
arrival: record.arrival&.utc,
departure: record.departure&.utc,
questions: {},
edit_url: edit_admin_conference_registration_path(conference, record),
DT_RowId: record.id

View file

@ -40,19 +40,20 @@ class UserDatatable < AjaxDatatablesRails::Base
# rubocop:disable Naming/AccessorMethodName
def get_raw_records
User.left_outer_joins(:registrations, :roles)
.distinct
.select("users.*, COUNT(CASE WHEN registrations.attended = 't' THEN 1 END) AS attended_count")
.group('users.id')
User.left_outer_joins(:registrations, :roles).select(
"DISTINCT users.id, users.name, users.email, users.confirmed_at, COUNT(CASE WHEN registrations.attended = 't' THEN 1 END) AS attended_count"
).group(
'users.id, users.name, users.email, users.confirmed_at'
)
end
# rubocop:enable Naming/AccessorMethodName
def records_total_count
fetch_records.unscope(:group).count(:all)
fetch_records.unscoped.count(:id)
end
def records_filtered_count
filter_records(fetch_records).unscope(:group).count(:all)
filter_records(fetch_records).unscoped.count
end
# ==== These methods represent the basic operations to perform on records

View file

@ -178,20 +178,22 @@ module ApplicationHelper
'hidden' if Date.today > conference.end_date
end
# TODO:Snap!Con: Replace this with a search for a conference logo.
def nav_root_link_for(conference)
link_text = (
conference.try(:organization).try(:name) ||
ENV['OSEM_NAME'] ||
'OSEM'
)
link_to(
link_text,
image_tag('snapcon_logo.png'),
root_path,
class: 'navbar-brand',
title: 'Open Source Event Manager'
title: nav_link_text(conference)
)
end
def nav_link_text(conference)
conference.try(:organization).try(:name) ||
ENV['OSEM_NAME'] ||
'OSEM'
end
# returns the url to be used for logo on basis of sponsorship level position
def get_logo(object)
if object.try(:sponsorship_level)

View file

@ -1,5 +1,7 @@
# frozen_string_literal: true
require 'redcarpet/render_strip'
module FormatHelper
##
# Includes functions related to formatting (like adding classes, colors)
@ -42,12 +44,11 @@ module FormatHelper
def target_progress_color(progress)
progress = progress.to_i
result =
case
when progress >= 90 then 'green'
when progress < 90 && progress >= 80 then 'orange'
else 'red'
end
result = case
when progress >= 90 then 'green'
when progress < 90 && progress >= 80 then 'orange'
else 'red'
end
result
end
@ -99,19 +100,11 @@ module FormatHelper
end
def icon_for_todo(bool)
if bool
'fa fa-check'
else
'fa fa-times'
end
bool ? 'fa fa-check' : 'fa fa-times'
end
def class_for_todo(bool)
if bool
'todolist-ok'
else
'todolist-missing'
end
bool ? 'todolist-ok' : 'todolist-missing'
end
def word_pluralize(count, singular, plural = nil)
@ -191,9 +184,12 @@ module FormatHelper
return '' if text.nil?
options = {
autolink: true,
autolink: true,
space_after_headers: true,
no_intra_emphasis: true
tables: true,
strikethrough: true,
footnotes: true,
superscript: true
}
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(escape_html: escape_html), options)
markdown.render(text).html_safe
@ -203,6 +199,11 @@ module FormatHelper
markdown("#{text} Please look at #{link_to '**Markdown Syntax**', 'https://daringfireball.net/projects/markdown/syntax', target: '_blank'} to format your text", false)
end
# Return a plain text markdown stripped of formatting.
def plain_text(content)
Redcarpet::Markdown.new(Redcarpet::Render::StripDown).render(content)
end
def quantity_left_of(resource)
return '-/-' if resource.quantity.blank?

View file

@ -1,8 +1,11 @@
# frozen_string_literal: true
SNAPCON_BCC_ADDRESS = 'messages@snap.berkeley.edu'
class Mailbot < ActionMailer::Base
def registration_mail(conference, user)
mail(to: user.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.registration_subject,
body: conference.email_settings.generate_email_on_conf_updates(conference,
@ -21,6 +24,7 @@ class Mailbot < ActionMailer::Base
end
mail(to: @user.email,
bcc: SNAPCON_BCC_ADDRESS,
from: @conference.contact.email,
template_name: 'ticket_confirmation_template',
subject: "#{@conference.title} | Ticket Confirmation and PDF!")
@ -30,6 +34,7 @@ class Mailbot < ActionMailer::Base
conference = event.program.conference
mail(to: event.submitter.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.accepted_subject,
body: conference.email_settings.generate_event_mail(event, conference.email_settings.accepted_body))
@ -39,6 +44,7 @@ class Mailbot < ActionMailer::Base
conference = event.program.conference
mail(to: event.submitter.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.submitted_proposal_subject,
body: conference.email_settings.generate_event_mail(event, conference.email_settings.submitted_proposal_body))
@ -48,6 +54,7 @@ class Mailbot < ActionMailer::Base
conference = event.program.conference
mail(to: event.submitter.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.rejected_subject,
body: conference.email_settings.generate_event_mail(event, conference.email_settings.rejected_body))
@ -57,6 +64,7 @@ class Mailbot < ActionMailer::Base
conference = event.program.conference
mail(to: event.submitter.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.confirmed_without_registration_subject,
body: conference.email_settings.generate_event_mail(event,
@ -65,6 +73,7 @@ class Mailbot < ActionMailer::Base
def conference_date_update_mail(conference, user)
mail(to: user.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.conference_dates_updated_subject,
body: conference.email_settings.generate_email_on_conf_updates(conference,
@ -74,6 +83,7 @@ class Mailbot < ActionMailer::Base
def conference_registration_date_update_mail(conference, user)
mail(to: user.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.conference_registration_dates_updated_subject,
body: conference.email_settings.generate_email_on_conf_updates(conference,
@ -83,6 +93,7 @@ class Mailbot < ActionMailer::Base
def conference_venue_update_mail(conference, user)
mail(to: user.email,
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.venue_updated_subject,
body: conference.email_settings.generate_email_on_conf_updates(conference,

View file

Binary file not shown.

View file

@ -87,7 +87,9 @@ class Ability
end
can :index, Organization
can :index, Ticket
can :index, Ticket do |ticket|
ticket.visible
end
can :manage, TicketPurchase, user_id: user.id
can [:new, :create], Payment, user_id: user.id
can [:index, :show], PhysicalTicket, user: user

View file

@ -39,7 +39,7 @@ class Commercial < ApplicationRecord
commercial = event.commercials.new(url: url)
unless commercial.save
errors[:validation_errors] << "Could not create commercial for event with ID #{event.id} (" + commercial.errors.full_messages.to_sentence + ')'
errors[:validation_errors] << "Could not create materials for event with ID #{event.id} (" + commercial.errors.full_messages.to_sentence + ')'
end
end
errors

View file

@ -25,8 +25,8 @@ class Conference < ApplicationRecord
has_one :email_settings, dependent: :destroy
has_one :program, dependent: :destroy
has_one :venue, dependent: :destroy
has_many :physical_tickets, through: :ticket_purchases
has_many :ticket_purchases, dependent: :destroy
has_many :physical_tickets, through: :ticket_purchases
has_many :payments, dependent: :destroy
has_many :supporters, through: :ticket_purchases, source: :user
has_many :tickets, dependent: :destroy

View file

@ -28,8 +28,6 @@ class Registration < ApplicationRecord
validates :user_id, uniqueness: { scope: :conference_id, message: 'already Registered!' }
validate :registration_limit_not_exceed, on: :create
validate :registration_to_events_only_if_present
validates :accepted_code_of_conduct, acceptance: {
if: -> { conference.try(:code_of_conduct).present? }
}
@ -48,19 +46,6 @@ class Registration < ApplicationRecord
private
##
# If the user registers to attend events that are already scheduled,
# only allow registration to events if the user will be present
# (based on arrival and departure attributes)
# No validation if arrival/departure attributes are empty
def registration_to_events_only_if_present
if (arrival || departure) && events.pluck(:start_time).any?
errors.add(:arrival, 'is too late! You cannot register for events that take place before your arrival') if events.pluck(:start_time).compact.map { |x| x < arrival }.any?
errors.add(:departure, 'is too early! You cannot register for events that take place after your departure') if events.pluck(:start_time).compact.map { |x| x > departure }.any?
end
end
def subscribe_to_conference
Subscription.create(conference_id: conference.id, user_id: user.id)
end

View file

@ -20,6 +20,8 @@ class Ticket < ApplicationRecord
validates :price_cents, numericality: { greater_than_or_equal_to: 0 }
scope :visible, -> { where(visible: true) }
def bought?(user)
buyers.include?(user)
end

View file

@ -32,7 +32,7 @@ class TicketPurchase < ApplicationRecord
errors.push('You cannot buy more than one registration tickets.')
else
ActiveRecord::Base.transaction do
conference.tickets.each do |ticket|
conference.tickets.visible.each do |ticket|
quantity = purchases[ticket.id.to_s].to_i
# if the user bought the ticket and is still unpaid, just update the quantity
purchase = if ticket.bought?(user) && ticket.unpaid?(user)

View file

@ -50,7 +50,10 @@ class User < ApplicationRecord
else
[:database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable,
:omniauthable, omniauth_providers: [:suse, :google, :facebook, :github]]
:omniauthable,
# omniauth_providers: [:suse, :google, :facebook, :github, :discourse]
omniauth_providers: [:google, :discourse]
]
end
devise(*devise_modules)

View file

@ -1,11 +1,11 @@
.row
.col-md-12
.page-header
%h1 Commercials
%h1 Session Materials
%p.text-muted
Conference commercials will be displayed on the events in the
Conference materials will be displayed on the events in the
= link_to 'schedule,', conference_schedule_path(@conference.short_title)
if the event speaker didn't add an event commercial.
if the event speaker didn't add any event materials.
- if can? :create, @conference.commercials.new
.row
.col-md-6

View file

@ -7,11 +7,12 @@
Event Type
= @event_type.title
.row
.col-md-12
= semantic_form_for(@event_type, url: (@event_type.new_record? ? admin_conference_program_event_types_path : admin_conference_program_event_type_path(@conference.short_title, @event_type))) do |f|
.col-md-8
- form_url = (@event_type.new_record? ? admin_conference_program_event_types_path : admin_conference_program_event_type_path(@conference.short_title, @event_type))
= semantic_form_for(@event_type, url: form_url) do |f|
= f.input :title, input_html: { autofocus: true }
= f.input :length, input_html: {size: 3, type: 'number', step: @event_type.program.schedule_interval, min: @event_type.program.schedule_interval}
= f.input :description
= f.input :description, as: :text, hint: markdown_hint, input_html: { rows: 5, data: { provide: 'markdown-editable' } }
= f.input :minimum_abstract_length, input_html: {size: 3}
= f.input :maximum_abstract_length, input_html: {size: 3}
= f.input :color, input_html: { size: 6, type: 'color' }

View file

@ -20,7 +20,7 @@
%td
= event_type.title
%td
= event_type.description
= markdown(event_type.description)
%td
= event_type.length
Minutes

View file

@ -6,9 +6,9 @@
= "(#{@events.length})" if @events.any?
.btn-group.pull-right
%button.btn.btn-primary{ title: 'Mass import of commercials for events',
%button.btn.btn-primary{ title: 'Mass import of materials for events',
data: { toggle: 'modal', target: '#mass-commercials-modal' } }
Add Commercials
Add Materials
- if can? :create, Event
= link_to 'Add Event',
@ -28,7 +28,7 @@
.modal-dialog
.modal-content
.modal-header
%h1 Add commercials to events
%h1 Add materials to events
.text-muted
Upload your file with data in the following format:
%b Event_ID:Commercial_Link

View file

@ -11,7 +11,7 @@
- progress_status = @event.progress_status
= progress_status.reject{ |_key, value| value || value.nil? }.length
%li
= link_to 'Commercials', '#proposal-commercials', 'data-toggle' => 'tab'
= link_to 'Materials', '#proposal-commercials', 'data-toggle' => 'tab'
.tab-content
#proposal-content.tab-pane.active
@ -42,7 +42,7 @@
- else
= general_change_description(version)
= link_to 'commercial',
= link_to 'materials',
edit_admin_conference_program_event_path(conference_id: @conference.short_title,
id: @event.id, anchor: 'commercials-content')
@ -82,7 +82,7 @@
%td{ 'class' => class_for_todo(progress_status['subtitle']) }
%span{ 'class' => [icon_for_todo(progress_status['subtitle']), 'fa-lg'] }
%tr
%td= link_to 'Add a commercial', edit_admin_conference_program_event_path(@event.program.conference.short_title, @event, anchor: 'commercials-content')
%td= link_to 'Add materials', edit_admin_conference_program_event_path(@event.program.conference.short_title, @event, anchor: 'commercials-content')
%td{ 'class' => class_for_todo(progress_status['commercials']) }
%span{ 'class' => [icon_for_todo(progress_status['commercials']), 'fa-lg'] }
- unless progress_status['track'].nil?

View file

@ -30,8 +30,6 @@
%th{ width: '0' } E-Mail
%th{ width: '0' }
%abbr{ title: 'Code of Conduct' } CoC
%th{ width: '0' } Arrival
%th{ width: '0' } Departure
%th{ width: '0' } Actions
%tbody
@ -81,22 +79,6 @@
"className": "code-of-conduct text-center",
"searchable": false
},
{
"data": "arrival",
"searchable": false,
"render": function(data, type, row) {
if (data) { return moment(data).format('ll LT'); }
return '';
}
},
{
"data": "departure",
"searchable": false,
"render": function(data, type, row) {
if (data) { return moment(data).format('ll LT'); }
return '';
}
},
{
"data": null,
"className": "actions",

View file

@ -4,9 +4,7 @@ prawn_document(force_download: true, filename: @pdf_filename, page_layout: :land
'Name',
'Nickname',
'Affiliation',
'Email',
'Arrival Date',
'Departure Date']
'Email']
@conference.questions.each do |question|
header_array << question.title
end
@ -19,8 +17,6 @@ prawn_document(force_download: true, filename: @pdf_filename, page_layout: :land
row << registration.nickname
row << registration.affiliation
row << registration.email
row << registration.arrival.to_s || ''
row << registration.departure.to_s || ''
@conference.questions.each do |question|
qa = registration.qanswers.find_by(question: question)

View file

@ -3,7 +3,7 @@
wb = xlsx_package.workbook
wb.add_worksheet(name: 'registrations') do |sheet|
bold_style = wb.styles.add_style(b: true)
row = ['Attended', 'Name', 'Nickname', 'Affilιation', 'Email', 'Arrival', 'Departure']
row = ['Attended', 'Name', 'Nickname', 'Affilιation', 'Email']
@conference.questions.each do |question|
row << question.title
@ -18,8 +18,6 @@ wb.add_worksheet(name: 'registrations') do |sheet|
row << registration.nickname
row << registration.affiliation
row << registration.email
row << registration.arrival.to_s
row << registration.departure.to_s
@conference.questions.each do |question|
qa = registration.qanswers.find_by(question: question)
answer = ( qa ? qa.answer.title : '' )
@ -30,4 +28,3 @@ wb.add_worksheet(name: 'registrations') do |sheet|
sheet.add_row row
end
end

View file

@ -14,7 +14,7 @@
%th Title
%th Speakers Registered
%th Speakers Biographies
%th Commercial
%th Materials
%th Subtitle
%th Difficulty Level
- if @program.tracks.any?

View file

@ -2,10 +2,10 @@
.col-md-12
.page-header
%h1
Events without commercials
Events Without Materials
= "(#{@events_missing_commercial.length})"
%p.text-muted
All submissions that have no commercial
All submissions that have no materials
.col-md-12
%table.datatable
%thead

View file

@ -4,7 +4,7 @@
= link_to 'All Events', '#all', 'data-toggle' => 'tab'
%li
%a{href: '#missing-commercial', 'data-toggle' => 'tab'}
Events without Commercials
Events without Materials
%span.label.label-danger{style: 'border-radius: 1em;'}
= @events_missing_commercial.length
%li

View file

@ -14,5 +14,6 @@
= f.input :price
= f.input :price_currency, as: :select, class: 'form-control', collection: ['USD', 'EUR', 'GBP', 'INR', 'CNY', 'CHF'], include_blank: false
= f.input :registration_ticket, hint: 'A registration ticket is with which user register for the conference.'
= f.input :visible, hint: 'Only visible tickets are available to registrants. Non-visible tickets can only be managed by Admins.'
%p.text-right
= f.action :submit, as: :button, button_html: { class: 'btn btn-primary' }

View file

@ -15,6 +15,7 @@
%th Sold
%th Turnover
%th Registration Ticket
%th Visible?
%th Actions
%tbody
- @conference.tickets.each do |ticket|
@ -30,6 +31,8 @@
= humanized_money_with_symbol ticket.tickets_turnover_total(ticket.id)
%td
= ticket.registration_ticket? ? 'Yes' : 'No'
%td
= ticket.visible? ? 'Yes' : 'No'
%td
.btn-group
= link_to 'Edit', edit_admin_conference_ticket_path(@conference.short_title, ticket.id),

View file

@ -7,7 +7,13 @@
Ticket
%small
= humanized_money_with_symbol @ticket.price
= link_to 'Edit Ticket', edit_admin_conference_ticket_path, class: 'btn btn-primary pull-right'
= link_to 'Edit Ticket', edit_admin_conference_ticket_path, class: 'btn btn-primary pull-right'
- if can? :give, Ticket
.pull-right
= link_to 'Give a Ticket', '#',
data: { toggle: 'modal', target: "#modal-give-ticket-#{@ticket.id}" },
class: 'button btn btn-default btn-info'
%p.text-muted
People who bought this ticket
.row
@ -35,3 +41,26 @@
= buyer.affiliation
%td
= @ticket.tickets_paid(buyer)
- content_for :modals do
.modal.fade{ id: "modal-give-ticket-#{@ticket.id}" }
.modal-dialog
.modal-content
= semantic_form_for(@ticket.ticket_purchases.new,
url: give_admin_conference_ticket_path(@conference, @ticket)) do |f|
.modal-header
%button.close{ data: { dismiss: 'modal' } }
%i.fa.fa-close
%h3.modal-title
Give a
= @ticket.title
Ticket
.modal-body
= user_selector_input(:user, f, '', false)
.modal-footer
= f.action :submit, as: :button, button_html: { class: 'btn btn-primary' }
:javascript
$(document).ready(function() {
$('#ticket_purchase_user_id').selectize({})
});

View file

@ -7,7 +7,7 @@
%li.active
= link_to 'Details', '#details-content', 'data-toggle' => 'tab'
%li
= link_to 'Commercials', '#commercials-content', 'data-toggle' => 'tab'
= link_to 'Materials', '#commercials-content', 'data-toggle' => 'tab'
.tab-content
#details-content.tab-pane.active
@ -56,4 +56,4 @@
%hr
- else
First Create Venue, then update commercial
First Create Venue, then update materials

View file

@ -12,7 +12,7 @@
-else
- if @venue.commercial.nil?
.row
%img{ "data-src" => "holder.js/500x300?text=No Commercial Set", class: 'img-responsive img-rounded' }
%img{ "data-src" => "holder.js/500x300?text=No Materials Set", class: 'img-responsive img-rounded' }
- else
- if @venue.commercial.persisted?
.thumbnail

View file

@ -2,7 +2,7 @@
.row
.col-md-12
.page-header
%h1 Editing Commercial
%h1 Edit Materials
.row
.col-md-12
= semantic_form_for @commercial, url: conference_program_proposal_commercial_path(conference_id: @conference.short_title, proposal_id: @event.id, id: @commercial.id) do |f|

View file

@ -2,7 +2,7 @@
.row
.col-md-12
.page-header
%h1 New Commercial
%h1 New Materials
.row
.col-md-12
= semantic_form_for @commercial, url: conference_program_proposal_commercials_path(conference_id: @conference.short_title, proposal_id: @event.id) do |f|

View file

@ -22,6 +22,7 @@
= render partial: 'devise/shared/sign_up_form_embedded'
= render partial: 'registration_info', locals: { f: f }
= f.input :conference_id, as: :hidden, value: @conference.id
.row
.col-md-12
%p.pull-right

View file

@ -24,10 +24,4 @@
(Scheduled on: #{event.time.to_date})
%br
= f.inputs 'Your Travel Info' do
= f.input :arrival, as: :string, label: 'Your arrival time', hint: "Leave blank if not sure", input_html: { value: (f.object.arrival.to_formatted_s(:db_without_seconds) unless f.object.arrival.nil?), id: 'registration-arrival-datepicker',start_date: @conference.start_date,end_date: @conference.end_date }
= f.input :departure, as: :string, label: 'Your departure time', hint: "Leave blank if not sure", input_html: { value: (f.object.departure.to_formatted_s(:db_without_seconds) unless f.object.departure.nil?), id: 'registration-departure-datepicker' }
= render 'conferences/code_of_conduct', organization: @conference.organization

View file

@ -33,28 +33,6 @@
data: { toggle: 'modal', target: '#modal-code-of-conduct'}
= render 'conferences/code_of_conduct',
organization: @conference.organization
.row
.col-md-12
%h4
%span.fa-stack
%i.fa.fa-square-o.fa-stack-2x
%i.fa.fa-plane.fa-stack-1x
Travel Schedule
%ul
%li
- if @registration.arrival.present?
arrive at
%strong
= @registration.arrival.strftime('%A, %B %-d. %Y %H:%M')
- else
You haven't scheduled your arrival
%li
- if @registration.departure.present?
depart at
%strong
= @registration.departure.strftime('%A, %B %-d. %Y %H:%M')
- else
You haven't scheduled your departure
- if @conference.surveys.for_registration.any?
.row
.col-md-12
@ -94,7 +72,7 @@
= link_to event.title, conference_program_proposal_path(@conference.short_title, event.id)
= '(' + registered_text(event) + ')'
- if @conference.tickets.any?
- if @conference.tickets.visible.any?
.row
.col-md-12
%h4

View file

@ -1,6 +1,6 @@
= content_for :splash_nav do
%li
%a.smoothscroll{ href: '#call' } Call For Content
%a.smoothscroll{ href: '#call' } Call For Participation
%section#call
.container
@ -20,3 +20,4 @@
call: call_for_booths
- if two_calls_open(call_for_events, call_for_tracks, call_for_booths)
.col-md-2.col-sm-2.hidden-xs &nbsp;
.trapezoid

View file

@ -2,7 +2,7 @@
expires_in: 1.hour) do
.col-md-4.col-sm-4.text-center
%h2
Call for Papers
Call for Participation
%p.lead
We are now accepting proposals for sessions!
%p

View file

@ -6,7 +6,7 @@
= image_tag(conference.picture_url, class: 'img-responsive') if conference.picture?
.col-md-6
%h3
= conference.title
= conference.title.html_safe
%small
%b
= date_string(conference.start_date, conference.end_date)

View file

@ -1,14 +1,14 @@
.scroll-top-wrapper
= link_to "#banner", class: "smoothscroll" do
%i.fa.fa-2x.fa-arrow-circle-up
-# .scroll-top-wrapper
-# = link_to "#banner", class: "smoothscroll" do
-# %i.fa.fa-2x.fa-arrow-circle-up
:javascript
$(function(){
$(document).on( 'scroll', function(){
if ($(window).scrollTop() > 100) {
$('.scroll-top-wrapper').addClass('show');
} else {
$('.scroll-top-wrapper').removeClass('show');
}
});
});
-# :javascript
-# $(function(){
-# $(document).on( 'scroll', function(){
-# if ($(window).scrollTop() > 100) {
-# $('.scroll-top-wrapper').addClass('show');
-# } else {
-# $('.scroll-top-wrapper').removeClass('show');
-# }
-# });
-# });

View file

@ -1,28 +1,28 @@
- cache [conference, venue, '#splash#header'] do
#banner
#banner{ style: ("background-image: url(#{conference.picture_url})" if conference.picture_url) }
.container
.row
.col-md-8.col-md-offset-2#header
.col-md-6.col-md-offset-3{id: (conference.picture? ? "header-image" : "header-no-image")}
.row
.col-md-4
- if conference.picture?
= image_tag(conference.picture_url,
class: 'img-responsive img-center',
id: 'splash-logo')
-# - if conference.picture?
-# .col-md-4
-# = image_tag(conference.picture_url,
-# class: 'img-responsive img-center',
-# id: 'splash-logo')
.col-md-8
%h1
= conference.title
= conference.title.html_safe
%h3
- if conference.start_date && conference.end_date
%span.date.text-nowrap
= date_string(conference.start_date, conference.end_date)
- if conference.venue
%span.venue.text-nowrap
- if venue.website
- if venue.website.present?
= sanitize link_to(venue.name, venue.website)
- else
= venue.city
- if venue.country_name != 'US'
- if venue.country != 'US'
&bull;
= venue.country_name
@ -32,3 +32,4 @@
.row
.col-md-8.col-md-offset-2
= markdown(conference.description)
.trapezoid

View file

@ -17,11 +17,11 @@
.row.row-centered
- lodgings.each do |lodging|
.col-md-4.col-sm-4.col-centered.col-top
.col-md-6.col-sm-4.col-centered.col-top
.thumbnail
- if lodging.picture?
- if lodging.website_link.present?
= link_to(lodging.website_link, class: 'thumbnail') do
= link_to(lodging.website_link) do
= image_tag lodging.picture.large.url,
class: 'img-responsive img-lodging'
- else
@ -30,12 +30,16 @@
- else
%p.text-center
- if lodging.website_link.present?
= link_to(lodging.website_link, class: 'thumbnail') do
= link_to(lodging.website_link) do
%i.fa.fa-home.fa-5x
- else
%i.fa.fa-home.fa-5x
.caption
%h3.text-center
= lodging.name
- if lodging.website_link.present?
= link_to(lodging.name, lodging.website_link)
- else
= lodging.name
- if lodging.description.present?
= markdown(lodging.description)
.trapezoid

View file

@ -9,8 +9,8 @@
.col-md-12
%p.lead.text-center
%span.notranslate
= conference.title
has the most awesome program ever!
= conference.title.html_safe
will have an enaging program!
- unless highlights.blank?
= render 'highlights', conference_id: conference.short_title,
@ -31,6 +31,7 @@
= link_to(conference_schedule_path(conference.short_title),
class: 'btn btn-success btn-lg') do
Full Schedule
.trapezoid
- unless booths.blank?
- booths.each do |booth|

View file

@ -37,3 +37,4 @@
= link_to('Register Now',
new_conference_conference_registration_path(conference_id),
class: 'btn btn-lg btn-success')
.trapezoid

View file

@ -27,3 +27,4 @@
- if contact.email?
= mail_to "#{ contact.email }" do
%i.fa.fa-envelope-o.fa-4x
.trapezoid

View file

@ -27,9 +27,10 @@
.row
.col-md-12
%h3.text-center
Want to sponsor?
= "Interested in sponsoring #{conference.title}?"
= link_to(sponsorship_mailto(conference)) do
Contact us!
Please, contact us!
.trapezoid
- sponsors.each do |sponsor|
- content_for :modals do

View file

@ -7,19 +7,21 @@
.container
.row
.col-md-12.text-center
%h2
Support
= conference.title
%h2 Sign Up for Snap<em>!</em>Con
%br
-# %h2
-# Support
-# = conference.title
.row.row-centered
- tickets.each do |ticket|
.col-md-3.col-sm-3.col-centered.col-top
= link_to(conference_tickets_path(conference.short_title),
class: 'thumbnail') do
.col-lg-4.col-md-3.col-sm-3.col-centered.col-top
= link_to(conference_tickets_path(conference.short_title), class: 'thumbnail') do
.caption
%h3.text-center.word_break
= ticket.title
.word_break
= markdown(ticket.description)
%button.btn-block.btn.btn-lg.btn-success
%i.fa.fa-ticket.fa-fw
%i.fa.fa-ticket.fa-fw{"aria-hidden": true}
= humanized_money_with_symbol(ticket.price)
.trapezoid

View file

@ -5,6 +5,12 @@
%section#venue
- if venue.location?
= render '/conferences/venue_map', venue: venue
- if venue.description.present?
.container
.row
.col-md-8.col-md-offset-2
= markdown(venue.description, escape_html=false)
.trapezoid
- else
- cache [venue, commercial, '#splash#venue'] do
.container
@ -41,3 +47,4 @@
- if venue.website
%br
= sanitize link_to(h(venue.website), h(venue.website))
.trapezoid

View file

@ -1,10 +1,10 @@
- content_for :head do
%meta{ property: "og:title", content: @conference.title }
%meta{ property: "og:site_name", content: (ENV['OSEM_NAME'] || 'OSEM') }
%meta{ property: "og:description", content: @conference.description }
%meta{ property: "og:description", content: plain_text(@conference.description) }
%meta{ property: "og:url", content: conference_url(@conference.short_title) }
%meta{ property: "twitter:title", content: (@conference.title) }
%meta{ property: "twitter:description", content: @conference.description }
%meta{ property: "twitter:description", content: plain_text(@conference.description) }
- if @conference.picture?
%meta{ property: "og:image", content: @image_url }
%meta{ property: "og:image:secure_url", content: @image_url }
@ -64,21 +64,22 @@
= render 'social_media', contact: @conference.contact
= render 'footer'
- content_for :script_head do
:javascript
var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic();
var triangle_colors = triangle_tcs.map(function(t) {
return t.toHexString();
});
$(function () {
$(document).ready(function() {
var triangle_width = document.body.clientWidth;
var triangle_height = ($( "#banner" ).height() + 200 );
var pattern = Trianglify({ width: triangle_width,
height: triangle_height,
cell_size: 100,
x_colors: triangle_colors
});
$('#banner').css('background-image', 'url("' + pattern.png() + '")');
});
});
-# - content_for :script_head do
-# :javascript
-# var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic();
-# var triangle_colors = triangle_tcs.map(function(t) {
-# return t.toHexString();
-# });
-# $(function () {
-# $(document).ready(function() {
-# var triangle_width = document.body.clientWidth;
-# var triangle_height = ($( "#banner" ).height() + 200 );
-# var pattern = Trianglify({ width: triangle_width,
-# height: triangle_height,
-# cell_size: 100,
-# x_colors: triangle_colors
-# });
-# $('#banner').css('background-image', 'url(' + 0 + ')');
-# });
-# });

View file

@ -1,7 +1,16 @@
.text-center
.btn-group.btn-group-lg#openid-btn-grp
- omniauth_configured.each do |provider|
= link_to "user_#{provider}_omniauth_authorize".to_sym, class: "btn btn-success btn-lg",
id: "omniauth-#{provider}",
title: "Your #{provider} login" do
%i{class: "fa fa-#{provider}"}
- if provider != :discourse
= link_to "user_#{provider}_omniauth_authorize".to_sym, class: "btn btn-success btn-lg",
id: "omniauth-#{provider}",
title: "Your #{provider} login" do
%i{class: "fa fa-#{provider}"}
- else
= link_to("user_#{provider}_omniauth_authorize".to_sym,
class: "btn btn-success btn-lg",
id: "omniauth-#{provider}",
title: "Your #{provider} login") do
%span
Snap
%em> !

View file

@ -1,25 +1,26 @@
- if ENV['OSEM_ICHAIN_ENABLED'] != 'true'
= form_tag(new_user_session_path, class: 'form-horizontal') do
%legend
%span
Sign In
.form-group
%label{for: "user[login]", class: 'col-sm-2 control-label'}
Username
.col-sm-10
= text_field_tag 'user[login]', nil, placeholder: 'Username', class: 'form-control', required: 'required'
.form-group
%label{for: "user[password]", class: 'col-sm-2 control-label'}
Password
.col-sm-10
= password_field_tag 'user[password]', nil, placeholder: 'Password', class: 'form-control', required: 'required'
.form-group
.col-sm-12
%button.btn.btn-success.pull-right
Sign in
= render partial: 'devise/shared/openid'
%p.text-right
%a.small.btn.btn-default{"data-toggle" => "collapse", "data-target" => "#devise-help-sign-in"}
Need Help?
#devise-help-sign-in.collapse
= render partial: 'devise/shared/links'
.container.panel
= form_tag(new_user_session_path, class: '') do
%legend
%span
Sign In
.form-group
%label{for: "user[login]", class: 'col-sm-2 control-label'}
Username
.col-sm-10
= text_field_tag 'user[login]', nil, placeholder: 'Username', class: 'form-control', required: 'required'
.form-group
%label{for: "user[password]", class: 'col-sm-2 control-label'}
Password
.col-sm-10
= password_field_tag 'user[password]', nil, placeholder: 'Password', class: 'form-control', required: 'required'
.form-group
.col-sm-12
%button.btn.btn-success.pull-right
Sign in
= render partial: 'devise/shared/openid'
%p.text-right
%a.small.btn.btn-default{"data-toggle" => "collapse", "data-target" => "#devise-help-sign-in"}
Need Help?
#devise-help-sign-in.collapse
= render partial: 'devise/shared/links'

View file

@ -43,7 +43,7 @@
= link_to 'Contact', edit_admin_conference_contact_path(@conference.short_title)
- if can? :index, @conference.commercials.build
%li{class: "#{active_nav_li(admin_conference_commercials_path(@conference.short_title))}"}
= link_to 'Commercials', admin_conference_commercials_path(@conference.short_title)
= link_to 'Materials', admin_conference_commercials_path(@conference.short_title)
- if can? :update, @conference
%li{class: active_nav_li(edit_admin_conference_splashpage_path(@conference.short_title))}
= link_to 'Splashpage', admin_conference_splashpage_path(@conference.short_title)

View file

@ -1,7 +1,6 @@
.navbar.navbar-default.navbar-fixed-top.nav-osem{role: 'navigation'}
%nav.navbar.navbar-default.navbar-fixed-top.nav-osem{role: 'navigation'}
.container
.navbar-header
- if controller.class.name.split("::").first=="Admin"
%button{ "data-target"=>"#side-nav", "data-toggle"=>"collapse", class: 'navbar-toggle side-nav-btn', type: 'button' }
%span.sr-only Toggle navigation
@ -14,7 +13,7 @@
%span.icon-bar
%span.icon-bar
%span.icon-bar
= nav_root_link_for conference
= nav_root_link_for(conference)
.collapse.navbar-collapse#main-nav
- if content_for :splash_nav
@ -42,34 +41,41 @@
= link_to(new_registration_path('user')) do
%span.fa.fa-heart
Sign Up
%li.dropdown.visible-desktop
%a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'}
%span.fa.fa-user
Sign In
%span.caret
.dropdown-menu
- if ENV['OSEM_ICHAIN_ENABLED'] == 'true'
= form_tag User.ichain_login_url do
= text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username'
= password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password'
%button.btn.btn-success.btn-block Sign in
- else
= form_tag new_user_session_path do
= text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail'
= password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password'
%p.text-right
%small
%label{for: 'user_remember_me'} Remember me
= check_box_tag 'user[remember_me]'
%button.btn.btn-success.btn-block Sign in
- unless omniauth_configured.empty?
.divider
%h6.text-center
or
= render 'devise/shared/openid_links'
%p.text-right
%br
%a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"}
Need Help?
#navbar-devise-help.collapse
= render 'devise/shared/links'
%li{class: ""}
= link_to(sign_in_path) do
%span.fa.fa-user
Sign In
-# %li.dropdown.visible-desktop
-# %a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'}
-# %span.fa.fa-user
-# Sign In
-# %span.caret
-# .dropdown-menu
-# - if ENV['OSEM_ICHAIN_ENABLED'] == 'true'
-# = form_tag User.ichain_login_url do
-# = text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username'
-# = password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password'
-# %button.btn.btn-success.btn-block Sign in
-# - else
-# %div{style: "padding: 6px"}
-# = form_tag new_user_session_path, class: 'form-group' do
-# = text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail'
-# = password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password'
-# %p.text-right
-# %small
-# %label{for: 'user_remember_me'} Remember me
-# = check_box_tag 'user[remember_me]'
-# %br
-# %button.btn.btn-success.btn-block Sign in
-# - unless omniauth_configured.empty?
-# .divider
-# %h6.text-center
-# or
-# = render 'devise/shared/openid_links'
-# %p.text-right
-# %br
-# %a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"}
-# Need Help?
-# #navbar-devise-help.collapse
-# = render 'devise/shared/links'
.trapezoid

View file

@ -1,10 +1,10 @@
%html{xmlns: 'http://www.w3.org/1999/html'}
%html{lang: 'en'}
%head
%meta{charset: 'utf-8'}
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1, maximum-scale=1'}
%title= content_for?(:title) ? yield(:title) : (ENV['OSEM_NAME'] || 'OSEM')
%meta{content: '', name: 'description'}
%meta{content: '', name: 'author'}
%meta{name: 'viewport', content: 'width=device-width, initial-scale=1'}
%title= content_for?(:title) ? strip_tags( yield(:title) ) : (ENV['OSEM_NAME'] || 'OSEM')
%meta{content: 'Snap!Con -- A conference all about Snap!, a programing language from UC Berkeley.', name: 'description'}
%meta{content: 'Michael Ball, Brian Harvey, Jens Moenig, Bernat Romagosa, Dan Garcia, Lauren Mock', name: 'author'}
= stylesheet_link_tag "application", media: 'all'
= javascript_include_tag "application"
@ -26,7 +26,7 @@
-# Admin area
- if controller.class.name.split("::").first=="Admin"
= render 'layouts/admin'
-else
- else
#messages
.container
= render 'layouts/messages'
@ -45,7 +45,7 @@
#{link_to "MIT license", "http://opensource.org/licenses/MIT"}.
You can run, copy, distribute, study, change and improve it.
The source code and the developers are on
#{link_to "GitHub", "https://github.com/openSUSE/osem"}.
#{link_to "GitHub", "https://github.com/snap-cloud/snapcon"}. This site is a modification of #{link_to "OSEM", "https://github.com/openSUSE/osem"}.
- if ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"].present?
Performance data is available on
#{link_to "Skylight", ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"]}.

View file

@ -1,6 +1,6 @@
.div
.col-md-12.table-responsive
%table.table.table-hover
%table.table.table-hover.table-striped
%thead
%tr
%th Ticket
@ -20,8 +20,13 @@
= humanized_money_with_symbol ticket.quantity * ticket.price
= form_tag conference_payments_path do
%script.stripe-button{ src: "https://checkout.stripe.com/checkout.js",
data: { amount: @total_amount_to_pay.cents, label: "Pay #{humanized_money_with_symbol @total_amount_to_pay}",
email: current_user.email, currency: @total_amount_to_pay.currency, name: ENV['OSEM_NAME'] || 'OSEM',
description: "book your tickets", key: Rails.application.secrets.stripe_publishable_key, locale: "auto"}}
= link_to 'Edit Purchase', conference_tickets_path(@conference.short_title), class: 'btn btn-default'
%script.stripe-button{'src': "https://checkout.stripe.com/checkout.js",
'data': {amount: @total_amount_to_pay.cents,
label: "Pay #{humanized_money_with_symbol @total_amount_to_pay}",
email: current_user.email,
currency: @total_amount_to_pay.currency,
name: ENV['OSEM_NAME'] || 'OSEM',
description: "#{ENV['OSEM_NAME']} tickets",
key: ENV['STRIPE_PUBLISHABLE_KEY'] || Rails.application.secrets.stripe_publishable_key, locale: "auto"}}
= link_to('Edit Purchase', conference_tickets_path(@conference.short_title),
class: 'btn btn-default')

View file

@ -16,6 +16,7 @@
%th ID
%th Type
%th User
%th Registration?
%th Actions
%tbody
- @physical_tickets.each do |physical_ticket|
@ -23,6 +24,7 @@
%td= physical_ticket.id
%td= physical_ticket.ticket.title
%td= physical_ticket.user.name
%td= physical_ticket.ticket.registration_ticket? ? 'Yes' : 'No'
%td
.btn-group
= link_to 'Show',

View file

@ -3,15 +3,15 @@
%li.active
= link_to 'Proposal', '#proposal-content', 'data-toggle' => 'tab'
%li
= link_to 'Commercials', '#commercials-content', 'data-toggle' => 'tab'
= link_to 'Materials', '#commercials-content', 'data-toggle' => 'tab'
.tab-content
#proposal-content.tab-pane.active
= render 'proposals/proposal_form'
#commercials-content.tab-pane
%p.text-muted
You can add commercials for your proposal. These commercials will be displayed on the
You can add materals for your proposal. These materials will be displayed on the
= link_to 'public proposal page.', conference_program_proposal_path(@conference.short_title, @event)
If you don't add a commercial, the conference commercial will be displayed!
If you don't add any materials, the conference materials will be displayed.
- if can? :create, @event.commercials.new
.row
.col-md-6

View file

@ -20,7 +20,7 @@
= link_to 'Add a subtitle', edit_conference_program_proposal_path(event.program.conference.short_title, event)
%li{'class'=>class_for_todo(progress_status['commercials'])}
%span{'class'=>icon_for_todo(progress_status['commercials'])}
= link_to 'Add a commercial', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content')
= link_to 'Add materials', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content')
- unless progress_status['track'].nil?
%li{'class'=>class_for_todo(progress_status['track'])}
%span{'class'=>icon_for_todo(progress_status['track'])}

View file

@ -7,7 +7,7 @@
- if @program.cfp.description.present?
.row
.col-md-12
= markdown(@program.cfp.description)
= markdown(@program.cfp.description, escape_html=false)
.row
.col-md-12
= render partial: 'encouragement_text'
@ -43,10 +43,10 @@
- @program.event_types.each do |event_type|
%span{ class: 'help-block event_event_type_id collapse', id: "#{event_type.id}-help" }
= event_type.description
= markdown(event_type.description)
= f.input :abstract, required: true, input_html: { rows: 5, data: { provide: 'markdown-editable' } },
hint: markdown_hint('[Tips to improve your presentations.](http://blog.hubspot.com/blog/tabid/6307/bid/5975/10-Rules-to-Instantly-Improve-Your-Presentations.aspx)')
hint: markdown_hint
%p
You have used

View file

@ -3,9 +3,9 @@
.media
.media-body
%h4.media-heading= ticket.title
%h5.media-heading= markdown(ticket.description)
- if @conference.tickets.for_registration.any?
%td.col-sm-1.col-md-2.text-center
.media-heading= markdown(ticket.description)
%td.col-sm-1.col-md-2
%span.text-center
= ticket.registration_ticket? ? 'Yes' : 'No'
%td.col-sm-1.col-md-1
:ruby

View file

@ -13,18 +13,16 @@
%thead
%tr
%th Ticket
- if @conference.tickets.for_registration.any?
%th Registration Ticket
%th Registration?
%th Quantity
%th Price
%th Total
%tbody
- @conference.tickets.each do |ticket|
- @conference.tickets.visible.each do |ticket|
= render 'ticket', f: f, ticket: ticket
%tr
%td
- if @conference.tickets.for_registration.any?
%td
%td
%td
%td.col-sm-1.col-md-1.text-center
%h4

View file

@ -1,4 +1,5 @@
#!/bin/bash
bundle install
# Setup the app if it isn't already setup
bundle exec rake db:bootstrap
# Start the app

View file

@ -1,22 +0,0 @@
Airbrake.configure do |config|
# Change this to some sensible data for your errbit instance
config.project_id = ENV['OSEM_ERRBIT_ID'] || Rails.application.secrets.errbit_id || ''
config.project_key = ENV['OSEM_ERRBIT_KEY'] || Rails.application.secrets.errbit_key || ''
config.host = ENV['OSEM_ERRBIT_HOST']
config.environment = Rails.env
if config.project_key.blank? || config.host.blank?
config.ignore_environments = [:production, :development, :test]
else
config.ignore_environments = [:development, :test]
end
end
Airbrake.add_filter do |notice|
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActiveRecord::RecordNotFound' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActionController::InvalidAuthenticityToken' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActionController::UnknownAction' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'AbstractController::ActionNotFound' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActionView::MissingTemplate' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActionController::UnknownFormat' }
notice.ignore! if notice[:errors].any? { |error| error[:type] == 'ActionController::RoutingError' && error[:message] =~ %r{\[GET\]} }
end

View file

@ -6,12 +6,25 @@ Devise.setup do |config|
# Define the available openID providers that can be used to log in
# Pass each provider to User model in :omniauth_providers (for open_id providers use their name)
config.omniauth :open_id, name: 'suse', identifier: 'http://www.opensuse.org/openid/user'
config.omniauth :google_oauth2, (ENV['OSEM_GOOGLE_KEY'] || Rails.application.secrets.google_key), (ENV['OSEM_GOOGLE_SECRET'] || Rails.application.secrets.google_secret),
# config.omniauth :open_id, name: 'suse', identifier: 'http://www.opensuse.org/openid/user'
config.omniauth :google_oauth2,
(ENV['OSEM_GOOGLE_KEY'] || Rails.application.secrets.google_key),
(ENV['OSEM_GOOGLE_SECRET'] || Rails.application.secrets.google_secret),
name: 'google',
scope: 'email'
config.omniauth :facebook, (ENV['OSEM_FACEBOOK_KEY'] || Rails.application.secrets.facebook_key), (ENV['OSEM_FACEBOOK_SECRET'] || Rails.application.secrets.facebook_secret)
config.omniauth :github, (ENV['OSEM_GITHUB_KEY'] || Rails.application.secrets.github_key), (ENV['OSEM_GITHUB_SECRET'] || Rails.application.secrets.github_secret)
config.omniauth :discourse,
sso_url: 'https://forum.snap.berkeley.edu/session/sso_provider',
sso_secret: ENV['OSEM_DISCOURSE_SECRET']
config.omniauth :facebook,
(ENV['OSEM_FACEBOOK_KEY'] || Rails.application.secrets.facebook_key),
(ENV['OSEM_FACEBOOK_SECRET'] || Rails.application.secrets.facebook_secret)
config.omniauth :github,
(ENV['OSEM_GITHUB_KEY'] || Rails.application.secrets.github_key),
(ENV['OSEM_GITHUB_SECRET'] || Rails.application.secrets.github_secret)
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,

View file

@ -0,0 +1,4 @@
Raven.configure do |config|
config.dsn = ENV['SENTRY_DSN']
config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
end

View file

@ -1 +1 @@
Stripe.api_key = Rails.application.secrets.stripe_secret_key
Stripe.api_key = ENV['STRIPE_SECRET_KEY'] || Rails.application.secrets.stripe_secret_key

View file

@ -43,5 +43,16 @@ on_worker_boot do
ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end
lowlevel_error_handler do |ex, env|
Raven.capture_exception(
ex,
:message => ex.message,
:extra => { :puma => env },
:transaction => "Puma"
)
# note the below is just a Rack response
[500, {}, ["An error has occurred, and engineers have been informed. Please reload the page. If you continue to have problems, contact conference@snap.berkeley.edu\n"]]
end
# Allow puma to be restarted by `rails restart` command.
plugin :tmp_restart

View file

@ -115,7 +115,11 @@ Osem::Application.routes.draw do
end
resources :resources
resources :tickets
resources :tickets do
member do
post :give
end
end
resources :sponsors, except: [:show]
resources :lodgings, except: [:show]
resources :emails, only: [:show, :update, :index]

View file

@ -0,0 +1,11 @@
class AddVisibleToTickets < ActiveRecord::Migration[5.0]
def up
add_column :tickets, :visible, :boolean, default: true
Ticket.reset_column_information
Ticket.update_all(visible: true) # rubocop:disable Rails/SkipsModelValidations
end
def down
remove_column :tickets, :visible
end
end

View file

@ -0,0 +1,6 @@
class RemoveArrivalDepartureFromRegistrations < ActiveRecord::Migration[5.0]
def change
remove_column :registrations, :arrival, :datetime
remove_column :registrations, :departure, :datetime
end
end

View file

@ -10,7 +10,10 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20181113195810) do
ActiveRecord::Schema.define(version: 2018_12_29_233811) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "answers", force: :cascade do |t|
t.string "title"
@ -364,8 +367,6 @@ ActiveRecord::Schema.define(version: 20181113195810) do
create_table "registrations", force: :cascade do |t|
t.integer "conference_id"
t.datetime "arrival"
t.datetime "departure"
t.datetime "created_at"
t.datetime "updated_at"
t.text "other_special_needs"
@ -530,6 +531,7 @@ ActiveRecord::Schema.define(version: 20181113195810) do
t.boolean "registration_ticket", default: false
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "visible", default: true
end
create_table "tracks", force: :cascade do |t|

View file

@ -1,5 +1,6 @@
# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
#
# To ban all spiders from the entire site uncomment the next two lines:
# User-Agent: *
# Disallow: /
User-Agent: *
Allow: /
Disallow: /admin

View file

@ -0,0 +1,257 @@
# frozen_string_literal: true
require 'spec_helper'
describe Admin::TicketsController do
let(:admin) { create(:admin) }
let(:conference) { create(:conference) }
let!(:ticket) { create(:ticket, conference: conference) }
let(:new_title) { Faker::Hipster.sentence }
context 'admin is signed in' do
before { sign_in admin }
describe 'GET #index' do
before { get :index, params: { conference_id: conference } }
it 'assigns conference and tickets variables via cancancan' do
expect(assigns(:conference)).to eq conference
expect(assigns(:tickets)).to eq conference.tickets
end
it 'renders index template' do
expect(response).to render_template('index')
end
end
describe 'GET #edit' do
before { get :edit, params: { conference_id: conference, id: ticket } }
it 'assigns ticket variable via cancancan' do
expect(assigns(:ticket)).to eq ticket
end
it 'renders edit template' do
expect(response).to render_template('edit')
end
end
describe 'GET #new' do
before { get :new, params: { conference_id: conference } }
it 'assigns ticket variable' do
expect(assigns(:ticket)).to be_instance_of(Ticket)
end
it 'renders new template' do
expect(response).to render_template('new')
end
end
describe 'POST #create' do
context 'saves successfuly' do
before(:each, run: true) do
post :create, params: { conference_id: conference, ticket: attributes_for(:ticket) }
end
let!(:ticket_count) { conference.tickets.count }
it 'redirects to index path', run: true do
expect(response).to redirect_to(
admin_conference_tickets_path(conference_id: conference)
)
end
it 'shows success message in flash notice', run: true do
expect(flash[:notice]).to match('Ticket successfully created.')
end
it 'creates new ticket' do
expect do
post :create, params: {
ticket: attributes_for(:ticket),
conference_id: conference
}
end.to change{ conference.tickets.count }.from(ticket_count).to(ticket_count + 1)
end
end
context 'save fails' do
before do
allow_any_instance_of(Ticket).to receive(:save).and_return(false)
post :create, params: { conference_id: conference, ticket: attributes_for(:ticket) }
end
let!(:ticket_count) { conference.tickets.count }
it 'renders new template' do
expect(response).to render_template('new')
end
it 'shows error in flash message' do
expect(flash[:error]).to match("Creating Ticket failed: #{ticket.errors.full_messages.join('. ')}.")
end
it 'does not create new ticket' do
expect(conference.tickets.count).to eq ticket_count
end
end
end
describe 'PATCH #update' do
context 'updates successfully' do
before do
patch :update, params: {
conference_id: conference, id: ticket,
ticket: attributes_for(:ticket, title: new_title)
}
end
it 'redirects to index path' do
expect(response).to redirect_to(
admin_conference_tickets_path(conference_id: conference)
)
end
it 'shows success message in flash notice' do
expect(flash[:notice]).to match('Ticket successfully updated.')
end
it 'updates the ticket' do
ticket.reload
expect(ticket.title).to eq(new_title)
end
end
context 'update fails' do
before do
allow_any_instance_of(Ticket).to receive(:save).and_return(false)
patch :update, params: {
conference_id: conference, id: ticket,
ticket: attributes_for(:ticket, title: new_title)
}
end
it 'renders edit template' do
expect(response).to render_template('edit')
end
it 'shows error in flash message' do
expect(flash[:error]).to match("Ticket update failed: #{ticket.errors.full_messages.join('. ')}.")
end
it 'does not update ticket' do
ticket.reload
expect(ticket.title).not_to eq(new_title)
end
end
end
describe 'DELETE #destroy' do
context 'deletes successfully' do
before(:each, run: true) do
delete :destroy, params: { conference_id: conference, id: ticket }
end
let!(:ticket_count) { conference.tickets.count }
it 'redirects to index path', run: true do
expect(response).to redirect_to(
admin_conference_tickets_path(conference_id: conference)
)
end
it 'shows success message in flash notice', run: true do
expect(flash[:notice]).to match('Ticket successfully deleted.')
end
it 'deletes the ticket' do
expect do
delete :destroy, params: { conference_id: conference, id: ticket }
end.to change{ conference.tickets.count }.from(ticket_count).to(ticket_count - 1)
end
end
context 'delete fails' do
let!(:ticket_count) { conference.tickets.count }
before do
allow_any_instance_of(Ticket).to receive(:destroy).and_return(false)
delete :destroy, params: { conference_id: conference, id: ticket }
end
it 'redirects to index path' do
expect(response).to redirect_to(
admin_conference_tickets_path(conference_id: conference)
)
end
it 'shows error in flash message' do
expect(flash[:error]).to match("Deleting ticket failed! #{ticket.errors.full_messages.join('. ')}.")
end
it 'does not delete ticket' do
expect(conference.tickets.count).to eq(ticket_count)
end
end
end
describe 'POST #give' do
context 'grants a ticket purchase to a user' do
let!(:purchase_count) { admin.ticket_purchases.count }
before do
post :give, params: {
conference_id: conference, id: ticket,
ticket_purchase: { user_id: admin.id }
}
end
it 'redirects to ticket' do
expect(response).to redirect_to(
admin_conference_ticket_path(conference_id: conference, id: ticket)
)
end
it 'shows success message in flash notice' do
expect(flash[:notice]).to match(
"#{admin.name} was given a #{ticket.title} ticket."
)
end
it 'creates a ticket purchase' do
expect(admin.ticket_purchases.count).to eq(purchase_count + 1)
expect(admin.ticket_purchases.last.ticket).to eq(ticket)
end
end
context 'giving fails' do
before do
allow_any_instance_of(TicketPurchase).to receive(:save).and_return(false)
post :give, params: {
conference_id: conference, id: ticket,
ticket_purchase: { user_id: admin.id }
}
end
let(:purchase_count) { admin.ticket_purchases.count }
it 'redirects to ticket' do
expect(response).to redirect_to(
admin_conference_ticket_path(conference_id: conference, id: ticket)
)
end
it 'shows error in flash message' do
expect(flash[:error]).to match(
"Unable to give #{admin.name} a #{ticket.title} ticket: "
)
end
it 'does not create a ticket purchase' do
expect(admin.ticket_purchases.count).to eq(purchase_count)
end
end
end
end
end

View file

@ -290,14 +290,15 @@ describe ConferenceRegistrationsController, type: :controller do
before do
@registration = create(:registration,
conference: conference,
user: user,
arrival: Date.new(2014, 04, 25))
user: user)
end
context 'updates successfully' do
before do
patch :update, params: { registration: attributes_for(:registration, arrival: Date.new(2014, 04, 29)),
conference_id: conference.short_title }
patch :update, params: {
registration: attributes_for(:registration, volunteer: true),
conference_id: conference.short_title
}
end
it 'redirects to registration show path' do
@ -309,16 +310,17 @@ describe ConferenceRegistrationsController, type: :controller do
end
it 'updates the registration' do
@registration.reload
expect(@registration.arrival).to eq Date.new(2014, 04, 29)
expect{ @registration.reload }.to change(@registration, :updated_at)
end
end
context 'update fails' do
before do
allow_any_instance_of(Registration).to receive(:update_attributes).and_return(false)
patch :update, params: { registration: attributes_for(:registration, arrival: Date.new(2014, 04, 27)),
conference_id: conference.short_title }
patch :update, params: {
registration: attributes_for(:registration, volunteer: true),
conference_id: conference.short_title
}
end
it 'renders edit template' do
@ -331,7 +333,7 @@ describe ConferenceRegistrationsController, type: :controller do
it 'does not update the registration' do
@registration.reload
expect(@registration.arrival).to eq Date.new(2014, 04, 25)
expect { @registration.reload }.not_to change(@registration, :updated_at)
end
end
end

View file

@ -5,6 +5,7 @@ FactoryBot.define do
title { "#{Faker::Hipster.word} Ticket" }
price_cents { 1000 }
price_currency { 'USD' }
visible { true }
factory :registration_ticket do
registration_ticket { true }
end

View file

@ -17,9 +17,9 @@ feature Commercial do
# Create valid commercial
fill_in 'commercial_url', with: 'https://www.youtube.com/watch?v=M9bq_alk-sw'
click_button 'Create Commercial'
click_button 'Save Materials'
page.find('#flash')
expect(flash).to eq('Commercial was successfully created.')
expect(flash).to eq('Materials were successfully created.')
page.find('#flash .button.close').click
expect(conference.commercials.count).to eq(1)
@ -28,7 +28,7 @@ feature Commercial do
fill_in "commercial_url_#{commercial.id}", with: 'https://www.youtube.com/watch?v=VNkDJk5_9eU'
click_button 'Update'
page.find('#flash')
expect(flash).to eq('Commercial was successfully updated.')
expect(flash).to eq('Materials were successfully updated.')
page.find('#flash .button.close').click
expect(conference.commercials.count).to eq(1)
commercial.reload
@ -39,7 +39,7 @@ feature Commercial do
click_link 'Delete'
end
page.find('#flash')
expect(flash).to eq('Commercial was successfully destroyed.')
expect(flash).to eq('Materials were successfully destroyed.')
expect(conference.commercials.count).to eq(0)
end
end
@ -56,23 +56,23 @@ feature Commercial do
scenario 'adds a valid commercial of an event', feature: true, js: true do
visit edit_conference_program_proposal_path(conference.short_title, event.id)
click_link 'Commercials'
click_link 'Materials'
fill_in 'commercial_url', with: 'https://www.youtube.com/watch?v=M9bq_alk-sw'
# Workaround to enable the 'Create Commercial' button
# Workaround to enable the 'Save Materials' button
page.execute_script("$('#commercial_submit_action').prop('disabled', false)")
click_button 'Create Commercial'
click_button 'Save Materials'
page.find('#flash')
expect(flash).to eq('Commercial was successfully created.')
expect(flash).to eq('Materials were successfully created.')
end
scenario 'does not add an invalid commercial of an event', feature: true, js: true do
visit edit_conference_program_proposal_path(conference.short_title, event.id)
click_link 'Commercials'
click_link 'Materials'
fill_in 'commercial_url', with: 'invalid_commercial_url'
expect(page).to have_content('No embeddable content')
expect(page).to have_css("button[type='submit']:disabled", text: 'Create Commercial')
expect(page).to have_css("button[type='submit']:disabled", text: 'Save Materials')
end
scenario 'updates a commercial of an event', feature: true, js: true do
@ -80,11 +80,11 @@ feature Commercial do
commercialable_id: event.id,
commercialable_type: 'Event')
visit edit_conference_program_proposal_path(conference.short_title, event.id)
click_link 'Commercials'
click_link 'Materials'
fill_in "commercial_url_#{commercial.id}", with: 'https://www.youtube.com/watch?v=M9bq_alk-sw'
click_button 'Update'
page.find('#flash')
expect(flash).to eq('Commercial was successfully updated.')
expect(flash).to eq('Materials were successfully updated.')
TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
expect(event.commercials.count).to eq(1)
commercial.reload
@ -97,12 +97,12 @@ feature Commercial do
commercialable_type: 'Event',
url: 'https://www.youtube.com/watch?v=BTTygyxuGj8')
visit edit_conference_program_proposal_path(conference.short_title, event.id)
click_link 'Commercials'
click_link 'Materials'
fill_in "commercial_url_#{commercial.id}", with: 'invalid_commercial_url'
click_button 'Update'
find('#flash')
expect(current_path).to eq edit_conference_program_proposal_path(conference.short_title, event.id)
expect(flash).to include('An error prohibited this Commercial from being saved:')
expect(flash).to include('An error prohibited materials from being saved:')
commercial.reload
expect(commercial.url).to eq('https://www.youtube.com/watch?v=BTTygyxuGj8')
end
@ -112,12 +112,12 @@ feature Commercial do
commercialable_id: event.id,
commercialable_type: 'Event')
visit edit_conference_program_proposal_path(conference.short_title, event.id)
click_link 'Commercials'
click_link 'Materials'
page.accept_alert do
click_link 'Delete'
end
page.find('#flash')
expect(flash).to eq('Commercial was successfully destroyed.')
expect(flash).to eq('Materials were successfully destroyed.')
TransactionalCapybara::AjaxHelpers.wait_for_ajax(page)
expect(event.commercials.count).to eq(0)
end

View file

@ -98,7 +98,8 @@ feature Conference do
sign_in user
visit admin_conference_path(conference.short_title)
expect(find('.navbar-brand').text).to eq(conference.organization.name)
# expect(find('.navbar-brand')).to eq(conference.organization.name)
expect(find('.navbar-brand img')['alt']).to have_content conference.organization.name
end
it_behaves_like 'add and update conference'

View file

@ -21,7 +21,7 @@ feature 'Has correct abilities' do
expect(page).to_not have_link('Basics', href: "/admin/conferences/#{conference.short_title}/edit")
expect(page).to have_text('Basics')
expect(page).to_not have_link('Contact', href: "/admin/conferences/#{conference.short_title}/contact/edit")
expect(page).to have_link('Commercials', href: "/admin/conferences/#{conference.short_title}/commercials")
expect(page).to have_link('Materials', href: "/admin/conferences/#{conference.short_title}/commercials")
expect(page).to_not have_link('Splashpage', href: "/admin/conferences/#{conference.short_title}/splashpage")
expect(page).to_not have_link('Lodgings', href: "/admin/conferences/#{conference.short_title}/lodgings")
expect(page).to_not have_link('Registration Period', href: "/admin/conferences/#{conference.short_title}/registration_period")

View file

@ -32,7 +32,7 @@ feature 'Has correct abilities' do
expect(page).to have_selector('li.nav-header.nav-header-bigger a', text: 'Dashboard')
expect(page).to have_link('Basics', href: "/admin/conferences/#{conference.short_title}/edit")
expect(page).to have_link('Contact', href: "/admin/conferences/#{conference.short_title}/contact/edit")
expect(page).to have_link('Commercials', href: "/admin/conferences/#{conference.short_title}/commercials")
expect(page).to have_link('Materials', href: "/admin/conferences/#{conference.short_title}/commercials")
expect(page).to have_link('Splashpage', href: "/admin/conferences/#{conference.short_title}/splashpage")
expect(page).to have_link('Venue', href: "/admin/conferences/#{conference.short_title}/venue")
expect(page).to have_link('Rooms', href: "/admin/conferences/#{conference.short_title}/venue/rooms")

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