Commit 09c7de10 authored by eric's avatar eric
Browse files

Pull in the django etherpadlite bridge fork from...

Pull in the django etherpadlite bridge fork from https://github.com/codingisacopingstrategy/django-etherpad-lite/zipball/master

We need to edit these models
parent f002fc15
# -*- coding: utf-8 -*-
from django.contrib import admin
from etherpadlite.models import *
class PadAuthorAdmin(admin.ModelAdmin):
list_display = ('__unicode__',)
class PadAdmin(admin.ModelAdmin):
list_display = ('__unicode__',)
admin.site.register(PadServer)
admin.site.register(PadGroup)
admin.site.register(PadAuthor, PadAuthorAdmin)
admin.site.register(Pad, PadAdmin)
"""
This file centralizes configuration of this module
"""
# This sets the number of seconds to keep the session cookie and server side
# session alive for an author's access to a pad. The default is one day
SESSION_LENGTH = 1 * 24 * 60 * 60
# Uncomment this tuple and supply values to define a testing server for the
# automated tests
#
# TESTING_SERVER = {
# 'title': 'Testing Server',
# 'url': 'http://example.com:9001',
# 'apikey': 'secret'
# }
from django import forms
from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _
class PadCreate(forms.Form):
name = forms.CharField(label=_("Name"))
group = forms.CharField(widget=forms.HiddenInput)
class GroupCreate(forms.ModelForm):
class Meta:
model = Group
exclude = ('permissions')
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-04-23 20:05-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
#: forms.py:5
msgid "Name"
msgstr "Nom"
#: models.py:12
msgid "URL"
msgstr "URL"
#: models.py:13
msgid "API key"
msgstr "clé API"
#: models.py:14
msgid "description"
msgstr "déscription"
#: models.py:17
msgid "server"
msgstr "serveur"
#: models.py:38
msgid "group"
msgstr "groupe"
#: models.py:85
msgid "author"
msgstr "auteur"
#: views.py:29
#, python-format
msgid "Create pad in %(grp)s"
msgstr "Créer un pad dans %(grp)s"
#: views.py:47
msgid "Really delete this pad?"
msgstr "Effacer vraiment ce pad?"
#: views.py:47
#, python-format
msgid "Deleting %(pad)s"
msgstr "Effacer %(pad)s"
#: views.py:100
msgid "You are not allowed to view or edit this pad"
msgstr "Vous ne pouvez pas visionner ou modifier ce pad"
#: views.py:118
msgid "etherpad-lite session request returned:"
msgstr "retour de la demande de session à etherpad-lite"
#: templates/etherpad-lite/base.html:16
msgid "profile"
msgstr "profile"
#: templates/etherpad-lite/base.html:17
msgid "logout"
msgstr "déconnecter"
#: templates/etherpad-lite/confirm.html:13
msgid "No"
msgstr "Non"
#: templates/etherpad-lite/confirm.html:14
msgid "Yes"
msgstr "Oui"
#: templates/etherpad-lite/login.html:5 templates/etherpad-lite/login.html:8
#: templates/etherpad-lite/login.html:26
msgid "Login"
msgstr "Connexion"
#: templates/etherpad-lite/login.html:10
msgid "Your username and password didn't match. Please try again."
msgstr "Votre pseudo ou votre mot de passe sont incorrecte. Veuillez ressayer."
#: templates/etherpad-lite/logout.html:5
#, fuzzy
msgid "Logout"
msgstr "Déconnexion"
#: templates/etherpad-lite/logout.html:8
msgid "You have been logged out."
msgstr "Vous êtes déconnecté."
#: templates/etherpad-lite/logout.html:8
msgid "Log back in."
msgstr "Reconnectez vous"
#: templates/etherpad-lite/padCreate.html:19
msgid "Create"
msgstr "Créer"
#: templates/etherpad-lite/profile.html:11
msgid "PADS:"
msgstr "PADS:"
#: templates/etherpad-lite/profile.html:17
msgid "Del"
msgstr "Supprimer"
#: templates/etherpad-lite/profile.html:19
msgid "Add"
msgstr "Ajouter"
# coding=utf-8
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import simplejson
class Command(BaseCommand):
def execute(self, *args, **kwargs):
# Etherpad-lite's default configuration
conf = {
"ip": "0.0.0.0",
"port": 9001,
'databaseAlias': 'default',
"defaultPadText": "",
"requireSession": False,
"editOnly": False,
"minify": True,
"maxAge": 6 * 60 * 60 * 1000,
"abiword": None,
"loglevel": "INFO"
}
conf.update(getattr(settings, 'ETHERPAD_CONFIGURATION', {}))
# TODO: "Classic" database definition, i.e. DATABASE_ENGINE etc.
# Dict-style database definition
if 'databaseAlias' in conf and not 'dbType' in conf:
if conf['databaseAlias'] in settings.DATABASES:
dbconf = settings.DATABASES[conf['databaseAlias']]
conf['dbSettings'] = {}
engine = dbconf['ENGINE']
if engine == 'django.db.backends.sqlite3':
conf['dbType'] = 'sqlite'
conf['dbSettings']['filename'] = dbconf['NAME']
if engine == 'django.db.backends.mysql':
conf['dbType'] = 'mysql'
conf['dbSettings']['database'] = dbconf['NAME']
conf['dbSettings']['user'] = dbconf['USER']
conf['dbSettings']['password'] = dbconf['PASSWORD']
conf['dbSettings']['host'] = dbconf['HOST']
if engine == 'django.contrib.gis.db.backends.postgis' or \
engine == 'django.db.backends.postgresql_psycopg2':
conf['dbType'] = 'postgres'
conf['dbSettings']['database'] = dbconf['NAME']
conf['dbSettings']['user'] = dbconf['USER']
conf['dbSettings']['password'] = dbconf['PASSWORD']
conf['dbSettings']['host'] = dbconf['HOST']
del conf['databaseAlias']
print simplejson.dumps(conf, indent=4 * ' ')
from django.db import models
from django.db.models.signals import pre_delete
from django.contrib.auth.models import User, Group
from django.utils.translation import ugettext_lazy as _
from py_etherpad import EtherpadLiteClient
import string
import random
class PadServer(models.Model):
"""Schema and methods for etherpad-lite servers
"""
title = models.CharField(max_length=256)
url = models.URLField(
max_length=256,
verbose_name=_('URL')
)
apikey = models.CharField(max_length=256, verbose_name=_('API key'))
notes = models.TextField(_('description'), blank=True)
class Meta:
verbose_name = _('server')
def __unicode__(self):
return self.url
@property
def apiurl(self):
if self.url[-1:] == '/':
return "%sapi" % self.url
else:
return "%s/api" % self.url
class PadGroup(models.Model):
"""Schema and methods for etherpad-lite groups
"""
group = models.ForeignKey(Group)
groupID = models.CharField(max_length=256, blank=True)
server = models.ForeignKey(PadServer)
class Meta:
verbose_name = _('group')
def __unicode__(self):
return self.group.__unicode__()
@property
def epclient(self):
return EtherpadLiteClient(self.server.apikey, self.server.apiurl)
def _get_random_id(self, size=6,
chars=string.ascii_uppercase + string.digits + string.ascii_lowercase):
""" To make the ID unique, we generate a randomstring
"""
return ''.join(random.choice(chars) for x in range(size))
def EtherMap(self):
result = self.epclient.createGroupIfNotExistsFor(
self.group.__unicode__() + self._get_random_id() +
self.group.id.__str__()
)
self.groupID = result['groupID']
return result
def save(self, *args, **kwargs):
if not self.id:
self.EtherMap()
super(PadGroup, self).save(*args, **kwargs)
def Destroy(self):
# First find and delete all associated pads
Pad.objects.filter(group=self).delete()
return self.epclient.deleteGroup(self.groupID)
def padGroupDel(sender, **kwargs):
"""Make sure groups are purged from etherpad when deleted
"""
grp = kwargs['instance']
grp.Destroy()
pre_delete.connect(padGroupDel, sender=PadGroup)
def groupDel(sender, **kwargs):
"""Make sure our groups are destroyed properly when auth groups are deleted
"""
grp = kwargs['instance']
# Make shure auth groups without a pad group can be deleted, too.
try:
padGrp = PadGroup.objects.get(group=grp)
padGrp.Destroy()
except Exception:
pass
pre_delete.connect(groupDel, sender=Group)
class PadAuthor(models.Model):
"""Schema and methods for etherpad-lite authors
"""
user = models.ForeignKey(User)
authorID = models.CharField(max_length=256, blank=True)
server = models.ForeignKey(PadServer)
group = models.ManyToManyField(
PadGroup,
blank=True,
null=True,
related_name='authors'
)
class Meta:
verbose_name = _('author')
def __unicode__(self):
return self.user.__unicode__()
def EtherMap(self):
epclient = EtherpadLiteClient(self.server.apikey, self.server.apiurl)
result = epclient.createAuthorIfNotExistsFor(
self.user.id.__str__(),
name=self.__unicode__()
)
self.authorID = result['authorID']
return result
def GroupSynch(self, *args, **kwargs):
for ag in self.user.groups.all():
try:
gr = PadGroup.objects.get(group=ag)
except PadGroup.DoesNotExist:
gr = False
if (isinstance(gr, PadGroup)):
self.group.add(gr)
super(PadAuthor, self).save(*args, **kwargs)
def save(self, *args, **kwargs):
self.EtherMap()
super(PadAuthor, self).save(*args, **kwargs)
class Pad(models.Model):
"""Schema and methods for etherpad-lite pads
"""
name = models.CharField(max_length=256)
server = models.ForeignKey(PadServer)
group = models.ForeignKey(PadGroup)
def __unicode__(self):
return self.name
@property
def padid(self):
return "%s$%s" % (self.group.groupID, self.name)
@property
def epclient(self):
return EtherpadLiteClient(self.server.apikey, self.server.apiurl)
def Create(self):
return self.epclient.createGroupPad(self.group.groupID, self.name)
def Destroy(self):
return self.epclient.deletePad(self.padid)
def isPublic(self):
result = self.epclient.getPublicStatus(self.padid)
return result['publicStatus']
def ReadOnly(self):
return self.epclient.getReadOnlyID(self.padid)
def save(self, *args, **kwargs):
self.Create()
super(Pad, self).save(*args, **kwargs)
def padDel(sender, **kwargs):
"""Make sure pads are purged from the etherpad-lite server on deletion
"""
pad = kwargs['instance']
pad.Destroy()
pre_delete.connect(padDel, sender=Pad)
/*********
* Layout *
**********/
/* Center nav and main areas */
#nav,
#main,
#footer {
min-width: 768px;
width: 55%;
margin: 0 auto;
}
#content,
#sidebar,
div.inliner {
display: inline-block;
vertical-align: top;
padding: 0 .5em;
}
#sidebar {
width: 250px;
float: right;
}
#wrapper {
width: 100%;
clear: both;
}
#footer {
clear: both;
}
/* Text alignment and padding rules */
#nav {
text-align: right;
}
#nav #navlinks {
display: inline-block;
}
#nav a.nav {
margin: 0 .5em;
font-size: 16px;
}
#main {
padding: 0 1em;
text-align: justify;
}
h1, h2, h3, h4, h5, h6 {
text-align: left;
}
input.submit {
font-size: 100%;
padding: .2em 1em;
}
a.action {
margin-left: 1em;
}
div.form {
margin-top: 1em;
}
ul.plain {
padding-left: 1em;
list-style-type: none;
}
/**********************
* Fonts & text style *
**********************/
body {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
font-weight: normal;
}
#nav a.nav {
font-weight: bold;
text-decoration: none;
}
label {
font-weight: bold;
}
a.action {
font-weight: bold;
text-transform: uppercase;
font-size: 80%;
}
/*********************
* Colours & Borders *
*********************/
body {
background-color: #fff;
}
#wrapper {
border-top: 4px solid #000;
}
a {
color: #047;
}
a:hover {
color: #c00;
}
img {
border-style: none;
}
#errors {
color: #c00;
font-weight: bold;
}
input.submit {
background-color: #047;
color: #fff;
}
/***************
* Fancy Stuff *
***************/
#wrapper {
box-shadow: inset 0 30px 40px #eee;
-moz-box-shadow: inset 0 30px 40px #eee;
-webkit-box-shadow: inset 0 30px 40px #eee;
-o-box-shadow: inset 0 30px 40px #eee;
}
input.submit {
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-o-border-radius: 10px;
}
a.act-add {
background: transparent url('../img/add.png') no-repeat;
}
a.act-del {
background: transparent url('../img/del.png') no-repeat;
}
a.act-add, a.act-del {
height: 20px;
width: 20px;
color: transparent;
display: inline-block;
vertical-align: text-bottom;
}
<!DOCTYPE html>
{% load i18n %}
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta charset="UTF-8" />
<title>{% block title %}{% endblock %}</title>
<link href="{{ STATIC_URL }}etherpad-lite/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js" ></script>
</head>
<body>
<div id="nav"><nav>
{% block nav %}
{% if user.is_authenticated %}