From 99ce0411bc10e234350697f4985d82894971ba93 Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Fri, 4 Mar 2016 13:14:29 -0300 Subject: [PATCH 01/56] Updated vagrant box to official Leap release related to openSUSE/osem#824 Signed-off-by: Carlos Coelho --- Vagrantfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 45c04c4c..827cb8ed 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -12,7 +12,7 @@ Vagrant.configure(2) do |config| # Every Vagrant development environment requires a box. You can search for # boxes at https://atlas.hashicorp.com/search. - config.vm.box = "webhippie/opensuse-13.2" + config.vm.box = "opensuse/openSUSE-42.1-x86_64" # Disable automatic box update checking. If you disable this, then # boxes will only be checked for updates when the user runs From feaf9d807874ebde0349914a6a906439c5082e22 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Sat, 5 Mar 2016 02:54:09 +0100 Subject: [PATCH 02/56] Feature: Add/change Track for Event --- app/controllers/proposal_controller.rb | 2 +- app/models/event.rb | 1 + app/views/proposal/_proposal_form.html.haml | 5 ++++ app/views/proposal/_tooltip.html.haml | 28 ++++++--------------- app/views/proposal/index.html.haml | 3 ++- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/app/controllers/proposal_controller.rb b/app/controllers/proposal_controller.rb index 95042af5..82706e64 100644 --- a/app/controllers/proposal_controller.rb +++ b/app/controllers/proposal_controller.rb @@ -140,7 +140,7 @@ class ProposalController < ApplicationController private def event_params - params.require(:event).permit(:title, :subtitle, :event_type_id, :abstract, :description, :require_registration, :difficulty_level_id) + params.require(:event).permit(:title, :subtitle, :track_id, :event_type_id, :abstract, :description, :require_registration, :difficulty_level_id) end def user_params diff --git a/app/models/event.rb b/app/models/event.rb index 780e65b9..fc1c8f52 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -194,6 +194,7 @@ class Event < ActiveRecord::Base commercials: self.commercials.any?, biography: !self.submitter.biography.blank?, subtitle: !self.subtitle.blank?, + track: !self.track.blank?, difficulty_level: !self.difficulty_level.blank?, title: true, abstract: true diff --git a/app/views/proposal/_proposal_form.html.haml b/app/views/proposal/_proposal_form.html.haml index d30ad689..5addd7d2 100644 --- a/app/views/proposal/_proposal_form.html.haml +++ b/app/views/proposal/_proposal_form.html.haml @@ -4,6 +4,11 @@ = f.input :subtitle, as: :string + - if @program.tracks.any? + = f.input :track_id, as: :select, + collection: @program.tracks.map {|track| ["#{track.name}", track.id] }, + include_blank: true + = f.input :event_type_id, as: :select, collection: @conference.program.event_types.map {|type| ["#{type.title} - #{show_time(type.length)}", type.id, data: { min_words: type.minimum_abstract_length, max_words: type.maximum_abstract_length }]}, diff --git a/app/views/proposal/_tooltip.html.haml b/app/views/proposal/_tooltip.html.haml index aced298b..dd626209 100644 --- a/app/views/proposal/_tooltip.html.haml +++ b/app/views/proposal/_tooltip.html.haml @@ -3,33 +3,21 @@ %li{'class'=>class_for_todo(progress_status['registered'])} %span{'class'=>icon_for_todo(progress_status['registered'])} - if progress_status['registered'] - = link_to 'Edit your registration', edit_conference_conference_registrations_path(event.program.conference.short_title) + = link_to 'Register to the conference', edit_conference_conference_registrations_path(event.program.conference.short_title) - else = link_to 'Register to the conference', new_conference_conference_registrations_path(event.program.conference.short_title) - %li{'class'=>class_for_todo(progress_status['biography'])} %span{'class'=>icon_for_todo(progress_status['biography'])} - - if progress_status['biography'] - = link_to 'Edit your biography', edit_user_path(event.submitter) - - else - = link_to 'Fill out your biography', edit_user_path(event.submitter) - + = link_to 'Fill out your biography', edit_user_path(event.submitter) %li{'class'=>class_for_todo(progress_status['subtitle'])} %span{'class'=>icon_for_todo(progress_status['subtitle'])} - - if progress_status['subtitle'] - = link_to 'Edit the subtitle', edit_conference_program_proposal_path(event.program.conference.short_title, event) - - else - = link_to 'Add a subtitle', edit_conference_program_proposal_path(event.program.conference.short_title, event) - + = 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'])} - - if progress_status['commercials'] - = link_to 'Edit the commercials', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content') - - else - = link_to 'Add a commercial', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content') + = link_to 'Add a commercial', edit_conference_program_proposal_path(event.program.conference.short_title, event, anchor: 'commercials-content') + %li{'class'=>class_for_todo(progress_status['track'])} + %span{'class'=>icon_for_todo(progress_status['track'])} + = link_to 'Add a track', edit_conference_program_proposal_path(event.program.conference.short_title, event) %li{'class'=>class_for_todo(progress_status['difficulty_level'])} %span{'class'=>icon_for_todo(progress_status['difficulty_level'])} - - if progress_status['difficulty_level'] - = link_to 'Change the difficulty level', edit_conference_program_proposal_path(event.program.conference.short_title, event) - - else - = link_to 'Add a difficulty level', edit_conference_program_proposal_path(event.program.conference.short_title, event) + = link_to 'Add a difficulty level', edit_conference_program_proposal_path(event.program.conference.short_title, event) diff --git a/app/views/proposal/index.html.haml b/app/views/proposal/index.html.haml index 0a514daa..c72b6a93 100644 --- a/app/views/proposal/index.html.haml +++ b/app/views/proposal/index.html.haml @@ -65,12 +65,13 @@ %small.text-muted = event.event_type.title = "(#{event.event_type.length} min)" + = "in #{event.track.name}" if event.track - if event.state == 'confirmed' && event.require_registration == true , Pre-registered: #{pre_registered(event).count} %td.col-md-2{style: "padding:20px 8px 20px 8px;"} - = link_to 'Complete your todo list', 'javascript: void(0)', "type"=>"button", "data-trigger"=>"focus", "data-toggle"=>"popover", "title"=>"Your todo list", "data-content"=>"#{render partial: 'tooltip', locals: { event: event} }" + = link_to 'Complete your proposal', 'javascript: void(0)', "type"=>"button", "data-trigger"=>"focus", "data-toggle"=>"popover", "title"=>"Your todo list", "data-content"=>"#{render partial: 'tooltip', locals: { event: event} }" - progress_percentage = event.calculate_progress .progress From 2dad051ab96dd6593f281ea26a3fc3b6e27f71b0 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Sat, 5 Mar 2016 14:09:22 +0100 Subject: [PATCH 03/56] Add letter_opener_web to present emails in the browser in development mode. Using letter_opener in combination with Vagrant does not work because it's not possible to launch a web browser in your Vagrant box. Fixes #817. --- Gemfile | 2 ++ Gemfile.lock | 5 +++++ INSTALL.md | 5 +++++ config/environments/development.rb | 3 +++ config/routes.rb | 5 +++++ 5 files changed, 20 insertions(+) diff --git a/Gemfile b/Gemfile index 6be4ccc8..890425e7 100644 --- a/Gemfile +++ b/Gemfile @@ -163,6 +163,8 @@ group :development do gem 'sqlite3' # Use letter_opener to open mails in development gem 'letter_opener' + # Use letter_opener_web to open mails in browser (e.g. necessary for Vagrant) + gem 'letter_opener_web' # mina is a blazing fast deployment system gem 'mina' gem 'web-console', '~> 2.0' diff --git a/Gemfile.lock b/Gemfile.lock index 436ed447..a958697c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -211,6 +211,10 @@ GEM addressable (~> 2.3) letter_opener (1.2.0) launchy (~> 2.2) + letter_opener_web (1.3.0) + actionmailer (>= 3.2) + letter_opener (~> 1.0) + railties (>= 3.2) listen (2.7.2) celluloid (>= 0.15.2) celluloid-io (>= 0.15.0) @@ -518,6 +522,7 @@ DEPENDENCIES jquery-datatables-rails (~> 2.2.1) jquery-rails letter_opener + letter_opener_web mina money-rails mysql2 diff --git a/INSTALL.md b/INSTALL.md index a44ac3a6..4ee49ab0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -47,6 +47,11 @@ You can access the app [localhost:3000](http://localhost:3000). Whatever you cha vagrant ssh ``` +**Note**: We use [letter_opener](https://github.com/ryanb/letter_opener) in development environment. +However, letter_opener uses launchy to present the emails in your browser which doesn't work in combination with Vagrant. +Therefore we use [letter_open_web](https://github.com/fgrehm/letter_opener_web). +You can check out your mails by visiting [localhost:3000/letter_opener](http://localhost:3000/letter_opener) if you use Vagrant. + ### Run OSEM in production We recommend to run OSEM in production with [mod_passenger](https://www.phusionpassenger.com/download/#open_source) and the [apache web-server](https://www.apache.org/). There are tons of guides on how to deploy rails apps on various diff --git a/config/environments/development.rb b/config/environments/development.rb index e1610a27..ab207493 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -4,6 +4,9 @@ Osem::Application.configure do # Use letter_opener config.action_mailer.delivery_method = :letter_opener + # Use letter_opener_web for Vagrant (launchy won't work) + config.action_mailer.delivery_method = ENV['USER'] == 'vagrant' ? :letter_opener_web : :letter_opener + # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. diff --git a/config/routes.rb b/config/routes.rb index 1df57cbe..40b45a80 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,6 +10,11 @@ Osem::Application.routes.draw do path: 'accounts' end + # Use letter_opener_web to open mails in browser (e.g. necessary for Vagrant) + if Rails.env.development? + mount LetterOpenerWeb::Engine, at: "/letter_opener" + end + resources :users, except: [:new, :index, :create, :destroy] namespace :admin do From c9951b451a80396acebc2bcd0be62a8364cc90d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Sede=C3=B1o?= Date: Sat, 5 Mar 2016 23:48:43 +0100 Subject: [PATCH 04/56] Fix send emails because missing event program relation. fix #835 --- app/mailers/mailbot.rb | 8 ++++---- app/models/email_settings.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/mailers/mailbot.rb b/app/mailers/mailbot.rb index 5c378e09..1c772eff 100644 --- a/app/mailers/mailbot.rb +++ b/app/mailers/mailbot.rb @@ -9,7 +9,7 @@ class Mailbot < ActionMailer::Base end def acceptance_mail(event) - conference = event.conference + conference = event.program.conference person = event.submitter build_email(conference, person.email, @@ -18,7 +18,7 @@ class Mailbot < ActionMailer::Base end def rejection_mail(event) - conference = event.conference + conference = event.program.conference person = event.submitter build_email(conference, person.email, @@ -27,7 +27,7 @@ class Mailbot < ActionMailer::Base end def confirm_reminder_mail(event) - conference = event.conference + conference = event.program.conference person = event.submitter build_email(conference, person.email, @@ -83,7 +83,7 @@ class Mailbot < ActionMailer::Base def send_notification_email_for_comment(comment) @comment = comment @event = @comment.commentable - @conference = @event.conference + @conference = @event.program.conference recipients = User.comment_notifiable(@conference) # with scope recipients.each do |user| @user = user diff --git a/app/models/email_settings.rb b/app/models/email_settings.rb index be1fc1cb..da54d0e8 100644 --- a/app/models/email_settings.rb +++ b/app/models/email_settings.rb @@ -38,7 +38,7 @@ class EmailSettings < ActiveRecord::Base if event h['eventtitle'] = event.title - h['proposalslink'] = Rails.application.routes.url_helpers.conference_proposal_index_url( + h['proposalslink'] = Rails.application.routes.url_helpers.conference_program_proposal_index_url( conference.short_title, host: CONFIG['url_for_emails']) end h From dd08b702b917d7a38c6c863e631287c1e02be4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Sede=C3=B1o?= Date: Sun, 6 Mar 2016 00:19:55 +0100 Subject: [PATCH 05/56] Add program relation in generate_event_mail. fix #835 --- app/models/email_settings.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/email_settings.rb b/app/models/email_settings.rb index da54d0e8..7ce4bb82 100644 --- a/app/models/email_settings.rb +++ b/app/models/email_settings.rb @@ -45,7 +45,7 @@ class EmailSettings < ActiveRecord::Base end def generate_event_mail(event, event_template) - values = get_values(event.conference, event.submitter, event) + values = get_values(event.program.conference, event.submitter, event) parse_template(event_template, values) end From 680d23a64a86d2fbfe54c2b07f2355262281890f Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Tue, 1 Mar 2016 01:48:02 +0530 Subject: [PATCH 06/56] Tests for target model created_at and due_date are preset cause we don't want it to depend on system time. --- app/models/target.rb | 2 +- spec/models/target_spec.rb | 153 +++++++++++++++++++++++++------------ 2 files changed, 107 insertions(+), 48 deletions(-) diff --git a/app/models/target.rb b/app/models/target.rb index a1b496a2..ea91b38a 100644 --- a/app/models/target.rb +++ b/app/models/target.rb @@ -64,7 +64,7 @@ class Target < ActiveRecord::Base 'unit' => unit, 'created_at' => created_at, 'progress' => progress, - 'days_left' => days_left, + 'days_left' => days_left } result end diff --git a/spec/models/target_spec.rb b/spec/models/target_spec.rb index 50a4103f..5297cabc 100644 --- a/spec/models/target_spec.rb +++ b/spec/models/target_spec.rb @@ -1,8 +1,11 @@ require 'spec_helper' describe Target do + let(:registration_target) { create(:target, target_count: 10, unit: Target.units[:registrations]) } + let(:submission_target) { create(:target, target_count: 10, unit: Target.units[:submissions]) } + let(:program_minutes_target) { create(:target, target_count: 300, unit: Target.units[:program_minutes]) } - describe 'validations' do + describe 'validation' do it 'has a valid factory' do expect(build(:target)).to be_valid end @@ -32,74 +35,130 @@ describe Target do end end + describe 'default scope' do + before do + @first_target = create(:target, due_date: 2.days.from_now) + @second_target = create(:target, due_date: 3.days.from_now) + end + + it 'orders by ascending due_date' do + expect(Target.all).to match_array [@first_target, @second_target] + end + end + + describe 'association' do + it { should belong_to(:conference) } + it { should belong_to(:campaign) } + end + describe '#get_progress' do - it 'returns zero if there are no registrations' do - conference = build(:conference) - target = build(:target, target_count: 10, unit: Target.units[:registrations]) - conference.targets = [target] - - expect(target.get_progress).to eq('0') + it 'returns zero, when there are no registrations' do + expect(registration_target.get_progress).to eq('0') end - it 'returns 10 if there one registrations of 10' do - conference = create(:conference) - target = create(:target, target_count: 10, unit: Target.units[:registrations]) - registration = create(:registration) + it 'returns 10, when there is 1 registration and the target is 10' do + create(:registration, conference: registration_target.conference) - conference.targets = [target] - conference.registrations = [registration] - - expect(target.get_progress).to eq('10') + expect(registration_target.get_progress).to eq('10') end - it 'returns zero if there are no submissions' do - conference = create(:conference) - target = build(:target, target_count: 10, unit: Target.units[:submissions]) - conference.targets = [target] - - expect(target.get_progress).to eq('0') + it 'returns zero, when there are no submissions' do + expect(submission_target.get_progress).to eq('0') end - it 'returns 10 if there one submissions of 10' do - conference = create(:conference) - target = create(:target, target_count: 10, unit: Target.units[:submissions]) - event = create(:event) + it 'returns 10, when there is 1 submission and the target is 10' do + create(:event, program: submission_target.conference.program) - conference.targets = [target] - conference.program.events = [event] - - expect(target.get_progress).to eq('10') + expect(submission_target.get_progress).to eq('10') end - it 'returns zero if there are no program minutes' do - conference = create(:conference) - target = build(:target, target_count: 10, unit: Target.units[:program_minutes]) - conference.targets = [target] - - expect(target.get_progress).to eq('0') + it 'returns zero, when there are no program minutes' do + expect(program_minutes_target.get_progress).to eq('0') end - it 'returns 10 if there are 30 program minutes of 300' do - conference = create(:conference) - target = create(:target, target_count: 300, unit: Target.units[:program_minutes]) - event = create(:event) + it 'returns 10, when there are 30 program minutes and the target is 300' do + create(:event, program: program_minutes_target.conference.program) - conference.targets = [target] - conference.program.events = [event] + expect(program_minutes_target.get_progress).to eq('10') + end + end - expect(target.get_progress).to eq('10') + describe '#get_campaign' do + context 'submissions' do + before do + submission_target.campaign = create(:campaign, name: 'Submission Campaign', conference: submission_target.conference) + submission_target.created_at = Time.utc(2014, 5, 10) + submission_target.due_date = Date.today + 4.days + allow(submission_target.campaign).to receive(:submissions_count) { 20 } + end + + it 'returns a hash with values of the corresponding campaign submissions' do + result = { + 'target_name' => "10 Submissions by #{Date.today + 4.days}", + 'campaign_name' => 'Submission Campaign', + 'value' => 20, + 'unit' => 'Submission', + 'created_at' => Time.utc(2014, 5, 10).in_time_zone, + 'progress' => '200', + 'days_left' => 4 + } + + expect(submission_target.get_campaign).to eq result + end + end + + context 'registrations' do + before do + registration_target.campaign = create(:campaign, name: 'Registration Campaign', conference: registration_target.conference) + registration_target.created_at = Time.utc(2014, 5, 10) + registration_target.due_date = Date.today + 4.days + allow(registration_target.campaign).to receive(:registrations_count) { 20 } + end + + it 'returns a hash with values of the corresponding campaign registrations' do + result = { + 'target_name' => "10 Registrations by #{Date.today + 4.days}", + 'campaign_name' => 'Registration Campaign', + 'value' => 20, + 'unit' => 'Registration', + 'created_at' => Time.utc(2014, 5, 10).in_time_zone, + 'progress' => '200', + 'days_left' => 4 + } + + expect(registration_target.get_campaign).to eq result + end + end + + context 'program_minutes' do + before do + program_minutes_target.campaign = create(:campaign, name: 'Program Campaign', conference: program_minutes_target.conference) + program_minutes_target.created_at = Time.utc(2014, 5, 10) + program_minutes_target.due_date = Date.today + 4.days + allow(program_minutes_target.conference).to receive(:current_program_minutes) { 20 } + end + + it 'returns a hash with values of the corresponding campaign program minutes' do + result = { + 'target_name' => "300 Program minutes by #{Date.today + 4.days}", + 'campaign_name' => 'Program Campaign', + 'value' => 20, + 'unit' => 'Program minute', + 'created_at' => Time.utc(2014, 5, 10).in_time_zone, + 'progress' => '7', + 'days_left' => 4 + } + + expect(program_minutes_target.get_campaign).to eq result + end end end describe '#to_s' do it 'returns a string in the correct format' do - conference = build(:conference) - target = build(:target, target_count: 10, unit: Target.units[:registrations]) - conference.targets = [target] - result = "10 Registrations by #{14.days.from_now.to_date}" - expect(target.to_s).to eq(result) + expect(registration_target.to_s).to eq(result) end end end From c219ffc9a3a1864f9816c4cc63f8abe616eba7fa Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Tue, 1 Mar 2016 03:01:49 +0530 Subject: [PATCH 07/56] Tests for Admin::Targets controller Authorization in index action is not needed. Fix failed delete flash error message. --- app/controllers/admin/targets_controller.rb | 10 +- .../admin/targets_controller_spec.rb | 168 ++++++++++++++++++ 2 files changed, 172 insertions(+), 6 deletions(-) create mode 100644 spec/controllers/admin/targets_controller_spec.rb diff --git a/app/controllers/admin/targets_controller.rb b/app/controllers/admin/targets_controller.rb index 6f73dc0a..d15d5726 100644 --- a/app/controllers/admin/targets_controller.rb +++ b/app/controllers/admin/targets_controller.rb @@ -3,9 +3,7 @@ module Admin load_and_authorize_resource :conference, find_by: :short_title load_and_authorize_resource :target, through: :conference - def index - authorize! :update, Target.new(conference_id: @conference.id) - end + def index; end def new @target = @conference.targets.new @@ -39,9 +37,9 @@ module Admin redirect_to(admin_conference_targets_path(conference_id: @conference.short_title), notice: 'Target successfully destroyed.') else - redirect_to(admin_conference_targets_path(conference_id: @conference.short_title), - error: 'Target was successfully destroyed.' \ - "#{@target.errors.full_messages.join('. ')}.") + redirect_to admin_conference_targets_path(conference_id: @conference.short_title), + flash: { error: "Could not delete target for #{@conference.title}: "\ + "#{@target.errors.full_messages.join('. ')}." } end end diff --git a/spec/controllers/admin/targets_controller_spec.rb b/spec/controllers/admin/targets_controller_spec.rb new file mode 100644 index 00000000..2b8b5dd4 --- /dev/null +++ b/spec/controllers/admin/targets_controller_spec.rb @@ -0,0 +1,168 @@ +require 'spec_helper' + +describe Admin::TargetsController, type: :controller do + let(:admin) { create(:admin) } + let(:conference) { create(:conference) } + let(:target) { create(:target, conference: conference, target_count: 100) } + + context 'user is admin' do + before { sign_in admin } + + describe 'GET #index' do + before { get :index, conference_id: conference.short_title } + + it 'renders index template' do + expect(response).to render_template('index') + end + + it 'assigns targets and conference variables' do + expect(assigns(:conference)).to eq conference + expect(assigns(:targets)).to eq [target] + end + end + + describe 'GET #new' do + before { get :new, conference_id: conference.short_title } + + it 'renders new template' do + expect(response).to render_template('new') + end + + it 'assigns target variable' do + expect(assigns(:target)).to be_instance_of(Target) + end + end + + describe 'POST #create' do + context 'saves successfuly' do + before do + post :create, target: attributes_for(:target), conference_id: conference.short_title + end + + it 'redirects to admin target index path' do + expect(response).to redirect_to admin_conference_targets_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Target successfully created.') + end + + it 'creates new target' do + expect(Target.count).to eq 1 + end + end + + context 'save fails' do + before do + allow_any_instance_of(Target).to receive(:save).and_return(false) + post :create, target: attributes_for(:target), conference_id: conference.short_title + end + + 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 target failed: #{target.errors.full_messages.join('. ')}.") + end + + it 'does not create new target' do + expect(Target.count).to eq 0 + end + end + end + + describe 'GET #edit' do + before { get :edit, conference_id: conference.short_title, id: target.id } + + it 'renders edit template' do + expect(response).to render_template('edit') + end + + it 'assigns target variable' do + expect(assigns(:target)).to eq target + end + end + + describe 'PATCH #update' do + context 'updates successfully' do + before do + patch :update, target: attributes_for(:target, target_count: 2), + conference_id: conference.short_title, + id: target.id + end + + it 'redirects to admin target index path' do + expect(response).to redirect_to admin_conference_targets_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Target successfully updated.') + end + + it 'updates the target' do + target.reload + expect(target.target_count).to eq 2 + end + end + + context 'update fails' do + before do + allow_any_instance_of(Target).to receive(:save).and_return(false) + patch :update, target: attributes_for(:target, target_count: 2), + conference_id: conference.short_title, + id: target.id + 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("Target update failed: #{target.errors.full_messages.join('. ')}.") + end + + it 'does not update target' do + expect(target.target_count).to eq 100 + end + end + end + + describe 'DELETE #destroy' do + context 'deletes successfully' do + before { delete :destroy, conference_id: conference.short_title, id: target.id } + + it 'redirects to admin target index path' do + expect(response).to redirect_to admin_conference_targets_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Target successfully destroyed.') + end + + it 'deletes target' do + expect(Target.count).to eq 0 + end + end + + context 'delete fails' do + before do + allow_any_instance_of(Target).to receive(:destroy).and_return(false) + delete :destroy, conference_id: conference.short_title, id: target.id + end + + it 'redirects to admin target index path' do + expect(response).to redirect_to admin_conference_targets_path(conference_id: conference.short_title) + end + + it 'shows error in flash message' do + expect(flash[:error]).to match("Could not delete target for #{conference.title}: #{target.errors.full_messages.join('. ')}.") + end + + it 'does not delete target' do + expect(Target.count).to eq 1 + end + end + end + end +end From 69a4139268fbab18f98c2e9cc0b97b8aa0ffa411 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Sat, 5 Mar 2016 16:41:46 +0530 Subject: [PATCH 08/56] Tests for room model --- spec/models/room_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spec/models/room_spec.rb diff --git a/spec/models/room_spec.rb b/spec/models/room_spec.rb new file mode 100644 index 00000000..9220416b --- /dev/null +++ b/spec/models/room_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe Room do + subject { create(:room) } + + describe 'validation' do + it { should validate_presence_of(:name) } + it { should validate_presence_of(:venue_id) } + it { should validate_numericality_of(:size).only_integer.is_greater_than(0).allow_nil } + end + + describe 'association' do + it { should belong_to(:venue) } + it { should have_many(:events).dependent(:nullify) } + end + + describe 'callback' do + after { subject.run_callbacks(:create) } + + it '#generate_guid' do + regex_base64 = %r{^(?:[A-Za-z_\-0-9+\/]{4}\n?)*(?:[A-Za-z_\-0-9+\/]{2}|[A-Za-z_\-0-9+\/]{3}=)?$} + expect(subject).to receive(:generate_guid) + expect(subject.guid).to match regex_base64 + end + end +end From ebd01f064a010b2203078900682298d662e36b33 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Sat, 5 Mar 2016 15:49:10 +0530 Subject: [PATCH 09/56] Tests for ticket model Change in error message of validation cause previously it was: "Price currency Currency is different.." `paid?` method returned true even when `ticket_purchases` is empty for a given user. --- app/models/ticket.rb | 4 +- spec/models/ticket_spec.rb | 82 +++++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 16 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index d3b3d48b..08806b95 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -18,7 +18,7 @@ class Ticket < ActiveRecord::Base end def paid?(user) - ticket_purchases.where(user_id: user.id, paid: false).count == 0 + ticket_purchases.find_by(user: user, paid: true).present? end def quantity_bought_by(user) @@ -52,7 +52,7 @@ class Ticket < ActiveRecord::Base def tickets_of_conference_have_same_currency unless Ticket.where(conference_id: conference_id).all?{|t| t.price_currency == self.price_currency } - errors.add(:price_currency, 'Currency is different from the exist ticktes of this conference.') + errors.add(:price_currency, 'is different from the existing tickets of this conference.') end end end diff --git a/spec/models/ticket_spec.rb b/spec/models/ticket_spec.rb index 2b673fbb..fc67ff3d 100644 --- a/spec/models/ticket_spec.rb +++ b/spec/models/ticket_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' describe Ticket do let(:conference) { create(:conference) } - let(:ticket) { create(:ticket, price: 50, conference: conference) } + let(:ticket) { create(:ticket, price: 50, price_currency: 'USD', conference: conference) } let(:user) { create(:user) } - describe 'validations' do + describe 'validation' do it 'has a valid factory' do expect(build(:ticket)).to be_valid end @@ -33,6 +33,22 @@ describe Ticket do it 'is valid with a price_cents greater than zero' do should allow_value(1).for(:price_cents) end + + it 'is not valid if tickets of conference do not have same currency' do + conflicting_currency_ticket = build(:ticket, + conference: ticket.conference, + price_currency: 'INR') + expected_error_message = 'Price currency is different from the existing tickets of this conference.' + + expect(conflicting_currency_ticket).not_to be_valid + expect(conflicting_currency_ticket.errors.full_messages).to eq([expected_error_message]) + end + end + + describe 'association' do + it { should belong_to(:conference) } + it { should have_many(:ticket_purchases).dependent(:destroy) } + it { should have_many(:buyers).through(:ticket_purchases).source(:user) } end describe '#bought?' do @@ -43,11 +59,29 @@ describe Ticket do expect(ticket.bought?(user)).to eq(true) end - it 'returns true if the user has bought this ticket' do + it 'returns false if the user has not bought this ticket' do expect(ticket.bought?(user)).to eq(false) end end + describe '#paid?' do + let!(:ticket_purchase) { create(:ticket_purchase, user: user, ticket: ticket) } + + context 'user has paid' do + before { ticket_purchase.update_attributes(paid: true) } + + it 'returns true' do + expect(ticket.paid?(user)).to eq(true) + end + end + + context 'user has not paid' do + it 'returns false' do + expect(ticket.paid?(user)).to eq(false) + end + end + end + describe '#quantity_bought_by' do it 'returns the correct value if the user has bought this ticket' do create(:ticket_purchase, @@ -68,7 +102,7 @@ describe Ticket do user: user, ticket: ticket, quantity: 20) - expect(ticket.total_price(user)).to eq(Money.new(20 * ticket.price_cents, 'USD')) + expect(ticket.total_price(user)).to eq(Money.new(100000, 'USD')) end it 'returns zero if the user has not bought this ticket' do @@ -76,17 +110,37 @@ describe Ticket do end end - describe 'self#total_price' do - it 'returns the correct value if the user has bought this ticket' do - create(:ticket_purchase, - user: user, - ticket: ticket, - quantity: 20) - expect(Ticket.total_price(conference, user)).to eq(Money.new(20 * ticket.price_cents, 'USD')) - end + describe 'self.total_price' do + let(:diversity_supporter_ticket) { create(:ticket, conference: conference, price: 500) } - it 'returns zero if the user has not bought this ticket' do - expect(Ticket.total_price(conference, user)).to eq(Money.new(0, 'USD')) + describe 'user has bought' do + context 'no tickets' do + it 'returns zero' do + expect(Ticket.total_price(conference, user)).to eq(Money.new(0, 'USD')) + end + end + + context 'one type of ticket' do + before do + create(:ticket_purchase, ticket: ticket, user: user, quantity: 20) + end + + it 'returns the correct total price' do + expect(Ticket.total_price(conference, user)).to eq(Money.new(100000, 'USD')) + end + end + + context 'multiple types of tickets' do + before do + create(:ticket_purchase, ticket: ticket, user: user, quantity: 20) + create(:ticket_purchase, ticket: diversity_supporter_ticket, user: user, quantity: 2) + end + + it 'returns the correct total price' do + total_price = Money.new(200000, 'USD') + expect(Ticket.total_price(conference, user)).to eq(total_price) + end + end end end end From 0336171e4a6e5b34ed3c6394b1c911a3c7f0e96a Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Sun, 6 Mar 2016 22:20:13 -0300 Subject: [PATCH 10/56] Unset footer fixed height If footer is set to a fixed height, it makes some white block between footer and bottom of page. Its height should be resized according to footer content. Related to #840 Signed-off-by: Carlos Coelho --- app/assets/stylesheets/osem.css.scss | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/assets/stylesheets/osem.css.scss b/app/assets/stylesheets/osem.css.scss index 2f44ba19..58ffbc34 100644 --- a/app/assets/stylesheets/osem.css.scss +++ b/app/assets/stylesheets/osem.css.scss @@ -18,8 +18,6 @@ body { position: absolute; bottom: 0; width: 100%; - /* Set the fixed height of the footer here */ - height: 60px; background-color: #f5f5f5; .container { padding: 15px; From 2c1db3bd2ac39d6459aa6f4ddc9e5950b33258bc Mon Sep 17 00:00:00 2001 From: Rishabh Saxena Date: Mon, 7 Mar 2016 15:15:29 +0530 Subject: [PATCH 11/56] Making datatable responsive in admin's users view. --- app/views/admin/users/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 5f7b4d91..7752a41e 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -6,7 +6,7 @@ - if @users = "(#{@users.length})" .row - .col-md-12 + .col-md-12.table-responsive %table.table.table-striped.table-bordered.table-hover.datatable %thead %th ID From 483d9a234e1fbe04bdf227851551040096674a6d Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Mon, 7 Mar 2016 09:43:55 -0300 Subject: [PATCH 12/56] Verified contact has email or not issue #764 Signed-off-by: Carlos Coelho --- app/models/contact.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/contact.rb b/app/models/contact.rb index 3e45200a..4f904eeb 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -9,7 +9,7 @@ class Contact < ActiveRecord::Base format: URI::regexp(%w(http https)), allow_blank: true def has_social_media? - return true if !facebook.blank? || !twitter.blank? || !googleplus.blank? || !instagram.blank? + return true if !facebook.blank? || !twitter.blank? || !googleplus.blank? || !instagram.blank? || !email.blank? false end end From fda08ecdb5bfa02088b0764a180d0ffa48d4b126 Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Mon, 7 Mar 2016 09:47:21 -0300 Subject: [PATCH 13/56] Added email to social media section related to #764 Signed-off-by: Carlos Coelho --- app/views/conference/_social_media.html.haml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/views/conference/_social_media.html.haml b/app/views/conference/_social_media.html.haml index eefcbd0c..29eac688 100644 --- a/app/views/conference/_social_media.html.haml +++ b/app/views/conference/_social_media.html.haml @@ -17,3 +17,6 @@ - unless @conference.contact.googleplus.blank? = link_to "#{ @conference.contact.googleplus }" do %i.fa.fa-google-plus-square.fa-4x + - unless @conference.contact.email.blank? + = mail_to "#{ @conference.contact.email }" do + %i.fa.fa-envelope-o.fa-4x From 7b3208b43b6aae3bbffd5900973cf3b94f02e3e5 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Date: Sun, 6 Mar 2016 11:21:31 +0530 Subject: [PATCH 14/56] Tests for room controller --- .../admin/rooms_controller_spec.rb | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 spec/controllers/admin/rooms_controller_spec.rb diff --git a/spec/controllers/admin/rooms_controller_spec.rb b/spec/controllers/admin/rooms_controller_spec.rb new file mode 100644 index 00000000..dc8c3d2e --- /dev/null +++ b/spec/controllers/admin/rooms_controller_spec.rb @@ -0,0 +1,171 @@ +require 'spec_helper' + +describe Admin::RoomsController do + let!(:admin) { create(:admin) } + let(:conference) { create(:conference) } + let!(:venue) { create(:venue, conference: conference) } + let(:room) { create(:room, venue: venue, size: 4) } + + context 'admin is signed in' do + before { sign_in admin } + + describe 'GET #index' do + before { get :index, conference_id: conference.short_title } + + it 'assigns conference, venue and rooms variables' do + expect(assigns(:conference)).to eq conference + expect(assigns(:venue)).to eq venue + expect(assigns(:rooms)).to eq [room] + end + + it 'renders index template' do + expect(response).to render_template('index') + end + end + + describe 'GET #edit' do + before { get :edit, conference_id: conference.short_title, id: room.id } + + it 'renders edit template' do + expect(response).to render_template('edit') + end + + it 'assigns room variable' do + expect(assigns(:room)).to eq room + end + end + + describe 'GET #new' do + before { get :new, conference_id: conference.short_title } + + it 'renders new template' do + expect(response).to render_template('new') + end + + it 'assigns room variable' do + expect(assigns(:room)).to be_instance_of(Room) + end + end + + describe 'POST #create' do + context 'saves successfuly' do + before do + post :create, room: attributes_for(:room), conference_id: conference.short_title + end + + it 'redirects to admin room index path' do + expect(response).to redirect_to admin_conference_venue_rooms_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Room successfully created.') + end + + it 'creates new room' do + expect(Room.count).to eq 1 + end + end + + context 'save fails' do + before do + allow_any_instance_of(Room).to receive(:save).and_return(false) + post :create, room: attributes_for(:room), conference_id: conference.short_title + end + + 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 Room failed: #{room.errors.full_messages.join('. ')}.") + end + + it 'does not create new room' do + expect(Room.count).to eq 0 + end + end + end + + describe 'PATCH #update' do + context 'updates successfully' do + before do + patch :update, room: attributes_for(:room, size: 2), + conference_id: conference.short_title, + id: room.id + end + + it 'redirects to admin room index path' do + expect(response).to redirect_to admin_conference_venue_rooms_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Room successfully updated.') + end + + it 'updates the room' do + room.reload + expect(room.size).to eq 2 + end + end + + context 'update fails' do + before do + allow_any_instance_of(Room).to receive(:save).and_return(false) + patch :update, room: attributes_for(:room, size: 2), + conference_id: conference.short_title, + id: room.id + 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("Update Room failed: #{room.errors.full_messages.join('. ')}.") + end + + it 'does not update room' do + room.reload + expect(room.size).to eq 4 + end + end + end + + describe 'DELETE #destroy' do + context 'deletes successfully' do + before { delete :destroy, conference_id: conference.short_title, id: room.id } + + it 'redirects to admin room index path' do + expect(response).to redirect_to admin_conference_venue_rooms_path(conference_id: conference.short_title) + end + + it 'shows success message in flash notice' do + expect(flash[:notice]).to match('Room successfully deleted.') + end + + it 'deletes the room' do + expect(Room.count).to eq 0 + end + end + + context 'delete fails' do + before do + allow_any_instance_of(Room).to receive(:destroy).and_return(false) + delete :destroy, conference_id: conference.short_title, id: room.id + end + + it 'redirects to admin room index path' do + expect(response).to redirect_to admin_conference_venue_rooms_path(conference_id: conference.short_title) + end + + it 'shows error in flash message' do + expect(flash[:error]).to match("Destroying room failed! #{room.errors.full_messages.join('. ')}.") + end + + it 'does not delete room' do + expect(Room.count).to eq 1 + end + end + end + end +end From c9cce9fcca8612e9e8d534fd12623cea28902626 Mon Sep 17 00:00:00 2001 From: Henne Vogelsang Date: Mon, 7 Mar 2016 14:52:39 +0100 Subject: [PATCH 15/56] Update INSTALL.md Add `vagrant exec` instructions --- INSTALL.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 4ee49ab0..5b7a45be 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -26,27 +26,33 @@ We are using [Vagrant](https://www.vagrantup.com/) to create our development env vagrant up ``` -7. Start your OSEM rails app: +5. Start your OSEM rails app: ``` vagrant exec rails server -b 0.0.0.0 ``` -8. Check out your OSEM rails app: +6. Check out your OSEM rails app: You can access the app [localhost:3000](http://localhost:3000). Whatever you change in your cloned repository will have effect in the development environment. Sign up, the first user will be automatically assigned the admin role. -9. Changed something? Test your changes!: +7. Changed something? Test your changes!: ``` vagrant exec rake test ``` -10. Explore the development environment: +8. Explore the development environment: ``` vagrant ssh ``` +9. Or issue any standard `rails`/`rake`/`bundler` command by prepending `vagrant exec` + + ``` + vagrant exec rake db:migrate + ``` + **Note**: We use [letter_opener](https://github.com/ryanb/letter_opener) in development environment. However, letter_opener uses launchy to present the emails in your browser which doesn't work in combination with Vagrant. Therefore we use [letter_open_web](https://github.com/fgrehm/letter_opener_web). From d5f138b3dc6540b5b1684da3e1b54f1557cd1471 Mon Sep 17 00:00:00 2001 From: Christian Bruckmayer Date: Mon, 7 Mar 2016 18:28:14 +0100 Subject: [PATCH 16/56] Update country_select gem and removed git repository from Gemfile. Caused bundle install error in vagrant box. --- Gemfile | 2 +- Gemfile.lock | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 890425e7..a7d8548f 100644 --- a/Gemfile +++ b/Gemfile @@ -94,7 +94,7 @@ gem 'chart-js-rails' gem 'gravtastic' # for country selects -gem 'country_select', github: 'stefanpenner/country_select' +gem 'country_select' # for upload management gem 'paperclip' diff --git a/Gemfile.lock b/Gemfile.lock index a958697c..995bf235 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,3 @@ -GIT - remote: git://github.com/stefanpenner/country_select.git - revision: 585e9538a01ae9878e92f12a98261a09842ed015 - specs: - country_select (2.1.0) - countries (~> 0.9, >= 0.9.3) - GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ @@ -122,8 +115,12 @@ GEM execjs coffee-script-source (1.10.0) columnize (0.8.9) - countries (0.9.3) + countries (1.2.5) currencies (~> 0.4.2) + i18n_data (~> 0.7.0) + country_select (2.5.2) + countries (~> 1.2.0) + sort_alphabetical (~> 1.0) coveralls (0.7.0) multi_json (~> 1.3) rest-client @@ -197,6 +194,7 @@ GEM builder htmlentities (4.3.1) i18n (0.7.0) + i18n_data (0.7.0) inversion (0.12.3) loggability (~> 0.4) jquery-datatables-rails (2.2.3) @@ -431,6 +429,8 @@ GEM simplecov-html (0.8.0) sixarm_ruby_unaccent (1.1.1) slop (3.6.0) + sort_alphabetical (1.0.2) + unicode_utils (>= 1.2.2) spring (1.6.3) spring-commands-rspec (1.0.4) spring (>= 0.9.1) @@ -462,6 +462,7 @@ GEM execjs (>= 0.3.0) json (>= 1.8.0) unicode-display_width (0.3.1) + unicode_utils (1.4.0) unobtrusive_flash (3.1.0) railties user_agent_parser (2.1.5) @@ -504,7 +505,7 @@ DEPENDENCIES capybara chart-js-rails cocoon - country_select! + country_select coveralls daemons database_cleaner From 40a48e1e7ef75ea26ebcd60027b2ebee7c18468d Mon Sep 17 00:00:00 2001 From: Stella Rouzi Date: Fri, 4 Mar 2016 19:33:06 +0200 Subject: [PATCH 17/56] Update rolify and cancancan --- Gemfile.lock | 8 +- app/models/role.rb | 2 +- app/models/user.rb | 1 - config/initializers/rolify.rb | 2 +- ...33808_rename_roles_users_to_users_roles.rb | 5 + db/schema.rb | 693 +++++++++--------- 6 files changed, 359 insertions(+), 352 deletions(-) create mode 100644 db/migrate/20160226133808_rename_roles_users_to_users_roles.rb diff --git a/Gemfile.lock b/Gemfile.lock index a958697c..89700107 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,7 +92,7 @@ GEM byebug (3.1.2) columnize (~> 0.8) debugger-linecache (~> 1.2) - cancancan (1.8.4) + cancancan (1.13.1) capybara (2.2.1) mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -334,8 +334,8 @@ GEM railties (= 4.2.5.2) sprockets-rails rails-assets-date.format (1.2.3) - rails-assets-holderjs (2.9.1) - rails-assets-jquery (2.2.0) + rails-assets-holderjs (2.9.3) + rails-assets-jquery (2.2.1) rails-assets-jquery-smooth-scroll (1.7.2) rails-assets-jquery (>= 1.4.2) rails-assets-leaflet (0.7.7) @@ -380,7 +380,7 @@ GEM rest-client (1.7.3) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) - rolify (3.4.0) + rolify (5.0.0) rspec (3.0.0) rspec-core (~> 3.0.0) rspec-expectations (~> 3.0.0) diff --git a/app/models/role.rb b/app/models/role.rb index 77ffac2b..07c5b29e 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,6 +1,6 @@ class Role < ActiveRecord::Base belongs_to :resource, polymorphic: true - has_and_belongs_to_many :users + has_and_belongs_to_many :users, join_table: :users_roles scopify diff --git a/app/models/user.rb b/app/models/user.rb index f31beb29..4ca0418f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -29,7 +29,6 @@ class User < ActiveRecord::Base devise(*devise_modules) - has_and_belongs_to_many :roles has_many :openids attr_accessor :login diff --git a/config/initializers/rolify.rb b/config/initializers/rolify.rb index 30651dd0..14460ef6 100644 --- a/config/initializers/rolify.rb +++ b/config/initializers/rolify.rb @@ -4,5 +4,5 @@ Rolify.configure do |config| # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false # Enable this feature _after_ running rake db:migrate as it relies on the roles table - config.use_dynamic_shortcuts + # config.use_dynamic_shortcuts end diff --git a/db/migrate/20160226133808_rename_roles_users_to_users_roles.rb b/db/migrate/20160226133808_rename_roles_users_to_users_roles.rb new file mode 100644 index 00000000..6f8424b8 --- /dev/null +++ b/db/migrate/20160226133808_rename_roles_users_to_users_roles.rb @@ -0,0 +1,5 @@ +class RenameRolesUsersToUsersRoles < ActiveRecord::Migration + def change + rename_table :roles_users, :users_roles + end +end diff --git a/db/schema.rb b/db/schema.rb index 2ff3289c..e4f4d556 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,307 +11,310 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160201221411) do +ActiveRecord::Schema.define(version: 20160226133808) do create_table "ahoy_events", force: :cascade do |t| t.uuid "visit_id", limit: 16 - t.integer "user_id" - t.string "name" - t.text "properties" + t.integer "user_id", limit: 4 + t.string "name", limit: 255 + t.text "properties", limit: 65535 t.datetime "time" end - add_index "ahoy_events", ["time"], name: "index_ahoy_events_on_time" - add_index "ahoy_events", ["user_id"], name: "index_ahoy_events_on_user_id" - add_index "ahoy_events", ["visit_id"], name: "index_ahoy_events_on_visit_id" + add_index "ahoy_events", ["time"], name: "index_ahoy_events_on_time", using: :btree + add_index "ahoy_events", ["user_id"], name: "index_ahoy_events_on_user_id", using: :btree + add_index "ahoy_events", ["visit_id"], name: "index_ahoy_events_on_visit_id", using: :btree create_table "answers", force: :cascade do |t| - t.string "title" - t.datetime "created_at" - t.datetime "updated_at" + t.string "title", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "question_id", limit: 4 + t.text "options", limit: 65535, null: false + t.integer "answer_type", limit: 4, default: 0, null: false end create_table "campaigns", force: :cascade do |t| - t.integer "conference_id" - t.string "name" - t.string "utm_source" - t.string "utm_medium" - t.string "utm_term" - t.string "utm_content" - t.string "utm_campaign" + t.integer "conference_id", limit: 4 + t.string "name", limit: 255 + t.string "utm_source", limit: 255 + t.string "utm_medium", limit: 255 + t.string "utm_term", limit: 255 + t.string "utm_content", limit: 255 + t.string "utm_campaign", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "cfps", force: :cascade do |t| - t.date "start_date", null: false - t.date "end_date", null: false - t.datetime "created_at" - t.datetime "updated_at" - t.integer "program_id" + t.date "start_date", null: false + t.date "end_date", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "program_id", limit: 4 end create_table "comments", force: :cascade do |t| - t.string "title", limit: 50, default: "" - t.text "body" - t.integer "commentable_id" - t.string "commentable_type" - t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" - t.string "subject" - t.integer "parent_id" - t.integer "lft" - t.integer "rgt" + t.string "title", limit: 50, default: "" + t.text "body", limit: 16777215 + t.integer "commentable_id", limit: 4 + t.string "commentable_type", limit: 255 + t.integer "user_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "subject", limit: 255 + t.integer "parent_id", limit: 4 + t.integer "lft", limit: 4 + t.integer "rgt", limit: 4 end - add_index "comments", ["commentable_id"], name: "index_comments_on_commentable_id" - add_index "comments", ["commentable_type"], name: "index_comments_on_commentable_type" - add_index "comments", ["user_id"], name: "index_comments_on_user_id" + add_index "comments", ["commentable_id"], name: "index_comments_on_commentable_id", using: :btree + add_index "comments", ["commentable_type"], name: "index_comments_on_commentable_type", using: :btree + add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree create_table "commercials", force: :cascade do |t| - t.string "commercial_id" - t.string "commercial_type" - t.integer "commercialable_id" - t.string "commercialable_type" + t.string "commercial_id", limit: 255 + t.string "commercial_type", limit: 255 + t.integer "commercialable_id", limit: 4 + t.string "commercialable_type", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "url" + t.string "url", limit: 255 end create_table "conferences", force: :cascade do |t| - t.string "guid", null: false - t.string "title", null: false - t.string "short_title", null: false - t.string "timezone", null: false - t.string "html_export_path" - t.date "start_date", null: false - t.date "end_date", null: false - t.datetime "created_at" - t.datetime "updated_at" - t.string "logo_file_name" - t.string "logo_content_type" - t.integer "logo_file_size" + t.string "guid", limit: 255, null: false + t.string "title", limit: 255, null: false + t.string "short_title", limit: 255, null: false + t.string "timezone", limit: 255, null: false + t.string "html_export_path", limit: 255 + t.date "start_date", null: false + t.date "end_date", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "logo_file_name", limit: 255 + t.string "logo_content_type", limit: 255 + t.integer "logo_file_size", limit: 4 t.datetime "logo_updated_at" - t.boolean "use_dietary_choices", default: false - t.integer "revision" - t.boolean "use_vpositions", default: false - t.boolean "use_vdays", default: false - t.boolean "use_difficulty_levels", default: false + t.boolean "use_dietary_choices", default: false + t.integer "revision", limit: 4 + t.boolean "use_vpositions", default: false + t.boolean "use_vdays", default: false + t.boolean "use_difficulty_levels", default: false t.boolean "use_volunteers" - t.string "color" - t.text "events_per_week" - t.text "description" - t.integer "registration_limit", default: 0 + t.string "color", limit: 255 + t.text "events_per_week", limit: 65535 + t.text "description", limit: 65535 + t.integer "registration_limit", limit: 4, default: 0 end create_table "conferences_questions", id: false, force: :cascade do |t| - t.integer "conference_id" - t.integer "question_id" + t.integer "conference_id", limit: 4 + t.integer "question_id", limit: 4 end create_table "contacts", force: :cascade do |t| - t.string "social_tag" - t.string "email" - t.string "facebook" - t.string "googleplus" - t.string "twitter" - t.string "instagram" - t.integer "conference_id" + t.string "social_tag", limit: 255 + t.string "email", limit: 255 + t.string "facebook", limit: 255 + t.string "googleplus", limit: 255 + t.string "twitter", limit: 255 + t.string "instagram", limit: 255 + t.integer "conference_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "sponsor_email" + t.string "sponsor_email", limit: 255 end create_table "delayed_jobs", force: :cascade do |t| - t.integer "priority", default: 0, null: false - t.integer "attempts", default: 0, null: false - t.text "handler", null: false - t.text "last_error" + t.integer "priority", limit: 4, default: 0, null: false + t.integer "attempts", limit: 4, default: 0, null: false + t.text "handler", limit: 65535, null: false + t.text "last_error", limit: 65535 t.datetime "run_at" t.datetime "locked_at" t.datetime "failed_at" - t.string "locked_by" - t.string "queue" + t.string "locked_by", limit: 255 + t.string "queue", limit: 255 t.datetime "created_at" t.datetime "updated_at" end - add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority" + add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree create_table "dietary_choices", force: :cascade do |t| - t.integer "conference_id" - t.string "title", null: false - t.datetime "created_at" - t.datetime "updated_at" + t.integer "conference_id", limit: 4 + t.string "title", limit: 255, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "difficulty_levels", force: :cascade do |t| - t.string "title" - t.text "description" - t.string "color" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "program_id" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.string "color", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "program_id", limit: 4 end create_table "email_settings", force: :cascade do |t| - t.integer "conference_id" - t.boolean "send_on_registration", default: false - t.boolean "send_on_accepted", default: false - t.boolean "send_on_rejected", default: false - t.boolean "send_on_confirmed_without_registration", default: false - t.text "registration_body" - t.text "accepted_body" - t.text "rejected_body" - t.text "confirmed_without_registration_body" - t.datetime "created_at" - t.datetime "updated_at" - t.string "registration_subject" - t.string "accepted_subject" - t.string "rejected_subject" - t.string "confirmed_without_registration_subject" - t.boolean "send_on_conference_dates_updated", default: false - t.string "conference_dates_updated_subject" - t.text "conference_dates_updated_body" - t.boolean "send_on_conference_registration_dates_updated", default: false - t.string "conference_registration_dates_updated_subject" - t.text "conference_registration_dates_updated_body" - t.boolean "send_on_venue_updated", default: false - t.string "venue_updated_subject" - t.text "venue_updated_body" - t.boolean "send_on_cfp_dates_updated", default: false - t.boolean "send_on_program_schedule_public", default: false - t.string "program_schedule_public_subject" - t.string "cfp_dates_updated_subject" - t.text "program_schedule_public_body" - t.text "cfp_dates_updated_body" + t.integer "conference_id", limit: 4 + t.boolean "send_on_registration", default: false + t.boolean "send_on_accepted", default: false + t.boolean "send_on_rejected", default: false + t.boolean "send_on_confirmed_without_registration", default: false + t.text "registration_body", limit: 16777215 + t.text "accepted_body", limit: 16777215 + t.text "rejected_body", limit: 16777215 + t.text "confirmed_without_registration_body", limit: 16777215 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "registration_subject", limit: 255 + t.string "accepted_subject", limit: 255 + t.string "rejected_subject", limit: 255 + t.string "confirmed_without_registration_subject", limit: 255 + t.boolean "send_on_conference_dates_updated", default: false + t.string "conference_dates_updated_subject", limit: 255 + t.text "conference_dates_updated_body", limit: 65535 + t.boolean "send_on_conference_registration_dates_updated", default: false + t.string "conference_registration_dates_updated_subject", limit: 255 + t.text "conference_registration_dates_updated_body", limit: 65535 + t.boolean "send_on_venue_updated", default: false + t.string "venue_updated_subject", limit: 255 + t.text "venue_updated_body", limit: 65535 + t.boolean "send_on_cfp_dates_updated", default: false + t.boolean "send_on_program_schedule_public", default: false + t.string "program_schedule_public_subject", limit: 255 + t.string "cfp_dates_updated_subject", limit: 255 + t.text "program_schedule_public_body", limit: 65535 + t.text "cfp_dates_updated_body", limit: 65535 end create_table "event_types", force: :cascade do |t| - t.string "title", null: false - t.integer "length", default: 30 - t.integer "minimum_abstract_length", default: 0 - t.integer "maximum_abstract_length", default: 500 - t.string "color" - t.string "description" - t.integer "program_id" + t.string "title", limit: 255, null: false + t.integer "length", limit: 4, default: 30 + t.integer "minimum_abstract_length", limit: 4, default: 0 + t.integer "maximum_abstract_length", limit: 4, default: 500 + t.string "color", limit: 255 + t.string "description", limit: 255 + t.integer "program_id", limit: 4 end create_table "event_users", force: :cascade do |t| - t.integer "user_id" - t.integer "event_id" - t.string "event_role", default: "participant", null: false - t.string "comment" + t.integer "user_id", limit: 4 + t.integer "event_id", limit: 4 + t.string "event_role", limit: 255, default: "participant", null: false + t.string "comment", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "events", force: :cascade do |t| - t.string "guid", null: false - t.integer "event_type_id" - t.string "title", null: false - t.string "subtitle" - t.integer "time_slots" - t.string "state", default: "new", null: false - t.string "progress", default: "new", null: false - t.string "language" + t.string "guid", limit: 255, null: false + t.integer "event_type_id", limit: 4 + t.string "title", limit: 255, null: false + t.string "subtitle", limit: 255 + t.integer "time_slots", limit: 4 + t.string "state", limit: 255, default: "new", null: false + t.string "progress", limit: 255, default: "new", null: false + t.string "language", limit: 255 t.datetime "start_time" - t.text "abstract" - t.text "description" - t.boolean "public", default: true - t.string "logo_file_name" - t.string "logo_content_type" - t.integer "logo_file_size" + t.text "abstract", limit: 16777215 + t.text "description", limit: 16777215 + t.boolean "public", default: true + t.string "logo_file_name", limit: 255 + t.string "logo_content_type", limit: 255 + t.integer "logo_file_size", limit: 4 t.datetime "logo_updated_at" - t.text "proposal_additional_speakers" - t.integer "track_id" - t.integer "room_id" - t.datetime "created_at" - t.datetime "updated_at" + t.text "proposal_additional_speakers", limit: 16777215 + t.integer "track_id", limit: 4 + t.integer "room_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "require_registration" - t.integer "difficulty_level_id" - t.integer "week" - t.boolean "is_highlight", default: false - t.integer "program_id" + t.integer "difficulty_level_id", limit: 4 + t.integer "week", limit: 4 + t.boolean "is_highlight", default: false + t.integer "program_id", limit: 4 end create_table "events_registrations", id: false, force: :cascade do |t| - t.integer "registration_id" - t.integer "event_id" + t.integer "registration_id", limit: 4 + t.integer "event_id", limit: 4 end create_table "lodgings", force: :cascade do |t| - t.string "name" - t.text "description" - t.string "photo_file_name" - t.string "photo_content_type" - t.integer "photo_file_size" + t.string "name", limit: 255 + t.text "description", limit: 65535 + t.string "photo_file_name", limit: 255 + t.string "photo_content_type", limit: 255 + t.integer "photo_file_size", limit: 4 t.datetime "photo_updated_at" t.datetime "created_at" t.datetime "updated_at" - t.string "website_link" - t.integer "conference_id" + t.string "website_link", limit: 255 + t.integer "conference_id", limit: 4 end create_table "openids", force: :cascade do |t| - t.string "provider" - t.string "email" - t.string "uid" - t.integer "user_id" + t.string "provider", limit: 255 + t.string "email", limit: 255 + t.string "uid", limit: 255 + t.integer "user_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "photos", force: :cascade do |t| - t.text "description" - t.string "picture_file_name" - t.string "picture_content_type" - t.integer "picture_file_size" + t.text "description", limit: 65535 + t.string "picture_file_name", limit: 255 + t.string "picture_content_type", limit: 255 + t.integer "picture_file_size", limit: 4 t.datetime "picture_updated_at" - t.integer "conference_id" + t.integer "conference_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "programs", force: :cascade do |t| - t.integer "conference_id" - t.integer "rating", default: 0 - t.boolean "schedule_public", default: false - t.boolean "schedule_fluid", default: false + t.integer "conference_id", limit: 4 + t.integer "rating", limit: 4, default: 0 + t.boolean "schedule_public", default: false + t.boolean "schedule_fluid", default: false t.datetime "created_at" t.datetime "updated_at" end create_table "qanswers", force: :cascade do |t| - t.integer "question_id" - t.integer "answer_id" + t.integer "question_id", limit: 4 + t.integer "answer_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "qanswers_registrations", id: false, force: :cascade do |t| - t.integer "registration_id", null: false - t.integer "qanswer_id", null: false + t.integer "registration_id", limit: 4, null: false + t.integer "qanswer_id", limit: 4, null: false end create_table "question_types", force: :cascade do |t| - t.string "title" - t.datetime "created_at" - t.datetime "updated_at" + t.string "title", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "questions", force: :cascade do |t| - t.string "title" - t.integer "question_type_id" - t.integer "conference_id" + t.string "title", limit: 255 + t.integer "question_type_id", limit: 4 + t.integer "conference_id", limit: 4 t.boolean "global" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "registration_periods", force: :cascade do |t| - t.integer "conference_id" + t.integer "conference_id", limit: 4 t.date "start_date" t.date "end_date" t.datetime "created_at" @@ -319,65 +322,58 @@ ActiveRecord::Schema.define(version: 20160201221411) do end create_table "registrations", force: :cascade do |t| - t.integer "conference_id" + t.integer "conference_id", limit: 4 t.datetime "arrival" t.datetime "departure" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "dietary_choice_id" - t.text "other_dietary_choice" - t.text "other_special_needs" - t.boolean "attended", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "dietary_choice_id", limit: 4 + t.text "other_dietary_choice", limit: 16777215 + t.text "other_special_needs", limit: 16777215 + t.boolean "attended", default: false t.boolean "volunteer" - t.integer "user_id" - t.integer "week" + t.integer "user_id", limit: 4 + t.integer "week", limit: 4 end create_table "registrations_social_events", id: false, force: :cascade do |t| - t.integer "registration_id" - t.integer "social_event_id" + t.integer "registration_id", limit: 4 + t.integer "social_event_id", limit: 4 end create_table "registrations_vchoices", id: false, force: :cascade do |t| - t.integer "registration_id" - t.integer "vchoice_id" + t.integer "registration_id", limit: 4 + t.integer "vchoice_id", limit: 4 end create_table "roles", force: :cascade do |t| - t.string "name" - t.datetime "created_at" - t.datetime "updated_at" - t.string "description" - t.integer "resource_id" - t.string "resource_type" + t.string "name", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "description", limit: 255 + t.integer "resource_id", limit: 4 + t.string "resource_type", limit: 255 end - add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" - add_index "roles", ["name"], name: "index_roles_on_name" - - create_table "roles_users", id: false, force: :cascade do |t| - t.integer "role_id" - t.integer "user_id" - end - - add_index "roles_users", ["user_id", "role_id"], name: "index_roles_users_on_user_id_and_role_id" + add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree + add_index "roles", ["name"], name: "index_roles_on_name", using: :btree create_table "rooms", force: :cascade do |t| - t.string "guid", null: false - t.string "name", null: false - t.integer "size" - t.integer "venue_id", null: false + t.string "guid", limit: 255, null: false + t.string "name", limit: 255, null: false + t.integer "size", limit: 4 + t.integer "venue_id", limit: 4, null: false end create_table "social_events", force: :cascade do |t| - t.integer "conference_id" - t.string "title" - t.text "description" + t.integer "conference_id", limit: 4 + t.string "title", limit: 255 + t.text "description", limit: 65535 t.date "date" end create_table "splashpages", force: :cascade do |t| - t.integer "conference_id" + t.integer "conference_id", limit: 4 t.boolean "public" t.boolean "include_tracks" t.boolean "include_program" @@ -389,199 +385,206 @@ ActiveRecord::Schema.define(version: 20160201221411) do t.boolean "include_lodgings" t.datetime "created_at" t.datetime "updated_at" - t.boolean "include_cfp", default: false + t.boolean "include_cfp", default: false end create_table "sponsors", force: :cascade do |t| - t.string "name" - t.text "description" - t.string "website_url" - t.string "logo_file_name" - t.string "logo_content_type" - t.integer "logo_file_size" + t.string "name", limit: 255 + t.text "description", limit: 65535 + t.string "website_url", limit: 255 + t.string "logo_file_name", limit: 255 + t.string "logo_content_type", limit: 255 + t.integer "logo_file_size", limit: 4 t.datetime "logo_updated_at" - t.integer "sponsorship_level_id" - t.integer "conference_id" + t.integer "sponsorship_level_id", limit: 4 + t.integer "conference_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "sponsorship_levels", force: :cascade do |t| - t.string "title" - t.integer "conference_id" + t.string "title", limit: 255 + t.integer "conference_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "position" + t.integer "position", limit: 4 end create_table "subscriptions", force: :cascade do |t| - t.integer "user_id" - t.integer "conference_id" + t.integer "user_id", limit: 4 + t.integer "conference_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end create_table "targets", force: :cascade do |t| - t.integer "conference_id" - t.integer "campaign_id" + t.integer "conference_id", limit: 4 + t.integer "campaign_id", limit: 4 t.date "due_date" - t.integer "target_count" - t.string "unit" + t.integer "target_count", limit: 4 + t.string "unit", limit: 255 t.datetime "created_at" t.datetime "updated_at" end create_table "ticket_purchases", force: :cascade do |t| - t.integer "ticket_id" - t.integer "conference_id" - t.boolean "paid", default: false + t.integer "ticket_id", limit: 4 + t.integer "conference_id", limit: 4 + t.boolean "paid", default: false t.datetime "created_at" - t.integer "quantity", default: 1 - t.integer "user_id" + t.integer "quantity", limit: 4, default: 1 + t.integer "user_id", limit: 4 end create_table "tickets", force: :cascade do |t| - t.integer "conference_id" - t.string "title", null: false - t.text "description" - t.integer "price_cents", default: 0, null: false - t.string "price_currency", default: "USD", null: false + t.integer "conference_id", limit: 4 + t.string "title", limit: 255, null: false + t.text "description", limit: 65535 + t.integer "price_cents", limit: 4, default: 0, null: false + t.string "price_currency", limit: 255, default: "USD", null: false end create_table "tracks", force: :cascade do |t| - t.string "guid", null: false - t.string "name", null: false - t.text "description" - t.string "color" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "program_id" + t.string "guid", limit: 255, null: false + t.string "name", limit: 255, null: false + t.text "description", limit: 16777215 + t.string "color", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "program_id", limit: 4 end create_table "users", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + t.string "email", limit: 255, default: "", null: false + t.string "encrypted_password", limit: 255, default: "", null: false + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", limit: 4, default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.datetime "created_at" - t.datetime "updated_at" - t.string "name" + t.string "unconfirmed_email", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "name", limit: 255 t.boolean "email_public" - t.text "biography" - t.string "nickname" - t.string "affiliation" - t.string "avatar_file_name" - t.string "avatar_content_type" - t.integer "avatar_file_size" + t.text "biography", limit: 65535 + t.string "nickname", limit: 255 + t.string "affiliation", limit: 255 + t.string "avatar_file_name", limit: 255 + t.string "avatar_content_type", limit: 255 + t.integer "avatar_file_size", limit: 4 t.datetime "avatar_updated_at" - t.string "mobile" - t.string "tshirt" - t.string "languages" - t.text "volunteer_experience" - t.boolean "is_admin", default: false - t.string "username" - t.boolean "is_disabled", default: false + t.string "mobile", limit: 255 + t.string "tshirt", limit: 255 + t.string "languages", limit: 255 + t.text "volunteer_experience", limit: 65535 + t.boolean "is_admin", default: false + t.string "username", limit: 255 + t.boolean "is_disabled", default: false end - add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true - add_index "users", ["email"], name: "index_users_on_email", unique: true - add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true - add_index "users", ["username"], name: "index_users_on_username", unique: true + add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree + add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree + add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree + add_index "users", ["username"], name: "index_users_on_username", unique: true, using: :btree + + create_table "users_roles", id: false, force: :cascade do |t| + t.integer "role_id", limit: 4 + t.integer "user_id", limit: 4 + end + + add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree create_table "vchoices", force: :cascade do |t| - t.integer "vday_id" - t.integer "vposition_id" + t.integer "vday_id", limit: 4 + t.integer "vposition_id", limit: 4 end create_table "vdays", force: :cascade do |t| - t.integer "conference_id" + t.integer "conference_id", limit: 4 t.date "day" - t.text "description" - t.datetime "created_at" - t.datetime "updated_at" + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "venues", force: :cascade do |t| - t.string "guid" - t.string "name" - t.string "website" - t.text "description" - t.datetime "created_at" - t.datetime "updated_at" - t.string "photo_file_name" - t.string "photo_content_type" - t.integer "photo_file_size" + t.string "guid", limit: 255 + t.string "name", limit: 255 + t.string "website", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "photo_file_name", limit: 255 + t.string "photo_content_type", limit: 255 + t.integer "photo_file_size", limit: 4 t.datetime "photo_updated_at" - t.string "street" - t.string "postalcode" - t.string "city" - t.string "country" - t.string "latitude" - t.string "longitude" - t.integer "conference_id" + t.string "street", limit: 255 + t.string "postalcode", limit: 255 + t.string "city", limit: 255 + t.string "country", limit: 255 + t.string "latitude", limit: 255 + t.string "longitude", limit: 255 + t.integer "conference_id", limit: 4 end create_table "versions", force: :cascade do |t| - t.string "item_type", null: false - t.integer "item_id", null: false - t.string "event", null: false - t.string "whodunnit" - t.text "object" - t.text "object_changes" + t.string "item_type", limit: 255, null: false + t.integer "item_id", limit: 4, null: false + t.string "event", limit: 255, null: false + t.string "whodunnit", limit: 255 + t.text "object", limit: 16777215 + t.text "object_changes", limit: 16777215 t.datetime "created_at" end - add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id" + add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree create_table "visits", force: :cascade do |t| t.uuid "visitor_id", limit: 16 - t.string "ip" - t.text "user_agent" - t.text "referrer" - t.text "landing_page" - t.integer "user_id" - t.string "referring_domain" - t.string "search_keyword" - t.string "browser" - t.string "os" - t.string "device_type" - t.string "country" - t.string "region" - t.string "city" - t.string "utm_source" - t.string "utm_medium" - t.string "utm_term" - t.string "utm_content" - t.string "utm_campaign" + t.string "ip", limit: 255 + t.text "user_agent", limit: 65535 + t.text "referrer", limit: 65535 + t.text "landing_page", limit: 65535 + t.integer "user_id", limit: 4 + t.string "referring_domain", limit: 255 + t.string "search_keyword", limit: 255 + t.string "browser", limit: 255 + t.string "os", limit: 255 + t.string "device_type", limit: 255 + t.string "country", limit: 255 + t.string "region", limit: 255 + t.string "city", limit: 255 + t.string "utm_source", limit: 255 + t.string "utm_medium", limit: 255 + t.string "utm_term", limit: 255 + t.string "utm_content", limit: 255 + t.string "utm_campaign", limit: 255 t.datetime "started_at" end - add_index "visits", ["user_id"], name: "index_visits_on_user_id" + add_index "visits", ["user_id"], name: "index_visits_on_user_id", using: :btree create_table "votes", force: :cascade do |t| - t.integer "event_id" - t.integer "rating" - t.datetime "created_at" - t.datetime "updated_at" - t.integer "user_id" + t.integer "event_id", limit: 4 + t.integer "rating", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "user_id", limit: 4 end create_table "vpositions", force: :cascade do |t| - t.integer "conference_id" - t.string "title", null: false - t.text "description" - t.datetime "created_at" - t.datetime "updated_at" + t.integer "conference_id", limit: 4 + t.string "title", limit: 255, null: false + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end end From 34f2c1f39504d32ee7c1a833e3abb492a5200ef6 Mon Sep 17 00:00:00 2001 From: Stella Rouzi Date: Tue, 8 Mar 2016 00:19:54 +0200 Subject: [PATCH 18/56] new db/schema --- db/schema.rb | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index e4f4d556..b58e17f2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160226133808) do +ActiveRecord::Schema.define(version: 20160201221411) do create_table "ahoy_events", force: :cascade do |t| t.uuid "visit_id", limit: 16 @@ -26,12 +26,9 @@ ActiveRecord::Schema.define(version: 20160226133808) do add_index "ahoy_events", ["visit_id"], name: "index_ahoy_events_on_visit_id", using: :btree create_table "answers", force: :cascade do |t| - t.string "title", limit: 255 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "question_id", limit: 4 - t.text "options", limit: 65535, null: false - t.integer "answer_type", limit: 4, default: 0, null: false + t.string "title", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "campaigns", force: :cascade do |t| @@ -358,6 +355,13 @@ ActiveRecord::Schema.define(version: 20160226133808) do add_index "roles", ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree add_index "roles", ["name"], name: "index_roles_on_name", using: :btree + create_table "roles_users", id: false, force: :cascade do |t| + t.integer "role_id", limit: 4 + t.integer "user_id", limit: 4 + end + + add_index "roles_users", ["user_id", "role_id"], name: "index_roles_users_on_user_id_and_role_id", using: :btree + create_table "rooms", force: :cascade do |t| t.string "guid", limit: 255, null: false t.string "name", limit: 255, null: false @@ -494,13 +498,6 @@ ActiveRecord::Schema.define(version: 20160226133808) do add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree add_index "users", ["username"], name: "index_users_on_username", unique: true, using: :btree - create_table "users_roles", id: false, force: :cascade do |t| - t.integer "role_id", limit: 4 - t.integer "user_id", limit: 4 - end - - add_index "users_roles", ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree - create_table "vchoices", force: :cascade do |t| t.integer "vday_id", limit: 4 t.integer "vposition_id", limit: 4 From 64b825cebe6a9979ade1df06a63bd45a28169fa0 Mon Sep 17 00:00:00 2001 From: Nishanth Vijayan Date: Tue, 8 Mar 2016 16:50:30 +0530 Subject: [PATCH 19/56] Fix markdown editors bug #811 using asset gem. --- Gemfile | 4 + Gemfile.lock | 9 + app/assets/stylesheets/application.css | 2 +- .../stylesheets/bootstrap-markdown.min.css | 1 - .../assets/javascripts/bootstrap-markdown.js | 1293 ------------- vendor/assets/javascripts/markdown.js | 1616 ----------------- vendor/assets/javascripts/to-markdown.js | 184 -- 7 files changed, 14 insertions(+), 3095 deletions(-) delete mode 100644 app/assets/stylesheets/bootstrap-markdown.min.css delete mode 100644 vendor/assets/javascripts/bootstrap-markdown.js delete mode 100644 vendor/assets/javascripts/markdown.js delete mode 100644 vendor/assets/javascripts/to-markdown.js diff --git a/Gemfile b/Gemfile index a7d8548f..dd0a01da 100644 --- a/Gemfile +++ b/Gemfile @@ -82,6 +82,10 @@ source 'https://rails-assets.org' do gem 'rails-assets-waypoints' # for displaying maps gem 'rails-assets-leaflet' + # for markdown editors + gem 'rails-assets-bootstrap-markdown' + gem 'rails-assets-to-markdown' + gem 'rails-assets-markdown' end # as date picker diff --git a/Gemfile.lock b/Gemfile.lock index 995bf235..f9ad33e9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -331,16 +331,22 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 4.2.5.2) sprockets-rails + rails-assets-bootstrap (3.3.6) + rails-assets-jquery (>= 1.9.1, < 3) + rails-assets-bootstrap-markdown (2.10.0) + rails-assets-bootstrap (~> 3) rails-assets-date.format (1.2.3) rails-assets-holderjs (2.9.1) rails-assets-jquery (2.2.0) rails-assets-jquery-smooth-scroll (1.7.2) rails-assets-jquery (>= 1.4.2) rails-assets-leaflet (0.7.7) + rails-assets-markdown (0.5.0) rails-assets-momentjs (2.11.2) rails-assets-spectrum (1.8.0) rails-assets-jquery (>= 1.7.2) rails-assets-tinycolor (1.3.0) + rails-assets-to-markdown (1.3.0) rails-assets-trianglify (0.4.0) rails-assets-waypoints (4.0.0) rails-deprecated_sanitizer (1.0.3) @@ -540,13 +546,16 @@ DEPENDENCIES prawn_rails quiet_assets rails (~> 4.2) + rails-assets-bootstrap-markdown! rails-assets-date.format! rails-assets-holderjs! rails-assets-jquery-smooth-scroll! rails-assets-leaflet! + rails-assets-markdown! rails-assets-momentjs! rails-assets-spectrum! rails-assets-tinycolor! + rails-assets-to-markdown! rails-assets-trianglify! rails-assets-waypoints! rails-observers diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 9a771225..d0447354 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -10,7 +10,7 @@ *= require osem-splash *= require font-awesome *= require osem-fonts - *= require bootstrap-markdown.min + *= require bootstrap-markdown *= require bootstrap-datetimepicker *= require leaflet *= require bootstrap3-switch diff --git a/app/assets/stylesheets/bootstrap-markdown.min.css b/app/assets/stylesheets/bootstrap-markdown.min.css deleted file mode 100644 index ac71e895..00000000 --- a/app/assets/stylesheets/bootstrap-markdown.min.css +++ /dev/null @@ -1 +0,0 @@ -.md-editor{display:block;border:1px solid #ddd}.md-editor>.md-header,.md-editor .md-footer{display:block;padding:6px 4px;background:#fff}.md-editor>.md-header{margin: 0;}.md-editor>.md-preview{background:#fff;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;min-height:10px;overflow:auto}.md-editor>textarea{font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:14px;outline:0;outline:thin dotted \9;margin:0;display:block;padding:0;width:100%;border:0;border-top:1px dashed #ddd;border-bottom:1px dashed #ddd;border-radius:0;box-shadow:none;background:#eee}.md-editor>textarea:focus{box-shadow:none;background:#fff}.md-editor.active{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6)} \ No newline at end of file diff --git a/vendor/assets/javascripts/bootstrap-markdown.js b/vendor/assets/javascripts/bootstrap-markdown.js deleted file mode 100644 index 2256df64..00000000 --- a/vendor/assets/javascripts/bootstrap-markdown.js +++ /dev/null @@ -1,1293 +0,0 @@ -/* =================================================== - * bootstrap-markdown.js v2.5.0 - * http://github.com/toopay/bootstrap-markdown - * =================================================== - * Copyright 2013 Taufan Aditya - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - -!function ($) { - - "use strict"; // jshint ;_; - - - /* MARKDOWN CLASS DEFINITION - * ========================== */ - - var Markdown = function (element, options) { - // Class Properties - this.$ns = 'bootstrap-markdown' - this.$element = $(element) - this.$editable = {el:null, type:null,attrKeys:[], attrValues:[], content:null} - this.$options = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data(), this.$element.data('options')) - this.$oldContent = null - this.$isPreview = false - this.$editor = null - this.$textarea = null - this.$handler = [] - this.$callback = [] - this.$nextTab = [] - - this.showEditor() - } - - Markdown.prototype = { - - constructor: Markdown - - , __alterButtons: function(name,alter) { - var handler = this.$handler, isAll = (name == 'all'),that = this - - $.each(handler,function(k,v) { - var halt = true - if (isAll) { - halt = false - } else { - halt = v.indexOf(name) < 0 - } - - if (halt == false) { - alter(that.$editor.find('button[data-handler="'+v+'"]')) - } - }) - } - - , __buildButtons: function(buttonsArray, container) { - var i, - ns = this.$ns, - handler = this.$handler, - callback = this.$callback - - for (i=0;i', { - 'class': 'btn-group' - }) - - for (z=0;z ' - +this.__localize(btnText) - +'') - - // Register handler and callback - handler.push(buttonHandler) - callback.push(button.callback) - } - - // Attach the button group into container dom - container.append(btnGroupContainer) - } - } - - return container - } - , __setListener: function() { - // Set size and resizable Properties - var hasRows = typeof this.$textarea.attr('rows') != 'undefined', - maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5', - rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows - - this.$textarea.attr('rows',rowsVal) - if (this.$options.resize) { - this.$textarea.css('resize',this.$options.resize) - } - - this.$textarea - .on('focus', $.proxy(this.focus, this)) - .on('keypress', $.proxy(this.keypress, this)) - .on('keyup', $.proxy(this.keyup, this)) - .on('change', $.proxy(this.change, this)) - - if (this.eventSupported('keydown')) { - this.$textarea.on('keydown', $.proxy(this.keydown, this)) - } - - // Re-attach markdown data - this.$textarea.data('markdown',this) - } - - , __handle: function(e) { - var target = $(e.currentTarget), - handler = this.$handler, - callback = this.$callback, - handlerName = target.attr('data-handler'), - callbackIndex = handler.indexOf(handlerName), - callbackHandler = callback[callbackIndex] - - // Trigger the focusin - $(e.currentTarget).focus() - - callbackHandler(this) - - // Trigger onChange for each button handle - this.change(this); - - // Unless it was the save handler, - // focusin the textarea - if (handlerName.indexOf('cmdSave') < 0) { - this.$textarea.focus() - } - - e.preventDefault() - } - - , __localize: function(string) { - var messages = $.fn.markdown.messages, - language = this.$options.language - if ( - typeof messages !== 'undefined' && - typeof messages[language] !== 'undefined' && - typeof messages[language][string] !== 'undefined' - ) { - return messages[language][string]; - } - return string; - } - - , showEditor: function() { - var instance = this, - textarea, - ns = this.$ns, - container = this.$element, - originalHeigth = container.css('height'), - originalWidth = container.css('width'), - editable = this.$editable, - handler = this.$handler, - callback = this.$callback, - options = this.$options, - editor = $( '
', { - 'class': 'md-editor', - click: function() { - instance.focus() - } - }) - - // Prepare the editor - if (this.$editor == null) { - // Create the panel - var editorHeader = $('
', { - 'class': 'md-header btn-toolbar' - }) - - // Merge the main & additional button groups together - var allBtnGroups = [] - if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]) - if (options.additionalButtons.length > 0) allBtnGroups = allBtnGroups.concat(options.additionalButtons[0]) - - // Reduce and/or reorder the button groups - if (options.reorderButtonGroups.length > 0) { - allBtnGroups = allBtnGroups - .filter(function(btnGroup) { - return options.reorderButtonGroups.indexOf(btnGroup.name) > -1 - }) - .sort(function(a, b) { - if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1 - if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1 - return 0 - }) - } - - // Build the buttons - if (allBtnGroups.length > 0) { - editorHeader = this.__buildButtons([allBtnGroups], editorHeader) - } - - editor.append(editorHeader) - - // Wrap the textarea - if (container.is('textarea')) { - container.before(editor) - textarea = container - textarea.addClass('md-input') - editor.append(textarea) - } else { - var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(), - currentContent = $.trim(rawContent) - - // This is some arbitrary content that could be edited - textarea = $('