Initial import

This commit is contained in:
tonio
2009-03-24 16:59:18 +01:00
commit 18ad148479
58 changed files with 5887 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
.*~$
^[^\.]+\.pyc
+13
View File
@@ -0,0 +1,13 @@
Copyright (c) 2009, Antoine Nguyen <tonio@ngyn.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+29
View File
@@ -0,0 +1,29 @@
Installation
============
Requirements
------------
- Python version 2.5+
- Django version 1.0+ (http://docs.djangoproject.com/en/dev/intro/install/#intro-install)
How to install
--------------
Download Mailng's tarball and extract it::
tar xzf mailng-<version>.tar.gz
Enter the mailng repository, create a settings.py file (you can use settings-sample.py as a model). Specify database relative informations. You must choose between mysql and postgresql, other types are not supported by major email projects like postfix or dovecot.
Initialise the database by running the following command::
python manage.py syncdb
Create the super admin account (just follow the procedure).
Testing installation
--------------------
As a typical Django application, Mailng can be tested using a simple web server. Just run this command to start it::
python manage.py runserver
You will be able to play with mailng by looking at http://<youraddress>:8000/mailng/admin/
+7
View File
@@ -0,0 +1,7 @@
Mailng is a light web messaging solution. It provides different tools that facilitates virtual domains hosting. It is designed to be integrated with email servers like postfix (http://www.postfix.org/) and/or dovecot (http://www.dovecot.org/).
For now, only the administration component is available. Additional tools will come in a near future.
Django is needed to use Mailng (http://www.djangoproject.com/)
Mootools version 1.2 (http://www.mootools.net/) and SqueezeBox version 1.1 (http://digitarald.de/project/squeezebox/) are provided with Mailng.
View File
View File
+34
View File
@@ -0,0 +1,34 @@
from django import forms
from mailng.admin.models import Domain, Mailbox, Alias
class DomainForm(forms.ModelForm):
class Meta:
model = Domain
class MailboxForm(forms.ModelForm):
password1 = forms.CharField(label="Password", widget=forms.PasswordInput)
password2 = forms.CharField(label="Confirmation", widget=forms.PasswordInput)
enabled = forms.BooleanField(label="Enabled", required=False)
class Meta:
model = Mailbox
fields = ('name', 'address', 'quota')
def clean_password2(self):
if self.cleaned_data["password1"] != self.cleaned_data["password2"]:
raise forms.ValidationError("Passwords mismatch")
return self.cleaned_data["password2"]
class AliasForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
domain = None
if kwargs.has_key("domain"):
domain = kwargs["domain"]
del kwargs["domain"]
super(AliasForm, self).__init__(*args, **kwargs)
if domain:
self.fields['mbox'].queryset = Mailbox.objects.filter(domain=domain.id)
class Meta:
model = Alias
+30
View File
@@ -0,0 +1,30 @@
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Domain(models.Model):
name = models.CharField(max_length=100)
quota = models.IntegerField()
enabled = models.BooleanField()
class Mailbox(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
# password = models.CharField(max_length=100)
quota = models.IntegerField()
# enabled = models.BooleanField()
uid = models.IntegerField()
gid = models.IntegerField()
path = models.CharField(max_length=200)
domain = models.ForeignKey(Domain)
user = models.ForeignKey(User)
def __str__(self):
return "%s" % (self.address)
class Alias(models.Model):
address = models.CharField(max_length=100)
mbox = models.ForeignKey(Mailbox)
enabled = models.BooleanField()
View File
+36
View File
@@ -0,0 +1,36 @@
from django import template
from django.template.loader import render_to_string
register = template.Library()
@register.simple_tag
def domain_menu(domain_id, selection):
return render_to_string('admin/domain_menu.html',
{"selection" : selection,
"domain_id" : domain_id})
# class MyVar(template.Node):
# def __init__(self, value, var_name):
# self.var_name = var_name
# self.value = value
# def render(self, context):
# context[self.var_name] = self.value
# return ""
# import re
# @register.tag(name="var")
# def do_my_var(parser, token):
# try:
# tag_name, arg = token.contents.split(None, 1)
# except ValueError:
# raise template.TemplateSyntaxError, '%r tag requires arguments' \
# % token.contents.split()[0]
# m = re.search('(.*?) as (\w+)', arg)
# if not m:
# raise template.TemplateSyntaxError, "%r tag had invalid arguments" \
# % tag_name
# value, var_name = m.groups()
# return MyVar(value, var_name)
+18
View File
@@ -0,0 +1,18 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('mailng.admin.views',
(r'^$', 'domains'),
(r'^domains/$', 'domains'),
(r'^domains/new/', 'newdomain'),
(r'^domains/(?P<dom_id>\d+)/edit/$', 'editdomain'),
(r'^domains/(?P<dom_id>\d+)/delete/$', 'deldomain'),
(r'^domains/(?P<dom_id>\d+)/newmailbox/$', 'newmailbox'),
(r'^domains/(?P<dom_id>\d+)/editmailbox/(?P<mbox_id>\d+)/$', 'editmailbox'),
(r'^domains/(?P<dom_id>\d+)/deletemailbox/(?P<mbox_id>\d+)/$', 'delmailbox'),
(r'^domains/(?P<dom_id>\d+)/newalias/(?P<mbox_id>\d+)/$', 'newalias'),
(r'^domains/(?P<dom_id>\d+)/editalias/(?P<alias_id>\d+)/$', 'editalias'),
(r'^domains/(?P<dom_id>\d+)/$', 'mailboxes'),
url(r'^domains/(?P<dom_id>\d+)/aliases/$', "aliases", name="full-aliases"),
url(r'^domains/(?P<dom_id>\d+)/aliases/(?P<mbox_id>\d+)/$', "aliases", name="mbox-aliases"),
(r'^domains/(?P<dom_id>\d+)/delalias/(?P<alias_id>\d+)/$', 'delalias'),
)
+222
View File
@@ -0,0 +1,222 @@
from django.shortcuts import get_object_or_404, render_to_response
from django.template.loader import render_to_string
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.utils import simplejson
from django.core import serializers
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from mailng import admin
from mailng.admin.models import Domain, Mailbox, Alias
from forms import MailboxForm, DomainForm, AliasForm
def _ctx_ok(url):
return {"status" : "ok", "url" : url}
def _ctx_ko(tpl, ctx):
return {"status" : "ko", "content" : render_to_string(tpl, ctx)}
def _render(request, tpl, user_context):
return render_to_response(tpl, user_context,
context_instance=RequestContext(request))
@login_required
def domains(request):
domains = Domain.objects.all()
counters = {}
for dom in domains:
dom.mboxcounter = len(dom.mailbox_set.all())
return _render(request, 'admin/domains.html', {
"domains" : domains, "counters" : counters
})
@login_required
def newdomain(request):
if request.method == "POST":
form = DomainForm(request.POST)
error = None
if form.is_valid():
if Domain.objects.filter(name=request.POST["name"]):
error = "Domain with this name already defined"
else:
form.save()
ctx = _ctx_ok(reverse(admin.views.domains))
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
ctx = _ctx_ko("admin/newdomain.html", {
"form" : form, "error" : error
})
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
form = DomainForm()
return render_to_response('admin/newdomain.html', {
"form" : form
})
@login_required
def editdomain(request, dom_id):
domain = Domain.objects.get(pk=dom_id)
if request.method == "POST":
form = DomainForm(request.POST, instance=domain)
if form.is_valid():
form.save()
ctx = _ctx_ok(reverse(admin.views.domains))
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
ctx = _ctx_ko("admin/editdomain.html", {
"domain" : domain, "form" : form
})
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
form = DomainForm(instance=domain)
return render_to_response('admin/editdomain.html', {
"domain" : domain, "form" : form
})
@login_required
def deldomain(request, dom_id):
domain = Domain.objects.get(pk=dom_id)
domain.delete()
return HttpResponseRedirect('/mailng/admin/')
@login_required
def mailboxes(request, dom_id=None):
domain = Domain.objects.get(pk=dom_id)
mailboxes = Mailbox.objects.filter(domain=dom_id)
return _render(request, 'admin/mailboxes.html', {
"mailboxes" : mailboxes, "domain" : domain
})
@login_required
def newmailbox(request, dom_id=None):
domain = Domain.objects.get(pk=dom_id)
if request.method == "POST":
form = MailboxForm(request.POST)
error = None
if form.is_valid():
if Mailbox.objects.filter(address=request.POST["address"],
domain=dom_id):
error = "Mailbox with this address already exists"
else:
mb = form.save(commit=False)
user = User()
user.username = user.email = "%s@%s" % (mb.address, domain.name)
user.set_password(request.POST["password1"])
user.is_active = request.POST.has_key("enabled") \
and True or False
fname, lname = mb.name.split()
user.first_name = fname
user.last_name = lname
user.save()
mb.user = user
mb.uid = mb.gid = 500
mb.domain = domain
mb.save()
ctx = _ctx_ok(reverse(admin.views.mailboxes, args=[domain.id]))
return HttpResponse(simplejson.dumps(ctx),
mimetype="application/json")
ctx = _ctx_ko("admin/newmailbox.html", {
"form" : form, "domain" : domain, "error" : error
})
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
form = MailboxForm()
return render_to_response('admin/newmailbox.html', {
"domain" : domain, "form" : form
})
@login_required
def editmailbox(request, dom_id, mbox_id=None):
mb = Mailbox.objects.get(pk=mbox_id)
if request.method == "POST":
form = MailboxForm(request.POST, instance=mb)
if form.is_valid():
if request.POST["enabled"] != mb.user.is_active \
or request.POST["password1"] != mb.user.password:
mb.user.is_active = request.POST["enabled"]
mb.user.password = request.POST["password1"]
mb.user.save()
form.save()
ctx = _ctx_ok(reverse(admin.views.mailboxes, args=[dom_id]))
else:
ctx = _ctx_ko("admin/editmailbox.html", {
"mbox" : mb, "form" : form
})
json = simplejson.dumps(ctx)
return HttpResponse(json, mimetype="application/json")
form = MailboxForm(instance=mb)
form.fields['enabled'].initial = mb.user.is_active
form.fields['password1'].initial = mb.user.password
form.fields['password2'].initial = mb.user.password
return _render(request, 'admin/editmailbox.html', {
"form" : form, "mbox" : mb
})
@login_required
def delmailbox(request, dom_id, mbox_id=None):
mb = Mailbox.objects.get(pk=mbox_id)
mb.delete()
return HttpResponseRedirect(reverse(admin.views.mailboxes,
args=[dom_id]))
@login_required
def aliases(request, dom_id=None, mbox_id=None):
domain = Domain.objects.get(pk=dom_id)
if not mbox_id:
mboxes = Mailbox.objects.filter(domain=dom_id)
aliases = []
for mb in mboxes:
aliases += Alias.objects.filter(mbox=mb.id)
else:
aliases = Alias.objects.filter(mbox=mbox_id)
return _render(request, 'admin/aliases.html', {
"aliases" : aliases, "domain" : domain
})
@login_required
def newalias(request, dom_id, mbox_id):
mbox = Mailbox.objects.get(pk=mbox_id)
if request.method == "POST":
form = AliasForm(request.POST)
if form.is_valid():
form.save()
ctx = _ctx_ok(reverse(admin.views.aliases, args=[mbox.domain.id]))
else:
ctx = _ctx_ko("admin/newalias.html", {
"mbox" : mbox, "form" : form
})
json = simplejson.dumps(ctx)
return HttpResponse(json, mimetype="application/json")
form = AliasForm({"mbox" : mbox_id}, domain=mbox.domain)
return render_to_response('admin/newalias.html', {
"mbox" : mbox, "form" : form, "noerrors" : True
})
@login_required
def editalias(request, dom_id, alias_id):
alias = Alias.objects.get(pk=alias_id)
if request.method == "POST":
form = AliasForm(request.POST, instance=alias)
if form.is_valid():
form.save()
ctx = _ctx_ok(reverse(admin.views.aliases, args=[dom_id]))
else:
ctx = _ctx_ko("admin/editalias.html", {
"alias" : alias, "form" : form
})
json = simplejson.dumps(ctx)
return HttpResponse(json, mimetype="application/json")
form = AliasForm(instance=alias)
return _render(request, 'admin/editalias.html', {
"form" : form, "alias" : alias
})
@login_required
def delalias(request, dom_id, alias_id):
alias = Alias.objects.get(pk=alias_id)
alias.delete()
return HttpResponseRedirect(reverse(admin.views.aliases,
args=[dom_id]))
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env python
from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)
if __name__ == "__main__":
execute_manager(settings)
+82
View File
@@ -0,0 +1,82 @@
# Django settings for mailng project.
DEBUG = False
TEMPLATE_DEBUG = DEBUG
ADMINS = (
# ('Your Name', 'your_email@domain.com'),
)
MANAGERS = ADMINS
DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
DATABASE_NAME = 'mailng' # Or path to database file if using sqlite3.
DATABASE_USER = '' # Not used with sqlite3.
DATABASE_PASSWORD = '' # Not used with sqlite3.
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'America/Chicago'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
LOGIN_REDIRECT_URL = '/mailng/admin/'
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = ''
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = ''
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = '/media/'
# Make this unique, and don't share it with anybody.
SECRET_KEY = '2)e+la#y$1b&v!p)s^&4lwpc92o59fye)mj^3^7$jytmvx379d'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
ROOT_URLCONF = 'mailng.urls'
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'mailng.admin'
)
+384
View File
@@ -0,0 +1,384 @@
/**
* SqueezeBox - Expandable Lightbox
*
* Allows to open various content as modal,
* centered and animated box.
*
* Dependencies: MooTools 1.2 trunk (04/2008)
*
* Inspired by
* ... Lokesh Dhakar - The original Lightbox v2
*
* @version 1.1 rc2
*
* @license MIT-style license
* @author Harald Kirschner <mail [at] digitarald.de>
* @copyright Author
*/
var SqueezeBox = {
presets: {
size: {x: 600, y: 450},
sizeLoading: {x: 200, y: 150},
marginInner: {x: 20, y: 20},
marginImage: {x: 50, y: 75},
handler: false,
target: null,
closable: true,
closeBtn: true,
zIndex: 65555,
overlayOpacity: 0.7,
classWindow: '',
classOverlay: '',
overlayFx: {},
resizeFx: {},
contentFx: {},
parse: false, // 'rel'
parseSecure: false,
ajaxOptions: {},
onOpen: $empty,
onClose: $empty,
onUpdate: $empty,
onResize: $empty,
onMove: $empty,
onShow: $empty,
onHide: $empty
},
initialize: function(presets) {
if (this.options) return this;
this.presets = $merge(this.presets, presets);
this.options = {};
this.setOptions(this.presets).build();
this.bound = {
window: this.reposition.bind(this, [null]),
scroll: this.checkTarget.bind(this),
close: this.close.bind(this),
key: this.onKey.bind(this)
};
this.isOpen = this.isLoading = false;
return this;
},
build: function() {
this.overlay = new Element('div', {
id: 'sbox-overlay',
styles: {display: 'none', zIndex: this.options.zIndex}
});
this.content = new Element('div', {id: 'sbox-content'});
this.closeBtn = new Element('a', {id: 'sbox-btn-close', href: '#'});
this.win = new Element('div', {
id: 'sbox-window',
styles: {display: 'none', zIndex: this.options.zIndex + 2}
}).adopt(this.closeBtn, this.content);
this.fx = {
overlay: new Fx.Tween(this.overlay, $merge({
property: 'opacity',
onStart: Events.prototype.clearChain,
duration: 250,
link: 'cancel'
}, this.options.overlayFx)).set(0),
win: new Fx.Morph(this.win, $merge({
onStart: Events.prototype.clearChain,
unit: 'px',
duration: 750,
transition: Fx.Transitions.Quint.easeOut,
link: 'cancel',
unit: 'px'
}, this.options.resizeFx)),
content: new Fx.Tween(this.content, $merge({
property: 'opacity',
duration: 250,
link: 'cancel'
}, this.options.contentFx)).set(0)
};
$(document.body).adopt(this.overlay, this.win);
},
assign: function(to, options) {
return to.addEvent('click', function() {
return !SqueezeBox.fromElement(this, options);
});
},
fromElement: function(from, options) {
this.initialize();
if (this.element) this.trash();
this.element = $(from);
this.setOptions($merge(this.presets, options || {}));
if (this.element && this.options.parse) {
var obj = this.element.getProperty(this.options.parse);
if (obj && (obj = JSON.decode(obj, this.options.parseSecure))) this.setOptions(obj);
}
this.assignOptions();
this.url = ((this.element) ? (this.options.url || this.element.get('href')) : from) || '';
var handler = this.options.handler;
if (handler) return this.setContent(handler, this.parsers[handler].call(this, true));
var ret = false;
this.parsers.some(function(parser, key) {
var content = parser.call(this);
if (content) {
ret = this.setContent(key, content);
return true;
}
return false;
}, this);
return ret;
},
assignOptions: function() {
this.overlay.set('class', this.options.classOverlay);
this.win.set('class', this.options.classWindow);
if (Browser.Engine.trident4) this.win.addClass('sbox-window-ie6');
},
close: function(e) {
var stoppable = ($type(e) == 'event');
if (stoppable) e.stop();
if (!this.isOpen || (stoppable && !$lambda(this.options.closable).call(this, e))) return this;
this.fx.overlay.start(0).chain(this.toggleOverlay.bind(this));
this.win.setStyle('display', 'none');
this.toggleListeners();
this.isOpen = false;
this.fireEvent('onClose', [this.content]);
this.trash();
return this;
},
trash: function() {
this.element = this.asset = null;
this.options = {};
this.removeEvents().setOptions(this.presets).callChain();
},
onError: function() {
this.asset = null;
this.setContent('string', 'Error during loading');
},
setContent: function(handler, content) {
if (!this.handlers[handler]) return false;
this.content.className = 'sbox-content-' + handler;
this.applyTimer = this.applyContent.delay(this.fx.overlay.options.duration, this, this.handlers[handler].call(this, content));
if (this.overlay.retrieve('opacity')) return this;
this.toggleOverlay(true);
this.fx.overlay.start(this.options.overlayOpacity);
return this.reposition();
},
applyContent: function(content, size) {
this.applyTimer = $clear(this.applyTimer);
this.hideContent();
if (!content) {
this.toggleLoading(true);
} else {
if (this.isLoading) this.toggleLoading(false);
this.fireEvent('onUpdate', [this.content], 20);
}
this.content.empty();
if (['string', 'array', false].contains($type(content))) this.content.set('html', content || '');
else this.content.adopt(content);
this.callChain();
if (!this.isOpen) {
this.toggleListeners(true);
this.resize(size, true);
this.isOpen = true;
this.fireEvent('onOpen', [this.content]);
} else {
this.resize(size);
}
},
resize: function(size, instantly) {
var box = document.getSize(), scroll = document.getScroll();
this.size = $merge((this.isLoading) ? this.options.sizeLoading : this.options.size, size);
var to = {
width: this.size.x,
height: this.size.y,
left: (scroll.x + (box.x - this.size.x - this.options.marginInner.x) / 2).toInt(),
top: (scroll.y + (box.y - this.size.y - this.options.marginInner.y) / 2).toInt()
};
$clear(this.showTimer || null);
this.hideContent();
if (!instantly) {
this.fx.win.start(to).chain(this.showContent.bind(this));
} else {
this.win.setStyles(to).setStyle('display', '');
this.showTimer = this.showContent.delay(50, this);
}
return this.reposition();
},
toggleListeners: function(state) {
var fn = (state) ? 'addEvent' : 'removeEvent';
this.closeBtn[fn]('click', this.bound.close);
this.overlay[fn]('click', this.bound.close);
document[fn]('keydown', this.bound.key)[fn]('mousewheel', this.bound.scroll);
window[fn]('resize', this.bound.window)[fn]('scroll', this.bound.window);
},
toggleLoading: function(state) {
this.isLoading = state;
this.win[(state) ? 'addClass' : 'removeClass']('sbox-loading');
if (state) this.fireEvent('onLoading', [this.win]);
},
toggleOverlay: function(state) {
this.overlay.setStyle('display', (state) ? '' : 'none');
$(document.body)[(state) ? 'addClass' : 'removeClass']('body-overlayed');
},
showContent: function() {
if (this.content.get('opacity')) this.fireEvent('onShow', [this.win]);
this.fx.content.start(1);
},
hideContent: function() {
if (!this.content.get('opacity')) this.fireEvent('onHide', [this.win]);
this.fx.content.set(0);
},
onKey: function(e) {
switch (e.key) {
case 'esc': this.close(e);
case 'up': case 'down': return false;
}
},
checkTarget: function(e) {
return this.content.hasChild(e.target);
},
reposition: function() {
var size = document.getSize(), scroll = document.getScroll();
this.overlay.setStyles({
left: scroll.x + 'px',
top: scroll.y + 'px',
width: size.x + 'px',
height: size.y + 'px'
});
this.win.setStyles({
left: (scroll.x + (size.x - this.win.offsetWidth) / 2).toInt() + 'px',
top: (scroll.y + (size.y - this.win.offsetHeight) / 2).toInt() + 'px'
});
return this.fireEvent('onMove', [this.overlay, this.win]);
},
removeEvents: function(type){
if (!this.$events) return this;
if (!type) this.$events = null;
else if (this.$events[type]) this.$events[type] = null;
return this;
},
extend: function(properties) {
return $extend(this, properties);
},
handlers: new Hash(),
parsers: new Hash()
};
SqueezeBox.extend(new Events($empty)).extend(new Options($empty)).extend(new Chain($empty));
SqueezeBox.parsers.extend({
image: function(preset) {
return (preset || (/\.(?:jpg|png|gif)$/i).test(this.url)) ? this.url : false;
},
clone: function(preset) {
if ($(this.options.target)) return $(this.options.target);
if (this.element && !this.element.parentNode) return this.element;
var bits = this.url.match(/#([\w-]+)$/);
return (bits) ? $(bits[1]) : (preset ? this.element : false);
},
ajax: function(preset) {
return (preset || (this.url && !(/^(?:javascript|#)/i).test(this.url))) ? this.url : false;
},
iframe: function(preset) {
return (preset || this.url) ? this.url : false;
},
string: function(preset) {
return true;
}
});
SqueezeBox.handlers.extend({
image: function(url) {
var size, tmp = new Image();
this.asset = null;
tmp.onload = tmp.onabort = tmp.onerror = (function() {
tmp.onload = tmp.onabort = tmp.onerror = null;
if (!tmp.width) {
this.onError.delay(10, this);
return;
}
var box = document.getSize();
box.x -= this.options.marginImage.x;
box.y -= this.options.marginImage.y;
size = {x: tmp.width, y: tmp.height};
for (var i = 2; i--;) {
if (size.x > box.x) {
size.y *= box.x / size.x;
size.x = box.x;
} else if (size.y > box.y) {
size.x *= box.y / size.y;
size.y = box.y;
}
}
size.x = size.x.toInt();
size.y = size.y.toInt();
this.asset = $(tmp);
tmp = null;
this.asset.setProperties({width: size.x, height: size.y});
if (this.isOpen) this.applyContent(this.asset, size);
}).bind(this);
tmp.src = url;
if (tmp && tmp.onload && tmp.complete) tmp.onload();
return (this.asset) ? [this.asset, size] : null;
},
clone: function(el) {
return el.clone();
},
adopt: $arguments(0),
ajax: function(url) {
this.asset = new Request.HTML($merge({
method: 'get'
}, this.options.ajaxOptions)).addEvents({
onSuccess: function(resp) {
this.applyContent(resp);
this.asset = null;
}.bind(this),
onFailure: this.onError.bind(this)
});
this.asset.send.delay(10, this.asset, [{url: url}]);
},
iframe: function(url) {
return new Element('iframe', $merge({
src: url,
frameBorder: 0,
width: this.options.size.x,
height: this.options.size.y
}, this.options.iframeOptions));
},
string: function(str) {
return str;
}
});
SqueezeBox.handlers.url = SqueezeBox.handlers.ajax;
SqueezeBox.parsers.url = SqueezeBox.parsers.ajax;
SqueezeBox.parsers.adopt = SqueezeBox.parsers.clone;
+92
View File
@@ -0,0 +1,92 @@
window.addEvent('domready', function() {
var handlers = new Array();
// handlers['loadDom'] = function(obj, target) {
/* $$('a[name=loadDom]').setStyles({'color' : '#999'});*/
/* obj.setStyles({"color": "black"});*/
// loadPage(target, "content", null);
// };
// handlers['loadContent'] = function(obj, target) {
// loadPage(target, "content", null);
// };
if ($$("a[name=deleteDom]"))
$$("a[name=deleteDom]").addEvent('click', function(event) {
if (!confirm("Delete this domain?"))
event.stop();
});
if ($$("a[name=deleteMb]"))
$$("a[name=deleteMb]").addEvent('click', function(event) {
if (!confirm("Delete this mailbox?"))
event.stop();
});
if ($$("a[name=deleteAlias]"))
$$("a[name=deleteAlias]").addEvent('click', function(event) {
if (!confirm("Delete this alias?"))
event.stop();
});
handlers['deleteDom'] = function(obj, target) {
return confirm("Supprimer ce domaine?");
}
$('body').addEvent('click', function(event) {
target = event.target;
if (target.get('tag') == 'a') {
name = target.get('name');
if (name == 'undefined')
return;
if (typeof(handlers[name]) != 'undefined') {
if (!handlers[name](target, target.get('href'))) {
new Event(event).stop();
}
}
}
});
$('body').addEvent('submit', function(event) {
alert("newodm submit");
target = event.target;
if (target.get('tag') == 'form') {
name = target.get('name');
if (name == 'undefined')
return;
if (typeof(handlers[name]) != 'undefined') {
new Event(event).stop();
handlers[name](target);
}
}
});
SqueezeBox.assign($$('a.boxed'), {
//size: {x:300, y:180}
parse: 'rel',
});
});
newdom = function() {
alert("pouet");
form = $("form[name=newdom]");
var params = obj.toQueryString();
form.set('send', {
onSuccess: function(response) {
SqueezeBox.loadModal(obj.action + '?' + params);
}
}).send();
};
loadPage = function(url, destination, callback) {
var destination = (destination == null) ? "page" : destination;
if (callback)
new Request({url: url, method: "get", onSuccess: callback}).send();
else
new Request({url: url, method: "get", onSuccess: function(data) {
$(destination).set('html', data);
}}).send();
};
+40
View File
@@ -0,0 +1,40 @@
window.addEvent("domready", function() {
sqbsubmit = function(obj, dest, id, callback) {
obj.set('send', {
onSuccess: function(responseText) {
response = JSON.decode(responseText);
if (response.status == "ko") {
$(dest).set("html", response.content);
$(id).addEvent("submit", callback);
} else {
parent.SqueezeBox.close();
parent.location.href = response.url;
}
}
});
obj.send();
}
generic_submit = function(obj, event, id, callback) {
event.stop();
sqbsubmit(obj, "content", id, callback);
}
domain_submit = function(event) {
generic_submit(this, event, "domform", domain_submit);
}
mailbox_submit = function(event) {
generic_submit(this, event, "mboxform", mailbox_submit);
}
alias_submit = function(event) {
generic_submit(this, event, "aliasform", alias_submit);
}
if ($("domform"))
$("domform").addEvent("submit", domain_submit);
if ($("mboxform"))
$("mboxform").addEvent("submit", mailbox_submit);
if ($("aliasform"))
$("aliasform").addEvent("submit", alias_submit);
});
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 619 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

+78
View File
@@ -0,0 +1,78 @@
#sbox-window embed, #sbox-window object, #sbox-window select
{
visibility: visible;
}
#sbox-overlay
{
position: absolute;
background-color: #000;
}
#sbox-window
{
position: absolute;
background-color: #fff;
text-align: left;
overflow: visible;
padding: 10px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
#sbox-btn-close
{
position: absolute;
width: 30px;
height: 30px;
right: -15px;
top: -15px;
background: url(closebox.png) no-repeat center;
border: none;
}
.sbox-window-ie6 #sbox-btn-close
{
background-image: url(closebox.gif);
}
.sbox-loading #sbox-content
{
background-image: url(spinner.gif);
background-repeat: no-repeat;
background-position: center;
}
#sbox-content
{
clear: both;
overflow: auto;
background-color: #fff;
height: 100%;
width: 100%;
}
.sbox-content-image#sbox-content
{
overflow: visible;
}
#sbox-image
{
display: block;
}
.sbox-content-image img
{
display: block;
}
.sbox-content-iframe#sbox-content
{
overflow: visible;
}
.body-overlayed embed, .body-overlayed object, .body-overlayed select
{
visibility: hidden;
}
+275
View File
@@ -0,0 +1,275 @@
body {
font-family: arial, helvetica, verdana, tahoma, sans-serif;
font-size: small;
background: #153F65;
width: 950px;
margin: 0 auto;
padding: 0;
}
#header {
width: 100%;
height: 120px;
background: #072342;
margin-top: 20px;
border: 1px solid #333;
}
#header h1 {
color: white;
}
#header h2 {
margin-left: 20px;
color: #6AB0C5;
}
#header h3 {
margin: 0 0 5px 0;
text-align: center;
font-size: small;
}
#logo {
float: left;
margin-top: 20px;
background: url(logo.png) left no-repeat;
height: 90px;
line-height: 90px;
min-width: 90px;
width: expression(document.body.clientWidth < 1280 ? "90px" : "15%");
}
#title {
float: left;
margin-left: 10px;
}
#info {
float: right;
text-align: center;
background: white;
width: 150px;
margin: 20px 20px;
padding: 10px;
border: 1px solid #333;
}
#body {
float: left;
width: 100%;
margin: 15px 0;
/*height: 600px;*/
}
#loginbox {
margin: 50px auto;
width: 300px;
padding-bottom: 15px;
border: 1px solid #ddd;
background: white;
}
#loginbox h3 {
font-size: small;
text-align: center;
}
#leftcol {
float: left;
}
.leftbox {
border: 1px solid #333;
background: white;
}
#menubox {
width: 170px;
}
#userbox {
width: 170px;
}
.leftbox h3 {
font-size: small;
margin: 2px 0px 2px 0px;
text-align: center;
}
.leftbox ul {
list-style: none;
padding: 5px 5px;
margin: 0;
}
.leftbox li {
clear: both;
margin-bottom: 4px;
}
.leftbox a:link, .leftbox a:visited {
background: transparent;
color: black;
font-weight: bold;
text-decoration: none;
}
.leftbox a:hover {
color: #6AB0C5;
text-decoration: none;
}
.leftbox img {
float: left;
margin-right: 2px;
}
#content {
float: right;
width: 750px;
height: 400px;
background: white;
border: 1px solid #333;
padding: 5px;
margin: 0 0 0 15px;
}
#menubar {
margin-left: 20px;
display: table;
margin-bottom: 15px;
}
.menu2 {
font-size: 95%;
white-space: nowrap;
}
.menu2 ul {
margin: 0;
padding: 0;
list-style: none;
float: left;
width: 100%;
}
.menu2 li {
float: left;
display: inline;
margin: 2px 5px;
}
.menu2 li.selected {
/* text-decoration: underline;*/
background: #ffffcc;
}
.menu2 a:link, .menu2 a:visited {
background: transparent;
color: black;
font-weight: bold;
text-decoration: none;
}
.menu2 a:hover {
color: #6AB0C5;
}
.menu2 img {
float: left;
margin: 1px 3px;
}
#footer {
border-top: 1px solid #333;
text-align: center;
padding-top: 15px;
}
.spacer {
clear: both;
}
.title {
float: left;
width: 100%;
margin-bottom: 5px;
}
.title img {
float: left;
margin: 1px 3px;;
}
.title h1 {
float: left;
margin: 5px 10px;
font-size: medium;
font-weight: bold;
}
#body table {
margin: 0 auto;
width: 100%;
border-collapse: collapse;
border-spacing: 20px;
}
#body tr.odd {
background: #F7F9Fb;
}
#body tr.even {
background: white;
}
#body table th {
background: #CEDBEC;
text-align: left;
padding: 5px;
}
#body table th.right {
text-align: right;
}
#body table td {
border-bottom: 1px solid #C8D6E8;
padding: 5px;
}
#body a, a:visited {
color: #2a4069;
text-decoration: none;
}
#body a:hover {
text-decoration: underline;
}
#domcontent {
margin: 10px auto;
width: 90%;
}
.button {
margin-left: 35px;
}
.button img {
float: left;
margin: 0px 3px;
border: 0;
}
.header {
margin-left: 20px;
margin-bottom: 20px;
}
.header h1 {
font-size: medium;
}
+74
View File
@@ -0,0 +1,74 @@
body {
font-family: arial, helvetica, verdana, tahoma, sans-serif;
font-size: small;
margin: 0 auto;
padding: 0;
}
div.row {
clear: both;
padding-top: 10px;
padding-left: 20px;
}
div.row label {
float: left;
width: 120px;
font-size: small;
padding: 3px 0;
}
form input {
border: 1px solid #cccccc;
color: inherit;
/*background-color: #e9e9e9;*/
background-color: #eee;
width: 120px;
padding: 2px;
}
form input:hover {
color: inherit;
background-color: #ffffcc;
}
.title {
float: left;
width: 100%;
margin-bottom: 5px;
}
.title img {
float: left;
margin: 1px 3px;;
}
.title h1 {
float: left;
margin: 5px 10px;
font-size: medium;
font-weight: bold;
}
.lastrow {
margin-top: 20px;
}
.errorlist ul {
float: left;
list-style: none;
}
.errorlist li {
margin-left: 10px;
float: left;
display: inline;
color: red;
}
.error {
margin-left: 20px;
color: red;
font-size: small;
font-weight: bold;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 495 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+38
View File
@@ -0,0 +1,38 @@
{% extends "admin/domain_header.html" %}
{% block menu %}
{% load admin_extras %}
{% domain_menu domain.id "aliases" %}
{% endblock %}
{% block domcontent %}
{% if not aliases %}
<p>No alias defined.</p>
{% else %}
<table>
<tr>
<th width="50px">Actions</th>
<th width="150px">Address</th>
<th width="200px">Mailbox</th>
<th width="75px">Enabled</th>
</tr>
{% for alias in aliases %}
<tr>
<td>
{% url admin.views.editalias domain.id alias.id as edit_url %}
<a href="{{ edit_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:190}}">
<img src="/static/pics/edit.png" border="0" title="Edit alias"/>
</a>
<a href="{{ del_url }}" name="deleteAlias">
<img src="/static/pics/remove.png" border="0" title="Delete alias" />
</a>
</td>
<td>{{ alias.address }}@{{ alias.mbox.domain.name }}</td>
<td>{{ alias.mbox.address }}@{{ alias.mbox.domain.name }}</td>
<td>{{ alias.enabled|yesno }}</td
{% url admin.views.delalias domain.id alias.id as del_url %}
</tr>
{% endfor %}
</table>
{% endif %}
{% endblock %}
+17
View File
@@ -0,0 +1,17 @@
{% extends "admin/layout.html" %}
{% block html_head %}
<script src="/static/js/domains.js" type="text/javascript"></script>
{% endblock %}
{% block mainframe %}
<div class="header">
<h1>Domain {{ domain.name }}</h1>
</div>
<div id="menubar" class="menu2">
{% block menu %}{% endblock %}
</div>
<div id="domcontent">
{% block domcontent %}{% endblock %}
</div>
{% endblock %}
+27
View File
@@ -0,0 +1,27 @@
{% url admin.views.editdomain domain_id as edit_url %}
{% url admin.views.newmailbox domain_id as new_url %}
{% url admin.views.mailboxes domain_id as mboxes_url %}
{% url full-aliases domain_id as aliases_url %}
<ul>
{% url admin.views.newmailbox domain.id as newmb_url %}
<li>
<a href="{{ new_url }}"
class="boxed" rel="{handler:'iframe',size:{x:300,y:280}}">
<img src="/static/pics/add.png" border="0" />
New mailbox
</a>
</li>
<li {% ifequal selection "mailboxes" %}class="selected"{% endifequal %}>
<a href="{{ mboxes_url }}">
<img src="/static/pics/mailbox.png" border="0"/>
Mailboxes</a></li>
<li {% ifequal selection "aliases" %}class="selected"{% endifequal %}>
<a href="{{ aliases_url }}">
<img src="/static/pics/alias.png" border="0"/>
Aliases</a></li>
<li>
<a href="{{ edit_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:180}}">
<img src="/static/pics/edit.png" border="0"/>
Properties</a></li>
</ul>
+45
View File
@@ -0,0 +1,45 @@
{% extends "admin/layout.html" %}
{% block html_head %}
<script src="/static/js/domains.js" type="text/javascript"></script>
{% endblock %}
{% block mainframe %}
<div class="header">
<h1>Available domains</h1>
</div>
<div id="domcontent">
{% if not domains %}
No domain defined.
{% else %}
<table>
<tr>
<th width="50px">Actions</th>
<th width="80px">Name</th>
<th width="50px">Mailboxes</th>
<th width="50px">Quota</th>
<th width="50px">Enabled</th>
</tr>
{% for dom in domains %}
<tr class="{% cycle 'odd' 'even' %}">
<td>
{% url admin.views.editdomain dom.id as edit_url %}
<a href="{{ edit_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:180}}">
<img src="/static/pics/edit.png" border="0" title="Edit domain"/>
</a>
{% url admin.views.deldomain dom.id as del_url %}
<a href="{{ del_url }}" name="deleteDom">
<img src="/static/pics/remove.png" border="0" title="Delete domain"/>
</a>
</td>
{% url admin.views.mailboxes dom.id as domurl %}
<td><a name="loadDom" href="{{ domurl }}">{{ dom.name }}</a></td>
<td>{{ dom.mboxcounter }}</td>
<td>{{ dom.quota }} MB</td>
<td>{{ dom.enabled|yesno }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
</div>
{% endblock %}
+15
View File
@@ -0,0 +1,15 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>Alias {{ alias.address }}</h1></div>
{% url admin.views.editalias alias.mbox.domain.id alias.id as edit_url %}
<form action="{{ edit_url }}" method="POST" id="aliasform" name="aliasform">
{% include "admin/genericform.html" %}
<div class="spacer"></div>
<div class="lastrow" align="center">
<input type="submit" name="submit" value="Update" />
</div>
</form>
{% endblock %}
+16
View File
@@ -0,0 +1,16 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>Domain {{ domain.name }}</h1></div>
{% url admin.views.editdomain domain.id as dom_url %}
<form action="{{ dom_url }}" method="post" name="domform" id="domform">
{% include "admin/genericform.html" %}
<div class="lastrow" align="center">
<input type="submit" class="button" name="submit" value="Update" />
</div>
</form>
{% endblock %}
+17
View File
@@ -0,0 +1,17 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>Mailbox {{ mbox.name }}</h1></div>
{% url admin.views.editmailbox mbox.domain_id mbox.id as box_url %}
<form action="{{ box_url }}" method="POST" id="mboxform" name="mboxform">
{% include "admin/genericform.html" %}
<div class="spacer"></div>
<div class="lastrow" align="center">
<input type="submit" name="submit" value="Update" />
</div>
</form>
{% endblock %}
+5
View File
@@ -0,0 +1,5 @@
{% for field in form %}
<div class="row">
{{ field.label_tag }} {{ field }} {% ifequal noerrors False %}{{ field.errors }}{% endifequal %}
</div>
{% endfor %}
+12
View File
@@ -0,0 +1,12 @@
{% extends "admin/layout.html" %}
{%block pagetitle %}Administration{%endblock %}
{%block breadcrumb %}Domains{%endblock %}
{% block html_head %}
<script src="/static/js/domains.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
{% include default %}
{% endblock %}
+48
View File
@@ -0,0 +1,48 @@
{% extends "layout.html" %}
{% block content %}
{% url admin.views.domains as dom_url %}
<div id="body">
<div id="leftcol">
<div id="userbox" class="leftbox">
{% if user.first_name %}
<h3>{{ user.first_name }} {{ user.last_name }}</h3>
{% else %}
<h3>{{ user.username }}</h3>
{% endif %}
<ul>
<li>
{% url django.contrib.auth.views.logout_then_login as logout_url %}
<a href="{{ logout_url }}">
<img src="/static/pics/logout.png" border="0" />Logout</a>
</li>
</ul>
</div>
<br/>
<div id="menubox" class="leftbox">
<ul>
<li>
{% url admin.views.newdomain as newdom_url %}
<a href="{{ newdom_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:200}}">
<img src="/static/pics/add.png" border="0"/>
New domain
</a>
</li>
<li>
<a name="loadContent" href="{{ dom_url }}">
<img src="/static/pics/domains.png" border="0"/>
Domains</a>
</li>
<li>
<a name="loadContent" href="">
<img src="/static/pics/settings.png" border="0"/>
Settings</a>
</li>
</ul>
</div>
</div>
<div id="content">
{%block mainframe %}{% endblock %}
</div>
</div>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/SqueezeBox.css" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/box.css" />
<script src="/static/js/mootools.js" type="text/javascript"></script>
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
{%block html_head %}{% endblock %}
</head>
<body>
<div id="content">
{%block content %}{% endblock %}
</div>
</body>
</html>
+22
View File
@@ -0,0 +1,22 @@
{% extends "admin/layout.html" %}
{% block html_head %}{% endblock %}
{% block content %}
<div class="header">
<h1>Mailbox {{ mbox.address }}@{{ mbox.domain.name }}</h1>
</div>
<div id="menubar" class="menu2">
{% block menu %}{% endblock %}
</div>
<div id="mboxcontent">
<div class="row">
<label>Name :</label><label>{{ mb.name }}</label>
</div>
<h2>Aliases</h2>
{% for alias in aliases %}
{{ alias.address }}
{% endfor %}
</div>
{% endblock %}
+50
View File
@@ -0,0 +1,50 @@
{% extends "admin/domain_header.html" %}
{% block menu %}
{% load admin_extras %}
{% domain_menu domain.id "mailboxes" %}
{% endblock %}
{% block domcontent %}
{% if not mailboxes %}
<p>No mailbox defined.</p>
{% else %}
<table>
<tr>
<th width="80px">Actions</th>
<th width="130px">Name</th>
<th width="170px">Address</th>
<th width="60px">Quota</th>
<th width="50px">Enabled</th>
</tr>
{% for mb in mailboxes %}
<tr class="{% cycle 'odd' 'even' %}">
<td>
{% url admin.views.editmailbox domain.id mb.id as edit_url %}
<a href="{{ edit_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:280}}">
<img src="/static/pics/edit.png" border="0" title="Edit mailbox"/>
</a>
{% url admin.views.delmailbox domain.id mb.id as del_url %}
<a href="{{ del_url }}" name="deleteMb">
<img src="/static/pics/remove.png" border="0"
title="Delete mailbox" />
</a>
{% url admin.views.newalias domain.id mb.id as alias_url %}
<a href="{{ alias_url }}" class="boxed"
rel="{handler:'iframe',size:{x:300,y:190}}">
<img src="/static/pics/add.png" border="0" title="Add new alias"/>
</a>
{% url mbox-aliases domain.id mb.id as aliases_url %}
<a href="{{ aliases_url }}">
<img src="/static/pics/alias.png" border="0" title="Mailbox aliases"/>
</a>
</td>
<td>{{ mb.name }}</td>
<td>{{ mb.address }}@{{ mb.domain.name }}</td>
<td>{{ mb.quota }} MB</td>
<td>{{ mb.user.is_active|yesno }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endblock %}
+14
View File
@@ -0,0 +1,14 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>Aliases for {{ mbox.address }}</h1></div>
<p>
<ul>
{% for alias in aliases %}
<li>{{alias.address}}</li>
{% endfor %}
</ul>
</p>
{% endblock %}
+15
View File
@@ -0,0 +1,15 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>New alias</h1></div>
{% url admin.views.newalias mbox.domain_id mbox.id as box_url %}
<form action="{{ box_url }}" method="POST" id="aliasform" name="aliasform">
{% include "admin/genericform.html" %}
<div class="spacer"></div>
<div class="lastrow" align="center">
<input type="submit" name="submit" value="Create" />
</div>
</form>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>New domain</h1></div>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
{% url admin.views.newdomain as dom_url %}
<form action="{{ dom_url }}" method="post" name="domform" id="domform">
{% include "admin/genericform.html" %}
<div class="lastrow" align="center">
<input type="submit" class="button" name="submit" value="Create" />
</div>
</form>
{% endblock %}
²
+18
View File
@@ -0,0 +1,18 @@
{% extends "admin/layout_simple.html" %}
{% block html_head %}
<script src="/static/js/form.js" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="title"><h1>New mailbox</h1></div>
{% if error %}<div class="error">{{ error }}</div>{% endif %}
{% url admin.views.newmailbox domain.id as box_url %}
<form action="{{ box_url }}" method="POST" id="mboxform" name="mboxform">
{% include "admin/genericform.html" %}
<div class="spacer"></div>
<div class="lastrow" align="center">
<input type="submit" name="submit" value="Create" />
</div>
</form>
{% endblock %}
+36
View File
@@ -0,0 +1,36 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MailNG - {%block pagetitle %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="/static/stylesheets/basic.css" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/SqueezeBox.css" />
<script src="/static/js/mootools.js" type="text/javascript"></script>
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
{%block html_head %}{% endblock %}
</head>
<body>
<div id="header" class="rounded">
<div id="logo"></div>
<div id="title">
<h1>MailNG</h1>
<h2>Simple web messaging solution</h2>
<div id="info"></div>
</div>
</div>
<div id="content">
{%block content %}{% endblock %}
</div>
<div class="spacer"></div>
<div id="footer">
&copy; Antoine Nguyen 2009
</div>
</body>
</html>
+29
View File
@@ -0,0 +1,29 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MailNG - {%block pagetitle %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="/static/stylesheets/basic.css" />
<link rel="stylesheet" type="text/css" href="/static/stylesheets/SqueezeBox.css" />
<script src="/static/js/mootools.js" type="text/javascript"></script>
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
{%block html_head %}{% endblock %}
</head>
<body>
<div id="header" class="rounded">
<div id="logo"></div>
<div id="title">
<h1>MailNG</h1>
<h2>Simple web messaging solution</h2>
</div>
</div>
{% block content %}{% endblock %}
<div class="spacer"></div>
<div id="footer">
&copy; Antoine Nguyen 2009
</div>
</body>
</html>
+25
View File
@@ -0,0 +1,25 @@
{% extends "layout.html" %}
{% block html_head %}
<link rel="stylesheet" type="text/css" href="/static/stylesheets/box.css" />
{% endblock %}
{% block content %}
<div id="loginbox">
<h3>Welcome</h3>
{% if form.errors %}
<div class="error">
<p>Your username and password didn't match. Please try again.</p>
</div>
{% endif %}
<form method="post" action=".">
{% for field in form %}
<div class="row">
{{ field.label_tag }}{{ field }}
</div>
{% endfor %}
<div class="lastrow" align="center">
<input type="submit" value="login" />
</div>
<input type="hidden" name="next" value="{{ next }}" />
</form>
</div>
{% endblock %}
+29
View File
@@ -0,0 +1,29 @@
from django.conf.urls.defaults import *
from django.conf import settings
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^mailng/', include('mailng.foo.urls')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# (r'^admin/(.*)', admin.site.root),
(r'^mailng/admin/', include('mailng.admin.urls')),
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
(r'^accounts/logout/$', 'django.contrib.auth.views.logout_then_login')
)
if settings.DEBUG:
urlpatterns += patterns(
'',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/home/tonio/projets/mailng/static'})
)