Compare commits
79 commits
kerl/hotfi
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
98a6f98fda | ||
|
0aae767a3e | ||
|
d88768311e | ||
|
abc6c62a89 | ||
|
3e065f30c0 | ||
|
0ee798a64e | ||
|
1e8b993739 | ||
|
8398805b54 | ||
|
56d7490879 | ||
|
aa430fa4d2 | ||
|
5eb27e2171 | ||
|
31f6dc0961 | ||
|
764ffea61f | ||
|
7122c1c0c4 | ||
|
14e8d963d6 | ||
|
99e3438ead | ||
|
8a36b051a1 | ||
|
07d2e30b32 | ||
|
f88ed9ece6 | ||
|
5062a1e84e | ||
|
bc7430cb5d | ||
|
a7851ff123 | ||
|
50f888a07c | ||
|
343eaeb72e | ||
|
5aebd7bbe1 | ||
|
cb2577c04b | ||
|
bd42fe6fb9 | ||
|
bbff984513 | ||
|
9aed5d1758 | ||
|
f961722fa8 | ||
|
904f9fc74a | ||
|
280e0c625d | ||
|
8e6ca0cc86 | ||
|
0673e64083 | ||
|
82bc6c1e1b | ||
|
26bd2484a2 | ||
|
4d8b97c2cb | ||
|
b62d6f47a4 | ||
|
10159393f1 | ||
|
d217a74da5 | ||
|
079e0d1c3f | ||
|
45fdd4683b | ||
|
95cf80c234 | ||
|
e6f9173c62 | ||
|
149cc3b9f0 | ||
|
67cc2e658a | ||
|
dba4498cd7 | ||
|
9ea37de108 | ||
|
f48605210e | ||
|
eab532bf7e | ||
|
2633829f83 | ||
|
451a5cc83d | ||
|
d35772e116 | ||
|
bfb1f32132 | ||
|
ec0dbd2282 | ||
|
a5c1fb48fb | ||
|
a1a8a6d9aa | ||
|
d7fd5e5537 | ||
|
662764b581 | ||
|
2a33ba5cd1 | ||
|
0d443407a7 | ||
|
38b0f12201 | ||
|
80a7f99f28 | ||
|
fc4577c661 | ||
|
446acd1cb7 | ||
|
d1d0980778 | ||
|
e36311774b | ||
|
de50d9b187 | ||
|
b260ae8eb8 | ||
|
d6036766c7 | ||
|
9bd21283c0 | ||
|
ab120e5e63 | ||
|
7b19a581cf | ||
|
777bd930c6 | ||
|
0fbec31d14 | ||
|
6ba168d286 | ||
|
406f92098f | ||
|
5d1d3f8eff | ||
|
7a7979c91a |
179 changed files with 7126 additions and 3030 deletions
|
@ -1,4 +1,5 @@
|
|||
import os
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
try:
|
||||
|
@ -31,63 +32,61 @@ 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',
|
||||
"propositions",
|
||||
"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 +102,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,60 @@ 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("yearbook2021", gestion_views.YearBook2021.as_view(), name="yearbook2021"),
|
||||
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")),
|
||||
path("photos", gestion_views.PhotoList.as_view(), name="liste_photo"),
|
||||
path("add_photo", gestion_views.PhotoCreate.as_view(), name="add_photo"),
|
||||
path(
|
||||
"photo_edition/<int:pk>", gestion_views.PhotoUpdate.as_view(), name="edit_photo"
|
||||
),
|
||||
path(
|
||||
"photo_delete/<int:pk>",
|
||||
gestion_views.PhotoDelete.as_view(),
|
||||
name="delete_photo",
|
||||
),
|
||||
path("videos", gestion_views.VideoList.as_view(), name="liste_video"),
|
||||
path("add_video", gestion_views.VideoCreate.as_view(), name="add_video"),
|
||||
path(
|
||||
"video_edition/<int:pk>", gestion_views.VideoUpdate.as_view(), name="edit_video"
|
||||
),
|
||||
path(
|
||||
"video_delete/<int:pk>",
|
||||
gestion_views.VideoDelete.as_view(),
|
||||
name="delete_video",
|
||||
),
|
||||
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é",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
23
actu/migrations/0002_actu_rainbow.py
Normal file
23
actu/migrations/0002_actu_rainbow.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 2.2.25 on 2022-01-06 12:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("actu", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="actu",
|
||||
name="rainbow",
|
||||
field=models.CharField(
|
||||
choices=[("y", "Oui"), ("n", "Non")],
|
||||
default="n",
|
||||
max_length=1,
|
||||
verbose_name="Actu en arc-en-ciel (ne pas mettre d'émoji, il prennent aussi la couleur et c'est moche)",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1,14 +1,26 @@
|
|||
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"))
|
||||
rainbow = models.CharField(
|
||||
verbose_name=_(
|
||||
"Actu en arc-en-ciel (ne pas mettre d'émoji, il prennent aussi la couleur et c'est moche)"
|
||||
),
|
||||
max_length=1,
|
||||
choices=(("y", "Oui"), ("n", "Non")),
|
||||
default="n",
|
||||
blank=False,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Actualité")
|
||||
verbose_name_plural = _("Actualités")
|
||||
ordering = ('order',)
|
||||
ordering = ("order",)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -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", "rainbow"]
|
||||
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", "rainbow"]
|
||||
template_name = "actu/update_actu.html"
|
||||
success_url = reverse_lazy("actu:liste")
|
||||
|
||||
|
|
|
@ -1,6 +1,28 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Event, Participants
|
||||
|
||||
from .models import Event
|
||||
|
||||
class ParticipantsAdmin(admin.ModelAdmin):
|
||||
fields = [
|
||||
"event",
|
||||
"participant",
|
||||
"reponse",
|
||||
"instrument",
|
||||
"instrument_autre",
|
||||
"dont_play_main",
|
||||
"details",
|
||||
"creationDate",
|
||||
"updateDate",
|
||||
]
|
||||
readonly_fields = ["creationDate", "updateDate"]
|
||||
list_display = ["participant", "event", "reponse", "creationDate", "updateDate"]
|
||||
def has_add_permission(self, req):
|
||||
return False
|
||||
def has_change_permission(self,obj, change=False):
|
||||
return False
|
||||
|
||||
|
||||
# Add event by admin page return a 502 error
|
||||
admin.site.register(Event)
|
||||
admin.site.register(Participants, ParticipantsAdmin)
|
||||
|
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
|||
|
||||
|
||||
class CalendrierConfig(AppConfig):
|
||||
name = 'calendrier'
|
||||
name = "calendrier"
|
||||
|
|
|
@ -1,44 +1,49 @@
|
|||
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 href="/agenda/' + '%s"' % ev.id)
|
||||
if ev.calendrier == "C":
|
||||
body.append('style="color:#160083">' + esc(ev.nom))
|
||||
elif ev.calendrier == "D":
|
||||
body.append('style="color:#770083">' + esc(ev.nom))
|
||||
else:
|
||||
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", " ")
|
||||
|
||||
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,65 @@
|
|||
from django import forms
|
||||
from calendrier.models import Event, Participants
|
||||
from gestion.models import ErnestoUser
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from gestion.models import ErnestoUser
|
||||
|
||||
from calendrier.models import Event, Participants
|
||||
|
||||
|
||||
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",
|
||||
"dont_play_main",
|
||||
"instrument",
|
||||
"instrument_autre",
|
||||
)
|
||||
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",
|
||||
),
|
||||
),
|
||||
]
|
28
calendrier/migrations/0004_auto_20210606_1640.py
Normal file
28
calendrier/migrations/0004_auto_20210606_1640.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 2.2.17 on 2021-06-06 16:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("calendrier", "0003_auto_20210427_1834"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="participants",
|
||||
name="dont_play_main",
|
||||
field=models.CharField(
|
||||
choices=[("Non", "Non"), ("Oui", "Oui")],
|
||||
default="Non",
|
||||
max_length=3,
|
||||
verbose_name="Je veux jouer d'un instrument different de mon instrument principal:",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="participants",
|
||||
name="instrument",
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
]
|
46
calendrier/migrations/0005_auto_20210726_0949.py
Normal file
46
calendrier/migrations/0005_auto_20210726_0949.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
# Generated by Django 2.2.24 on 2021-07-26 07:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("calendrier", "0004_auto_20210606_1640"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
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"),
|
||||
("C", "Visible seulement par les cheff·e·s"),
|
||||
("D", "Visible seulement par les cheff·e·s et sur l'agenda public"),
|
||||
],
|
||||
default="F",
|
||||
max_length=1,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="event",
|
||||
name="desc_users",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name="Infos (visible seulement des fanfaron·ne·s)",
|
||||
),
|
||||
),
|
||||
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",
|
||||
),
|
||||
),
|
||||
]
|
41
calendrier/migrations/0006_auto_20210929_1629.py
Normal file
41
calendrier/migrations/0006_auto_20210929_1629.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 2.2.24 on 2021-09-29 14:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("calendrier", "0005_auto_20210726_0949"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="participants",
|
||||
name="instrument_autre",
|
||||
field=models.CharField(blank=True, max_length=50, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="participants",
|
||||
name="instrument",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
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"),
|
||||
],
|
||||
max_length=50,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
]
|
31
calendrier/migrations/0007_auto_20220314_2320.py
Normal file
31
calendrier/migrations/0007_auto_20220314_2320.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
# Generated by Django 2.2.25 on 2022-03-14 23:20
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("calendrier", "0006_auto_20210929_1629"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="participants",
|
||||
name="creationDate",
|
||||
field=models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
default=django.utils.timezone.now,
|
||||
verbose_name="Date de création",
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="participants",
|
||||
name="updateDate",
|
||||
field=models.DateTimeField(
|
||||
auto_now=True, verbose_name="Dernière mise à jour"
|
||||
),
|
||||
),
|
||||
]
|
17
calendrier/migrations/0008_auto_20220322_1454.py
Normal file
17
calendrier/migrations/0008_auto_20220322_1454.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2.27 on 2022-03-22 13:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('calendrier', '0007_auto_20220314_2320'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddConstraint(
|
||||
model_name='participants',
|
||||
constraint=models.UniqueConstraint(fields=('event', 'participant'), name='reponse unique aux event'),
|
||||
),
|
||||
]
|
|
@ -1,54 +1,82 @@
|
|||
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 INSTRU_CHOICES, 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")),
|
||||
("C", _("Visible seulement par les cheff·e·s")),
|
||||
("D", _("Visible seulement par les cheff·e·s et sur l'agenda public")),
|
||||
]
|
||||
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
|
||||
)
|
||||
instrument = models.CharField(
|
||||
max_length=50, blank=True, null=True, choices=INSTRU_CHOICES
|
||||
)
|
||||
instrument_autre = models.CharField(max_length=50, blank=True, null=True)
|
||||
dont_play_main = models.CharField(
|
||||
_("Je veux jouer d'un instrument different de mon instrument principal:"),
|
||||
default="Non",
|
||||
null=False,
|
||||
max_length=3,
|
||||
choices=[("Non", _("Non")), ("Oui", _("Oui"))],
|
||||
)
|
||||
details = models.CharField(max_length=50, blank=True)
|
||||
creationDate = models.DateTimeField(
|
||||
auto_now_add=True, verbose_name=_("Date de création")
|
||||
)
|
||||
updateDate = models.DateTimeField(
|
||||
auto_now=True, verbose_name=_("Dernière mise à jour")
|
||||
)
|
||||
class Meta:
|
||||
constraints = [ models.UniqueConstraint(fields=['event', 'participant'], name='reponse unique aux event') ]
|
||||
|
|
38
calendrier/static/css/add2calendar.css
Normal file
38
calendrier/static/css/add2calendar.css
Normal file
|
@ -0,0 +1,38 @@
|
|||
.a2cldr {
|
||||
height: 46px;
|
||||
width: 246px;
|
||||
position: relative;
|
||||
color: #032c53;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.a2cldr.active .a2cldr-list {
|
||||
display: block;
|
||||
}
|
||||
.a2cldr-list {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 0 12px;
|
||||
display: none;
|
||||
background-color: #000;
|
||||
box-shadow: 0px 8px 20px 0px #bababa;
|
||||
}
|
||||
.a2cldr-item {
|
||||
list-style: none;
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px solid #f3f3f3;
|
||||
}
|
||||
.a2cldr-item a {
|
||||
color: #032c53;
|
||||
text-decoration: none;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
.a2cldr-item a:hover {
|
||||
color: #032c53;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.a2cldr-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
683
calendrier/static/js/add2calendar.js
Normal file
683
calendrier/static/js/add2calendar.js
Normal file
|
@ -0,0 +1,683 @@
|
|||
/* global module */
|
||||
// prefix: a2cldr
|
||||
|
||||
var Add2Calendar = function(eventData) {
|
||||
|
||||
/*================================================================ Util
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check if the element has this class name
|
||||
*
|
||||
* @param {[type]} ele
|
||||
* @param {String} cls
|
||||
* @return {Boolean}
|
||||
*/
|
||||
this.hasClass = function(ele, cls) {
|
||||
return (' ' + ele.className + ' ').indexOf(' ' + cls + ' ') > -1;
|
||||
};
|
||||
|
||||
this.mergeObj = function(obj1, obj2) {
|
||||
var result = {}
|
||||
|
||||
for (var attr1 in obj1) { result[attr1] = obj1[attr1]; }
|
||||
for (var attr2 in obj2) { result[attr2] = obj2[attr2]; }
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* @see https://stackoverflow.com/questions/2998784/how-to-output-numbers-with-leading-zeros-in-javascript
|
||||
* @param {Number} number
|
||||
* @param {Number} size
|
||||
*/
|
||||
this.pad = function(number, size) {
|
||||
var num = number.toString();
|
||||
while (num.length < size) num = "0" + num;
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* formatTime
|
||||
*
|
||||
* @todo change naming
|
||||
* @param {Date} date
|
||||
* @return {string} e.g. "20191223T110000Z", "20191223T230000Z"
|
||||
*/
|
||||
this.formatTime = function(date) {
|
||||
return date.toISOString().replace(/-|:|\.\d+/g, '');
|
||||
};
|
||||
|
||||
/**
|
||||
* [formatTime2 description]
|
||||
* this method ignore timezone
|
||||
*
|
||||
* @see https://stackoverflow.com/questions/43670062/get-iso-string-from-a-date-without-time-zone
|
||||
* @todo change naming
|
||||
* @param {Date} date
|
||||
* @return {string} e.g. "20191223", "20191224"
|
||||
*/
|
||||
this.formatTime2 = function(date) {
|
||||
return this.pad(date.getFullYear(), 4) + this.pad(date.getMonth() + 1, 2) + this.pad(date.getDate(), 2)
|
||||
};
|
||||
|
||||
/**
|
||||
* [isValidEventData description]
|
||||
* UNUSED, UNCOMPLETE
|
||||
* TODO
|
||||
* - validate `eventData`
|
||||
* - require only `start`
|
||||
* - validate both single and multi
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/5812220/how-to-validate-a-date
|
||||
* @see http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
|
||||
*
|
||||
* @param {[type]} args [description]
|
||||
* @return {Boolean} [description]
|
||||
*/
|
||||
this.isValidEventData = function(eventData) {
|
||||
if (this.isSingleEvent) {
|
||||
// HACK
|
||||
return true;
|
||||
|
||||
} else {
|
||||
if (eventData.length > 0) {
|
||||
// HACK
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
this.isObjectType = function(obj, type) {
|
||||
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
|
||||
};
|
||||
|
||||
/**
|
||||
* [isDateObject description]
|
||||
* UNUSED
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/643782/how-to-check-whether-an-object-is-a-date
|
||||
*
|
||||
* @param {[type]} obj [description]
|
||||
* @return {Boolean} [description]
|
||||
*/
|
||||
this.isDateObject = function(obj) {
|
||||
return this.isObjectType(obj, 'Date');
|
||||
};
|
||||
|
||||
this.isArray = function(obj) {
|
||||
return this.isObjectType(obj, 'Array');
|
||||
};
|
||||
|
||||
this.isFunc = function(obj) {
|
||||
return this.isObjectType(obj, 'Function');
|
||||
};
|
||||
|
||||
/**
|
||||
* [serialize description]
|
||||
* Object to query string (encode)
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/1714786/querystring-encoding-of-a-javascript-object
|
||||
*
|
||||
* @param {[type]} obj [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
this.serialize = function(obj) {
|
||||
var str = [];
|
||||
for (var p in obj) {
|
||||
// eslint-disable-next-line
|
||||
if (obj.hasOwnProperty(p)) {
|
||||
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
|
||||
}
|
||||
}
|
||||
|
||||
return str.join('&');
|
||||
};
|
||||
|
||||
/**
|
||||
* [replaceSpecialCharacterAndSpaceWithHyphen description]
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/18936483/regex-for-replacing-all-special-characters-and-spaces-in-a-string-with-hyphens
|
||||
*
|
||||
* @param {[type]} str [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
this.replaceSpecialCharacterAndSpaceWithHyphen = function(str) {
|
||||
// eslint-disable-next-line
|
||||
return str.replace(/([~!@#$%^&*()_+=`{}\[\]\|\\:;'<>,.\/? ])+/g, '-').replace(/^(-)+|(-)+$/g,'');
|
||||
};
|
||||
|
||||
this.getLinkHtml = function(text, url, customClass, isEnableDownloadAttr, uniqueId) {
|
||||
if (typeof isEnableDownloadAttr === 'undefined') { isEnableDownloadAttr = false; }
|
||||
if (typeof uniqueId === 'undefined') { uniqueId = this.getCurrentUtcTimestamp(); }
|
||||
|
||||
var downloadAttr = '';
|
||||
|
||||
if (isEnableDownloadAttr) {
|
||||
var fileName = 'add2Calendar-' + this.replaceSpecialCharacterAndSpaceWithHyphen(text).toLowerCase() + '-' + uniqueId;
|
||||
|
||||
downloadAttr = ' download="' + fileName + '" ';
|
||||
}
|
||||
|
||||
return '<a ' + downloadAttr + ' class="' + customClass + '" target="_blank" href="' + url + '">' + text + '</a>';
|
||||
};
|
||||
|
||||
/**
|
||||
* [getLiHtml description]
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
||||
*
|
||||
* @param {[type]} text [description]
|
||||
* @param {[type]} url [description]
|
||||
* @param {[type]} customClass [description]
|
||||
* @param {Boolean} isEnableDownloadAttr [description]
|
||||
* @return {[type]} [description]
|
||||
*/
|
||||
this.getLiHtml = function(text, url, customClass, isEnableDownloadAttr, uniqueId) {
|
||||
var result = '',
|
||||
isValid = false;
|
||||
|
||||
// Validate
|
||||
if (url) {
|
||||
if (customClass === 'ical' || customClass === 'outlook') {
|
||||
isValid = true;
|
||||
|
||||
} else {
|
||||
var urlLength = url.length;
|
||||
|
||||
if (urlLength <= 20000) {
|
||||
isValid = true;
|
||||
|
||||
} else {
|
||||
console.log('Url longer than 2000');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
var linkHtml = this.getLinkHtml(text, url, 'icon-' + customClass, isEnableDownloadAttr, uniqueId);
|
||||
result = '<li class="a2cldr-item a2cldr-' + customClass + '">' + linkHtml + '</li>';
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
this.getCurrentUtcTimestamp = function() {
|
||||
return Date.now();
|
||||
};
|
||||
|
||||
/*================================================================ Google
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo take an arguments and return it instead of doing internal manipulation
|
||||
*/
|
||||
this.updateGoogleUrl = function() {
|
||||
if (this.isSingleEvent) {
|
||||
var startDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(this.eventData.start))
|
||||
: this.formatTime(new Date(this.eventData.start));
|
||||
var endDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(this.eventData.end))
|
||||
: this.formatTime(new Date(this.eventData.end));
|
||||
|
||||
var googleArgs = {
|
||||
'text' : (this.eventData.title || ''),
|
||||
'dates' : startDate + '/' + endDate,
|
||||
'location' : (this.eventData.location || ''),
|
||||
'details' : (this.eventData.description || ''),
|
||||
'ctz' : (this.eventData.timezone || ''),
|
||||
'locale' : (this.eventData.locale || ''),
|
||||
'sprop' : ''
|
||||
};
|
||||
|
||||
this.googleUrl = 'https://www.google.com/calendar/render?action=TEMPLATE&' + this.serialize(googleArgs);
|
||||
}
|
||||
|
||||
return this.googleUrl;
|
||||
}
|
||||
|
||||
this.getGoogleUrl = function() {
|
||||
return this.googleUrl;
|
||||
};
|
||||
|
||||
this.getGoogleLiHtml = function() {
|
||||
return this.getLiHtml('Google', this.googleUrl, 'google');
|
||||
};
|
||||
|
||||
this.openGoogle = function() {
|
||||
window.open(this.googleUrl);
|
||||
};
|
||||
|
||||
/*================================================================ iCal / Outlook
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo take an arguments and return it instead of doing internal manipulation
|
||||
*/
|
||||
this.updateICalUrl = function() {
|
||||
var url = typeof document !== 'undefined' ? document.URL : ''; // todo fix it
|
||||
var startDate = ''
|
||||
var endDate = ''
|
||||
|
||||
if (this.isSingleEvent) {
|
||||
startDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(this.eventData.start))
|
||||
: this.formatTime(new Date(this.eventData.start));
|
||||
endDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(this.eventData.end))
|
||||
: this.formatTime(new Date(this.eventData.end));
|
||||
|
||||
this.iCalUrl = encodeURI(
|
||||
'data:text/calendar;charset=utf8,' +
|
||||
[
|
||||
'BEGIN:VCALENDAR',
|
||||
'VERSION:2.0',
|
||||
'BEGIN:VEVENT',
|
||||
'URL:' + url,
|
||||
'DTSTART:' + startDate,
|
||||
'DTEND:' + endDate,
|
||||
'SUMMARY:' + (this.eventData.title || ''),
|
||||
'DESCRIPTION:' + (this.eventData.description || ''),
|
||||
'LOCATION:' + (this.eventData.location || ''),
|
||||
'END:VEVENT',
|
||||
'END:VCALENDAR'
|
||||
].join('\n')
|
||||
);
|
||||
|
||||
} else {
|
||||
var i = 0,
|
||||
n = this.eventData.length;
|
||||
|
||||
var iCalData = [];
|
||||
for (i = 0; i < n; i++) {
|
||||
var data = this.eventData[i];
|
||||
startDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(data.start))
|
||||
: this.formatTime(new Date(data.start));
|
||||
endDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(data.end))
|
||||
: this.formatTime(new Date(data.end));
|
||||
|
||||
var tmp = [
|
||||
'BEGIN:VEVENT',
|
||||
'URL:' + url,
|
||||
'DTSTART:' + startDate,
|
||||
'DTEND:' + endDate,
|
||||
'SUMMARY:' + (data.title || ''),
|
||||
'DESCRIPTION:' + (data.description || ''),
|
||||
'LOCATION:' + (data.location || ''),
|
||||
'END:VEVENT',
|
||||
];
|
||||
|
||||
iCalData = iCalData.concat(tmp);
|
||||
}
|
||||
|
||||
var iCalDataBegin = [
|
||||
'BEGIN:VCALENDAR',
|
||||
'VERSION:2.0'
|
||||
];
|
||||
var iCalDataAfter = [
|
||||
'END:VCALENDAR'
|
||||
];
|
||||
iCalData = iCalDataBegin.concat(iCalData, iCalDataAfter).join('\n');
|
||||
|
||||
this.iCalUrl = encodeURI('data:text/calendar;charset=utf8,' + iCalData);
|
||||
}
|
||||
|
||||
// data is truncated when it contains a "#" character
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
|
||||
// https://en.wikipedia.org/wiki/Percent-encoding
|
||||
this.iCalUrl = this.iCalUrl.replace(/#/g, '%23');
|
||||
|
||||
return this.iCalUrl;
|
||||
};
|
||||
|
||||
this.getICalUrl = function() {
|
||||
return this.iCalUrl;
|
||||
};
|
||||
|
||||
this.getICalLiHtml = function() {
|
||||
return this.getLiHtml('iCal', this.iCalUrl, 'ical', true);
|
||||
};
|
||||
|
||||
this.openICal = function() {
|
||||
window.open(this.iCalUrl);
|
||||
};
|
||||
|
||||
// Same as getICalUrl
|
||||
this.getOutlookUrl = function() {
|
||||
return this.iCalUrl;
|
||||
};
|
||||
|
||||
// Same as getICalLiHtml
|
||||
this.getOutlookLiHtml = function() {
|
||||
return this.getLiHtml('Outlook', this.iCalUrl, 'outlook', true);
|
||||
};
|
||||
|
||||
// Same as openICal
|
||||
this.openOutlook = function() {
|
||||
window.open(this.iCalUrl);
|
||||
};
|
||||
|
||||
/*================================================================ Outlook Online
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo complete it
|
||||
* @todo take an arguments and return it instead of doing internal manipulation
|
||||
*/
|
||||
this.updateOutlookOnlineUrl = function() {
|
||||
if (this.isSingleEvent) {
|
||||
var startDate = new Date(this.eventData.start),
|
||||
endDate = new Date(this.eventData.end);
|
||||
|
||||
var startDateTimezoneOffset = startDate.getTimezoneOffset();
|
||||
startDate.setMinutes(startDate.getMinutes() - 2 * startDateTimezoneOffset); // HACK
|
||||
|
||||
var endDateTimezoneOffset = endDate.getTimezoneOffset();
|
||||
endDate.setMinutes(endDate.getMinutes() - endDateTimezoneOffset); // HACK
|
||||
|
||||
startDate = this.formatTime(startDate).slice(0, -1);
|
||||
endDate = this.formatTime(endDate).slice(0, -1);
|
||||
|
||||
var outlookOnlineArgs = {
|
||||
'summary' : (this.eventData.title || ''),
|
||||
'dtstart' : startDate,
|
||||
'dtend' : endDate,
|
||||
'location' : (this.eventData.location || ''),
|
||||
'description' : (this.eventData.description || '')
|
||||
};
|
||||
|
||||
this.outlookOnlineUrl = 'http://calendar.live.com/calendar/calendar.aspx?rru=addevent&' + this.serialize(outlookOnlineArgs);
|
||||
}
|
||||
|
||||
return this.outlookOnlineUrl;
|
||||
};
|
||||
|
||||
this.getOutlookOnlineUrl = function() {
|
||||
return this.outlookOnlineUrl;
|
||||
};
|
||||
|
||||
this.getOutlookOnlineLiHtml = function() {
|
||||
return this.getLiHtml('Outlook Online', this.outlookOnlineUrl, 'outlook-online');
|
||||
};
|
||||
|
||||
this.openOutlookOnline = function() {
|
||||
window.open(this.outlookOnlineUrl);
|
||||
};
|
||||
|
||||
/*================================================================ Yahoo
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo take an arguments and return it instead of doing internal manipulation
|
||||
*/
|
||||
this.updateYahooUrl = function() {
|
||||
if (this.isSingleEvent) {
|
||||
var startDate = this.eventData.isAllDay
|
||||
? this.formatTime2(new Date(this.eventData.start))
|
||||
: this.formatTime(new Date(this.eventData.start))
|
||||
|
||||
// FIXED: Yahoo! calendar bug
|
||||
//
|
||||
// Yahoo! did calculate timezone for `start`
|
||||
// but they did not calculate timezone for `end`
|
||||
var tmp = new Date(this.eventData.end);
|
||||
var timezoneOffset = tmp.getTimezoneOffset();
|
||||
tmp.setMinutes(tmp.getMinutes() - timezoneOffset);
|
||||
var endDate = this.eventData.isAllDay
|
||||
? this.formatTime2(tmp)
|
||||
: this.formatTime(tmp)
|
||||
|
||||
var yahooArgs = {
|
||||
'view' : 'd',
|
||||
'type' : '20',
|
||||
'title' : (this.eventData.title || ''),
|
||||
'st' : startDate,
|
||||
'et' : endDate,
|
||||
// 'dur' : '',
|
||||
'in_loc' : (this.eventData.location || ''),
|
||||
'desc' : (this.eventData.description || '')
|
||||
};
|
||||
|
||||
this.yahooUrl = 'https://calendar.yahoo.com/?v=60&' + this.serialize(yahooArgs);
|
||||
}
|
||||
|
||||
return this.yahooUrl;
|
||||
};
|
||||
|
||||
this.getYahooUrl = function() {
|
||||
return this.yahooUrl;
|
||||
};
|
||||
|
||||
this.getYahooLiHtml = function() {
|
||||
return this.getLiHtml('Yahoo!', this.yahooUrl, 'yahoo');
|
||||
};
|
||||
|
||||
this.openYahoo = function() {
|
||||
window.open(this.yahooUrl);
|
||||
};
|
||||
|
||||
/*================================================================ Widget
|
||||
*/
|
||||
|
||||
this.getEventListHtml = function() {
|
||||
var html = '<ul class="a2cldr-list">';
|
||||
|
||||
html += this.getEventListItemsHtml();
|
||||
html += '</ul>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
this.getEventListItemsHtml = function() {
|
||||
var html = '';
|
||||
|
||||
html += this.getGoogleLiHtml();
|
||||
html += this.getICalLiHtml();
|
||||
html += this.getOutlookLiHtml();
|
||||
html += this.getOutlookOnlineLiHtml();
|
||||
html += this.getYahooLiHtml();
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
// UNUSED
|
||||
// QUITE DUPLICATE
|
||||
this.getEventNotFoundListHtml = function() {
|
||||
var html = '<ul class="a2cldr-list">';
|
||||
|
||||
html += this.getEventNotFoundListItemsHtml();
|
||||
html += '</ul>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
// UNUSED
|
||||
// QUITE DUPLICATE
|
||||
this.getEventNotFoundListItemsHtml = function() {
|
||||
var html = '';
|
||||
|
||||
html += '<li class="a2cldr-item a2cldr-not-found">';
|
||||
html += '<span class="not-found" href="javascript:;">Not Found</span>';
|
||||
html += '</li>';
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
this.getWidgetNode = function() {
|
||||
var html = '<button class="a2cldr-btn" type="button">';
|
||||
html += this.getWidgetBtnText();
|
||||
html += '</button>';
|
||||
html += this.getEventListHtml();
|
||||
|
||||
var result = document.createElement('div');
|
||||
result.innerHTML = html;
|
||||
result.className = this.textDomain;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
this.getWidgetBtnText = function() {
|
||||
var result = (this.option.buttonText)
|
||||
? this.option.buttonText
|
||||
: this.add2calendarBtnTextMap[this.option.lang];
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/*================================================================ API (Public)
|
||||
*/
|
||||
|
||||
this.createWidget = function(selector, cb) {
|
||||
this.selector = selector;
|
||||
this.eWidget = document.querySelector(selector);
|
||||
|
||||
// create and append into the DOM
|
||||
var node = this.getWidgetNode();
|
||||
this.eWidget.appendChild(node);
|
||||
|
||||
// bind an event
|
||||
this.eButton = document.querySelector(selector + ' > .a2cldr > .a2cldr-btn');
|
||||
this.bindClickEvent();
|
||||
|
||||
// callback
|
||||
if (this.isFunc(cb)) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
this.bindClickEvent = function() {
|
||||
var activeClassName = 'active';
|
||||
var self = this;
|
||||
var ele = this.eButton;
|
||||
|
||||
ele.onclick = function() {
|
||||
var parent = ele.parentNode;
|
||||
if (self.hasClass(parent, activeClassName)) {
|
||||
parent.classList.remove(activeClassName);
|
||||
} else {
|
||||
parent.classList.add(activeClassName);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.unBindClickEvent = function() {
|
||||
if (this.eButton && this.eButton.onclick) {
|
||||
this.eButton.onclick = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.setOption = function(option) {
|
||||
this.userOption = option;
|
||||
this.option = this.mergeObj(this.defaultOption, this.userOption);
|
||||
};
|
||||
|
||||
this.resetOption = function() {
|
||||
this.option = this.defaultOption;
|
||||
};
|
||||
|
||||
/*================================================================ API (Public) - In progress
|
||||
*/
|
||||
|
||||
this.update = function(eventData) {
|
||||
this.init(eventData);
|
||||
};
|
||||
|
||||
this.updateWidget = function(eventData, cb) {
|
||||
this.update(eventData);
|
||||
|
||||
var ele = document.querySelector(this.selector + ' .a2cldr-list');
|
||||
ele.innerHTML = this.getEventListItemsHtml();
|
||||
|
||||
if (this.isFunc(cb)) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
/*================================================================ Global var
|
||||
*/
|
||||
|
||||
this.textDomain = 'a2cldr';
|
||||
this.add2calendarBtnTextMap = {
|
||||
'en': 'Add to Calendar',
|
||||
'th': 'เพิ่มเข้าปฏิทิน',
|
||||
'jp': 'カレンダーに追加',
|
||||
'kr': '캘린더에 추가',
|
||||
'ja': 'カレンダーに追加',
|
||||
'cn': '添加到日历',
|
||||
'de': 'In den Kalender',
|
||||
'es': 'Añadir al Calendario',
|
||||
'fr': 'Ajouter au calendrier',
|
||||
'ru': 'Добавить в календарь'
|
||||
};
|
||||
|
||||
this.isSingleEvent;
|
||||
|
||||
// constructor parameter
|
||||
this.eventData;
|
||||
|
||||
this.selector;
|
||||
this.eWidget;
|
||||
|
||||
// option
|
||||
this.defaultOption;
|
||||
this.userOption;
|
||||
this.option;
|
||||
|
||||
this.googleUrl;
|
||||
this.iCalUrl; // iCal and Outlook
|
||||
this.yahooUrl;
|
||||
this.outlookOnlineUrl;
|
||||
|
||||
/*================================================================ Init & Others
|
||||
*/
|
||||
|
||||
this.updateAllCalendars = function() {
|
||||
this.updateGoogleUrl();
|
||||
this.updateICalUrl();
|
||||
this.updateYahooUrl();
|
||||
|
||||
// disabled@01112016-1146 - cause it's not working
|
||||
// this.updateOutlookOnlineUrl();
|
||||
};
|
||||
|
||||
this.init = function(eventData) {
|
||||
this.isSingleEvent = ! this.isArray(eventData);
|
||||
|
||||
if (! this.isValidEventData(eventData)) {
|
||||
console.log('Event data format is not valid');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
this.eventData = eventData;
|
||||
|
||||
this.selector = '';
|
||||
this.eWidget = null; // widget element
|
||||
this.eButton = null; // button element to click for opening the list
|
||||
|
||||
this.defaultOption = {
|
||||
lang: 'fr',
|
||||
buttonText: '',
|
||||
};
|
||||
this.option = this.defaultOption;
|
||||
|
||||
this.googleUrl = '';
|
||||
this.iCalUrl = ''; // iCal and Outlook
|
||||
this.yahooUrl = '';
|
||||
this.outlookOnlineUrl = '';
|
||||
|
||||
this.updateAllCalendars();
|
||||
};
|
||||
|
||||
this.init(eventData);
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' &&
|
||||
module.exports != null) {
|
||||
module.exports = Add2Calendar
|
||||
}
|
|
@ -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> <span class="ernestocouleur">{% blocktrans count counter=actu|length %}Actualité des chef·fe·s:{% plural %}Actualités des chef·fe·s:{% endblocktrans %}</span></h4>
|
||||
<ul>
|
||||
{% for a in actu %}
|
||||
<li>{% if a.rainbow == 'y' %}<span class="ernestocouleur font-weight-bold">{% endif %}{% autotranslate current_language a.text a.text_en %}{% if a.rainbow %}</span>{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<h4><span class="ernestocouleur">{% trans "Agenda :" %}</span></h4>
|
||||
<table width="100%" style="background-color:#e4522f" >
|
||||
<tr>
|
||||
<td width="20%" align="left">
|
||||
|
@ -59,18 +60,98 @@
|
|||
</tr>
|
||||
</table>
|
||||
<div id="calendar">
|
||||
{% if user.profile.is_chef_event or user.profile.is_chef %}
|
||||
{% ifequal current_language "fr" %}
|
||||
{{Calendar_chef|translate}}
|
||||
{% else %}
|
||||
{{Calendar_chef}}
|
||||
{% endifequal %}
|
||||
{% else %}
|
||||
{% ifequal current_language "fr" %}
|
||||
{{Calendar|translate}}
|
||||
{% else %}
|
||||
{{Calendar}}
|
||||
{% endifequal %}
|
||||
{% endif%}
|
||||
</div>
|
||||
{% if user.profile.is_chef %}
|
||||
{% if user.profile.is_chef_event or user.profile.is_chef %}
|
||||
<a href="{% url "calendrier:create_event" %}" class="button">{% trans "Ajouter un évènement" %}</a>
|
||||
{% endif %}
|
||||
</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 user.profile.is_chef_event or user.profile.is_chef %}
|
||||
{% if events_a_venir_chef %}
|
||||
<div class="box" style="background-color:#4169E1">
|
||||
<h1> {% blocktrans count counter=events_a_venir_chef|length %}Doodle seulement visible par les cheff·e·s :{% plural %}Doodles seulement visibles par les cheff·e·s :{% endblocktrans %} </h1>
|
||||
<div class="table-wrapper">
|
||||
<table class="default">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Nom" %}</th>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Lieu" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for e in events_a_venir_chef %}
|
||||
<tr>
|
||||
<td><b><u><a href="{% url 'calendrier:view-event' e.id %}">{{ e.nom }}</a></u></b></td>
|
||||
|
||||
<td>{% blocktrans with date=e.date debut=e.debut %}Le {{ date }} à {{ debut }} {% endblocktrans %} </td>
|
||||
<td> {{e.lieu}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if events_a_venir_chef_public %}
|
||||
<div class="box" style="background-color:#a9008a">
|
||||
<h1> {% blocktrans count counter=events_a_venir_chef_public|length %}Doodle visible par les cheff·e·s et le public :{% plural %}Doodles seulement visibles par les cheff·e·s :{% endblocktrans %} </h1>
|
||||
<div class="table-wrapper">
|
||||
<table class="default">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Nom" %}</th>
|
||||
<th>{% trans "Date" %}</th>
|
||||
<th>{% trans "Lieu" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for e in events_a_venir_chef_public %}
|
||||
<tr>
|
||||
<td><b><u><a href="{% url 'calendrier:view-event' e.id %}">{{ e.nom }}</a></u></b></td>
|
||||
|
||||
<td>{% blocktrans with date=e.date debut=e.debut %}Le {{ date }} à {{ debut }} {% endblocktrans %} </td>
|
||||
<td> {{e.lieu}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% 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 +263,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 %}
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
{% if not user.is_superuser or not user.profile.is_chef %}
|
||||
{% if user.is_superuser or user.profile.is_chef %}
|
||||
{% trans "Cet événement est encore en construction ! Reviens plus tard." %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if user.is_superuser or user.profile.is_chef or not chef_only%}
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
{% if envoi %}<p>{% trans "Votre réponse a été enregistrée !" %}</p>{% endif %}
|
||||
|
@ -13,15 +19,69 @@
|
|||
|
||||
<p><a href="{% url 'calendrier:view-event' id %}" class="button alt">{% trans "Retour à l'événement" %}</a></p>
|
||||
<div><h4> {% blocktrans with nom=ev.nom date=ev.date debut=ev.debut|time:"H:i" %} Voulez vous participer à l'événement {{ nom }}, le {{ date }} à {{ debut }} ?{% endblocktrans %}</h4></div>
|
||||
<p> <b>{% trans "Instrument principal"%} : {% if request.user.profile.instru == "Autre" %}{{request.user.profile.instru_autre}}{% else %}{{request.user.profile.instru}}{% endif %}</b></p>
|
||||
|
||||
|
||||
<form action="{% url 'calendrier:reponse' id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{{ form.non_field_errors }}
|
||||
{% for field in form %}
|
||||
<div class="fieldWrapper">
|
||||
{{ field.errors }}
|
||||
|
||||
|
||||
{% if field.id_for_label == "id_dont_play_main" %}
|
||||
|
||||
<div id="dont_play_main_field" {% if request.user.profile.multi_instrumentiste == "Non" %} style="display: none; "{% endif %}>
|
||||
{% elif field.id_for_label == "id_instrument" %}
|
||||
<div id="instru_ev_field" style="display: none; ">
|
||||
{% elif field.id_for_label == "id_instrument_autre" %}
|
||||
<div id="instru_autre_ev_field" style="display: none; ">
|
||||
{% else %}
|
||||
|
||||
<div>
|
||||
{% endif %}
|
||||
<p>{{ field.label_tag }}
|
||||
{{ field }} {% if field.help_text %}
|
||||
{{ field.help_text|safe }}
|
||||
{% endif %}</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
<input type="submit" value="{% trans "Valider" %}" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script type="text/javascript">
|
||||
$('#id_dont_play_main').on('change', function() {
|
||||
|
||||
if (this.value == "Oui" ) {
|
||||
$('#instru_ev_field').show();
|
||||
}
|
||||
else {
|
||||
$('#instru_ev_field').hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
$('#id_instrument').on('change', function() {
|
||||
|
||||
if (this.value == "Autre" ) {
|
||||
$('#instru_autre_ev_field').show();
|
||||
}
|
||||
else {
|
||||
$('#instru_autre_ev_field').hide();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Participation à un événement" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if envoi %}<p>{% trans "Votre réponse a été enregistrée !" %}</p>{% endif %}
|
||||
|
||||
|
||||
<p><a href="{% url 'calendrier:view-event' id %}">{% trans "Retour à l'événement" %}</a></p>
|
||||
<div> {% blocktrans with nom=ev.nom date=ev.date debut=ev.debut%} Voulez vous participer à l'événement {{ nom }}, le {{ date }} à {{ debut|time:"H:i" }} ?{% endblocktrans %}</div>
|
||||
|
||||
<form action="{% url 'calendrier:reponse' id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Valider" %}" />
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -3,15 +3,23 @@
|
|||
{% load autotranslate %}
|
||||
{% get_current_language as current_language %}
|
||||
{% block titre %}{{ event.nom.capitalize }}{% endblock %}
|
||||
|
||||
{% block extrahead %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
|
||||
{% if not user.profile.is_chef and not user.profile.is_chef_event %}
|
||||
{% if chef_only %}
|
||||
{% trans "Cet événement est encore en construction ! Reviens plus tard." %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef_event or user.profile.is_chef or not chef_only%}
|
||||
<div class="row">
|
||||
<div class="6u 12u$(small)">
|
||||
<div id="viewevent">
|
||||
|
||||
<div id="viewevent">
|
||||
<h2>{{ event.nom.capitalize }}</h2>
|
||||
<h4>
|
||||
{% blocktrans with date=event.date%} Le {{ date }}{% endblocktrans %}
|
||||
|
@ -24,6 +32,7 @@
|
|||
</h4>
|
||||
|
||||
{% if user.is_authenticated and event.desc_users %}
|
||||
|
||||
<div class="box">
|
||||
{% autotranslate current_language event.desc_users event.desc_users_en %}
|
||||
|
||||
|
@ -76,12 +85,12 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p><a href="{% url 'calendrier:reponse' event.id %}" class="button">{% trans "Répondre à l'événement" %}</a></p>
|
||||
<p><a href="{% url 'calendrier:reponse' event.id %}" class="button">{% trans "Répondre à l'événement" %}</a> <div class="event-box" id="single-normal"></div></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="6u 12u$(small)">
|
||||
{% if instrument_count and user.profile.is_chef %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_event %}
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>{% trans "Instrument" %}</th>
|
||||
|
@ -153,14 +162,14 @@
|
|||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% if multi_instrumentistes and user.profile.is_chef %}
|
||||
|
||||
{% if user.profile.is_chef or user.profile.is_chef_event %}
|
||||
{% if multi_instrumentistes %}
|
||||
<h1>{% blocktrans count counter=multi_instrumentistes|length %}Multi-instrumentiste présent :{% plural %}Multi-instrumentistes présents{% endblocktrans %}</h1>
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>{% trans "Nom" %}</th>
|
||||
<th>{% trans "Instrument principal" %}</th>
|
||||
<th>{% trans "Instrument" %}</th>
|
||||
<th>{% trans "Instrument·s bonus" %}</th>
|
||||
<th>{% trans "Réponse" %}</th>
|
||||
</tr>
|
||||
|
@ -173,21 +182,36 @@
|
|||
{% endif %}
|
||||
|
||||
</td>
|
||||
<td>{% if participant.participant.instru == "Autre" %}
|
||||
<td>{% if participant.dont_play_main == 'Oui' %}
|
||||
{% if participant.instrument == "Autre" %}
|
||||
{{participant.instrument_autre}}
|
||||
{% else %}
|
||||
{{participant.instrument}}
|
||||
{% endif %}
|
||||
{% elif participant.participant.instru == "Autre" %}
|
||||
{{participant.participant.instru_autre}}
|
||||
{% else %}
|
||||
{{ participant.participant.instru }}
|
||||
{% endif %}</td>
|
||||
<td>{{ participant.participant.instru_bonus }}</td>
|
||||
<td>{% if participant.dont_play_main == 'Oui' %}
|
||||
{% if participant.participant.instru == "Autre" %}
|
||||
{{participant.participant.instru_autre}}
|
||||
{% else %}
|
||||
{{ participant.participant.instru }}
|
||||
{% endif %}<br>{% endif %}
|
||||
{% if participant.instrument != participant.participant.instru_bonus %}
|
||||
{{ participant.participant.instru_bonus }}
|
||||
{% endif %}</td>
|
||||
<td>{{participant.reponse}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="6u 12u$(small)">
|
||||
{% if user.is_authenticated %}
|
||||
<div id="actions"> {% if user.profile.is_chef %}
|
||||
<div id="actions"> {% if user.profile.is_chef or user.profile.is_chef_event %}
|
||||
<p><a href="{% url "calendrier:edit_event" event.id %}" class="button alt">{% trans "Modifier l'événement" %}</a>   <a href="{% url "calendrier:delete_event" event.id %}" class="button alt">{% trans "Supprimer l'événement" %}</a></p>
|
||||
{% endif %}
|
||||
<p><a href="{% url 'calendrier:change-doodle-name' event.id %}" class="button">{% trans "Changer mon nom pour le doodle" %}</a>   <a href="{% url 'calendrier:home' %}" class="button">{% trans "Retour au calendrier" %}</a></p>
|
||||
|
@ -195,7 +219,61 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% if event.id == 573 %}
|
||||
<div class="fireworks" style="pointer-events: none; position:fixed; top: 0; left: 0; right: 0; bottom: 0; height: 100%; weight: 100%;"></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block script %}
|
||||
<script>
|
||||
/*================================ Single Event
|
||||
*/
|
||||
|
||||
var startDate,
|
||||
endDate;
|
||||
|
||||
var tmpstart = new Date('{{ event.date.isoformat }}'+' '+'{{ event.debut.isoformat }}'+':00');
|
||||
startDate = tmpstart.toString();
|
||||
|
||||
{% if event.fin %}
|
||||
var tmpend = new Date('{{ event.date.isoformat }}'+' '+'{{ event.fin.isoformat }}'+':00');
|
||||
endDate = tmpend.toString();
|
||||
{% else %}
|
||||
var tmpend = new Date('{{ event.date.isoformat }}'+' '+'{{ event.debut.isoformat }}'+':00');
|
||||
tmpend.setHours(tmpend.getHours() +2)
|
||||
endDate = tmpend.toString();
|
||||
{% endif %}
|
||||
var singleEventArgs = {
|
||||
title : '{{ event.nomcourt}}',
|
||||
start : startDate,
|
||||
end : endDate,
|
||||
location : '{{ event.lieu}}',
|
||||
description : ''
|
||||
};
|
||||
var singleEvent = new Add2Calendar(singleEventArgs);
|
||||
|
||||
|
||||
// widget 1 - normal
|
||||
singleEvent.createWidget('#single-normal', function() {
|
||||
console.log('#single-normal widget has been created');
|
||||
});
|
||||
|
||||
{% ifequal current_language "fr" %}
|
||||
singleEvent.setOption({ lang: 'fr' });
|
||||
{% else %}
|
||||
singleEvent.setOption({ lang: 'en' });
|
||||
{% endifequal %}
|
||||
</script>
|
||||
{% if event.id == 573 %}
|
||||
<script src="https://unpkg.com/fireworks-js@2.x/dist/index.umd.js"></script>
|
||||
<script>
|
||||
const container = document.querySelector('.fireworks');
|
||||
const fireworks = new Fireworks.default(container);
|
||||
fireworks.updateOptions({ acceleration: 1.01, traceSpeed: 5 });
|
||||
fireworks.start();
|
||||
</script>
|
||||
{% endif %}
|
||||
{% 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)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -4,8 +4,8 @@ from django.contrib.auth import get_user_model
|
|||
from django.template.defaultfilters import urlencode
|
||||
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 +28,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 +40,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 +50,7 @@ class TestViews(TestCase):
|
|||
fin=later.time(),
|
||||
slug="pubevt",
|
||||
lieu="somewhere",
|
||||
calendrier=True
|
||||
calendrier=True,
|
||||
)
|
||||
|
||||
# Everyone can see theses pages
|
||||
|
@ -88,13 +84,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,261 +1,418 @@
|
|||
import random
|
||||
import string
|
||||
from calendar import monthrange
|
||||
from collections import defaultdict
|
||||
from datetime import date, datetime
|
||||
import string
|
||||
import random
|
||||
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.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 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.models import Event, Participants
|
||||
from partitions.decorators import chef_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.views.generic import DeleteView, TemplateView, UpdateView
|
||||
from gestion.mixins import ChefEventRequiredMixin
|
||||
from gestion.models import Photo
|
||||
|
||||
from calendrier.calend import EventCalendar
|
||||
from calendrier.forms import (ChangeDoodleName, EventForm, ModifEventForm,
|
||||
ParticipantsForm)
|
||||
from calendrier.models import Event, Participants
|
||||
|
||||
|
||||
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')
|
||||
|
||||
@login_required
|
||||
def home(request):
|
||||
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,
|
||||
|
||||
})
|
||||
|
||||
@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)
|
||||
return date(1900, pMonthNumber, 1).strftime("%B")
|
||||
|
||||
|
||||
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")
|
||||
.exclude(calendrier__iexact="C")
|
||||
.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 = self.pYear
|
||||
lMonth = 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
|
||||
)
|
||||
.exclude(calendrier__iexact="C")
|
||||
.exclude(calendrier__iexact="D")
|
||||
)
|
||||
lEvents_chef = Event.objects.filter(
|
||||
date__gte=lCalendarFromMonth, date__lte=lCalendarToMonth
|
||||
)
|
||||
lCalendar = EventCalendar(lEvents).formatmonth(lYear, lMonth)
|
||||
lCalendar_chef = EventCalendar(lEvents_chef).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
|
||||
|
||||
events_a_venir_not_answered = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.exclude(participants__participant=self.request.user.profile)
|
||||
.exclude(calendrier__iexact="C")
|
||||
.exclude(calendrier__iexact="D")
|
||||
.order_by("date")
|
||||
)
|
||||
events_a_venir_answered_yes = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="oui")
|
||||
)
|
||||
.exclude(calendrier__iexact="C")
|
||||
.exclude(calendrier__iexact="D")
|
||||
.order_by("date")
|
||||
)
|
||||
events_a_venir_answered_no = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="non")
|
||||
)
|
||||
.exclude(calendrier__iexact="C")
|
||||
.exclude(calendrier__iexact="D")
|
||||
.order_by("date")
|
||||
)
|
||||
events_a_venir_answered_pe = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.filter(
|
||||
Q(participants__participant=self.request.user.profile)
|
||||
& Q(participants__reponse="pe")
|
||||
)
|
||||
.exclude(calendrier__iexact="C")
|
||||
.exclude(calendrier__iexact="D")
|
||||
.order_by("date")
|
||||
)
|
||||
events_a_venir_chef = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.filter(calendrier__in=["C"])
|
||||
.order_by("date")
|
||||
)
|
||||
events_a_venir_chef_public = (
|
||||
Event.objects.filter(date__gte=lToday)
|
||||
.filter(calendrier__in=["D"])
|
||||
.order_by("date")
|
||||
)
|
||||
|
||||
context["Calendar"] = mark_safe(lCalendar)
|
||||
context["Calendar_chef"] = mark_safe(lCalendar_chef)
|
||||
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["events_a_venir_chef"] = events_a_venir_chef
|
||||
context["events_a_venir_chef_public"] = events_a_venir_chef_public
|
||||
context["actu"] = actu
|
||||
context["photo"] = photo
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
def changename(request,id):
|
||||
if request.method == 'POST':
|
||||
class Home(Calendar):
|
||||
@property
|
||||
def pYear(self):
|
||||
lToday = datetime.now()
|
||||
return lToday.year
|
||||
|
||||
@property
|
||||
def pMonth(self):
|
||||
lToday = datetime.now()
|
||||
return 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
|
||||
if participant.dont_play_main == "Oui":
|
||||
if participant.instrument == "Autre":
|
||||
instru = participant.instrument_autre
|
||||
else:
|
||||
instru = participant.instrument
|
||||
|
||||
instru = "" if instru is None else instru
|
||||
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_l = []
|
||||
instru_order = [
|
||||
"Clarinette",
|
||||
"Piccolo",
|
||||
"Flute",
|
||||
"Glockenspiel",
|
||||
"Saxophone Alto",
|
||||
"Trompette",
|
||||
"Trombone",
|
||||
"Cor",
|
||||
"Saxophone Ténor",
|
||||
"Saxophone Baryton",
|
||||
"Clarinette Basse",
|
||||
"Euphonium",
|
||||
"Souba",
|
||||
"Percussion",
|
||||
]
|
||||
for instrument in instru_order:
|
||||
if instrument in instrument_count.keys():
|
||||
(sure, maybe, namesoui, namespe, namesnon) = instrument_count[
|
||||
instrument
|
||||
]
|
||||
instrument_count_l.append(
|
||||
(
|
||||
instrument,
|
||||
sure,
|
||||
maybe,
|
||||
namesoui,
|
||||
namespe,
|
||||
namesnon,
|
||||
)
|
||||
)
|
||||
for instrument in sorted(instrument_count.keys()):
|
||||
if instrument not in instru_order:
|
||||
(sure, maybe, namesoui, namespe, namesnon) = instrument_count[
|
||||
instrument
|
||||
]
|
||||
instrument_count_l.append(
|
||||
(
|
||||
instrument,
|
||||
sure,
|
||||
maybe,
|
||||
namesoui,
|
||||
namespe,
|
||||
namesnon,
|
||||
)
|
||||
)
|
||||
|
||||
context["event"] = event
|
||||
context["instrument_count"] = instrument_count_l
|
||||
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
|
||||
context["chef_only"] = (event.calendrier == "C") | (event.calendrier == "D")
|
||||
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
|
||||
|
||||
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(ChefEventRequiredMixin, 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)
|
||||
ev = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
try:
|
||||
context["form"] = self.form_class(
|
||||
instance=Participants.objects.get(
|
||||
event=ev, participant=self.request.user.profile
|
||||
)
|
||||
)
|
||||
except Participants.DoesNotExist:
|
||||
context["form"] = self.form_class()
|
||||
context["ev"] = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
context["id"] = self.kwargs["id"]
|
||||
context["chef_only"] = (context["ev"].calendrier == "C") | (
|
||||
context["ev"].calendrier == "D"
|
||||
)
|
||||
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):
|
||||
ev = get_object_or_404(Event, id=self.kwargs["id"])
|
||||
part = request.user.profile
|
||||
try:
|
||||
p = Participants.objects.get(event=ev, participant=part)
|
||||
except Participants.DoesNotExist:
|
||||
p = None
|
||||
form = self.form_class(request.POST, instance=p)
|
||||
if form.is_valid():
|
||||
try:
|
||||
p = Participants.objects.get(event=ev, participant=part)
|
||||
p.delete()
|
||||
except Participants.DoesNotExist:
|
||||
pass
|
||||
obj = form.save(commit=False)
|
||||
# Si la participation existe déjà, ces 2 ligne sont redondantes
|
||||
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(ChefEventRequiredMixin, 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(ChefEventRequiredMixin, 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):
|
||||
|
@ -37,6 +36,7 @@ User.profile_phone = ProfileInfo("phone", "Téléphone")
|
|||
User.profile_instru = ProfileInfo("instru", "Instrument joué")
|
||||
User.profile_is_ern = ProfileInfo("is_ernesto", "Ernestophoniste")
|
||||
User.profile_is_chef = ProfileInfo("is_chef", "Chef Fanfare")
|
||||
User.profile_is_chef_event = ProfileInfo("is_chef_event", "Respo événement")
|
||||
User.profile_get_mails = ProfileInfo("mails", "Recevoir les mails")
|
||||
|
||||
|
||||
|
@ -58,6 +58,7 @@ class UserProfileAdmin(UserAdmin):
|
|||
"profile_instru",
|
||||
"profile_is_ern",
|
||||
"profile_is_chef",
|
||||
"profile_is_chef_event",
|
||||
]
|
||||
list_display_links = ["username", "email", "first_name", "last_name"]
|
||||
list_filter = ["profile__instru"]
|
||||
|
@ -112,7 +113,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:",
|
||||
),
|
||||
),
|
||||
]
|
24
gestion/migrations/0006_auto_20210608_1029.py
Normal file
24
gestion/migrations/0006_auto_20210608_1029.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 2.2.17 on 2021-06-08 10:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
import gestion.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0005_auto_20210427_1834"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="photo",
|
||||
name="image",
|
||||
field=models.ImageField(
|
||||
default=None,
|
||||
upload_to="trombonoscope/deco",
|
||||
validators=[gestion.models.Photo.validate_image],
|
||||
),
|
||||
),
|
||||
]
|
20
gestion/migrations/0007_ernestouser_is_chef_event.py
Normal file
20
gestion/migrations/0007_ernestouser_is_chef_event.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.24 on 2021-10-06 09:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0006_auto_20210608_1029"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="ernestouser",
|
||||
name="is_chef_event",
|
||||
field=models.BooleanField(
|
||||
default=False, verbose_name="Respo événement Fanfare"
|
||||
),
|
||||
),
|
||||
]
|
28
gestion/migrations/0008_auto_20211022_1923.py
Normal file
28
gestion/migrations/0008_auto_20211022_1923.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 2.2.24 on 2021-10-22 17:23
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0007_ernestouser_is_chef_event"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="ernestouser",
|
||||
name="is_chef_com",
|
||||
field=models.BooleanField(default=False, verbose_name="Respo com"),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="ernestouser",
|
||||
name="is_chef_instru",
|
||||
field=models.BooleanField(default=False, verbose_name="Respo instruments"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="ernestouser",
|
||||
name="is_chef_event",
|
||||
field=models.BooleanField(default=False, verbose_name="Respo événements"),
|
||||
),
|
||||
]
|
18
gestion/migrations/0009_ernestouser_is_chef_mu.py
Normal file
18
gestion/migrations/0009_ernestouser_is_chef_mu.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.24 on 2022-01-11 15:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("gestion", "0008_auto_20211022_1923"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="ernestouser",
|
||||
name="is_chef_mu",
|
||||
field=models.BooleanField(default=False, verbose_name="Respo musique"),
|
||||
),
|
||||
]
|
|
@ -5,3 +5,76 @@ class ChefRequiredMixin(UserPassesTestMixin):
|
|||
def test_func(self):
|
||||
user = self.request.user
|
||||
return (user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
|
||||
|
||||
class ChefEventRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
user = self.request.user
|
||||
is_chef = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
)
|
||||
is_chef_event = (
|
||||
(user is not None)
|
||||
and hasattr(user, "profile")
|
||||
and user.profile.is_chef_event
|
||||
)
|
||||
return is_chef or is_chef_event
|
||||
|
||||
|
||||
class ChefInstruRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
user = self.request.user
|
||||
is_chef = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
)
|
||||
is_chef_instru = (
|
||||
(user is not None)
|
||||
and hasattr(user, "profile")
|
||||
and user.profile.is_chef_instru
|
||||
)
|
||||
return is_chef or is_chef_instru
|
||||
|
||||
|
||||
class ChefComRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
user = self.request.user
|
||||
is_chef = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
)
|
||||
is_chef_com = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef_com
|
||||
)
|
||||
return is_chef or is_chef_com
|
||||
|
||||
|
||||
class ChefMuRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
user = self.request.user
|
||||
is_chef = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
)
|
||||
is_chef_mu = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef_mu
|
||||
)
|
||||
return is_chef or is_chef_mu
|
||||
|
||||
|
||||
class AllChefRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
user = self.request.user
|
||||
is_chef = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef
|
||||
)
|
||||
is_su = (user is not None) and user.is_superuser
|
||||
is_chef_com = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef_com
|
||||
)
|
||||
is_chef_event = (
|
||||
(user is not None)
|
||||
and hasattr(user, "profile")
|
||||
and user.profile.is_chef_event
|
||||
)
|
||||
is_chef_mu = (
|
||||
(user is not None) and hasattr(user, "profile") and user.profile.is_chef_mu
|
||||
)
|
||||
return is_chef or is_chef_com or is_chef_event or is_su or is_chef_mu
|
||||
|
|
|
@ -1,63 +1,167 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.db import models
|
||||
import os
|
||||
|
||||
from colorful.fields import RGBColorField
|
||||
from django.conf import settings
|
||||
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 _
|
||||
|
||||
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")),
|
||||
]
|
||||
|
||||
|
||||
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="trombonoscope/deco", default=None, validators=[validate_image]
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def delete(self):
|
||||
os.remove(self.image.path)
|
||||
return super(Photo, self).delete()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
try:
|
||||
this = Photo.objects.get(id=self.id)
|
||||
if this.image.path != self.image.path:
|
||||
os.remove(this.image.path)
|
||||
except Photo.DoesNotExist:
|
||||
pass
|
||||
super(Photo, self).save(*args, **kwargs)
|
||||
|
||||
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"))
|
||||
|
||||
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')),
|
||||
]
|
||||
is_chef_event = models.BooleanField(_("Respo événements"), default=False)
|
||||
is_chef_com = models.BooleanField(_("Respo com"), default=False)
|
||||
is_chef_instru = models.BooleanField(_("Respo instruments"), default=False)
|
||||
is_chef_mu = models.BooleanField(_("Respo musique"), default=False)
|
||||
phone = models.CharField(
|
||||
_("Téléphone"),
|
||||
max_length=20,
|
||||
blank=True,
|
||||
help_text=_("seulement visible par les chef·fe·s"),
|
||||
)
|
||||
|
||||
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,54 @@ 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%;
|
||||
}
|
||||
|
||||
/* class to add colorful rainbowed texts */
|
||||
.ernestocouleur {
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
background-image: linear-gradient(to right,
|
||||
hsl(10, 100%, 75%),
|
||||
hsl(20, 100%, 65%),
|
||||
hsl(30, 100%, 55%),
|
||||
hsl(40, 100%, 50%),
|
||||
hsl(50, 100%, 50%),
|
||||
hsl(60, 100%, 50%),
|
||||
hsl(70, 100%, 50%),
|
||||
hsl(80, 100%, 50%),
|
||||
hsl(90, 100%, 50%),
|
||||
hsl(100, 100%, 50%),
|
||||
hsl(110, 100%, 50%),
|
||||
hsl(120, 100%, 50%),
|
||||
hsl(130, 100%, 50%),
|
||||
hsl(140, 100%, 50%),
|
||||
hsl(150, 100%, 50%),
|
||||
hsl(160, 100%, 50%),
|
||||
hsl(170, 100%, 50%),
|
||||
hsl(180, 100%, 50%),
|
||||
hsl(190, 100%, 50%),
|
||||
hsl(200, 100%, 50%),
|
||||
hsl(210, 100%, 50%),
|
||||
hsl(220, 100%, 50%),
|
||||
hsl(230, 100%, 50%),
|
||||
hsl(240, 100%, 50%),
|
||||
hsl(250, 100%, 50%)
|
||||
);
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
select[multiple] {
|
||||
height: 15em;
|
||||
}
|
||||
|
|
|
@ -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%; }
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 53 KiB |
Binary file not shown.
Binary file not shown.
BIN
gestion/static/images/cvec.png
Normal file
BIN
gestion/static/images/cvec.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
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
|
@ -41,18 +41,7 @@
|
|||
);
|
||||
});
|
||||
|
||||
// Menu.
|
||||
$('#menu')
|
||||
.append('<a href="#menu" class="close"></a>')
|
||||
.appendTo($body)
|
||||
.panel({
|
||||
delay: 500,
|
||||
hideOnClick: true,
|
||||
hideOnSwipe: true,
|
||||
resetScroll: true,
|
||||
resetForms: true,
|
||||
side: 'right'
|
||||
});
|
||||
|
||||
|
||||
$('#id_multi_instrumentiste').on('change', function() {
|
||||
|
||||
|
@ -64,6 +53,8 @@
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
$('#id_instru').on('change', function() {
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load changelang %}
|
||||
{% load avatar_tags %}
|
||||
{% get_current_language as current_language %}
|
||||
|
||||
<!DOCTYPE HTML>
|
||||
|
@ -13,56 +14,126 @@
|
|||
<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 %}
|
||||
<link rel="stylesheet" href="{% static 'css/main.css' %}?version=1" />
|
||||
<link rel="stylesheet" href="{% static 'css/add2calendar.css' %}">
|
||||
|
||||
</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='vertical-align: middle;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>
|
||||
|
||||
{% else %}
|
||||
<li><a href="{% url 'login' %}">{% trans "Se connecter" %}</a></li>
|
||||
<li><a href="{% url 'registration' %}">{% trans "Créer un compte" %}</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'%}</b>
|
||||
</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>
|
||||
<a class="dropdown-item" href="https://heyzine.com/flip-book/b2cf4809b7.html" target="_blank">{% trans "Year Book 2021" %}</a>
|
||||
</div>
|
||||
</li>
|
||||
{% if user.is_superuser or user.profile.is_chef or user.profile.is_chef_event or user.profile.is_chef_com or user.profile.is_chef_mu %}
|
||||
<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">
|
||||
{% if user.is_superuser or user.profile.is_chef %}
|
||||
<a class="dropdown-item" href="/admin/">{% trans "Administration" %}</a>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% if user.profile.is_chef %}
|
||||
<a class="dropdown-item" href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_event %}
|
||||
<a class="dropdown-item" href="{% url 'calendrier:create_event' %}">{% trans "Ajouter un événement" %}</a>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_com %}
|
||||
<a class="dropdown-item" href="{% url 'liste_photo' %}">{% trans "Modifier les photos" %}</a>
|
||||
<a class="dropdown-item" href="{% url 'liste_video' %}">{% trans "Modifier les vidéos" %}</a>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_mu %}
|
||||
<a class="dropdown-item" href="{% url 'partitions:list_setlist' %}">{% trans "Gérer les programmes de répétition" %}</a>
|
||||
{% endif %}
|
||||
|
||||
</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" style="vertical-align: middle"%}
|
||||
{% else %}
|
||||
<img src="{% static "images/Ernestophone_logo.png" %}" width="50" height="50" class="rounded-circle"style="vertical-align: middle">
|
||||
{% 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" %}</b></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" style="vertical-align: middle"></a>
|
||||
{% else %}
|
||||
<a class="nav-link" href="{% changelang "fr" %}" ><img src="{% static 'images\fr_flag.jpg' %}" width="60" height="40" style="vertical-align: middle"></a>
|
||||
{% endifequal %}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<!-- Main -->
|
||||
|
@ -74,6 +145,10 @@
|
|||
<!-- Footer -->
|
||||
<footer id="footer" style="background-color:rgb(228, 82, 47);">
|
||||
<div class="copyright">
|
||||
<ul class="icons">
|
||||
<li><a target="_blank" href="https://cvec.etudiant.gouv.fr/"><img alt="Logo de la CVEC" src='{% static "images/cvec.png" %}' width="100px"/></a></li>
|
||||
|
||||
</ul>
|
||||
<ul class="icons">
|
||||
<li><a target="_blank" href="https://www.facebook.com/ernestophone"
|
||||
|
||||
|
@ -82,19 +157,58 @@
|
|||
<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 src="{% static 'js/add2calendar.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];
|
||||
|
@ -107,5 +221,7 @@
|
|||
}
|
||||
|
||||
</script>
|
||||
{% block script %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -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>
|
||||
|
|
38
gestion/templates/gestion/chef.html
Normal file
38
gestion/templates/gestion/chef.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
{% 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>
|
||||
{% if user.profile.is_chef or user.is_superuser %}
|
||||
<li> <a href="/admin/">{% trans "Administration" %}</a></li>
|
||||
|
||||
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef %}
|
||||
<li><a href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_event%}
|
||||
<li> <a href="{% url 'calendrier:create_event' %}">{% trans "Ajouter un événement" %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_com%}
|
||||
<li><a href="{% url 'liste_photo' %}">{% trans "Modifier les photos" %}</a></li>
|
||||
<li><a href="{% url 'liste_video' %}">{% trans "Modifier les vidéos" %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.profile.is_chef or user.profile.is_chef_mu %}
|
||||
<li> <a href="{% url 'partitions:list_setlist' %}">{% trans "Gérer les programmes de répétition" %}</a> </li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
19
gestion/templates/gestion/create_photo.html
Normal file
19
gestion/templates/gestion/create_photo.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{%block titre %}{% trans "Ajout d'une photo" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<p><a href="{% url "liste_photo" %}" class="button alt">{% trans "Retour à la liste" %}</a></p>
|
||||
{% if envoi %}<p>{% trans "Cette photo à été enregistrée" %}.{% endif %}
|
||||
<form action="" method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
19
gestion/templates/gestion/create_video.html
Normal file
19
gestion/templates/gestion/create_video.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{%block titre %}{% trans "Ajout d'une vidéo" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<p><a href="{% url "liste_video" %}" class="button alt">{% trans "Retour à la liste" %}</a></p>
|
||||
{% if envoi %}<p>{% trans "Cette vidéo à é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
gestion/templates/gestion/delete_photo.html
Normal file
16
gestion/templates/gestion/delete_photo.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Suppression d'une photo" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<p><a href="{% url "liste_photo" %}" class="button alt">{% trans "Retour aux photos" %}</a></p>
|
||||
<p>{% blocktrans with object=object %} Voulez vous vraiment supprimer la photo {{ object.name }}?{% endblocktrans %}</p>
|
||||
<input type="submit" value="{% trans "Oui" %}" />
|
||||
</form>
|
||||
</div></section>
|
||||
</div>
|
||||
{% endblock %}
|
16
gestion/templates/gestion/delete_video.html
Normal file
16
gestion/templates/gestion/delete_video.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Suppression d'une vidéo" %}{% endblock %}
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<p><a href="{% url "liste_video" %}" class="button alt">{% trans "Retour aux vidéos" %}</a></p>
|
||||
<p>{% blocktrans with object=object %} Voulez vous vraiment supprimer la vidéo {{ object.name }}?{% endblocktrans %}</p>
|
||||
<input type="submit" value="{% trans "Oui" %}" />
|
||||
</form>
|
||||
</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>
|
||||
|
@ -174,12 +196,24 @@
|
|||
Nous répétons tous les mardis et jeudi soirs de 20h à 22h dans les sous sols du NIR à l'ENS. <br>Fanfaron débutant ou musicien aguerri, n'hésite pas à venir nous rejoindre !
|
||||
Nous serons heureux de te compter dans nos rangs !<br>
|
||||
Nous prêtons des instruments à tout membre du COF souhaitant découvrir les joies de la fanfaronnerie !{% endblocktrans %}</p>
|
||||
<p align="center">{% blocktrans %}Pour un petit aperçu du fun qu'on peux avoir n'hésites pas à consulter notre {% endblocktrans %}<a class="text" href="https://heyzine.com/flip-book/b2cf4809b7.html" target="_blank">year book</a></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 +226,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 +256,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 +270,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>
|
||||
|
||||
|
||||
|
|
42
gestion/templates/gestion/photo.html
Normal file
42
gestion/templates/gestion/photo.html
Normal file
|
@ -0,0 +1,42 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% get_current_language as current_language %}
|
||||
{% load autotranslate %}
|
||||
{% block titre %}{% trans "Liste des Photos" %}{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<h4>{% trans "Liste des photos" %} :</h4>
|
||||
|
||||
|
||||
<p><a href="{% url "add_photo" %}" class="button">{% trans "Ajouter une photo" %}</a></p>
|
||||
|
||||
<ul class="filelist">
|
||||
{% for p in photos %}
|
||||
<li>
|
||||
<p> <b>{{ p.name }}</b> {% if p.cat == 'n' %}: {% trans "Non utilisée" %} <br>( {% trans "Pensez à supprimer les photos non utilisée" %}){% endif %}
|
||||
{% if p.cat == 'home_join' %}: {% trans "Rejoignez nous" %} {% endif %}
|
||||
{% if p.cat == 'home_contact' %}: {% trans "Nous Contacter" %} {% endif %}
|
||||
{% if p.cat == 'home_rep' %}: {% trans "Répertoire de l'acceuil" %} {% endif %}
|
||||
{% if p.cat == 'login' %}: {% trans "Connexion" %} {% endif %}
|
||||
{% if p.cat == 'change_membre' %}: {% trans "Modification du profil" %} {% endif %}
|
||||
{% if p.cat == 'inscription_membre' %}: {% trans "Inscription" %} {% endif %}
|
||||
{% if p.cat == 'home' %}: {% trans "Calendrier connecté" %} {% endif %}
|
||||
{% if p.cat == 'liste' %}: {% trans "Agenda public" %} {% endif %}
|
||||
{% if p.cat == 'part' %}: {% trans "Répertoire" %} {% endif %}
|
||||
{% if p.cat == 'instru' %}: {% trans "Instruments" %} {% endif %}
|
||||
|
||||
  <a class="button alt" href="{% url "edit_photo" p.id %}">{% trans "Modifier" %}</a> <a class="button alt" href="{% url "delete_photo" p.id %}">{% trans "Supprimer" %}</a>
|
||||
<img src="{{p.image.url}}" alt="" style='vertical-align: middle;height:4em;width:auto' /></p>
|
||||
</li>
|
||||
|
||||
{% empty %}
|
||||
<p>{% trans "Pas de photos pour le moment" %}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
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 'change_membre' %}">{% trans "Modifier le profil" %}</a></li>
|
||||
<li> <a href="{% url 'trombonoscope:change' %}">{% trans "Modifier le Trombo" %}</a></li>
|
||||
<li><a href="{% url 'logout' %}">{% trans "Déconnexion" %}</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>
|
||||
|
||||
|
|
24
gestion/templates/gestion/social.html
Normal file
24
gestion/templates/gestion/social.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% 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>
|
||||
<li><a href="{% url 'yearbook2021' %}" target="_blank">{% trans "Year Book 2021" %}</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
15
gestion/templates/gestion/update_photo.html
Normal file
15
gestion/templates/gestion/update_photo.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Modification d'une photo" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div></section></div>
|
||||
{% endblock %}
|
15
gestion/templates/gestion/update_video.html
Normal file
15
gestion/templates/gestion/update_video.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% block titre %}{% trans "Modification d'une vidéo" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="{% trans "Enregistrer" %}" />
|
||||
</form>
|
||||
</div></section></div>
|
||||
{% endblock %}
|
30
gestion/templates/gestion/video.html
Normal file
30
gestion/templates/gestion/video.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% get_current_language as current_language %}
|
||||
{% load autotranslate %}
|
||||
{% block titre %}{% trans "Liste des vidéos" %}{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
<h4>{% trans "Liste des vidéos" %} :</h4>
|
||||
|
||||
|
||||
<p><a href="{% url "add_video" %}" class="button">{% trans "Ajouter une vidéo" %}</a></p>
|
||||
|
||||
<ul class="filelist">
|
||||
{% for v in videos %}
|
||||
<li>
|
||||
<p> <b>{{ v }}</b>  <a class="button alt" href="{% url "edit_video" v.id %}">{% trans "Modifier" %}</a>
|
||||
  <a class="button alt" href="{% url "delete_video" v.id %}">{% trans "Supprimer" %}</a></p>
|
||||
</li>
|
||||
|
||||
{% empty %}
|
||||
<p>{% trans "Pas de vidéos pour le moment" %}</p>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
{% endblock %}
|
15
gestion/templates/gestion/yearbook2021.html
Normal file
15
gestion/templates/gestion/yearbook2021.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
{% extends "gestion/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load static %}
|
||||
{% block titre %}{% trans "Modification d'une photo" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div id="main">
|
||||
<section class="wrapper style1">
|
||||
<div class="inner">
|
||||
|
||||
<iframe allowfullscreen="allowfullscreen" scrolling="no" class="fp-iframe" src="https://heyzine.com/flip-book/b2cf4809b7.html" style="border: 1px solid lightgray; width: 100%; height: 600px;"></iframe>
|
||||
|
||||
|
||||
</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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
307
gestion/views.py
307
gestion/views.py
|
@ -1,115 +1,274 @@
|
|||
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 os
|
||||
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.http import HttpResponseRedirect
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic import (CreateView, DeleteView, ListView,
|
||||
TemplateView, UpdateView)
|
||||
|
||||
from calendrier.forms import ChangeDoodleName
|
||||
from gestion.forms import (ChangeFormUser, ChangeMembreForm,
|
||||
InscriptionMembreForm, RegistrationFormUser)
|
||||
from gestion.mixins import (AllChefRequiredMixin, ChefComRequiredMixin,
|
||||
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().order_by("order")
|
||||
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(AllChefRequiredMixin, TemplateView):
|
||||
template_name = "gestion/chef.html"
|
||||
|
||||
|
||||
class YearBook2021(TemplateView):
|
||||
template_name = "gestion/yearbook2021.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)
|
||||
|
||||
|
||||
class PhotoList(ChefComRequiredMixin, ListView):
|
||||
model = Photo
|
||||
context_object_name = "photos"
|
||||
ordering = "cat"
|
||||
template_name = "gestion/photo.html"
|
||||
|
||||
|
||||
class PhotoCreate(ChefComRequiredMixin, CreateView):
|
||||
model = Photo
|
||||
fields = ["name", "cat", "auteur", "url", "color", "image"]
|
||||
template_name = "gestion/create_photo.html"
|
||||
success_url = reverse_lazy("liste_photo")
|
||||
|
||||
def form_valid(self, form):
|
||||
photo = form.save(commit=False)
|
||||
photo.save()
|
||||
return HttpResponseRedirect(self.success_url)
|
||||
|
||||
|
||||
class PhotoUpdate(ChefComRequiredMixin, UpdateView):
|
||||
model = Photo
|
||||
fields = ["name", "cat", "auteur", "url", "color", "image"]
|
||||
template_name = "gestion/update_photo.html"
|
||||
success_url = reverse_lazy("liste_photo")
|
||||
|
||||
|
||||
class PhotoDelete(ChefComRequiredMixin, DeleteView):
|
||||
model = Photo
|
||||
template_name = "gestion/delete_photo.html"
|
||||
success_url = reverse_lazy("liste_photo")
|
||||
|
||||
|
||||
class VideoList(ChefComRequiredMixin, ListView):
|
||||
model = VideoGallery
|
||||
ordering = "order"
|
||||
context_object_name = "videos"
|
||||
template_name = "gestion/video.html"
|
||||
|
||||
|
||||
class VideoCreate(ChefComRequiredMixin, CreateView):
|
||||
model = VideoGallery
|
||||
fields = ["name", "url", "order"]
|
||||
template_name = "gestion/create_video.html"
|
||||
success_url = reverse_lazy("liste_video")
|
||||
|
||||
def form_valid(self, form):
|
||||
video = form.save(commit=False)
|
||||
video.save()
|
||||
return HttpResponseRedirect(self.success_url)
|
||||
|
||||
|
||||
class VideoUpdate(ChefComRequiredMixin, UpdateView):
|
||||
model = VideoGallery
|
||||
fields = ["name", "url", "order"]
|
||||
template_name = "gestion/update_video.html"
|
||||
success_url = reverse_lazy("liste_video")
|
||||
|
||||
|
||||
class VideoDelete(ChefComRequiredMixin, DeleteView):
|
||||
model = VideoGallery
|
||||
template_name = "gestion/delete_video.html"
|
||||
success_url = reverse_lazy("liste_video")
|
||||
|
|
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"
|
28
instruments/forms.py
Normal file
28
instruments/forms.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
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",
|
||||
"etat",
|
||||
"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/documents/responsabilite_instru.pdf
Normal file
BIN
instruments/static/documents/responsabilite_instru.pdf
Normal file
Binary file not shown.
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 |
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue