Revamping filtering big time!
This commit is contained in:
parent
691c6533c3
commit
9071a9c524
|
@ -1,5 +1,6 @@
|
|||
from channels.generic.websockets import JsonWebsocketConsumer
|
||||
|
||||
from camps.models import Camp
|
||||
from .models import EventInstance, Favorite
|
||||
|
||||
|
||||
|
@ -10,7 +11,17 @@ class ScheduleConsumer(JsonWebsocketConsumer):
|
|||
return ['schedule_users']
|
||||
|
||||
def connect(self, message, **kwargs):
|
||||
self.send({"accept": True})
|
||||
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')))
|
||||
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({
|
||||
"accept": True,
|
||||
"event_instances": event_instances,
|
||||
"days": days,
|
||||
"action": "init"
|
||||
})
|
||||
|
||||
def raw_receive(self, message, **kwargs):
|
||||
content = self.decode_json(message['text'])
|
||||
|
|
|
@ -460,13 +460,18 @@ class EventInstance(CampRelatedModel):
|
|||
'event_slug': self.event.slug,
|
||||
'abstract': abstract,
|
||||
'from': self.when.lower.isoformat(),
|
||||
'to': self.when.lower.isoformat(),
|
||||
'to': self.when.upper.isoformat(),
|
||||
'url': str(self.event.get_absolute_url()),
|
||||
'id': self.id,
|
||||
'speakers': [
|
||||
{ 'name': speaker.name
|
||||
, 'url': str(speaker.get_absolute_url())
|
||||
} for speaker in self.event.speakers.all()]
|
||||
} for speaker in self.event.speakers.all()
|
||||
],
|
||||
'bg-color': self.event.event_type.color,
|
||||
'fg-color': '#fff' if self.event.event_type.light_text else '#000',
|
||||
'event_type': self.event.event_type.slug,
|
||||
'location': self.location.slug,
|
||||
}
|
||||
|
||||
if user and user.is_authenticated:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const webSocketBridge = new channels.WebSocketBridge();
|
||||
var modals = {};
|
||||
var EVENT_INSTANCES, DAYS;
|
||||
|
||||
function toggleFavoriteButton(button) {
|
||||
if(button.getAttribute('data-state') == 'true') {
|
||||
|
@ -27,9 +28,8 @@ function toggleFavoriteButton(button) {
|
|||
}
|
||||
|
||||
webSocketBridge.connect('/schedule/');
|
||||
webSocketBridge.socket.addEventListener('open', function() {
|
||||
webSocketBridge.send({action: 'init', camp_slug: '{{ camp.slug }}'});
|
||||
});
|
||||
//webSocketBridge.socket.addEventListener('open', function() {
|
||||
//});
|
||||
webSocketBridge.listen(function(payload, stream) {
|
||||
if(payload['action'] == 'event_instance') {
|
||||
event_instance_id = payload['event_instance']['id'];
|
||||
|
@ -60,8 +60,95 @@ webSocketBridge.listen(function(payload, stream) {
|
|||
speakers_div.appendChild(speaker_li);
|
||||
}
|
||||
}
|
||||
if(payload['action'] == 'init') {
|
||||
EVENT_INSTANCES = payload['event_instances'];
|
||||
console.log(EVENT_INSTANCES);
|
||||
DAYS = payload['days'];
|
||||
render_schedule([], []);
|
||||
}
|
||||
});
|
||||
|
||||
function render_schedule(types, locations) {
|
||||
var event_instances = get_instances(types, locations);
|
||||
var schedule_container = document.getElementById('schedule-container');
|
||||
schedule_container.innerHTML = "";
|
||||
|
||||
var cloned_days = DAYS.slice(0);
|
||||
|
||||
var rendered_days = cloned_days.map(function(day) {
|
||||
day_event_instances = event_instances.slice(0).filter(
|
||||
function(event_instance) {
|
||||
var event_day = event_instance['from'].slice(0, 10);
|
||||
return event_day == day['iso'];
|
||||
}
|
||||
);
|
||||
return render_day(day, day_event_instances);
|
||||
});
|
||||
|
||||
for(day_id in rendered_days) {
|
||||
schedule_container.appendChild(rendered_days[day_id]['label']);
|
||||
schedule_container.appendChild(rendered_days[day_id]['element']);
|
||||
}
|
||||
}
|
||||
|
||||
function render_day(day, event_instances) {
|
||||
var element = document.createElement('div');
|
||||
element.classList.add('schedule-day-row');
|
||||
var day_label = document.createElement('h4');
|
||||
day_label.innerHTML = day['repr'];
|
||||
element.appendChild(day_label);
|
||||
for(event_instance_id in event_instances) {
|
||||
var event_instance = event_instances[event_instance_id];
|
||||
var rendered_event_instance = render_event_instance(event_instance);
|
||||
element.appendChild(rendered_event_instance);
|
||||
}
|
||||
return {"label": day_label, "element": element};
|
||||
}
|
||||
|
||||
function render_event_instance(event_instance) {
|
||||
var element = document.createElement('a');
|
||||
element.setAttribute(
|
||||
'style',
|
||||
'background-color: ' + event_instance['bg-color'] +
|
||||
'; color: ' + event_instance['fg-color']);
|
||||
element.classList.add('event');
|
||||
element.dataset.eventInstanceId = event_instance['id'];
|
||||
|
||||
time_element = document.createElement('small');
|
||||
time_element.innerHTML = event_instance.from.slice(11, 16) + " - " + event_instance.to.slice(11, 16);
|
||||
|
||||
title_element = document.createElement('p');
|
||||
title_element.innerHTML = event_instance['title'];
|
||||
|
||||
element.appendChild(time_element);
|
||||
element.appendChild(title_element);
|
||||
element.onclick = openModal
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
function get_instances(types, locations) {
|
||||
var event_instances = EVENT_INSTANCES.slice(0);
|
||||
if(locations.length != 0) {
|
||||
event_instances = event_instances.filter(
|
||||
function(event_instance) {
|
||||
return locations.includes(event_instance['location']);
|
||||
}
|
||||
);
|
||||
}
|
||||
if(types.length != 0) {
|
||||
event_instances = event_instances.filter(
|
||||
function(event_instance) {
|
||||
console.log(event_instance['event_type']);
|
||||
console.log(types);
|
||||
console.log(event_instance['event_type'] in types);
|
||||
return types.includes(event_instance['event_type']);
|
||||
}
|
||||
);
|
||||
}
|
||||
return event_instances
|
||||
}
|
||||
|
||||
function openModal(e) {
|
||||
e.preventDefault();
|
||||
|
||||
|
@ -71,7 +158,7 @@ function openModal(e) {
|
|||
target = e.target.parentElement
|
||||
}
|
||||
|
||||
event_instance_id = target.dataset['eventinstanceId'];
|
||||
event_instance_id = target.dataset.eventInstanceId;
|
||||
|
||||
modal = modals[event_instance_id];
|
||||
|
||||
|
@ -88,12 +175,27 @@ function openModal(e) {
|
|||
webSocketBridge.send({action: 'get_event_instance', event_instance_id: event_instance_id})
|
||||
}
|
||||
|
||||
|
||||
function init_modals(event_class_name) {
|
||||
var event_elements = document.getElementsByClassName(event_class_name);
|
||||
|
||||
for (var event_id in event_elements) {
|
||||
event_element = event_elements.item(event_id);
|
||||
event_element.onclick = openModal
|
||||
if(event_element != null) {
|
||||
event_element.onclick = openModal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var filter = document.getElementById('filter')
|
||||
filter.addEventListener('change', function(e) {
|
||||
var type_input = Array.prototype.slice.call(document.querySelectorAll('.event-type-checkbox:checked'));
|
||||
var types = type_input.map(function(box) {
|
||||
return box.value
|
||||
})
|
||||
var location_input = Array.prototype.slice.call(document.querySelectorAll('.location-checkbox:checked'));
|
||||
var event_locations = location_input.map(function(box) {
|
||||
return box.value
|
||||
})
|
||||
|
||||
render_schedule(types, event_locations);
|
||||
});
|
||||
|
|
|
@ -4,37 +4,53 @@
|
|||
{% block program_content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<form method="get" id="filter" class="form-inline">
|
||||
<div class="schedule-days btn-group">
|
||||
<a href="{% url 'schedule_index' camp_slug=camp.slug %}" class="btn btn-default">
|
||||
<li>All days</li>
|
||||
</a>
|
||||
{% for day in camp.camp_days %}
|
||||
{% with month_padded=day.lower.date|date:"m" day_padded=day.lower.date|date:"d" %}
|
||||
<a href="{% url 'schedule_day' camp_slug=camp.slug year=day.lower.date.year month=day.lower.date|date:'m' day=day.lower.date|date:'d' %}" class="btn btn-{% if urlyear and urlyear|add:"0" == day.lower.date.year and urlmonth == month_padded and urlday == day_padded %}primary{% else %}default{% endif %}">
|
||||
{{ day.lower.date|date:"l" }}
|
||||
</a>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-sm-push-9 schedule-filter">
|
||||
<form id="filter" class="form-inline">
|
||||
<div class="form-group">
|
||||
<select id="day" name="day" class="form-control filter-control">
|
||||
<option value="">All Days</option>
|
||||
{% for day in camp.camp_days %}
|
||||
{% with month_padded=day.lower.date|date:"m" day_padded=day.lower.date|date:"d" %}
|
||||
<option
|
||||
value="{{ day.lower.date|date:"Y-m-d" }}"
|
||||
{% if urlyear and urlyear|add:"0" == day.lower.date.year and urlmonth == month_padded and urlday == day_padded %}
|
||||
selected
|
||||
{% endif %}>
|
||||
{{ day.lower.date|date:"l" }}
|
||||
</option>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div>
|
||||
<h4>Type:</h4>
|
||||
<ul>
|
||||
{% for type in camp.event_types %}
|
||||
<li>
|
||||
<input type="checkbox"
|
||||
name="event_type"
|
||||
value="{{ type.slug }}"
|
||||
class="form-control event-type-checkbox"/> {{ type.name }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<select id="event_type" name="event_type" class="form-control filter-control">
|
||||
<option value="">All Types</option>
|
||||
{% for type in camp.event_types %}
|
||||
<option value="{{ type.slug }}"{% if eventtype and eventtype == type %}selected{% endif %}>{{ type.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<select id="location" name="location" class="fa-select form-control filter-control">
|
||||
<option value=""> All Locations</option>
|
||||
{% for loc in camp.event_locations %}
|
||||
<option value="{{ loc.slug }}" {% if location and location == loc %}selected{% endif %}>&#x{{ loc.icon }}; {{ loc.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div>
|
||||
<h4>Location:</h4>
|
||||
<ul>
|
||||
{% for location in camp.event_locations %}
|
||||
<li>
|
||||
<input type="checkbox"
|
||||
name="locations"
|
||||
value="{{ location.slug }}"
|
||||
class="form-control location-checkbox"/> {{ location.name }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<a href="{% url 'ics_view' camp_slug=camp.slug %}{{ get_string }}" class="btn btn-default form-control filter-control">
|
||||
<i class="fa fa-calendar"></i> ICS
|
||||
|
@ -42,26 +58,23 @@
|
|||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-sm-9 col-sm-pull-3">
|
||||
{% block schedule_content %}
|
||||
{% endblock schedule_content %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
{% block schedule_content %}
|
||||
{% endblock schedule_content %}
|
||||
|
||||
{% url 'schedule_index' camp_slug=camp.slug as baseurl %}
|
||||
|
||||
<script>
|
||||
$('.filter-control').on('change', function() {
|
||||
var day = $('#day').val();
|
||||
var type = $('#event_type').val();
|
||||
var loc = $('#location').val();
|
||||
var url = "{{baseurl}}";
|
||||
|
||||
if(day) {
|
||||
url = url + day + '/';
|
||||
}
|
||||
|
||||
if(type != '' || loc != '') {
|
||||
url = url + '?';
|
||||
if(type != '') {
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
{% load staticfiles %}
|
||||
|
||||
{% block schedule_content %}
|
||||
|
||||
<div id="schedule-container"></div>
|
||||
|
||||
{% comment %}
|
||||
{% if eventinstances %}
|
||||
{% for day in camp.camp_days %}
|
||||
{{ day.lower.date|date:"D d/m" }} <br />
|
||||
|
@ -29,13 +33,10 @@
|
|||
{% else %}
|
||||
<h2>No scheduled events for {{ camp.title }} yet!</h2>
|
||||
{% endif %}
|
||||
{% endcomment %}
|
||||
|
||||
{% include "event_modal.html" %}
|
||||
<script src="{% static "channels/js/websocketbridge.js" %}"></script>
|
||||
<script src="{% static "js/event_instance_websocket.js" %}"></script>
|
||||
<script>
|
||||
init_modals('event');
|
||||
</script>
|
||||
|
||||
|
||||
{% endblock schedule_content %}
|
||||
|
|
|
@ -89,10 +89,6 @@ a, a:active, a:focus {
|
|||
|
||||
|
||||
/* btn-group */
|
||||
.btn-group .btn {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.btn-group .btn:last-of-type {
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
|
@ -161,6 +157,7 @@ footer {
|
|||
min-height: 100px;
|
||||
flex-grow: 1;
|
||||
border: 1px solid black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.event-td {
|
||||
|
@ -207,3 +204,31 @@ footer {
|
|||
padding: 5px !important;
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.schedule-filter ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 520px) {
|
||||
.schedule-filter {
|
||||
border-left: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.schedule-days {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.schedule-days a {
|
||||
display: inline;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.schedule-day-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue