Merge branch 'master' into 'master'

Master

- Du nettoyage (suppression des `.pyc`, `__pycache__`)
- Édition du `.gitignore`
- Mise à jour avec la version en ligne à `www.ernestophone.ens.fr`

See merge request !1
This commit is contained in:
Martin Pépin 2016-06-24 20:53:49 +02:00
commit 7baecebbfb
179 changed files with 14770 additions and 147 deletions

6
.gitignore vendored
View file

@ -1 +1,5 @@
*/migrations/* .pyc
media/
db.sqlite3
Ernestophone/settings.py
__pycache__

Binary file not shown.

Binary file not shown.

View file

@ -10,24 +10,27 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
MEDIA_ROOT = 'media/'
MEDIA_URL = 'media/'
EMAIL_HOST='clipper.ens.fr' BASE_DIR = os.path.dirname(os.path.dirname(__file__))
EMAIL_PORT= 25
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
# Quick-start development settings - unsuitable for production # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/ # See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '+9czchiqs@imvckb6e7-msqdu!e^c9b7n1&+*qgo%p7ackwu7$' SECRET_KEY = 'ax0|dG^AhtYfXPXgu3*e|k3l^yKpbK;$~(_%q/5C!H9yHA(Z(2'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
TEMPLATE_DEBUG = True TEMPLATE_DEBUG = True
ALLOWED_HOSTS = [] ALLOWED_HOSTS = ['*']
# Application definition # Application definition
@ -43,6 +46,7 @@ INSTALLED_APPS = (
'partitions', 'partitions',
'calendrier', 'calendrier',
'propositions', 'propositions',
'pads',
) )
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
@ -87,17 +91,17 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/ # https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = ( STATICFILES_DIRS = (
'static', os.path.join(BASE_DIR, 'static'),
'media/partitions', os.path.join(BASE_DIR, 'media/partitions'),
) )
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
'templates/gestion/', os.path.join(BASE_DIR, 'templates/gestion/'),
'templates/', os.path.join(BASE_DIR, 'templates/'),
) )
AUTH_PROFILE_MODEL = 'gestion.ErnestoUser' AUTH_PROFILE_MODEL = 'gestion.ErnestoUser'
LOGIN_URL = "/login" LOGIN_URL = "/login"

Binary file not shown.

View file

@ -11,8 +11,15 @@ urlpatterns = patterns('',
url(r'^login/?$', 'gestion.views.login', ), url(r'^login/?$', 'gestion.views.login', ),
url(r'^logout/?$', 'django.contrib.auth.views.logout', {'next_page': '/'}, ), url(r'^logout/?$', 'django.contrib.auth.views.logout', {'next_page': '/'}, ),
url(r'^registration/?$', 'gestion.views.inscription_membre'), url(r'^registration/?$', 'gestion.views.inscription_membre'),
url(r'^change/?', 'gestion.views.change_membre'),
url(r'^password/?', 'gestion.views.change_password'),
url(r'^user/password/reset/$', 'django.contrib.auth.views.password_reset', {'post_reset_redirect': '/user/password/reset/done/'}, name="password_reset"),
url(r'^user/password/reset/done/$', 'django.contrib.auth.views.password_reset_done'),
url(r'^user/password/reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', 'django.contrib.auth.views.password_reset_confirm', {'post_reset_redirect': '/user/password/done/'}, name="password_reset_confirm"),
url(r'^user/password/done/$', 'django.contrib.auth.views.password_reset_complete'),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^partitions/', include('partitions.urls')), url(r'^partitions/', include('partitions.urls')),
url(r'^pads/', include('pads.urls')),
url(r'^calendar/', include('calendrier.urls')), url(r'^calendar/', include('calendrier.urls')),
url(r'^propositions/', include('propositions.urls')), url(r'^propositions/', include('propositions.urls')),
url(r'^divers/', 'gestion.views.divers'), url(r'^divers/', 'gestion.views.divers'),

View file

@ -1,3 +1,4 @@
""" """
WSGI config for Ernestophone project. WSGI config for Ernestophone project.
@ -8,7 +9,7 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
""" """
import os import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ernestophone.settings") os.environ["DJANGO_SETTINGS_MODULE"] = "Ernestophone.settings"
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
application = get_wsgi_application() application = get_wsgi_application()

View file

@ -0,0 +1,16 @@
Ernesto
=======
Pour installer le site :
1. Copier le fichier de settings et l'adapter à ses besoins.
- `cp Ernestophone/settings-example.py Ernestophone/settings.py`.
- Principalement, éditer `STATIC_ROOT` et `MEDIA_ROOT`.
- **Penser à changer la `SECRET_KEY`**.
2. Appliquer les migrations `python manage.py migrate`.
3. Puis :
- En production :
- charger les fichiers statiques : `python manage.py collectstatic`
- Lancer le serveur après avoir configuré le serveur web.
- En développement : lancer le serveur `python manage.py runserver`.
Le site est alors accessible à `localhost:8000`.

Binary file not shown.

View file

@ -20,7 +20,7 @@ class EventCalendar(HTMLCalendar):
body = [] body = []
for ev in self.events[day]: for ev in self.events[day]:
body.append('<a href="/calendar/%s">' % ev.id) body.append('<a href="/calendar/%s">' % ev.id)
body.append(esc(ev.nomcourt)) body.append(esc(ev.nom))
body.append('</a><br/>') body.append('</a><br/>')
return self.day_cell(cssclass, '<div class="dayNumber">%d</div> %s' % (day, ''.join(body))) return self.day_cell(cssclass, '<div class="dayNumber">%d</div> %s' % (day, ''.join(body)))
return self.day_cell(cssclass, '<div class="dayNumber">%d</div>' % day) return self.day_cell(cssclass, '<div class="dayNumber">%d</div>' % day)

View file

@ -1,11 +1,12 @@
from django import forms from django import forms
from calendrier.models import Event, Participants from calendrier.models import Event, Participants
from gestion.models import ErnestoUser
class ModifEventForm(forms.ModelForm): class ModifEventForm(forms.ModelForm):
class Meta: class Meta:
model = Event model = Event
widgets = { widgets = {
'description': forms.Textarea(attrs={"placeholder":"facultatif"}), 'description': forms.Textarea(attrs={"placeholder":"facultatif, balises html supportées"}),
'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}), 'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}),
'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}), 'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
'fin': forms.TextInput(attrs={"placeholder": 'hh:mm facultatif'}) 'fin': forms.TextInput(attrs={"placeholder": 'hh:mm facultatif'})
@ -20,7 +21,8 @@ class EventForm(forms.ModelForm):
class Meta: class Meta:
model = Event model = Event
widgets = { widgets = {
'description': forms.Textarea(attrs={"placeholder":"facultatif"}), 'nomcourt': forms.TextInput(attrs={"placeholder": '9 caractères max'}),
'description': forms.Textarea(attrs={"placeholder":"facultatif, balises html supportées"}),
'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}), 'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}),
'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}), 'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
'fin': forms.TextInput(attrs={"placeholder": 'hh:mm facultatif'}) 'fin': forms.TextInput(attrs={"placeholder": 'hh:mm facultatif'})
@ -29,4 +31,23 @@ class EventForm(forms.ModelForm):
class ParticipantsForm(forms.ModelForm): class ParticipantsForm(forms.ModelForm):
class Meta: class Meta:
model = Participants model = Participants
fields = ('reponse', ) fields = ('reponse', 'details')
widgets = {
'details': forms.Textarea(attrs={"placeholder": "50 caractères max"}),
}
class ChangeDoodleName(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ChangeDoodleName, self).__init__(*args, **kwargs)
self.fields['doodlename'].initial = self.instance.profile.doodlename
def save(self, *args, **kwargs):
super(ChangeDoodleName, self).save(*args, **kwargs)
self.instance.profile.doodlename = self.cleaned_data['doodlename']
self.instance.save()
self.instance.profile.save()
class Meta:
model = ErnestoUser
fields = ('doodlename',)

View file

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('gestion', '0003_auto_20151014_1904'),
]
operations = [
migrations.CreateModel(
name='Event',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
('nom', models.CharField(max_length=100)),
('nomcourt', models.CharField(verbose_name='Nom court', max_length=9)),
('date', models.DateField()),
('debut', models.TimeField()),
('fin', models.TimeField(blank=True, null=True)),
('slug', models.CharField(max_length=7, editable=False, unique=True)),
('lieu', models.CharField(max_length=200)),
('description', models.TextField(blank=True)),
('calendrier', models.BooleanField(verbose_name='Afficher dans le calendrier pour tous', default=False)),
],
options={
'verbose_name': 'Événement',
},
bases=(models.Model,),
),
migrations.CreateModel(
name='Participants',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, primary_key=True, auto_created=True)),
('reponse', models.CharField(verbose_name='Réponse', choices=[('oui', 'Oui'), ('non', 'Non'), ('pe', 'Peut-être')], default='non', max_length=20)),
('details', models.CharField(blank=True, max_length=50)),
('event', models.ForeignKey(to='calendrier.Event')),
('participant', models.ForeignKey(to='gestion.ErnestoUser')),
],
options={
},
bases=(models.Model,),
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('calendrier', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='event',
name='desc_users',
field=models.TextField(null=True, verbose_name='Infos (visible seulement des fanfaron-ne-s)', blank=True),
preserve_default=True,
),
]

View file

View file

@ -16,6 +16,7 @@ class Event(models.Model):
slug = models.CharField(max_length=7, editable=False, unique=True) slug = models.CharField(max_length=7, editable=False, unique=True)
lieu = models.CharField(max_length=200) lieu = models.CharField(max_length=200)
description = models.TextField(blank=True) description = models.TextField(blank=True)
desc_users = models.TextField(blank=True, verbose_name="Infos (visible seulement des fanfaron-ne-s)", null=True)
calendrier = models.BooleanField(default=False, verbose_name="Afficher dans le calendrier pour tous") calendrier = models.BooleanField(default=False, verbose_name="Afficher dans le calendrier pour tous")
def __str__(self): def __str__(self):
@ -28,5 +29,6 @@ class Participants(models.Model):
event = models.ForeignKey(Event) event = models.ForeignKey(Event)
participant = models.ForeignKey(ErnestoUser) participant = models.ForeignKey(ErnestoUser)
reponse = models.CharField("Réponse", max_length = 20, default = "non", choices = ANSWERS) reponse = models.CharField("Réponse", max_length = 20, default = "non", choices = ANSWERS)
details = models.CharField(max_length=50, blank=True)
# Create your models here. # Create your models here.

View file

View file

@ -7,6 +7,7 @@ urlpatterns = patterns('calendrier.views',
url(r'^edition/(?P<pk>\d+)$', EventUpdate.as_view()), url(r'^edition/(?P<pk>\d+)$', EventUpdate.as_view()),
url(r'^supprimer/(?P<pk>\d+)$', EventDelete.as_view()), url(r'^supprimer/(?P<pk>\d+)$', EventDelete.as_view()),
url(r'^resend/(?P<id>\d+)$', 'resend'), url(r'^resend/(?P<id>\d+)$', 'resend'),
url(r'^changename/?$', 'changename'),
url(r'(?P<id>\d+)/reponse/?', 'reponse'), url(r'(?P<id>\d+)/reponse/?', 'reponse'),
url(r'(?P<codeus>\w{6})/(?P<codeev>\w{6})/oui', 'repouidir'), url(r'(?P<codeus>\w{6})/(?P<codeev>\w{6})/oui', 'repouidir'),
url(r'(?P<codeus>\w{6})/(?P<codeev>\w{6})/pe', 'reppedir'), url(r'(?P<codeus>\w{6})/(?P<codeev>\w{6})/pe', 'reppedir'),

View file

@ -1,5 +1,5 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from calendrier.forms import ModifEventForm, EventForm, ParticipantsForm, SendMail from calendrier.forms import ModifEventForm, EventForm, ParticipantsForm, SendMail, ChangeDoodleName
from calendrier.models import Event, Participants from calendrier.models import Event, Participants
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.views.generic import UpdateView, DeleteView from django.views.generic import UpdateView, DeleteView
@ -64,6 +64,8 @@ def calendar(request, pYear, pMonth):
def view_event(request, pYear, pMonth, id): def view_event(request, pYear, pMonth, id):
ev = Event.objects.get(id=id) ev = Event.objects.get(id=id)
if not request.user.is_authenticated() and not ev.calendrier:
return redirect('calendrier.views.home')
nom = ev.nom.capitalize nom = ev.nom.capitalize
fin = False fin = False
desc = False desc = False
@ -79,6 +81,8 @@ def view_event(request, pYear, pMonth, id):
def view_eventbis(request, id): def view_eventbis(request, id):
ev = Event.objects.get(id=id) ev = Event.objects.get(id=id)
if not request.user.is_authenticated() and not ev.calendrier:
return redirect('calendrier.views.home')
part = ev.participants_set.all() part = ev.participants_set.all()
nom = ev.nom.capitalize nom = ev.nom.capitalize
fin = False fin = False
@ -102,12 +106,14 @@ def resend(request, id):
message = form.cleaned_data["message"] message = form.cleaned_data["message"]
try: try:
for user in users: for user in users:
Subject = ev.nom + ", le " + ev.date.strftime('%d/%m/%Y') if user.mails:
Subject = "[Pouet-Pouet] " + ev.nom + ", le " + ev.date.strftime('%d/%m/%Y')
sender = 'fanfare@ens.fr' sender = 'fanfare@ens.fr'
receivers = [user.user.email] receivers = [user.user.email]
text = "Bonjour, un évémenent a été créé." text = "Bonjour, un évémenent a été créé."
if message != '': if message != '':
text = message text = message
text+= '\n Pour voir l\'événement, allez sur http://www.ernestophone.ens.fr/calendar/' + str(ev.id) +'\n'
text+= '\nPour répondre oui, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/oui' text+= '\nPour répondre oui, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/oui'
text+= '\nPour répondre non, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/non' text+= '\nPour répondre non, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/non'
text+= '\nPour répondre peut-être, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/pe' text+= '\nPour répondre peut-être, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + ev.slug + '/pe'
@ -119,6 +125,17 @@ def resend(request, id):
form = SendMail() form = SendMail()
return render(request, "calendrier/resend.html", locals()) return render(request, "calendrier/resend.html", locals())
@login_required
def changename(request):
if request.method == 'POST':
requbis = request.POST.copy()
form = ChangeDoodleName(requbis, instance=request.user)
if form.is_valid():
form.save()
success=True
else:
form = ChangeDoodleName(instance=request.user)
return render(request, 'calendrier/changename.html', locals())
@chef_required @chef_required
def create_event(request): def create_event(request):
@ -146,13 +163,15 @@ def create_event(request):
if sendmail: if sendmail:
users = ErnestoUser.objects.filter(is_ernesto=True) users = ErnestoUser.objects.filter(is_ernesto=True)
for user in users: for user in users:
if user.mails:
try: try:
Subject = nom + ", le " + date Subject = "[Pouet-Pouet] " + nom + ", le " + date
sender = 'fanfare@ens.fr' sender = 'fanfare@ens.fr'
receivers = [user.user.email] receivers = [user.user.email]
text = "Bonjour, un évémenent a été créé." text = "Bonjour, un évémenent a été créé."
if message != '': if message != '':
text = message text = message
text+= '\n Pour voir l\'événement, allez sur http://www.ernestophone.ens.fr/calendar/' + str(obj.id) +'\n'
text+= '\nPour répondre oui, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/oui' text+= '\nPour répondre oui, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/oui'
text+= '\nPour répondre non, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/non' text+= '\nPour répondre non, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/non'
text+= '\nPour répondre peut-être, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/pe' text+= '\nPour répondre peut-être, allez sur http://www.ernestophone.ens.fr/calendar/' + user.slug + '/' + obj.slug + '/pe'
@ -223,6 +242,7 @@ def reppedir(request, codeus, codeev):
obj.reponse="pe" obj.reponse="pe"
obj.save() obj.save()
envoi = True envoi = True
return redirect('calendrier.views.home')
def repnondir(request, codeus, codeev): def repnondir(request, codeus, codeev):
part = ErnestoUser.objects.get(slug=codeus) part = ErnestoUser.objects.get(slug=codeus)

Binary file not shown.

Binary file not shown.

View file

@ -3,7 +3,6 @@ from django.contrib.auth.models import User, Group
from gestion.models import ErnestoUser from gestion.models import ErnestoUser
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from calendrier.models import Event from calendrier.models import Event
from propositions.models import Prop
class UserProfileInline(admin.StackedInline): class UserProfileInline(admin.StackedInline):
model = ErnestoUser model = ErnestoUser
@ -22,6 +21,7 @@ User.profile_phone = ProfileInfo("phone", "Telephone")
User.profile_instru = ProfileInfo("instru", "Instrument joué") User.profile_instru = ProfileInfo("instru", "Instrument joué")
User.profile_is_ern = ProfileInfo("is_ernesto", "Ernestophoniste") User.profile_is_ern = ProfileInfo("is_ernesto", "Ernestophoniste")
User.profile_is_chef = ProfileInfo("is_chef", "Chef Fanfare") User.profile_is_chef = ProfileInfo("is_chef", "Chef Fanfare")
User.profile_get_mails = ProfileInfo("mails", "Recevoir les mails")
class UserProfileAdmin(UserAdmin): class UserProfileAdmin(UserAdmin):
list_display = ('username', 'first_name', 'last_name', 'email', 'profile_phone', 'profile_instru', 'profile_is_ern', 'profile_is_chef',) list_display = ('username', 'first_name', 'last_name', 'email', 'profile_phone', 'profile_instru', 'profile_is_ern', 'profile_is_chef',)
@ -30,7 +30,7 @@ class UserProfileAdmin(UserAdmin):
ordering = ('username',) ordering = ('username',)
search_fields = ('username', 'first_name', 'last_name', 'profile__phone', 'profile__instru',) search_fields = ('username', 'first_name', 'last_name', 'profile__phone', 'profile__instru',)
inlines = [ UserProfileInline, ] inlines = [ UserProfileInline, ]
fieldsets = (('Général', { 'fields': ('username', 'first_name', 'last_name', ) }), fieldsets = (('Général', { 'fields': ('username', 'password', 'first_name', 'last_name', ) }),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser' )}) ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser' )})
) )
@ -39,5 +39,4 @@ admin.site.unregister(User)
admin.site.unregister(Group) admin.site.unregister(Group)
admin.site.register(User, UserProfileAdmin) admin.site.register(User, UserProfileAdmin)
admin.site.register(Event) admin.site.register(Event)
admin.site.register(Prop)
# Register your models here. # Register your models here.

View file

@ -1,7 +1,7 @@
from django import forms from django import forms
from gestion.models import ErnestoUser from gestion.models import ErnestoUser
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class RegistrationFormUser(UserCreationForm): class RegistrationFormUser(UserCreationForm):
class Meta: class Meta:
@ -13,3 +13,42 @@ class InscriptionMembreForm(forms.ModelForm):
class Meta: class Meta:
model = ErnestoUser model = ErnestoUser
fields = ("phone", "instru", ) fields = ("phone", "instru", )
class ChangeMembreForm(forms.ModelForm):
first_name = forms.CharField(max_length=30, required=False)
last_name = forms.CharField(max_length=50, required=False)
email = forms.EmailField()
mails = forms.BooleanField(label="Recevoir les mails", required=False)
def __init__(self, *args, **kwargs):
super(ChangeMembreForm, self).__init__(*args, **kwargs)
self.fields['first_name'].initial = self.instance.first_name
self.fields['last_name'].initial = self.instance.last_name
self.fields['email'].initial = self.instance.email
self.fields['instru'].initial = self.instance.profile.instru
self.fields["phone"].initial = self.instance.profile.phone
self.fields["mails"].initial = self.instance.profile.mails
self.fields.keyOrder = [
'first_name',
'last_name',
'email',
'phone',
'instru',
'mails',
]
def save(self, *args, **kwargs):
super(ChangeMembreForm, self).save(*args, **kwargs)
self.instance.first_name = self.cleaned_data['first_name']
self.instance.last_name = self.cleaned_data['last_name']
self.instance.email = self.cleaned_data['email']
self.instance.profile.instru = self.cleaned_data["instru"]
self.instance.profile.phone = self.cleaned_data["phone"]
self.instance.profile.mails = self.cleaned_data["mails"]
self.instance.save()
self.instance.profile.save()
class Meta:
model = ErnestoUser
fields = ("phone", "instru", "mails")

View file

@ -16,12 +16,10 @@ class Migration(migrations.Migration):
model_name='ernestouser', model_name='ernestouser',
name='phone', name='phone',
field=models.CharField(max_length=20, blank=True, verbose_name='Téléphone'), field=models.CharField(max_length=20, blank=True, verbose_name='Téléphone'),
preserve_default=True,
), ),
migrations.AlterField( migrations.AlterField(
model_name='ernestouser', model_name='ernestouser',
name='user', name='user',
field=models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='profile'), field=models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='profile'),
preserve_default=True,
), ),
] ]

View file

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('gestion', '0002_auto_20150413_1705'),
]
operations = [
migrations.AlterModelOptions(
name='ernestouser',
options={'verbose_name_plural': 'Profil Ernestophoniste', 'verbose_name': 'Profil Ernestophoniste'},
),
migrations.AddField(
model_name='ernestouser',
name='doodlename',
field=models.CharField(max_length=30, default='afafa', blank=True, verbose_name='Nom pour le doodle'),
preserve_default=False,
),
migrations.AddField(
model_name='ernestouser',
name='slug',
field=models.CharField(max_length=7, default='fafafa', editable=False, unique=True),
preserve_default=False,
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('gestion', '0003_auto_20151014_1904'),
]
operations = [
migrations.AddField(
model_name='ernestouser',
name='mails',
field=models.BooleanField(default=True, verbose_name='Recevoir les mails'),
preserve_default=True,
),
]

View file

@ -10,6 +10,8 @@ class ErnestoUser(models.Model):
phone = models.CharField("Téléphone", max_length=20, blank=True) phone = models.CharField("Téléphone", max_length=20, blank=True)
instru = models.CharField("Instrument joué", max_length=40, blank=True) instru = models.CharField("Instrument joué", max_length=40, blank=True)
slug = models.CharField(max_length=7, editable=False, unique=True) slug = models.CharField(max_length=7, editable=False, unique=True)
doodlename = models.CharField("Nom pour le doodle", max_length=30, blank=True)
mails = models.BooleanField("Recevoir les mails", default=True)
class Meta: class Meta:
verbose_name = "Profil Ernestophoniste" verbose_name = "Profil Ernestophoniste"

Binary file not shown.

View file

@ -1,7 +1,8 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth.views import login as django_login_view from django.contrib.auth.views import login as django_login_view
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm
from django.contrib.auth.decorators import login_required
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
@ -9,7 +10,7 @@ from email.mime.text import MIMEText
from datetime import * from datetime import *
import smtplib import smtplib
from gestion.forms import InscriptionMembreForm, RegistrationFormUser from gestion.forms import InscriptionMembreForm, RegistrationFormUser, ChangeMembreForm
from gestion.models import ErnestoUser from gestion.models import ErnestoUser
from propositions.utils import generer from propositions.utils import generer
@ -34,7 +35,7 @@ def inscription_membre(request):
except: except:
temp=False temp=False
member.save() member.save()
(profile, _) = ErnestoUser.objects.get_or_create(user = member) (profile, _) = ErnestoUser.objects.get_or_create(user = member, slug=code)
comp_form = InscriptionMembreForm(requbis, instance = profile) comp_form = InscriptionMembreForm(requbis, instance = profile)
obj = comp_form.save(commit=False) obj = comp_form.save(commit=False)
obj.slug=code obj.slug=code
@ -46,6 +47,30 @@ def inscription_membre(request):
user_form = RegistrationFormUser() user_form = RegistrationFormUser()
return render(request, 'gestion/registration.html', locals()) return render(request, 'gestion/registration.html', locals())
@login_required
def change_password(request):
if request.method == 'POST':
requbis = request.POST.copy()
form = PasswordChangeForm(request.user, data=requbis)
if form.is_valid():
form.save()
success = True
else:
form = PasswordChangeForm(request.user)
return render(request, 'gestion/changepasswd.html', locals())
@login_required
def change_membre(request):
if request.method == 'POST':
requbis=request.POST.copy()
form = ChangeMembreForm(requbis, instance = request.user)
if form.is_valid():
form.save()
success=True
else:
form = ChangeMembreForm(instance=request.user)
return render(request, 'gestion/change.html', locals())
def home(request): def home(request):
lToday = datetime.now() lToday = datetime.now()
return calendar(request, lToday.year, lToday.month) return calendar(request, lToday.year, lToday.month)
@ -63,6 +88,7 @@ def login(request):
pass pass
return django_login_view(request, template_name = 'login.html', ) return django_login_view(request, template_name = 'login.html', )
@login_required
def divers(request): def divers(request):
return render(request, "gestion/divers.html", locals()) return render(request, "gestion/divers.html", locals())

0
manage.py Normal file → Executable file
View file

Binary file not shown.

0
pads/__init__.py Normal file
View file

3
pads/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

7
pads/forms.py Normal file
View file

@ -0,0 +1,7 @@
from django import forms
from pads.models import Pad
class PadForm(forms.ModelForm):
class Meta:
model = Pad
fields = ('nom', 'url',)

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
]
operations = [
migrations.CreateModel(
name='Pad',
fields=[
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)),
('nom', models.CharField(max_length=100)),
('url', models.URLField()),
('date', models.DateField(verbose_name='Créé le')),
],
options={
'verbose_name': 'Pad',
},
bases=(models.Model,),
),
]

View file

14
pads/models.py Normal file
View file

@ -0,0 +1,14 @@
from django.db import models
class Pad(models.Model):
nom = models.CharField(max_length=100)
url = models.URLField()
date = models.DateField(verbose_name="Créé le")
def __str__(self):
return self.nom
class Meta:
verbose_name="Pad"
# Create your models here.

3
pads/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
pads/urls.py Normal file
View file

@ -0,0 +1,9 @@
from django.conf.urls import patterns, url
from pads.views import PadUpdate, PadDelete
urlpatterns = patterns('pads.views',
url(r'^$', 'liste_pads'),
url(r'^ajouter$', 'add_pad'),
url(r'^edition/(?P<pk>\d+)$', PadUpdate.as_view()),
url(r'^supprimer/(?P<pk>\d+)$', PadDelete.as_view()),
)

48
pads/views.py Normal file
View file

@ -0,0 +1,48 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.core.urlresolvers import reverse_lazy
from django.views.generic import UpdateView, DeleteView
from django.utils.decorators import method_decorator
from datetime import date
from pads.models import Pad
from pads.forms import PadForm
from partitions.decorators import chef_required
@login_required
def liste_pads(request):
pads = Pad.objects.all().order_by("-date")
return render(request, "pads/liste.html", locals())
@chef_required
def add_pad(request):
if request.method == "POST":
form = PadForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.date = date.today()
obj.save()
envoi = True
else:
form = PadForm()
return render(request, "pads/create.html", locals())
class PadUpdate(UpdateView):
model = Pad
template_name="pads/update.html"
success_url=reverse_lazy(liste_pads)
@method_decorator(chef_required)
def dispatch(self, *args, **kwargs):
return super(PadUpdate, self).dispatch(*args, **kwargs)
class PadDelete(DeleteView):
model = Pad
template_name = "pads/delete.html"
success_url = reverse_lazy(liste_pads)
@method_decorator(chef_required)
def dispatch(self, *args, **kwargs):
return super(PadDelete, self).dispatch(*args, **kwargs)
# Create your views here.

Binary file not shown.

Binary file not shown.

View file

@ -8,12 +8,3 @@ def is_chef(user):
return False return False
chef_required = user_passes_test(lambda u: is_chef(u)) chef_required = user_passes_test(lambda u: is_chef(u))
def is_ernesto(user):
try:
profile = user.profile
return profile.is_ernesto
except:
return False
ernesto_required = user_passes_test(lambda u: is_ernesto(u))

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('partitions', '0005_partition_morceau'),
]
operations = [
migrations.AddField(
model_name='partitionset',
name='category',
field=models.CharField(choices=[('active', 'Actif'), ('incoming', 'À venir'), ('old', 'Archive')], max_length=8, verbose_name='Types de partitions', default='incoming'),
preserve_default=True,
),
migrations.AddField(
model_name='partitionset',
name='infos',
field=models.TextField(null=True, blank=True, verbose_name='Infos utiles'),
preserve_default=True,
),
]

View file

@ -3,6 +3,12 @@ import os
import Ernestophone.settings import Ernestophone.settings
PARTITION_TYPES = (
("active", "Actif"),
("incoming", "À venir"),
("old", "Archive"),
)
class Partition(models.Model): class Partition(models.Model):
nom = models.CharField(max_length=100) nom = models.CharField(max_length=100)
part = models.FileField(upload_to="partitions/") part = models.FileField(upload_to="partitions/")
@ -18,8 +24,14 @@ class Partition(models.Model):
class PartitionSet(models.Model): class PartitionSet(models.Model):
nom = models.CharField(max_length=100) nom = models.CharField(max_length=100)
auteur = models.CharField(max_length=100) auteur = models.CharField(max_length=100)
category = models.CharField('Types de partitions', max_length=8,
choices=PARTITION_TYPES, default="incoming")
infos = models.TextField("Infos utiles", null=True, blank=True)
def __str__(self): def __str__(self):
return self.nom + " - " + self.auteur return("%s - %s [%s]" % (self.nom, self.auteur,
self.get_category_display()))
def get_category(self):
return
# Create your models here.

Binary file not shown.

View file

@ -1,17 +1,25 @@
from django.shortcuts import render, redirect, HttpResponse, render_to_response from django.shortcuts import render, redirect, HttpResponse, render_to_response,\
get_object_or_404
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.utils.encoding import smart_str from django.utils.encoding import smart_str
from django.forms.models import modelform_factory
import os import os
from partitions.forms import UploadFileForm, UploadMorceauForm from partitions.forms import UploadFileForm, UploadMorceauForm
from partitions.models import Partition, PartitionSet from partitions.models import Partition, PartitionSet, PARTITION_TYPES
from partitions.decorators import chef_required from partitions.decorators import chef_required
def liste(request): def liste(request):
partitions = PartitionSet.objects.all().order_by("nom") partitions = PartitionSet.objects.order_by("nom")
return render(request, 'partitions/liste.html', locals()) context = {
"request": request,
"active_partitions": partitions.filter(category="active").all(),
"incoming_partitions": partitions.filter(category="incoming").all(),
"old_partitions": partitions.filter(category="old").all()
}
return render(request, 'partitions/liste.html', context)
@login_required @login_required
def upload(request, nom, auteur): def upload(request, nom, auteur):
@ -33,8 +41,6 @@ def upload(request, nom, auteur):
except Partition.DoesNotExist: except Partition.DoesNotExist:
partition.save() partition.save()
sauvegarde = True sauvegarde = True
else:
sauvegarde = True
else: else:
form = UploadFileForm() form = UploadFileForm()
return render(request, 'partitions/upload.html', locals()) return render(request, 'partitions/upload.html', locals())
@ -42,18 +48,18 @@ def upload(request, nom, auteur):
@login_required @login_required
def see(request, nom, auteur, file_name): def see(request, nom, auteur, file_name):
if ".pdf" in file_name: if ".pdf" in file_name:
abspath=open('/home/rikm/Projets/Ernesto/media/partitions/' + file_name, 'rb') abspath=open('/var/www_new/media/partitions/' + file_name, 'rb')
response=HttpResponse(content=abspath.read()) response=HttpResponse(content=abspath.read())
response["Content-Type"]="application/pdf" response["Content-Type"]="application/pdf"
response["Content-Disposition"]="inline; filename= %s" % (nom +'-'+ auteur +'-' + smart_str(file_name)) response["Content-Disposition"]="inline; filename= %s" % (nom +'-'+ auteur +'-' + smart_str(file_name))
abspath.close() abspath.close()
return response return response
elif ".mp3" in file_name: elif ".mp3" in file_name:
abspath=open('/home/rikm/Projets/Ernesto/media/partitions/' + file_name, 'rb') abspath=open('/var/www_new/media/partitions/' + file_name, 'rb')
response = HttpResponse() response = HttpResponse()
response.write(abspath.read()) response.write(abspath.read())
response["Content-Type"]="audio/mp3" response["Content-Type"]="audio/mp3"
response["Content-Length"]= os.path.getsize('/home/rikm/Projets/Ernesto/media/partitions/' + file_name) response["Content-Length"]= os.path.getsize('/var/www_new/media/partitions/' + file_name)
abspath.close() abspath.close()
return response return response
else: else:
@ -63,7 +69,7 @@ def see(request, nom, auteur, file_name):
@login_required @login_required
def download(request, nom, auteur, file_name): def download(request, nom, auteur, file_name):
abspath=open('/home/rikm/Projets/Ernesto/media/partitions/' + file_name, 'rb') abspath=open('/var/www_new/media/partitions/' + file_name, 'rb')
response = HttpResponse(content=abspath.read()) response = HttpResponse(content=abspath.read())
typ = file_name.split(".") typ = file_name.split(".")
n = len(typ) n = len(typ)
@ -94,7 +100,6 @@ def ajouter_morceau(request):
else: else:
form = UploadMorceauForm() form = UploadMorceauForm()
return render(request, 'partitions/new.html', locals()) return render(request, 'partitions/new.html', locals())
# Create your views here.
@chef_required @chef_required
def delete(request, nom, auteur, id): def delete(request, nom, auteur, id):
@ -127,7 +132,14 @@ def conf_delete_morc(request, nom, auteur):
@login_required @login_required
def listepart(request, nom, auteur): def listepart(request, nom, auteur):
p = PartitionSet.objects.get(nom=nom, auteur=auteur) p = PartitionSet.objects.get(nom=nom, auteur=auteur)
part = p.partition_set.all() part = p.partition_set.all()
return render(request, 'partitions/listepart.html', locals()) ChefEditForm = modelform_factory(PartitionSet, fields=("category", "infos"))
if request.method == "POST" and request.user.profile.is_chef:
form = ChefEditForm(request.POST, instance=p)
if form.is_valid():
form.save()
else:
form = ChefEditForm(instance=p)
return render(request, 'partitions/listepart.html', locals())

Binary file not shown.

View file

View file

@ -5,14 +5,9 @@ from django.views.generic import DeleteView
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
import string
import random
from propositions.forms import PropForm from propositions.forms import PropForm
from propositions.models import Prop from propositions.models import Prop
from propositions.models import Reponses from propositions.models import Reponses
from propositions.utils import generer
from gestion.models import ErnestoUser
@login_required @login_required
def create_prop(request): def create_prop(request):
@ -35,7 +30,6 @@ def liste(request):
n = len(props) n = len(props)
return render(request, 'propositions/liste.html', locals()) return render(request, 'propositions/liste.html', locals())
@login_required @login_required
def repoui(request, id): def repoui(request, id):
prop = Prop.objects.get(id=id) prop = Prop.objects.get(id=id)
@ -76,6 +70,13 @@ class PropDelete(DeleteView):
self.object.delete() self.object.delete()
return HttpResponseRedirect(success_url) return HttpResponseRedirect(success_url)
@login_required
def test(request, pk):
error = "Connard"
if True:
return redirect(PropDelete.as_view())
return render(request, "propositions/liste.html", locals())
@login_required @login_required
def repnon(request, id): def repnon(request, id):
prop = Prop.objects.get(id=id) prop = Prop.objects.get(id=id)
@ -97,5 +98,4 @@ def repnon(request, id):
prop.nbnon += 1 prop.nbnon += 1
prop.save() prop.save()
return redirect('propositions.views.liste') return redirect('propositions.views.liste')
# Create your views here. # Create your views here.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

847
static/admin/css/base.css Normal file
View file

@ -0,0 +1,847 @@
/*
DJANGO Admin styles
*/
body {
margin: 0;
padding: 0;
font-size: 12px;
font-family: "Lucida Grande","DejaVu Sans","Bitstream Vera Sans",Verdana,Arial,sans-serif;
color: #333;
background: #fff;
}
/* LINKS */
a:link, a:visited {
color: #5b80b2;
text-decoration: none;
}
a:hover {
color: #036;
}
a img {
border: none;
}
a.section:link, a.section:visited {
color: #fff;
text-decoration: none;
}
/* GLOBAL DEFAULTS */
p, ol, ul, dl {
margin: .2em 0 .8em 0;
}
p {
padding: 0;
line-height: 140%;
}
h1,h2,h3,h4,h5 {
font-weight: bold;
}
h1 {
font-size: 18px;
color: #666;
padding: 0 6px 0 0;
margin: 0 0 .2em 0;
}
h2 {
font-size: 16px;
margin: 1em 0 .5em 0;
}
h2.subhead {
font-weight: normal;
margin-top: 0;
}
h3 {
font-size: 14px;
margin: .8em 0 .3em 0;
color: #666;
font-weight: bold;
}
h4 {
font-size: 12px;
margin: 1em 0 .8em 0;
padding-bottom: 3px;
}
h5 {
font-size: 10px;
margin: 1.5em 0 .5em 0;
color: #666;
text-transform: uppercase;
letter-spacing: 1px;
}
ul li {
list-style-type: square;
padding: 1px 0;
}
ul.plainlist {
margin-left: 0 !important;
}
ul.plainlist li {
list-style-type: none;
}
li ul {
margin-bottom: 0;
}
li, dt, dd {
font-size: 11px;
line-height: 14px;
}
dt {
font-weight: bold;
margin-top: 4px;
}
dd {
margin-left: 0;
}
form {
margin: 0;
padding: 0;
}
fieldset {
margin: 0;
padding: 0;
}
blockquote {
font-size: 11px;
color: #777;
margin-left: 2px;
padding-left: 10px;
border-left: 5px solid #ddd;
}
code, pre {
font-family: "Bitstream Vera Sans Mono", Monaco, "Courier New", Courier, monospace;
background: inherit;
color: #666;
font-size: 11px;
}
pre.literal-block {
margin: 10px;
background: #eee;
padding: 6px 8px;
}
code strong {
color: #930;
}
hr {
clear: both;
color: #eee;
background-color: #eee;
height: 1px;
border: none;
margin: 0;
padding: 0;
font-size: 1px;
line-height: 1px;
}
/* TEXT STYLES & MODIFIERS */
.small {
font-size: 11px;
}
.tiny {
font-size: 10px;
}
p.tiny {
margin-top: -2px;
}
.mini {
font-size: 9px;
}
p.mini {
margin-top: -3px;
}
.help, p.help {
font-size: 10px !important;
color: #999;
}
img.help-tooltip {
cursor: help;
}
p img, h1 img, h2 img, h3 img, h4 img, td img {
vertical-align: middle;
}
.quiet, a.quiet:link, a.quiet:visited {
color: #999 !important;
font-weight: normal !important;
}
.quiet strong {
font-weight: bold !important;
}
.float-right {
float: right;
}
.float-left {
float: left;
}
.clear {
clear: both;
}
.align-left {
text-align: left;
}
.align-right {
text-align: right;
}
.example {
margin: 10px 0;
padding: 5px 10px;
background: #efefef;
}
.nowrap {
white-space: nowrap;
}
/* TABLES */
table {
border-collapse: collapse;
border-color: #ccc;
}
td, th {
font-size: 11px;
line-height: 13px;
border-bottom: 1px solid #eee;
vertical-align: top;
padding: 5px;
font-family: "Lucida Grande", Verdana, Arial, sans-serif;
}
th {
text-align: left;
font-size: 12px;
font-weight: bold;
}
thead th,
tfoot td {
color: #666;
padding: 2px 5px;
font-size: 11px;
background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
border-left: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
tfoot td {
border-bottom: none;
border-top: 1px solid #ddd;
}
thead th:first-child,
tfoot td:first-child {
border-left: none !important;
}
thead th.optional {
font-weight: normal !important;
}
fieldset table {
border-right: 1px solid #eee;
}
tr.row-label td {
font-size: 9px;
padding-top: 2px;
padding-bottom: 0;
border-bottom: none;
color: #666;
margin-top: -1px;
}
tr.alt {
background: #f6f6f6;
}
.row1 {
background: #EDF3FE;
}
.row2 {
background: #fff;
}
/* SORTABLE TABLES */
thead th {
padding: 2px 5px;
line-height: normal;
}
thead th a:link, thead th a:visited {
color: #666;
}
thead th.sorted {
background: #c5c5c5 url(../img/nav-bg-selected.gif) top left repeat-x;
}
thead th.sorted .text {
padding-right: 42px;
}
table thead th .text span {
padding: 2px 5px;
display:block;
}
table thead th .text a {
display: block;
cursor: pointer;
padding: 2px 5px;
}
table thead th.sortable:hover {
background: #fff url(../img/nav-bg-reverse.gif) 0 -5px repeat-x;
}
thead th.sorted a.sortremove {
visibility: hidden;
}
table thead th.sorted:hover a.sortremove {
visibility: visible;
}
table thead th.sorted .sortoptions {
display: block;
padding: 4px 5px 0 5px;
float: right;
text-align: right;
}
table thead th.sorted .sortpriority {
font-size: .8em;
min-width: 12px;
text-align: center;
vertical-align: top;
}
table thead th.sorted .sortoptions a {
width: 14px;
height: 12px;
display: inline-block;
}
table thead th.sorted .sortoptions a.sortremove {
background: url(../img/sorting-icons.gif) -4px -5px no-repeat;
}
table thead th.sorted .sortoptions a.sortremove:hover {
background: url(../img/sorting-icons.gif) -4px -27px no-repeat;
}
table thead th.sorted .sortoptions a.ascending {
background: url(../img/sorting-icons.gif) -5px -50px no-repeat;
}
table thead th.sorted .sortoptions a.ascending:hover {
background: url(../img/sorting-icons.gif) -5px -72px no-repeat;
}
table thead th.sorted .sortoptions a.descending {
background: url(../img/sorting-icons.gif) -5px -94px no-repeat;
}
table thead th.sorted .sortoptions a.descending:hover {
background: url(../img/sorting-icons.gif) -5px -115px no-repeat;
}
/* ORDERABLE TABLES */
table.orderable tbody tr td:hover {
cursor: move;
}
table.orderable tbody tr td:first-child {
padding-left: 14px;
background-image: url(../img/nav-bg-grabber.gif);
background-repeat: repeat-y;
}
table.orderable-initalized .order-cell, body>tr>td.order-cell {
display: none;
}
/* FORM DEFAULTS */
input, textarea, select, .form-row p {
margin: 2px 0;
padding: 2px 3px;
vertical-align: middle;
font-family: "Lucida Grande", Verdana, Arial, sans-serif;
font-weight: normal;
font-size: 11px;
}
textarea {
vertical-align: top !important;
}
input[type=text], input[type=password], input[type=email], input[type=url], input[type=number],
textarea, select, .vTextField {
border: 1px solid #ccc;
}
/* FORM BUTTONS */
.button, input[type=submit], input[type=button], .submit-row input {
background: #fff url(../img/nav-bg.gif) bottom repeat-x;
padding: 3px 5px;
color: black;
border: 1px solid #bbb;
border-color: #ddd #aaa #aaa #ddd;
}
.button:active, input[type=submit]:active, input[type=button]:active {
background-image: url(../img/nav-bg-reverse.gif);
background-position: top;
}
.button[disabled], input[type=submit][disabled], input[type=button][disabled] {
background-image: url(../img/nav-bg.gif);
background-position: bottom;
opacity: 0.4;
}
.button.default, input[type=submit].default, .submit-row input.default {
border: 2px solid #5b80b2;
background: #7CA0C7 url(../img/default-bg.gif) bottom repeat-x;
font-weight: bold;
color: #fff;
float: right;
}
.button.default:active, input[type=submit].default:active {
background-image: url(../img/default-bg-reverse.gif);
background-position: top;
}
.button[disabled].default, input[type=submit][disabled].default, input[type=button][disabled].default {
background-image: url(../img/default-bg.gif);
background-position: bottom;
opacity: 0.4;
}
/* MODULES */
.module {
border: 1px solid #ccc;
margin-bottom: 5px;
background: #fff;
}
.module p, .module ul, .module h3, .module h4, .module dl, .module pre {
padding-left: 10px;
padding-right: 10px;
}
.module blockquote {
margin-left: 12px;
}
.module ul, .module ol {
margin-left: 1.5em;
}
.module h3 {
margin-top: .6em;
}
.module h2, .module caption, .inline-group h2 {
margin: 0;
padding: 2px 5px 3px 5px;
font-size: 11px;
text-align: left;
font-weight: bold;
background: #7CA0C7 url(../img/default-bg.gif) top left repeat-x;
color: #fff;
}
.module table {
border-collapse: collapse;
}
/* MESSAGES & ERRORS */
ul.messagelist {
padding: 0;
margin: 0;
}
ul.messagelist li {
font-size: 12px;
font-weight: bold;
display: block;
padding: 5px 5px 4px 25px;
margin: 0 0 3px 0;
border-bottom: 1px solid #ddd;
color: #666;
background: #dfd url(../img/icon_success.gif) 5px .3em no-repeat;
}
ul.messagelist li.warning {
background: #ffc url(../img/icon_alert.gif) 5px .3em no-repeat;
}
ul.messagelist li.error {
background: #ffefef url(../img/icon_error.gif) 5px .3em no-repeat;
}
.errornote {
font-size: 12px !important;
font-weight: bold;
display: block;
padding: 5px 5px 4px 25px;
margin: 0 0 3px 0;
border: 1px solid #c22;
color: #c11;
background: #ffefef url(../img/icon_error.gif) 5px .38em no-repeat;
}
.errornote, ul.errorlist {
border-radius: 1px;
}
ul.errorlist {
margin: 0 0 4px !important;
padding: 0 !important;
color: #fff;
background: #c11;
}
ul.errorlist li {
font-size: 12px !important;
display: block;
padding: 5px 5px 4px 7px;
margin: 3px 0 0 0;
}
ul.errorlist li:first-child {
margin-top: 0;
}
ul.errorlist li a {
color: #fff;
text-decoration: underline;
}
td ul.errorlist {
margin: 0 !important;
padding: 0 !important;
}
td ul.errorlist li {
margin: 0 !important;
}
.errors, .form-row.errors {
background: #ffefef;
}
.form-row.errors {
border: 1px solid #c22;
margin: -1px;
}
.errors input, .errors select, .errors textarea {
border: 1px solid #c11;
}
div.system-message {
background: #ffc;
margin: 10px;
padding: 6px 8px;
font-size: .8em;
}
div.system-message p.system-message-title {
padding: 4px 5px 4px 25px;
margin: 0;
color: #c11;
background: #ffefef url(../img/icon_error.gif) 5px .3em no-repeat;
}
.description {
font-size: 12px;
padding: 5px 0 0 12px;
}
/* BREADCRUMBS */
div.breadcrumbs {
background: #fff url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
padding: 2px 8px 3px 8px;
font-size: 11px;
color: #999;
border-top: 1px solid #fff;
border-bottom: 1px solid #ddd;
text-align: left;
}
/* ACTION ICONS */
.addlink {
padding-left: 12px;
background: url(../img/icon_addlink.gif) 0 .2em no-repeat;
}
.changelink {
padding-left: 12px;
background: url(../img/icon_changelink.gif) 0 .2em no-repeat;
}
.deletelink {
padding-left: 12px;
background: url(../img/icon_deletelink.gif) 0 .25em no-repeat;
}
a.deletelink:link, a.deletelink:visited {
color: #CC3434;
}
a.deletelink:hover {
color: #993333;
}
/* OBJECT TOOLS */
.object-tools {
font-size: 10px;
font-weight: bold;
font-family: Arial,Helvetica,sans-serif;
padding-left: 0;
float: right;
position: relative;
margin-top: -2.4em;
margin-bottom: -2em;
}
.form-row .object-tools {
margin-top: 5px;
margin-bottom: 5px;
float: none;
height: 2em;
padding-left: 3.5em;
}
.object-tools li {
display: block;
float: left;
margin-left: 5px;
height: 16px;
}
.object-tools a {
border-radius: 15px;
}
.object-tools a:link, .object-tools a:visited {
display: block;
float: left;
color: #fff;
padding: .2em 10px;
background: #999;
}
.object-tools a:hover, .object-tools li:hover a {
background-color: #5b80b2;
}
.object-tools a.viewsitelink, .object-tools a.golink {
background: #999 url(../img/tooltag-arrowright.png) 95% center no-repeat;
padding-right: 26px;
}
.object-tools a.addlink {
background: #999 url(../img/tooltag-add.png) 95% center no-repeat;
padding-right: 26px;
}
/* OBJECT HISTORY */
table#change-history {
width: 100%;
}
table#change-history tbody th {
width: 16em;
}
/* PAGE STRUCTURE */
#container {
position: relative;
width: 100%;
min-width: 760px;
padding: 0;
}
#content {
margin: 10px 15px;
}
#content-main {
float: left;
width: 100%;
}
#content-related {
float: right;
width: 18em;
position: relative;
margin-right: -19em;
}
#footer {
clear: both;
padding: 10px;
}
/* COLUMN TYPES */
.colMS {
margin-right: 20em !important;
}
.colSM {
margin-left: 20em !important;
}
.colSM #content-related {
float: left;
margin-right: 0;
margin-left: -19em;
}
.colSM #content-main {
float: right;
}
.popup .colM {
width: 95%;
}
.subcol {
float: left;
width: 46%;
margin-right: 15px;
}
.dashboard #content {
width: 500px;
}
/* HEADER */
#header {
width: 100%;
background: #417690;
color: #ffc;
overflow: hidden;
}
#header a:link, #header a:visited {
color: #fff;
}
#header a:hover {
text-decoration: underline;
}
#branding {
float: left;
}
#branding h1 {
padding: 0 10px;
font-size: 18px;
margin: 8px 0;
font-weight: normal;
}
#branding h1, #branding h1 a:link, #branding h1 a:visited {
color: #f4f379;
}
#branding h2 {
padding: 0 10px;
font-size: 14px;
margin: -8px 0 8px 0;
font-weight: normal;
color: #ffc;
}
#branding a:hover {
text-decoration: none;
}
#user-tools {
float: right;
padding: 1.2em 10px;
font-size: 11px;
text-align: right;
}
/* SIDEBAR */
#content-related h3 {
font-size: 12px;
color: #666;
margin-bottom: 3px;
}
#content-related h4 {
font-size: 11px;
}
#content-related .module h2 {
background: #eee url(../img/nav-bg.gif) bottom left repeat-x;
color: #666;
}

View file

@ -0,0 +1,293 @@
/* CHANGELISTS */
#changelist {
position: relative;
width: 100%;
}
#changelist table {
width: 100%;
}
.change-list .hiddenfields { display:none; }
.change-list .filtered table {
border-right: 1px solid #ddd;
}
.change-list .filtered {
min-height: 400px;
}
.change-list .filtered {
background: white url(../img/changelist-bg.gif) top right repeat-y !important;
}
.change-list .filtered .results, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull {
margin-right: 160px !important;
width: auto !important;
}
.change-list .filtered table tbody th {
padding-right: 1em;
}
#changelist-form .results {
overflow-x: auto;
}
#changelist .toplinks {
border-bottom: 1px solid #ccc !important;
}
#changelist .paginator {
color: #666;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
background: white url(../img/nav-bg.gif) 0 180% repeat-x;
overflow: hidden;
}
.change-list .filtered .paginator {
border-right: 1px solid #ddd;
}
/* CHANGELIST TABLES */
#changelist table thead th {
padding: 0;
white-space: nowrap;
vertical-align: middle;
}
#changelist table thead th.action-checkbox-column {
width: 1.5em;
text-align: center;
}
#changelist table tbody td, #changelist table tbody th {
border-left: 1px solid #ddd;
}
#changelist table tbody td:first-child, #changelist table tbody th:first-child {
border-left: 0;
border-right: 1px solid #ddd;
}
#changelist table tbody td.action-checkbox {
text-align:center;
}
#changelist table tfoot {
color: #666;
}
/* TOOLBAR */
#changelist #toolbar {
padding: 3px;
border-bottom: 1px solid #ddd;
background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
color: #666;
}
#changelist #toolbar form input {
font-size: 11px;
padding: 1px 2px;
}
#changelist #toolbar form #searchbar {
padding: 2px;
}
#changelist #changelist-search img {
vertical-align: middle;
}
/* FILTER COLUMN */
#changelist-filter {
position: absolute;
top: 0;
right: 0;
z-index: 1000;
width: 160px;
border-left: 1px solid #ddd;
background: #efefef;
margin: 0;
}
#changelist-filter h2 {
font-size: 11px;
padding: 2px 5px;
border-bottom: 1px solid #ddd;
}
#changelist-filter h3 {
font-size: 12px;
margin-bottom: 0;
}
#changelist-filter ul {
padding-left: 0;
margin-left: 10px;
}
#changelist-filter li {
list-style-type: none;
margin-left: 0;
padding-left: 0;
}
#changelist-filter a {
color: #999;
}
#changelist-filter a:hover {
color: #036;
}
#changelist-filter li.selected {
border-left: 5px solid #ccc;
padding-left: 5px;
margin-left: -10px;
}
#changelist-filter li.selected a {
color: #5b80b2 !important;
}
/* DATE DRILLDOWN */
.change-list ul.toplinks {
display: block;
background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
border-top: 1px solid white;
float: left;
padding: 0 !important;
margin: 0 !important;
width: 100%;
}
.change-list ul.toplinks li {
padding: 3px 6px;
font-weight: bold;
list-style-type: none;
display: inline-block;
}
.change-list ul.toplinks .date-back a {
color: #999;
}
.change-list ul.toplinks .date-back a:hover {
color: #036;
}
/* PAGINATOR */
.paginator {
font-size: 11px;
padding-top: 10px;
padding-bottom: 10px;
line-height: 22px;
margin: 0;
border-top: 1px solid #ddd;
}
.paginator a:link, .paginator a:visited {
padding: 2px 6px;
border: solid 1px #ccc;
background: white;
text-decoration: none;
}
.paginator a.showall {
padding: 0 !important;
border: none !important;
}
.paginator a.showall:hover {
color: #036 !important;
background: transparent !important;
}
.paginator .end {
border-width: 2px !important;
margin-right: 6px;
}
.paginator .this-page {
padding: 2px 6px;
font-weight: bold;
font-size: 13px;
vertical-align: top;
}
.paginator a:hover {
color: white;
background: #5b80b2;
border-color: #036;
}
/* ACTIONS */
.filtered .actions {
margin-right: 160px !important;
border-right: 1px solid #ddd;
}
#changelist table input {
margin: 0;
}
#changelist table tbody tr.selected {
background-color: #FFFFCC;
}
#changelist .actions {
color: #999;
padding: 3px;
border-top: 1px solid #fff;
border-bottom: 1px solid #ddd;
background: white url(../img/nav-bg-reverse.gif) 0 -10px repeat-x;
}
#changelist .actions.selected {
background: #fffccf;
border-top: 1px solid #fffee8;
border-bottom: 1px solid #edecd6;
}
#changelist .actions span.all,
#changelist .actions span.action-counter,
#changelist .actions span.clear,
#changelist .actions span.question {
font-size: 11px;
margin: 0 0.5em;
display: none;
}
#changelist .actions:last-child {
border-bottom: none;
}
#changelist .actions select {
border: 1px solid #aaa;
margin-left: 0.5em;
padding: 1px 2px;
}
#changelist .actions label {
font-size: 11px;
margin-left: 0.5em;
}
#changelist #action-toggle {
display: none;
}
#changelist .actions .button {
font-size: 11px;
padding: 1px 2px;
}

View file

@ -0,0 +1,30 @@
/* DASHBOARD */
.dashboard .module table th {
width: 100%;
}
.dashboard .module table td {
white-space: nowrap;
}
.dashboard .module table td a {
display: block;
padding-right: .6em;
}
/* RECENT ACTIONS MODULE */
.module ul.actionlist {
margin-left: 0;
}
ul.actionlist li {
list-style-type: none;
}
ul.actionlist li {
overflow: hidden;
text-overflow: ellipsis;
-o-text-overflow: ellipsis;
}

376
static/admin/css/forms.css Normal file
View file

@ -0,0 +1,376 @@
@import url('widgets.css');
/* FORM ROWS */
.form-row {
overflow: hidden;
padding: 8px 12px;
font-size: 11px;
border-bottom: 1px solid #eee;
}
.form-row img, .form-row input {
vertical-align: middle;
}
form .form-row p {
padding-left: 0;
font-size: 11px;
}
.hidden {
display: none;
}
/* FORM LABELS */
form h4 {
margin: 0 !important;
padding: 0 !important;
border: none !important;
}
label {
font-weight: normal !important;
color: #666;
font-size: 12px;
}
.required label, label.required {
font-weight: bold !important;
color: #333 !important;
}
/* RADIO BUTTONS */
form ul.radiolist li {
list-style-type: none;
}
form ul.radiolist label {
float: none;
display: inline;
}
form ul.inline {
margin-left: 0;
padding: 0;
}
form ul.inline li {
float: left;
padding-right: 7px;
}
/* ALIGNED FIELDSETS */
.aligned label {
display: block;
padding: 3px 10px 0 0;
float: left;
width: 8em;
word-wrap: break-word;
}
.aligned ul label {
display: inline;
float: none;
width: auto;
}
.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField {
width: 350px;
}
form .aligned p, form .aligned ul {
margin-left: 7em;
padding-left: 30px;
}
form .aligned table p {
margin-left: 0;
padding-left: 0;
}
form .aligned p.help {
padding-left: 38px;
}
.aligned .vCheckboxLabel {
float: none !important;
display: inline;
padding-left: 4px;
}
.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField {
width: 610px;
}
.checkbox-row p.help {
margin-left: 0;
padding-left: 0 !important;
}
fieldset .field-box {
float: left;
margin-right: 20px;
}
/* WIDE FIELDSETS */
.wide label {
width: 15em !important;
}
form .wide p {
margin-left: 15em;
}
form .wide p.help {
padding-left: 38px;
}
.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField {
width: 450px;
}
/* COLLAPSED FIELDSETS */
fieldset.collapsed * {
display: none;
}
fieldset.collapsed h2, fieldset.collapsed {
display: block !important;
}
fieldset.collapsed h2 {
background-image: url(../img/nav-bg.gif);
background-position: bottom left;
color: #999;
}
fieldset.collapsed .collapse-toggle {
background: transparent;
display: inline !important;
}
/* MONOSPACE TEXTAREAS */
fieldset.monospace textarea {
font-family: "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace;
}
/* SUBMIT ROW */
.submit-row {
padding: 5px 7px;
text-align: right;
background: white url(../img/nav-bg.gif) 0 100% repeat-x;
border: 1px solid #ccc;
margin: 5px 0;
overflow: hidden;
}
body.popup .submit-row {
overflow: auto;
}
.submit-row input {
margin: 0 0 0 5px;
}
.submit-row p {
margin: 0.3em;
}
.submit-row p.deletelink-box {
float: left;
}
.submit-row .deletelink {
background: url(../img/icon_deletelink.gif) 0 50% no-repeat;
padding-left: 14px;
}
/* CUSTOM FORM FIELDS */
.vSelectMultipleField {
vertical-align: top !important;
}
.vCheckboxField {
border: none;
}
.vDateField, .vTimeField {
margin-right: 2px;
}
.vDateField {
min-width: 6.85em;
}
.vTimeField {
min-width: 4.7em;
}
.vURLField {
width: 30em;
}
.vLargeTextField, .vXMLLargeTextField {
width: 48em;
}
.flatpages-flatpage #id_content {
height: 40.2em;
}
.module table .vPositiveSmallIntegerField {
width: 2.2em;
}
.vTextField {
width: 20em;
}
.vIntegerField {
width: 5em;
}
.vBigIntegerField {
width: 10em;
}
.vForeignKeyRawIdAdminField {
width: 5em;
}
/* INLINES */
.inline-group {
padding: 0;
border: 1px solid #ccc;
margin: 10px 0;
}
.inline-group .aligned label {
width: 8em;
}
.inline-related {
position: relative;
}
.inline-related h3 {
margin: 0;
color: #666;
padding: 3px 5px;
font-size: 11px;
background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
border-bottom: 1px solid #ddd;
}
.inline-related h3 span.delete {
float: right;
}
.inline-related h3 span.delete label {
margin-left: 2px;
font-size: 11px;
}
.inline-related fieldset {
margin: 0;
background: #fff;
border: none;
width: 100%;
}
.inline-related fieldset.module h3 {
margin: 0;
padding: 2px 5px 3px 5px;
font-size: 11px;
text-align: left;
font-weight: bold;
background: #bcd;
color: #fff;
}
.inline-group .tabular fieldset.module {
border: none;
border-bottom: 1px solid #ddd;
}
.inline-related.tabular fieldset.module table {
width: 100%;
}
.last-related fieldset {
border: none;
}
.inline-group .tabular tr.has_original td {
padding-top: 2em;
}
.inline-group .tabular tr td.original {
padding: 2px 0 0 0;
width: 0;
_position: relative;
}
.inline-group .tabular th.original {
width: 0px;
padding: 0;
}
.inline-group .tabular td.original p {
position: absolute;
left: 0;
height: 1.1em;
padding: 2px 7px;
overflow: hidden;
font-size: 9px;
font-weight: bold;
color: #666;
_width: 700px;
}
.inline-group ul.tools {
padding: 0;
margin: 0;
list-style: none;
}
.inline-group ul.tools li {
display: inline;
padding: 0 5px;
}
.inline-group div.add-row,
.inline-group .tabular tr.add-row td {
color: #666;
padding: 3px 5px;
border-bottom: 1px solid #ddd;
background: #e1e1e1 url(../img/nav-bg.gif) top left repeat-x;
}
.inline-group .tabular tr.add-row td {
padding: 4px 5px 3px;
border-bottom: none;
}
.inline-group ul.tools a.add,
.inline-group div.add-row a,
.inline-group .tabular tr.add-row td a {
background: url(../img/icon_addlink.gif) 0 50% no-repeat;
padding-left: 14px;
font-size: 11px;
outline: 0; /* Remove dotted border around link */
}
.empty-form {
display: none;
}

Some files were not shown because too many files have changed in this diff Show more