Adding modals and websockets to day view.
This commit is contained in:
parent
c6c94fd65e
commit
f7749adb23
99
src/program/static/js/event_instance_websocket.js
Normal file
99
src/program/static/js/event_instance_websocket.js
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
const webSocketBridge = new channels.WebSocketBridge();
|
||||||
|
var modals = {};
|
||||||
|
|
||||||
|
function toggleFavoriteButton(button) {
|
||||||
|
if(button.getAttribute('data-state') == 'true') {
|
||||||
|
favorite_button.classList.remove('btn-success');
|
||||||
|
favorite_button.classList.add('btn-danger');
|
||||||
|
favorite_button.innerHTML = '<i class="fa fa-minus"></i> Remove favorite';
|
||||||
|
|
||||||
|
favorite_button.onclick = function(e) {
|
||||||
|
button.setAttribute('data-state', 'false')
|
||||||
|
webSocketBridge.send({action: 'unfavorite', event_instance_id: event_instance_id});
|
||||||
|
toggleFavoriteButton(button)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
favorite_button.classList.remove('btn-danger');
|
||||||
|
favorite_button.classList.add('btn-success');
|
||||||
|
favorite_button.innerHTML = '<i class="fa fa-star"></i> Favorite';
|
||||||
|
|
||||||
|
favorite_button.onclick = function(e) {
|
||||||
|
button.setAttribute('data-state', 'true')
|
||||||
|
webSocketBridge.send({action: 'favorite', event_instance_id: event_instance_id});
|
||||||
|
toggleFavoriteButton(button)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
webSocketBridge.connect('/schedule/');
|
||||||
|
webSocketBridge.socket.addEventListener('open', function() {
|
||||||
|
webSocketBridge.send({action: 'init', camp_slug: '{{ camp.slug }}'});
|
||||||
|
});
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function openModal(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// Avoid that clicking the text in the event will bring up an empty modal
|
||||||
|
target = e.target;
|
||||||
|
if (e.target !== this) {
|
||||||
|
target = e.target.parentElement
|
||||||
|
}
|
||||||
|
|
||||||
|
event_instance_id = target.dataset['eventinstanceId'];
|
||||||
|
|
||||||
|
modal = modals[event_instance_id];
|
||||||
|
|
||||||
|
if(modal == undefined) {
|
||||||
|
template = document.getElementById('event-template');
|
||||||
|
modal = template.cloneNode(true);
|
||||||
|
body = document.getElementsByTagName('body')[0];
|
||||||
|
body.appendChild(modal);
|
||||||
|
modal.setAttribute('id', 'event-modal-' + event_instance_id)
|
||||||
|
modals[event_instance_id] = modal;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#event-modal-' + event_instance_id).modal();
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
22
src/program/templates/event_modal.html
Normal file
22
src/program/templates/event_modal.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<div class="modal" id="event-template" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||||
|
<h4 class="modal-title"></h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body modal-body-content">
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<h4>Speaker(s):</h4>
|
||||||
|
<ul class="speakers">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
|
||||||
|
<a class="favorite-button btn btn-success"><i class="fa fa-star"></i> Favorite</a>
|
||||||
|
<a class="more-button btn btn-info" href=""><i class="fa fa-info"></i> More</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,15 +1,14 @@
|
||||||
{% extends 'schedule_base.html' %}
|
{% extends 'schedule_base.html' %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
|
||||||
{% block schedule_content %}
|
{% block schedule_content %}
|
||||||
<table>
|
<table class="table day-table">
|
||||||
<tbody>
|
|
||||||
<table>
|
|
||||||
{% for timeslot in timeslots %}
|
{% for timeslot in timeslots %}
|
||||||
<tr>
|
<tr>
|
||||||
<td style="height: 50px; padding: 5px;">{{ timeslot.time }}</td>
|
<td>{% if timeslot.time.minute == 0 %}{{ timeslot.time }}{% endif %}</td>
|
||||||
{% for eventinstance in eventinstances %}
|
{% for eventinstance in eventinstances %}
|
||||||
{% if eventinstance.when.lower.time == timeslot.time %}
|
{% if eventinstance.when.lower.time == timeslot.time %}
|
||||||
<td style="background-color: {{ eventinstance.event.event_type.color }}; color: {% if eventinstance.event.event_type.light_text %}white{% else %}black{% endif %};" class="event" rowspan={{ eventinstance.timeslots }}>
|
<td style="background-color: {{ eventinstance.event.event_type.color }}; color: {% if eventinstance.event.event_type.light_text %}white{% else %}black{% endif %};" class="event-td" rowspan={{ eventinstance.timeslots }} data-eventinstance-id="{{ eventinstance.id }}">
|
||||||
<a style="color:inherit;" href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}">
|
<a style="color:inherit;" href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}">
|
||||||
{{ eventinstance.event.title }}<br>
|
{{ eventinstance.event.title }}<br>
|
||||||
{{ eventinstance.when.lower.time }}-{{ eventinstance.when.upper.time }}
|
{{ eventinstance.when.lower.time }}-{{ eventinstance.when.upper.time }}
|
||||||
|
@ -20,6 +19,11 @@
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</tbody>
|
|
||||||
</table>
|
{% 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-td');
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -3,10 +3,6 @@
|
||||||
{% load commonmark %}
|
{% load commonmark %}
|
||||||
{% load staticfiles %}
|
{% load staticfiles %}
|
||||||
|
|
||||||
{% block extra_head %}
|
|
||||||
<script src="{% static "channels/js/websocketbridge.js" %}"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block schedule_content %}
|
{% block schedule_content %}
|
||||||
{% if eventinstances %}
|
{% if eventinstances %}
|
||||||
{% for day in camp.camp_days %}
|
{% for day in camp.camp_days %}
|
||||||
|
@ -27,28 +23,12 @@
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="modal" id="event-template" tabindex="-1" role="dialog">
|
{% include "event_modal.html" %}
|
||||||
<div class="modal-dialog" role="document">
|
<script src="{% static "channels/js/websocketbridge.js" %}"></script>
|
||||||
<div class="modal-content">
|
<script src="{% static "js/event_instance_websocket.js" %}"></script>
|
||||||
<div class="modal-header">
|
<script>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
init_modals('event');
|
||||||
<h4 class="modal-title"></h4>
|
</script>
|
||||||
</div>
|
|
||||||
<div class="modal-body modal-body-content">
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<h4>Speaker(s):</h4>
|
|
||||||
<ul class="speakers">
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
|
|
||||||
<a class="favorite-button btn btn-success"><i class="fa fa-star"></i> Favorite</a>
|
|
||||||
<a class="more-button btn btn-info" href=""><i class="fa fa-info"></i> More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -59,102 +39,6 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const webSocketBridge = new channels.WebSocketBridge();
|
|
||||||
|
|
||||||
var event_elements = document.getElementsByClassName("event");
|
|
||||||
var modals = {};
|
|
||||||
|
|
||||||
function toggleFavoriteButton(button) {
|
|
||||||
if(button.getAttribute('data-state') == 'true') {
|
|
||||||
favorite_button.classList.remove('btn-success');
|
|
||||||
favorite_button.classList.add('btn-danger');
|
|
||||||
favorite_button.innerHTML = '<i class="fa fa-minus"></i> Remove favorite';
|
|
||||||
|
|
||||||
favorite_button.onclick = function(e) {
|
|
||||||
button.setAttribute('data-state', 'false')
|
|
||||||
webSocketBridge.send({action: 'unfavorite', event_instance_id: event_instance_id});
|
|
||||||
toggleFavoriteButton(button)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
favorite_button.classList.remove('btn-danger');
|
|
||||||
favorite_button.classList.add('btn-success');
|
|
||||||
favorite_button.innerHTML = '<i class="fa fa-star"></i> Favorite';
|
|
||||||
|
|
||||||
favorite_button.onclick = function(e) {
|
|
||||||
button.setAttribute('data-state', 'true')
|
|
||||||
webSocketBridge.send({action: 'favorite', event_instance_id: event_instance_id});
|
|
||||||
toggleFavoriteButton(button)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
webSocketBridge.connect('/schedule/');
|
|
||||||
webSocketBridge.socket.addEventListener('open', function() {
|
|
||||||
webSocketBridge.send({action: 'init', camp_slug: '{{ camp.slug }}'});
|
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function openModal(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
// Avoid that clicking the text in the event will bring up an empty modal
|
|
||||||
target = e.target;
|
|
||||||
if (e.target !== this) {
|
|
||||||
target = e.target.parentElement
|
|
||||||
}
|
|
||||||
|
|
||||||
event_instance_id = target.dataset['eventinstanceId'];
|
|
||||||
|
|
||||||
modal = modals[event_instance_id];
|
|
||||||
|
|
||||||
if(modal == undefined) {
|
|
||||||
template = document.getElementById('event-template');
|
|
||||||
modal = template.cloneNode(true);
|
|
||||||
body = document.getElementsByTagName('body')[0];
|
|
||||||
body.appendChild(modal);
|
|
||||||
modal.setAttribute('id', 'event-modal-' + event_instance_id)
|
|
||||||
modals[event_instance_id] = modal;
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#event-modal-' + event_instance_id).modal();
|
|
||||||
webSocketBridge.send({action: 'get_event_instance', event_instance_id: event_instance_id})
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var event_id in event_elements) {
|
|
||||||
event_element = event_elements.item(event_id);
|
|
||||||
event_element.onclick = openModal
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,15 @@ footer {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.event-td {
|
||||||
|
padding: 5px;
|
||||||
|
vertical-align: top;
|
||||||
|
max-width: 200px;
|
||||||
|
min-width: 200px;
|
||||||
|
flex-grow: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 520px) {
|
@media (max-width: 520px) {
|
||||||
.event {
|
.event {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
|
@ -179,3 +188,13 @@ footer {
|
||||||
.fa-select {
|
.fa-select {
|
||||||
font-family: 'FontAwesome','Helvetica Neue',Helvetica,Arial,sans-serif;
|
font-family: 'FontAwesome','Helvetica Neue',Helvetica,Arial,sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.day-table {
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.day-table > tbody > tr > td {
|
||||||
|
padding: 5px !important;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue