From c01fc80f933798e29eedb1689bc1ef662506df80 Mon Sep 17 00:00:00 2001 From: Adrian Moennich Date: Thu, 2 Oct 2014 14:52:18 +0200 Subject: [PATCH] Add chatroom info to event header --- chat/.gitignore | 3 + chat/MANIFEST.in | 2 + chat/indico_chat/blueprint.py | 19 +++++++ chat/indico_chat/models/chatrooms.py | 4 +- chat/indico_chat/plugin.py | 51 ++++++++++++++++- chat/indico_chat/static/css/chat.scss | 28 +++++++++ chat/indico_chat/static/js/chat.js | 54 ++++++++++++++++++ chat/indico_chat/templates/event_header.html | 57 +++++++++++++++++++ .../indico_chat/templates/how_to_connect.html | 9 +++ chat/indico_chat/zodbimport.py | 7 +++ 10 files changed, 230 insertions(+), 4 deletions(-) create mode 100644 chat/MANIFEST.in create mode 100644 chat/indico_chat/blueprint.py create mode 100644 chat/indico_chat/static/css/chat.scss create mode 100644 chat/indico_chat/static/js/chat.js create mode 100644 chat/indico_chat/templates/event_header.html create mode 100644 chat/indico_chat/templates/how_to_connect.html diff --git a/chat/.gitignore b/chat/.gitignore index c63e593..3b7caa1 100644 --- a/chat/.gitignore +++ b/chat/.gitignore @@ -2,3 +2,6 @@ .*.swp *.pyc *.egg-info +.webassets-cache/ +*.min.css +*.min.js diff --git a/chat/MANIFEST.in b/chat/MANIFEST.in new file mode 100644 index 0000000..8519a44 --- /dev/null +++ b/chat/MANIFEST.in @@ -0,0 +1,2 @@ +graft indico_chat/static +graft indico_chat/migrations diff --git a/chat/indico_chat/blueprint.py b/chat/indico_chat/blueprint.py new file mode 100644 index 0000000..9f1f77c --- /dev/null +++ b/chat/indico_chat/blueprint.py @@ -0,0 +1,19 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2014 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +from indico.core.plugins import IndicoPluginBlueprint + +blueprint = IndicoPluginBlueprint('chat', 'indico_chat') diff --git a/chat/indico_chat/models/chatrooms.py b/chat/indico_chat/models/chatrooms.py index 809760c..fb62f4d 100644 --- a/chat/indico_chat/models/chatrooms.py +++ b/chat/indico_chat/models/chatrooms.py @@ -25,8 +25,6 @@ from indico.util.string import return_ascii from MaKaC.user import AvatarHolder from MaKaC.conference import ConferenceHolder -from indico_chat.plugin import ChatPlugin - class Chatroom(db.Model): __tablename__ = 'chatrooms' @@ -96,6 +94,8 @@ class Chatroom(db.Model): Usually the default one unless a custom one is set. """ + from indico_chat.plugin import ChatPlugin + return self.custom_server or ChatPlugin.settings.get('muc_server') @return_ascii diff --git a/chat/indico_chat/plugin.py b/chat/indico_chat/plugin.py index b08961a..d4eedf9 100644 --- a/chat/indico_chat/plugin.py +++ b/chat/indico_chat/plugin.py @@ -16,14 +16,33 @@ from __future__ import unicode_literals +from flask_pluginengine import render_plugin_template +from wtforms import ValidationError +from wtforms.fields.simple import TextField, TextAreaField + from indico.core.plugins import IndicoPlugin from indico.web.forms.base import IndicoForm -from wtforms.fields.simple import TextField +from indico.web.forms.fields import MultipleItemsField +from indico.web.forms.widgets import CKEditorWidget +from MaKaC.webinterface.pages.conferences import WPTPLConferenceDisplay, WPXSLConferenceDisplay + +from indico_chat.blueprint import blueprint +from indico_chat.models.chatrooms import ChatroomEventAssociation class SettingsForm(IndicoForm): server = TextField('XMPP server') - muc_server = TextField('XMPP MUC server (conference.*)') + muc_server = TextField('XMPP MUC server', description='Usually conference.XMPPSERVER') + how_to_connect = TextAreaField('How to connect', widget=CKEditorWidget(), + description='Text shown below the chatrooms on an event page') + chat_links = MultipleItemsField('Chatroom links', fields=(('title', 'Title'), ('link', 'Link')), + description='Links to join the chatroom. You can use the placeholders {room} and ' + '{server}.') + + def validate_chat_links(self, field): + for item in field.data: + if not all(item.values()): + raise ValidationError('All fields must contain a value.') class ChatPlugin(IndicoPlugin): @@ -33,3 +52,31 @@ class ChatPlugin(IndicoPlugin): """ settings_form = SettingsForm + + @property + def default_settings(self): + return {'how_to_connect': render_plugin_template('how_to_connect.html'), + 'chat_links': [{'title': 'Desktop Client', 'link': 'xmpp:{room}@{server}?join'}]} + + def init(self): + super(ChatPlugin, self).init() + self.template_hook('event-header', self.inject_event_header) + for wp in (WPTPLConferenceDisplay, WPXSLConferenceDisplay): + self.inject_css('chat_css', wp) + self.inject_js('chat_js', wp) + + def get_blueprints(self): + return blueprint + + def register_assets(self): + self.register_css_bundle('chat_css', 'css/chat.scss') + self.register_js_bundle('chat_js', 'js/chat.js') + + def inject_event_header(self, event, **kwargs): + chatrooms = ChatroomEventAssociation.find_all(ChatroomEventAssociation.event_id == event.id, + ~ChatroomEventAssociation.hidden) + if not chatrooms: + return '' + how_to_connect = self.settings.get('how_to_connect') + return render_plugin_template('event_header.html', event=event, event_chatrooms=chatrooms, + how_to_connect=how_to_connect, chat_links=self.settings.get('chat_links')) diff --git a/chat/indico_chat/static/css/chat.scss b/chat/indico_chat/static/css/chat.scss new file mode 100644 index 0000000..a66076b --- /dev/null +++ b/chat/indico_chat/static/css/chat.scss @@ -0,0 +1,28 @@ +@import 'base/palette'; + +.plugin-chat { + .chat-toggle-details { + color: #0B63A5; + text-decoration: none; + } + + .chatroom + .chatroom { + margin-top: 5px; + } + + dl.chat-details { + clear: left; + font-size: 90%; + margin: 5px 0 0 0; + + dt { + float: left; + color: $light-black; + } + + dd { + margin-left: 100px; + display: block; + } + } +} diff --git a/chat/indico_chat/static/js/chat.js b/chat/indico_chat/static/js/chat.js new file mode 100644 index 0000000..36f5ac1 --- /dev/null +++ b/chat/indico_chat/static/js/chat.js @@ -0,0 +1,54 @@ +/* + * This file is part of Indico. + * Copyright (C) 2002 - 2014 European Organization for Nuclear Research (CERN). + * + * Indico is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Indico is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Indico; if not, see . + */ + +(function(global) { + 'use strict'; + + global.eventChatInfo = function eventChatInfo() { + var menu = null; + var links = $('#chat-info-container').data('chatLinks'); + + $('.chat-toggle-details').on('click', function(e) { + e.preventDefault(); + $(this).siblings('.js-chat-details').slideToggle(); + }); + + $('.js-chat-join').on('click', function(e) { + e.preventDefault(); + var $this = $(this); + var menuItems = {}; + $.each(links, function(i, link) { + var action = link.link; + action = action.replace(/\{server\}/g, $this.data('server')); + action = action.replace(/\{room\}/g, $this.data('room')); + menuItems[i] = {display: link.title, action: action}; + }); + + if (menu && menu.isOpen()) { + menu.close(); + if (menu._link == this) { + return; + } + } + menu = new PopupMenu(menuItems, [$E(this)], 'categoryDisplayPopupList', true, false, null, null, true); + menu._link = this; + var pos = $this.offset(); + menu.open(pos.left - 3, pos.top + $this.height()); + }); + } +})(window); diff --git a/chat/indico_chat/templates/event_header.html b/chat/indico_chat/templates/event_header.html new file mode 100644 index 0000000..bafa120 --- /dev/null +++ b/chat/indico_chat/templates/event_header.html @@ -0,0 +1,57 @@ + + Chat rooms + +
+ {% for event_chatroom in event_chatrooms %} + {% set chatroom = event_chatroom.chatroom %} + {% set server = chatroom.server %} +
+ {{ chatroom.name }} + + {% trans %}More Info{% endtrans %} + {% if chat_links %} + | + {% trans %}Join now!{% endtrans %} + {% endif %} + +
+ {% endfor %} + +
+ + +{% if how_to_connect %} + + + + + + + + + +
{% trans %}How to connect to the chat{% endtrans %}
{{ how_to_connect | safe }}
+ + +{% endif %} diff --git a/chat/indico_chat/templates/how_to_connect.html b/chat/indico_chat/templates/how_to_connect.html new file mode 100644 index 0000000..85322db --- /dev/null +++ b/chat/indico_chat/templates/how_to_connect.html @@ -0,0 +1,9 @@ +
    +
  • + Download a messaging client compatible with XMPP (such as Pidgin, Gajim, Adium, Spark). + You may want to look here) and install it. +
  • +
  • Add the XMPP account that you want to use.
  • +
  • In the menus, try to find something like 'Join a Chat', 'Join Group Chat', or related.
  • +
  • Fill the fields Room and Server with the information above. In case there is only one field for both the room and the server, the format to use is 'room@server'.
  • +
diff --git a/chat/indico_chat/zodbimport.py b/chat/indico_chat/zodbimport.py index b17d2b0..05aa604 100644 --- a/chat/indico_chat/zodbimport.py +++ b/chat/indico_chat/zodbimport.py @@ -44,10 +44,17 @@ class ChatImporter(Importer): def migrate_settings(self): print cformat('%{white!}migrating settings') ChatPlugin.settings.delete_all() + type_opts = self.zodb_root['plugins']['InstantMessaging']._PluginBase__options opts = self.zodb_root['plugins']['InstantMessaging']._PluginType__plugins['XMPP']._PluginBase__options host = convert_to_unicode(opts['chatServerHost'].getValue()) ChatPlugin.settings.set('server', host) ChatPlugin.settings.set('muc_server', 'conference.{}'.format(host)) + ChatPlugin.settings.set('how_to_connect', opts['ckEditor'].getValue().strip()) + chat_links = [] + for item in type_opts['customLinks'].getValue(): + link = item['structure'].replace('[chatroom]', '{room}').replace('[host]', '{server}') + chat_links.append({'title': item['name'], 'link': link}) + ChatPlugin.settings.set('chat_links', chat_links) # TODO: migrate other settings db.session.commit()