Godwin
9 years ago
82 changed files with 1671 additions and 270 deletions
@ -0,0 +1,146 @@ |
|||
|
|||
module ScheduleHelper |
|||
def get_schedule_data |
|||
schedule = Hash.new |
|||
workshop_errors = Hash.new |
|||
workshop_warnings = Hash.new |
|||
|
|||
all_events = (@workshops + @events) |
|||
conflicts = 0 |
|||
errors = 0 |
|||
|
|||
(0...all_events.count).each do |i| |
|||
w = all_events[i] |
|||
|
|||
if w.start_time.present? && w.end_time.present? && w.event_location_id.present? |
|||
type = w.is_a?(Workshop) ? :workshop : :event |
|||
|
|||
hour = w.start_time.strftime('%H').to_i |
|||
hour += 0.5 if w.start_time.strftime('%M').to_i > 15 |
|||
|
|||
end_hour = w.end_time.strftime('%H').to_i |
|||
end_hour += 0.5 if w.end_time.strftime('%M').to_i > 15 |
|||
|
|||
day = w.conference_day |
|||
|
|||
schedule[day] ||= Hash.new |
|||
schedule[day][:locations] ||= Hash.new |
|||
schedule[day][:locations][w.event_location_id] ||= Hash.new |
|||
|
|||
conflict = nil |
|||
(hour...end_hour).step(0.5).each do |h| |
|||
h = h.to_i if h == h.to_i |
|||
if !conflict && schedule[day][:locations][w.event_location_id][h].present? |
|||
conflict = schedule[day][:locations][w.event_location_id][h] |
|||
end |
|||
end |
|||
|
|||
if conflict.present? |
|||
w_conflict = get_workshop(conflict, @workshops, @events) |
|||
workshop_errors[(w_conflict.is_a?(Workshop) ? 'w' : 'e') + w_conflict.id.to_s] = "Time conflict with “<strong>#{w_conflict.title}</strong>”".html_safe |
|||
workshop_errors[(w.is_a?(Workshop) ? 'w' : 'e') + w.id.to_s] = "Time conflict with “<strong>#{w.title}</strong>”".html_safe |
|||
errors += 1 if workshop_errors[(w_conflict.is_a?(Workshop) ? 'w' : 'e') + w_conflict.id.to_s].nil? |
|||
else |
|||
schedule[day][:start_time] = hour if schedule[day][:start_time].nil? || hour < schedule[day][:start_time] |
|||
schedule[day][:end_time] = end_hour if schedule[day][:end_time].nil? || end_hour > schedule[day][:end_time] |
|||
|
|||
schedule[day][:locations][w.event_location_id][hour] = { |
|||
:span => w.duration / 60.0, |
|||
:type => w.is_a?(Event) ? w.event_type : :workshop |
|||
} |
|||
schedule[day][:locations][w.event_location_id][hour][:workshop] = i if type == :workshop |
|||
schedule[day][:locations][w.event_location_id][hour][:event] = (i - @workshops.count) if type == :event |
|||
end |
|||
else |
|||
workshop_warnings["w#{w.id}"] ||= Array.new |
|||
workshop_warnings["w#{w.id}"] << (w.is_a?(Workshop) ? "This workshop is not scheduled" : "This event is not scheduled") |
|||
end |
|||
end |
|||
|
|||
schedule.each do |day, day_data| |
|||
day_data[:locations].each do |location1, location_data1| |
|||
location_data1.each do |time1, data1| |
|||
day_data[:locations].each do |location2, location_data2| |
|||
location_data2.each do |time2, data2| |
|||
if data1[:workshop].present? |
|||
if data2[:workshop].present? |
|||
unless location1 == location2 && time1 == time2 |
|||
if workshop_errors[data1[:workshop]].nil? |
|||
w1 = @workshops[data1[:workshop]] |
|||
w2 = @workshops[data2[:workshop]] |
|||
if time1 == time2 |
|||
w1.workshop_facilitators.each do |f| |
|||
u = User.find(f.user_id) |
|||
if w2.active_facilitator?(u) |
|||
errors += 1 if workshop_errors[(w2.is_a?(Workshop) ? 'w' : 'e') + w2.id.to_s].nil? |
|||
workshop_errors["w#{w1.id}"] = "This workshop shares facilitators with “<strong>#{w2.title}</strong>”".html_safe |
|||
end |
|||
end |
|||
connection ||= ActiveRecord::Base.connection |
|||
common_interest_count = connection.select_value("SELECT COUNT(w1.user_id) FROM workshop_interests AS w1 JOIN workshop_interests AS w2 ON w2.user_id=w1.user_id WHERE w1.workshop_id=#{w1.id} AND w2.workshop_id=#{w2.id}") |
|||
common_interest_count = common_interest_count ? common_interest_count.to_i : 0 |
|||
if common_interest_count > 0 |
|||
conflicts += common_interest_count |
|||
workshop_warnings["w#{w1.id}"] ||= Array.new |
|||
workshop_warnings["w#{w1.id}"] << "<strong>#{common_interest_count}</strong> people are also interested in “<strong>#{w2.title}</strong>”".html_safe |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
|
|||
{ |
|||
:schedule => schedule.sort, |
|||
:errors => workshop_errors, |
|||
:warnings => workshop_warnings, |
|||
:conflict_score => conflicts, |
|||
:error_count => errors |
|||
} |
|||
end |
|||
|
|||
def get_workshop(workshop, workshops, events) |
|||
workshop[:workshop] ? workshops[workshop[:workshop]] : (events[workshop[:event]] || :event) |
|||
end |
|||
|
|||
def workshop_classes(workshop, show_interest) |
|||
classes = [workshop.is_a?(Workshop) ? :workshop : workshop.event_type] |
|||
if show_interest && workshop.is_a?(Workshop) && current_user && WorkshopInterest.where(:user_id => current_user.id) |
|||
if workshop.interested?(current_user) || workshop.facilitator?(current_user) |
|||
classes << 'interested' |
|||
else |
|||
classes << 'not-interested' |
|||
end |
|||
end |
|||
|
|||
return classes |
|||
end |
|||
|
|||
def schedule_start_and_end_times(day_part, day_parts, day_schedule) |
|||
start_time = [day_parts[day_parts.keys[day_part]], day_schedule[:start_time]].max |
|||
end_time = [day_parts[day_parts.keys[day_part + 1]] || 24, day_schedule[:end_time]].min |
|||
|
|||
min_time = nil |
|||
max_time = nil |
|||
|
|||
day_schedule[:locations].each do |location, location_schedule| |
|||
location_schedule.each do |hour, workshop| |
|||
t_start = hour |
|||
t_end = hour + workshop[:span] |
|||
if t_start >= start_time && t_end <= end_time |
|||
min_time = [min_time || 24, t_start].min |
|||
max_time = [max_time || 0, t_end].max |
|||
end |
|||
end |
|||
end |
|||
|
|||
return nil unless min_time.present? && max_time.present? |
|||
|
|||
[min_time || 0, max_time || 24] |
|||
end |
|||
end |
@ -1,2 +1,17 @@ |
|||
class Event < ActiveRecord::Base |
|||
end |
|||
class Event < ActiveRecord::Base |
|||
belongs_to :conference |
|||
|
|||
def conference_day |
|||
return nil unless start_time.present? && end_time.present? |
|||
|
|||
start_day = conference.start_date.change(hour: 0, minute: 0, second: 0) |
|||
w_start_day = start_time.change(hour: 0, minute: 0, second: 0) |
|||
return (((w_start_day - start_day) / 86400) + 1).to_i |
|||
end |
|||
|
|||
def duration |
|||
return nil unless start_time.present? && end_time.present? |
|||
((end_time - start_time) / 60).to_i |
|||
end |
|||
|
|||
end |
|||
|
@ -0,0 +1,2 @@ |
|||
class EventLocation < ActiveRecord::Base |
|||
end |
@ -0,0 +1,23 @@ |
|||
= render 'conferences/page_header', :page_key => (@location ? 'Edit_Location' : 'New_Location') |
|||
%article |
|||
= form_tag save_location_path(@this_conference.slug), class: 'composition' do |
|||
= row do |
|||
= columns(medium: 12) do |
|||
= (hidden_field_tag :location_id, @location.id) if @location |
|||
.text-field.input-field.big |
|||
= label_tag :title |
|||
= text_field_tag :title, @location ? @location.title : nil, :required => true |
|||
= row do |
|||
= columns(medium: 6) do |
|||
.text-area-field.input-field |
|||
= label_tag :address |
|||
= text_area_tag :address, @location ? @location.address : nil, :required => true |
|||
= columns(medium: 6) do |
|||
%h3=_'articles.locations.headings.amenities' |
|||
- [:sound, :projector, :tools].each do |need| |
|||
.single-check-box-field.input-field |
|||
= label_tag "needs_#{need}" do |
|||
= check_box_tag "needs[#{need}]", 1, @location && @amenities.include?(need) |
|||
= _"workshop.options.needs.#{need}" |
|||
.actions |
|||
= button_tag :save, :value => :save |
@ -1,7 +1,22 @@ |
|||
%h1 Editing event |
|||
|
|||
= render 'form' |
|||
|
|||
= link_to 'Show', @event |
|||
\| |
|||
= link_to 'Back', events_path |
|||
= render 'conferences/page_header', :page_key => (@event ? 'Edit_Event' : 'New_Event') |
|||
%article |
|||
= form_tag save_event_path(@this_conference.slug), class: 'composition' do |
|||
= row do |
|||
= columns(medium: 9) do |
|||
= (hidden_field_tag :event_id, @event.id) if @event |
|||
.text-field.input-field.big |
|||
= label_tag :title |
|||
= text_field_tag :title, @event ? @event.title : nil, :required => true |
|||
= columns(medium: 3) do |
|||
.select-field.input-field |
|||
= label_tag :event_type do |
|||
= select_tag :event_type, options_for_select([:event, :meal], @event ? @event.event_type : nil), :include_blank => true |
|||
=_'forms.labels.generic.event_type' |
|||
= row do |
|||
= columns(medium: 12) do |
|||
.text-area-field.input-field |
|||
= label_tag :info |
|||
= text_area_tag :info, @event ? @event.info : nil, :required => true |
|||
= columns(medium: 12) do |
|||
.actions.right |
|||
= button_tag :save, :value => :save |
|||
|
@ -0,0 +1,36 @@ |
|||
.programme |
|||
- schedule.each do |day, day_schedule| |
|||
.programme-day |
|||
%h2=I18n.l(conference.start_date + (day - 1).days, :format => "%A") |
|||
- (0...day_parts.length).each do |day_part| |
|||
.programme-day-part |
|||
- times = schedule_start_and_end_times(day_part, day_parts, day_schedule) |
|||
- if times.present? |
|||
%h3=_"articles.headings.schedule.day_parts.#{day_parts.keys[day_part].to_s}" if day_parts.length > 1 |
|||
%table.schedule |
|||
%tr |
|||
%th |
|||
- (times.first...times.last).step(0.5).each do |t| |
|||
- t = t.to_i if t == t.to_i |
|||
%th=I18n.l(Date.today + t.hours, :format => :short) |
|||
- day_schedule[:locations].each do |location, location_schedule| |
|||
%tr |
|||
%th=locations[location.to_s].title |
|||
- skip = 0 |
|||
- (times.first...times.last).step(0.5).each do |t| |
|||
- t = t.to_i if t == t.to_i |
|||
- if location_schedule[t].present? |
|||
- workshop = location_schedule[t] |
|||
- w = get_workshop(workshop, workshops, events) |
|||
%td{:class => workshop_classes(w, show_interest) + [show_previews && workshop[:type] == :workshop ? 'previewable' : nil], :colspan => (workshop[:span] * 2), :id => "workshop-#{w.id}"} |
|||
.title= w.title |
|||
- if show_previews && workshop[:type] == :workshop |
|||
.info |
|||
%a.close{href: "#!"} |
|||
= render 'workshops/show', :workshop => w, :preview => true |
|||
%a{class: 'preview', href: "#workshop-#{w.id}"} |
|||
- skip = workshop[:span] - 0.5 |
|||
- elsif skip > 0 |
|||
- skip -= 0.5 |
|||
- else |
|||
%td.empty |
@ -0,0 +1,77 @@ |
|||
= render 'conferences/page_header', :page_key => 'Edit_Schedule' |
|||
%article |
|||
= form_tag save_schedule_path(@this_conference.slug), class: 'composition' do |
|||
= row do |
|||
= columns(medium: 12) do |
|||
= render 'schedule/programme', :schedule => @schedule, :conference => @this_conference, :workshops => @workshops, :events => @events, :locations => @location_hash, :show_interest => false, :day_parts => @day_parts, :show_previews => false |
|||
= row do |
|||
= columns(medium: 12) do |
|||
- if @error_count && @error_count > 0 |
|||
%h3.errors |
|||
=_'errors.schedule.errors',"Errors:" |
|||
= @error_count |
|||
- if @conflict_score && @conflict_score > 0 |
|||
%h3.conflict-score |
|||
=_'errors.schedule.conflict_score',"Interest Conflicts:" |
|||
= @conflict_score |
|||
= row do |
|||
= columns(medium: 12) do |
|||
= (hidden_field_tag :location_id, @location.id) if @location |
|||
.actions |
|||
- if @this_conference.workshop_schedule_published |
|||
= button_tag :Unpublish, :value => :unpublish, :class => 'delete' |
|||
- elsif @error_count < 1 |
|||
= button_tag :Publish, :value => :publish |
|||
= button_tag :Preview, :value => :preview, :class => 'secondary' |
|||
- unless @this_conference.workshop_schedule_published && @error_count > 0 |
|||
= button_tag :save, :value => :save |
|||
- unless @saved |
|||
.unsaved=_'errors.schedule.unsaved','Your changes will not be saved until you press Save or Publish' |
|||
= row do |
|||
= columns(medium: 6) do |
|||
%h2=_"articles.headings.schedule.day_parts.Workshops" |
|||
%ul.all-workshops |
|||
- @workshops.each do |i| |
|||
- error = @errors["w#{i.id}"] |
|||
- warnings = @warnings["w#{i.id}"] |
|||
%li{class: error.present? ? :error : nil} |
|||
%h3=i.title |
|||
.workshop-interest=_'articles.workshops.info.interested_count', "#{i.interested_count} people are interested in this workshop", :vars => {:count => i.interested_count} |
|||
.time |
|||
= select_tag "workshop_day[#{i.id}]", options_for_select(@days, i.conference_day), :include_blank => true |
|||
= select_tag "workshop_hour[#{i.id}]", options_for_select(@hours, i.start_time ? i.start_time.strftime('%R') : nil), :include_blank => true |
|||
= select_tag "workshop_duration[#{i.id}]", options_for_select(@workshop_durations, i.duration || 60) |
|||
.location |
|||
= select_tag "workshop_location[#{i.id}]", options_from_collection_for_select(@locations, :id, :title, i.event_location_id), :include_blank => true |
|||
- if warnings |
|||
%ul.warnings |
|||
- warnings.each do |warning| |
|||
%li=warning |
|||
- if error |
|||
.error-description=error |
|||
= columns(medium: 6) do |
|||
%h2=_"articles.headings.schedule.day_parts.Events" |
|||
%ul.all-events |
|||
- @events.each do |i| |
|||
- error = @errors["e#{i.id}"] |
|||
%li{:class => [i.event_type, error.present? ? :error : nil]} |
|||
%h3=i.title |
|||
.time |
|||
= select_tag "event_day[#{i.id}]", options_for_select(@days, i.conference_day) |
|||
= select_tag "event_hour[#{i.id}]", options_for_select(@hours, i.start_time ? i.start_time.strftime('%R') : '12:00') |
|||
= select_tag "event_duration[#{i.id}]", options_for_select(@event_durations, i.duration || 60) |
|||
.location |
|||
= select_tag "event_location[#{i.id}]", options_from_collection_for_select(@locations, :id, :title, i.event_location_id), :include_blank => true |
|||
- if error |
|||
.error-description=error |
|||
%h2=_"articles.headings.schedule.day_parts.Day_Parts" |
|||
%ul.day_parts |
|||
- [:morning, :afternoon, :evening].each do |day_part| |
|||
%li |
|||
%h4 |
|||
=_"articles.headings.schedule.day_parts.#{day_part.to_s}" |
|||
- h = (Date.today + @day_parts[day_part.to_s].to_f.hours).strftime('%R') |
|||
- if day_part == :morning |
|||
.select=h |
|||
- else |
|||
= select_tag "day_parts[#{day_part.to_s}]", options_for_select(@hours, h) |
@ -0,0 +1,28 @@ |
|||
= render 'conferences/page_header', :page_key => 'Schedule' |
|||
%article |
|||
- if @this_conference.host?(current_user) |
|||
= row do |
|||
= columns(medium: 12) do |
|||
.actions.left |
|||
= link_to (_'actions.schedule.edit','Edit Schedule'), edit_schedule_path(@this_conference.slug), class: [:button] |
|||
= row do |
|||
= columns(medium: 6) do |
|||
%h2=_'articles.schedule.headings.Events' |
|||
- if @events |
|||
%ul |
|||
- @events.each do |event| |
|||
%li |
|||
%h3=_!event.title |
|||
= link_to (_'actions.events.edit','Edit'), edit_event_path(@this_conference.slug, event.id), class: [:button, :modify] |
|||
.actions.left |
|||
= link_to (_'actions.events.create','Add Event'), add_event_path(@this_conference.slug), class: [:button, :modify] |
|||
= columns(medium: 6) do |
|||
%h2=_'articles.schedule.headings.Locations' |
|||
- if @locations |
|||
%ul |
|||
- @locations.each do |location| |
|||
%li |
|||
%h3=_!location.title |
|||
= link_to (_'actions.locations.edit','Edit'), edit_location_path(@this_conference.slug, location.id), class: [:button, :modify] |
|||
.actions.left |
|||
= link_to (_'actions.schedule.edit','Add Location'), add_location_path(@this_conference.slug), class: [:button, :modify] |
@ -0,0 +1,58 @@ |
|||
= row do |
|||
= columns(medium: 12) do |
|||
%h2=_!workshop.title |
|||
.workshop-interest |
|||
- if workshop.interested?(current_user) |
|||
=_'articles.workshops.info.you_are_interested_count', "You and #{workshop.interested_count - 1} others are interested in this workshop", :vars => {:count => (workshop.interested_count - 1)} |
|||
- else |
|||
=_'articles.workshops.info.interested_count', "#{workshop.interested_count} people are interested in this workshop", :vars => {:count => workshop.interested_count} |
|||
- if !preview && workshop.can_show_interest?(current_user) |
|||
= form_tag toggle_workshop_interest_path(workshop.conference.slug, workshop.id) do |
|||
= button_tag (workshop.interested?(current_user) ? :remove_interest : :show_interest), :value => :toggle_interest, :class => (workshop.interested?(current_user) ? 'delete' : 'add') |
|||
=markdown _!(workshop.info) || '' |
|||
- if !preview && logged_in? && current_user.can_translate? |
|||
.actions |
|||
- I18n.backend.enabled_locales.each do |locale| |
|||
= (link_to (_'actions.workshops.Translate', "Translate into #{language_name(locale)}", :vars => {:language => language_name(locale)}), edit_workshop_url(workshop.conference.slug, workshop.id, url_params(locale)), :class => 'button translate') if workshop.can_translate?(current_user, locale) |
|||
= columns(medium: 6) do |
|||
%h3=_'articles.workshops.headings.facilitators' |
|||
.facilitators |
|||
- workshop.workshop_facilitators.each do |f| |
|||
- u = User.find(f.user_id) |
|||
- if logged_in? && (workshop.public_facilitator?(u) || f.user_id == current_user.id || workshop.active_facilitator?(current_user)) |
|||
.facilitator |
|||
.name=_!(u.firstname || u.username || u.email) |
|||
.role |
|||
=_"roles.workshops.facilitator.#{workshop.role(u).to_s}" |
|||
- if !preview && f.role.to_sym == :requested && workshop.active_facilitator?(current_user) |
|||
=(link_to (_'actions.workshops.Approve'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'approve'), :class => 'button modify') |
|||
=(link_to (_'actions.workshops.Deny'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'deny'), :class => 'button delete') |
|||
- elsif !preview && (f.user_id == current_user.id && f.role.to_sym != :creator) || (!workshop.conference.registered?(u) && workshop.active_facilitator?(current_user)) |
|||
=(link_to (_'actions.workshops.Remove'), approve_facilitate_workshop_request_path(workshop.conference.slug, workshop.id, f.user_id, 'remove'), :class => 'button delete') |
|||
- if !preview |
|||
.actions |
|||
=(link_to (_'actions.workshops.Facilitate'), facilitate_workshop_path(workshop.conference.slug, workshop.id), :class => 'button modify') if !workshop.facilitator?(current_user) |
|||
- if workshop.active_facilitator?(current_user) |
|||
= form_tag workshop_add_facilitator_path(workshop.conference.slug, workshop.id), :class => 'add-facilitator' do |
|||
%h4='Add a facilitator' |
|||
.email-field.input-field |
|||
= email_field_tag :email, nil, required: true |
|||
= label_tag :email |
|||
= button_tag :add |
|||
- if workshop.languages |
|||
= columns(medium: 6) do |
|||
%h3=_'articles.workshops.headings.languages','Workshop Language' |
|||
%p= _!((JSON.parse(workshop.languages || '[]').map { |x| _"languages.#{x}" }).join(', ').to_s.html_safe) |
|||
- if workshop.theme |
|||
= columns(medium: 6) do |
|||
%h3=_'articles.workshops.headings.theme','Theme' |
|||
%p= [:race_gender, :mechanics, :funding, :organization, :community].include?((workshop.theme || '').to_sym) ? (_"workshop.options.theme.#{workshop.theme}") : workshop.theme |
|||
- if workshop.active_facilitator?(current_user) || workshop.conference.host?(current_user) |
|||
- if workshop.needs |
|||
= columns(medium: 6) do |
|||
%h3=_'articles.workshops.headings.needs','What do you need?' |
|||
%p= _!((JSON.parse(workshop.needs || '[]').map { |x| _"workshop.options.needs.#{x}" }).join(', ').to_s.html_safe) |
|||
- if workshop.notes |
|||
= columns(medium: 12) do |
|||
%h3=_'articles.workshops.headings.notes','Notes' |
|||
=markdown _!(workshop.notes) |
@ -0,0 +1,248 @@ |
|||
<!DOCTYPE html><html lang="en"><head> |
|||
<meta charset="utf-8"> |
|||
<meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" name="viewport"> |
|||
<title>Bike!Bike!</title> |
|||
<meta content="Bike!Bike! A conference for bike collectives, co-ops, non-profit DIY bike shops" name="description"> |
|||
|
|||
<link href="/assets/application/safari-7.css" rel="stylesheet" media="all" type="text/css"><link href="/assets/web-fonts/safari-7.css" rel="stylesheet" media="all" type="text/css"> |
|||
<link href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon"> |
|||
<link href="/assets/favicon.ico" rel="icon" type="image/x-icon"> |
|||
<link href="/apple-touch-icon.png" rel="apple-touch-icon"> |
|||
<link href="/apple-touch-icon-72x72.png" rel="apple-touch-icon" sizes="72x72"> |
|||
<link href="/apple-touch-icon-114x114.png" rel="apple-touch-icon" sizes="114x114"> |
|||
<link href="/apple-touch-icon-144x144.png" rel="apple-touch-icon" sizes="144x144"> |
|||
|
|||
</head> |
|||
<body class="home"> |
|||
<nav> |
|||
<div id="main-nav"> |
|||
<div class="inner-nav"> |
|||
<a class="logo" href="/"><img src="/assets/bb-icon-logo.png" class="sprite icons bb-icon-logo"> |
|||
<img src="/assets/bb-icon-logo-text.png" class="sprite icons bb-icon-logo-text"> |
|||
</a><div class="nav"> |
|||
<a class="current" href="/"><span>My Bike!Bike!</span></a> |
|||
<a href="/about/"><span><span class="translated-content" data-i18n-key="page_titles.About_BikeBike" data-i18n-needs-translation="0">About Bike!Bike!</span></span></a> |
|||
<a href="/policy/"><span><span class="translated-content" data-i18n-key="page_titles.Safe_Space_Policy" data-i18n-needs-translation="0">Safer Space Agreement</span></span></a> |
|||
</div> |
|||
<div class="actions"> |
|||
<a class="button register" href="/conferences/MyBikeBike/register/"><span class="translated-content" data-i18n-key="conference.actions.Register" data-i18n-needs-translation="0">Register</span> |
|||
</a></div> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
|
|||
<main id="main"> |
|||
<header id="banner"> |
|||
<div id="header-title"> |
|||
|
|||
<div class="cover" style="background-image: url(/assets/default_cover.jpg)"></div> |
|||
<div class="title"> |
|||
<h2 class="background">2015!</h2> |
|||
<div class="details"> |
|||
<h3 class="primary">Boise, Idaho</h3> |
|||
<div class="secondary"> |
|||
August 27 – 31, 2015 |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<figure> |
|||
<img src="/assets/default_poster.jpg"> |
|||
</figure> |
|||
|
|||
</header> |
|||
<div id="content"> |
|||
<article> |
|||
<h2>My Bike!Bike!</h2> |
|||
Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. |
|||
<h3><span class="translated-content" data-i18n-key="articles.workshops.headings.Schedule" data-i18n-needs-translation="1">Schedule</span></h3> |
|||
<div class="programme"> |
|||
<div class="programme-day"> |
|||
<h2>Friday</h2> |
|||
<div class="programme-day-part"> |
|||
<h3><span class="translated-content" data-i18n-key="articles.headings.schedule.day_parts.morning" data-i18n-needs-translation="1">morning</span></h3> |
|||
<table class="schedule"> |
|||
<tbody><tr> |
|||
<th></th> |
|||
<th> 9:00am</th> |
|||
<th> 9:30am</th> |
|||
<th>10:00am</th> |
|||
</tr> |
|||
<tr> |
|||
<th>The Shop</th> |
|||
<td class="workshop previewable" colspan="3.0" id="workshop-1"> |
|||
<div class="title">Bikes and Beers</div> |
|||
<div class="info"> |
|||
<a class="close" href="#!"></a> |
|||
<div class="row"><div class="columns medium-12"><h2>Bikes and Beers</h2> |
|||
<div class="workshop-interest"> |
|||
<span class="translated-content" data-i18n-key="articles.workshops.info.interested_count" data-i18n-needs-translation="0">No one is interested in this workshop yet</span> |
|||
</div> |
|||
<p>Sed sagittis. Nam congue, risus semper porta volutpat, quam pede lobortis ligula, sit amet eleifend pede libero quis orci. Nullam molestie nibh in lectus.</p> |
|||
|
|||
</div><div class="columns medium-6"><h3><span class="translated-content" data-i18n-key="articles.workshops.headings.facilitators" data-i18n-needs-translation="0">Facilitators</span></h3> |
|||
<div class="facilitators"> |
|||
</div> |
|||
</div></div> |
|||
</div> |
|||
<a class="preview" href="#workshop-1"></a> |
|||
</td> |
|||
</tr> |
|||
</tbody></table> |
|||
</div> |
|||
<div class="programme-day-part"> |
|||
<h3><span class="translated-content" data-i18n-key="articles.headings.schedule.day_parts.afternoon" data-i18n-needs-translation="1">afternoon</span></h3> |
|||
<table class="schedule"> |
|||
<tbody><tr> |
|||
<th></th> |
|||
<th> 2:00pm</th> |
|||
<th> 2:30pm</th> |
|||
<th> 3:00pm</th> |
|||
</tr> |
|||
<tr> |
|||
<th>The Shop</th> |
|||
<td class="workshop previewable" colspan="3.0" id="workshop-3"> |
|||
<div class="title">Advocacy Now!</div> |
|||
<div class="info"> |
|||
<a class="close" href="#!"></a> |
|||
<div class="row"><div class="columns medium-12"><h2>Advocacy Now!</h2> |
|||
<div class="workshop-interest"> |
|||
<span class="translated-content" data-i18n-key="articles.workshops.info.interested_count" data-i18n-needs-translation="0">No one is interested in this workshop yet</span> |
|||
</div> |
|||
<p>In hac habitasse platea dictumst. Etiam faucibus cursus urna. Ut tellus.</p> |
|||
|
|||
</div><div class="columns medium-6"><h3><span class="translated-content" data-i18n-key="articles.workshops.headings.facilitators" data-i18n-needs-translation="0">Facilitators</span></h3> |
|||
<div class="facilitators"> |
|||
</div> |
|||
</div></div> |
|||
</div> |
|||
<a class="preview" href="#workshop-3"></a> |
|||
</td> |
|||
</tr> |
|||
</tbody></table> |
|||
</div> |
|||
<div class="programme-day-part"> |
|||
<h3><span class="translated-content" data-i18n-key="articles.headings.schedule.day_parts.evening" data-i18n-needs-translation="1">evening</span></h3> |
|||
<table class="schedule"> |
|||
<tbody><tr> |
|||
<th></th> |
|||
<th> 9:00pm</th> |
|||
<th> 9:30pm</th> |
|||
<th>10:00pm</th> |
|||
</tr> |
|||
<tr> |
|||
<th>The Shop</th> |
|||
<td class="workshop previewable" colspan="3.0" id="workshop-4"> |
|||
<div class="title">Public Outreach</div> |
|||
<div class="info"> |
|||
<a class="close" href="#!"></a> |
|||
<div class="row"><div class="columns medium-12"><h2>Public Outreach</h2> |
|||
<div class="workshop-interest"> |
|||
<span class="translated-content" data-i18n-key="articles.workshops.info.interested_count" data-i18n-needs-translation="0">No one is interested in this workshop yet</span> |
|||
</div> |
|||
<p>Duis bibendum. Morbi non quam nec dui luctus rutrum. Nulla tellus.</p> |
|||
|
|||
</div><div class="columns medium-6"><h3><span class="translated-content" data-i18n-key="articles.workshops.headings.facilitators" data-i18n-needs-translation="0">Facilitators</span></h3> |
|||
<div class="facilitators"> |
|||
</div> |
|||
</div></div> |
|||
</div> |
|||
<a class="preview" href="#workshop-4"></a> |
|||
</td> |
|||
</tr> |
|||
</tbody></table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</article> |
|||
</div> |
|||
</main> |
|||
|
|||
<div id="footer"> |
|||
<footer><div class="github"> |
|||
<img src="/assets/bb-icon-github.png" class="sprite icons bb-icon-github"> |
|||
<a href="https://github.com/bikebike/BikeBike/issues" target="_blank"> |
|||
<span class="translated-content" data-i18n-key="links.footer.text.File_an_Issue" data-i18n-needs-translation="0">File an issue</span> |
|||
</a> |
|||
| |
|||
<a href="https://github.com/bikebike/BikeBike/contributing.md" target="_blank"> |
|||
<span class="translated-content" data-i18n-key="links.footer.text.Help_contribute" data-i18n-needs-translation="0">Help contribute</span> |
|||
</a> |
|||
</div> |
|||
<div class="facebook"> |
|||
<span class="translated-contentblock" data-i18n-key="links.footer.help_text.facebook" data-i18n-needs-translation="0"><a href="https://www.facebook.com/groups/648758205249998/" target="_blank" title="Join our Facebook group"> |
|||
<img src="/assets/bb-icon-fb.png" class="sprite icons bb-icon-fb"> |
|||
</a> |
|||
</span></div> |
|||
<div class="locale"> |
|||
<span class="translated-contentblock" data-i18n-key="links.footer.help_text.select_language" data-i18n-needs-translation="0"><input id="select-language" type="checkbox"> |
|||
<label class="launch" for="select-language" title="Change your language"> |
|||
EN |
|||
</label> |
|||
<div class="selector"> |
|||
<ul> |
|||
<li> |
|||
<a href="/?lang=en"> |
|||
EN |
|||
</a> |
|||
<span>English</span> |
|||
</li> |
|||
<li> |
|||
<a href="/?lang=es"> |
|||
ES |
|||
</a> |
|||
<span>español</span> |
|||
</li> |
|||
<li> |
|||
<a href="/?lang=fr"> |
|||
FR |
|||
</a> |
|||
<span>français</span> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</span></div> |
|||
<div class="copy"> |
|||
<span class="translated-contentblock" data-i18n-key="links.footer.help_text.contributors" data-i18n-needs-translation="0"><a title="Contributors" href="/humans.txt">©2015 Bike!Bike! |
|||
</a></span></div> |
|||
</footer> |
|||
</div> |
|||
<script> |
|||
(function() { |
|||
if (!String.prototype.trim) { |
|||
(function() { |
|||
var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; |
|||
String.prototype.trim = function() { |
|||
return this.replace(rtrim, ''); |
|||
}; |
|||
})(); |
|||
} |
|||
|
|||
function classExists(elem,className){var p = new RegExp('(^| )'+className+'( |$)');return (elem.className && elem.className.match(p));} |
|||
function addClass(elem,className){if(classExists(elem,className)){return true;}elem.className += ' '+className;} |
|||
function removeClass(elem,className){var c = elem.className;var p = new RegExp('(^| )'+className+'( |$)');c = c.replace(p,' ').replace(/ /g,' ');elem.className = c.trim();} |
|||
|
|||
[].slice.call(document.querySelectorAll('.input-field input')).forEach(function(inputEl) { |
|||
if (inputEl.value.trim() === '') { |
|||
inputEl.parentNode.className = inputEl.parentNode.className + ' empty'; |
|||
} |
|||
|
|||
inputEl.addEventListener('focus', onInputFocus); |
|||
inputEl.addEventListener('blur', onInputBlur); |
|||
}); |
|||
|
|||
function onInputFocus(ev) { |
|||
removeClass(ev.target.parentNode, 'empty') |
|||
} |
|||
|
|||
function onInputBlur(ev) { |
|||
if (ev.target.value.trim() === '') { |
|||
addClass(ev.target.parentNode, 'empty'); |
|||
} |
|||
} |
|||
})(); |
|||
</script> |
|||
|
|||
|
|||
</body></html> |
@ -1,38 +1,54 @@ |
|||
BikeBike::Application.routes.draw do |
|||
|
|||
get '/organizations/json' => 'organizations#json', :as => :organizations_json |
|||
get '/organizations/json' => 'organizations#json', :as => :organizations_json |
|||
|
|||
get '/conferences/:slug/edit' => 'conferences#edit', :as => :edit_conference |
|||
post '/conferences/:slug/save' => 'conferences#save', :as => :save_conference |
|||
|
|||
match '/conferences/:slug/register' => 'conferences#register', :as => :register, via: [:get, :post] |
|||
match '/conferences/:slug/broadcast' => 'conferences#broadcast', :as => :broadcast, via: [:get, :post] |
|||
get '/conferences/:slug/stats' => 'conferences#stats', :as => :stats |
|||
get '/conferences/:slug/register/:button/:confirmation_token' => 'conferences#register', :as => :register_paypal_confirm |
|||
get '/conferences/:slug/workshops' => 'conferences#workshops', :as => :workshops |
|||
get '/conferences/:slug/stats' => 'conferences#stats', :as => :stats |
|||
get '/conferences/:slug/register/:button/:confirmation_token' => 'conferences#register', :as => :register_paypal_confirm |
|||
|
|||
get '/conferences/:slug/schedule' => 'conferences#schedule', :as => :schedule |
|||
get '/conferences/:slug/schedule/edit' => 'conferences#edit_schedule', :as => :edit_schedule |
|||
post '/conferences/:slug/schedule/save' => 'conferences#save_schedule', :as => :save_schedule |
|||
|
|||
get '/conferences/:slug/schedule/location/add' => 'conferences#add_location', :as => :add_location |
|||
post '/conferences/:slug/schedule/location/save' => 'conferences#save_location', :as => :save_location |
|||
get '/conferences/:slug/schedule/location/:id' => 'conferences#view_location', :as => :view_location |
|||
get '/conferences/:slug/schedule/location/:id/edit' => 'conferences#edit_location', :as => :edit_location |
|||
|
|||
get '/conferences/:slug/schedule/event/add' => 'conferences#add_event', :as => :add_event |
|||
post '/conferences/:slug/schedule/event/save' => 'conferences#save_event', :as => :save_event |
|||
get '/conferences/:slug/schedule/event/:id' => 'conferences#view_event', :as => :view_event |
|||
get '/conferences/:slug/schedule/event/:id/edit' => 'conferences#edit_event', :as => :edit_event |
|||
|
|||
get '/conferences/:slug/workshops' => 'conferences#workshops', :as => :workshops |
|||
match '/conferences/:slug/workshops/create' => 'conferences#create_workshop', :as => :create_workshop, via: [:get, :post] |
|||
post '/conferences/:slug/workshops/save' => 'conferences#save_workshop', :as => :save_workshop |
|||
get '/conferences/:slug/workshops/:workshop_id' => 'conferences#view_workshop', :as => :view_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/toggle-interest' => 'conferences#toggle_workshop_interest', :as => :toggle_workshop_interest |
|||
post '/conferences/:slug/workshops/save' => 'conferences#save_workshop', :as => :save_workshop |
|||
get '/conferences/:slug/workshops/:workshop_id' => 'conferences#view_workshop', :as => :view_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/toggle-interest' => 'conferences#toggle_workshop_interest', :as => :toggle_workshop_interest |
|||
match '/conferences/:slug/workshops/:workshop_id/edit' => 'conferences#edit_workshop', :as => :edit_workshop, via: [:get, :post] |
|||
match '/conferences/:slug/workshops/:workshop_id/delete' => 'conferences#delete_workshop', :as => :delete_workshop, via: [:get, :post] |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate' => 'conferences#facilitate_workshop', :as => :facilitate_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/facilitate_request' => 'conferences#facilitate_request', :as => :facilitate_workshop_request |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate_request/:user_id/:approve_or_deny' => 'conferences#approve_facilitate_request', :as => :approve_facilitate_workshop_request |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate/sent' => 'conferences#sent_facilitate_request', :as => :sent_facilitate_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/add_facilitator' => 'conferences#add_workshop_facilitator', :as => :workshop_add_facilitator |
|||
get '/conferences/:slug/edit' => 'conferences#edit', :as => :edit_conference |
|||
post '/conferences/:slug/save' => 'conferences#save', :as => :save_conference |
|||
|
|||
get '/robots.txt' => 'application#robots', :as => :robots_txt |
|||
get '/humans.txt' => 'application#humans', :as => :humans_txt |
|||
|
|||
get '/confirm/:token' => 'application#confirm', :as => :confirm |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate' => 'conferences#facilitate_workshop', :as => :facilitate_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/facilitate_request' => 'conferences#facilitate_request', :as => :facilitate_workshop_request |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate_request/:user_id/:approve_or_deny' => 'conferences#approve_facilitate_request', :as => :approve_facilitate_workshop_request |
|||
get '/conferences/:slug/workshops/:workshop_id/facilitate/sent' => 'conferences#sent_facilitate_request', :as => :sent_facilitate_workshop |
|||
post '/conferences/:slug/workshops/:workshop_id/add_facilitator' => 'conferences#add_workshop_facilitator', :as => :workshop_add_facilitator |
|||
|
|||
get '/robots.txt' => 'application#robots', :as => :robots_txt |
|||
get '/humans.txt' => 'application#humans', :as => :humans_txt |
|||
|
|||
get '/confirm/:token' => 'application#confirm', :as => :confirm |
|||
match '/doconfirm' => 'application#do_confirm', :as => :do_confirm, via: [:get, :post] |
|||
#post '/doconfirm' => 'application#do_confirm', :as => :do_confirm |
|||
post '/logout' => 'application#user_logout', :as => :logout |
|||
post '/translator-request' => 'application#translator_request', :as => :translator_request |
|||
post '/logout' => 'application#user_logout', :as => :logout |
|||
post '/translator-request' => 'application#translator_request', :as => :translator_request |
|||
|
|||
get '/error_404' => 'application#error_404' |
|||
get '/about' => 'application#about', :as => :about |
|||
get '/policy' => 'application#policy', :as => :policy |
|||
root 'application#home', :as => :home |
|||
get '/error_404' => 'application#error_404' |
|||
get '/about' => 'application#about', :as => :about |
|||
get '/policy' => 'application#policy', :as => :policy |
|||
root 'application#home', :as => :home |
|||
|
|||
end |
|||
|
@ -0,0 +1,14 @@ |
|||
class CreateEventLocations < ActiveRecord::Migration |
|||
def change |
|||
create_table :event_locations do |t| |
|||
t.string :title |
|||
t.integer :conference_id |
|||
t.float :latitude |
|||
t.float :longitude |
|||
t.string :address |
|||
t.string :amenities |
|||
|
|||
t.timestamps null: false |
|||
end |
|||
end |
|||
end |
@ -0,0 +1,5 @@ |
|||
class AddEventLocationIdToWorkshops < ActiveRecord::Migration |
|||
def change |
|||
add_column :workshops, :event_location_id, :integer |
|||
end |
|||
end |
@ -0,0 +1,5 @@ |
|||
class AddEventLocationIdToEvents < ActiveRecord::Migration |
|||
def change |
|||
add_column :events, :event_location_id, :integer |
|||
end |
|||
end |
@ -0,0 +1,5 @@ |
|||
class AddTypeToEvents < ActiveRecord::Migration |
|||
def change |
|||
add_column :events, :event_type, :string |
|||
end |
|||
end |
@ -0,0 +1,5 @@ |
|||
class AddDayPartsToConferences < ActiveRecord::Migration |
|||
def change |
|||
add_column :conferences, :day_parts, :string |
|||
end |
|||
end |
@ -0,0 +1,26 @@ |
|||
Feature: Workshop Page |
|||
In order to facilitate and attend workshops |
|||
As a visitor |
|||
|
|||
Scenario: View published schedule |
|||
Given There is an upcoming conference in Boise ID |
|||
And Registration is open |
|||
|
|||
And a location named The Shop exists |
|||
|
|||
And a workshop titled Bikes and Beers exists |
|||
And the workshop is scheduled for day 2 at 9:00 at The Shop |
|||
|
|||
And a workshop titled Bike Art exists |
|||
And the workshop is scheduled for day 2 at 12:00 at The Shop |
|||
|
|||
And a workshop titled Advocacy Now! exists |
|||
And the workshop is scheduled for day 2 at 14:00 at The Shop |
|||
|
|||
And a workshop titled Public Outreach exists |
|||
And the workshop is scheduled for day 2 at 21:00 at The Shop |
|||
|
|||
And the workshop schedule is published |
|||
|
|||
And I am on the landing page |
|||
Then I see the Bike!Bike! logo |
Loading…
Reference in new issue