Improved chatbox style. Updated jquery cookie and jquery ui.

- Fixed js error on dashboard page if no cookie is found.
- Use cookies only until end of session. For dashboard cookies use url /dashboard only.
- Updated permission numbering of builtin groups and added can_use_chat permission.
- Used minified version of jquery.cookie.
- Added TODO comment for django session way from pull request.
This commit is contained in:
Emanuel Schütze 2014-03-12 22:15:05 +01:00
parent 42796f6118
commit 3b3597aa1f
19 changed files with 278 additions and 144 deletions

View File

@ -296,10 +296,6 @@ OpenSlides uses the following projects or parts of them:
* `jQuery <http://www.jquery.com>`_, License: MIT * `jQuery <http://www.jquery.com>`_, License: MIT
* `jQuery UI <http://jqueryui.com>`_ with custom ui components: core,
widget, mouse, sortable, datepicker, slider and css theme 'smoothness',
License: MIT
* jQuery Plugins: * jQuery Plugins:
- `jQuery DataTables Plugin <http://www.datatables.net>`_, License: - `jQuery DataTables Plugin <http://www.datatables.net>`_, License:
@ -309,7 +305,7 @@ OpenSlides uses the following projects or parts of them:
License: MIT License: MIT
- `jQuery Cookie Plugin <https://github.com/carhartl/jquery-cookie/>`_, - `jQuery Cookie Plugin <https://github.com/carhartl/jquery-cookie/>`_,
License: MIT/GPL License: MIT
- `jQuery Form Plugin <http://malsup.com/jquery/form/>`_, License: MIT/GPLv2 - `jQuery Form Plugin <http://malsup.com/jquery/form/>`_, License: MIT/GPLv2
@ -321,6 +317,12 @@ OpenSlides uses the following projects or parts of them:
- `jQuery bsmSelect <https://github.com/vicb/bsmSelect/>`_, License: - `jQuery bsmSelect <https://github.com/vicb/bsmSelect/>`_, License:
MIT/GPLv2 MIT/GPLv2
* `jQuery UI <http://jqueryui.com>`_ with custom ui components: core,
widget, mouse, resizable, sortable, datepicker, slider and css theme 'smoothness',
License: MIT
* jQuery UI AddOns:
- `jQuery UI Nested Sortable - `jQuery UI Nested Sortable
<https://github.com/mjsarfatti/nestedSortable/>`_, License: MIT <https://github.com/mjsarfatti/nestedSortable/>`_, License: MIT
@ -332,7 +334,6 @@ OpenSlides uses the following projects or parts of them:
<http://trentrichardson.com/examples/timepicker/>`_, License: MIT/GPLv2 <http://trentrichardson.com/examples/timepicker/>`_, License: MIT/GPLv2
VII. License and authors VII. License and authors
======================== ========================

View File

@ -60,9 +60,8 @@ def setup_agenda_config(sender, **kwargs):
help_text=ugettext_lazy('[Begin speach] starts the countdown, [End speach] stops the countdown.'), help_text=ugettext_lazy('[Begin speach] starts the countdown, [End speach] stops the countdown.'),
required=False)) required=False))
extra_stylefiles = ['css/jquery-ui-timepicker.css', 'css/jquery-ui/jquery-ui.custom.min.css'] extra_stylefiles = ['css/jquery-ui-timepicker.css']
extra_javascript = ['js/jquery/jquery-ui.custom.min.js', extra_javascript = ['js/jquery/jquery-ui-timepicker-addon.min.js',
'js/jquery/jquery-ui-timepicker-addon.min.js',
'js/jquery/jquery-ui-sliderAccess.min.js', 'js/jquery/jquery-ui-sliderAccess.min.js',
'js/jquery/datepicker-config.js'] 'js/jquery/datepicker-config.js']

View File

@ -12,7 +12,6 @@
{% block javascript %} {% block javascript %}
<script type="text/javascript" src="{% static 'js/agenda.js' %}"></script> <script type="text/javascript" src="{% static 'js/agenda.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery/jquery.cookie.js' %}"></script>
{% if perms.agenda.can_manage_agenda %} {% if perms.agenda.can_manage_agenda %}
<script type="text/javascript" src="{% static 'js/jquery/jquery-ui.custom.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/jquery/jquery-ui.custom.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery/jquery.once.js' %}"></script> <script type="text/javascript" src="{% static 'js/jquery/jquery.once.js' %}"></script>

View File

@ -8,7 +8,6 @@
{% block header %} {% block header %}
<link type="text/css" rel="stylesheet" media="all" href="{% static 'css/agenda.css' %}" /> <link type="text/css" rel="stylesheet" media="all" href="{% static 'css/agenda.css' %}" />
<link rel="stylesheet" href="{% static 'css/jquery-ui/jquery-ui.custom.min.css' %}" />
{% endblock %} {% endblock %}
{% block javascript %} {% block javascript %}

View File

@ -4,6 +4,7 @@ from datetime import datetime
from django.conf import settings from django.conf import settings
from django.contrib.sessions.models import Session from django.contrib.sessions.models import Session
from django.utils.html import urlize
from sockjs.tornado import SockJSConnection from sockjs.tornado import SockJSConnection
@ -19,6 +20,9 @@ class ChatboxSocketHandler(SockJSConnection):
""" """
from openslides.participant.models import User from openslides.participant.models import User
# TODO: Use the django way to get the session to be compatible with
# other auth-backends; see comment in pull request #1220:
# https://github.com/OpenSlides/OpenSlides/pull/1220#discussion_r11565705
session_key = info.get_cookie(settings.SESSION_COOKIE_NAME).value session_key = info.get_cookie(settings.SESSION_COOKIE_NAME).value
session = Session.objects.get(session_key=session_key) session = Session.objects.get(session_key=session_key)
try: try:
@ -26,8 +30,7 @@ class ChatboxSocketHandler(SockJSConnection):
except User.DoesNotExist: except User.DoesNotExist:
return_value = False return_value = False
else: else:
# TODO: Use correct permission here if self.user.has_perm('core.can_use_chat'):
if self.user.has_perm('projector.can_manage_projector'):
self.clients.add(self) self.clients.add(self)
return_value = True return_value = True
else: else:
@ -41,16 +44,16 @@ class ChatboxSocketHandler(SockJSConnection):
Also appends the message to the cache and removes old messages if there Also appends the message to the cache and removes old messages if there
are more than 100. are more than 100.
""" """
# TODO: Use correct permission here if self.user.has_perm('core.can_use_chat') and message:
if self.user.has_perm('projector.can_manage_projector') and message:
message_object = ChatMessage(person=self.user, message=message) message_object = ChatMessage(person=self.user, message=message)
chat_messages.append(message_object) chat_messages.append(message_object)
if len(chat_messages) > 100: if len(chat_messages) > 100:
chat_messages.pop(0) chat_messages.pop(0)
self.broadcast( self.broadcast(
self.clients, self.clients,
'%s %s' % (message_object.html_time_and_person(), '%s %s %s' % (message_object.html_time(),
message_object.message)) message_object.html_person(),
urlize(message_object.message)))
def on_close(self): def on_close(self):
""" """
@ -73,14 +76,19 @@ class ChatMessage(object):
self.color = color or (0, 0, 0) self.color = color or (0, 0, 0)
self.time = datetime.now() self.time = datetime.now()
def html_time_and_person(self): def html_time(self):
""" """
Returns a styled prefix for each message using span and small html tags. Returns the message time in html style.
""" """
return '<span style="color:%(color)s;">%(person)s <small class="grey">%(time)s</small>:</span>' % { return '<small class="grey">%s</small>' % self.time.strftime('%H:%M')
def html_person(self):
"""
Returns the message sender name in html style.
"""
return "<span style='color:%(color)s;'>%(person)s:</span>" % {
'color': 'rgb(%d,%d,%d)' % self.color, 'color': 'rgb(%d,%d,%d)' % self.color,
'person': self.person.clean_name, 'person': self.person.clean_name}
'time': self.time.strftime('%H:%M')}
chat_messages = [] chat_messages = []
@ -92,8 +100,9 @@ Cache with all messages during livetime of the server.
def chat_messages_context_processor(request): def chat_messages_context_processor(request):
""" """
Adds all chat messages to the request context as template context processor. Adds all chat messages to the request context as template context processor.
Returns None if the request user has no permission to use the chat.
""" """
if True: # TODO: Add permission check here if request.user.has_perm('core.can_use_chat'):
value = chat_messages value = chat_messages
else: else:
value = None value = None

View File

@ -24,6 +24,7 @@ class CustomSlide(SlideMixin, AbsoluteUrlMixin, models.Model):
('can_manage_projector', ugettext_noop('Can manage the projector')), ('can_manage_projector', ugettext_noop('Can manage the projector')),
('can_see_projector', ugettext_noop('Can see the projector')), ('can_see_projector', ugettext_noop('Can see the projector')),
('can_see_dashboard', ugettext_noop('Can see the dashboard')), ('can_see_dashboard', ugettext_noop('Can see the dashboard')),
('can_use_chat', ugettext_noop('Can use the chat')),
) )
def __unicode__(self): def __unicode__(self):

View File

@ -0,0 +1,64 @@
/** Chatbox **/
.icon-comments {
background-position: -240px -120px;
}
div#chatbox {
width: 40%;
height: 220px;
min-height: 140px;
min-width: 300px;
position: fixed;
right: 0px;
bottom: 0;
z-index: 99;
margin-bottom: 0;
box-shadow: -3px -3px 10px rgba(0,0,0,0.2);
border-width: 2px;
border-color: darkgrey;
padding: 0;
}
#chatbox-header{
background-color: #333333;
background-image: -moz-linear-gradient(top, #444444, #222222);
background-image: -ms-linear-gradient(top, #444444, #222222);
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
background-image: -webkit-linear-gradient(top, #444444, #222222);
background-image: -o-linear-gradient(top, #444444, #222222);
background-image: linear-gradient(top, #444444, #222222);
border-color: #333333;
}
h1#chatbox-title {
color: #999999;
font-size: 16px;
font-weight: bold;
line-height: 16px;
margin: 0;
padding: 3px 10px 7px 10px;
border-bottom: none;
}
div#chatbox div#chatbox-text {
clear: both;
overflow-y:scroll;
background-color: white;
padding: 0 10px;
font-size: 12px;
height: calc(100% - 65px);
}
#chatbox form {
margin-bottom: 0px;
padding: 5px;
}
#chatbox form input {
width: 90%;
}
#newchatmessage {
border-radius: 8px;
background-color: red;
color: white;
font-size: 0.7em;
position: relative;
right: 0;
top: -6px;
padding: 2px 6px;
display: none;
}

File diff suppressed because one or more lines are too long

View File

@ -1,35 +0,0 @@
// Functions for OpenSlides manager chatbox
$("button#open-chatbox").click(function(){
$("div#chatbox").removeClass('hidden');
});
$("button#close-chatbox").click(function(){
$("div#chatbox").addClass('hidden');
});
$(document).ready(function(){
//~ var transports = $('#protocols input:checked').map(function(){
//~ return $(this).attr('id');
//~ }).get();
function print_message(message) {
var chatbox = $('#chatbox-text');
chatbox.html(chatbox.html() + '<p>' + message + '</p>');
chatbox.scrollTop(chatbox.scrollTop() + 10000);
}
//~ var connection = new SockJS('http://' + window.location.host + '/chatbox', transports);
var connection = new SockJS('http://' + window.location.host + '/core/chatbox');
connection.onmessage = function(event) {
print_message(event.data);
};
$("#chatbox-form-send").click(function(){
var message = $('#chatbox-form-input').val();
connection.send(message);
$('#chatbox-form-input').val('').focus();
return false;
});
});

View File

@ -0,0 +1,111 @@
// Functions for OpenSlides chatbox
$(function() {
// Chatbox is resizable on two sides (north and west) and
// one corner (nortwest)
$("div#chatbox").resizable({ handles: 'n, w, nw' });
});
$("#chatboxbutton").click(function(){
if ($(this).hasClass('active')) {
/* close chatbox */
$("#chatbox").addClass('hidden');
// Save new chatbox state in cookie
save_cookie(false);
} else {
/* open chatbox */
$("#chatbox").removeClass('hidden');
// Scroll chat content to end
$("#chatbox-text").scrollTop(10000);
// Set focus to input field
$("#chatbox-form-input").val('').focus();
// Save new chatbox state in cookie
save_cookie(true)
$.cookie('openslides-chatbox-new-message', 0, { path: "/"});
// Hide new message number
$("#newchatmessage").fadeOut();
}
});
$("#close-chatbox").click(function(){
$("#chatbox").addClass('hidden');
$("#chatboxbutton").removeClass('active');
// Save new chatbox state in cookie
save_cookie(false);
});
$("#chatbox").resize(function() {
// If resizing the chatbox window the chatbox text scrolls to latest message.
// Sets a minimum for width and height.
$("#chatbox-text").scrollTop(10000);
$("#chatbox").resizable( "option", "minWidth", 300 );
$("#chatbox").resizable( "option", "minHeight", 140 );
save_cookie(true);
});
// Save chatbox state in cookie.
// Parameter 'active': chatbox window is open (true) or closed (false).
function save_cookie(active) {
var status = {
'active': active,
'width': $("#chatbox").width(),
'height': $("#chatbox").height()
};
$.cookie('openslides-chatbox', JSON.stringify(status), { path: "/"});
}
$(document).ready(function(){
// Load chatbox state from cookie.
var cookie = $.cookie('openslides-chatbox');
if (cookie) {
var status = $.parseJSON(cookie);
if (status['active']) {
$("#chatbox").removeClass('hidden');
$("#chatboxbutton").addClass('active');
// Scroll chat content to end
$("#chatbox-text").scrollTop(10000);
// Set focus to input field
$('#chatbox-form-input').val('').focus();
}
if (status['width']) {
$("#chatbox").width(status['width']);
}
if (status['height']) {
$("#chatbox").height(status['height']);
}
}
// Load number of new messages from cookie
if ($.cookie('openslides-chatbox-new-message') > 0) {
$("#newchatmessage").html($.cookie('openslides-chatbox-new-message'));
$("#newchatmessage").show(0);
}
// Print chat messages into chatbox
function print_message_into_box(message) {
var chatcontent = $('#chatbox-text');
chatcontent.html(chatcontent.html() + '<br>' + message);
chatcontent.scrollTop(chatcontent.scrollTop() + 10000);
// if chatbox is hidden show number of new messages and save in cookie
if ($("#chatbox").hasClass('hidden')){
new_messages = parseInt($.cookie('openslides-chatbox-new-message')) + 1;
if (new_messages == 1)
$("#newchatmessage").fadeIn();
$("#newchatmessage").html(new_messages);
$.cookie('openslides-chatbox-new-message', new_messages, { path: "/"});
}
}
var connection = new SockJS('http://' + window.location.host + '/core/chatbox');
connection.onmessage = function(event) {
print_message_into_box(event.data);
};
$("#chatbox-form").submit(function(){
var message = $('#chatbox-form-input').val();
connection.send(message);
$('#chatbox-form-input').val('').focus();
return false;
});
});

View File

@ -7,7 +7,7 @@
function saveOrder() { function saveOrder() {
$(".column").each(function(index, value){ $(".column").each(function(index, value){
var colid = value.id; var colid = value.id;
var cookieName = "cookie-" + colid; var cookieName = "openslides-dashboard-" + colid;
// Get the order for this column. // Get the order for this column.
var order = $('#' + colid).sortable("toArray"); var order = $('#' + colid).sortable("toArray");
var cookie_content = []; var cookie_content = [];
@ -24,7 +24,7 @@ function saveOrder() {
} }
cookie_content[i] = widget_id + '/' + is_collabsed + '/' + is_pinned; cookie_content[i] = widget_id + '/' + is_collabsed + '/' + is_pinned;
} }
$.cookie(cookieName, cookie_content, { path: "/", expiry: new Date(2012, 1, 1)}); $.cookie(cookieName, cookie_content);
}); });
} }
@ -32,9 +32,9 @@ function saveOrder() {
function restoreOrder() { function restoreOrder() {
$(".column").each(function(index, value) { $(".column").each(function(index, value) {
var colid = value.id; var colid = value.id;
var cookieName = "cookie-" + colid; var cookieName = "openslides-dashboard-" + colid;
var cookie = $.cookie(cookieName); var cookie = $.cookie(cookieName);
if ( cookie === null ) { return; } if ( cookie === undefined ) { return; }
var widgets = cookie.split(","); var widgets = cookie.split(",");
for (var i = 0, n = widgets.length; i < n; i++ ) { for (var i = 0, n = widgets.length; i < n; i++ ) {
var widget_information = widgets[i].split('/'); var widget_information = widgets[i].split('/');

File diff suppressed because one or more lines are too long

View File

@ -1,12 +0,0 @@
// $Id: jquery.cookie.js,v 1.1 2009/07/01 12:16:48 dries Exp $
/**
* Cookie plugin 1.0
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}};

View File

@ -0,0 +1,11 @@
/*!
* jQuery Cookie Plugin v1.4.0
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function(factory){if(typeof define==="function"&&define.amd)define(["jquery"],factory);else if(typeof exports==="object")factory(require("jquery"));else factory(jQuery)})(function($){var pluses=/\+/g;function encode(s){return config.raw?s:encodeURIComponent(s)}function decode(s){return config.raw?s:decodeURIComponent(s)}function stringifyCookieValue(value){return encode(config.json?JSON.stringify(value):String(value))}function parseCookieValue(s){if(s.indexOf('"')===0)s=s.slice(1,-1).replace(/\\"/g,
'"').replace(/\\\\/g,"\\");try{s=decodeURIComponent(s.replace(pluses," "));return config.json?JSON.parse(s):s}catch(e){}}function read(s,converter){var value=config.raw?s:parseCookieValue(s);return $.isFunction(converter)?converter(value):value}var config=$.cookie=function(key,value,options){if(value!==undefined&&!$.isFunction(value)){options=$.extend({},config.defaults,options);if(typeof options.expires==="number"){var days=options.expires,t=options.expires=new Date;t.setTime(+t+days*864E5)}return document.cookie=
[encode(key),"=",stringifyCookieValue(value),options.expires?"; expires="+options.expires.toUTCString():"",options.path?"; path="+options.path:"",options.domain?"; domain="+options.domain:"",options.secure?"; secure":""].join("")}var result=key?undefined:{};var cookies=document.cookie?document.cookie.split("; "):[];for(var i=0,l=cookies.length;i<l;i++){var parts=cookies[i].split("=");var name=decode(parts.shift());var cookie=parts.join("=");if(key&&key===name){result=read(cookie,value);break}if(!key&&
(cookie=read(cookie))!==undefined)result[name]=cookie}return result};config.defaults={};$.removeCookie=function(key,options){if($.cookie(key)===undefined)return false;$.cookie(key,"",$.extend({},options,{expires:-1}));return!$.cookie(key)}});

View File

@ -1,19 +0,0 @@
/** Chatbox **/
.icon-comments {
background-position: -240px -120px;
}
div#chatbox {
width: 35%;
}
div#chatbox h1 {
border-bottom: none;
font-size: 14px;
margin-bottom: 10px;
float: left;
}
div#chatbox div#chatbox-text {
clear: both;
min-height: 150px;
max-height:150px;
overflow-y:scroll;
}

View File

@ -11,6 +11,7 @@
<!-- styles --> <!-- styles -->
<link href="{% static 'css/bootstrap.min.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'css/bootstrap.min.css' %}" type="text/css" rel="stylesheet" />
<link href="{% static 'css/bootstrap-responsive.min.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'css/bootstrap-responsive.min.css' %}" type="text/css" rel="stylesheet" />
<link href="{% static 'css/jquery-ui/jquery-ui.custom.min.css'%}" type="text/css" rel="stylesheet" />
<link href="{% static 'css/base.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'css/base.css' %}" type="text/css" rel="stylesheet" />
<link href="{% static 'css/chatbox.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'css/chatbox.css' %}" type="text/css" rel="stylesheet" />
<link href="{% static 'img/favicon.png' %}" type="image/png" rel="shortcut icon" /> <link href="{% static 'img/favicon.png' %}" type="image/png" rel="shortcut icon" />
@ -26,7 +27,7 @@
<div class="span12"> <div class="span12">
<div id="header"> <div id="header">
<a href="/" class="logo" title="{% trans 'Home' %}"><img src="{% static 'img/logo.png' %}" alt="{% trans 'Logo' %}" /></a> <a href="/" class="logo" title="{% trans 'Home' %}"><img src="{% static 'img/logo.png' %}" alt="{% trans 'Logo' %}" /></a>
<span class="title optional">{% get_config 'event_name' %} {% get_config 'event_description' %}</span> <span class="title optional">{% get_config 'event_name' %} {% if 'event_description'|get_config %} {% get_config 'event_description' %}{% endif %}</span>
{% block loginbutton %} {% block loginbutton %}
<div class="pull-right"> <div class="pull-right">
<!-- Search field --> <!-- Search field -->
@ -39,9 +40,10 @@
<!-- Chatbox button --> <!-- Chatbox button -->
{% if chat_messages != None %} {% if chat_messages != None %}
<button class="btn" id="open-chatbox"> <button class="btn" id="chatboxbutton" data-toggle="button">
<i class="icon-comments"></i> <i class="icon-comments"></i>
{% trans 'Chat' %} {% trans 'Chat' %}
<span id="newchatmessage"></span>
</button> </button>
{% endif %} {% endif %}
@ -122,8 +124,9 @@
<!-- JavaScript (Placed at the end of the document so the pages load faster) --> <!-- JavaScript (Placed at the end of the document so the pages load faster) -->
<script src="{% static 'js/jquery/jquery.min.js' %}" type="text/javascript"></script> <script src="{% static 'js/jquery/jquery.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/jquery/jquery.cookie.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/jquery/jquery-ui.custom.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/bootstrap.min.js' %}" type="text/javascript"></script> <script src="{% static 'js/bootstrap.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/utils.js' %}" type="text/javascript"></script>
<script src="{% static 'js/sockjs-0.3.min.js' %}" type="text/javascript"></script> <script src="{% static 'js/sockjs-0.3.min.js' %}" type="text/javascript"></script>
<script src="{% static 'js/utils.js' %}" type="text/javascript"></script> <script src="{% static 'js/utils.js' %}" type="text/javascript"></script>
<script src="{% static 'js/chatbox.js' %}" type="text/javascript"></script> <script src="{% static 'js/chatbox.js' %}" type="text/javascript"></script>

View File

@ -2,22 +2,20 @@
{% if chat_messages != None %} {% if chat_messages != None %}
<div class="hidden well" id="chatbox"> <div class="hidden well" id="chatbox">
<div> <div id="chatbox-header">
<h1>Chatbox</h1> <h1 id="chatbox-title"><i class="icon-comments icon-white"></i> Chat
<button class="btn btn-mini pull-right" id="close-chatbox"><i class="icon-remove"></i></button> <button class="btn btn-mini right" id="close-chatbox"><i class="icon-remove"></i></button>
</h1>
</div> </div>
<div id="chatbox-text"> <div id="chatbox-text">
{% for message in chat_messages %} {% for message in chat_messages %}
<p>{{ message.html_time_and_person|safe }} {{ message.message }}</p> <br>{{ message.html_time|safe }} {{ message.html_person|safe }} {{ message.message|urlize }}
{% endfor %} {% endfor %}
</div> </div>
<hr />
<form class="form-inline" id="chatbox-form"> <form class="form-inline" id="chatbox-form">
<div class="input-append"> <div class="input-append" style="width: calc(100% - 25px);">
<input id="chatbox-form-input" type="text" /> <input id="chatbox-form-input" type="text" />
<button id="chatbox-form-send" type="submit" class="btn btn-primary" title="{% trans 'Send message' %}"> <button type="submit" class="btn"><i class="icon-comments"></i></button>
<i class="icon-ok icon-white"></i>
</button>
</div> </div>
</form> </form>
</div> </div>

View File

@ -8,8 +8,6 @@
{% endblock %} {% endblock %}
{% block javascript %} {% block javascript %}
<script type="text/javascript" src="{% static 'js/jquery/jquery-ui.custom.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery/jquery.cookie.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery/jquery.form.js' %}"></script> <script type="text/javascript" src="{% static 'js/jquery/jquery.form.js' %}"></script>
<script type="text/javascript" src="{% static 'js/dashboard.js' %}"></script> <script type="text/javascript" src="{% static 'js/dashboard.js' %}"></script>
{% endblock %} {% endblock %}

View File

@ -124,58 +124,63 @@ def create_builtin_groups_and_admin(sender, **kwargs):
# Do completely nothing if there are already some of our groups in the database. # Do completely nothing if there are already some of our groups in the database.
return return
# Anonymous and Registered # Anonymous (pk 1) and Registered (pk 2)
ct_core = ContentType.objects.get(app_label='core', model='customslide') ct_core = ContentType.objects.get(app_label='core', model='customslide')
perm_1 = Permission.objects.get(content_type=ct_core, codename='can_see_projector') perm_11 = Permission.objects.get(content_type=ct_core, codename='can_see_projector')
perm_2 = Permission.objects.get(content_type=ct_core, codename='can_see_dashboard') perm_12 = Permission.objects.get(content_type=ct_core, codename='can_see_dashboard')
ct_agenda = ContentType.objects.get(app_label='agenda', model='item') ct_agenda = ContentType.objects.get(app_label='agenda', model='item')
ct_speaker = ContentType.objects.get(app_label='agenda', model='speaker') ct_speaker = ContentType.objects.get(app_label='agenda', model='speaker')
perm_3 = Permission.objects.get(content_type=ct_agenda, codename='can_see_agenda') perm_13 = Permission.objects.get(content_type=ct_agenda, codename='can_see_agenda')
perm_3a = Permission.objects.get(content_type=ct_agenda, codename='can_see_orga_items') perm_14 = Permission.objects.get(content_type=ct_agenda, codename='can_see_orga_items')
can_speak = Permission.objects.get(content_type=ct_speaker, codename='can_be_speaker') can_speak = Permission.objects.get(content_type=ct_speaker, codename='can_be_speaker')
ct_motion = ContentType.objects.get(app_label='motion', model='motion') ct_motion = ContentType.objects.get(app_label='motion', model='motion')
perm_4 = Permission.objects.get(content_type=ct_motion, codename='can_see_motion') perm_15 = Permission.objects.get(content_type=ct_motion, codename='can_see_motion')
ct_assignment = ContentType.objects.get(app_label='assignment', model='assignment') ct_assignment = ContentType.objects.get(app_label='assignment', model='assignment')
perm_5 = Permission.objects.get(content_type=ct_assignment, codename='can_see_assignment') perm_16 = Permission.objects.get(content_type=ct_assignment, codename='can_see_assignment')
ct_participant = ContentType.objects.get(app_label='participant', model='user') ct_participant = ContentType.objects.get(app_label='participant', model='user')
perm_6 = Permission.objects.get(content_type=ct_participant, codename='can_see_participant') perm_17 = Permission.objects.get(content_type=ct_participant, codename='can_see_participant')
ct_mediafile = ContentType.objects.get(app_label='mediafile', model='mediafile') ct_mediafile = ContentType.objects.get(app_label='mediafile', model='mediafile')
perm_6a = Permission.objects.get(content_type=ct_mediafile, codename='can_see') perm_18 = Permission.objects.get(content_type=ct_mediafile, codename='can_see')
group_anonymous = Group.objects.create(name=ugettext_noop('Anonymous'), pk=1) group_anonymous = Group.objects.create(name=ugettext_noop('Anonymous'), pk=1)
group_anonymous.permissions.add(perm_1, perm_2, perm_3, perm_3a, perm_4, perm_5, perm_6, perm_6a) group_anonymous.permissions.add(perm_11, perm_12, perm_13, perm_14, perm_15, perm_16, perm_17, perm_18)
group_registered = Group.objects.create(name=ugettext_noop('Registered'), pk=2) group_registered = Group.objects.create(name=ugettext_noop('Registered'), pk=2)
group_registered.permissions.add(perm_1, perm_2, perm_3, perm_3a, perm_4, perm_5, perm_6, perm_6a, can_speak) group_registered.permissions.add(perm_11, perm_12, perm_13, perm_14, perm_15, perm_16, perm_17, perm_18, can_speak)
# Delegates # Delegates (pk 3)
perm_7 = Permission.objects.get(content_type=ct_motion, codename='can_create_motion') perm_31 = Permission.objects.get(content_type=ct_motion, codename='can_create_motion')
perm_8 = Permission.objects.get(content_type=ct_motion, codename='can_support_motion') perm_32 = Permission.objects.get(content_type=ct_motion, codename='can_support_motion')
perm_9 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_other') perm_33 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_other')
perm_10 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_self') perm_34 = Permission.objects.get(content_type=ct_assignment, codename='can_nominate_self')
perm_10a = Permission.objects.get(content_type=ct_mediafile, codename='can_upload') perm_35 = Permission.objects.get(content_type=ct_mediafile, codename='can_upload')
group_delegates = Group.objects.create(name=ugettext_noop('Delegates'), pk=3) group_delegates = Group.objects.create(name=ugettext_noop('Delegates'), pk=3)
group_delegates.permissions.add(perm_7, perm_8, perm_9, perm_10, perm_10a) group_delegates.permissions.add(perm_31, perm_32, perm_33, perm_34, perm_35)
# Staff # Staff (pk 4)
perm_11 = Permission.objects.get(content_type=ct_agenda, codename='can_manage_agenda') perm_41 = Permission.objects.get(content_type=ct_agenda, codename='can_manage_agenda')
perm_12 = Permission.objects.get(content_type=ct_motion, codename='can_manage_motion') perm_42 = Permission.objects.get(content_type=ct_motion, codename='can_manage_motion')
perm_13 = Permission.objects.get(content_type=ct_assignment, codename='can_manage_assignment') perm_43 = Permission.objects.get(content_type=ct_assignment, codename='can_manage_assignment')
perm_14 = Permission.objects.get(content_type=ct_participant, codename='can_manage_participant') perm_44 = Permission.objects.get(content_type=ct_participant, codename='can_manage_participant')
perm_15 = Permission.objects.get(content_type=ct_core, codename='can_manage_projector') perm_45 = Permission.objects.get(content_type=ct_core, codename='can_manage_projector')
perm_15a = Permission.objects.get(content_type=ct_mediafile, codename='can_manage') perm_46 = Permission.objects.get(content_type=ct_core, codename='can_use_chat')
perm_47 = Permission.objects.get(content_type=ct_mediafile, codename='can_manage')
ct_config = ContentType.objects.get(app_label='config', model='configstore') ct_config = ContentType.objects.get(app_label='config', model='configstore')
perm_16 = Permission.objects.get(content_type=ct_config, codename='can_manage') perm_48 = Permission.objects.get(content_type=ct_config, codename='can_manage')
group_staff = Group.objects.create(name=ugettext_noop('Staff'), pk=4) group_staff = Group.objects.create(name=ugettext_noop('Staff'), pk=4)
group_staff.permissions.add(perm_7, perm_9, perm_10, perm_10a, perm_11, perm_12, perm_13, perm_14, perm_15, perm_15a, perm_16) # add delegate permissions (without can_support_motion)
group_staff.permissions.add(perm_6) # TODO: Remove this redundancy after cleanup of the permission system group_staff.permissions.add(perm_31, perm_33, perm_34, perm_35)
# add staff permissions
group_staff.permissions.add(perm_41, perm_42, perm_43, perm_44, perm_45, perm_46, perm_47, perm_48)
# add can_see_participant permission
group_staff.permissions.add(perm_17) # TODO: Remove this redundancy after cleanup of the permission system
# Admin user # Admin user
create_or_reset_admin_user() create_or_reset_admin_user()