diff --git a/app/controllers/admin/commercials_controller.rb b/app/controllers/admin/commercials_controller.rb index f13b4322..3c694246 100644 --- a/app/controllers/admin/commercials_controller.rb +++ b/app/controllers/admin/commercials_controller.rb @@ -49,6 +49,26 @@ module Admin end end + ## + # Received a file from user + # Reads file and creates commercial for event + # File content example: + # EventID:MyURL + def mass_upload + errors = Commercial.read_file(params[:file]) if params[:file] + + if errors.all? { |_k, v| v.blank? } + flash[:notice] = 'Successfully added commercials.' + else + errors_text = '' + errors_text << 'Unable to find event with ID: ' + errors[:no_event].join(', ') + '. ' if errors[:no_event].any? + errors_text << 'There were some errors: ' + errors[:validation_errors].join('. ') if errors[:validation_errors].any? + + flash[:error] = errors_text + end + redirect_to :back + end + private def commercial_params diff --git a/app/models/commercial.rb b/app/models/commercial.rb index 0976fe44..ad9597e4 100644 --- a/app/models/commercial.rb +++ b/app/models/commercial.rb @@ -5,7 +5,7 @@ class Commercial < ApplicationRecord has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id } - validates :url, presence: true + validates :url, presence: true, uniqueness: { scope: :commercialable } validates :url, format: URI::regexp(%w(http https)) validate :valid_url @@ -20,6 +20,29 @@ class Commercial < ApplicationRecord end end + def self.read_file(file) + errors = {} + errors[:no_event] = [] + errors[:validation_errors] = [] + + file.read.each_line do |line| + # Get the event id (text before :) + id = line.match(/:/).pre_match.to_i + # Get the commercial url (text after :) + url = line.match(/:/).post_match + event = Event.find_by(id: id) + + # Go to next event, if the event is not found + errors[:no_event] << id && next unless event + + commercial = event.commercials.new(url: url) + unless commercial.save + errors[:validation_errors] << "Could not create commercial for event with ID #{event.id} (" + commercial.errors.full_messages.to_sentence + ')' + end + end + errors + end + private def valid_url diff --git a/app/views/admin/events/index.html.haml b/app/views/admin/events/index.html.haml index f8b58b63..be7abe05 100644 --- a/app/views/admin/events/index.html.haml +++ b/app/views/admin/events/index.html.haml @@ -4,37 +4,60 @@ %h1 Events = "(#{@events.length})" if @events.any? - .pull-right + + .btn-group.pull-right + %button.btn.btn-primary{ 'data-toggle' => 'modal', 'data-target' => '#mass-commercials-modal', title: 'Mass import of commercials for events' } + Add Commercials + - if can? :create, Event - =link_to 'Add Event', new_admin_conference_program_event_path(@conference.short_title), class: 'button btn btn-default btn-info' + = link_to 'Add Event', new_admin_conference_program_event_path(@conference.short_title), class: 'button btn btn-default btn-info' + - if can? :read, Event .btn-group - .btn-group - %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } - Export PDF - %span.caret - %ul.dropdown-menu{ role: 'menu' } - %li= link_to 'All Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all') - %li= link_to 'Confirmed Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'confirmed') - %li= link_to 'All Events with Comments', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all_with_comments') - .btn-group - %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } - Export CSV - %span.caret - %ul.dropdown-menu{ role: 'menu' } - %li= link_to 'All', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all') - %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'confirmed') - %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all_with_comments') - .btn-group - %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } - Export XLS - %span.caret - %ul.dropdown-menu{ role: 'menu' } - %li= link_to 'All', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all') - %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'confirmed') - %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all_with_comments') + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export PDF + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all') + %li= link_to 'Confirmed Events', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'confirmed') + %li= link_to 'All Events with Comments', admin_conference_program_events_path(@conference.short_title, format: :pdf, event_export_option: 'all_with_comments') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export CSV + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'confirmed') + %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :csv, event_export_option: 'all_with_comments') + .btn-group + %button.btn.btn-default.dropdown-toggle{ 'data-toggle' => 'dropdown', type: 'button', class: 'btn btn-success' } + Export XLS + %span.caret + %ul.dropdown-menu{ role: 'menu' } + %li= link_to 'All', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all') + %li= link_to 'Confirmed', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'confirmed') + %li= link_to 'All with Comments', admin_conference_program_events_path(@conference.short_title, format: :xlsx, event_export_option: 'all_with_comments') + %p.text-muted All the submissions of your speakers + +.modal#mass-commercials-modal + .modal-dialog + .modal-content + .modal-header + %h1 Add commercials to events + .text-muted + Upload your file with data in the following format: + %b Event_ID:Commercial_Link + , eg. + %br + %b 11:https://youtube.com/myvideo + + .modal-body + = semantic_form_for '', url: mass_upload_commercials_admin_conference_program_path(@conference.short_title), method: :post do |f| + = f.input 'file', as: :file + .modal-footer + = f.submit 'Add', class: 'btn btn-primary' .row .col-md-4 = render partial: 'admin/conferences/doughnut_chart', locals: { title: 'Events state', data: @event_distribution } diff --git a/config/routes.rb b/config/routes.rb index 33a92a48..4e2fca74 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,6 +98,7 @@ Osem::Application.routes.draw do end resources :event_types resources :difficulty_levels + post 'mass_upload_commercials' => 'commercials#mass_upload' resources :events do member do patch :toggle_attendance diff --git a/spec/factories/commercials.rb b/spec/factories/commercials.rb index 2578d1cd..cf865348 100644 --- a/spec/factories/commercials.rb +++ b/spec/factories/commercials.rb @@ -2,7 +2,7 @@ FactoryGirl.define do factory :commercial do - url 'https://www.youtube.com/watch?v=BTTygyxuGj8' + sequence(:url) { |n| "https://www.youtube.com/watch?v=BTTygyxuGj#{n}" } factory :conference_commercial do association :commercialable, factory: :conference diff --git a/spec/features/commercials_spec.rb b/spec/features/commercials_spec.rb index 65efa0b6..d460a725 100644 --- a/spec/features/commercials_spec.rb +++ b/spec/features/commercials_spec.rb @@ -98,7 +98,8 @@ feature Commercial do scenario 'does not update a commercial of an event with invalid data', feature: true, versioning: true, js: true do commercial = create(:commercial, commercialable_id: event.id, - commercialable_type: 'Event') + commercialable_type: 'Event', + url: 'https://www.youtube.com/watch?v=BTTygyxuGj8') visit edit_conference_program_proposal_path(conference.short_title, event.id) click_link 'Commercials' fill_in "commercial_url_#{commercial.id}", with: 'invalid_commercial_url'