Merge branch 'v1.1' into 'master'
v1.1 See merge request klub-dev-ens/Ernesto!12
This commit is contained in:
commit
9bd21283c0
112 changed files with 4116 additions and 2910 deletions
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
try:
|
||||
|
@ -31,63 +32,60 @@ DBPASSWD = import_secret("DBPASSWD")
|
|||
|
||||
ACCOUNT_CREATION_PASS = import_secret("ACCOUNT_CREATION_PASS")
|
||||
|
||||
|
||||
|
||||
BASE_DIR = os.path.join(
|
||||
os.path.dirname(__file__), "..", ".."
|
||||
)
|
||||
BASE_DIR = os.path.join(os.path.dirname(__file__), "..", "..")
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'trombonoscope',
|
||||
'actu',
|
||||
'colorful',
|
||||
'pads',
|
||||
'calendrier',
|
||||
'gestion.apps.GestionConfig',
|
||||
'partitions.apps.PartitionsConfig',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'avatar',
|
||||
"trombonoscope",
|
||||
"actu",
|
||||
"colorful",
|
||||
"pads",
|
||||
"calendrier",
|
||||
"gestion.apps.GestionConfig",
|
||||
"partitions.apps.PartitionsConfig",
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"avatar",
|
||||
"instruments",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"django.middleware.locale.LocaleMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "Ernestophone.urls"
|
||||
|
||||
TEMPLATES = [{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
|
||||
],
|
||||
'libraries':{
|
||||
'changelang': 'gestion.templatetags.changelang',
|
||||
'modulo': 'gestion.templatetags.modulo',
|
||||
'autotranslate': 'gestion.templatetags.autotranslate',
|
||||
'halflength': 'gestion.templatetags.halflength',
|
||||
|
||||
}
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
],
|
||||
"libraries": {
|
||||
"changelang": "gestion.templatetags.changelang",
|
||||
"modulo": "gestion.templatetags.modulo",
|
||||
"autotranslate": "gestion.templatetags.autotranslate",
|
||||
"halflength": "gestion.templatetags.halflength",
|
||||
},
|
||||
},
|
||||
}
|
||||
}]
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = "Ernestophone.wsgi.application"
|
||||
|
||||
|
@ -103,51 +101,51 @@ DATABASES = {
|
|||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# I18n
|
||||
# I18n
|
||||
LANGUAGE_CODE = 'fr'
|
||||
LANGUAGE_CODE = "fr"
|
||||
LANGUAGES = (
|
||||
('fr', _('Français')),
|
||||
('en', _('English')),
|
||||
("fr", _("Français")),
|
||||
("en", _("English")),
|
||||
)
|
||||
TIME_ZONE = 'UTC'
|
||||
TIME_ZONE = "UTC"
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), )
|
||||
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
|
||||
|
||||
|
||||
AUTH_PROFILE_MODEL = 'gestion.ErnestoUser'
|
||||
AUTH_PROFILE_MODEL = "gestion.ErnestoUser"
|
||||
|
||||
LOGIN_URL = "/login"
|
||||
|
||||
AVATAR_CLEANUP_DELETED = True
|
||||
AVATAR_AUTO_GENERATE_SIZES = (250,)
|
||||
AVATAR_CHANGE_TEMPLATE = "trombonoscope/change_avatar.html"
|
||||
AVATAR_MAX_AVATARS_PER_USER=1
|
||||
AVATAR_EXPOSE_USERNAMES=False
|
||||
AVATAR_STORAGE_DIR="trombonoscope"
|
||||
AVATAR_ADD_TEMPLATE="trombonoscope/add_avatar.html"
|
||||
AVATAR_DELETE_TEMPLATE="trombonoscope/delete_avatar.html"
|
||||
AVATAR_DEFAULT_URL="Ernesto"
|
||||
AVATAR_PROVIDERS=(
|
||||
'avatar.providers.PrimaryAvatarProvider',
|
||||
'avatar.providers.DefaultAvatarProvider',
|
||||
)
|
||||
AVATAR_THUMB_FORMAT = 'JPEG'
|
||||
AVATAR_MAX_AVATARS_PER_USER = 1
|
||||
AVATAR_EXPOSE_USERNAMES = False
|
||||
AVATAR_STORAGE_DIR = "trombonoscope"
|
||||
AVATAR_ADD_TEMPLATE = "trombonoscope/add_avatar.html"
|
||||
AVATAR_DELETE_TEMPLATE = "trombonoscope/delete_avatar.html"
|
||||
AVATAR_DEFAULT_URL = "Ernesto"
|
||||
AVATAR_PROVIDERS = (
|
||||
"avatar.providers.PrimaryAvatarProvider",
|
||||
"avatar.providers.DefaultAvatarProvider",
|
||||
)
|
||||
AVATAR_THUMB_FORMAT = "JPEG"
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
import os
|
||||
|
||||
|
||||
from .common import * # noqa
|
||||
from .common import BASE_DIR, INSTALLED_APPS, MIDDLEWARE
|
||||
|
||||
|
||||
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||
|
||||
DEBUG = True
|
||||
|
||||
INSTALLED_APPS += ["debug_toolbar"]
|
||||
MIDDLEWARE = (
|
||||
["debug_toolbar.middleware.DebugToolbarMiddleware"]
|
||||
+ MIDDLEWARE
|
||||
)
|
||||
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_ROOT = "static"
|
||||
|
|
|
@ -3,7 +3,6 @@ import os
|
|||
from .common import * # noqa
|
||||
from .common import BASE_DIR
|
||||
|
||||
|
||||
DEBUG = False
|
||||
|
||||
ALLOWED_HOSTS = [
|
||||
|
@ -12,11 +11,7 @@ ALLOWED_HOSTS = [
|
|||
]
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
STATIC_ROOT = os.path.join(
|
||||
BASE_DIR, "..", "..", "public", "ernesto", "static"
|
||||
)
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "..", "..", "public", "ernesto", "static")
|
||||
|
||||
MEDIA_URL = "/media/"
|
||||
MEDIA_ROOT = os.path.join(
|
||||
BASE_DIR, "..", "media"
|
||||
)
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, "..", "media")
|
||||
|
|
|
@ -13,36 +13,39 @@ Including another URLconf
|
|||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from gestion import views as gestion_views
|
||||
from django.contrib.auth import views as auth_views
|
||||
import django.contrib.auth.urls as urls
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.conf.urls.static import static
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import include, path
|
||||
|
||||
from gestion import views as gestion_views
|
||||
|
||||
urlpatterns = []
|
||||
urlpatterns += i18n_patterns(
|
||||
path('', gestion_views.home, name="home"),
|
||||
path("registration", gestion_views.inscription_membre, name="registration"),
|
||||
path("change", gestion_views.change_membre, name="change_membre"),
|
||||
path("password", gestion_views.change_password, name="change_password"),
|
||||
path("thanks", gestion_views.thanks, name="thanks"),
|
||||
path("changename", gestion_views.changename, name="change-doodle-name"),
|
||||
path("", gestion_views.Home.as_view(), name="home"),
|
||||
path("registration", gestion_views.Inscription.as_view(), name="registration"),
|
||||
path("change", gestion_views.ChangeMembre.as_view(), name="change_membre"),
|
||||
path("password", gestion_views.ChangePassword.as_view(), name="change_password"),
|
||||
path("thanks", gestion_views.Thanks.as_view(), name="thanks"),
|
||||
path("social", gestion_views.Social.as_view(), name="social"),
|
||||
path("chef", gestion_views.Chef.as_view(), name="chef"),
|
||||
path("profil", gestion_views.Profil.as_view(), name="profile"),
|
||||
path("changename", gestion_views.ChangeName.as_view(), name="change-doodle-name"),
|
||||
path("logout", auth_views.LogoutView.as_view(next_page="home"), name="logout"),
|
||||
path("login", gestion_views.MyLoginView.as_view(), name="login"),
|
||||
path("agenda/", include("calendrier.urls", namespace="calendrier")),
|
||||
path("partitions/", include("partitions.urls")),
|
||||
path("instruments/", include("instruments.urls")),
|
||||
path("pads/", include("pads.urls")),
|
||||
path(
|
||||
"login",
|
||||
auth_views.LoginView.as_view(template_name="gestion/login.html"),
|
||||
name="login"
|
||||
"admin/",
|
||||
admin.site.urls,
|
||||
),
|
||||
path('agenda/', include('calendrier.urls',namespace='calendrier')),
|
||||
path('partitions/', include('partitions.urls')),
|
||||
path('pads/', include('pads.urls')),
|
||||
path('admin/', admin.site.urls,),
|
||||
path('trombonoscope/',include('trombonoscope.urls')),
|
||||
path("actu/",include('actu.urls')),
|
||||
path('avatar/', include('avatar.urls')),
|
||||
prefix_default_language=False )
|
||||
path("trombonoscope/", include("trombonoscope.urls")),
|
||||
path("actu/", include("actu.urls")),
|
||||
path("avatar/", include("avatar.urls")),
|
||||
prefix_default_language=False,
|
||||
)
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
"""
|
||||
WSGI config for Ernestophone project.
|
||||
|
||||
|
@ -10,10 +9,8 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
|
|||
|
||||
import os
|
||||
|
||||
os.environ.setdefault(
|
||||
"DJANGO_SETTINGS_MODULE",
|
||||
"Ernestophone.settings.prod"
|
||||
)
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ernestophone.settings.prod")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
application = get_wsgi_application()
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class ActuConfig(AppConfig):
|
||||
name = 'actu'
|
||||
name = "actu"
|
||||
|
|
|
@ -7,22 +7,34 @@ class Migration(migrations.Migration):
|
|||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Actu',
|
||||
name="Actu",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField(null=True, verbose_name='Info')),
|
||||
('text_en', models.TextField(blank=True, null=True, verbose_name='Info en anglais')),
|
||||
('order', models.IntegerField(verbose_name='ordre')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("text", models.TextField(null=True, verbose_name="Info")),
|
||||
(
|
||||
"text_en",
|
||||
models.TextField(
|
||||
blank=True, null=True, verbose_name="Info en anglais"
|
||||
),
|
||||
),
|
||||
("order", models.IntegerField(verbose_name="ordre")),
|
||||
],
|
||||
options={
|
||||
'ordering': ('order',),
|
||||
'verbose_name_plural': 'Actualités',
|
||||
'verbose_name': 'Actualité',
|
||||
"ordering": ("order",),
|
||||
"verbose_name_plural": "Actualités",
|
||||
"verbose_name": "Actualité",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Actu(models.Model):
|
||||
|
||||
text = models.TextField(_("Info"), null=True, blank=False)
|
||||
text_en = models.TextField(("Info en anglais"), null=True, blank=True)
|
||||
order = models.IntegerField(verbose_name=_("ordre"))
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Actualité")
|
||||
verbose_name_plural = _("Actualités")
|
||||
ordering = ('order',)
|
||||
ordering = ("order",)
|
||||
|
|
|
@ -2,11 +2,10 @@ from django.urls import path
|
|||
|
||||
from actu import views
|
||||
|
||||
|
||||
app_name = "actu"
|
||||
urlpatterns = [
|
||||
path("", views.ActuList.as_view(), name="liste"),
|
||||
path("ajouter", views.ActuCreate.as_view(), name="add_actu"),
|
||||
path("edition/<int:pk>", views.ActuUpdate.as_view(), name="edit_actu"),
|
||||
path("supprimer/<int:pk>", views.ActuDelete.as_view(), name="delete_actu")
|
||||
path("supprimer/<int:pk>", views.ActuDelete.as_view(), name="delete_actu"),
|
||||
]
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
from django.shortcuts import render
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
from django.urls import reverse_lazy
|
||||
from actu.models import Actu
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
|
||||
from actu.models import Actu
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
|
||||
|
||||
class ActuList(ChefRequiredMixin, ListView):
|
||||
|
@ -14,7 +14,7 @@ class ActuList(ChefRequiredMixin, ListView):
|
|||
|
||||
class ActuCreate(ChefRequiredMixin, CreateView):
|
||||
model = Actu
|
||||
fields = ["text","order","text_en"]
|
||||
fields = ["text", "order", "text_en"]
|
||||
template_name = "actu/create_actu.html"
|
||||
success_url = reverse_lazy("actu:liste")
|
||||
|
||||
|
@ -26,7 +26,7 @@ class ActuCreate(ChefRequiredMixin, CreateView):
|
|||
|
||||
class ActuUpdate(ChefRequiredMixin, UpdateView):
|
||||
model = Actu
|
||||
fields = ["text","order","text_en"]
|
||||
fields = ["text", "order", "text_en"]
|
||||
template_name = "actu/update_actu.html"
|
||||
success_url = reverse_lazy("actu:liste")
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from django.contrib import admin
|
||||
|
||||
|
||||
from .models import Event
|
||||
|
||||
admin.site.register(Event)
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class CalendrierConfig(AppConfig):
|
||||
name = 'calendrier'
|
||||
name = "calendrier"
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
from django.utils.html import conditional_escape as esc
|
||||
from itertools import groupby
|
||||
from calendar import HTMLCalendar
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from datetime import date
|
||||
from itertools import groupby
|
||||
|
||||
from django.utils.html import conditional_escape as esc
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class EventCalendar(HTMLCalendar):
|
||||
|
||||
def __init__(self, pEvents):
|
||||
super(EventCalendar, self).__init__()
|
||||
self.events = self.group_by_day(pEvents.order_by('date'))
|
||||
self.events = self.group_by_day(pEvents.order_by("date"))
|
||||
|
||||
def formatday(self, day, weekday):
|
||||
if day != 0:
|
||||
cssclass = self.cssclasses[weekday]
|
||||
if date.today() == date(self.year, self.month, day):
|
||||
cssclass += ' today'
|
||||
cssclass += " today"
|
||||
if day in self.events:
|
||||
cssclass += ' filled'
|
||||
cssclass += " filled"
|
||||
body = []
|
||||
for ev in self.events[day]:
|
||||
body.append(_('<a href="/agenda/') + '%s">' % ev.id)
|
||||
body.append(esc(ev.nom))
|
||||
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>' % day)
|
||||
return self.day_cell('noday', ' ')
|
||||
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>' % day)
|
||||
return self.day_cell("noday", " ")
|
||||
|
||||
def formatmonth(self, year, month):
|
||||
self.year, self.month = year, month
|
||||
return super(EventCalendar, self).formatmonth(year, month)
|
||||
|
||||
def group_by_day(self, pEvents):
|
||||
def field(ev): return(ev.date.day)
|
||||
return dict(
|
||||
[(dat, list(items)) for dat, items in groupby(pEvents, field)]
|
||||
)
|
||||
def field(ev):
|
||||
return ev.date.day
|
||||
|
||||
return dict([(dat, list(items)) for dat, items in groupby(pEvents, field)])
|
||||
|
||||
def day_cell(self, cssclass, body):
|
||||
return '<td class="%s">%s</td>' % (cssclass, body)
|
||||
|
|
|
@ -1,61 +1,59 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from calendrier.models import Event, Participants
|
||||
from gestion.models import ErnestoUser
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class ModifEventForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Event
|
||||
exclude = ['slug']
|
||||
exclude = ["slug"]
|
||||
widgets = {
|
||||
'description': forms.Textarea(attrs={
|
||||
"placeholder": _("facultatif, balises html supportées")}),
|
||||
'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}),
|
||||
'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
|
||||
'fin': forms.TextInput(attrs={"placeholder": _('hh:mm facultatif')})
|
||||
"description": forms.Textarea(
|
||||
attrs={"placeholder": _("facultatif, balises html supportées")}
|
||||
),
|
||||
"date": forms.TextInput(attrs={"placeholder": "jj/mm/aaaa"}),
|
||||
"debut": forms.TextInput(attrs={"placeholder": "hh:mm"}),
|
||||
"fin": forms.TextInput(attrs={"placeholder": _("hh:mm facultatif")}),
|
||||
}
|
||||
|
||||
|
||||
|
||||
class EventForm(forms.ModelForm):
|
||||
|
||||
|
||||
class Meta:
|
||||
model = Event
|
||||
exclude = ['slug']
|
||||
exclude = ["slug"]
|
||||
widgets = {
|
||||
'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'}),
|
||||
'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
|
||||
'fin': forms.TextInput(attrs={"placeholder": _('hh:mm 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"}),
|
||||
"debut": forms.TextInput(attrs={"placeholder": "hh:mm"}),
|
||||
"fin": forms.TextInput(attrs={"placeholder": _("hh:mm facultatif")}),
|
||||
}
|
||||
|
||||
|
||||
class ParticipantsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Participants
|
||||
fields = ('reponse', 'details')
|
||||
fields = ("reponse", "details")
|
||||
widgets = {
|
||||
'details': forms.Textarea(
|
||||
attrs={"placeholder": _("50 caractères max")}),
|
||||
"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.get_doodlename()
|
||||
self.fields["doodlename"].initial = self.instance.profile.get_doodlename()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(ChangeDoodleName, self).save(*args, **kwargs)
|
||||
self.instance.profile.doodlename = self.cleaned_data['doodlename']
|
||||
self.instance.profile.doodlename = self.cleaned_data["doodlename"]
|
||||
self.instance.profile.save()
|
||||
self.instance.save()
|
||||
|
||||
class Meta:
|
||||
model = ErnestoUser
|
||||
fields = ('doodlename',)
|
||||
model = ErnestoUser
|
||||
fields = ("doodlename",)
|
||||
|
|
|
@ -7,37 +7,82 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestion', '0001_initial'),
|
||||
("gestion", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Event',
|
||||
name="Event",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('nom', models.CharField(max_length=100)),
|
||||
('nomcourt', models.CharField(max_length=9, verbose_name='Nom court')),
|
||||
('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)),
|
||||
('desc_users', models.TextField(blank=True, verbose_name='Infos (visible seulement des fanfaron-ne-s)', null=True)),
|
||||
('calendrier', models.BooleanField(verbose_name='Afficher dans le calendrier pour tous', default=False)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("nom", models.CharField(max_length=100)),
|
||||
("nomcourt", models.CharField(max_length=9, verbose_name="Nom court")),
|
||||
("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)),
|
||||
(
|
||||
"desc_users",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
verbose_name="Infos (visible seulement des fanfaron-ne-s)",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"calendrier",
|
||||
models.BooleanField(
|
||||
verbose_name="Afficher dans le calendrier pour tous",
|
||||
default=False,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Événement',
|
||||
"verbose_name": "Événement",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Participants',
|
||||
name="Participants",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('reponse', models.CharField(max_length=20, choices=[('oui', 'Oui'), ('non', 'Non'), ('pe', 'Peut-être')], default='non', verbose_name='Réponse')),
|
||||
('details', models.CharField(blank=True, max_length=50)),
|
||||
('event', models.ForeignKey(to='calendrier.Event', on_delete=models.CASCADE)),
|
||||
('participant', models.ForeignKey(to='gestion.ErnestoUser', on_delete=models.CASCADE)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"reponse",
|
||||
models.CharField(
|
||||
max_length=20,
|
||||
choices=[("oui", "Oui"), ("non", "Non"), ("pe", "Peut-être")],
|
||||
default="non",
|
||||
verbose_name="Réponse",
|
||||
),
|
||||
),
|
||||
("details", models.CharField(blank=True, max_length=50)),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(to="calendrier.Event", on_delete=models.CASCADE),
|
||||
),
|
||||
(
|
||||
"participant",
|
||||
models.ForeignKey(
|
||||
to="gestion.ErnestoUser", on_delete=models.CASCADE
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,43 +1,63 @@
|
|||
# Generated by Django 2.2.14 on 2020-07-14 15:59
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('calendrier', '0001_initial'),
|
||||
("calendrier", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='event',
|
||||
options={'verbose_name': 'Evenement'},
|
||||
name="event",
|
||||
options={"verbose_name": "Evenement"},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='desc_users_en',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='Infos en anglais (visible seulement des fanfaron-ne-s)'),
|
||||
model_name="event",
|
||||
name="desc_users_en",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Infos en anglais (visible seulement des fanfaron-ne-s)",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='description_en',
|
||||
model_name="event",
|
||||
name="description_en",
|
||||
field=models.TextField(blank=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='calendrier',
|
||||
field=models.CharField(choices=[('F', 'Visible seulement par les fanfarons'), ('T', 'Afficher dans le calendrier pour tous'), ('H', 'Hall of fame')], default='F', max_length=1),
|
||||
model_name="event",
|
||||
name="calendrier",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("F", "Visible seulement par les fanfarons"),
|
||||
("T", "Afficher dans le calendrier pour tous"),
|
||||
("H", "Hall of fame"),
|
||||
],
|
||||
default="F",
|
||||
max_length=1,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='slug',
|
||||
field=models.CharField(default=uuid.uuid1, editable=False, max_length=7, unique=True),
|
||||
model_name="event",
|
||||
name="slug",
|
||||
field=models.CharField(
|
||||
default=uuid.uuid1, editable=False, max_length=7, unique=True
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='participants',
|
||||
name='reponse',
|
||||
field=models.CharField(choices=[('oui', 'Oui'), ('non', 'Non'), ('pe', 'Peut-etre')], default='non', max_length=20, verbose_name='Réponse'),
|
||||
model_name="participants",
|
||||
name="reponse",
|
||||
field=models.CharField(
|
||||
choices=[("oui", "Oui"), ("non", "Non"), ("pe", "Peut-etre")],
|
||||
default="non",
|
||||
max_length=20,
|
||||
verbose_name="Réponse",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
22
calendrier/migrations/0003_auto_20210427_1834.py
Normal file
22
calendrier/migrations/0003_auto_20210427_1834.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 2.2.17 on 2021-04-27 18:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("calendrier", "0002_auto_20200714_1559"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="event",
|
||||
name="desc_users_en",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Infos en anglais (visible seulement des fanfaron-ne-s",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,54 +1,62 @@
|
|||
from django.db import models
|
||||
import uuid
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
ANSWERS = (
|
||||
('oui', _('Oui')),
|
||||
('non', _('Non')),
|
||||
('pe', _('Peut-etre')),
|
||||
)
|
||||
("oui", _("Oui")),
|
||||
("non", _("Non")),
|
||||
("pe", _("Peut-etre")),
|
||||
)
|
||||
|
||||
|
||||
class Event(models.Model):
|
||||
|
||||
nom = models.CharField(max_length=100)
|
||||
nomcourt = models.CharField(max_length=9, verbose_name=_("Nom court"))
|
||||
date = models.DateField()
|
||||
debut = models.TimeField()
|
||||
fin = models.TimeField(blank=True, null=True)
|
||||
slug = models.CharField(max_length=7, editable=False, unique=True, default=uuid.uuid1)
|
||||
slug = models.CharField(
|
||||
max_length=7, editable=False, unique=True, default=uuid.uuid1
|
||||
)
|
||||
lieu = models.CharField(max_length=200)
|
||||
description = models.TextField(blank=True)
|
||||
description_en = models.TextField(blank=True)
|
||||
desc_users = models.TextField(
|
||||
blank=True,
|
||||
verbose_name=_("Infos (visible seulement des fanfaron-ne-s)"),
|
||||
null=True)
|
||||
blank=True,
|
||||
verbose_name=_("Infos (visible seulement des fanfaron-ne-s)"),
|
||||
null=True,
|
||||
)
|
||||
desc_users_en = models.TextField(
|
||||
blank=True,
|
||||
verbose_name=_("Infos en anglais (visible seulement des fanfaron-ne-s)"),
|
||||
null=True)
|
||||
blank=True,
|
||||
verbose_name=_("Infos en anglais (visible seulement des fanfaron-ne-s"),
|
||||
null=True,
|
||||
)
|
||||
CALENDRIER_CHOICES = [
|
||||
('F', _('Visible seulement par les fanfarons')),
|
||||
('T', _('Afficher dans le calendrier pour tous')),
|
||||
('H', _('Hall of fame')),
|
||||
("F", _("Visible seulement par les fanfarons")),
|
||||
("T", _("Afficher dans le calendrier pour tous")),
|
||||
("H", _("Hall of fame")),
|
||||
]
|
||||
calendrier = models.CharField(
|
||||
max_length=1,
|
||||
choices=CALENDRIER_CHOICES,
|
||||
default='F',
|
||||
default="F",
|
||||
)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.nom
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Evenement")
|
||||
|
||||
|
||||
class Participants(models.Model):
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE)
|
||||
participant = models.ForeignKey(ErnestoUser, on_delete=models.CASCADE)
|
||||
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)
|
||||
|
|
|
@ -13,10 +13,23 @@
|
|||
<!-- One -->
|
||||
<section class="wrapper style1" >
|
||||
<div class="inner">
|
||||
<p align="center"><div><span class="image right"><img src="{% static 'images/agenda.jpg' %}" alt="" />
|
||||
|
||||
<p align="center"><div><span class="image right">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/agenda.jpg' %}" alt="" />
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span></div>
|
||||
<h2 align="center">{% trans "Découvrez les différents évènements de l'Ernestophone !" %}</h2>
|
||||
|
||||
|
@ -33,15 +46,7 @@
|
|||
<a href="mailto:fanfare@ens.fr" class="icon fa-envelope fa-5x "><span
|
||||
|
||||
class="label">Mail</span></a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ"
|
||||
|
||||
class="icon fa-youtube-play fa-5x"><span class="label">Youtube</span></a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -98,7 +103,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<h1> {% blocktrans count counter=events_passe|length %}Evénement passé :{% plural %}Evénements passés :{% endblocktrans %} </h1>
|
||||
|
||||
<div class="table-wrapper" color="white">
|
||||
|
@ -154,4 +159,5 @@
|
|||
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
{% load i18n %}
|
||||
{% load translate %}
|
||||
{% load autotranslate %}
|
||||
|
||||
{% get_current_language as current_language %}
|
||||
|
||||
{% block extrahead %}
|
||||
|
@ -16,28 +17,28 @@
|
|||
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
|
||||
<div class="inner">
|
||||
<span class="image fit">
|
||||
<img src="{% static 'images/home.png' %}"/>
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="" class="icon fa-copyright">lor_tie</a>
|
||||
</div>
|
||||
</span>
|
||||
{% if actu %}
|
||||
<div class="box" style="background-color:rgba(228,82,47,0.5)">
|
||||
|
||||
<h4> {% blocktrans count counter=actu|length %}Actualité des chef·fe·s:{% plural %}Actualités des chef·fe·s:{% endblocktrans %}</h4>
|
||||
<ul>
|
||||
{% for a in actu %}
|
||||
<li>{% autotranslate current_language a.text a.text_en %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div id="instagram-feed" class="instagram_feed"> </div>
|
||||
|
||||
|
||||
|
||||
<h4>{% trans "Agenda :" %} </h4>
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
|
||||
{% if actu %}
|
||||
<div class="box" style="background-color:rgba(228,82,47,0.5)">
|
||||
|
||||
<h4> {% blocktrans count counter=actu|length %}Actualité des chef·fe·s:{% plural %}Actualités des chef·fe·s:{% endblocktrans %}</h4>
|
||||
<ul>
|
||||
{% for a in actu %}
|
||||
<li>{% autotranslate current_language a.text a.text_en %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<h4>{% trans "Agenda :" %} </h4>
|
||||
<table width="100%" style="background-color:#e4522f" >
|
||||
<tr>
|
||||
<td width="20%" align="left">
|
||||
|
@ -71,6 +72,25 @@
|
|||
</div>
|
||||
<div class="1u 12u$(small)"><p></p></div>
|
||||
<div class="5u 12u$(small)">
|
||||
|
||||
<span class="image fit">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/home.png' %}"/>
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<div class="icon fa-copyright"> lor_tie</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
{% if events_a_venir_not_answered %}
|
||||
<div class="box" style="background-color:#e4522f">
|
||||
<h1> {% blocktrans count counter=events_a_venir_not_answered|length %}Doodle à remplir !!!! :{% plural %}Doodles à remplir !!!! :{% endblocktrans %} </h1>
|
||||
|
@ -182,10 +202,29 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/InstagramFeed.min.js' %}"></script>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
new InstagramFeed({
|
||||
'username': 'ernestophone',
|
||||
'container': "#instagram-feed" ,
|
||||
'display_profile': false,
|
||||
'display_biography': false,
|
||||
'display_gallery': true,
|
||||
'display_captions': true,
|
||||
'callback': null,
|
||||
'styling': true,
|
||||
'items': 8,
|
||||
'items_per_row': 8,
|
||||
'margin': 1
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -20,7 +20,7 @@ def translate(tex):
|
|||
tex = tex.replace("December", "Décembre", 1)
|
||||
tex = tex.replace("Mon", "Lun", 1)
|
||||
tex = tex.replace("Tue", "Mar", 1)
|
||||
tex = tex.replace('Wed', "Mer", 1)
|
||||
tex = tex.replace("Wed", "Mer", 1)
|
||||
tex = tex.replace("Thu", "Jeu", 1)
|
||||
tex = tex.replace("Fri", "Ven", 1)
|
||||
tex = tex.replace("Sat", "Sam", 1)
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.test import Client, TestCase
|
|||
from django.utils import timezone
|
||||
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
from ..models import Event
|
||||
|
||||
User = get_user_model()
|
||||
|
@ -28,11 +29,7 @@ class TestViews(TestCase):
|
|||
ernesto = new_user("ernesto", ernesto=True)
|
||||
ernesto_c = Client()
|
||||
ernesto_c.force_login(ernesto)
|
||||
self.client_matrix = [
|
||||
(chef, chef_c),
|
||||
(ernesto, ernesto_c),
|
||||
(None, Client())
|
||||
]
|
||||
self.client_matrix = [(chef, chef_c), (ernesto, ernesto_c), (None, Client())]
|
||||
# A private and a public event
|
||||
now = timezone.now()
|
||||
later = now + timedelta(seconds=3600)
|
||||
|
@ -44,7 +41,7 @@ class TestViews(TestCase):
|
|||
fin=later.time(),
|
||||
slug="privevt",
|
||||
lieu="somewhere",
|
||||
calendrier=False
|
||||
calendrier=False,
|
||||
)
|
||||
self.pub_event = Event.objects.create(
|
||||
nom="public event",
|
||||
|
@ -54,7 +51,7 @@ class TestViews(TestCase):
|
|||
fin=later.time(),
|
||||
slug="pubevt",
|
||||
lieu="somewhere",
|
||||
calendrier=True
|
||||
calendrier=True,
|
||||
)
|
||||
|
||||
# Everyone can see theses pages
|
||||
|
@ -88,13 +85,16 @@ class TestViews(TestCase):
|
|||
chef, _ = self.client_matrix[0]
|
||||
codereps = ["oui", "non", "pe"]
|
||||
for coderep in codereps:
|
||||
url = "/calendar/rep/{}/{}/{}".format(chef.profile.slug, self.priv_event.slug, coderep)
|
||||
url = "/calendar/rep/{}/{}/{}".format(
|
||||
chef.profile.slug, self.priv_event.slug, coderep
|
||||
)
|
||||
self._everyone_can_get(url, redirect_url="/calendar/")
|
||||
|
||||
# Only ernesto members can get theses pages
|
||||
|
||||
def _get_restricted_page(self, url, chef_only=False, redirect_url=None):
|
||||
"""Shorthand for testing wether a page in only accessible by ernesto members"""
|
||||
|
||||
def user_allowed(user):
|
||||
if user is None:
|
||||
return False
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
from .views import EventUpdate, EventDelete
|
||||
from .views import EventDelete, EventUpdate
|
||||
|
||||
app_name = 'calendrier'
|
||||
app_name = "calendrier"
|
||||
urlpatterns = [
|
||||
path('', views.liste, name='liste'),
|
||||
path("calendar", views.home, name="home"),
|
||||
path("new", views.create_event, name="create_event"),
|
||||
path("", views.Agenda.as_view(), name="liste"),
|
||||
path("calendar", views.Home.as_view(), name="home"),
|
||||
path("new", views.CreateEvent.as_view(), name="create_event"),
|
||||
path("edition/<int:pk>", EventUpdate.as_view(), name="edit_event"),
|
||||
path("supprimer/<int:pk>", EventDelete.as_view(), name="delete_event"),
|
||||
path("<int:id>/changename", views.changename, name="change-doodle-name"),
|
||||
path("<int:id>/reponse", views.reponse, name="reponse"),
|
||||
path("<int:pYear>/<int:pMonth>", views.calendar, name="view-month"),
|
||||
path("<int:id>", views.view_event, name="view-event"),
|
||||
path("<int:id>/changename", views.ChangeName.as_view(), name="change-doodle-name"),
|
||||
path("<int:id>/reponse", views.ReponseEvent.as_view(), name="reponse"),
|
||||
path("<int:pYear>/<int:pMonth>", views.Calendar.as_view(), name="view-month"),
|
||||
path("<int:id>", views.ViewEvent.as_view(), name="view-event"),
|
||||
]
|
||||
|
|
|
@ -1,214 +1,300 @@
|
|||
import random
|
||||
import string
|
||||
from calendar import monthrange
|
||||
from collections import defaultdict
|
||||
from datetime import date, datetime
|
||||
import string
|
||||
import random
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db.models import Q
|
||||
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.db.models import Count
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import UpdateView, DeleteView
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.core.mail import send_mail
|
||||
from django.http import Http404
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import DeleteView, TemplateView, UpdateView
|
||||
|
||||
from gestion.models import ErnestoUser
|
||||
from actu.models import Actu
|
||||
from calendrier.calend import EventCalendar
|
||||
from calendar import monthrange
|
||||
from calendrier.forms import ModifEventForm, EventForm, ParticipantsForm, ChangeDoodleName
|
||||
from calendrier.forms import (ChangeDoodleName, EventForm, ModifEventForm,
|
||||
ParticipantsForm)
|
||||
from calendrier.models import Event, Participants
|
||||
from partitions.decorators import chef_required
|
||||
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from gestion.models import Photo
|
||||
|
||||
|
||||
def generer(*args):
|
||||
caracteres = string.ascii_letters + string.digits
|
||||
aleatoire = [random.choice(caracteres) for _ in range(6)]
|
||||
return ''.join(aleatoire)
|
||||
|
||||
def liste(request):
|
||||
if request.user.is_authenticated :
|
||||
return redirect('calendrier:home')
|
||||
lToday = datetime.today()
|
||||
events_a_venir = Event.objects.filter(date__gte = lToday).exclude(calendrier__iexact = 'F')
|
||||
events_passe = Event.objects.filter(date__lt = lToday).filter(calendrier__iexact = 'H')
|
||||
return render(request, 'calendrier/agenda.html', {"events_a_venir": events_a_venir,"events_passe":events_passe})
|
||||
return "".join(aleatoire)
|
||||
|
||||
|
||||
def named_month(pMonthNumber):
|
||||
return date(1900, pMonthNumber, 1).strftime('%B')
|
||||
return date(1900, pMonthNumber, 1).strftime("%B")
|
||||
|
||||
@login_required
|
||||
def home(request):
|
||||
|
||||
class Agenda(TemplateView):
|
||||
template_name = "calendrier/agenda.html"
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
return redirect("calendrier:home")
|
||||
return super(Agenda, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
lToday = datetime.today()
|
||||
context["photo"] = Photo.objects.filter(cat="liste").order_by("?").first()
|
||||
context["events_a_venir"] = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.exclude(calendrier__iexact="F")
|
||||
.order_by("-date")
|
||||
)
|
||||
context["events_passe"] = (
|
||||
Event.objects.filter(date__lt=lToday)
|
||||
.filter(calendrier__iexact="H")
|
||||
.order_by("-date")
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class Calendar(LoginRequiredMixin, TemplateView):
|
||||
template_name = "calendrier/home.html"
|
||||
|
||||
@property
|
||||
def pYear(self):
|
||||
return self.kwargs["pYear"]
|
||||
|
||||
@property
|
||||
def pMonth(self):
|
||||
return self.kwargs["pMonth"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(Calendar, self).get_context_data(**kwargs)
|
||||
actu = Actu.objects.all()
|
||||
photo = Photo.objects.filter(cat="home").order_by("?").first()
|
||||
lToday = datetime.now()
|
||||
lYear = int(self.pYear)
|
||||
lMonth = int(self.pMonth)
|
||||
lCalendarFromMonth = datetime(lYear, lMonth, 1)
|
||||
lCalendarToMonth = datetime(lYear, lMonth, monthrange(lYear, lMonth)[1])
|
||||
lEvents = Event.objects.filter(
|
||||
date__gte=lCalendarFromMonth, date__lte=lCalendarToMonth
|
||||
)
|
||||
lCalendar = EventCalendar(lEvents).formatmonth(lYear, lMonth)
|
||||
lPreviousYear = lYear
|
||||
lPreviousMonth = lMonth - 1
|
||||
if lPreviousMonth == 0:
|
||||
lPreviousMonth = 12
|
||||
lPreviousYear -= 1
|
||||
lNextYear = lYear
|
||||
lNextMonth = lMonth + 1
|
||||
if lNextMonth == 13:
|
||||
lNextMonth = 1
|
||||
lNextYear = lYear + 1
|
||||
lYearAfterThis = lYear + 1
|
||||
lYearBeforeThis = lYear - 1
|
||||
try:
|
||||
events_a_venir_not_answered = Event.objects.filter(
|
||||
date__gte=lToday
|
||||
).exclude(participants__participant=self.request.user.profile)
|
||||
events_a_venir_answered_yes = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="oui")
|
||||
)
|
||||
events_a_venir_answered_no = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="non")
|
||||
)
|
||||
events_a_venir_answered_pe = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="pe")
|
||||
)
|
||||
except Event.DoesNotExist:
|
||||
events_a_venir_not_answered = Event.objects.filter(
|
||||
date__gte=lToday
|
||||
).exclude(participants__participant__user__username=self.request.user)
|
||||
events_a_venir_answered_yes = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant__user__username=self.request.user)
|
||||
& Q(participants__reponse="oui")
|
||||
)
|
||||
events_a_venir_answered_no = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant__user__username=self.request.user)
|
||||
& Q(participants__reponse="non")
|
||||
)
|
||||
events_a_venir_answered_pe = Event.objects.filter(date__gte=lToday).filter(
|
||||
Q(participants__participant__user__username=self.request.user)
|
||||
& Q(participants__reponse="pe")
|
||||
)
|
||||
|
||||
context["Calendar"] = mark_safe(lCalendar)
|
||||
context["Month"] = lMonth
|
||||
context["MonthName"] = named_month(lMonth)
|
||||
context["Year"] = lYear
|
||||
context["PreviousMonth"] = lPreviousMonth
|
||||
context["PreviousMonthName"] = named_month(lPreviousMonth)
|
||||
context["PreviousYear"] = lPreviousYear
|
||||
context["NextMonth"] = lNextMonth
|
||||
context["NextMonthName"] = named_month(lNextMonth)
|
||||
context["NextYear"] = lNextYear
|
||||
context["YearBeforeThis"] = lYearBeforeThis
|
||||
context["YearAfterThis"] = lYearAfterThis
|
||||
context["events_a_venir_answered_yes"] = events_a_venir_answered_yes
|
||||
context["events_a_venir_answered_no"] = events_a_venir_answered_no
|
||||
context["events_a_venir_answered_pe"] = events_a_venir_answered_pe
|
||||
context["events_a_venir_not_answered"] = events_a_venir_not_answered
|
||||
context["actu"] = actu
|
||||
context["photo"] = photo
|
||||
return context
|
||||
|
||||
|
||||
class Home(Calendar):
|
||||
lToday = datetime.now()
|
||||
return calendar(request, lToday.year, lToday.month)
|
||||
|
||||
@login_required
|
||||
def calendar(request, pYear, pMonth):
|
||||
actu = Actu.objects.all()
|
||||
lToday = datetime.now()
|
||||
lYear = int(pYear)
|
||||
lMonth = int(pMonth)
|
||||
lCalendarFromMonth = datetime(lYear, lMonth, 1)
|
||||
lCalendarToMonth = datetime(lYear, lMonth, monthrange(lYear, lMonth)[1])
|
||||
lEvents = Event.objects.filter(
|
||||
date__gte=lCalendarFromMonth, date__lte=lCalendarToMonth
|
||||
)
|
||||
if request.user.is_authenticated:
|
||||
lEvents = Event.objects.filter(date__gte=lCalendarFromMonth,
|
||||
date__lte=lCalendarToMonth)
|
||||
lCalendar = EventCalendar(lEvents).formatmonth(lYear, lMonth)
|
||||
lPreviousYear = lYear
|
||||
lPreviousMonth = lMonth - 1
|
||||
if lPreviousMonth == 0:
|
||||
lPreviousMonth = 12
|
||||
lPreviousYear -= 1
|
||||
lNextYear = lYear
|
||||
lNextMonth = lMonth + 1
|
||||
if lNextMonth == 13:
|
||||
lNextMonth = 1
|
||||
lNextYear = lYear + 1
|
||||
lYearAfterThis = lYear + 1
|
||||
lYearBeforeThis = lYear - 1
|
||||
try:
|
||||
events_a_venir_not_answered = Event.objects.filter(date__gte = lToday).exclude(participants__participant=request.user.profile)
|
||||
events_a_venir_answered = Event.objects.filter(date__gte = lToday).filter(participants__participant=request.user.profile)
|
||||
events_a_venir_answered_yes = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant=request.user.profile )& Q(participants__reponse= 'oui'))
|
||||
events_a_venir_answered_no = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant=request.user.profile) & Q(participants__reponse= 'non'))
|
||||
events_a_venir_answered_pe = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant=request.user.profile)& Q(participants__reponse= 'pe'))
|
||||
except:
|
||||
events_a_venir_not_answered = Event.objects.filter(date__gte = lToday).exclude(participants__participant__user__username=request.user)
|
||||
events_a_venir_answered = Event.objects.filter(date__gte = lToday).filter(participants__participant__user__username=request.user)
|
||||
events_a_venir_answered_yes = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant__user__username=request.user )& Q(participants__reponse= 'oui'))
|
||||
events_a_venir_answered_no = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant__user__username=request.user) & Q(participants__reponse= 'non'))
|
||||
events_a_venir_answered_pe = Event.objects.filter(date__gte = lToday).filter(Q(participants__participant__user__username=request.user)& Q(participants__reponse= 'pe'))
|
||||
return render(request, 'calendrier/home.html', {
|
||||
'Calendar': mark_safe(lCalendar),
|
||||
'Month': lMonth,
|
||||
'MonthName': named_month(lMonth),
|
||||
'Year': lYear,
|
||||
'PreviousMonth': lPreviousMonth,
|
||||
'PreviousMonthName': named_month(lPreviousMonth),
|
||||
'PreviousYear': lPreviousYear,
|
||||
'NextMonth': lNextMonth,
|
||||
'NextMonthName': named_month(lNextMonth),
|
||||
'NextYear': lNextYear,
|
||||
'YearBeforeThis': lYearBeforeThis,
|
||||
'YearAfterThis': lYearAfterThis,
|
||||
"events_a_venir_answered_yes": events_a_venir_answered_yes,
|
||||
"events_a_venir_answered_no": events_a_venir_answered_no,
|
||||
"events_a_venir_answered_pe": events_a_venir_answered_pe,
|
||||
"events_a_venir_not_answered": events_a_venir_not_answered,
|
||||
"actu" : actu,
|
||||
@property
|
||||
def pYear(self):
|
||||
return self.lToday.year
|
||||
|
||||
})
|
||||
|
||||
@login_required
|
||||
def view_event(request, id):
|
||||
event = get_object_or_404(Event, id=id)
|
||||
participants = event.participants_set.all()
|
||||
multi_instrumentistes = event.participants_set.filter(Q(participant__multi_instrumentiste = 'Oui')& ~Q(reponse = 'non'))
|
||||
|
||||
# Restricted event, only erneso users can see it
|
||||
if not request.user.is_authenticated and not event.calendrier:
|
||||
return redirect(reverse('calendrier:home'))
|
||||
|
||||
# Count the number of occurences of each instrument
|
||||
instrument_count = defaultdict(lambda: (0, 0,[],[],[]))
|
||||
for participant in participants:
|
||||
instrument = participant.participant.instru
|
||||
if (instrument == "Autre"):
|
||||
instrument = participant.participant.instru_autre
|
||||
|
||||
sure, maybe, namesoui, namespe, namesnon = instrument_count[instrument]
|
||||
|
||||
if participant.reponse == "oui":
|
||||
|
||||
namesoui += [participant.participant.get_doodlename()]
|
||||
instrument_count[instrument] = (sure + 1, maybe,namesoui,namespe,namesnon)
|
||||
elif participant.reponse == "pe":
|
||||
namespe += [participant.participant.get_doodlename()]
|
||||
instrument_count[instrument] = (sure, maybe + 1,namesoui,namespe,namesnon)
|
||||
else:
|
||||
namesnon += [participant.participant.get_doodlename()]
|
||||
instrument_count[instrument] = (sure, maybe,namesoui,namespe,namesnon)
|
||||
|
||||
instrument_count = [
|
||||
(instrument, sure, maybe,namesoui, namespe ,namesnon)
|
||||
for instrument, (sure, maybe,namesoui,namespe,namesnon) in instrument_count.items()
|
||||
]
|
||||
|
||||
context = {
|
||||
"event": event,
|
||||
"instrument_count": instrument_count,
|
||||
"participants": participants,
|
||||
"nboui": len(participants.filter(reponse="oui")),
|
||||
"nbpe": len(participants.filter(reponse="pe")),
|
||||
"nbnon": len(participants.filter(reponse="non")),
|
||||
"multi_instrumentistes":multi_instrumentistes,
|
||||
}
|
||||
return render(request, 'calendrier/view_event.html', context=context)
|
||||
@property
|
||||
def pMonth(self):
|
||||
return self.lToday.month
|
||||
|
||||
|
||||
class ViewEvent(LoginRequiredMixin, TemplateView):
|
||||
template_name = "calendrier/view_event.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ViewEvent, self).get_context_data(**kwargs)
|
||||
event = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
participants = event.participants_set.all()
|
||||
multi_instrumentistes = event.participants_set.filter(
|
||||
Q(participant__multi_instrumentiste="Oui") & ~Q(reponse="non")
|
||||
)
|
||||
|
||||
# Restricted event, only erneso users can see it
|
||||
if not self.request.user.is_authenticated and not event.calendrier:
|
||||
return redirect(reverse("calendrier:home"))
|
||||
|
||||
# Count the number of occurences of each instrument
|
||||
instrument_count = defaultdict(lambda: (0, 0, [], [], []))
|
||||
for participant in participants:
|
||||
instru = participant.participant.instru
|
||||
if instru == "Autre":
|
||||
instru = participant.participant.instru_autre
|
||||
|
||||
sure, maybe, namesoui, namespe, namesnon = instrument_count[instru]
|
||||
|
||||
if participant.reponse == "oui":
|
||||
|
||||
namesoui += [participant.participant.get_doodlename()]
|
||||
instrument_count[instru] = (
|
||||
sure + 1,
|
||||
maybe,
|
||||
namesoui,
|
||||
namespe,
|
||||
namesnon,
|
||||
)
|
||||
elif participant.reponse == "pe":
|
||||
namespe += [participant.participant.get_doodlename()]
|
||||
instrument_count[instru] = (
|
||||
sure,
|
||||
maybe + 1,
|
||||
namesoui,
|
||||
namespe,
|
||||
namesnon,
|
||||
)
|
||||
else:
|
||||
namesnon += [participant.participant.get_doodlename()]
|
||||
instrument_count[instru] = (sure, maybe, namesoui, namespe, namesnon)
|
||||
|
||||
instrument_count = [
|
||||
(instrument, sure, maybe, namesoui, namespe, namesnon)
|
||||
for instrument, (
|
||||
sure,
|
||||
maybe,
|
||||
namesoui,
|
||||
namespe,
|
||||
namesnon,
|
||||
) in instrument_count.items()
|
||||
]
|
||||
|
||||
context["event"] = event
|
||||
context["instrument_count"] = instrument_count
|
||||
context["participants"] = participants
|
||||
context["nboui"] = len(participants.filter(reponse="oui"))
|
||||
context["nbpe"] = len(participants.filter(reponse="pe"))
|
||||
context["nbnon"] = len(participants.filter(reponse="non"))
|
||||
context["multi_instrumentistes"] = multi_instrumentistes
|
||||
return context
|
||||
|
||||
|
||||
class ChangeName(LoginRequiredMixin, TemplateView):
|
||||
form_class = ChangeDoodleName
|
||||
template_name = "calendrier/changename.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class(instance=self.request.user)
|
||||
context["id"] = self.kwargs["id"]
|
||||
return context
|
||||
|
||||
@login_required
|
||||
def changename(request,id):
|
||||
if request.method == 'POST':
|
||||
def post(self, request, *args, **kwargs):
|
||||
success = False
|
||||
requbis = request.POST.copy()
|
||||
form = ChangeDoodleName(requbis, instance=request.user)
|
||||
form = self.form_class(requbis, instance=request.user)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
success = True
|
||||
return redirect('calendrier:view-event',id=id)
|
||||
else:
|
||||
form = ChangeDoodleName(instance=request.user)
|
||||
return render(request, 'calendrier/changename.html',locals())
|
||||
return redirect("calendrier:view-event", id=self.kwargs["id"])
|
||||
else:
|
||||
context = self.get_context_data()
|
||||
context["success"] = success
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
@chef_required
|
||||
def create_event(request):
|
||||
if request.method == "POST":
|
||||
form = EventForm(request.POST)
|
||||
class CreateEvent(LoginRequiredMixin, TemplateView):
|
||||
form_class = EventForm
|
||||
template_name = "calendrier/create.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class()
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.form_class(request.POST)
|
||||
if form.is_valid():
|
||||
temp = True
|
||||
while temp:
|
||||
code = generer()
|
||||
try:
|
||||
Event.objects.get(slug=code)
|
||||
except:
|
||||
except Event.DoesNotExist:
|
||||
temp = False
|
||||
nom = form.cleaned_data["nom"]
|
||||
date = form.cleaned_data["date"]
|
||||
date = date.strftime('%d/%m/%Y')
|
||||
debut = form.cleaned_data["debut"]
|
||||
date = date.strftime("%d/%m/%Y")
|
||||
obj = form.save(commit=False)
|
||||
obj.slug = code
|
||||
obj.save()
|
||||
id = obj.id
|
||||
envoi = True
|
||||
return redirect('calendrier:view-event',id=id)
|
||||
|
||||
else:
|
||||
form = EventForm()
|
||||
|
||||
return render(request, "calendrier/create.html", locals())
|
||||
return redirect("calendrier:view-event", id=id)
|
||||
else:
|
||||
context = self.get_context_data()
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class ReponseEvent(LoginRequiredMixin, TemplateView):
|
||||
form_class = ParticipantsForm
|
||||
template_name = "calendrier/reponse.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class()
|
||||
context["ev"] = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
context["id"] = self.kwargs["id"]
|
||||
return context
|
||||
|
||||
@login_required
|
||||
def reponse(request, id):
|
||||
part = request.user.profile
|
||||
ev = get_object_or_404(Event, id=id)
|
||||
if request.method == "POST":
|
||||
form = ParticipantsForm(request.POST)
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.form_class(request.POST)
|
||||
ev = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
part = request.user.profile
|
||||
if form.is_valid():
|
||||
try:
|
||||
p = Participants.objects.get(event=ev, participant=part)
|
||||
|
@ -219,43 +305,32 @@ def reponse(request, id):
|
|||
obj.event = ev
|
||||
obj.participant = part
|
||||
obj.save()
|
||||
envoi = True
|
||||
return redirect('calendrier:view-event',id=id)
|
||||
else:
|
||||
form = ParticipantsForm()
|
||||
return render(request, "calendrier/reponse.html", locals())
|
||||
return redirect("calendrier:view-event", id=self.kwargs["id"])
|
||||
else:
|
||||
context = self.get_context_data()
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
|
||||
|
||||
class EventUpdate(UpdateView):
|
||||
class EventUpdate(ChefRequiredMixin, UpdateView):
|
||||
model = Event
|
||||
template_name = "calendrier/update.html"
|
||||
form_class = ModifEventForm
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(EventUpdate, self).get_context_data(**kwargs)
|
||||
ctx['id'] = self.get_object().id
|
||||
ctx["id"] = self.get_object().id
|
||||
return ctx
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('calendrier:view-event', kwargs={'id' : self.get_object().id})
|
||||
|
||||
@method_decorator(chef_required)
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(EventUpdate, self).dispatch(*args, **kwargs)
|
||||
return reverse("calendrier:view-event", kwargs={"id": self.get_object().id})
|
||||
|
||||
|
||||
class EventDelete(DeleteView):
|
||||
class EventDelete(ChefRequiredMixin, DeleteView):
|
||||
model = Event
|
||||
template_name = "calendrier/delete.html"
|
||||
success_url = reverse_lazy("calendrier:home")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super(EventDelete, self).get_context_data(**kwargs)
|
||||
ctx['id'] = self.get_object().id
|
||||
ctx["id"] = self.get_object().id
|
||||
return ctx
|
||||
|
||||
@method_decorator(chef_required)
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(EventDelete,self).dispatch(*args, **kwargs)
|
||||
|
|
|
@ -6,12 +6,11 @@ les permissions.
|
|||
"""
|
||||
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.models import User, Group, Permission
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.models import Group, Permission, User
|
||||
|
||||
from gestion.models import ErnestoUser, VideoGallery
|
||||
from actu.models import Actu
|
||||
|
||||
from gestion.models import ErnestoUser, Photo, VideoGallery
|
||||
|
||||
|
||||
class UserProfileInline(admin.StackedInline):
|
||||
|
@ -112,7 +111,9 @@ class UserProfileAdmin(UserAdmin):
|
|||
user.groups.add(chef_group)
|
||||
user.save()
|
||||
|
||||
|
||||
admin.site.unregister(User)
|
||||
admin.site.register(User, UserProfileAdmin)
|
||||
admin.site.register(VideoGallery)
|
||||
admin.site.register(Photo)
|
||||
admin.site.register(Actu)
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class GestionConfig(AppConfig):
|
||||
name = 'gestion'
|
||||
name = "gestion"
|
||||
|
|
|
@ -1,47 +1,71 @@
|
|||
from django import forms
|
||||
from gestion.models import ErnestoUser
|
||||
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
|
||||
class RegistrationFormUser(UserCreationForm):
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('username', 'first_name', 'last_name', 'password1',
|
||||
'password2', 'email',)
|
||||
fields = (
|
||||
"username",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"password1",
|
||||
"password2",
|
||||
"email",
|
||||
)
|
||||
|
||||
|
||||
class ChangeFormUser(UserChangeForm):
|
||||
password = None
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ('first_name', 'last_name', 'email',)
|
||||
|
||||
fields = (
|
||||
"first_name",
|
||||
"last_name",
|
||||
"email",
|
||||
)
|
||||
|
||||
|
||||
class ChangeMembreForm(forms.ModelForm):
|
||||
def clean(self):
|
||||
cleaned_data = super(ChangeMembreForm, self).clean()
|
||||
instru=cleaned_data.get("instru")
|
||||
instru = cleaned_data.get("instru")
|
||||
instru_autre = cleaned_data.get("instru_autre")
|
||||
if (instru == "Autre") and not (instru_autre):
|
||||
raise forms.ValidationError(_("Préçisez quel autre instrument"))
|
||||
multi_instru=cleaned_data.get("multi_instrumentiste")
|
||||
multi_instru = cleaned_data.get("multi_instrumentiste")
|
||||
instru_bonus = cleaned_data.get("instru_bonus")
|
||||
if (multi_instru == "Oui") and not (instru_bonus):
|
||||
raise forms.ValidationError(_("Préçisez quel·s instrument·s supplémentaire·s vous pouvez jouer"))
|
||||
raise forms.ValidationError(
|
||||
_("Préçisez quel·s instrument·s supplémentaire·s vous pouvez jouer")
|
||||
)
|
||||
return cleaned_data
|
||||
|
||||
class Meta:
|
||||
model = ErnestoUser
|
||||
fields = ("phone", "instru","instru_autre","multi_instrumentiste","instru_bonus")
|
||||
fields = (
|
||||
"phone",
|
||||
"instru",
|
||||
"instru_autre",
|
||||
"multi_instrumentiste",
|
||||
"instru_bonus",
|
||||
)
|
||||
|
||||
|
||||
class InscriptionMembreForm(ChangeMembreForm):
|
||||
validation = forms.CharField(max_length=100, widget=forms.PasswordInput)
|
||||
|
||||
class Meta:
|
||||
model = ErnestoUser
|
||||
fields = ("phone", "instru","instru_autre",'multi_instrumentiste',
|
||||
'instru_bonus' )
|
||||
fields = (
|
||||
"phone",
|
||||
"instru",
|
||||
"instru_autre",
|
||||
"multi_instrumentiste",
|
||||
"instru_bonus",
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from django.db import migrations, models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -10,28 +10,64 @@ class Migration(migrations.Migration):
|
|||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ErnestoUser',
|
||||
name="ErnestoUser",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('is_ernesto', models.BooleanField(verbose_name="Membre de l'Ernestophone", default=True)),
|
||||
('is_chef', models.BooleanField(verbose_name='Chef Fanfare', default=False)),
|
||||
('phone', models.CharField(blank=True, max_length=20, verbose_name='Téléphone')),
|
||||
('instru', models.CharField(blank=True, max_length=40, verbose_name='Instrument joué')),
|
||||
('slug', models.CharField(max_length=7, editable=False, unique=True)),
|
||||
('doodlename', models.CharField(blank=True, max_length=30, verbose_name='Nom pour le doodle')),
|
||||
('mails', models.BooleanField(verbose_name='Recevoir les mails', default=True)),
|
||||
(
|
||||
'user',
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_ernesto",
|
||||
models.BooleanField(
|
||||
verbose_name="Membre de l'Ernestophone", default=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"is_chef",
|
||||
models.BooleanField(verbose_name="Chef Fanfare", default=False),
|
||||
),
|
||||
(
|
||||
"phone",
|
||||
models.CharField(
|
||||
blank=True, max_length=20, verbose_name="Téléphone"
|
||||
),
|
||||
),
|
||||
(
|
||||
"instru",
|
||||
models.CharField(
|
||||
blank=True, max_length=40, verbose_name="Instrument joué"
|
||||
),
|
||||
),
|
||||
("slug", models.CharField(max_length=7, editable=False, unique=True)),
|
||||
(
|
||||
"doodlename",
|
||||
models.CharField(
|
||||
blank=True, max_length=30, verbose_name="Nom pour le doodle"
|
||||
),
|
||||
),
|
||||
(
|
||||
"mails",
|
||||
models.BooleanField(
|
||||
verbose_name="Recevoir les mails", default=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.OneToOneField(
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='profile'
|
||||
)
|
||||
related_name="profile",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Profil Ernestophoniste',
|
||||
'verbose_name_plural': 'Profil Ernestophoniste',
|
||||
"verbose_name": "Profil Ernestophoniste",
|
||||
"verbose_name_plural": "Profil Ernestophoniste",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -7,80 +7,157 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestion', '0001_initial'),
|
||||
("gestion", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='VideoGallery',
|
||||
name="VideoGallery",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=127)),
|
||||
('order', models.IntegerField(verbose_name='ordre')),
|
||||
('url', models.URLField()),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=127)),
|
||||
("order", models.IntegerField(verbose_name="ordre")),
|
||||
("url", models.URLField()),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'Videos',
|
||||
'verbose_name': 'Video',
|
||||
"verbose_name_plural": "Videos",
|
||||
"verbose_name": "Video",
|
||||
},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ernestouser',
|
||||
name='mails',
|
||||
model_name="ernestouser",
|
||||
name="mails",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='instru_autre',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Lequel ?'),
|
||||
model_name="ernestouser",
|
||||
name="instru_autre",
|
||||
field=models.CharField(
|
||||
blank=True, max_length=100, null=True, verbose_name="Lequel ?"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='instru_bonus',
|
||||
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Le·s·quel·s ?'),
|
||||
model_name="ernestouser",
|
||||
name="instru_bonus",
|
||||
field=models.CharField(
|
||||
blank=True, max_length=100, null=True, verbose_name="Le·s·quel·s ?"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='instru_trombonoscope',
|
||||
field=models.CharField(blank=True, max_length=30, verbose_name='Instrument affiché sur le trombonoscope'),
|
||||
model_name="ernestouser",
|
||||
name="instru_trombonoscope",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=30,
|
||||
verbose_name="Instrument affiché sur le trombonoscope",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='multi_instrumentiste',
|
||||
field=models.CharField(choices=[('Non', 'Non'), ('Oui', 'Oui')], default='Non', help_text='Seulement si tu connais les partitions par coeur', max_length=3, verbose_name="Je suis capable de jouer d'un autre instrument en manche :"),
|
||||
model_name="ernestouser",
|
||||
name="multi_instrumentiste",
|
||||
field=models.CharField(
|
||||
choices=[("Non", "Non"), ("Oui", "Oui")],
|
||||
default="Non",
|
||||
help_text="Seulement si tu connais les partitions par coeur",
|
||||
max_length=3,
|
||||
verbose_name="Je suis capable de jouer d'un autre instrument en manche :",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='nom_trombonoscope',
|
||||
field=models.CharField(blank=True, max_length=30, verbose_name='Nom affiché sur le trombonoscope'),
|
||||
model_name="ernestouser",
|
||||
name="nom_trombonoscope",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
max_length=30,
|
||||
verbose_name="Nom affiché sur le trombonoscope",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='trombonoscope',
|
||||
field=models.CharField(choices=[('non', 'Non'), ('o_a', 'Oui en tant que fanfaron actuel'), ('o_v', 'Oui en tant que vie·ille·ux')], default='non', max_length=3, null=True, verbose_name='Je souhaite apparaitre dans le trombonoscope :'),
|
||||
model_name="ernestouser",
|
||||
name="trombonoscope",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("non", "Non"),
|
||||
("o_a", "Oui en tant que fanfaron actuel"),
|
||||
("o_v", "Oui en tant que vie·ille·ux"),
|
||||
],
|
||||
default="non",
|
||||
max_length=3,
|
||||
null=True,
|
||||
verbose_name="Je souhaite apparaitre dans le trombonoscope :",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='trombonoscope_colors',
|
||||
field=models.CharField(choices=[('#e4522f#ffffff', 'Orange et Blanc'), ('#ffffff#000000', 'Blanc et Noir'), ('#A8107C#000000', 'Rose et Noir'), ('#10A4A8#ffffff', 'Bleu et Blanc'), ('#26A810#000000', 'Vert et Noir'), ('#A81026#ffffff', 'Rouge et Blanc'), ('#E3E54C#000000', 'Jaune et Noir'), ('autre', 'Autre')], default='OrangeBlanc', max_length=40, verbose_name='Couleur du profil'),
|
||||
model_name="ernestouser",
|
||||
name="trombonoscope_colors",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("#e4522f#ffffff", "Orange et Blanc"),
|
||||
("#ffffff#000000", "Blanc et Noir"),
|
||||
("#A8107C#000000", "Rose et Noir"),
|
||||
("#10A4A8#ffffff", "Bleu et Blanc"),
|
||||
("#26A810#000000", "Vert et Noir"),
|
||||
("#A81026#ffffff", "Rouge et Blanc"),
|
||||
("#E3E54C#000000", "Jaune et Noir"),
|
||||
("autre", "Autre"),
|
||||
],
|
||||
default="OrangeBlanc",
|
||||
max_length=40,
|
||||
verbose_name="Couleur du profil",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='trombonoscope_fond',
|
||||
field=colorful.fields.RGBColorField(default='#e4522f', verbose_name='Couleur de fond du profil'),
|
||||
model_name="ernestouser",
|
||||
name="trombonoscope_fond",
|
||||
field=colorful.fields.RGBColorField(
|
||||
default="#e4522f", verbose_name="Couleur de fond du profil"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ernestouser',
|
||||
name='trombonoscope_texte',
|
||||
field=colorful.fields.RGBColorField(default='#ffffff', verbose_name='Couleur du texte du profil'),
|
||||
model_name="ernestouser",
|
||||
name="trombonoscope_texte",
|
||||
field=colorful.fields.RGBColorField(
|
||||
default="#ffffff", verbose_name="Couleur du texte du profil"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ernestouser',
|
||||
name='instru',
|
||||
field=models.CharField(choices=[('Clarinette', 'Clarinette'), ('Euphonium', 'Euphonium'), ('Percussion', 'Percussion'), ('Piccolo', 'Piccolo'), ('Saxophone Alto', 'Saxophone Alto'), ('Saxophone Ténor', 'Saxophone Ténor'), ('Saxophone Baryton', 'Saxophone Baryton'), ('Souba', 'Souba'), ('Trombone', 'Trombone'), ('Trompette', 'Trompette'), ('Autre', 'Autre'), ('ne sais pas', 'Je ne sais pas encore')], default='ne sais pas', max_length=40, verbose_name='Instrument joué'),
|
||||
model_name="ernestouser",
|
||||
name="instru",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("Clarinette", "Clarinette"),
|
||||
("Euphonium", "Euphonium"),
|
||||
("Percussion", "Percussion"),
|
||||
("Piccolo", "Piccolo"),
|
||||
("Saxophone Alto", "Saxophone Alto"),
|
||||
("Saxophone Ténor", "Saxophone Ténor"),
|
||||
("Saxophone Baryton", "Saxophone Baryton"),
|
||||
("Souba", "Souba"),
|
||||
("Trombone", "Trombone"),
|
||||
("Trompette", "Trompette"),
|
||||
("Autre", "Autre"),
|
||||
("ne sais pas", "Je ne sais pas encore"),
|
||||
],
|
||||
default="ne sais pas",
|
||||
max_length=40,
|
||||
verbose_name="Instrument joué",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ernestouser',
|
||||
name='phone',
|
||||
field=models.CharField(blank=True, help_text='seulement visible par les chef·fe·s', max_length=20, verbose_name='Téléphone'),
|
||||
model_name="ernestouser",
|
||||
name="phone",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
help_text="seulement visible par les chef·fe·s",
|
||||
max_length=20,
|
||||
verbose_name="Téléphone",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
85
gestion/migrations/0003_photo.py
Normal file
85
gestion/migrations/0003_photo.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
# Generated by Django 2.2.17 on 2021-03-31 13:50
|
||||
|
||||
import colorful.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import gestion.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0002_auto_20200908_2222"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Photo",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=127)),
|
||||
(
|
||||
"cat",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("home_join", "Rejoignez nous"),
|
||||
("home_contact", "Nous Contacter"),
|
||||
("home_rep", "Répertoire de l'acceuil"),
|
||||
("login", "Connexion"),
|
||||
("change_membre", "Modification du profil"),
|
||||
("inscription_membre", "Inscription"),
|
||||
("home", "Calendrier connecté"),
|
||||
("liste", "Agenda public"),
|
||||
("part", "Répertoire"),
|
||||
("n", "N'apparait pas"),
|
||||
],
|
||||
default="n",
|
||||
max_length=127,
|
||||
),
|
||||
),
|
||||
(
|
||||
"auteur",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=127,
|
||||
null=True,
|
||||
verbose_name="Auteur de l'image",
|
||||
),
|
||||
),
|
||||
(
|
||||
"url",
|
||||
models.URLField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Lien vers le site de l'auteur",
|
||||
),
|
||||
),
|
||||
(
|
||||
"color",
|
||||
colorful.fields.RGBColorField(
|
||||
default="#ffffff", verbose_name="Couleur du nom de l'auteur"
|
||||
),
|
||||
),
|
||||
(
|
||||
"image",
|
||||
models.ImageField(
|
||||
default=None,
|
||||
upload_to="deco",
|
||||
validators=[gestion.models.Photo.validate_image],
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Photo",
|
||||
"verbose_name_plural": "Photos",
|
||||
},
|
||||
),
|
||||
]
|
34
gestion/migrations/0004_auto_20210331_2031.py
Normal file
34
gestion/migrations/0004_auto_20210331_2031.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Generated by Django 2.2.17 on 2021-03-31 20:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0003_photo"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="photo",
|
||||
name="cat",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("home_join", "Rejoignez nous"),
|
||||
("home_contact", "Nous Contacter"),
|
||||
("home_rep", "Répertoire de l'acceuil"),
|
||||
("login", "Connexion"),
|
||||
("change_membre", "Modification du profil"),
|
||||
("inscription_membre", "Inscription"),
|
||||
("home", "Calendrier connecté"),
|
||||
("liste", "Agenda public"),
|
||||
("part", "Répertoire"),
|
||||
("instru", "Instruments"),
|
||||
("n", "N'apparait pas"),
|
||||
],
|
||||
default="n",
|
||||
max_length=127,
|
||||
),
|
||||
),
|
||||
]
|
28
gestion/migrations/0005_auto_20210427_1834.py
Normal file
28
gestion/migrations/0005_auto_20210427_1834.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 2.2.17 on 2021-04-27 18:34
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0004_auto_20210331_2031"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="ernestouser",
|
||||
name="trombonoscope",
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
("non", "Non"),
|
||||
("o_a", "Oui en tant que fanfaron actuel"),
|
||||
("o_v", "Oui en tant que vie·ille·ux"),
|
||||
],
|
||||
default="non",
|
||||
max_length=3,
|
||||
null=True,
|
||||
verbose_name="Je souhaite apparaitre dans le trombonoscope:",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,63 +1,147 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.db import models
|
||||
from colorful.fields import RGBColorField
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Photo(models.Model):
|
||||
PHOTO_PLACEMENT = (
|
||||
("home_join", _("Rejoignez nous")),
|
||||
("home_contact", _("Nous Contacter")),
|
||||
("home_rep", _("Répertoire de l'acceuil")),
|
||||
("login", _("Connexion")),
|
||||
("change_membre", _("Modification du profil")),
|
||||
("inscription_membre", _("Inscription")),
|
||||
("home", _("Calendrier connecté")),
|
||||
("liste", _("Agenda public")),
|
||||
("part", _("Répertoire")),
|
||||
("instru", _("Instruments")),
|
||||
("n", _("N'apparait pas")),
|
||||
)
|
||||
|
||||
def validate_image(fieldfile_obj):
|
||||
filesize = fieldfile_obj.file.size
|
||||
mb_limit = 1.0
|
||||
if filesize > mb_limit * 1024 * 1024:
|
||||
raise ValidationError("La taille max est %sMB" % str(mb_limit))
|
||||
|
||||
name = models.CharField(max_length=127)
|
||||
cat = models.CharField(max_length=127, choices=PHOTO_PLACEMENT, default="n")
|
||||
auteur = models.CharField(
|
||||
max_length=127, verbose_name=_("Auteur de l'image"), null=True, blank=True
|
||||
)
|
||||
url = models.URLField(
|
||||
verbose_name=_("Lien vers le site de l'auteur"), null=True, blank=True
|
||||
)
|
||||
color = RGBColorField(_("Couleur du nom de l'auteur"), default="#ffffff")
|
||||
image = models.ImageField(
|
||||
upload_to="deco", default=None, validators=[validate_image]
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Photo")
|
||||
verbose_name_plural = _("Photos")
|
||||
|
||||
|
||||
class ErnestoUser(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
|
||||
is_ernesto = models.BooleanField(_("Membre de l'Ernestophone"), default=True)
|
||||
is_chef = models.BooleanField(_("Chef Fanfare"), default=False)
|
||||
phone = models.CharField(_("Téléphone"), max_length=20, blank=True ,help_text= _("seulement visible par les chef·fe·s"))
|
||||
phone = models.CharField(
|
||||
_("Téléphone"),
|
||||
max_length=20,
|
||||
blank=True,
|
||||
help_text=_("seulement visible par les chef·fe·s"),
|
||||
)
|
||||
|
||||
INSTRU_CHOICES = [
|
||||
('Clarinette', _('Clarinette')),
|
||||
('Euphonium', _('Euphonium')),
|
||||
('Percussion', _('Percussion')),
|
||||
('Piccolo', _('Piccolo')),
|
||||
('Saxophone Alto', _('Saxophone Alto')),
|
||||
('Saxophone Ténor', _('Saxophone Ténor')),
|
||||
('Saxophone Baryton', _('Saxophone Baryton')),
|
||||
('Souba', _('Souba')),
|
||||
('Trombone', _('Trombone')),
|
||||
('Trompette', _('Trompette')),
|
||||
('Autre', _('Autre')),
|
||||
('ne sais pas', _('Je ne sais pas encore')),
|
||||
("Clarinette", _("Clarinette")),
|
||||
("Euphonium", _("Euphonium")),
|
||||
("Percussion", _("Percussion")),
|
||||
("Piccolo", _("Piccolo")),
|
||||
("Saxophone Alto", _("Saxophone Alto")),
|
||||
("Saxophone Ténor", _("Saxophone Ténor")),
|
||||
("Saxophone Baryton", _("Saxophone Baryton")),
|
||||
("Souba", _("Souba")),
|
||||
("Trombone", _("Trombone")),
|
||||
("Trompette", _("Trompette")),
|
||||
("Autre", _("Autre")),
|
||||
("ne sais pas", _("Je ne sais pas encore")),
|
||||
]
|
||||
|
||||
COLORS_CHOICES = [
|
||||
('#e4522f#ffffff', _('Orange et Blanc')),
|
||||
('#ffffff#000000', _('Blanc et Noir')),
|
||||
('#A8107C#000000', _('Rose et Noir')),
|
||||
('#10A4A8#ffffff', _('Bleu et Blanc')),
|
||||
('#26A810#000000', _('Vert et Noir')),
|
||||
('#A81026#ffffff', _('Rouge et Blanc')),
|
||||
('#E3E54C#000000', _('Jaune et Noir')),
|
||||
('autre',_('Autre')),
|
||||
("#e4522f#ffffff", _("Orange et Blanc")),
|
||||
("#ffffff#000000", _("Blanc et Noir")),
|
||||
("#A8107C#000000", _("Rose et Noir")),
|
||||
("#10A4A8#ffffff", _("Bleu et Blanc")),
|
||||
("#26A810#000000", _("Vert et Noir")),
|
||||
("#A81026#ffffff", _("Rouge et Blanc")),
|
||||
("#E3E54C#000000", _("Jaune et Noir")),
|
||||
("autre", _("Autre")),
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
instru = models.CharField(_("Instrument joué"), max_length=40, blank=False,choices=INSTRU_CHOICES,default='ne sais pas')
|
||||
instru_autre = models.CharField(_("Lequel ?"),null=True,max_length=100,blank=True)
|
||||
instru = models.CharField(
|
||||
_("Instrument joué"),
|
||||
max_length=40,
|
||||
blank=False,
|
||||
choices=INSTRU_CHOICES,
|
||||
default="ne sais pas",
|
||||
)
|
||||
instru_autre = models.CharField(
|
||||
_("Lequel ?"), null=True, max_length=100, blank=True
|
||||
)
|
||||
slug = models.CharField(max_length=7, editable=False, unique=True)
|
||||
doodlename = models.CharField(_("Nom pour le doodle"), max_length=30,
|
||||
blank=True)
|
||||
|
||||
trombonoscope = models.CharField(_('Je souhaite apparaitre dans le trombonoscope :'),max_length=3,blank=False,null=True,choices=[('non',_('Non')),('o_a',_('Oui en tant que fanfaron actuel')),('o_v',_('Oui en tant que vie·ille·ux'))],default='non')
|
||||
instru_trombonoscope = models.CharField(_("Instrument affiché sur le trombonoscope"), max_length=30,
|
||||
blank=True)
|
||||
nom_trombonoscope = models.CharField(_("Nom affiché sur le trombonoscope"), max_length=30,
|
||||
blank=True)
|
||||
trombonoscope_colors = models.CharField(_("Couleur du profil"), max_length=40, blank=False,choices=COLORS_CHOICES,default='OrangeBlanc')
|
||||
trombonoscope_fond = RGBColorField(_("Couleur de fond du profil"),default='#e4522f')
|
||||
trombonoscope_texte = RGBColorField(_("Couleur du texte du profil"),default='#ffffff')
|
||||
|
||||
multi_instrumentiste = models.CharField(_("Je suis capable de jouer d'un autre instrument en manche :"),default='Non',null=False,max_length=3,choices=[('Non',_('Non')),('Oui',_('Oui'))],help_text= _("Seulement si tu connais les partitions par coeur"))
|
||||
instru_bonus = models.CharField(_("Le·s·quel·s ?"),null=True,max_length=100,blank=True)
|
||||
doodlename = models.CharField(_("Nom pour le doodle"), max_length=30, blank=True)
|
||||
|
||||
trombonoscope = models.CharField(
|
||||
_("Je souhaite apparaitre dans le trombonoscope:"),
|
||||
max_length=3,
|
||||
blank=False,
|
||||
null=True,
|
||||
choices=[
|
||||
("non", _("Non")),
|
||||
("o_a", _("Oui en tant que fanfaron actuel")),
|
||||
("o_v", _("Oui en tant que vie·ille·ux")),
|
||||
],
|
||||
default="non",
|
||||
)
|
||||
instru_trombonoscope = models.CharField(
|
||||
_("Instrument affiché sur le trombonoscope"), max_length=30, blank=True
|
||||
)
|
||||
nom_trombonoscope = models.CharField(
|
||||
_("Nom affiché sur le trombonoscope"), max_length=30, blank=True
|
||||
)
|
||||
trombonoscope_colors = models.CharField(
|
||||
_("Couleur du profil"),
|
||||
max_length=40,
|
||||
blank=False,
|
||||
choices=COLORS_CHOICES,
|
||||
default="OrangeBlanc",
|
||||
)
|
||||
trombonoscope_fond = RGBColorField(
|
||||
_("Couleur de fond du profil"), default="#e4522f"
|
||||
)
|
||||
trombonoscope_texte = RGBColorField(
|
||||
_("Couleur du texte du profil"), default="#ffffff"
|
||||
)
|
||||
|
||||
multi_instrumentiste = models.CharField(
|
||||
_("Je suis capable de jouer d'un autre instrument en manche :"),
|
||||
default="Non",
|
||||
null=False,
|
||||
max_length=3,
|
||||
choices=[("Non", _("Non")), ("Oui", _("Oui"))],
|
||||
help_text=_("Seulement si tu connais les partitions par coeur"),
|
||||
)
|
||||
instru_bonus = models.CharField(
|
||||
_("Le·s·quel·s ?"), null=True, max_length=100, blank=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Profil Ernestophoniste")
|
||||
|
|
36
gestion/static/css/bootstrap.css
vendored
36
gestion/static/css/bootstrap.css
vendored
|
@ -545,7 +545,7 @@ pre code {
|
|||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.container {
|
||||
.container_carousel {
|
||||
width: 100%;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
|
@ -554,25 +554,25 @@ pre code {
|
|||
}
|
||||
|
||||
@media (min-width: 576px) {
|
||||
.container {
|
||||
.container_carousel {
|
||||
max-width: 540px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
.container_carousel {
|
||||
max-width: 720px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.container {
|
||||
.container_carousel {
|
||||
max-width: 960px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.container {
|
||||
.container_carousel {
|
||||
max-width: 1140px;
|
||||
}
|
||||
}
|
||||
|
@ -4157,7 +4157,7 @@ input[type="button"].btn-block {
|
|||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.navbar > .container,
|
||||
.navbar > .container_carousel,
|
||||
.navbar > .container-fluid {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
|
@ -4242,7 +4242,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
.navbar-expand-sm > .container,
|
||||
.navbar-expand-sm > .container_carousel,
|
||||
.navbar-expand-sm > .container-fluid {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
@ -4267,7 +4267,7 @@ input[type="button"].btn-block {
|
|||
padding-right: 0.5rem;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.navbar-expand-sm > .container,
|
||||
.navbar-expand-sm > .container_carousel,
|
||||
.navbar-expand-sm > .container-fluid {
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
|
@ -4284,7 +4284,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.navbar-expand-md > .container,
|
||||
.navbar-expand-md > .container_carousel,
|
||||
.navbar-expand-md > .container-fluid {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
@ -4309,7 +4309,7 @@ input[type="button"].btn-block {
|
|||
padding-right: 0.5rem;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.navbar-expand-md > .container,
|
||||
.navbar-expand-md > .container_carousel,
|
||||
.navbar-expand-md > .container-fluid {
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
|
@ -4326,7 +4326,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
@media (max-width: 991.98px) {
|
||||
.navbar-expand-lg > .container,
|
||||
.navbar-expand-lg > .container_carousel,
|
||||
.navbar-expand-lg > .container-fluid {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
@ -4351,7 +4351,7 @@ input[type="button"].btn-block {
|
|||
padding-right: 0.5rem;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.navbar-expand-lg > .container,
|
||||
.navbar-expand-lg > .container_carousel,
|
||||
.navbar-expand-lg > .container-fluid {
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
|
@ -4368,7 +4368,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
@media (max-width: 1199.98px) {
|
||||
.navbar-expand-xl > .container,
|
||||
.navbar-expand-xl > .container_carousel,
|
||||
.navbar-expand-xl > .container-fluid {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
@ -4393,7 +4393,7 @@ input[type="button"].btn-block {
|
|||
padding-right: 0.5rem;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
.navbar-expand-xl > .container,
|
||||
.navbar-expand-xl > .container_carousel,
|
||||
.navbar-expand-xl > .container-fluid {
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
|
@ -4416,7 +4416,7 @@ input[type="button"].btn-block {
|
|||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.navbar-expand > .container,
|
||||
.navbar-expand > .container_carousel,
|
||||
.navbar-expand > .container-fluid {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
@ -4436,7 +4436,7 @@ input[type="button"].btn-block {
|
|||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.navbar-expand > .container,
|
||||
.navbar-expand > .container_carousel,
|
||||
.navbar-expand > .container-fluid {
|
||||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
|
@ -10001,7 +10001,7 @@ a.text-dark:hover, a.text-dark:focus {
|
|||
body {
|
||||
min-width: 992px !important;
|
||||
}
|
||||
.container {
|
||||
.container_carousel {
|
||||
min-width: 992px !important;
|
||||
}
|
||||
.navbar {
|
||||
|
@ -10035,4 +10035,4 @@ a.text-dark:hover, a.text-dark:focus {
|
|||
border-color: #dee2e6;
|
||||
}
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap.css.map */
|
||||
/*# sourceMappingURL=bootstrap.css.map */
|
||||
|
|
2
gestion/static/css/bootstrap.min.css
vendored
2
gestion/static/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
|
@ -9,8 +9,37 @@
|
|||
Released for free under the Creative Commons Attribution 3.0 license (templated.co/license)
|
||||
*/
|
||||
|
||||
/* Instagram feed*/
|
||||
|
||||
|
||||
|
||||
|
||||
#app{
|
||||
display: grid;
|
||||
grid-gap: var(--spacing);
|
||||
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||
min-height: calc(100vh - var(--spacing)*2);
|
||||
}
|
||||
|
||||
a.error{
|
||||
grid-column: 1 / -1;
|
||||
justify-self: center;
|
||||
}
|
||||
a.loading{
|
||||
width: calc(var(--spacing)*3);
|
||||
height: calc(var(--spacing)*3);
|
||||
grid-column: 1 / -1;
|
||||
justify-self: center;
|
||||
align-self: center;
|
||||
background: var(--color);
|
||||
animation: load var(--speed) infinite ease-in-out;
|
||||
transform: rotate(0);
|
||||
}
|
||||
@keyframes load{
|
||||
100%{
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* Reset */
|
||||
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
|
||||
|
@ -219,6 +248,7 @@
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* Grid */
|
||||
|
||||
.row {
|
||||
|
@ -1558,9 +1588,7 @@
|
|||
width: device-width;
|
||||
}
|
||||
|
||||
body {
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
|
||||
|
@ -1574,16 +1602,7 @@
|
|||
background: #e4522f;
|
||||
}
|
||||
|
||||
body.is-loading *, body.is-loading *:before, body.is-loading *:after {
|
||||
-moz-animation: none !important;
|
||||
-webkit-animation: none !important;
|
||||
-ms-animation: none !important;
|
||||
animation: none !important;
|
||||
-moz-transition: none !important;
|
||||
-webkit-transition: none !important;
|
||||
-ms-transition: none !important;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
|
||||
/* Type */
|
||||
|
||||
|
@ -2284,7 +2303,7 @@ div.spoiler
|
|||
display: block;
|
||||
float: left;
|
||||
margin-right: -2em;
|
||||
opacity: 0;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
@ -2704,31 +2723,7 @@ div.spoiler
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
header p {
|
||||
position: relative;
|
||||
margin: 0 0 1.5em 0;
|
||||
}
|
||||
|
||||
header h2 + p {
|
||||
font-size: 1.25em;
|
||||
margin-top: -1em;
|
||||
}
|
||||
|
||||
header h3 + p {
|
||||
font-size: 1.1em;
|
||||
margin-top: -0.8em;
|
||||
}
|
||||
|
||||
header h4 + p,
|
||||
header h5 + p,
|
||||
header h6 + p {
|
||||
font-size: 0.9em;
|
||||
margin-top: -0.6em;
|
||||
}
|
||||
|
||||
header p {
|
||||
color: #676d71;
|
||||
}
|
||||
|
||||
/* Tab */
|
||||
|
||||
|
@ -2888,17 +2883,8 @@ div.spoiler
|
|||
z-index: 99;
|
||||
}
|
||||
|
||||
.wrapper header {
|
||||
margin-bottom: 4em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 736px) {
|
||||
|
||||
.wrapper header {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.wrapper.style1 {
|
||||
background-color: #e39576;
|
||||
|
@ -3104,9 +3090,7 @@ div.spoiler
|
|||
border-top-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.wrapper.style1 header p {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
|
||||
.wrapper.style1 table tbody tr {
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
|
@ -3327,9 +3311,7 @@ div.spoiler
|
|||
border-top-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.wrapper.style2 header p {
|
||||
color: #9ba2a8;
|
||||
}
|
||||
|
||||
|
||||
.wrapper.style2 table tbody tr {
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
|
@ -3463,281 +3445,7 @@ div.spoiler
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
|
||||
body.subpage {
|
||||
padding-top: 3.125em;
|
||||
}
|
||||
|
||||
#header {
|
||||
background: #e4522f;
|
||||
color: #e4522f;
|
||||
cursor: default;
|
||||
height: 3.25em;
|
||||
left: 0;
|
||||
line-height: 3.25em;
|
||||
position: fixed;
|
||||
text-align: right;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
#header > h1 {
|
||||
color:#000000;
|
||||
display: inline-block;
|
||||
height: inherit;
|
||||
left: 1.25em;
|
||||
line-height: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
#header > h1 a {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
#header > h1 a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
#header > h1 span {
|
||||
font-weight: 300;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#header > a {
|
||||
|
||||
-moz-transition: color 0.2s ease-in-out;
|
||||
-webkit-transition: color 0.2s ease-in-out;
|
||||
-ms-transition: color 0.2s ease-in-out;
|
||||
transition: color 0.2s ease-in-out;
|
||||
display: inline-block;
|
||||
padding: 0 0.75em;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#header > a:hover {
|
||||
color: #e4522f;
|
||||
}
|
||||
|
||||
#header > a[href="#menu"]:hover {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#header > a[href="#menu"] {
|
||||
text-decoration: none;
|
||||
font-size: larger;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
#header > a[href="#menu"]:before {
|
||||
content: "";
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: FontAwesome;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
text-transform: none !important;
|
||||
}
|
||||
|
||||
#header > a[href="#menu"]:before {
|
||||
margin: 0 0.5em 0 0;
|
||||
}
|
||||
|
||||
#header > a + a[href="#menu"]:last-child {
|
||||
border-left: solid 1px rgba(228, 82, 47, 0.15);
|
||||
padding-left: 1.25em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
#header > a:last-child {
|
||||
padding-right: 1.25em;
|
||||
}
|
||||
|
||||
#logo
|
||||
{
|
||||
position: absolute;
|
||||
left:0;
|
||||
top:0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 736px) {
|
||||
|
||||
#header > a {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
|
||||
#header > a + a[href="#menu"]:last-child {
|
||||
padding-left: 1em;
|
||||
margin-left: 0.25em;
|
||||
}
|
||||
|
||||
#header > a:last-child {
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 980px) {
|
||||
|
||||
body {
|
||||
padding-top: 44px;
|
||||
}
|
||||
|
||||
#header {
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
}
|
||||
|
||||
#header > h1 {
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
#header > h1 a {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
|
||||
#header {
|
||||
min-width: 320px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Menu */
|
||||
|
||||
#menu {
|
||||
-moz-transform: translateX(20em);
|
||||
-webkit-transform: translateX(20em);
|
||||
-ms-transform: translateX(20em);
|
||||
transform: translateX(20em);
|
||||
-moz-transition: -moz-transform 0.5s ease, box-shadow 0.5s ease, visibility 0.5s;
|
||||
-webkit-transition: -webkit-transform 0.5s ease, box-shadow 0.5s ease, visibility 0.5s;
|
||||
-ms-transition: -ms-transform 0.5s ease, box-shadow 0.5s ease, visibility 0.5s;
|
||||
transition: transform 0.5s ease, box-shadow 0.5s ease, visibility 0.5s;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
background: #e4522f;
|
||||
box-shadow: none;
|
||||
color: #ffffff;
|
||||
height: 100%;
|
||||
max-width: 80%;
|
||||
overflow-y: auto;
|
||||
padding: 3em 2em;
|
||||
position: fixed;
|
||||
font-size: larger;
|
||||
right: 0;
|
||||
top: 0;
|
||||
visibility: hidden;
|
||||
width: 20em;
|
||||
z-index: 10002;
|
||||
}
|
||||
|
||||
#menu > ul {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
#menu > ul.links {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#menu > ul.links > li {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#menu > ul.links > li > a:not(.button) {
|
||||
border: 0;
|
||||
border-top: solid 1px rgba(255, 255, 255, 0.15);
|
||||
color: inherit;
|
||||
display: block;
|
||||
line-height: 3.5em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#menu > ul.links > li > .button {
|
||||
display: block;
|
||||
margin: 0.5em 0 0 0;
|
||||
}
|
||||
#menu > ul.links > li > a:not(.button):hover {
|
||||
color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
#menu > ul.links > li:first-child > a:not(.button) {
|
||||
border-top: 0 !important;
|
||||
}
|
||||
|
||||
#menu .close {
|
||||
text-decoration: none;
|
||||
-moz-transition: color 0.2s ease-in-out;
|
||||
-webkit-transition: color 0.2s ease-in-out;
|
||||
-ms-transition: color 0.2s ease-in-out;
|
||||
transition: color 0.2s ease-in-out;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
border: 0;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 2.75em;
|
||||
line-height: 3.25em;
|
||||
padding-right: 1.25em;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
top: 0;
|
||||
vertical-align: middle;
|
||||
width: 2.75em;
|
||||
}
|
||||
|
||||
#menu .close:before {
|
||||
content: "";
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-family: FontAwesome;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
text-transform: none !important;
|
||||
}
|
||||
|
||||
#menu .close:before {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
#menu .close:hover {
|
||||
color: rgba(255,255,255,0.2);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 736px) {
|
||||
|
||||
#menu .close {
|
||||
height: 4em;
|
||||
line-height: 4em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#menu.visible {
|
||||
-moz-transform: translateX(0);
|
||||
-webkit-transform: translateX(0);
|
||||
-ms-transform: translateX(0);
|
||||
transform: translateX(0);
|
||||
box-shadow: 0 0 1.5em 0 rgba(0, 0, 0, 0.2);
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 736px) {
|
||||
|
||||
#menu {
|
||||
padding: 2.5em 1.75em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Banner */
|
||||
|
||||
|
@ -3884,6 +3592,9 @@ div.spoiler
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Main */
|
||||
|
||||
/* Footer */
|
||||
|
@ -3950,3 +3661,16 @@ div.spoiler
|
|||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
#rudr_instafeed{
|
||||
list-style:none
|
||||
}
|
||||
#rudr_instafeed li{
|
||||
float:left;
|
||||
width:200px;
|
||||
height:200px;
|
||||
margin:10px
|
||||
}
|
||||
#rudr_instafeed li img{
|
||||
max-width:100%;
|
||||
max-height:100%;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/***** Top content *****/
|
||||
|
||||
.top-content { width: 100%; padding: 60px 0 120px 0; }
|
||||
|
||||
.top-content .carousel { box-shadow: 0 0 15px 0 #444; }
|
||||
.top-content .carousel { box-shadow: 0 0 15px 0 #444; }
|
||||
.top-content .carousel-control-prev { left: -110px; border-bottom: 0; }
|
||||
.top-content .carousel-control-next { right: -110px; border-bottom: 0; }
|
||||
.top-content .carousel-indicators { bottom: -80px; }
|
||||
.top-content .carousel-indicators li { width: 16px; height: 16px; margin-left: 5px; margin-right: 5px; border-radius: 50%; }
|
||||
.top-content .carousel-indicators { bottom: -80px; }
|
||||
.top-content .carousel-indicators li { width: 16px; height: 16px; margin-left: 5px; margin-right: 5px; border-radius: 50%; }
|
||||
|
|
278
gestion/static/js/InstagramFeed.js
Normal file
278
gestion/static/js/InstagramFeed.js
Normal file
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* InstagramFeed
|
||||
*
|
||||
* @version 1.4.0
|
||||
*
|
||||
* @author jsanahuja <bannss1@gmail.com>
|
||||
* @contributor csanahuja <csanahuja10@gmail.com>
|
||||
*
|
||||
* https://github.com/jsanahuja/InstagramFeed
|
||||
*
|
||||
*/
|
||||
(function(root, factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof exports === "object") {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.InstagramFeed = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
var defaults = {
|
||||
'host': "https://www.instagram.com/",
|
||||
'username': '',
|
||||
'tag': '',
|
||||
'container': '',
|
||||
'display_profile': true,
|
||||
'display_biography': true,
|
||||
'display_gallery': true,
|
||||
'display_captions': false,
|
||||
'display_igtv': false,
|
||||
'callback': null,
|
||||
'styling': true,
|
||||
'items': 8,
|
||||
'items_per_row': 4,
|
||||
'margin': 0.5,
|
||||
'image_size': 640,
|
||||
'lazy_load': false,
|
||||
'on_error': console.error
|
||||
};
|
||||
|
||||
var image_sizes = {
|
||||
"150": 0,
|
||||
"240": 1,
|
||||
"320": 2,
|
||||
"480": 3,
|
||||
"640": 4
|
||||
};
|
||||
|
||||
var escape_map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
"'": ''',
|
||||
'/': '/',
|
||||
'`': '`',
|
||||
'=': '='
|
||||
};
|
||||
function escape_string(str){
|
||||
return str.replace(/[&<>"'`=\/]/g, function (char) {
|
||||
return escape_map[char];
|
||||
});
|
||||
}
|
||||
|
||||
return function(opts) {
|
||||
this.options = Object.assign({}, defaults);
|
||||
this.options = Object.assign(this.options, opts);
|
||||
this.is_tag = this.options.username == "";
|
||||
|
||||
this.valid = true;
|
||||
if (this.options.username == "" && this.options.tag == "") {
|
||||
this.options.on_error("InstagramFeed: Error, no username or tag defined.", 1);
|
||||
this.valid = false;
|
||||
}
|
||||
if (typeof this.options.get_data !== "undefined") {
|
||||
console.warn("InstagramFeed: options.get_data is deprecated, options.callback is always called if defined");
|
||||
}
|
||||
if (this.options.callback == null && this.options.container == "") {
|
||||
this.options.on_error("InstagramFeed: Error, neither container found nor callback defined.", 2);
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
this.get = function(callback) {
|
||||
var url = this.is_tag ? this.options.host + "explore/tags/" + this.options.tag + "/" : this.options.host + this.options.username + "/",
|
||||
xhr = new XMLHttpRequest();
|
||||
|
||||
var _this = this;
|
||||
xhr.onload = function(e) {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
try{
|
||||
var data = xhr.responseText.split("window._sharedData = ")[1].split("<\/script>")[0];
|
||||
}catch(error){
|
||||
_this.options.on_error("InstagramFeed: It looks like the profile you are trying to fetch is age restricted. See https://github.com/jsanahuja/InstagramFeed/issues/26", 3);
|
||||
return;
|
||||
}
|
||||
data = JSON.parse(data.substr(0, data.length - 1));
|
||||
data = data.entry_data.ProfilePage || data.entry_data.TagPage;
|
||||
if(typeof data === "undefined"){
|
||||
_this.options.on_error("InstagramFeed: It looks like YOUR network has been temporary banned because of too many requests. See https://github.com/jsanahuja/jquery.instagramFeed/issues/25", 4);
|
||||
return;
|
||||
}
|
||||
data = data[0].graphql.user || data[0].graphql.hashtag;
|
||||
callback(data, _this);
|
||||
} else {
|
||||
_this.options.on_error("InstagramFeed: Unable to fetch the given user/tag. Instagram responded with the status code: " + xhr.statusText, 5);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.open("GET", url, true);
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
this.parse_caption = function(igobj, data) {
|
||||
if (
|
||||
typeof igobj.node.edge_media_to_caption.edges[0] !== "undefined" &&
|
||||
typeof igobj.node.edge_media_to_caption.edges[0].node !== "undefined" &&
|
||||
typeof igobj.node.edge_media_to_caption.edges[0].node.text !== "undefined" &&
|
||||
igobj.node.edge_media_to_caption.edges[0].node.text !== null
|
||||
) {
|
||||
return igobj.node.edge_media_to_caption.edges[0].node.text;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof igobj.node.title !== "undefined" &&
|
||||
igobj.node.title !== null &&
|
||||
igobj.node.title.length != 0
|
||||
) {
|
||||
return igobj.node.title;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof igobj.node.accessibility_caption !== "undefined" &&
|
||||
igobj.node.accessibility_caption !== null &&
|
||||
igobj.node.accessibility_caption.length != 0
|
||||
) {
|
||||
return igobj.node.accessibility_caption;
|
||||
}
|
||||
return (this.is_tag ? data.name : data.username) + " image ";
|
||||
}
|
||||
|
||||
this.display = function(data) {
|
||||
// Styling
|
||||
var html = "",
|
||||
styles;
|
||||
if (this.options.styling) {
|
||||
var width = (100 - this.options.margin * 2 * this.options.items_per_row) / this.options.items_per_row;
|
||||
styles = {
|
||||
'profile_container': " style='text-align:center;'",
|
||||
'profile_image': " style='border-radius:10em;width:15%;max-width:125px;min-width:50px;'",
|
||||
'profile_name': " style='font-size:1.2em;'",
|
||||
'profile_biography': " style='font-size:1em;'",
|
||||
'gallery_image': " style='width:100%;'",
|
||||
'gallery_image_link': " style='width:" + width + "%; margin:" + this.options.margin + "%; position:relative; display: inline-block; height: 100%;'"
|
||||
};
|
||||
// Caption Styling
|
||||
if(this.options.display_captions){
|
||||
html += "<style>\
|
||||
a[data-caption]:hover::after {\
|
||||
content: attr(data-caption);\
|
||||
text-align: center;\
|
||||
font-size: 0.8rem;\
|
||||
color: black;\
|
||||
position: absolute;\
|
||||
left: 0;\
|
||||
right: 0;\
|
||||
bottom: 0;\
|
||||
padding: 1%;\
|
||||
max-height: 100%;\
|
||||
overflow-y: auto;\
|
||||
overflow-x: hidden;\
|
||||
background-color: hsla(0, 100%, 100%, 0.8);\
|
||||
}\
|
||||
</style>";
|
||||
}
|
||||
} else {
|
||||
styles = {
|
||||
'profile_container': "",
|
||||
'profile_image': "",
|
||||
'profile_name': "",
|
||||
'profile_biography': "",
|
||||
'gallery_image': "",
|
||||
'gallery_image_link': ""
|
||||
};
|
||||
}
|
||||
|
||||
// Profile
|
||||
if (this.options.display_profile) {
|
||||
html += "<div class='instagram_profile'" + styles.profile_container + ">";
|
||||
html += "<img class='instagram_profile_image'" + (this.options.lazy_load ? " loading='lazy'" : '') + " src='" + data.profile_pic_url + "' alt='" + (this.is_tag ? data.name + " tag pic" : data.username + " profile pic") + " profile pic'" + styles.profile_image + " />";
|
||||
if (this.is_tag)
|
||||
html += "<p class='instagram_tag'" + styles.profile_name + "><a href='https://www.instagram.com/explore/tags/" + this.options.tag + "' rel='noopener' target='_blank'>#" + this.options.tag + "</a></p>";
|
||||
else
|
||||
html += "<p class='instagram_username'" + styles.profile_name + ">@" + data.full_name + " (<a href='https://www.instagram.com/" + this.options.username + "' rel='noopener' target='_blank'>@" + this.options.username + "</a>)</p>";
|
||||
|
||||
if (!this.is_tag && this.options.display_biography)
|
||||
html += "<p class='instagram_biography'" + styles.profile_biography + ">" + data.biography + "</p>";
|
||||
|
||||
html += "</div>";
|
||||
}
|
||||
|
||||
// Gallery
|
||||
if (this.options.display_gallery) {
|
||||
var image_index = typeof image_sizes[this.options.image_size] !== "undefined" ? image_sizes[this.options.image_size] : image_sizes[640];
|
||||
|
||||
if (typeof data.is_private !== "undefined" && data.is_private === true) {
|
||||
html += "<p class='instagram_private'><strong>This profile is private</strong></p>";
|
||||
} else {
|
||||
var imgs = (data.edge_owner_to_timeline_media || data.edge_hashtag_to_media).edges;
|
||||
max = (imgs.length > this.options.items) ? this.options.items : imgs.length;
|
||||
|
||||
html += "<div class='instagram_gallery'>";
|
||||
for (var i = 0; i < max; i++) {
|
||||
var url = "https://www.instagram.com/p/" + imgs[i].node.shortcode,
|
||||
image, type_resource,
|
||||
caption = escape_string(this.parse_caption(imgs[i], data));
|
||||
|
||||
switch (imgs[i].node.__typename) {
|
||||
case "GraphSidecar":
|
||||
type_resource = "sidecar"
|
||||
image = imgs[i].node.thumbnail_resources[image_index].src;
|
||||
break;
|
||||
case "GraphVideo":
|
||||
type_resource = "video";
|
||||
image = imgs[i].node.thumbnail_src
|
||||
break;
|
||||
default:
|
||||
type_resource = "image";
|
||||
image = imgs[i].node.thumbnail_resources[image_index].src;
|
||||
}
|
||||
|
||||
if (this.is_tag) data.username = '';
|
||||
html += "<a href='" + url + (this.options.display_captions? "' data-caption='" + caption : "") + "' class='instagram-" + type_resource + "' rel='noopener' target='_blank'" + styles.gallery_image_link + ">";
|
||||
html += "<img" + (this.options.lazy_load ? " loading='lazy'" : '') + " src='" + image + "' alt='" + caption + "'" + styles.gallery_image + " />";
|
||||
html += "</a>";
|
||||
}
|
||||
|
||||
html += "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
// IGTV
|
||||
if (this.options.display_igtv && typeof data.edge_felix_video_timeline !== "undefined") {
|
||||
var igtv = data.edge_felix_video_timeline.edges,
|
||||
max = (igtv.length > this.options.items) ? this.options.items : igtv.length
|
||||
if (igtv.length > 0) {
|
||||
html += "<div class='instagram_igtv'>";
|
||||
for (var i = 0; i < max; i++) {
|
||||
var url = "https://www.instagram.com/p/" + igtv[i].node.shortcode,
|
||||
caption = escape_string(this.parse_caption(igtv[i], data));
|
||||
|
||||
html += "<a href='" + url + (this.options.display_captions? "' data-caption='" + caption : "") + "' rel='noopener' target='_blank'" + styles.gallery_image_link + ">";
|
||||
html += "<img" + (this.options.lazy_load ? " loading='lazy'" : '') + " src='" + igtv[i].node.thumbnail_src + "' alt='" + caption + "'" + styles.gallery_image + " />";
|
||||
html += "</a>";
|
||||
}
|
||||
html += "</div>";
|
||||
}
|
||||
}
|
||||
|
||||
this.options.container.innerHTML = html;
|
||||
};
|
||||
|
||||
this.run = function() {
|
||||
this.get(function(data, instance) {
|
||||
if(instance.options.container != ""){
|
||||
instance.display(data);
|
||||
}
|
||||
if(typeof instance.options.callback === "function"){
|
||||
instance.options.callback(data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (this.valid) {
|
||||
this.run();
|
||||
}
|
||||
};
|
||||
}));
|
1
gestion/static/js/InstagramFeed.min.js
vendored
Normal file
1
gestion/static/js/InstagramFeed.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
22
gestion/static/js/bootstrap.js
vendored
22
gestion/static/js/bootstrap.js
vendored
|
@ -1265,7 +1265,7 @@ if (typeof jQuery === 'undefined') {
|
|||
title: '',
|
||||
delay: 0,
|
||||
html: false,
|
||||
container: false,
|
||||
container_carousel: false,
|
||||
viewport: {
|
||||
selector: 'body',
|
||||
padding: 0
|
||||
|
@ -1407,7 +1407,7 @@ if (typeof jQuery === 'undefined') {
|
|||
.addClass(placement)
|
||||
.data('bs.' + this.type, this)
|
||||
|
||||
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
||||
this.options.container_carousel ? $tip.appendTo(this.options.container_carousel) : $tip.insertAfter(this.$element)
|
||||
|
||||
var pos = this.getPosition()
|
||||
var actualWidth = $tip[0].offsetWidth
|
||||
|
@ -1415,13 +1415,13 @@ if (typeof jQuery === 'undefined') {
|
|||
|
||||
if (autoPlace) {
|
||||
var orgPlacement = placement
|
||||
var $container = this.options.container ? $(this.options.container) : this.$element.parent()
|
||||
var containerDim = this.getPosition($container)
|
||||
var $container_carousel = this.options.container_carousel ? $(this.options.container_carousel) : this.$element.parent()
|
||||
var container_carouselDim = this.getPosition($container_carousel)
|
||||
|
||||
placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
|
||||
placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
|
||||
placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
|
||||
placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
|
||||
placement = placement == 'bottom' && pos.bottom + actualHeight > container_carouselDim.bottom ? 'top' :
|
||||
placement == 'top' && pos.top - actualHeight < container_carouselDim.top ? 'bottom' :
|
||||
placement == 'right' && pos.right + actualWidth > container_carouselDim.width ? 'left' :
|
||||
placement == 'left' && pos.left - actualWidth < container_carouselDim.left ? 'right' :
|
||||
placement
|
||||
|
||||
$tip
|
||||
|
@ -2051,11 +2051,11 @@ if (typeof jQuery === 'undefined') {
|
|||
})
|
||||
}
|
||||
|
||||
Tab.prototype.activate = function (element, container, callback) {
|
||||
var $active = container.find('> .active')
|
||||
Tab.prototype.activate = function (element, container_carousel, callback) {
|
||||
var $active = container_carousel.find('> .active')
|
||||
var transition = callback
|
||||
&& $.support.transition
|
||||
&& (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
|
||||
&& (($active.length && $active.hasClass('fade')) || !!container_carousel.find('> .fade').length)
|
||||
|
||||
function next() {
|
||||
$active
|
||||
|
|
4
gestion/static/js/bootstrap.min.js
vendored
4
gestion/static/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
22
gestion/static/js/bootstrap_carousel.js
vendored
22
gestion/static/js/bootstrap_carousel.js
vendored
|
@ -2755,7 +2755,7 @@
|
|||
selector: '(string|boolean)',
|
||||
placement: '(string|function)',
|
||||
offset: '(number|string|function)',
|
||||
container: '(string|element|boolean)',
|
||||
container_carousel: '(string|element|boolean)',
|
||||
fallbackPlacement: '(string|array)',
|
||||
boundary: '(string|element)',
|
||||
sanitize: 'boolean',
|
||||
|
@ -2779,7 +2779,7 @@
|
|||
selector: false,
|
||||
placement: 'top',
|
||||
offset: 0,
|
||||
container: false,
|
||||
container_carousel: false,
|
||||
fallbackPlacement: 'flip',
|
||||
boundary: 'scrollParent',
|
||||
sanitize: true,
|
||||
|
@ -2957,12 +2957,12 @@
|
|||
|
||||
this.addAttachmentClass(attachment);
|
||||
|
||||
var container = this._getContainer();
|
||||
var container_carousel = this._getcontainer_carousel();
|
||||
|
||||
$(tip).data(this.constructor.DATA_KEY, this);
|
||||
|
||||
if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
|
||||
$(tip).appendTo(container);
|
||||
$(tip).appendTo(container_carousel);
|
||||
}
|
||||
|
||||
$(this.element).trigger(this.constructor.Event.INSERTED);
|
||||
|
@ -3153,16 +3153,16 @@
|
|||
return offset;
|
||||
};
|
||||
|
||||
_proto._getContainer = function _getContainer() {
|
||||
if (this.config.container === false) {
|
||||
_proto._getcontainer_carousel = function _getcontainer_carousel() {
|
||||
if (this.config.container_carousel === false) {
|
||||
return document.body;
|
||||
}
|
||||
|
||||
if (Util.isElement(this.config.container)) {
|
||||
return $(this.config.container);
|
||||
if (Util.isElement(this.config.container_carousel)) {
|
||||
return $(this.config.container_carousel);
|
||||
}
|
||||
|
||||
return $(document).find(this.config.container);
|
||||
return $(document).find(this.config.container_carousel);
|
||||
};
|
||||
|
||||
_proto._getAttachment = function _getAttachment(placement) {
|
||||
|
@ -4060,10 +4060,10 @@
|
|||
} // Private
|
||||
;
|
||||
|
||||
_proto._activate = function _activate(element, container, callback) {
|
||||
_proto._activate = function _activate(element, container_carousel, callback) {
|
||||
var _this2 = this;
|
||||
|
||||
var activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector$9.ACTIVE_UL) : $(container).children(Selector$9.ACTIVE);
|
||||
var activeElements = container_carousel && (container_carousel.nodeName === 'UL' || container_carousel.nodeName === 'OL') ? $(container_carousel).find(Selector$9.ACTIVE_UL) : $(container_carousel).children(Selector$9.ACTIVE);
|
||||
var active = activeElements[0];
|
||||
var isTransitioning = callback && active && $(active).hasClass(ClassName$9.FADE);
|
||||
|
||||
|
|
2
gestion/static/js/bootstrap_carousel.min.js
vendored
2
gestion/static/js/bootstrap_carousel.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load changelang %}
|
||||
{% load avatar_tags %}
|
||||
{% get_current_language as current_language %}
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
|
@ -13,56 +14,114 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>{% block titre %}{% endblock %}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
{% block extrahead %}{% endblock %}
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/main.css' %}" />
|
||||
{% block extrahead %}{% endblock %}
|
||||
|
||||
</head>
|
||||
<body class="subpage">
|
||||
|
||||
<!-- Header -->
|
||||
<header id="header">
|
||||
|
||||
<a href="{% url 'home' %}"><img src="{% static 'images/Ernestophone_white.png' %}"
|
||||
|
||||
style="float: left; width: auto; height: 3.1em;" alt="L'Ernestophone" title="white_esnesto" id="logo"></a>
|
||||
|
||||
<a href="#menu">Menu</a>
|
||||
</header>
|
||||
<nav class="navbar navbar-expand-md">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand -->
|
||||
<a class="navbar-brand" href="{% url 'home' %}"><img style='float:left;height:3em;width:auto' src='{% static "images/Ernestophone_white.png" %}'/></a>
|
||||
|
||||
<!-- Nav -->
|
||||
<nav id="menu">
|
||||
<ul class="links">
|
||||
<li><p></p></li>
|
||||
<li>{% ifequal current_language "fr" %}
|
||||
<a href="{% changelang "en" %}" >English<span class="image right"><img src="{% static "images/en_flag.jpg" %}"></span></a>
|
||||
{% else %}
|
||||
<a href="{% changelang "fr" %}">Français<span class="image right"><img src="{% static "images/fr_flag.jpg" %}"></span></a>
|
||||
{% endifequal %}</li>
|
||||
{% if not user.is_authenticated %}
|
||||
<li><a href="{% url 'home' %}">{% trans "Accueil" %}</a></li>
|
||||
<li><a href="{% url 'calendrier:liste' %}">{% trans "Agenda" %}</a></li>
|
||||
{% else %}
|
||||
<li><a href="{% url 'calendrier:home' %}">{% trans "Agenda" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a href="{% url 'partitions:liste' %}">{% trans "Répertoire" %}</a></li>
|
||||
<!-- Links -->
|
||||
<ul class="navbar-nav mr-auto" >
|
||||
|
||||
{% if not user.is_authenticated %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'home' %}"><b>{% trans "Accueil" %}</b></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link"href="{% url 'calendrier:liste' %}"><b>{% trans "Agenda" %}</b></a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'calendrier:home' %}"><b>{% trans "Agenda" %}</b></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'partitions:liste' %}"><b>{% trans "Répertoire" %}</b></a>
|
||||
</li>
|
||||
{% if user.is_authenticated %}
|
||||
<li><a href="{% url 'trombonoscope:view' %}">{% trans "Trombonoscope" %}</a></li>
|
||||
<li><a href="{% url 'pads:list' %}">{% trans "Pads" %}</a></li>
|
||||
{% if user.is_superuser or user.profile.is_chef %}
|
||||
<li><a href="/admin/">{% trans "Administration" %}</a></li>
|
||||
{% if user.profile.is_chef %}
|
||||
<li><a href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li><a href="{% url 'change_membre' %}">{% trans "Modification du profil" %}</a></li>
|
||||
<li><a href="{% url 'logout' %}">{% trans "Déconnexion" %}</a></li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'instruments:liste' %}"><b>{% trans "Instruments" %}</b></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'pads:list' %}"><b>{% trans "Pads" %}</b></a>
|
||||
</li>
|
||||
<!-- Dropdown -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="{% url 'social' %}" id="navbardrop" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<b>{% trans 'Social'%}
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="{% url 'trombonoscope:view' %}">{% trans "Trombonoscope" %}</a>
|
||||
<a class="dropdown-item" href="https://photos.cof.ens.fr/index.php/Clubs-du-COF/L'Ernestophone" target="_blank">{% trans "Galerie Photo" %}</a>
|
||||
|
||||
{% else %}
|
||||
<li><a href="{% url 'login' %}">{% trans "Se connecter" %}</a></li>
|
||||
<li><a href="{% url 'registration' %}">{% trans "Créer un compte" %}</a></li>
|
||||
</div>
|
||||
</li>
|
||||
{% if user.is_superuser or user.profile.is_chef %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="{% url 'chef' %}" id="navbardrop" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<b>{% trans 'Le pouvoir des cheff·e·s'%}</b>
|
||||
</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/admin/">{% trans "Administration" %}</a>
|
||||
{% if user.profile.is_chef %}
|
||||
<a class="dropdown-item" href="{% url 'calendrier:create_event' %}">{% trans "Ajouter un événement" %}</a>
|
||||
<a class="dropdown-item" href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'home' %}#contact"><b>{% trans "Contact" %}</b></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
|
||||
<ul class="navbar-nav" style="float:right">
|
||||
{% if user.is_authenticated %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="{% url 'profile' %}" id="navbardrop" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{% if request.user|has_avatar %}
|
||||
{% avatar request.user 50 class="rounded-circle"%}
|
||||
{% else %}
|
||||
<img src="{% static "images/Ernestophone_logo.png" %}" width="50" height="50" class="rounded-circle">
|
||||
{% endif %}
|
||||
|
||||
</a>
|
||||
<div class="dropdown-menu" >
|
||||
<a class="dropdown-item" href="{% url 'change_membre' %}">{% trans "Modifier le profil" %}</a>
|
||||
<a class="dropdown-item" href="{% url 'trombonoscope:change' %}">{% trans "Modifier le Trombo" %}</a>
|
||||
<a class="dropdown-item" href="{% url 'logout' %}">{% trans "Déconnexion" %}</a>
|
||||
</div>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'login' %}"><b>{% trans "Se connecter" %}</b></a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{% url 'registration' %}"><b>{% trans "Créer un compte" %}</a></li>
|
||||
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
{% ifequal current_language "fr" %}
|
||||
<a class="nav-link" href="{% changelang "en" %}" ><img src="{% static 'images\en_flag.jpg' %}" width="60" height="40" class="rounded-circle"></a>
|
||||
{% else %}
|
||||
<a class="nav-link" href="{% changelang "fr" %}" ><img src="{% static 'images\fr_flag.jpg' %}" width="60" height="40" class="rounded-circle"></a>
|
||||
{% endifequal %}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<!-- Main -->
|
||||
|
@ -82,19 +141,57 @@
|
|||
<li><a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ"
|
||||
|
||||
class="icon fa-youtube-play"><span class="label">Youtube</span></a></li>
|
||||
|
||||
<li><a target="_blank" href="https://www.instagram.com/ernestophone/" class="icon fa-instagram"><span class="label">Instagram</span></a></li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Scripts -->
|
||||
|
||||
|
||||
<script src="{% static 'js/jquery.min.js' %}"></script>
|
||||
<script src="{% static 'js/jquery.scrolly.min.js' %}"></script>
|
||||
<script src="{% static 'js/skel.min.js' %}"></script>
|
||||
<script src="{% static 'js/util.js' %}"></script>
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
<script src="{% static 'js/InstagramFeed.js' %}"></script>
|
||||
|
||||
<script>
|
||||
|
||||
|
||||
const $dropdown = $(".dropdown");
|
||||
const $dropdownToggle = $(".dropdown-toggle");
|
||||
const $dropdownMenu = $(".dropdown-menu");
|
||||
const showClass = "show";
|
||||
|
||||
$(window).on("load resize", function() {
|
||||
|
||||
if (this.matchMedia("(min-width: 768px)").matches) {
|
||||
$dropdown.hover(
|
||||
function() {
|
||||
const $this = $(this);
|
||||
$this.addClass(showClass);
|
||||
$this.find($dropdownToggle).attr("aria-expanded", "true");
|
||||
$this.find($dropdownMenu).addClass(showClass);
|
||||
},
|
||||
function() {
|
||||
const $this = $(this);
|
||||
$this.removeClass(showClass);
|
||||
$this.find($dropdownToggle).attr("aria-expanded", "false");
|
||||
$this.find($dropdownMenu).removeClass(showClass);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$dropdown.off("mouseenter mouseleave");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
function ouvrirFermerSpoiler(div)
|
||||
{
|
||||
var divContenu = div.getElementsByTagName('div')[1];
|
||||
|
|
|
@ -52,9 +52,20 @@
|
|||
</div>
|
||||
<div class ="6u 12u (small)">
|
||||
<span class="image fit">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/registration.png' %}" alt="" />
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="" class="icon fa-copyright">lor_tie</a>
|
||||
<div href="" class="icon fa-copyright"> lor_tie</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
|
|
23
gestion/templates/gestion/chef.html
Normal file
23
gestion/templates/gestion/chef.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Cheff·e·s" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
<h2>{% trans "Le pouvoir des cheff·e·s" %} :</h2>
|
||||
<ul>
|
||||
<li> <a href="/admin/">{% trans "Administration" %}</a></li>
|
||||
<li> <a href="{% url 'calendrier:create_event' %}">{% trans "Ajouter un événement" %}</a></li>
|
||||
<li><a href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -3,6 +3,7 @@
|
|||
{% load i18n %}
|
||||
{% load halflength %}
|
||||
{% block titre %}{% trans "L'Ernestophone : La fanfare de l'Ecole normale supérieure de Paris" %}{% endblock %}
|
||||
{% block extrahead %} <link rel="stylesheet" href="{% static 'css/style.css' %}" />{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<!-- Banner -->
|
||||
|
@ -32,8 +33,12 @@
|
|||
grâce à notre énergie et notre répertoire oscillant entre pop et
|
||||
brass band.{% endblocktrans %}</p>
|
||||
</header>
|
||||
<!-- 2 Column Video Section -->
|
||||
|
||||
<!-- Carousel row -->
|
||||
<div class="top-content">
|
||||
<div class="container_carousel">
|
||||
<div class="row">
|
||||
<div class="col col-md-10 offset-md-1 col-lg-8 offset-lg-2">
|
||||
<!-- Carousel -->
|
||||
{% if videos %}
|
||||
<div id="carousel" class="carousel slide">
|
||||
|
@ -72,17 +77,24 @@
|
|||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- End carousel -->
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<!-- Two -->
|
||||
<section class="wrapper style2" >
|
||||
|
||||
<div class="inner">
|
||||
<div class="inner" id="contact">
|
||||
<header>
|
||||
<h2>{% trans "L'Ernestophone in a nutshell" %}</h2>
|
||||
<div id="instagram-feed" class="instagram_feed"> </div>
|
||||
<p style="color:white">{% blocktrans %}L'Ernestophone, c'est la fanfare de l'École
|
||||
normale supérieure, (re)créée en septembre 2011, pour le plus
|
||||
grand bonheur des petits. Et des grands.{% endblocktrans %}</p>
|
||||
|
@ -155,10 +167,20 @@
|
|||
{% endfor %}
|
||||
<a href="{% url 'partitions:liste' %}" class="button alt fit" >{% trans "Voir le répertoire présent et passé" %}</a>
|
||||
<span class="image fit">
|
||||
{% if photo_rep %}
|
||||
<img src="{{photo_rep.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo_rep.url %}
|
||||
<a href="{{photo_rep.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo_rep.color}}"> {% if photo_rep.auteur %}{{photo_rep.auteur}}{%endif%}</a>
|
||||
{% elif photo_rep.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo_rep.color}}" > {{photo_rep.auteur}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/repertoire.jpg' %}" alt="" />
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="" class="icon fa-copyright"> Lucas Gierzack</a>
|
||||
<div class="icon fa-copyright"> Lucas Gierzack</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
@ -176,10 +198,21 @@
|
|||
Nous prêtons des instruments à tout membre du COF souhaitant découvrir les joies de la fanfaronnerie !{% endblocktrans %}</p>
|
||||
</div>
|
||||
<div class="5u 12u$(small)"><div>
|
||||
<span class="image fit"><img src="{% static 'images/join.jpg' %}" alt="" />
|
||||
<span class="image fit">
|
||||
{% if photo_join %}
|
||||
<img src="{{photo_join.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo_join.url %}
|
||||
<a href="{{photo_join.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo_join.color}}"> {% if photo_join.auteur %}{{photo_join.auteur}}{%endif%}</a>
|
||||
{% elif photo_join.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo_join.color}}" > {{photo_join.auteur}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/join.jpg' %}" alt="" />
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -192,12 +225,23 @@
|
|||
<div class="tab tab-3 flex flex-3 active">
|
||||
<div class="box">
|
||||
<div><span class="image right">
|
||||
{% if photo_contact %}
|
||||
<img src="{{photo_contact.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo_contact.url %}
|
||||
<a href="{{photo_contact.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo_contact.color}}"> {% if photo_contact.auteur %}{{photo_contact.auteur}}{%endif%}</a>
|
||||
{% elif photo_contact.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo_contact.color}}" > {{photo_contact.auteur}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/contact.jpg' %}" alt=""/>
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
|
||||
</div></span></div><p style="color:white" align="center">{% blocktrans %}Vous préparez un
|
||||
</div>
|
||||
{% endif %}
|
||||
</span></div><p style="color:white" align="center">{% blocktrans %}Vous préparez un
|
||||
évenement et vous recherchez une fanfare dynamique ? N'hésitez
|
||||
pas à nous envoyer un message nous serons ravis de venir
|
||||
pas à nous envoyer un message par mail ou sur Facebook. Nous serons ravis de venir
|
||||
fanfaronner pour vous !! Vérifiez notre{% endblocktrans %} <a href="{% url 'calendrier:liste' %}" class="text">{% trans "agenda" %}</a>. <br />
|
||||
|
||||
<a target="_blank" href="https://www.facebook.com/ernestophone"
|
||||
|
@ -211,10 +255,12 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
<a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ"
|
||||
|
||||
class="icon fa-youtube-play fa-5x"><span class="label">Youtube</span></a>
|
||||
class="icon fa-youtube-play fa-5x"><span class="label">Youtube</span> </a>
|
||||
|
||||
<a target="_blank" href="https://www.instagram.com/ernestophone/" class="icon fa-instagram fa-5x"><span class="label">Instagram</span></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -223,7 +269,25 @@
|
|||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script src="{% static 'js/InstagramFeed.min.js' %}"></script>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
new InstagramFeed({
|
||||
'username': 'ernestophone',
|
||||
'container': "#instagram-feed" ,
|
||||
'display_profile': false,
|
||||
'display_biography': false,
|
||||
'display_gallery': true,
|
||||
'display_captions': true,
|
||||
'callback': null,
|
||||
'styling': true,
|
||||
'items': 8,
|
||||
'items_per_row': 8,
|
||||
'margin': 1
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<script src="{% static 'js/jquery-3.3.1.min.js' %}"></script>
|
||||
<script src="{% static 'js/jquery-migrate-3.0.0.min.js' %}"></script>
|
||||
<script src="{% static 'js/popper.min.js' %}"></script>
|
||||
|
|
|
@ -34,9 +34,22 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="6u 12u$(xsmall)">
|
||||
<span class="image fit"><img src="{% static 'images/connect.jpg' %}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<span class="image fit">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/connect.jpg' %}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
|
||||
</div></span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
23
gestion/templates/gestion/profile.html
Normal file
23
gestion/templates/gestion/profile.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Profil" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
<h2>{% trans "Profil" %} :</h2>
|
||||
<ul>
|
||||
<li> <a href="{% url 'login' %}">{% trans "Se connecter" %}</a></li>
|
||||
<li> <a href="{% url 'trombonoscope:change' %}">{% trans "Modifier le Trombo" %}</a></li>
|
||||
<li><a href="{% url 'registration' %}">{% trans "Créer un compte" %}</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -12,7 +12,7 @@
|
|||
<section class="wrapper style1" >
|
||||
<div class="inner">
|
||||
<h2>{% trans "Créer un compte :" %}</h2>
|
||||
{% if error %}
|
||||
{% if error %}
|
||||
<p>{{ error }}</p>
|
||||
{% endif %}
|
||||
<div class="row uniform">
|
||||
|
@ -48,10 +48,21 @@
|
|||
</div>
|
||||
<div class ="6u 12u (small)">
|
||||
<span class="image fit">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/registration.png' %}" alt="" />
|
||||
<div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<a href="" class="icon fa-copyright">lor_tie</a>
|
||||
<div href="" class="icon fa-copyright"> lor_tie</div>
|
||||
</div>
|
||||
{%endif%}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
22
gestion/templates/gestion/social.html
Normal file
22
gestion/templates/gestion/social.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Social" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
<h2>{% trans "Social" %} :</h2>
|
||||
<ul>
|
||||
<li> <a href="{% url 'trombonoscope:view' %}">{% trans "Trombonoscope" %}</a></li>
|
||||
<li><a href="https://photos.cof.ens.fr/index.php/Clubs-du-COF/L'Ernestophone" target="_blank">{% trans "Galerie Photo" %}</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -3,12 +3,13 @@ from django.utils.safestring import mark_safe
|
|||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.simple_tag
|
||||
def autotranslate(current_language, description, description_en):
|
||||
|
||||
if( current_language != "fr" and description_en):
|
||||
if current_language != "fr" and description_en:
|
||||
return mark_safe(description_en)
|
||||
elif(current_language == "fr" and not description):
|
||||
elif current_language == "fr" and not description:
|
||||
return mark_safe(description_en)
|
||||
else:
|
||||
return mark_safe(description)
|
||||
|
|
|
@ -12,7 +12,7 @@ def changelang(context, lang=None, *args, **kwargs):
|
|||
Usage: {% change_lang 'en' %}
|
||||
"""
|
||||
|
||||
path = context['request'].path
|
||||
path = context["request"].path
|
||||
url_parts = resolve(path)
|
||||
|
||||
url = path
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from django.template import Library
|
||||
from math import ceil
|
||||
|
||||
from django.template import Library
|
||||
|
||||
register = Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def half_length(liste):
|
||||
try:
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from django import template
|
||||
from datetime import date, timedelta
|
||||
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def modulo(num, val):
|
||||
return num % val
|
||||
|
|
233
gestion/views.py
233
gestion/views.py
|
@ -1,115 +1,200 @@
|
|||
from django.shortcuts import render, redirect
|
||||
from partitions.models import Category
|
||||
from gestion.forms import ChangeMembreForm, ChangeFormUser,RegistrationFormUser, InscriptionMembreForm
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from gestion.models import ErnestoUser, VideoGallery
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
from calendrier.forms import ChangeDoodleName
|
||||
from partitions.decorators import chef_required
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
from django.urls import reverse_lazy
|
||||
from django.shortcuts import render_to_response
|
||||
import string
|
||||
import random
|
||||
import string
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.views import LoginView
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from calendrier.forms import ChangeDoodleName
|
||||
from gestion.forms import (ChangeFormUser, ChangeMembreForm,
|
||||
InscriptionMembreForm, RegistrationFormUser)
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from gestion.models import ErnestoUser, Photo, VideoGallery
|
||||
from partitions.models import Category
|
||||
|
||||
|
||||
def generer(*args):
|
||||
caracteres = string.ascii_letters + string.digits
|
||||
aleatoire = [random.choice(caracteres) for _ in range(6)]
|
||||
return ''.join(aleatoire)
|
||||
aleatoire = [random.choice(caracteres) for i in range(6)]
|
||||
return "".join(aleatoire)
|
||||
|
||||
|
||||
def home(request):
|
||||
if request.user.is_authenticated :
|
||||
return redirect('calendrier:home')
|
||||
categories = Category.objects.filter(name = "Partitions actives").prefetch_related("partitionset_set")
|
||||
videos = VideoGallery.objects.all()
|
||||
return render_to_response( 'gestion/index.html', {"request":request,"categories": categories,'videos':videos})
|
||||
def thanks(request):
|
||||
class Home(TemplateView):
|
||||
template_name = "gestion/index.html"
|
||||
|
||||
return render(request, 'gestion/thanks.html', locals())
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
return redirect("calendrier:home")
|
||||
return super(Home, self).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["categories"] = Category.objects.filter(
|
||||
name="Partitions actives"
|
||||
).prefetch_related("partitionset_set")
|
||||
context["videos"] = VideoGallery.objects.all()
|
||||
context["photo_rep"] = (
|
||||
Photo.objects.filter(cat="home_rep").order_by("?").first()
|
||||
)
|
||||
context["photo_join"] = (
|
||||
Photo.objects.filter(cat="home_join").order_by("?").first()
|
||||
)
|
||||
context["photo_contact"] = (
|
||||
Photo.objects.filter(cat="home_contact").order_by("?").first()
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
def changename(request):
|
||||
if request.method == 'POST':
|
||||
class MyLoginView(LoginView):
|
||||
|
||||
template_name = "gestion/login.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["photo"] = Photo.objects.filter(cat="login").order_by("?").first()
|
||||
return context
|
||||
|
||||
|
||||
class Thanks(TemplateView):
|
||||
template_name = "gestion/thanks.html"
|
||||
|
||||
|
||||
class Social(LoginRequiredMixin, TemplateView):
|
||||
template_name = "gestion/social.html"
|
||||
|
||||
|
||||
class Profil(LoginRequiredMixin, TemplateView):
|
||||
template_name = "gestion/profile.html"
|
||||
|
||||
|
||||
class Chef(ChefRequiredMixin, TemplateView):
|
||||
template_name = "gestion/chef.html"
|
||||
|
||||
|
||||
class ChangeName(LoginRequiredMixin, TemplateView):
|
||||
form_class = ChangeDoodleName
|
||||
template_name = "gestion/changename.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class(instance=self.request.user)
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
requbis = request.POST.copy()
|
||||
form = ChangeDoodleName(requbis, instance=request.user)
|
||||
form = self.form_class(requbis, instance=request.user)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
success = True
|
||||
return redirect('change_membre')
|
||||
else:
|
||||
form = ChangeDoodleName(instance=request.user)
|
||||
return render(request, 'gestion/changename.html', locals())
|
||||
return redirect("change_membre")
|
||||
|
||||
context = self.get_context_data()
|
||||
context["form"] = form
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class ChangeMembre(LoginRequiredMixin, TemplateView):
|
||||
comp_form_class = ChangeMembreForm
|
||||
user_form_class = ChangeFormUser
|
||||
template_name = "gestion/change.html"
|
||||
|
||||
@login_required
|
||||
def change_membre(request):
|
||||
if request.method == 'POST':
|
||||
comp_form = ChangeMembreForm(request.POST, instance=request.user.profile)
|
||||
user_form = ChangeFormUser(request.POST, instance=request.user)
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
comp_form = self.comp_form_class(instance=self.request.user.profile)
|
||||
user_form = self.user_form_class(instance=self.request.user)
|
||||
context["comp_form"] = comp_form
|
||||
context["user_form"] = user_form
|
||||
context["photo"] = (
|
||||
Photo.objects.filter(cat="change_membre").order_by("?").first()
|
||||
)
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
success = False
|
||||
comp_form = self.comp_form_class(request.POST, instance=request.user.profile)
|
||||
user_form = self.user_form_class(request.POST, instance=request.user)
|
||||
if user_form.is_valid() and comp_form.is_valid():
|
||||
user_form.save()
|
||||
comp_form.save()
|
||||
success = True
|
||||
return redirect('home')
|
||||
else:
|
||||
comp_form = ChangeMembreForm(instance=request.user.profile)
|
||||
user_form = ChangeFormUser(instance=request.user)
|
||||
return render(request, 'gestion/change.html', locals())
|
||||
|
||||
@login_required
|
||||
def change_password(request):
|
||||
if request.method == 'POST':
|
||||
context = self.get_context_data()
|
||||
context["success"] = success
|
||||
context["comp_form"] = comp_form
|
||||
context["user_form"] = user_form
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class ChangePassword(LoginRequiredMixin, TemplateView):
|
||||
form_class = PasswordChangeForm
|
||||
template_name = "gestion/changepasswd.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class(self.request.user)
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
requbis = request.POST.copy()
|
||||
form = PasswordChangeForm(request.user, data=requbis)
|
||||
success = False
|
||||
form = self.form_class(request.user, data=requbis)
|
||||
if form.is_valid():
|
||||
|
||||
request.user.profile.photo.delete()
|
||||
form.save()
|
||||
|
||||
success = True
|
||||
|
||||
else:
|
||||
form = PasswordChangeForm(request.user)
|
||||
return render(request, 'gestion/changepasswd.html', locals())
|
||||
context = self.get_context_data()
|
||||
context["success"] = success
|
||||
context["form"] = form
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class Inscription(TemplateView):
|
||||
user_form_class = RegistrationFormUser
|
||||
comp_form_class = InscriptionMembreForm
|
||||
template_name = "gestion/registration.html"
|
||||
|
||||
def inscription_membre(request):
|
||||
if request.method == 'POST':
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["comp_form"] = self.comp_form_class()
|
||||
context["user_form"] = self.user_form_class()
|
||||
context["photo"] = (
|
||||
Photo.objects.filter(cat="inscription_membre").order_by("?").first()
|
||||
)
|
||||
return context
|
||||
|
||||
user_form = RegistrationFormUser(request.POST)
|
||||
comp_form = InscriptionMembreForm(request.POST)
|
||||
def post(self, request, *args, **kwargs):
|
||||
user_form = self.user_form_class(request.POST)
|
||||
comp_form = self.comp_form_class(request.POST)
|
||||
if user_form.is_valid() and comp_form.is_valid():
|
||||
pseudo = user_form.cleaned_data['username']
|
||||
if not (comp_form.cleaned_data['validation']
|
||||
== settings.ACCOUNT_CREATION_PASS):
|
||||
error = "Le champ Validation ne correspond pas à celui attendu"
|
||||
return render(request, "gestion/registration.html", locals())
|
||||
|
||||
if not (
|
||||
comp_form.cleaned_data["validation"] == settings.ACCOUNT_CREATION_PASS
|
||||
):
|
||||
error = _("Le champ Validation ne correspond pas à celui attendu")
|
||||
context = self.get_context_data()
|
||||
context["user_form"] = user_form
|
||||
context["comp_form"] = comp_form
|
||||
context["error"] = error
|
||||
return render(request, self.template_name, context)
|
||||
member = user_form.save(commit=False)
|
||||
temp = True
|
||||
while temp:
|
||||
code = generer()
|
||||
try:
|
||||
ErnestoUser.objects.get(slug=code)
|
||||
except:
|
||||
except ErnestoUser.DoesNotExist:
|
||||
temp = False
|
||||
member.save()
|
||||
(profile, _) = ErnestoUser.objects.get_or_create(user=member,
|
||||
slug=code)
|
||||
comp_form = InscriptionMembreForm(request.POST, instance=profile)
|
||||
(profile, k) = ErnestoUser.objects.get_or_create(user=member, slug=code)
|
||||
comp_form = self.comp_form_class(request.POST, instance=profile)
|
||||
obj = comp_form.save(commit=False)
|
||||
obj.slug = code
|
||||
obj.save()
|
||||
envoi = True
|
||||
return redirect('thanks')
|
||||
else:
|
||||
comp_form = InscriptionMembreForm()
|
||||
user_form = RegistrationFormUser()
|
||||
return render(request, 'gestion/registration.html', locals())
|
||||
return redirect("thanks")
|
||||
else:
|
||||
context = self.get_context_data()
|
||||
context["user_form"] = user_form
|
||||
context["comp_form"] = comp_form
|
||||
return render(request, self.template_name, context)
|
||||
|
|
0
instruments/__init__.py
Normal file
0
instruments/__init__.py
Normal file
6
instruments/admin.py
Normal file
6
instruments/admin.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Instrument, Reparation
|
||||
|
||||
admin.site.register(Instrument)
|
||||
admin.site.register(Reparation)
|
5
instruments/apps.py
Normal file
5
instruments/apps.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class InstrumentsConfig(AppConfig):
|
||||
name = "instruments"
|
27
instruments/forms.py
Normal file
27
instruments/forms.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from django import forms
|
||||
|
||||
from .models import Instrument, Reparation
|
||||
|
||||
|
||||
class ChefReparationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Reparation
|
||||
fields = ("date", "description", "description_en", "prix", "lieux")
|
||||
|
||||
|
||||
class ChefEditInstrumentForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Instrument
|
||||
fields = (
|
||||
"statut",
|
||||
"user",
|
||||
"infos",
|
||||
"type",
|
||||
"owner",
|
||||
"marque",
|
||||
"model",
|
||||
"serial",
|
||||
"annee",
|
||||
"prix",
|
||||
"infos_en",
|
||||
)
|
174
instruments/migrations/0001_initial.py
Normal file
174
instruments/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,174 @@
|
|||
# Generated by Django 2.2.17 on 2021-04-01 19:25
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.db.models.functions.text
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Instrument",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"model",
|
||||
models.CharField(
|
||||
blank=True, max_length=100, null=True, verbose_name="Modèle"
|
||||
),
|
||||
),
|
||||
(
|
||||
"prix",
|
||||
models.CharField(
|
||||
blank=True, default="", max_length=100, verbose_name="Prix"
|
||||
),
|
||||
),
|
||||
(
|
||||
"etat",
|
||||
models.CharField(
|
||||
choices=[
|
||||
("Bon état", "Bon état"),
|
||||
("Etat moyen", "Etat moyen"),
|
||||
("Mauvais état", "Mauvais état"),
|
||||
],
|
||||
default="Bon état",
|
||||
max_length=100,
|
||||
),
|
||||
),
|
||||
(
|
||||
"marque",
|
||||
models.CharField(
|
||||
blank=True, max_length=100, null=True, verbose_name="Marque"
|
||||
),
|
||||
),
|
||||
(
|
||||
"serial",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default=" ",
|
||||
max_length=100,
|
||||
null=True,
|
||||
verbose_name="Numéro de série",
|
||||
),
|
||||
),
|
||||
(
|
||||
"annee",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
max_length=100,
|
||||
null=True,
|
||||
verbose_name="Année d'achat",
|
||||
),
|
||||
),
|
||||
(
|
||||
"owner",
|
||||
models.CharField(
|
||||
default="Fanfare", max_length=100, verbose_name="Propriétaire"
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.CharField(
|
||||
blank=True, max_length=100, verbose_name="Utilisateur"
|
||||
),
|
||||
),
|
||||
("type", models.CharField(max_length=40, verbose_name="Instrument")),
|
||||
(
|
||||
"statut",
|
||||
models.CharField(
|
||||
choices=[("Disponible", "Disponible"), ("Prêté", "Prêté")],
|
||||
default="Disponible",
|
||||
max_length=100,
|
||||
),
|
||||
),
|
||||
(
|
||||
"infos",
|
||||
models.TextField(
|
||||
blank=True, default="", verbose_name="Infos utiles"
|
||||
),
|
||||
),
|
||||
(
|
||||
"infos_en",
|
||||
models.TextField(
|
||||
blank=True, default="", verbose_name="Infos utiles en anglais"
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Instrument",
|
||||
"verbose_name_plural": "Instruments",
|
||||
"ordering": (django.db.models.functions.text.Lower("type"),),
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Reparation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("date", models.DateField(max_length=100, verbose_name="Date")),
|
||||
(
|
||||
"description",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default=" ",
|
||||
max_length=100,
|
||||
verbose_name="Description",
|
||||
),
|
||||
),
|
||||
(
|
||||
"description_en",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default=" ",
|
||||
max_length=100,
|
||||
verbose_name="Description en anglais",
|
||||
),
|
||||
),
|
||||
(
|
||||
"prix",
|
||||
models.CharField(
|
||||
blank=True, default="", max_length=100, verbose_name="Prix"
|
||||
),
|
||||
),
|
||||
(
|
||||
"lieux",
|
||||
models.CharField(
|
||||
blank=True, default=" ", max_length=100, verbose_name="Lieux"
|
||||
),
|
||||
),
|
||||
(
|
||||
"instru",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="instruments.Instrument",
|
||||
verbose_name="Instrument",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Réparation",
|
||||
"verbose_name_plural": "Réparations",
|
||||
"ordering": ("date",),
|
||||
},
|
||||
),
|
||||
]
|
22
instruments/migrations/0002_auto_20210428_2138.py
Normal file
22
instruments/migrations/0002_auto_20210428_2138.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 2.2.17 on 2021-04-28 21:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("instruments", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="instrument",
|
||||
name="statut",
|
||||
field=models.CharField(
|
||||
choices=[("Disponible", "Disponible"), ("Prêté", "Prêté·e")],
|
||||
default="Disponible",
|
||||
max_length=100,
|
||||
),
|
||||
),
|
||||
]
|
0
instruments/migrations/__init__.py
Normal file
0
instruments/migrations/__init__.py
Normal file
66
instruments/models.py
Normal file
66
instruments/models.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
from django.db import models
|
||||
from django.db.models.functions import Lower
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class Instrument(models.Model):
|
||||
|
||||
model = models.CharField(_("Modèle"), max_length=100, null=True, blank=True)
|
||||
prix = models.CharField(_("Prix"), max_length=100, default="", blank=True)
|
||||
etat = models.CharField(
|
||||
max_length=100,
|
||||
default="Bon état",
|
||||
choices=[
|
||||
("Bon état", _("Bon état")),
|
||||
("Etat moyen", _("Etat moyen")),
|
||||
("Mauvais état", _("Mauvais état")),
|
||||
],
|
||||
)
|
||||
marque = models.CharField(_("Marque"), max_length=100, null=True, blank=True)
|
||||
serial = models.CharField(
|
||||
_("Numéro de série"), max_length=100, default=" ", null=True, blank=True
|
||||
)
|
||||
annee = models.CharField(_("Année d'achat"), max_length=100, null=True, blank=True)
|
||||
owner = models.CharField(_("Propriétaire"), max_length=100, default="Fanfare")
|
||||
user = models.CharField(_("Utilisateur"), max_length=100, blank=True)
|
||||
type = models.CharField(_("Instrument"), max_length=40, blank=False)
|
||||
statut = models.CharField(
|
||||
max_length=100,
|
||||
default="Disponible",
|
||||
choices=[("Disponible", _("Disponible")), ("Prêté", _("Prêté·e"))],
|
||||
)
|
||||
infos = models.TextField(_("Infos utiles"), null=False, blank=True, default="")
|
||||
infos_en = models.TextField(
|
||||
"Infos utiles en anglais", null=False, blank=True, default=""
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Instrument")
|
||||
verbose_name_plural = _("Instruments")
|
||||
ordering = (Lower("type"),)
|
||||
|
||||
|
||||
class Reparation(models.Model):
|
||||
date = models.DateField(_("Date"), max_length=100)
|
||||
instru = models.ForeignKey(
|
||||
"Instrument", on_delete=models.CASCADE, verbose_name=_("Instrument")
|
||||
)
|
||||
description = models.CharField(
|
||||
_("Description"), max_length=100, default=" ", blank=True
|
||||
)
|
||||
description_en = models.CharField(
|
||||
_("Description en anglais"), max_length=100, default=" ", blank=True
|
||||
)
|
||||
prix = models.CharField(_("Prix"), max_length=100, default="", blank=True)
|
||||
lieux = models.CharField(_("Lieux"), max_length=100, default=" ", blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.description
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Réparation")
|
||||
verbose_name_plural = _("Réparations")
|
||||
ordering = ("date",)
|
BIN
instruments/static/images/instruments.jpg
Executable file
BIN
instruments/static/images/instruments.jpg
Executable file
Binary file not shown.
After Width: | Height: | Size: 341 KiB |
19
instruments/templates/instruments/create_instru.html
Normal file
19
instruments/templates/instruments/create_instru.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{%block titre %}{% trans "Ajout d'une instrument" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<p><a href="{% url "instruments:liste" %}" class="button alt">{% trans "Retour à la liste" %}</a></p>
|
||||
{% if envoi %}<p>{% trans "Cet instrument a été enregistré" %}.{% endif %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
19
instruments/templates/instruments/create_rep.html
Normal file
19
instruments/templates/instruments/create_rep.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{%block titre %}{% trans "Ajout d'une réparation" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<p><a href="{% url "instruments:fiche_instru" pk %}" class="button alt">{% trans "Retour à la fiche" %}</a></p>
|
||||
{% if envoi %}<p>{% trans "Cette réparation a été enregistrée" %}.{% endif %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
16
instruments/templates/instruments/delete_instru.html
Normal file
16
instruments/templates/instruments/delete_instru.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Suppression d'un instrument" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<p><a href="{% url "instruments:liste" %}" class="button alt">{% trans "Retour aux instruments" %}</a></p>
|
||||
<p>{% blocktrans with object=object %} Voulez vous vraiment supprimer le.a {{ object }}?{% endblocktrans %}</p>
|
||||
<input type="submit" value="{% trans "Oui" %}" />
|
||||
</form>
|
||||
</div></section>
|
||||
</div>
|
||||
{% endblock %}
|
16
instruments/templates/instruments/delete_rep.html
Normal file
16
instruments/templates/instruments/delete_rep.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Suppression d'une réparation" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<p><a href="{% url "instruments:fiche_instru" id %}" class="button alt">{% trans "Retour à la fiche instrument" %}</a></p>
|
||||
<p>{% blocktrans with object=object %} Voulez vous vraiment supprimer la réparation {{object}}?{% endblocktrans %}</p>
|
||||
<input type="submit" value="{% trans "Oui" %}" />
|
||||
</form>
|
||||
</div></section>
|
||||
</div>
|
||||
{% endblock %}
|
101
instruments/templates/instruments/instru_liste.html
Normal file
101
instruments/templates/instruments/instru_liste.html
Normal file
|
@ -0,0 +1,101 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Instruments" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<span class="image fit">
|
||||
{% if photo %}
|
||||
<img src="{{photo.image.url}}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
{% if photo.url %}
|
||||
<a href="{{photo.url}}" target="_blank" class="icon fa-copyright" style="color: {{photo.color}}"> {% if photo.auteur %}{{photo.auteur}}{%endif%}</a>
|
||||
{% elif photo.auteur %}
|
||||
<div class="icon fa-copyright" style="color: {{photo.color}}" > {{photo.auteur}}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<img src="{% static 'images/instruments.jpg' %}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
|
||||
<div class="icon fa-copyright" style="color:#000000"> Lucas Gierzack</div></div>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if user.profile.is_chef %}
|
||||
<a href="{% url "instruments:ajouter_instru" %}" class="button alt big">{% trans "Ajouter un instrument" %}</a>
|
||||
{% endif %}
|
||||
<p></p>
|
||||
<h4>{% trans "Instruments Disponibles :" %} </h4>
|
||||
<div class="table-wrapper">
|
||||
<table class="default">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Intrument" %}</th>
|
||||
<th>{% trans "Propriétaire" %}</th>
|
||||
<th>{% trans "Etat" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for instrument in instrus_dispo %}
|
||||
|
||||
<tr>
|
||||
<td> <u> <a href="{% url "instruments:fiche_instru" instrument.id %}">{{ instrument.type }} </a></u></td>
|
||||
<td> {{ instrument.owner }} </td>
|
||||
<td> {{ instrument.etat }} </td>
|
||||
<td>
|
||||
<a href="{% url "instruments:fiche_instru" instrument.id %}" class="button small">{% trans "Consulter" %}<a/>
|
||||
{% if user.profile.is_chef %}
|
||||
|
||||
<a href="{% url "instruments:delete_instru" instrument.id %}" class="button small">{% trans "Supprimer" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="wrapper style2">
|
||||
<div class="inner">
|
||||
<h4>{% trans "Instruments Prêtés :" %} </h4>
|
||||
<div class="table-wrapper">
|
||||
<table class="default">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>{% trans "Intrument" %}</th>
|
||||
<th>{% trans "Propriétaire" %}</th>
|
||||
<th>{% trans "Utilisateur" %}</th>
|
||||
<th>{% trans "Etat" %}</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for instrument in instrus_prete %}
|
||||
<tr>
|
||||
|
||||
<td> <u><a href="{% url "instruments:fiche_instru" instrument.id %}">{{ instrument.type }}</a></u></td>
|
||||
<td> {{ instrument.owner }} </td>
|
||||
<td> {{ instrument.user }} </td>
|
||||
<td> {{ instrument.etat}} </td>
|
||||
<td>
|
||||
<a href="{% url "instruments:fiche_instru" instrument.id %}" class="button small">{% trans "Consulter" %}<a/>
|
||||
{% if user.profile.is_chef %}
|
||||
|
||||
<a href="{% url "instruments:delete_instru" instrument.id %}" class="button small">{% trans "Supprimer" %}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
104
instruments/templates/instruments/update_instru.html
Normal file
104
instruments/templates/instruments/update_instru.html
Normal file
|
@ -0,0 +1,104 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% get_current_language as current_language %}
|
||||
{% load autotranslate %}
|
||||
{% block titre %}{{ instru.type }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<h3>{% blocktrans with type=instru.type etat=instru.etat statut=instru.statut%} {{type}} en {{etat}} : {{statut}} {% endblocktrans%}</h3>
|
||||
<div class="row">
|
||||
|
||||
<div class="7u 12u$(small)">
|
||||
<p>{% trans "Propriétaire : "%} {% if instru.owner %}{{instru.owner}} {% else %}-{% endif %}<br>
|
||||
{% trans "Statut : "%} {{instru.statut}} <br>
|
||||
{% ifequal instru.statut 'Prêté' %}
|
||||
{% trans "Utilisateur : "%} {% if instru.user %}{{instru.user}} {% else %}-{% endif %}<br>
|
||||
{% endifequal %}
|
||||
{% trans "Marque : "%} {% if instru.marque %}{{instru.marque}} {% else %}-{% endif %} <br>
|
||||
{% trans "Modele : "%} {% if instru.model %}{{instru.model}} {% else %}-{% endif %}<br>
|
||||
{% trans "Numéro de série : "%} {% if instru.serial %}{{instru.serial}}{% else %}-{% endif %} <br>
|
||||
{% trans "Prix : "%} {% if instru.prix %}{{instru.prix}} {% else %}-{% endif %}<br>
|
||||
{% trans "Acheté·e en" %}{% if instru.annee %}{{annee}}{% else %}-{% endif %}
|
||||
</p>
|
||||
{% if infos or infos_en %}
|
||||
|
||||
<h1>{% trans "Infos utiles :" %}</h1>
|
||||
|
||||
<div class="box">{% autotranslate current_language infos infos_en %}</div>
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% if suppression %}
|
||||
<p>{{ suppression }}</p>
|
||||
{% endif %}
|
||||
{% if not user.profile.is_chef %}
|
||||
</div>
|
||||
<div class="5u 12u$(small)">
|
||||
{% endif %}
|
||||
<h4>{% blocktrans count counter=reparations|length %}Réparation :{% plural %}Réparations {% endblocktrans %}</h4>
|
||||
<div class="table-wrapper">
|
||||
<table class="default">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Description" %}</th>
|
||||
<th>{% trans "Prix" %}</th>
|
||||
<th>{% trans "lieu" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rep in reparations %}
|
||||
<tr>
|
||||
|
||||
<td> {{ rep.date }} </td>
|
||||
<td> {% ifequal current_language "fr" %}
|
||||
{{ rep.description }}
|
||||
{% else %}
|
||||
{% if instru.description_en %}
|
||||
{{ rep.description_en }}
|
||||
{% else %}
|
||||
{{ rep.description }}
|
||||
{% endif %}
|
||||
{% endifequal %} </td>
|
||||
<td> {{ rep.prix }} </td>
|
||||
<td> {{ rep.lieux }} </td>
|
||||
{% if user.profile.is_chef %}
|
||||
<td>
|
||||
<a href="{% url "instruments:update_rep" rep.id %}" class="button small">{% trans "Modifier" %}</a>
|
||||
<a href="{% url "instruments:delete_rep" rep.id %}" class="button small">{% trans "Supprimer" %}</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
<a class='button ' href="{% url "instruments:liste" %}">Retour aux instruments</a>
|
||||
{% if user.profile.is_chef %}
|
||||
<a class='button ' href="{% url "instruments:ajouter_rep" instru.id %}">Ajouter une réparation</a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% if user.profile.is_chef %}
|
||||
|
||||
<div class="5u 12u$(small)">
|
||||
<div class="info_part">
|
||||
<form action="{% url "instruments:fiche_instru" instru.id %}" id="chef-edit-form" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Enregister" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
19
instruments/templates/instruments/update_rep.html
Normal file
19
instruments/templates/instruments/update_rep.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{%block titre %}{% trans "Ajout d'une réparation" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<p><a href="{% url "instruments:fiche_instru" object.instru.id %}" class="button alt">{% trans "Retour à la fiche" %}</a></p>
|
||||
{% if envoi %}<p>{% trans "Cette réparation a été enregistrée" %}.{% endif %}
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
0
instruments/tests/__init__.py
Normal file
0
instruments/tests/__init__.py
Normal file
1
instruments/tests/test_file.txt
Normal file
1
instruments/tests/test_file.txt
Normal file
|
@ -0,0 +1 @@
|
|||
do not delete me
|
89
instruments/tests/test_views.py
Normal file
89
instruments/tests/test_views.py
Normal file
|
@ -0,0 +1,89 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.core.files import File
|
||||
from django.template.defaultfilters import urlencode
|
||||
from django.test import Client, TestCase
|
||||
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
from ..models import Category, Partition, PartitionSet
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def new_user(username, ernesto=False, chef=False):
|
||||
u = User.objects.create_user(username=username)
|
||||
ErnestoUser.objects.create(user=u, slug=username, is_chef=chef, is_ernesto=ernesto)
|
||||
return u
|
||||
|
||||
|
||||
class TestViews(TestCase):
|
||||
# TODO: add tests for upload/deletions
|
||||
# TODO: test forms
|
||||
|
||||
def setUp(self):
|
||||
# User with different access level and their clients
|
||||
chef = new_user("chef", ernesto=True, chef=True)
|
||||
chef_c = Client()
|
||||
chef_c.force_login(chef)
|
||||
ernesto = new_user("ernesto", ernesto=True)
|
||||
ernesto_c = Client()
|
||||
ernesto_c.force_login(ernesto)
|
||||
self.client_matrix = [(chef, chef_c), (ernesto, ernesto_c), (None, Client())]
|
||||
# A Partition set with 1 partition
|
||||
self.pset = PartitionSet.objects.create(
|
||||
category=Category.objects.first(), nom="My PSet", auteur="PSet author"
|
||||
)
|
||||
file = File(open("partitions/tests/test_file.txt"), "test file")
|
||||
Partition.objects.create(nom="part1", part=file, morceau=self.pset)
|
||||
|
||||
def tearDown(self):
|
||||
"""Remove dummy files from media/partitions/"""
|
||||
for partition in self.pset.partition_set.all():
|
||||
partition.delete()
|
||||
|
||||
def _get_restricted_page(self, url):
|
||||
"""
|
||||
Shorthand for testing wether a page in only accessible by ernesto
|
||||
members
|
||||
"""
|
||||
for user, client in self.client_matrix:
|
||||
# If user is not None, it is an ernesto member
|
||||
resp = client.get(url)
|
||||
if user:
|
||||
self.assertEqual(200, resp.status_code)
|
||||
else:
|
||||
encoded_url = urlencode(urlencode(url))
|
||||
redirection_url = "/login?next={}".format(encoded_url)
|
||||
self.assertRedirects(resp, redirection_url)
|
||||
|
||||
def test_get_partition_sets(self):
|
||||
"""The list of all partition sets can be fetched by everyone"""
|
||||
for _, client in self.client_matrix:
|
||||
resp = client.get("/partitions/")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
def test_get_partitions(self):
|
||||
"""
|
||||
Only ernesto members can see the partitions inside of a partition set
|
||||
"""
|
||||
url = "/partitions/{}/{}".format(self.pset.nom, self.pset.auteur)
|
||||
self._get_restricted_page(url)
|
||||
|
||||
def test_see(self):
|
||||
"""Only ernesto members can see partitions"""
|
||||
part = self.pset.partition_set.first()
|
||||
url = "/partitions/{}/{}/see/{}".format(
|
||||
self.pset.nom, self.pset.auteur, part.id
|
||||
)
|
||||
self._get_restricted_page(url)
|
||||
|
||||
def test_download(self):
|
||||
"""Only ernesto members can download partitions"""
|
||||
part = self.pset.partition_set.first()
|
||||
url = "/partitions/{}/{}/{}".format(self.pset.nom, self.pset.auteur, part.id)
|
||||
self._get_restricted_page(url)
|
||||
|
||||
def test_new(self):
|
||||
"""Only ernesto members can create partiton sets"""
|
||||
url = "/partitions/new"
|
||||
self._get_restricted_page(url)
|
14
instruments/urls.py
Normal file
14
instruments/urls.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
app_name = "instruments"
|
||||
urlpatterns = [
|
||||
path("", views.ListeInstru.as_view(), name="liste"),
|
||||
path("delete/<int:pk>", views.DeleteInstru.as_view(), name="delete_instru"),
|
||||
path("delete_reparation/<int:pk>", views.DeleteRep.as_view(), name="delete_rep"),
|
||||
path("new", views.CreateInstru.as_view(), name="ajouter_instru"),
|
||||
path("new_rep/<int:pk>", views.CreateRep.as_view(), name="ajouter_rep"),
|
||||
path("update_rep/<int:pk>", views.UpdateRep.as_view(), name="update_rep"),
|
||||
path("fiche/<int:pk>", views.FicheInstru.as_view(), name="fiche_instru"),
|
||||
]
|
119
instruments/views.py
Normal file
119
instruments/views.py
Normal file
|
@ -0,0 +1,119 @@
|
|||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import (CreateView, DeleteView, TemplateView,
|
||||
UpdateView)
|
||||
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from gestion.models import Photo
|
||||
from instruments.forms import ChefEditInstrumentForm, ChefReparationForm
|
||||
from instruments.models import Instrument, Reparation
|
||||
|
||||
|
||||
class ListeInstru(LoginRequiredMixin, TemplateView):
|
||||
template_name = "instruments/instru_liste.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["photo"] = Photo.objects.filter(cat="instru").order_by("?").first()
|
||||
context["instrus_dispo"] = (
|
||||
Instrument.objects.all().order_by("type").filter(statut="Disponible")
|
||||
)
|
||||
context["instrus_prete"] = (
|
||||
Instrument.objects.all().order_by("type").filter(statut="Prêté")
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
class CreateInstru(ChefRequiredMixin, CreateView):
|
||||
model = Instrument
|
||||
fields = ["owner", "etat", "type", "marque", "model", "serial", "annee", "prix"]
|
||||
template_name = "instruments/create_instru.html"
|
||||
success_url = reverse_lazy("instruments:liste")
|
||||
|
||||
|
||||
class CreateRep(ChefRequiredMixin, TemplateView):
|
||||
form_class = ChefReparationForm
|
||||
template_name = "instruments/create_rep.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["form"] = self.form_class()
|
||||
context["pk"] = self.kwargs["pk"]
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.form_class(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
rep = form.save(commit=False)
|
||||
rep.instru = get_object_or_404(Instrument, id=self.kwargs["pk"])
|
||||
rep.save()
|
||||
return redirect("instruments:fiche_instru", pk=self.kwargs["pk"])
|
||||
else:
|
||||
context = self.get_context_data()
|
||||
context["form"] = form
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class DeleteRep(ChefRequiredMixin, TemplateView):
|
||||
model = Reparation
|
||||
template_name = "instruments/delete_instru.html"
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
rep = get_object_or_404(self.model, id=self.kwargs["pk"])
|
||||
id_instru = rep.instru.id
|
||||
rep.delete()
|
||||
return redirect("instruments:fiche_instru", pk=id_instru)
|
||||
|
||||
|
||||
class FicheInstru(LoginRequiredMixin, TemplateView):
|
||||
|
||||
template_name = "instruments/update_instru.html"
|
||||
model = Instrument
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
instru = get_object_or_404(self.model, id=self.kwargs["pk"])
|
||||
reparations = Reparation.objects.filter(instru=self.kwargs["pk"]).order_by(
|
||||
"-date"
|
||||
)
|
||||
|
||||
form = ChefEditInstrumentForm(instance=instru)
|
||||
infos = mark_safe(instru.infos)
|
||||
infos_en = mark_safe(instru.infos_en)
|
||||
|
||||
context["reparations"] = reparations
|
||||
context["instru"] = instru
|
||||
context["form"] = form
|
||||
context["infos"] = infos
|
||||
context["infos_en"] = infos_en
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
instru = get_object_or_404(self.model, id=self.kwargs["pk"])
|
||||
form = ChefEditInstrumentForm(request.POST, instance=instru)
|
||||
if request.user.profile.is_chef:
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
context = self.get_context_data()
|
||||
context["form"] = form
|
||||
return render(request, self.template_name, context)
|
||||
|
||||
|
||||
class UpdateRep(ChefRequiredMixin, UpdateView):
|
||||
model = Reparation
|
||||
fields = ["date", "description", "description_en", "prix", "lieux"]
|
||||
template_name = "instruments/update_rep.html"
|
||||
|
||||
def get_success_url(self):
|
||||
id_instru = get_object_or_404(Reparation, id=self.kwargs["pk"]).instru.id
|
||||
return reverse_lazy("instruments:fiche_instru", kwargs={"pk": id_instru})
|
||||
|
||||
|
||||
class DeleteInstru(ChefRequiredMixin, DeleteView):
|
||||
model = Instrument
|
||||
template_name = "instruments/delete_instru.html"
|
||||
success_url = reverse_lazy("instruments:liste")
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -3,10 +3,7 @@ import os
|
|||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault(
|
||||
"DJANGO_SETTINGS_MODULE",
|
||||
"Ernestophone.settings.local"
|
||||
)
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ernestophone.settings.local")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class PadsConfig(AppConfig):
|
||||
name = 'pads'
|
||||
name = "pads"
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
from django import forms
|
||||
|
||||
from pads.models import Pad
|
||||
|
||||
|
||||
class PadForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Pad
|
||||
fields = ('nom', 'url',)
|
||||
fields = (
|
||||
"nom",
|
||||
"url",
|
||||
)
|
||||
|
|
|
@ -6,20 +6,27 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Pad',
|
||||
name="Pad",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('nom', models.CharField(max_length=100)),
|
||||
('url', models.URLField()),
|
||||
('date', models.DateField(verbose_name='Créé le')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("nom", models.CharField(max_length=100)),
|
||||
("url", models.URLField()),
|
||||
("date", models.DateField(verbose_name="Créé le")),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Pad',
|
||||
"verbose_name": "Pad",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -6,13 +6,13 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pads', '0001_initial'),
|
||||
("pads", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='pad',
|
||||
name='date',
|
||||
field=models.DateField(verbose_name='Cree le'),
|
||||
model_name="pad",
|
||||
name="date",
|
||||
field=models.DateField(verbose_name="Cree le"),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -11,4 +11,6 @@ class Pad(models.Model):
|
|||
|
||||
class Meta:
|
||||
verbose_name = "Pad"
|
||||
|
||||
|
||||
# Create your models here.
|
||||
|
|
|
@ -2,7 +2,6 @@ from django.urls import path
|
|||
|
||||
from pads import views
|
||||
|
||||
|
||||
app_name = "pads"
|
||||
urlpatterns = [
|
||||
path("", views.PadList.as_view(), name="list"),
|
||||
|
|
|
@ -3,6 +3,7 @@ from django.http import HttpResponseRedirect
|
|||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
|
||||
|
||||
from gestion.mixins import ChefRequiredMixin
|
||||
from pads.models import Pad
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
|
||||
from .models import Category,PartitionSet
|
||||
from .models import Category, PartitionSet
|
||||
|
||||
admin.site.register(Category)
|
||||
admin.site.register(PartitionSet)
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class PartitionsConfig(AppConfig):
|
||||
name = 'partitions'
|
||||
name = "partitions"
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
from django.contrib.auth.decorators import user_passes_test
|
||||
|
||||
|
||||
def is_chef(user):
|
||||
try:
|
||||
profile = user.profile
|
||||
return profile.is_chef
|
||||
except:
|
||||
return False
|
||||
|
||||
chef_required = user_passes_test(lambda u: is_chef(u))
|
|
@ -1,5 +1,7 @@
|
|||
from django import forms
|
||||
|
||||
from .models import PartitionSet
|
||||
|
||||
|
||||
class UploadFileForm(forms.Form):
|
||||
title = forms.CharField(max_length=50)
|
||||
|
@ -9,3 +11,9 @@ class UploadFileForm(forms.Form):
|
|||
class UploadMorceauForm(forms.Form):
|
||||
titre = forms.CharField(max_length=100)
|
||||
auteur = forms.CharField(max_length=100)
|
||||
|
||||
|
||||
class ChefEditMorceauForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = PartitionSet
|
||||
fields = ("category", "download_unlogged", "infos", "url", "infos_en")
|
||||
|
|
|
@ -6,31 +6,66 @@ from django.db import migrations, models
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Partition',
|
||||
name="Partition",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('nom', models.CharField(max_length=100)),
|
||||
('part', models.FileField(upload_to='partitions/')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("nom", models.CharField(max_length=100)),
|
||||
("part", models.FileField(upload_to="partitions/")),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='PartitionSet',
|
||||
name="PartitionSet",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
|
||||
('nom', models.CharField(max_length=100)),
|
||||
('auteur', models.CharField(max_length=100)),
|
||||
('category', models.CharField(max_length=8, choices=[('active', 'Actif'), ('incoming', 'À venir'), ('old', 'Archive'), ('optional', 'Optionnel')], default='incoming', verbose_name='Types de partitions')),
|
||||
('infos', models.TextField(blank=True, verbose_name='Infos utiles', null=True)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
verbose_name="ID",
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("nom", models.CharField(max_length=100)),
|
||||
("auteur", models.CharField(max_length=100)),
|
||||
(
|
||||
"category",
|
||||
models.CharField(
|
||||
max_length=8,
|
||||
choices=[
|
||||
("active", "Actif"),
|
||||
("incoming", "À venir"),
|
||||
("old", "Archive"),
|
||||
("optional", "Optionnel"),
|
||||
],
|
||||
default="incoming",
|
||||
verbose_name="Types de partitions",
|
||||
),
|
||||
),
|
||||
(
|
||||
"infos",
|
||||
models.TextField(
|
||||
blank=True, verbose_name="Infos utiles", null=True
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='partition',
|
||||
name='morceau',
|
||||
field=models.ForeignKey(to='partitions.PartitionSet', on_delete=models.CASCADE),
|
||||
model_name="partition",
|
||||
name="morceau",
|
||||
field=models.ForeignKey(
|
||||
to="partitions.PartitionSet", on_delete=models.CASCADE
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +1,21 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def create_categories(apps, schema_editor):
|
||||
# Insert the previously hardcoded categories in the database
|
||||
Category = apps.get_model("partitions", "Category")
|
||||
Category.objects.bulk_create([
|
||||
Category(name="Partitions actives", order=1),
|
||||
Category(name="Partitions optionnelles", order=2),
|
||||
Category(name="Partitions à venir", order=3),
|
||||
Category(name="Archives", order=4)
|
||||
])
|
||||
Category.objects.bulk_create(
|
||||
[
|
||||
Category(name="Partitions actives", order=1),
|
||||
Category(name="Partitions optionnelles", order=2),
|
||||
Category(name="Partitions à venir", order=3),
|
||||
Category(name="Archives", order=4),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def set_new_categories(apps, schema_editor):
|
||||
|
@ -24,7 +26,7 @@ def set_new_categories(apps, schema_editor):
|
|||
"active": assoc_list[0],
|
||||
"incoming": assoc_list[2],
|
||||
"old": assoc_list[3],
|
||||
"optional": assoc_list[1]
|
||||
"optional": assoc_list[1],
|
||||
}
|
||||
for par_set in PartitionSet.objects.all():
|
||||
par_set.category = mapping[par_set.category_old]
|
||||
|
@ -39,7 +41,7 @@ def reset_old_categories(apps, schema_editor):
|
|||
assoc_list[0][1]: "active",
|
||||
assoc_list[2][1]: "incoming",
|
||||
assoc_list[3][1]: "old",
|
||||
assoc_list[1][1]: "optional"
|
||||
assoc_list[1][1]: "optional",
|
||||
}
|
||||
for par_set in PartitionSet.objects.all():
|
||||
par_set.category_old = mapping[par_set.category]
|
||||
|
@ -49,29 +51,39 @@ def reset_old_categories(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('partitions', '0001_initial'),
|
||||
("partitions", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
name="Category",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, serialize=False, auto_created=True)),
|
||||
('name', models.CharField(max_length=127)),
|
||||
('order', models.IntegerField(verbose_name='order')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID",
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
auto_created=True,
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=127)),
|
||||
("order", models.IntegerField(verbose_name="order")),
|
||||
],
|
||||
options={'verbose_name': 'catégorie', 'verbose_name_plural': 'catégories'},
|
||||
options={"verbose_name": "catégorie", "verbose_name_plural": "catégories"},
|
||||
),
|
||||
migrations.RunPython(create_categories, migrations.RunPython.noop),
|
||||
migrations.RenameField(model_name="partitionset", old_name="category", new_name="category_old"),
|
||||
migrations.RenameField(
|
||||
model_name="partitionset", old_name="category", new_name="category_old"
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='partitionset',
|
||||
name='category',
|
||||
model_name="partitionset",
|
||||
name="category",
|
||||
field=models.ForeignKey(
|
||||
verbose_name='Type de partition',
|
||||
to='partitions.Category',
|
||||
verbose_name="Type de partition",
|
||||
to="partitions.Category",
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
default=1 # Dummy, will be set by the RunPython operation
|
||||
default=1, # Dummy, will be set by the RunPython operation
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
|
|
|
@ -1,47 +1,78 @@
|
|||
# Generated by Django 2.2.14 on 2020-07-16 17:49
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.expressions
|
||||
import django.db.models.functions.text
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('partitions', '0002_category'),
|
||||
("partitions", "0002_category"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='category',
|
||||
options={'ordering': ('order',), 'verbose_name': 'Categorie', 'verbose_name_plural': 'Categories'},
|
||||
name="category",
|
||||
options={
|
||||
"ordering": ("order",),
|
||||
"verbose_name": "Categorie",
|
||||
"verbose_name_plural": "Categories",
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='partition',
|
||||
options={'ordering': (django.db.models.expressions.CombinedExpression(django.db.models.expressions.Value('-'), '+', django.db.models.functions.text.Lower('nom')),), 'verbose_name': 'Morceau', 'verbose_name_plural': 'Morceaux'},
|
||||
name="partition",
|
||||
options={
|
||||
"ordering": (
|
||||
django.db.models.expressions.CombinedExpression(
|
||||
django.db.models.expressions.Value("-"),
|
||||
"+",
|
||||
django.db.models.functions.text.Lower("nom"),
|
||||
),
|
||||
),
|
||||
"verbose_name": "Morceau",
|
||||
"verbose_name_plural": "Morceaux",
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='partitionset',
|
||||
options={'ordering': (django.db.models.expressions.CombinedExpression(django.db.models.expressions.Value('-'), '+', django.db.models.functions.text.Lower('nom')),), 'verbose_name': 'Morceau', 'verbose_name_plural': 'Morceaux'},
|
||||
name="partitionset",
|
||||
options={
|
||||
"ordering": (
|
||||
django.db.models.expressions.CombinedExpression(
|
||||
django.db.models.expressions.Value("-"),
|
||||
"+",
|
||||
django.db.models.functions.text.Lower("nom"),
|
||||
),
|
||||
),
|
||||
"verbose_name": "Morceau",
|
||||
"verbose_name_plural": "Morceaux",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='category',
|
||||
name='nom_en',
|
||||
model_name="category",
|
||||
name="nom_en",
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='partitionset',
|
||||
name='infos_en',
|
||||
field=models.TextField(blank=True, null=True, verbose_name='Infos utiles en anglais'),
|
||||
model_name="partitionset",
|
||||
name="infos_en",
|
||||
field=models.TextField(
|
||||
blank=True, null=True, verbose_name="Infos utiles en anglais"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='partitionset',
|
||||
name='url',
|
||||
field=models.URLField(blank=True, help_text='Dans Youtube cliquer sur partager puis importer pour récuperer la bonne adresse', null=True, verbose_name="Url d'une video youtube"),
|
||||
model_name="partitionset",
|
||||
name="url",
|
||||
field=models.URLField(
|
||||
blank=True,
|
||||
help_text="Dans Youtube cliquer sur partager puis importer pour récuperer la bonne adresse",
|
||||
null=True,
|
||||
verbose_name="Url d'une video youtube",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='category',
|
||||
name='order',
|
||||
field=models.IntegerField(verbose_name='ordre'),
|
||||
model_name="category",
|
||||
name="order",
|
||||
field=models.IntegerField(verbose_name="ordre"),
|
||||
),
|
||||
]
|
||||
|
|
52
partitions/migrations/0004_auto_20210331_1350.py
Normal file
52
partitions/migrations/0004_auto_20210331_1350.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Generated by Django 2.2.17 on 2021-03-31 13:50
|
||||
|
||||
import django.db.models.functions.text
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("partitions", "0003_auto_20200716_1749"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="partition",
|
||||
options={
|
||||
"ordering": (django.db.models.functions.text.Lower("nom"),),
|
||||
"verbose_name": "Morceau",
|
||||
"verbose_name_plural": "Morceaux",
|
||||
},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name="partitionset",
|
||||
options={
|
||||
"ordering": (django.db.models.functions.text.Lower("nom"),),
|
||||
"verbose_name": "Morceau",
|
||||
"verbose_name_plural": "Morceaux",
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="partitionset",
|
||||
name="download_unlogged",
|
||||
field=models.CharField(
|
||||
choices=[("n", "Non"), ("o", "Oui")],
|
||||
default="n",
|
||||
max_length=1,
|
||||
verbose_name="Téléchargeable non connecté ?",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="partitionset",
|
||||
name="infos",
|
||||
field=models.TextField(blank=True, default="", verbose_name="Infos utiles"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="partitionset",
|
||||
name="infos_en",
|
||||
field=models.TextField(
|
||||
blank=True, default="", verbose_name="Infos utiles en anglais"
|
||||
),
|
||||
),
|
||||
]
|
|
@ -9,20 +9,21 @@ from django.utils.translation import gettext_lazy as _
|
|||
class Category(models.Model):
|
||||
name = models.CharField(max_length=127)
|
||||
order = models.IntegerField(verbose_name=_("ordre"))
|
||||
nom_en = models.CharField(max_length=100,null=True,blank=True)
|
||||
nom_en = models.CharField(max_length=100, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Categorie")
|
||||
verbose_name_plural = _("Categories")
|
||||
ordering = ('order',)
|
||||
ordering = ("order",)
|
||||
|
||||
|
||||
class Partition(models.Model):
|
||||
nom = models.CharField(max_length=100)
|
||||
part = models.FileField(upload_to="partitions/")
|
||||
morceau = models.ForeignKey('PartitionSet', on_delete=models.CASCADE)
|
||||
morceau = models.ForeignKey("PartitionSet", on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return self.nom
|
||||
|
@ -32,26 +33,40 @@ class Partition(models.Model):
|
|||
super(Partition, self).delete(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Morceau')
|
||||
verbose_name_plural = _('Morceaux')
|
||||
ordering = (Lower('nom'),)
|
||||
verbose_name = _("Morceau")
|
||||
verbose_name_plural = _("Morceaux")
|
||||
ordering = (Lower("nom"),)
|
||||
|
||||
|
||||
class PartitionSet(models.Model):
|
||||
nom = models.CharField(max_length=100)
|
||||
auteur = models.CharField(max_length=100)
|
||||
category = models.ForeignKey(
|
||||
Category,
|
||||
on_delete=models.PROTECT,
|
||||
verbose_name=_("Type de partition")
|
||||
Category, on_delete=models.PROTECT, verbose_name=_("Type de partition")
|
||||
)
|
||||
download_unlogged = models.CharField(
|
||||
_("Téléchargeable non connecté ?"),
|
||||
default="n",
|
||||
choices=[("n", _("Non")), ("o", _("Oui"))],
|
||||
max_length=1,
|
||||
)
|
||||
infos = models.TextField(_("Infos utiles"), null=False, blank=True, default="")
|
||||
infos_en = models.TextField(
|
||||
"Infos utiles en anglais", null=False, blank=True, default=""
|
||||
)
|
||||
url = models.URLField(
|
||||
_("Url d'une video youtube"),
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_(
|
||||
"Dans Youtube cliquer sur partager puis importer pour récuperer la bonne adresse"
|
||||
),
|
||||
)
|
||||
|
||||
infos = models.TextField(_("Infos utiles"), null=True, blank=True)
|
||||
infos_en = models.TextField("Infos utiles en anglais", null=True, blank=True)
|
||||
url = models.URLField(_("Url d'une video youtube"),null=True,blank=True, help_text= _("Dans Youtube cliquer sur partager puis importer pour récuperer la bonne adresse"))
|
||||
def __str__(self):
|
||||
return("%s - %s [%s]" % (self.nom, self.auteur, self.category))
|
||||
return "%s - %s [%s]" % (self.nom, self.auteur, self.category)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Morceau')
|
||||
verbose_name_plural = _('Morceaux')
|
||||
ordering = (Lower('nom'),)
|
||||
verbose_name = _("Morceau")
|
||||
verbose_name_plural = _("Morceaux")
|
||||
ordering = (Lower("nom"),)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<div class="inner">
|
||||
|
||||
<h4>{% trans "Confirmation de suppression" %}</h4>
|
||||
<p>{% trans "Voulez-vous vraiment supprimer cette partition ?" %}"</p>
|
||||
<p>{% trans "Voulez-vous vraiment supprimer cette partition ?" %}</p>
|
||||
<p><a href="{% url "partitions:delete" nom auteur id %}" class="button " >{% trans "Oui" %}</a></p>
|
||||
<p><a href="{% url "partitions:listepart" nom auteur %}" class="button alt" >{% trans "Retour à la liste des partitions" %}</a></p>
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
|
||||
<div class="box">{% autotranslate current_language infos infos_en %}</div>
|
||||
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue