From a3942935007d4bc2446ad89fe8c86dfc7ba3566b Mon Sep 17 00:00:00 2001 From: Ana Date: Sun, 31 Jul 2016 18:41:27 +0200 Subject: [PATCH] Do not use JS to initialize the schedule - Only use JS for the drag&drop functionality and to the set/alter the time and rooms of the EventSchedule object. - Introduce has_many :events, through: :event_schedules association to get unscheduled event easily --- app/assets/javascripts/osem-schedule.js | 93 ++++++-------------- app/controllers/admin/schedule_controller.rb | 5 +- app/controllers/schedules_controller.rb | 10 ++- app/models/event.rb | 23 ----- app/models/program.rb | 4 - app/models/schedule.rb | 1 + app/serializers/event_serializer.rb | 1 - app/views/admin/schedule/_day_tab.html.haml | 15 +++- app/views/admin/schedule/_event.html.haml | 13 +++ app/views/admin/schedule/show.html.haml | 4 +- spec/models/event_spec.rb | 21 ----- spec/models/schedule_spec.rb | 1 + 12 files changed, 66 insertions(+), 125 deletions(-) create mode 100644 app/views/admin/schedule/_event.html.haml diff --git a/app/assets/javascripts/osem-schedule.js b/app/assets/javascripts/osem-schedule.js index 87aed96c..146b66b8 100644 --- a/app/assets/javascripts/osem-schedule.js +++ b/app/assets/javascripts/osem-schedule.js @@ -1,76 +1,14 @@ -var conference; // Should be initialize in Schedule.loadEvents -var schedule_id; // Should be initialize in Schedule.loadEvents +var conference; // Should be initialize in Schedule.initialize +var schedule_id; // Should be initialize in Schedule.initialize var Schedule = { - loadEvents: function(conference_param, schedule_id_param) { + initialize: function(conference_param, schedule_id_param) { conference = conference_param; schedule_id = schedule_id_param; - var url = '/admin/conference/' + conference + '/program/events'; - var callback = function(data) { - $.each(data, function(key, val) { - Schedule.newEvent(val); - }); - }; - $.getJSON(url, callback); - }, - newEvent: function(vars) { - var height = (vars["length"] / 15 * 58) - 23; // this height fits the room cells - var lines = Math.floor((height - 7) / 23); // subtracting the padding before calculate the number of lines - var newEvent = $('
' - + '
' - + 'X' - + vars["title"] + '
'); - newEvent.attr("id", "event-" + vars["guid"]); - newEvent.attr("guid", vars["guid"]); - newEvent.css("height", height); - newEvent.css('background-color',vars["track_color"]); - newEvent.css('color',vars["track_text_color"]); - var date = "none"; - var room = "none" - var time = "none"; - for (i = 0; i < vars["event_schedules"].length; i++) { - event_schedule = vars["event_schedules"][i]; - if(event_schedule["schedule_id"] == schedule_id){ - room = event_schedule["room_guid"]; - var d = new Date(event_schedule["start_time"]); - date = d.getUTCFullYear() + "-" - + ('0' + (d.getUTCMonth() +1)).slice(-2) + '-' - + ('0' + d.getUTCDate()).slice(-2); - minutes = d.getUTCMinutes(); - time = d.getUTCHours() + ':' + (minutes == 0 ? '00' : minutes); - console.log("date: " + d); - newEvent.attr("room", room); - newEvent.attr("date", date); - newEvent.attr("hour", time); - } - } - newEvent.draggable({ - snap: '.schedule-room-slot', - revertDuration: 200, - revert: function (event, ui) { - console.log(event.attr); - return !event; - }, - stop: function(event, ui) { - this._originalPosition = this._originalPosition || ui.originalPosition; - ui.helper.animate( this._originalPosition ); - }, - opacity: 0.7, - snapMode: "inner", - zIndex: 2 - }); - if (date == "none" || room == "none") { - newEvent.find(".schedule-event-delete-button").hide(); - $('.unscheduled-events').append(newEvent); - } else { - var element = "[date='" + date +"'][hour='" + time + "'][room-guid='" + room + "']"; - $(element).append(newEvent); - } }, remove: function(element) { var e = $("#" + element); var unscheduled = $(".unscheduled-events"); - var url = '/admin/conference/' + conference + '/schedule/' + schedule_id; var params = { event: e.attr("guid"), @@ -92,7 +30,7 @@ var Schedule = { dataType : 'json' }); }, - save: function (event_id, room_id, date, time) { + add: function (event_id, room_id, date, time) { var url = '/admin/conference/' + conference + '/schedule/' + schedule_id; var params = { event: event_id, @@ -116,6 +54,27 @@ var Schedule = { }; $(document).ready( function() { + // hide the remove button for unscheduled events + $('.unscheduled-events .schedule-event-delete-button').hide(); + + // set events as draggable + $('.schedule-event').draggable({ + snap: '.schedule-room-slot', + revertDuration: 200, + revert: function (event, ui) { + console.log(event.attr); + return !event; + }, + stop: function(event, ui) { + this._originalPosition = this._originalPosition || ui.originalPosition; + ui.helper.animate( this._originalPosition ); + }, + opacity: 0.7, + snapMode: "inner", + zIndex: 2 + }); + + // set room cells as droppable $('.schedule-room-slot').droppable({ accept: '.schedule-event', tolerance: "pointer", @@ -128,7 +87,7 @@ $(document).ready( function() { $(ui.draggable).css("left", 0); $(ui.draggable).css("top", 0); $(this).css("background-color", "#ffffff"); - Schedule.save(myId, myRoom, myDate, myTime); + Schedule.add(myId, myRoom, myDate, myTime); }, over: function(event, ui) { $(this).css("background-color", "#009ED8"); diff --git a/app/controllers/admin/schedule_controller.rb b/app/controllers/admin/schedule_controller.rb index be3d4b04..569310ce 100644 --- a/app/controllers/admin/schedule_controller.rb +++ b/app/controllers/admin/schedule_controller.rb @@ -21,6 +21,9 @@ module Admin def show @schedule_id = params[:id].to_i + schedule = Schedule.find(@schedule_id) + @event_schedules = schedule.event_schedules + @unscheduled_events = @program.events.confirmed - schedule.events @selected_schedule_id = @conference.program.selected_schedule.try(:id) @dates = @conference.start_date..@conference.end_date @rooms = (@venue && @venue.rooms.any?) ? @venue.rooms : [Room.new(name: 'No Rooms!', size: 0)] @@ -44,7 +47,7 @@ module Admin error_message = "Could not find event GUID: #{params[:event]}" end - event_schedule = event.event_schedule(params[:schedule]) + event_schedule = event.event_schedules.find_by(schedule_id: params[:schedule]) if params[:date] == 'none' event_schedule.destroy if event_schedule.present? diff --git a/app/controllers/schedules_controller.rb b/app/controllers/schedules_controller.rb index b0cc3dd0..4054d52f 100644 --- a/app/controllers/schedules_controller.rb +++ b/app/controllers/schedules_controller.rb @@ -6,11 +6,11 @@ class SchedulesController < ApplicationController def show @rooms = @conference.venue.rooms if @conference.venue - unless @program.selected_schedule.present? && @program.events.scheduled(@program.selected_schedule.id).any? + schedules = @program.selected_event_schedules + unless schedules redirect_to events_conference_schedule_path(@conference.short_title) end - schedules = @program.selected_event_schedules @events_xml = schedules.map(&:event).group_by{ |event| event.scheduled_start_time.to_date } if schedules @dates = @conference.start_date..@conference.end_date @step_minutes = EventType::LENGTH_STEP.minutes @@ -32,7 +32,11 @@ class SchedulesController < ApplicationController @events_schedules = @program.selected_event_schedules @events_schedules = [] unless @events_schedules - @unscheduled_events = @program.events.unscheduled(@program.selected_schedule.id) + @unscheduled_events = if @program.selected_schedule + @program.events.confirmed - @program.selected_schedule.events + else + @program.events.confirmed + end day = @conference.current_conference_day @tag = day.strftime('%Y-%m-%d') if day diff --git a/app/models/event.rb b/app/models/event.rb index ea72a6c1..29c3810f 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -78,15 +78,6 @@ class Event < ActiveRecord::Base selected_event_schedule.present? end - ## - # Checkes if the event has a start_time and a room for the given schedule - # (given by its id) or for the selected one if there is any. - # ====Returns - # * +true+ or +false+ - def unscheduled?(schedule_id) - state == 'confirmed' && !event_schedule(schedule_id).present? - end - def registration_possible? return false unless require_registration && state == 'confirmed' return true if max_attendees.nil? @@ -138,15 +129,6 @@ class Event < ActiveRecord::Base end end - def as_json(options={}) - json = super({ include: { event_schedules: { methods: [:room_guid] } } }.merge(options)) - json[:track_color] = track.try(:color) || '#FFFFFF' - json[:track_text_color] = ApplicationController.helpers.contrast_color(json[:track_color]) - json[:length] = event_type.try(:length) || EventType::LENGTH_STEP - - json - end - def transition_possible?(transition) self.class.state_machine.events_for(current_state).include?(transition) end @@ -263,11 +245,6 @@ class Event < ActiveRecord::Base selected_event_schedule.try(:start_time) end - # returns the event_schedule for this event and the schedule given in case that it exists - def event_schedule(schedule_id) - event_schedules.find_by(schedule_id: schedule_id) - end - # returns the event_schedule for this event and for the selected_schedule def selected_event_schedule event_schedules.find_by(schedule_id: program.try(:selected_schedule_id)) diff --git a/app/models/program.rb b/app/models/program.rb index 6b8f4aa9..280471a2 100644 --- a/app/models/program.rb +++ b/app/models/program.rb @@ -32,10 +32,6 @@ class Program < ActiveRecord::Base joins(:event_schedules).where('event_schedules.schedule_id = ?', schedule_id) end - def unscheduled(schedule_id) - select{ |e| e.unscheduled?(schedule_id) } - end - def highlights where(state: :confirmed, is_highlight: true) end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index c23351fe..2254ebc9 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -1,4 +1,5 @@ class Schedule < ActiveRecord::Base belongs_to :program has_many :event_schedules, dependent: :destroy + has_many :events, through: :event_schedules end diff --git a/app/serializers/event_serializer.rb b/app/serializers/event_serializer.rb index 2984706c..f9c0e2a6 100644 --- a/app/serializers/event_serializer.rb +++ b/app/serializers/event_serializer.rb @@ -34,7 +34,6 @@ class EventSerializer < ActiveModel::Serializer end end - # FIXME: duplicated logic from Event#as_json def length object.event_type.try(:length) || EventType::LENGTH_STEP end diff --git a/app/views/admin/schedule/_day_tab.html.haml b/app/views/admin/schedule/_day_tab.html.haml index fa16e0e1..2b041f8a 100644 --- a/app/views/admin/schedule/_day_tab.html.haml +++ b/app/views/admin/schedule/_day_tab.html.haml @@ -1,13 +1,20 @@ +- date_event_schedules = @event_schedules.select{ |e| e.start_time.to_date.eql? date } .row - @rooms.each do |room| .col-md-2.col-xs-6 .room-name + - room_date_event_schedules = date_event_schedules.select{ |e| e.room == room } = room.name - (9*4..18*4).each do |slot| - hour = slot / 4 - - time = (15 * (slot % 4) == 0) ? '00' : 15 * (slot % 4) - .schedule-room-slot{ id: "schedule-room-#{room.guid}-#{hour}-#{time}", | + - minutes = (15 * (slot % 4) == 0) ? '00' : 15 * (slot % 4) + - time = "#{hour}:#{minutes}" + .schedule-room-slot{ id: "schedule-room-#{room.guid}-#{hour}-#{minutes}", | "room-guid" => room.guid, | - hour: "#{hour}:#{time}", | + hour: time, | date: date} - = "#{hour}:#{time}" + .div + = time + - event_schedules = room_date_event_schedules.select{ |e| (e.start_time.hour.to_s + e.start_time.strftime(':%M')).eql? time } + - if event_schedules.any? + = render partial: 'event', locals: { event: event_schedules.first.event } diff --git a/app/views/admin/schedule/_event.html.haml b/app/views/admin/schedule/_event.html.haml new file mode 100644 index 00000000..62801e50 --- /dev/null +++ b/app/views/admin/schedule/_event.html.haml @@ -0,0 +1,13 @@ +- cells_length = event.event_type.length / EventType::LENGTH_STEP +/ this height fits the room cells +- height = (cells_length * 58) - 23 +/ subtracting the padding before calculate the number of lines +- lines = (height - 7) / 23 +- color = event.track.try(:color).present? ? event.track.try(:color) : 'FFFFFF' +.schedule-event{ style: "height: #{height}px; background-color: #{color}; color: #{contrast_color(color)}", | + id: "event-#{event.guid}", | + guid: event.guid, | + length: cells_length } + .schedule-event-text{ style: "-webkit-line-clamp: #{lines}; height: #{lines * 23}px;"} + %span.schedule-event-delete-button{ onclick: "Schedule.remove(\'event-#{event.guid}\');" } X + = event.title diff --git a/app/views/admin/schedule/show.html.haml b/app/views/admin/schedule/show.html.haml index dc26bb73..5c763b76 100644 --- a/app/views/admin/schedule/show.html.haml +++ b/app/views/admin/schedule/show.html.haml @@ -17,6 +17,8 @@ .h4 Unscheduled events .unscheduled-events + - @unscheduled_events.each do |e| + = render partial: 'event', locals: { event: e } .col-md-10 %ul.nav.nav-tabs - @dates.each do |date| @@ -30,5 +32,5 @@ :javascript $(document).ready( function() { - Schedule.loadEvents("#{@conference.short_title}", "#{@schedule_id}"); + Schedule.initialize("#{@conference.short_title}", "#{@schedule_id}"); }); diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 2a0b4173..f9c46559 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -259,27 +259,6 @@ describe Event do end end - describe '#as_json' do - it 'adds the event\'s track_color, track_text_color and length' do - create(:event_schedule, event: event) - event.track = create(:track, color: '#efefef') - json_hash = event.as_json - - expect(json_hash[:track_color]).to eq('#EFEFEF') - expect(json_hash[:track_text_color]).to eq('black') - expect(json_hash[:length]).to eq(30) - end - - it 'uses correct default values for track_color, track_text_color and length' do - event.event_type = nil - json_hash = event.as_json - - expect(json_hash[:track_color]).to eq('#FFFFFF') - expect(json_hash[:track_text_color]).to eq('black') - expect(json_hash[:length]).to eq(15) - end - end - describe '#transition_possible?(transition)' do shared_examples 'transition_possible?(transition)' do |state, transition, expected| it "returns #{expected} for #{transition} transition, when the event is #{state}}" do diff --git a/spec/models/schedule_spec.rb b/spec/models/schedule_spec.rb index 85d155c0..6d1f7346 100644 --- a/spec/models/schedule_spec.rb +++ b/spec/models/schedule_spec.rb @@ -5,5 +5,6 @@ describe Schedule do describe 'association' do it { should belong_to(:program) } it { should have_many(:event_schedules).dependent(:destroy) } + it { should have_many(:events).through(:event_schedules) } end end