Adding channels with the schedule as first app using them.
This commit is contained in:
parent
9d70782b70
commit
8000896f3d
8
src/bornhack/routing.py
Normal file
8
src/bornhack/routing.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
from program.consumers import ScheduleConsumer
|
||||
|
||||
|
||||
channel_routing = [
|
||||
ScheduleConsumer.as_route(path=r"^/schedule/"),
|
||||
]
|
||||
|
||||
|
|
@ -28,6 +28,8 @@ INSTALLED_APPS = [
|
|||
'django.contrib.staticfiles',
|
||||
'django.contrib.sites',
|
||||
|
||||
'channels',
|
||||
|
||||
'profiles',
|
||||
'camps',
|
||||
'shop',
|
||||
|
@ -108,9 +110,27 @@ MIDDLEWARE = [
|
|||
|
||||
if DEBUG:
|
||||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||
INSTALLED_APPS += ['debug_toolbar', ]
|
||||
INSTALLED_APPS += [
|
||||
'debug_toolbar',
|
||||
'channels_panel'
|
||||
]
|
||||
MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware'] + MIDDLEWARE
|
||||
INTERNAL_IPS = "127.0.0.1"
|
||||
DEBUG_TOOLBAR_PANELS = [
|
||||
'debug_toolbar.panels.versions.VersionsPanel',
|
||||
'debug_toolbar.panels.timer.TimerPanel',
|
||||
'debug_toolbar.panels.settings.SettingsPanel',
|
||||
'debug_toolbar.panels.headers.HeadersPanel',
|
||||
'debug_toolbar.panels.request.RequestPanel',
|
||||
'debug_toolbar.panels.sql.SQLPanel',
|
||||
'debug_toolbar.panels.staticfiles.StaticFilesPanel',
|
||||
'debug_toolbar.panels.templates.TemplatesPanel',
|
||||
'debug_toolbar.panels.cache.CachePanel',
|
||||
'debug_toolbar.panels.signals.SignalsPanel',
|
||||
'debug_toolbar.panels.logging.LoggingPanel',
|
||||
'debug_toolbar.panels.redirects.RedirectsPanel',
|
||||
'channels_panel.panel.ChannelsDebugPanel',
|
||||
]
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
|
@ -142,3 +162,9 @@ LOGGING = {
|
|||
},
|
||||
}
|
||||
|
||||
CHANNEL_LAYERS = {
|
||||
"default": {
|
||||
"BACKEND": "asgiref.inmemory.ChannelLayer",
|
||||
"ROUTING": "bornhack.routing.channel_routing",
|
||||
},
|
||||
}
|
||||
|
|
28
src/program/consumers.py
Normal file
28
src/program/consumers.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from channels.generic.websockets import JsonWebsocketConsumer
|
||||
|
||||
from .models import EventInstance
|
||||
|
||||
|
||||
class ScheduleConsumer(JsonWebsocketConsumer):
|
||||
http_user = True
|
||||
|
||||
def connection_groups(self, **kwargs):
|
||||
return ['schedule_users']
|
||||
|
||||
def connect(self, message, **kwargs):
|
||||
self.send({"accept": True})
|
||||
|
||||
def receive(self, content, **kwargs):
|
||||
action = content.get('action')
|
||||
data = {}
|
||||
|
||||
if action == 'get_event_instance':
|
||||
event_instance_id = content.get('event_instance_id')
|
||||
event_instance = EventInstance.objects.get(id=event_instance_id)
|
||||
data['action'] = 'event_instance'
|
||||
data['event_instance'] = event_instance.to_json()
|
||||
|
||||
self.send(data)
|
||||
|
||||
def disconnect(self, message, **kwargs):
|
||||
pass
|
|
@ -14,6 +14,7 @@ from django.apps import apps
|
|||
from django.core.files.base import ContentFile
|
||||
|
||||
import icalendar
|
||||
import CommonMark
|
||||
|
||||
from utils.models import CreatedUpdatedModel, CampRelatedModel
|
||||
|
||||
|
@ -448,6 +449,22 @@ class EventInstance(CampRelatedModel):
|
|||
ievent['location'] = icalendar.vText(self.location.name)
|
||||
return ievent
|
||||
|
||||
def to_json(self):
|
||||
parser = CommonMark.Parser()
|
||||
renderer = CommonMark.HtmlRenderer()
|
||||
ast = parser.parse(self.event.abstract)
|
||||
abstract = renderer.render(ast)
|
||||
return {
|
||||
'title': self.event.title,
|
||||
'event_slug': self.event.slug,
|
||||
'abstract': abstract,
|
||||
'from': self.when.lower.isoformat(),
|
||||
'to': self.when.lower.isoformat(),
|
||||
'url': str(self.event.get_absolute_url()),
|
||||
'id': self.id,
|
||||
}
|
||||
|
||||
|
||||
|
||||
def get_speaker_picture_upload_path(instance, filename):
|
||||
""" We want speaker pictures are saved as MEDIA_ROOT/public/speakers/camp-slug/speaker-slug/filename """
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
{% extends 'schedule_base.html' %}
|
||||
|
||||
{% load commonmark %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script src="{% static "channels/js/websocketbridge.js" %}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block schedule_content %}
|
||||
{% if eventinstances %}
|
||||
|
@ -12,9 +17,8 @@
|
|||
<a class="event"
|
||||
href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}"
|
||||
style="background-color: {{ eventinstance.event.event_type.color }}; color: {% if eventinstance.event.event_type.light_text %}white{% else %}black{% endif %};"
|
||||
data-toggle="modal"
|
||||
data-target="#{{ eventinstance.event.slug }}"
|
||||
data-remote=false>
|
||||
data-eventinstance-id="{{ eventinstance.id }}"
|
||||
>
|
||||
<small>{{ eventinstance.when.lower|date:"H:i" }} - {{ eventinstance.when.upper|date:"H:i" }}</small>
|
||||
<span class="pull-right" style="font-family: 'FontAwesome';">&#x{{ eventinstance.location.icon }};</span>
|
||||
<br />
|
||||
|
@ -23,20 +27,19 @@
|
|||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="modal" id="{{ eventinstance.event.slug }}" tabindex="-1" role="dialog" aria-labelledby="{{ eventinstance.event.slug }}-label">
|
||||
<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" id="{{ eventinstance.event.slug }}-label">{{ eventinstance.event.title }}</h4>
|
||||
<h4 class="modal-title"></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ eventinstance.event.abstract|commonmark}}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">Close</button>
|
||||
<a class="btn btn-success"><i class="fa fa-star"></i> Favorite</a>
|
||||
<a class="btn btn-info" href="{% url 'event_detail' camp_slug=camp.slug slug=eventinstance.event.slug %}"><i class="fa fa-info"></i> More</a>
|
||||
<a class="more-button btn btn-info" href=""><i class="fa fa-info"></i> More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -50,4 +53,48 @@
|
|||
<h2>No scheduled events for {{ camp.title }} yet!</h2>
|
||||
{% endif %}
|
||||
|
||||
<script>
|
||||
const webSocketBridge = new channels.WebSocketBridge();
|
||||
|
||||
var event_elements = document.getElementsByClassName("event");
|
||||
var modals = {};
|
||||
var events = {};
|
||||
|
||||
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 = modal.getElementsByClassName('modal-body')[0];
|
||||
modal_body.innerHTML = payload['event_instance']['abstract'];
|
||||
more_button = modal.getElementsByClassName('more-button')[0];
|
||||
more_button.setAttribute('href', payload['event_instance']['url']);
|
||||
}
|
||||
});
|
||||
|
||||
function openModal(e) {
|
||||
e.preventDefault();
|
||||
event_instance_id = e.target.dataset['eventinstanceId'];
|
||||
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>
|
||||
|
||||
{% endblock schedule_content %}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
CommonMark==0.7.3
|
||||
Django==1.10.5
|
||||
channels==1.1.3
|
||||
Pillow==4.0.0
|
||||
PyPDF2==1.26.0
|
||||
Unidecode==0.04.20
|
||||
|
@ -9,7 +10,7 @@ bleach==1.5.0
|
|||
defusedxml==0.4.1
|
||||
django-allauth==0.30.0
|
||||
django-bleach==0.3.0
|
||||
django-bootstrap3==8.1.0
|
||||
django-bootstrap3==8.2.2
|
||||
django-debug-toolbar==1.6
|
||||
django-extensions==1.7.7
|
||||
django-wkhtmltopdf==3.1.0
|
||||
|
|
Loading…
Reference in a new issue