From c845dca9505baf7177d4ce5509f3759b1e38a03f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=AD=C3=B0ir=20Valberg=20Gu=C3=B0mundsson?= Date: Thu, 27 Apr 2017 00:23:03 +0200 Subject: [PATCH] Now with support for days! --- src/program/consumers.py | 9 +- src/program/models.py | 1 + .../static/js/event_instance_websocket.js | 376 ++++++++++++++---- src/program/templates/event_modal.html | 22 - src/program/templates/schedule_base.html | 14 +- src/program/templates/schedule_overview.html | 37 +- src/program/views.py | 3 + 7 files changed, 329 insertions(+), 133 deletions(-) delete mode 100644 src/program/templates/event_modal.html diff --git a/src/program/consumers.py b/src/program/consumers.py index c1994354..8c035a9a 100644 --- a/src/program/consumers.py +++ b/src/program/consumers.py @@ -13,7 +13,14 @@ class ScheduleConsumer(JsonWebsocketConsumer): def connect(self, message, **kwargs): camp_slug = message.http_session['campslug'] camp = Camp.objects.get(slug=camp_slug) - days = list(map(lambda x: {'repr': x.lower.strftime('%A %Y-%m-%d'), 'iso': x.lower.strftime('%Y-%m-%d')}, camp.get_days('camp'))) + days = list(map( + lambda day: + { 'repr': day.lower.strftime('%A %Y-%m-%d') + , 'iso': day.lower.strftime('%Y-%m-%d') + , 'day_name': day.lower.strftime('%A') + }, + camp.get_days('camp') + )) event_instances_query_set = EventInstance.objects.filter(event__camp=camp) event_instances = list(map(lambda x: x.to_json(), event_instances_query_set)) self.send({ diff --git a/src/program/models.py b/src/program/models.py index 063b0c6f..f76588a8 100644 --- a/src/program/models.py +++ b/src/program/models.py @@ -472,6 +472,7 @@ class EventInstance(CampRelatedModel): 'fg-color': '#fff' if self.event.event_type.light_text else '#000', 'event_type': self.event.event_type.slug, 'location': self.location.slug, + 'timeslots': self.timeslots, } if user and user.is_authenticated: diff --git a/src/program/static/js/event_instance_websocket.js b/src/program/static/js/event_instance_websocket.js index 7619ceab..0d18b218 100644 --- a/src/program/static/js/event_instance_websocket.js +++ b/src/program/static/js/event_instance_websocket.js @@ -1,6 +1,6 @@ const webSocketBridge = new channels.WebSocketBridge(); var modals = {}; -var EVENT_INSTANCES, DAYS; +var EVENT_INSTANCES = [], DAYS = [], CONFIG = {}; function toggleFavoriteButton(button) { if(button.getAttribute('data-state') == 'true') { @@ -27,65 +27,199 @@ function toggleFavoriteButton(button) { } } -webSocketBridge.connect('/schedule/'); -webSocketBridge.listen(function(payload, stream) { - if(payload['action'] == 'event_instance') { - event_instance_id = payload['event_instance']['id']; - modal = modals[event_instance_id]; - modal_title = modal.getElementsByClassName('modal-title')[0]; - modal_title.innerHTML = payload['event_instance']['title'] - modal_body_content = modal.getElementsByClassName('modal-body-content')[0]; - modal_body_content.innerHTML = payload['event_instance']['abstract']; - more_button = modal.getElementsByClassName('more-button')[0]; - more_button.setAttribute('href', payload['event_instance']['url']); - favorite_button = modal.getElementsByClassName('favorite-button')[0]; - if(payload['event_instance']['is_favorited'] !== undefined) { - favorite_button.setAttribute('data-state', payload['event_instance']['is_favorited']) - toggleFavoriteButton(favorite_button); - } else { - favorite_button.remove(); - } +function setup_websocket() { + webSocketBridge.connect('/schedule/'); + webSocketBridge.listen(function(payload, stream) { + if(payload['action'] == 'event_instance') { + event_instance_id = payload['event_instance']['id']; + modal = modals[event_instance_id]; + modal_title = modal.getElementsByClassName('modal-title')[0]; + modal_title.innerHTML = payload['event_instance']['title'] + modal_body_content = modal.getElementsByClassName('modal-body-content')[0]; + modal_body_content.innerHTML = payload['event_instance']['abstract']; + more_button = modal.getElementsByClassName('more-button')[0]; + more_button.setAttribute('href', payload['event_instance']['url']); + favorite_button = modal.getElementsByClassName('favorite-button')[0]; + if(payload['event_instance']['is_favorited'] !== undefined) { + favorite_button.setAttribute('data-state', payload['event_instance']['is_favorited']) + toggleFavoriteButton(favorite_button); + } else { + favorite_button.remove(); + } - speakers_div = modal.getElementsByClassName('speakers')[0]; - speakers = payload['event_instance']['speakers']; - for(speaker_id in speakers) { - var speaker = speakers[speaker_id]; - var speaker_li = document.createElement('li'); - var speaker_a = document.createElement('a'); - speaker_a.setAttribute('href', speaker['url']); - speaker_a.appendChild(document.createTextNode(speaker['name'])); - speaker_li.appendChild(speaker_a); - speakers_div.appendChild(speaker_li); - } - } - if(payload['action'] == 'init') { - EVENT_INSTANCES = payload['event_instances']; - DAYS = payload['days']; - - function findGetParameter(parameterName) { - var result = null, - tmp = []; - location.search - .substr(1) - .split("&") - .forEach(function (item) { - tmp = item.split("="); - if (tmp[0] === parameterName) { - result = decodeURIComponent(tmp[1]); - } - }); - return result; + speakers_div = modal.getElementsByClassName('speakers')[0]; + speakers = payload['event_instance']['speakers']; + for(speaker_id in speakers) { + var speaker = speakers[speaker_id]; + var speaker_li = document.createElement('li'); + var speaker_a = document.createElement('a'); + speaker_a.setAttribute('href', speaker['url']); + speaker_a.appendChild(document.createTextNode(speaker['name'])); + speaker_li.appendChild(speaker_a); + speakers_div.appendChild(speaker_li); + } } + if(payload['action'] == 'init') { + EVENT_INSTANCES = payload['event_instances']; + DAYS = payload['days']; + render(); + } + }); +} - var type_parameter = findGetParameter('type'); - var types = type_parameter != null ? type_parameter.split(',') : []; - var location_parameter = findGetParameter('location') - var locations = location_parameter != null ? location_parameter.split(',') : []; +function init(config) { + CONFIG = config; + setup_websocket(); + render(); +} - toggleFilterBoxes(types, locations); - render_schedule(types, locations); +function findGetParameter(parameterName) { + var result = null, + tmp = []; + location.search + .substr(1) + .split("&") + .forEach(function (item) { + tmp = item.split("="); + if (tmp[0] === parameterName) { + result = decodeURIComponent(tmp[1]); + } + }); + return result; +} + +function get_parameters() { + + var day_parameter = findGetParameter('day'); + var filter_day = day_parameter != null ? day_parameter.split(',') : []; + var type_parameter = findGetParameter('type'); + var filter_types = type_parameter != null ? type_parameter.split(',') : []; + var location_parameter = findGetParameter('location') + var filter_locations = location_parameter != null ? location_parameter.split(',') : []; + + return { + 'day': filter_day[0], + 'types': filter_types, + 'locations': filter_locations } -}); +} + +function render() { + parameters = get_parameters(); + toggleFilterBoxes(parameters['types'], parameters['locations']); + render_day_menu(parameters['day']); + + if(parameters['day'] != null) { + render_day(parameters['types'], parameters['locations'], parameters['day']); + } else { + render_schedule(parameters['types'], parameters['locations']); + } +} + +function render_day_menu(active_iso) { + var container = document.getElementById('schedule-days'); + container.innerHTML = ''; + + function set_btn_type(classList, primary) { + if(primary == true) { + classList.add('btn-primary'); + } else { + classList.add('btn-default'); + } + } + + var all_days = document.createElement('a'); + all_days.classList.add('btn'); + set_btn_type(all_days.classList, active_iso == null); + all_days.innerHTML = 'All days'; + all_days.addEventListener('click', function(e) { + setHistoryState({'day': 'all-days'}); + render(); + }); + container.appendChild(all_days); + + for(var day_id in DAYS) { + var day_link = document.createElement('a'); + day_link.classList.add('btn'); + set_btn_type(day_link.classList, DAYS[day_id]['iso'] == active_iso); + day_link.dataset.iso = DAYS[day_id]['iso']; + day_link.innerHTML = DAYS[day_id]['day_name']; + + day_link.addEventListener('click', function(e) { + setHistoryState({ + 'day': this.dataset.iso + }); + render(); + }); + + container.appendChild(day_link); + } +} + +function render_day(types, locations, day) { + + function hoursTohhmm(hours){ + var hour = Math.floor(Math.abs(hours)); + var minutes = Math.floor((Math.abs(hours) * 60) % 60); + if(hour > 24) { + hour = hour - 24; + } + return (hour < 10 ? "0" : "") + hour + ":" + (minutes < 10 ? "0" : "") + minutes; + } + + var event_instances = get_instances(types, locations, day); + var schedule_container = document.getElementById('schedule-container'); + schedule_container.innerHTML = ''; + + var day_table = document.createElement('table'); + schedule_container.appendChild(day_table); + day_table.classList.add('table'); + day_table.classList.add('day-table'); + day_table_body = document.createElement('tbody'); + day_table.appendChild(day_table_body); + + var array_length = (24*60)/CONFIG['schedule_timeslot_length_minutes']; + var timeslots_ = Array(array_length); + var timeslots = []; + for(var i=0; i 0) { + var type_part = 'type=' + types; + query = query + type_part + "&"; + } + + locations = locations == undefined ? findGetParameter('location') : locations.join(','); + if(locations != null && locations.length > 0) { + var location_part = 'location=' + locations; + query = query + location_part; + } + + history.replaceState({}, '', query); + +} + function toggleFilterBoxes(types, locations) { var type_input = Array.prototype.slice.call(document.querySelectorAll('.event-type-checkbox')); type_input.map(function(box) { if(types.includes(box.value)) { - box.checked = !box.checked; + box.checked = true; } return box; }); var location_input = Array.prototype.slice.call(document.querySelectorAll('.location-checkbox')); location_input.map(function(box) { if(locations.includes(box.value)) { - box.checked = !box.checked; + box.checked = true; } return box; }); diff --git a/src/program/templates/event_modal.html b/src/program/templates/event_modal.html deleted file mode 100644 index 4c80125d..00000000 --- a/src/program/templates/event_modal.html +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/src/program/templates/schedule_base.html b/src/program/templates/schedule_base.html index 4ab5a43a..ef950e7b 100644 --- a/src/program/templates/schedule_base.html +++ b/src/program/templates/schedule_base.html @@ -4,18 +4,8 @@ {% block program_content %}
-
- -
  • All days
  • -
    - {% for day in camp.camp_days %} - {% with month_padded=day.lower.date|date:"m" day_padded=day.lower.date|date:"d" %} - - {{ day.lower.date|date:"l" }} - - {% endwith %} - {% endfor %} -
    +
    +

    diff --git a/src/program/templates/schedule_overview.html b/src/program/templates/schedule_overview.html index 05da7044..012f44f6 100644 --- a/src/program/templates/schedule_overview.html +++ b/src/program/templates/schedule_overview.html @@ -7,36 +7,15 @@
    -{% comment %} -{% if eventinstances %} -{% for day in camp.camp_days %} - {{ day.lower.date|date:"D d/m" }}
    -
    - {% for eventinstance in eventinstances %} - {% if eventinstance.schedule_date == day.lower.date %} - - {{ eventinstance.when.lower|date:"H:i" }} - {{ eventinstance.when.upper|date:"H:i" }} - &#x{{ eventinstance.location.icon }}; -
    - {{ eventinstance.event.title }} -
    -
    - {% endif %} - {% endfor %} -
    -
    -{% endfor %} -{% else %} -

    No scheduled events for {{ camp.title }} yet!

    -{% endif %} -{% endcomment %} - -{% include "event_modal.html" %} + + {% endblock schedule_content %} diff --git a/src/program/views.py b/src/program/views.py index b3afb9d7..1e4c6c50 100644 --- a/src/program/views.py +++ b/src/program/views.py @@ -274,6 +274,9 @@ class ScheduleView(CampViewMixin, TemplateView): context['urlmonth'] = self.kwargs['month'] context['urlday'] = self.kwargs['day'] + context['schedule_timeslot_length_minutes'] = settings.SCHEDULE_TIMESLOT_LENGTH_MINUTES; + context['schedule_midnight_offset_hours'] = settings.SCHEDULE_MIDNIGHT_OFFSET_HOURS; + return context