Compare commits

..

3 commits

Author SHA1 Message Date
Martin Pépin
56c31e2612
Add a unit test for the password view 2020-09-12 19:08:32 +02:00
Martin Pépin
e17b033aa5
Minor fixes on the 'change passwd' template 2020-09-12 19:08:32 +02:00
Martin Pépin
7c281f926b
Prevent the 'change passwd' view from crashing 2020-09-12 19:08:32 +02:00
187 changed files with 3159 additions and 7339 deletions

View file

@ -1 +0,0 @@
insecure-secret_key

View file

@ -1,161 +0,0 @@
from pathlib import Path
from django.utils.translation import gettext_lazy as _
from loadcredential import Credentials
credentials = Credentials(env_prefix="ERNESTOPHONE_")
BASE_DIR = Path(__file__).resolve().parent.parent
DEBUG = credentials.get_json("DEBUG", False)
ALLOWED_HOSTS = credentials.get_json("ALLOWED_HOSTS", [])
SECRET_KEY = credentials["SECRET_KEY"]
ADMINS = credentials.get_json("ADMINS", [])
SERVER_EMAIL = credentials.get("SERVER_EMAIL", "ernesto@localhost")
ACCOUNT_CREATION_PASS = credentials.get("ACCOUNT_CREATION_PASS", "dummy")
INSTALLED_APPS = [
"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",
]
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",
},
},
}
]
WSGI_APPLICATION = "Ernestophone.wsgi.application"
###
# Database configuration
# -> https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
DATABASES = credentials.get_json(
"DATABASES",
{
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
},
)
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# I18n
# I18n
LANGUAGE_CODE = "fr"
LANGUAGES = (
("fr", _("Français")),
("en", _("English")),
)
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = (BASE_DIR / "locale",)
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"
###
# Staticfiles configuration
STATIC_ROOT = credentials["STATIC_ROOT"]
STATIC_URL = "/static/"
MEDIA_ROOT = credentials.get("MEDIA_ROOT", BASE_DIR / "media")
MEDIA_URL = "/media/"
if DEBUG:
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
INSTALLED_APPS += ["debug_toolbar"]
MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE

View file

@ -0,0 +1,153 @@
import os
from django.utils.translation import gettext_lazy as _
try:
from . import secret
except ImportError:
raise ImportError(
"The secret.py file is missing.\n"
"For a development environment, simply copy secret_example.py"
)
def import_secret(name):
"""
Shorthand for importing a value from the secret module and raising an
informative exception if a secret is missing.
"""
try:
return getattr(secret, name)
except AttributeError:
raise RuntimeError("Secret missing: {}".format(name))
SECRET_KEY = import_secret("SECRET_KEY")
ADMINS = import_secret("ADMINS")
SERVER_EMAIL = import_secret("SERVER_EMAIL")
DBNAME = import_secret("DBNAME")
DBUSER = import_secret("DBUSER")
DBPASSWD = import_secret("DBPASSWD")
ACCOUNT_CREATION_PASS = import_secret("ACCOUNT_CREATION_PASS")
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',
]
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',
]
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',
}
}
}]
WSGI_APPLICATION = "Ernestophone.wsgi.application"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": DBNAME,
"USER": DBUSER,
"PASSWORD": DBPASSWD,
"HOST": "localhost",
}
}
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# I18n
# I18n
LANGUAGE_CODE = 'fr'
LANGUAGES = (
('fr', _('Français')),
('en', _('English')),
)
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = ( os.path.join(BASE_DIR, 'locale'), )
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'

View file

@ -0,0 +1,28 @@
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
)
STATIC_URL = "/static/"
STATIC_ROOT = "static"
MEDIA_URL = "/media/"
MEDIA_ROOT = "media"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}

View file

@ -0,0 +1,22 @@
import os
from .common import * # noqa
from .common import BASE_DIR
DEBUG = False
ALLOWED_HOSTS = [
"ernestophone.ens.fr",
"www.ernestophone.ens.fr",
]
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(
BASE_DIR, "..", "..", "public", "ernesto", "static"
)
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(
BASE_DIR, "..", "media"
)

View file

@ -0,0 +1,9 @@
SECRET_KEY = "vpb%-1@$ha98w5^ji#@9v2_kxj)zdk5+e!9!fqniu2$#eg+46="
ADMINS = None
SERVER_EMAIL = "ernesto@localhost"
DBNAME = "ernesto"
DBUSER = "ernesto"
DBPASSWD = "YNp2rrXowJnDAFF3"
ACCOUNT_CREATION_PASS = "dummy"

View file

@ -13,61 +13,36 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 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 import settings
from django.conf.urls.i18n import i18n_patterns 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 = []
urlpatterns += i18n_patterns( urlpatterns += i18n_patterns(
path("", gestion_views.Home.as_view(), name="home"), path('', gestion_views.home, name="home"),
path("registration", gestion_views.Inscription.as_view(), name="registration"), path("registration", gestion_views.inscription_membre, name="registration"),
path("change", gestion_views.ChangeMembre.as_view(), name="change_membre"), path("change", gestion_views.change_membre, name="change_membre"),
path("password", gestion_views.ChangePassword.as_view(), name="change_password"), path("password", gestion_views.change_password, name="change_password"),
path("thanks", gestion_views.Thanks.as_view(), name="thanks"), path("thanks", gestion_views.thanks, name="thanks"),
path("social", gestion_views.Social.as_view(), name="social"), path("changename", gestion_views.changename, name="change-doodle-name"),
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("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( path(
"admin/", "login",
admin.site.urls, auth_views.LoginView.as_view(template_name="gestion/login.html"),
name="login"
), ),
path("trombonoscope/", include("trombonoscope.urls")), path('agenda/', include('calendrier.urls',namespace='calendrier')),
path("actu/", include("actu.urls")), path('partitions/', include('partitions.urls')),
path("avatar/", include("avatar.urls")), path('pads/', include('pads.urls')),
path("photos", gestion_views.PhotoList.as_view(), name="liste_photo"), path('admin/', admin.site.urls,),
path("add_photo", gestion_views.PhotoCreate.as_view(), name="add_photo"), path('trombonoscope/',include('trombonoscope.urls')),
path( path("actu/",include('actu.urls')),
"photo_edition/<int:pk>", gestion_views.PhotoUpdate.as_view(), name="edit_photo" path('avatar/', include('avatar.urls')),
), prefix_default_language=False )
path( urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"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,
)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View file

@ -1,3 +1,4 @@
""" """
WSGI config for Ernestophone project. WSGI config for Ernestophone project.
@ -9,8 +10,10 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
import os 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 from django.core.wsgi import get_wsgi_application
application = get_wsgi_application() application = get_wsgi_application()

View file

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

View file

@ -2,4 +2,4 @@ from django.apps import AppConfig
class ActuConfig(AppConfig): class ActuConfig(AppConfig):
name = "actu" name = 'actu'

View file

@ -7,34 +7,22 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [] dependencies = [
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="Actu", name='Actu',
fields=[ fields=[
( ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
"id", ('text', models.TextField(null=True, verbose_name='Info')),
models.AutoField( ('text_en', models.TextField(blank=True, null=True, verbose_name='Info en anglais')),
auto_created=True, ('order', models.IntegerField(verbose_name='ordre')),
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={ options={
"ordering": ("order",), 'ordering': ('order',),
"verbose_name_plural": "Actualités", 'verbose_name_plural': 'Actualités',
"verbose_name": "Actualité", 'verbose_name': 'Actualité',
}, },
), ),
] ]

View file

@ -1,23 +0,0 @@
# 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)",
),
),
]

View file

@ -1,26 +1,14 @@
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
class Actu(models.Model): class Actu(models.Model):
text = models.TextField(_("Info"), null=True, blank=False) text = models.TextField(_("Info"), null=True, blank=False)
text_en = models.TextField(("Info en anglais"), null=True, blank=True) text_en = models.TextField(("Info en anglais"), null=True, blank=True)
order = models.IntegerField(verbose_name=_("ordre")) 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): def __str__(self):
return self.text return self.text
class Meta: class Meta:
verbose_name = _("Actualité") verbose_name = _("Actualité")
verbose_name_plural = _("Actualités") verbose_name_plural = _("Actualités")
ordering = ("order",) ordering = ('order',)

View file

@ -2,10 +2,11 @@ from django.urls import path
from actu import views from actu import views
app_name = "actu" app_name = "actu"
urlpatterns = [ urlpatterns = [
path("", views.ActuList.as_view(), name="liste"), path("", views.ActuList.as_view(), name="liste"),
path("ajouter", views.ActuCreate.as_view(), name="add_actu"), path("ajouter", views.ActuCreate.as_view(), name="add_actu"),
path("edition/<int:pk>", views.ActuUpdate.as_view(), name="edit_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")
] ]

View file

@ -1,9 +1,9 @@
from django.http import HttpResponseRedirect from django.shortcuts import render
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 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
class ActuList(ChefRequiredMixin, ListView): class ActuList(ChefRequiredMixin, ListView):
@ -14,7 +14,7 @@ class ActuList(ChefRequiredMixin, ListView):
class ActuCreate(ChefRequiredMixin, CreateView): class ActuCreate(ChefRequiredMixin, CreateView):
model = Actu model = Actu
fields = ["text", "order", "text_en", "rainbow"] fields = ["text","order","text_en"]
template_name = "actu/create_actu.html" template_name = "actu/create_actu.html"
success_url = reverse_lazy("actu:liste") success_url = reverse_lazy("actu:liste")
@ -26,7 +26,7 @@ class ActuCreate(ChefRequiredMixin, CreateView):
class ActuUpdate(ChefRequiredMixin, UpdateView): class ActuUpdate(ChefRequiredMixin, UpdateView):
model = Actu model = Actu
fields = ["text", "order", "text_en", "rainbow"] fields = ["text","order","text_en"]
template_name = "actu/update_actu.html" template_name = "actu/update_actu.html"
success_url = reverse_lazy("actu:liste") success_url = reverse_lazy("actu:liste")

View file

@ -1,28 +1,6 @@
from django.contrib import admin 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(Event)
admin.site.register(Participants, ParticipantsAdmin)

View file

@ -2,4 +2,4 @@ from django.apps import AppConfig
class CalendrierConfig(AppConfig): class CalendrierConfig(AppConfig):
name = "calendrier" name = 'calendrier'

View file

@ -1,49 +1,44 @@
from calendar import HTMLCalendar
from datetime import date
from itertools import groupby
from django.utils.html import conditional_escape as esc 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 django.utils.translation import gettext_lazy as _
from datetime import date
class EventCalendar(HTMLCalendar): class EventCalendar(HTMLCalendar):
def __init__(self, pEvents): def __init__(self, pEvents):
super(EventCalendar, self).__init__() 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): def formatday(self, day, weekday):
if day != 0: if day != 0:
cssclass = self.cssclasses[weekday] cssclass = self.cssclasses[weekday]
if date.today() == date(self.year, self.month, day): if date.today() == date(self.year, self.month, day):
cssclass += " today" cssclass += ' today'
if day in self.events: if day in self.events:
cssclass += " filled" cssclass += ' filled'
body = [] body = []
for ev in self.events[day]: for ev in self.events[day]:
body.append('<a href="/agenda/' + '%s"' % ev.id) body.append(_('<a href="/agenda/') + '%s">' % ev.id)
if ev.calendrier == "C": body.append(esc(ev.nom))
body.append('style="color:#160083">' + esc(ev.nom)) body.append('</a><br/>')
elif ev.calendrier == "D": return self.day_cell(cssclass,
body.append('style="color:#770083">' + esc(ev.nom)) '<div class="dayNumber">%d</div> %s'
else: % (day, ''.join(body)))
body.append(">" + esc(ev.nom)) return self.day_cell(cssclass,
body.append("</a><br/>") '<div class="dayNumber">%d</div>' % day)
return self.day_cell( return self.day_cell('noday', '&nbsp;')
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", "&nbsp;")
def formatmonth(self, year, month): def formatmonth(self, year, month):
self.year, self.month = year, month self.year, self.month = year, month
return super(EventCalendar, self).formatmonth(year, month) return super(EventCalendar, self).formatmonth(year, month)
def group_by_day(self, pEvents): def group_by_day(self, pEvents):
def field(ev): def field(ev): return(ev.date.day)
return ev.date.day return dict(
[(dat, list(items)) for dat, items in groupby(pEvents, field)]
return dict([(dat, list(items)) for dat, items in groupby(pEvents, field)]) )
def day_cell(self, cssclass, body): def day_cell(self, cssclass, body):
return '<td class="%s">%s</td>' % (cssclass, body) return '<td class="%s">%s</td>' % (cssclass, body)

View file

@ -1,65 +1,61 @@
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _
from gestion.models import ErnestoUser
from calendrier.models import Event, Participants from calendrier.models import Event, Participants
from gestion.models import ErnestoUser
from django.utils.translation import gettext_lazy as _
class ModifEventForm(forms.ModelForm): class ModifEventForm(forms.ModelForm):
class Meta: class Meta:
model = Event model = Event
exclude = ["slug"] exclude = ['slug']
widgets = { widgets = {
"description": forms.Textarea( 'description': forms.Textarea(attrs={
attrs={"placeholder": _("facultatif, balises html supportées")} "placeholder": _("facultatif, balises html supportées")}),
), 'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}),
"date": forms.TextInput(attrs={"placeholder": "jj/mm/aaaa"}), 'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
"debut": forms.TextInput(attrs={"placeholder": "hh:mm"}), 'fin': forms.TextInput(attrs={"placeholder": _('hh:mm facultatif')})
"fin": forms.TextInput(attrs={"placeholder": _("hh:mm facultatif")}),
} }
class EventForm(forms.ModelForm): class EventForm(forms.ModelForm):
class Meta: class Meta:
model = Event model = Event
exclude = ["slug"] exclude = ['slug']
widgets = { widgets = {
"nomcourt": forms.TextInput(attrs={"placeholder": _("9 caractères max")}), 'nomcourt': forms.TextInput(
"description": forms.Textarea( attrs={"placeholder": _('9 caractères max')}),
attrs={"placeholder": _("facultatif, balises html supportées")} 'description': forms.Textarea(
), attrs={"placeholder": _("facultatif, balises html supportées")}),
"date": forms.TextInput(attrs={"placeholder": "jj/mm/aaaa"}), 'date': forms.TextInput(attrs={"placeholder": 'jj/mm/aaaa'}),
"debut": forms.TextInput(attrs={"placeholder": "hh:mm"}), 'debut': forms.TextInput(attrs={"placeholder": 'hh:mm'}),
"fin": forms.TextInput(attrs={"placeholder": _("hh:mm facultatif")}), 'fin': forms.TextInput(attrs={"placeholder": _('hh:mm facultatif')}),
} }
class ParticipantsForm(forms.ModelForm): class ParticipantsForm(forms.ModelForm):
class Meta: class Meta:
model = Participants model = Participants
fields = ( fields = ('reponse', 'details')
"reponse",
"details",
"dont_play_main",
"instrument",
"instrument_autre",
)
widgets = { widgets = {
"details": forms.Textarea(attrs={"placeholder": _("50 caractères max")}), 'details': forms.Textarea(
attrs={"placeholder": _("50 caractères max")}),
} }
class ChangeDoodleName(forms.ModelForm): class ChangeDoodleName(forms.ModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ChangeDoodleName, self).__init__(*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): def save(self, *args, **kwargs):
super(ChangeDoodleName, self).save(*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.profile.save()
self.instance.save() self.instance.save()
class Meta: class Meta:
model = ErnestoUser model = ErnestoUser
fields = ("doodlename",) fields = ('doodlename',)

View file

@ -7,82 +7,37 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("gestion", "0001_initial"), ('gestion', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="Event", name='Event',
fields=[ fields=[
( ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
"id", ('nom', models.CharField(max_length=100)),
models.AutoField( ('nomcourt', models.CharField(max_length=9, verbose_name='Nom court')),
auto_created=True, ('date', models.DateField()),
primary_key=True, ('debut', models.TimeField()),
verbose_name="ID", ('fin', models.TimeField(blank=True, null=True)),
serialize=False, ('slug', models.CharField(max_length=7, editable=False, unique=True)),
), ('lieu', models.CharField(max_length=200)),
), ('description', models.TextField(blank=True)),
("nom", models.CharField(max_length=100)), ('desc_users', models.TextField(blank=True, verbose_name='Infos (visible seulement des fanfaron-ne-s)', null=True)),
("nomcourt", models.CharField(max_length=9, verbose_name="Nom court")), ('calendrier', models.BooleanField(verbose_name='Afficher dans le calendrier pour tous', default=False)),
("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={ options={
"verbose_name": "Événement", 'verbose_name': 'Événement',
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name="Participants", name='Participants',
fields=[ fields=[
( ('id', models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', serialize=False)),
"id", ('reponse', models.CharField(max_length=20, choices=[('oui', 'Oui'), ('non', 'Non'), ('pe', 'Peut-être')], default='non', verbose_name='Réponse')),
models.AutoField( ('details', models.CharField(blank=True, max_length=50)),
auto_created=True, ('event', models.ForeignKey(to='calendrier.Event', on_delete=models.CASCADE)),
primary_key=True, ('participant', models.ForeignKey(to='gestion.ErnestoUser', on_delete=models.CASCADE)),
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
),
),
], ],
), ),
] ]

View file

@ -1,63 +1,43 @@
# Generated by Django 2.2.14 on 2020-07-14 15:59 # Generated by Django 2.2.14 on 2020-07-14 15:59
import uuid
from django.db import migrations, models from django.db import migrations, models
import uuid
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("calendrier", "0001_initial"), ('calendrier', '0001_initial'),
] ]
operations = [ operations = [
migrations.AlterModelOptions( migrations.AlterModelOptions(
name="event", name='event',
options={"verbose_name": "Evenement"}, options={'verbose_name': 'Evenement'},
), ),
migrations.AddField( migrations.AddField(
model_name="event", model_name='event',
name="desc_users_en", name='desc_users_en',
field=models.TextField( field=models.TextField(blank=True, null=True, verbose_name='Infos en anglais (visible seulement des fanfaron-ne-s)'),
blank=True,
null=True,
verbose_name="Infos en anglais (visible seulement des fanfaron-ne-s)",
),
), ),
migrations.AddField( migrations.AddField(
model_name="event", model_name='event',
name="description_en", name='description_en',
field=models.TextField(blank=True), field=models.TextField(blank=True),
), ),
migrations.AlterField( migrations.AlterField(
model_name="event", model_name='event',
name="calendrier", name='calendrier',
field=models.CharField( 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),
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( migrations.AlterField(
model_name="event", model_name='event',
name="slug", name='slug',
field=models.CharField( field=models.CharField(default=uuid.uuid1, editable=False, max_length=7, unique=True),
default=uuid.uuid1, editable=False, max_length=7, unique=True
),
), ),
migrations.AlterField( migrations.AlterField(
model_name="participants", model_name='participants',
name="reponse", name='reponse',
field=models.CharField( field=models.CharField(choices=[('oui', 'Oui'), ('non', 'Non'), ('pe', 'Peut-etre')], default='non', max_length=20, verbose_name='Réponse'),
choices=[("oui", "Oui"), ("non", "Non"), ("pe", "Peut-etre")],
default="non",
max_length=20,
verbose_name="Réponse",
),
), ),
] ]

View file

@ -1,22 +0,0 @@
# 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",
),
),
]

View file

@ -1,28 +0,0 @@
# 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),
),
]

View file

@ -1,46 +0,0 @@
# 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",
),
),
]

View file

@ -1,41 +0,0 @@
# 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,
),
),
]

View file

@ -1,31 +0,0 @@
# 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"
),
),
]

View file

@ -1,17 +0,0 @@
# 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'),
),
]

View file

@ -1,82 +1,54 @@
import uuid
from django.db import models from django.db import models
import uuid
from gestion.models import ErnestoUser
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from gestion.models import INSTRU_CHOICES, ErnestoUser
ANSWERS = ( ANSWERS = (
("oui", _("Oui")), ('oui', _('Oui')),
("non", _("Non")), ('non', _('Non')),
("pe", _("Peut-etre")), ('pe', _('Peut-etre')),
) )
class Event(models.Model): class Event(models.Model):
nom = models.CharField(max_length=100) nom = models.CharField(max_length=100)
nomcourt = models.CharField(max_length=9, verbose_name=_("Nom court")) nomcourt = models.CharField(max_length=9, verbose_name=_("Nom court"))
date = models.DateField() date = models.DateField()
debut = models.TimeField() debut = models.TimeField()
fin = models.TimeField(blank=True, null=True) fin = models.TimeField(blank=True, null=True)
slug = models.CharField( slug = models.CharField(max_length=7, editable=False, unique=True, default=uuid.uuid1)
max_length=7, editable=False, unique=True, default=uuid.uuid1
)
lieu = models.CharField(max_length=200) lieu = models.CharField(max_length=200)
description = models.TextField(blank=True) description = models.TextField(blank=True)
description_en = models.TextField(blank=True) description_en = models.TextField(blank=True)
desc_users = models.TextField( desc_users = models.TextField(
blank=True, blank=True,
verbose_name=_("Infos (visible seulement des fanfaron·ne·s)"), verbose_name=_("Infos (visible seulement des fanfaron-ne-s)"),
null=True, null=True)
)
desc_users_en = models.TextField( desc_users_en = models.TextField(
blank=True, blank=True,
verbose_name=_("Infos en anglais (visible seulement des fanfaron·ne·s"), verbose_name=_("Infos en anglais (visible seulement des fanfaron-ne-s)"),
null=True, null=True)
)
CALENDRIER_CHOICES = [ CALENDRIER_CHOICES = [
("F", _("Visible seulement par les fanfarons")), ('F', _('Visible seulement par les fanfarons')),
("T", _("Afficher dans le calendrier pour tous")), ('T', _('Afficher dans le calendrier pour tous')),
("H", _("Hall of fame")), ('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( calendrier = models.CharField(
max_length=1, max_length=1,
choices=CALENDRIER_CHOICES, choices=CALENDRIER_CHOICES,
default="F", default='F',
) )
def __str__(self): def __str__(self):
return self.nom return self.nom
class Meta: class Meta:
verbose_name = _("Evenement") verbose_name = _("Evenement")
class Participants(models.Model): class Participants(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE) event = models.ForeignKey(Event, on_delete=models.CASCADE)
participant = models.ForeignKey(ErnestoUser, on_delete=models.CASCADE) participant = models.ForeignKey(ErnestoUser, on_delete=models.CASCADE)
reponse = models.CharField( reponse = models.CharField(_("Réponse"), max_length=20, default="non",
_("Réponse"), max_length=20, default="non", choices=ANSWERS 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) 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') ]

View file

@ -1,38 +0,0 @@
.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;
}

View file

@ -1,683 +0,0 @@
/* 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
}

View file

@ -13,23 +13,10 @@
<!-- One --> <!-- One -->
<section class="wrapper style1" > <section class="wrapper style1" >
<div class="inner"> <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"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a> <a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
</div> </div>
{% endif %}
</span></div> </span></div>
<h2 align="center">{% trans "Découvrez les différents évènements de l'Ernestophone !" %}</h2> <h2 align="center">{% trans "Découvrez les différents évènements de l'Ernestophone !" %}</h2>
@ -46,7 +33,15 @@
<a href="mailto:fanfare@ens.fr" class="icon fa-envelope fa-5x "><span <a href="mailto:fanfare@ens.fr" class="icon fa-envelope fa-5x "><span
class="label">Mail</span></a> class="label">Mail</span></a>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
&nbsp;
<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> </div>
</div> </div>
@ -103,7 +98,7 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<h1> {% blocktrans count counter=events_passe|length %}Evénement passé :{% plural %}Evénements passés :{% endblocktrans %} </h1> <h1> {% blocktrans count counter=events_passe|length %}Evénement passé :{% plural %}Evénements passés :{% endblocktrans %} </h1>
<div class="table-wrapper" color="white"> <div class="table-wrapper" color="white">
@ -159,5 +154,4 @@
</div> </div>
{% endblock %} {% endblock %}

View file

@ -1,10 +1,9 @@
{% extends "gestion/base.html" %} {% extends "gestion/base.html" %}
{% load static %} {% load staticfiles %}
{% load frenchmonth %} {% load frenchmonth %}
{% load i18n %} {% load i18n %}
{% load translate %} {% load translate %}
{% load autotranslate %} {% load autotranslate %}
{% get_current_language as current_language %} {% get_current_language as current_language %}
{% block extrahead %} {% block extrahead %}
@ -17,141 +16,61 @@
<div id="main"> <div id="main">
<section class="wrapper style1"> <section class="wrapper style1">
<div class="inner"> <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)">
<div id="instagram-feed" class="instagram_feed"> </div> <h4> {% blocktrans count counter=actu|length %}Actualité des chef·fe·s:{% plural %}Actualités des chef·fe·s:{% endblocktrans %}</h4>
<ul>
{% for a in actu %}
<li>{% autotranslate current_language a.text a.text_en %}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<h4>{% trans "Agenda :" %} </h4>
<div class="row"> <div class="row">
<div class="6u 12u$(small)"> <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" > <table width="100%" style="background-color:#e4522f" >
<tr> <tr>
<td width="20%" align="left"> <td width="20%" align="left">
&lt;&lt; &lt;&lt;
{% if current_language == "fr" %} {% ifequal current_language "fr" %}
<a href="{% url "calendrier:view-month" PreviousYear PreviousMonth %}">{{PreviousMonthName|frenchmonth}} {{PreviousYear}}</a> <a href="{% url "calendrier:view-month" PreviousYear PreviousMonth %}">{{PreviousMonthName|frenchmonth}} {{PreviousYear}}</a>
{% else %} {% else %}
<a href="{% url "calendrier:view-month" PreviousYear PreviousMonth %}">{{PreviousMonthName}} {{PreviousYear}}</a> <a href="{% url "calendrier:view-month" PreviousYear PreviousMonth %}">{{PreviousMonthName}} {{PreviousYear}}</a>
{% endif %} {% endifequal %}
</td> </td>
<td width="20%" align="center"><a href="{% url "calendrier:home" %}">{% trans "Aujourd'hui" %}</a></td> <td width="20%" align="center"><a href="{% url "calendrier:home" %}">{% trans "Aujourd'hui" %}</a></td>
<td width="20%" align="right"> <td width="20%" align="right">
{% if current_language == "fr" %} {% ifequal current_language "fr" %}
<a href="{% url "calendrier:view-month" NextYear NextMonth %}">{{NextMonthName|frenchmonth}} {{NextYear}}</a> &gt;&gt; <a href="{% url "calendrier:view-month" NextYear NextMonth %}">{{NextMonthName|frenchmonth}} {{NextYear}}</a> &gt;&gt;
{% else %} {% else %}
<a href="{% url "calendrier:view-month" NextYear NextMonth %}">{{NextMonthName}} {{NextYear}}</a> &gt;&gt; <a href="{% url "calendrier:view-month" NextYear NextMonth %}">{{NextMonthName}} {{NextYear}}</a> &gt;&gt;
{% endif %} {% endifequal %}
</td> </td>
</tr> </tr>
</table> </table>
<div id="calendar"> <div id="calendar">
{% if user.profile.is_chef_event or user.profile.is_chef %} {% ifequal current_language "fr" %}
{% if current_language == "fr" %}
{{Calendar_chef|translate}}
{% else %}
{{Calendar_chef}}
{% endif %}
{% else %}
{% if current_language == "fr" %}
{{Calendar|translate}} {{Calendar|translate}}
{% else %} {% else %}
{{Calendar}} {{Calendar}}
{% endif %} {% endifequal %}
{% endif%}
</div> </div>
{% if user.profile.is_chef_event or user.profile.is_chef %} {% if user.profile.is_chef %}
<a href="{% url "calendrier:create_event" %}" class="button">{% trans "Ajouter un évènement" %}</a> <a href="{% url "calendrier:create_event" %}" class="button">{% trans "Ajouter un évènement" %}</a>
{% endif %} {% endif %}
</div> </div>
<div class="1u 12u$(small)"><p></p></div> <div class="1u 12u$(small)"><p></p></div>
<div class="5u 12u$(small)"> <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 %} {% if events_a_venir_not_answered %}
<div class="box" style="background-color:#e4522f"> <div class="box" style="background-color:#e4522f">
<h1> {% blocktrans count counter=events_a_venir_not_answered|length %}Doodle à remplir !!!! :{% plural %}Doodles à remplir !!!! :{% endblocktrans %} </h1> <h1> {% blocktrans count counter=events_a_venir_not_answered|length %}Doodle à remplir !!!! :{% plural %}Doodles à remplir !!!! :{% endblocktrans %} </h1>
@ -263,29 +182,10 @@
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
</div> </div>
</section> </section>
</div> </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 %} {% endblock %}

View file

@ -6,12 +6,6 @@
<div id="main"> <div id="main">
<section class="wrapper style1"> <section class="wrapper style1">
<div class="inner"> <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="row">
<div class="6u 12u$(small)"> <div class="6u 12u$(small)">
{% if envoi %}<p>{% trans "Votre réponse a été enregistrée !" %}</p>{% endif %} {% if envoi %}<p>{% trans "Votre réponse a été enregistrée !" %}</p>{% endif %}
@ -19,69 +13,15 @@
<p><a href="{% url 'calendrier:view-event' id %}" class="button alt">{% trans "Retour à l'événement" %}</a></p> <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> <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"> <form action="{% url 'calendrier:reponse' id %}" method="post">
{% csrf_token %} {% csrf_token %}
{{ form.non_field_errors }} {{ form.as_p }}
{% 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" %}" /> <input type="submit" value="{% trans "Valider" %}" />
</form> </form>
</div> </div>
</div> </div>
{% endif %}
</div> </div>
</section> </section>
</div> </div>
{% endblock %} {% 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 %}

View file

@ -0,0 +1,17 @@
{% 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 %}

View file

@ -3,23 +3,15 @@
{% load autotranslate %} {% load autotranslate %}
{% get_current_language as current_language %} {% get_current_language as current_language %}
{% block titre %}{{ event.nom.capitalize }}{% endblock %} {% block titre %}{{ event.nom.capitalize }}{% endblock %}
{% block extrahead %}
{% endblock %}
{% block content %} {% block content %}
<div id="main"> <div id="main">
<section class="wrapper style1"> <section class="wrapper style1">
<div class="inner"> <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="row">
<div class="6u 12u$(small)"> <div class="6u 12u$(small)">
<div id="viewevent"> <div id="viewevent">
<h2>{{ event.nom.capitalize }}</h2> <h2>{{ event.nom.capitalize }}</h2>
<h4> <h4>
{% blocktrans with date=event.date%} Le {{ date }}{% endblocktrans %} {% blocktrans with date=event.date%} Le {{ date }}{% endblocktrans %}
@ -32,7 +24,6 @@
</h4> </h4>
{% if user.is_authenticated and event.desc_users %} {% if user.is_authenticated and event.desc_users %}
<div class="box"> <div class="box">
{% autotranslate current_language event.desc_users event.desc_users_en %} {% autotranslate current_language event.desc_users event.desc_users_en %}
@ -85,12 +76,12 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<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> <p><a href="{% url 'calendrier:reponse' event.id %}" class="button">{% trans "Répondre à l'événement" %}</a></p>
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="6u 12u$(small)"> <div class="6u 12u$(small)">
{% if user.profile.is_chef or user.profile.is_chef_event %} {% if instrument_count and user.profile.is_chef %}
<table class="table"> <table class="table">
<tr> <tr>
<th>{% trans "Instrument" %}</th> <th>{% trans "Instrument" %}</th>
@ -162,14 +153,14 @@
{% endfor %} {% endfor %}
</table> </table>
{% endif %} {% endif %}
{% if user.profile.is_chef or user.profile.is_chef_event %} {% if multi_instrumentistes and user.profile.is_chef %}
{% if multi_instrumentistes %}
<h1>{% blocktrans count counter=multi_instrumentistes|length %}Multi-instrumentiste présent :{% plural %}Multi-instrumentistes présents{% endblocktrans %}</h1> <h1>{% blocktrans count counter=multi_instrumentistes|length %}Multi-instrumentiste présent :{% plural %}Multi-instrumentistes présents{% endblocktrans %}</h1>
<table class="table"> <table class="table">
<tr> <tr>
<th>{% trans "Nom" %}</th> <th>{% trans "Nom" %}</th>
<th>{% trans "Instrument" %}</th> <th>{% trans "Instrument principal" %}</th>
<th>{% trans "Instrument·s bonus" %}</th> <th>{% trans "Instrument·s bonus" %}</th>
<th>{% trans "Réponse" %}</th> <th>{% trans "Réponse" %}</th>
</tr> </tr>
@ -182,36 +173,21 @@
{% endif %} {% endif %}
</td> </td>
<td>{% if participant.dont_play_main == 'Oui' %} <td>{% if participant.participant.instru == "Autre" %}
{% if participant.instrument == "Autre" %}
{{participant.instrument_autre}}
{% else %}
{{participant.instrument}}
{% endif %}
{% elif participant.participant.instru == "Autre" %}
{{participant.participant.instru_autre}} {{participant.participant.instru_autre}}
{% else %} {% else %}
{{ participant.participant.instru }} {{ participant.participant.instru }}
{% endif %}</td> {% endif %}</td>
<td>{% if participant.dont_play_main == 'Oui' %} <td>{{ participant.participant.instru_bonus }}</td>
{% 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> <td>{{participant.reponse}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
{% endif %} {% endif %}
{% endif %}
</div> </div>
<div class="6u 12u$(small)"> <div class="6u 12u$(small)">
{% if user.is_authenticated %} {% if user.is_authenticated %}
<div id="actions"> {% if user.profile.is_chef or user.profile.is_chef_event %} <div id="actions"> {% if user.profile.is_chef %}
<p><a href="{% url "calendrier:edit_event" event.id %}" class="button alt">{% trans "Modifier l'événement" %}</a> &nbsp <a href="{% url "calendrier:delete_event" event.id %}" class="button alt">{% trans "Supprimer l'événement" %}</a></p> <p><a href="{% url "calendrier:edit_event" event.id %}" class="button alt">{% trans "Modifier l'événement" %}</a> &nbsp <a href="{% url "calendrier:delete_event" event.id %}" class="button alt">{% trans "Supprimer l'événement" %}</a></p>
{% endif %} {% endif %}
<p><a href="{% url 'calendrier:change-doodle-name' event.id %}" class="button">{% trans "Changer mon nom pour le doodle" %}</a> &nbsp <a href="{% url 'calendrier:home' %}" class="button">{% trans "Retour au calendrier" %}</a></p> <p><a href="{% url 'calendrier:change-doodle-name' event.id %}" class="button">{% trans "Changer mon nom pour le doodle" %}</a> &nbsp <a href="{% url 'calendrier:home' %}" class="button">{% trans "Retour au calendrier" %}</a></p>
@ -219,61 +195,7 @@
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endif %}
</div> </div>
</section> </section>
</div> </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');
});
{% if current_language == "fr" %}
singleEvent.setOption({ lang: 'fr' });
{% else %}
singleEvent.setOption({ lang: 'en' });
{% endif %}
</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 %} {% endblock %}

View file

@ -20,7 +20,7 @@ def translate(tex):
tex = tex.replace("December", "Décembre", 1) tex = tex.replace("December", "Décembre", 1)
tex = tex.replace("Mon", "Lun", 1) tex = tex.replace("Mon", "Lun", 1)
tex = tex.replace("Tue", "Mar", 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("Thu", "Jeu", 1)
tex = tex.replace("Fri", "Ven", 1) tex = tex.replace("Fri", "Ven", 1)
tex = tex.replace("Sat", "Sam", 1) tex = tex.replace("Sat", "Sam", 1)

View file

@ -4,8 +4,8 @@ from django.contrib.auth import get_user_model
from django.template.defaultfilters import urlencode from django.template.defaultfilters import urlencode
from django.test import Client, TestCase from django.test import Client, TestCase
from django.utils import timezone from django.utils import timezone
from gestion.models import ErnestoUser
from gestion.models import ErnestoUser
from ..models import Event from ..models import Event
User = get_user_model() User = get_user_model()
@ -28,7 +28,11 @@ class TestViews(TestCase):
ernesto = new_user("ernesto", ernesto=True) ernesto = new_user("ernesto", ernesto=True)
ernesto_c = Client() ernesto_c = Client()
ernesto_c.force_login(ernesto) 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 # A private and a public event
now = timezone.now() now = timezone.now()
later = now + timedelta(seconds=3600) later = now + timedelta(seconds=3600)
@ -40,7 +44,7 @@ class TestViews(TestCase):
fin=later.time(), fin=later.time(),
slug="privevt", slug="privevt",
lieu="somewhere", lieu="somewhere",
calendrier=False, calendrier=False
) )
self.pub_event = Event.objects.create( self.pub_event = Event.objects.create(
nom="public event", nom="public event",
@ -50,7 +54,7 @@ class TestViews(TestCase):
fin=later.time(), fin=later.time(),
slug="pubevt", slug="pubevt",
lieu="somewhere", lieu="somewhere",
calendrier=True, calendrier=True
) )
# Everyone can see theses pages # Everyone can see theses pages
@ -84,16 +88,13 @@ class TestViews(TestCase):
chef, _ = self.client_matrix[0] chef, _ = self.client_matrix[0]
codereps = ["oui", "non", "pe"] codereps = ["oui", "non", "pe"]
for coderep in codereps: for coderep in codereps:
url = "/calendar/rep/{}/{}/{}".format( url = "/calendar/rep/{}/{}/{}".format(chef.profile.slug, self.priv_event.slug, coderep)
chef.profile.slug, self.priv_event.slug, coderep
)
self._everyone_can_get(url, redirect_url="/calendar/") self._everyone_can_get(url, redirect_url="/calendar/")
# Only ernesto members can get theses pages # Only ernesto members can get theses pages
def _get_restricted_page(self, url, chef_only=False, redirect_url=None): def _get_restricted_page(self, url, chef_only=False, redirect_url=None):
"""Shorthand for testing wether a page in only accessible by ernesto members""" """Shorthand for testing wether a page in only accessible by ernesto members"""
def user_allowed(user): def user_allowed(user):
if user is None: if user is None:
return False return False

View file

@ -1,17 +1,17 @@
from django.urls import path from django.urls import path
from . import views from . import views
from .views import EventDelete, EventUpdate from .views import EventUpdate, EventDelete
app_name = "calendrier" app_name = 'calendrier'
urlpatterns = [ urlpatterns = [
path("", views.Agenda.as_view(), name="liste"), path('', views.liste, name='liste'),
path("calendar", views.Home.as_view(), name="home"), path("calendar", views.home, name="home"),
path("new", views.CreateEvent.as_view(), name="create_event"), path("new", views.create_event, name="create_event"),
path("edition/<int:pk>", EventUpdate.as_view(), name="edit_event"), path("edition/<int:pk>", EventUpdate.as_view(), name="edit_event"),
path("supprimer/<int:pk>", EventDelete.as_view(), name="delete_event"), path("supprimer/<int:pk>", EventDelete.as_view(), name="delete_event"),
path("<int:id>/changename", views.ChangeName.as_view(), name="change-doodle-name"), path("<int:id>/changename", views.changename, name="change-doodle-name"),
path("<int:id>/reponse", views.ReponseEvent.as_view(), name="reponse"), path("<int:id>/reponse", views.reponse, name="reponse"),
path("<int:pYear>/<int:pMonth>", views.Calendar.as_view(), name="view-month"), path("<int:pYear>/<int:pMonth>", views.calendar, name="view-month"),
path("<int:id>", views.ViewEvent.as_view(), name="view-event"), path("<int:id>", views.view_event, name="view-event"),
] ]

View file

@ -1,418 +1,261 @@
import random
import string
from calendar import monthrange
from collections import defaultdict from collections import defaultdict
from datetime import date, datetime from datetime import date, datetime
import string
from actu.models import Actu import random
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q 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 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 calendrier.calend import EventCalendar
from calendrier.forms import (ChangeDoodleName, EventForm, ModifEventForm, from calendar import monthrange
ParticipantsForm) from calendrier.forms import ModifEventForm, EventForm, ParticipantsForm, ChangeDoodleName
from calendrier.models import Event, Participants from calendrier.models import Event, Participants
from partitions.decorators import chef_required
def generer(*args): def generer(*args):
caracteres = string.ascii_letters + string.digits caracteres = string.ascii_letters + string.digits
aleatoire = [random.choice(caracteres) for _ in range(6)] aleatoire = [random.choice(caracteres) for _ in range(6)]
return "".join(aleatoire) 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})
def named_month(pMonthNumber): def named_month(pMonthNumber):
return date(1900, pMonthNumber, 1).strftime("%B") 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)
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
class Home(Calendar): @login_required
@property def changename(request,id):
def pYear(self): if request.method == 'POST':
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.order_by('-creationDate')
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() requbis = request.POST.copy()
form = self.form_class(requbis, instance=request.user) form = ChangeDoodleName(requbis, instance=request.user)
if form.is_valid(): if form.is_valid():
form.save() form.save()
success = True success = True
return redirect("calendrier:view-event", id=self.kwargs["id"]) return redirect('calendrier:view-event',id=id)
else: else:
context = self.get_context_data() form = ChangeDoodleName(instance=request.user)
context["success"] = success return render(request, 'calendrier/changename.html',locals())
return render(request, self.template_name, context)
class CreateEvent(ChefEventRequiredMixin, TemplateView): @chef_required
form_class = EventForm def create_event(request):
template_name = "calendrier/create.html" if request.method == "POST":
form = EventForm(request.POST)
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(): if form.is_valid():
temp = True temp = True
while temp: while temp:
code = generer() code = generer()
try: try:
Event.objects.get(slug=code) Event.objects.get(slug=code)
except Event.DoesNotExist: except:
temp = False temp = False
nom = form.cleaned_data["nom"]
date = form.cleaned_data["date"] date = form.cleaned_data["date"]
date = date.strftime("%d/%m/%Y") date = date.strftime('%d/%m/%Y')
debut = form.cleaned_data["debut"]
obj = form.save(commit=False) obj = form.save(commit=False)
obj.slug = code obj.slug = code
obj.save() obj.save()
id = obj.id id = obj.id
return redirect("calendrier:view-event", id=id) envoi = True
else: return redirect('calendrier:view-event',id=id)
context = self.get_context_data()
return render(request, self.template_name, context) else:
form = EventForm()
return render(request, "calendrier/create.html", locals())
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
def post(self, request, *args, **kwargs): @login_required
ev = get_object_or_404(Event, id=self.kwargs["id"]) def reponse(request, id):
part = request.user.profile part = request.user.profile
try: ev = get_object_or_404(Event, id=id)
p = Participants.objects.get(event=ev, participant=part) if request.method == "POST":
except Participants.DoesNotExist: form = ParticipantsForm(request.POST)
p = None
form = self.form_class(request.POST, instance=p)
if form.is_valid(): if form.is_valid():
try:
p = Participants.objects.get(event=ev, participant=part)
p.delete()
except Participants.DoesNotExist:
pass
obj = form.save(commit=False) obj = form.save(commit=False)
# Si la participation existe déjà, ces 2 ligne sont redondantes
obj.event = ev obj.event = ev
obj.participant = part obj.participant = part
obj.save() obj.save()
return redirect("calendrier:view-event", id=self.kwargs["id"]) envoi = True
else: return redirect('calendrier:view-event',id=id)
context = self.get_context_data() else:
return render(request, self.template_name, context) form = ParticipantsForm()
return render(request, "calendrier/reponse.html", locals())
class EventUpdate(ChefEventRequiredMixin, UpdateView):
class EventUpdate(UpdateView):
model = Event model = Event
template_name = "calendrier/update.html" template_name = "calendrier/update.html"
form_class = ModifEventForm form_class = ModifEventForm
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(EventUpdate, self).get_context_data(**kwargs) ctx = super(EventUpdate, self).get_context_data(**kwargs)
ctx["id"] = self.get_object().id ctx['id'] = self.get_object().id
return ctx return ctx
def get_success_url(self): def get_success_url(self):
return reverse("calendrier:view-event", kwargs={"id": self.get_object().id}) 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)
class EventDelete(ChefEventRequiredMixin, DeleteView): class EventDelete(DeleteView):
model = Event model = Event
template_name = "calendrier/delete.html" template_name = "calendrier/delete.html"
success_url = reverse_lazy("calendrier:home") success_url = reverse_lazy("calendrier:home")
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(EventDelete, self).get_context_data(**kwargs) ctx = super(EventDelete, self).get_context_data(**kwargs)
ctx["id"] = self.get_object().id ctx['id'] = self.get_object().id
return ctx return ctx
@method_decorator(chef_required)
def dispatch(self, *args, **kwargs):
return super(EventDelete,self).dispatch(*args, **kwargs)

View file

@ -6,11 +6,12 @@ les permissions.
""" """
from django.contrib import admin 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.admin import UserAdmin
from django.contrib.auth.models import Group, Permission, User
from gestion.models import ErnestoUser, VideoGallery
from actu.models import Actu from actu.models import Actu
from gestion.models import ErnestoUser, Photo, VideoGallery
class UserProfileInline(admin.StackedInline): class UserProfileInline(admin.StackedInline):
@ -36,7 +37,6 @@ User.profile_phone = ProfileInfo("phone", "Téléphone")
User.profile_instru = ProfileInfo("instru", "Instrument joué") User.profile_instru = ProfileInfo("instru", "Instrument joué")
User.profile_is_ern = ProfileInfo("is_ernesto", "Ernestophoniste") User.profile_is_ern = ProfileInfo("is_ernesto", "Ernestophoniste")
User.profile_is_chef = ProfileInfo("is_chef", "Chef Fanfare") User.profile_is_chef = ProfileInfo("is_chef", "Chef Fanfare")
User.profile_is_chef_event = ProfileInfo("is_chef_event", "Respo événement")
User.profile_get_mails = ProfileInfo("mails", "Recevoir les mails") User.profile_get_mails = ProfileInfo("mails", "Recevoir les mails")
@ -58,7 +58,6 @@ class UserProfileAdmin(UserAdmin):
"profile_instru", "profile_instru",
"profile_is_ern", "profile_is_ern",
"profile_is_chef", "profile_is_chef",
"profile_is_chef_event",
] ]
list_display_links = ["username", "email", "first_name", "last_name"] list_display_links = ["username", "email", "first_name", "last_name"]
list_filter = ["profile__instru"] list_filter = ["profile__instru"]
@ -113,9 +112,7 @@ class UserProfileAdmin(UserAdmin):
user.groups.add(chef_group) user.groups.add(chef_group)
user.save() user.save()
admin.site.unregister(User) admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin) admin.site.register(User, UserProfileAdmin)
admin.site.register(VideoGallery) admin.site.register(VideoGallery)
admin.site.register(Photo)
admin.site.register(Actu) admin.site.register(Actu)

View file

@ -2,4 +2,4 @@ from django.apps import AppConfig
class GestionConfig(AppConfig): class GestionConfig(AppConfig):
name = "gestion" name = 'gestion'

View file

@ -1,71 +1,47 @@
from django import forms from django import forms
from django.contrib.auth.forms import UserChangeForm, UserCreationForm from gestion.models import ErnestoUser
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.tokens import default_token_generator
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from gestion.models import ErnestoUser
class RegistrationFormUser(UserCreationForm): class RegistrationFormUser(UserCreationForm):
class Meta: class Meta:
model = User model = User
fields = ( fields = ('username', 'first_name', 'last_name', 'password1',
"username", 'password2', 'email',)
"first_name",
"last_name",
"password1",
"password2",
"email",
)
class ChangeFormUser(UserChangeForm): class ChangeFormUser(UserChangeForm):
password = None password = None
class Meta: class Meta:
model = User model = User
fields = ( fields = ('first_name', 'last_name', 'email',)
"first_name",
"last_name",
"email",
)
class ChangeMembreForm(forms.ModelForm): class ChangeMembreForm(forms.ModelForm):
def clean(self): def clean(self):
cleaned_data = super(ChangeMembreForm, self).clean() cleaned_data = super(ChangeMembreForm, self).clean()
instru = cleaned_data.get("instru") instru=cleaned_data.get("instru")
instru_autre = cleaned_data.get("instru_autre") instru_autre = cleaned_data.get("instru_autre")
if (instru == "Autre") and not (instru_autre): if (instru == "Autre") and not (instru_autre):
raise forms.ValidationError(_("Préçisez quel autre instrument")) 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") instru_bonus = cleaned_data.get("instru_bonus")
if (multi_instru == "Oui") and not (instru_bonus): if (multi_instru == "Oui") and not (instru_bonus):
raise forms.ValidationError( raise forms.ValidationError(_("Préçisez quel·s instrument·s supplémentaire·s vous pouvez jouer"))
_("Préçisez quel·s instrument·s supplémentaire·s vous pouvez jouer")
)
return cleaned_data return cleaned_data
class Meta: class Meta:
model = ErnestoUser model = ErnestoUser
fields = ( fields = ("phone", "instru","instru_autre","multi_instrumentiste","instru_bonus")
"phone",
"instru",
"instru_autre",
"multi_instrumentiste",
"instru_bonus",
)
class InscriptionMembreForm(ChangeMembreForm): class InscriptionMembreForm(ChangeMembreForm):
validation = forms.CharField(max_length=100, widget=forms.PasswordInput) validation = forms.CharField(max_length=100, widget=forms.PasswordInput)
class Meta: class Meta:
model = ErnestoUser model = ErnestoUser
fields = ( fields = ("phone", "instru","instru_autre",'multi_instrumentiste',
"phone", 'instru_bonus' )
"instru",
"instru_autre",
"multi_instrumentiste",
"instru_bonus",
)

View file

@ -1,5 +1,5 @@
from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
from django.conf import settings
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -10,64 +10,28 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="ErnestoUser", name='ErnestoUser',
fields=[ 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)),
( (
"id", 'user',
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( models.OneToOneField(
to=settings.AUTH_USER_MODEL, to=settings.AUTH_USER_MODEL,
on_delete=models.CASCADE, on_delete=models.CASCADE,
related_name="profile", related_name='profile'
), )
), ),
], ],
options={ options={
"verbose_name": "Profil Ernestophoniste", 'verbose_name': 'Profil Ernestophoniste',
"verbose_name_plural": "Profil Ernestophoniste", 'verbose_name_plural': 'Profil Ernestophoniste',
}, },
), ),
] ]

View file

@ -7,157 +7,80 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
("gestion", "0001_initial"), ('gestion', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name="VideoGallery", name='VideoGallery',
fields=[ fields=[
( ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
"id", ('name', models.CharField(max_length=127)),
models.AutoField( ('order', models.IntegerField(verbose_name='ordre')),
auto_created=True, ('url', models.URLField()),
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=127)),
("order", models.IntegerField(verbose_name="ordre")),
("url", models.URLField()),
], ],
options={ options={
"verbose_name_plural": "Videos", 'verbose_name_plural': 'Videos',
"verbose_name": "Video", 'verbose_name': 'Video',
}, },
), ),
migrations.RemoveField( migrations.RemoveField(
model_name="ernestouser", model_name='ernestouser',
name="mails", name='mails',
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="instru_autre", name='instru_autre',
field=models.CharField( field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Lequel ?'),
blank=True, max_length=100, null=True, verbose_name="Lequel ?"
),
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="instru_bonus", name='instru_bonus',
field=models.CharField( field=models.CharField(blank=True, max_length=100, null=True, verbose_name='Le·s·quel·s ?'),
blank=True, max_length=100, null=True, verbose_name="Le·s·quel·s ?"
),
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="instru_trombonoscope", name='instru_trombonoscope',
field=models.CharField( field=models.CharField(blank=True, max_length=30, verbose_name='Instrument affiché sur le trombonoscope'),
blank=True,
max_length=30,
verbose_name="Instrument affiché sur le trombonoscope",
),
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="multi_instrumentiste", name='multi_instrumentiste',
field=models.CharField( 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 :"),
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( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="nom_trombonoscope", name='nom_trombonoscope',
field=models.CharField( field=models.CharField(blank=True, max_length=30, verbose_name='Nom affiché sur le trombonoscope'),
blank=True,
max_length=30,
verbose_name="Nom affiché sur le trombonoscope",
),
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="trombonoscope", name='trombonoscope',
field=models.CharField( 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 :'),
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( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="trombonoscope_colors", name='trombonoscope_colors',
field=models.CharField( 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'),
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( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="trombonoscope_fond", name='trombonoscope_fond',
field=colorful.fields.RGBColorField( field=colorful.fields.RGBColorField(default='#e4522f', verbose_name='Couleur de fond du profil'),
default="#e4522f", verbose_name="Couleur de fond du profil"
),
), ),
migrations.AddField( migrations.AddField(
model_name="ernestouser", model_name='ernestouser',
name="trombonoscope_texte", name='trombonoscope_texte',
field=colorful.fields.RGBColorField( field=colorful.fields.RGBColorField(default='#ffffff', verbose_name='Couleur du texte du profil'),
default="#ffffff", verbose_name="Couleur du texte du profil"
),
), ),
migrations.AlterField( migrations.AlterField(
model_name="ernestouser", model_name='ernestouser',
name="instru", name='instru',
field=models.CharField( 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é'),
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( migrations.AlterField(
model_name="ernestouser", model_name='ernestouser',
name="phone", name='phone',
field=models.CharField( field=models.CharField(blank=True, help_text='seulement visible par les chef·fe·s', max_length=20, verbose_name='Téléphone'),
blank=True,
help_text="seulement visible par les chef·fe·s",
max_length=20,
verbose_name="Téléphone",
),
), ),
] ]

View file

@ -1,85 +0,0 @@
# 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",
},
),
]

View file

@ -1,34 +0,0 @@
# 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,
),
),
]

View file

@ -1,28 +0,0 @@
# 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:",
),
),
]

View file

@ -1,24 +0,0 @@
# 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],
),
),
]

View file

@ -1,20 +0,0 @@
# 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"
),
),
]

View file

@ -1,28 +0,0 @@
# 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"),
),
]

View file

@ -1,18 +0,0 @@
# 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"),
),
]

View file

@ -5,76 +5,3 @@ class ChefRequiredMixin(UserPassesTestMixin):
def test_func(self): def test_func(self):
user = self.request.user user = self.request.user
return (user is not None) and hasattr(user, "profile") and user.profile.is_chef 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

View file

@ -1,167 +1,63 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
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.db import models
from colorful.fields import RGBColorField
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _ 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): class ErnestoUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile") user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
is_ernesto = models.BooleanField(_("Membre de l'Ernestophone"), default=True) is_ernesto = models.BooleanField(_("Membre de l'Ernestophone"), default=True)
is_chef = models.BooleanField(_("Chef Fanfare"), default=False) is_chef = models.BooleanField(_("Chef Fanfare"), default=False)
is_chef_event = models.BooleanField(_("Respo événements"), default=False) phone = models.CharField(_("Téléphone"), max_length=20, blank=True ,help_text= _("seulement visible par les chef·fe·s"))
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 = [ INSTRU_CHOICES = [
("#e4522f#ffffff", _("Orange et Blanc")), ('Clarinette', _('Clarinette')),
("#ffffff#000000", _("Blanc et Noir")), ('Euphonium', _('Euphonium')),
("#A8107C#000000", _("Rose et Noir")), ('Percussion', _('Percussion')),
("#10A4A8#ffffff", _("Bleu et Blanc")), ('Piccolo', _('Piccolo')),
("#26A810#000000", _("Vert et Noir")), ('Saxophone Alto', _('Saxophone Alto')),
("#A81026#ffffff", _("Rouge et Blanc")), ('Saxophone Ténor', _('Saxophone Ténor')),
("#E3E54C#000000", _("Jaune et Noir")), ('Saxophone Baryton', _('Saxophone Baryton')),
("autre", _("Autre")), ('Souba', _('Souba')),
('Trombone', _('Trombone')),
('Trompette', _('Trompette')),
('Autre', _('Autre')),
('ne sais pas', _('Je ne sais pas encore')),
] ]
instru = models.CharField( COLORS_CHOICES = [
_("Instrument joué"), ('#e4522f#ffffff', _('Orange et Blanc')),
max_length=40, ('#ffffff#000000', _('Blanc et Noir')),
blank=False, ('#A8107C#000000', _('Rose et Noir')),
choices=INSTRU_CHOICES, ('#10A4A8#ffffff', _('Bleu et Blanc')),
default="ne sais pas", ('#26A810#000000', _('Vert et Noir')),
) ('#A81026#ffffff', _('Rouge et Blanc')),
instru_autre = models.CharField( ('#E3E54C#000000', _('Jaune et Noir')),
_("Lequel ?"), null=True, max_length=100, blank=True ('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)
slug = models.CharField(max_length=7, editable=False, unique=True) slug = models.CharField(max_length=7, editable=False, unique=True)
doodlename = models.CharField(_("Nom pour le doodle"), max_length=30, blank=True) 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)
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: class Meta:
verbose_name = _("Profil Ernestophoniste") verbose_name = _("Profil Ernestophoniste")

View file

@ -545,7 +545,7 @@ pre code {
overflow-y: scroll; overflow-y: scroll;
} }
.container_carousel { .container {
width: 100%; width: 100%;
padding-right: 15px; padding-right: 15px;
padding-left: 15px; padding-left: 15px;
@ -554,25 +554,25 @@ pre code {
} }
@media (min-width: 576px) { @media (min-width: 576px) {
.container_carousel { .container {
max-width: 540px; max-width: 540px;
} }
} }
@media (min-width: 768px) { @media (min-width: 768px) {
.container_carousel { .container {
max-width: 720px; max-width: 720px;
} }
} }
@media (min-width: 992px) { @media (min-width: 992px) {
.container_carousel { .container {
max-width: 960px; max-width: 960px;
} }
} }
@media (min-width: 1200px) { @media (min-width: 1200px) {
.container_carousel { .container {
max-width: 1140px; max-width: 1140px;
} }
} }
@ -4157,7 +4157,7 @@ input[type="button"].btn-block {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
} }
.navbar > .container_carousel, .navbar > .container,
.navbar > .container-fluid { .navbar > .container-fluid {
display: -ms-flexbox; display: -ms-flexbox;
display: flex; display: flex;
@ -4242,7 +4242,7 @@ input[type="button"].btn-block {
} }
@media (max-width: 575.98px) { @media (max-width: 575.98px) {
.navbar-expand-sm > .container_carousel, .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid { .navbar-expand-sm > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@ -4267,7 +4267,7 @@ input[type="button"].btn-block {
padding-right: 0.5rem; padding-right: 0.5rem;
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.navbar-expand-sm > .container_carousel, .navbar-expand-sm > .container,
.navbar-expand-sm > .container-fluid { .navbar-expand-sm > .container-fluid {
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
@ -4284,7 +4284,7 @@ input[type="button"].btn-block {
} }
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
.navbar-expand-md > .container_carousel, .navbar-expand-md > .container,
.navbar-expand-md > .container-fluid { .navbar-expand-md > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@ -4309,7 +4309,7 @@ input[type="button"].btn-block {
padding-right: 0.5rem; padding-right: 0.5rem;
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.navbar-expand-md > .container_carousel, .navbar-expand-md > .container,
.navbar-expand-md > .container-fluid { .navbar-expand-md > .container-fluid {
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
@ -4326,7 +4326,7 @@ input[type="button"].btn-block {
} }
@media (max-width: 991.98px) { @media (max-width: 991.98px) {
.navbar-expand-lg > .container_carousel, .navbar-expand-lg > .container,
.navbar-expand-lg > .container-fluid { .navbar-expand-lg > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@ -4351,7 +4351,7 @@ input[type="button"].btn-block {
padding-right: 0.5rem; padding-right: 0.5rem;
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.navbar-expand-lg > .container_carousel, .navbar-expand-lg > .container,
.navbar-expand-lg > .container-fluid { .navbar-expand-lg > .container-fluid {
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
@ -4368,7 +4368,7 @@ input[type="button"].btn-block {
} }
@media (max-width: 1199.98px) { @media (max-width: 1199.98px) {
.navbar-expand-xl > .container_carousel, .navbar-expand-xl > .container,
.navbar-expand-xl > .container-fluid { .navbar-expand-xl > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@ -4393,7 +4393,7 @@ input[type="button"].btn-block {
padding-right: 0.5rem; padding-right: 0.5rem;
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.navbar-expand-xl > .container_carousel, .navbar-expand-xl > .container,
.navbar-expand-xl > .container-fluid { .navbar-expand-xl > .container-fluid {
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
@ -4416,7 +4416,7 @@ input[type="button"].btn-block {
justify-content: flex-start; justify-content: flex-start;
} }
.navbar-expand > .container_carousel, .navbar-expand > .container,
.navbar-expand > .container-fluid { .navbar-expand > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@ -4436,7 +4436,7 @@ input[type="button"].btn-block {
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.navbar-expand > .container_carousel, .navbar-expand > .container,
.navbar-expand > .container-fluid { .navbar-expand > .container-fluid {
-ms-flex-wrap: nowrap; -ms-flex-wrap: nowrap;
flex-wrap: nowrap; flex-wrap: nowrap;
@ -10001,7 +10001,7 @@ a.text-dark:hover, a.text-dark:focus {
body { body {
min-width: 992px !important; min-width: 992px !important;
} }
.container_carousel { .container {
min-width: 992px !important; min-width: 992px !important;
} }
.navbar { .navbar {
@ -10035,4 +10035,4 @@ a.text-dark:hover, a.text-dark:focus {
border-color: #dee2e6; border-color: #dee2e6;
} }
} }
/*# sourceMappingURL=bootstrap.css.map */ /*# sourceMappingURL=bootstrap.css.map */

File diff suppressed because one or more lines are too long

View file

@ -9,37 +9,8 @@
Released for free under the Creative Commons Attribution 3.0 license (templated.co/license) 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 */ /* 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 { 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 {
@ -248,7 +219,6 @@
} }
/* Grid */ /* Grid */
.row { .row {
@ -1588,7 +1558,9 @@
width: device-width; width: device-width;
} }
body {
-ms-overflow-style: scrollbar;
}
@media screen and (max-width: 480px) { @media screen and (max-width: 480px) {
@ -1602,7 +1574,16 @@
background: #e4522f; 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 */ /* Type */
@ -2303,7 +2284,7 @@ div.spoiler
display: block; display: block;
float: left; float: left;
margin-right: -2em; margin-right: -2em;
height: 1em; opacity: 0;
width: 1em; width: 1em;
z-index: -1; z-index: -1;
} }
@ -2723,7 +2704,31 @@ div.spoiler
text-align: center; 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 */ /* Tab */
@ -2883,8 +2888,17 @@ div.spoiler
z-index: 99; z-index: 99;
} }
.wrapper header {
margin-bottom: 4em;
}
@media screen and (max-width: 736px) {
.wrapper header {
margin-bottom: 2em;
}
}
.wrapper.style1 { .wrapper.style1 {
background-color: #e39576; background-color: #e39576;
@ -3090,7 +3104,9 @@ div.spoiler
border-top-color: rgba(255, 255, 255, 0.15); border-top-color: rgba(255, 255, 255, 0.15);
} }
.wrapper.style1 header p {
color: #ffffff;
}
.wrapper.style1 table tbody tr { .wrapper.style1 table tbody tr {
border-color: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.15);
@ -3311,7 +3327,9 @@ div.spoiler
border-top-color: rgba(255, 255, 255, 0.15); border-top-color: rgba(255, 255, 255, 0.15);
} }
.wrapper.style2 header p {
color: #9ba2a8;
}
.wrapper.style2 table tbody tr { .wrapper.style2 table tbody tr {
border-color: rgba(255, 255, 255, 0.15); border-color: rgba(255, 255, 255, 0.15);
@ -3445,7 +3463,281 @@ div.spoiler
display: none; 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 */ /* Banner */
@ -3592,9 +3884,6 @@ div.spoiler
/* Main */ /* Main */
/* Footer */ /* Footer */
@ -3661,54 +3950,3 @@ div.spoiler
width: 100%; width: 100%;
padding: 20px; 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;
}

View file

@ -1,9 +1,7 @@
/***** 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-prev { left: -110px; border-bottom: 0; }
.top-content .carousel-control-next { right: -110px; border-bottom: 0; } .top-content .carousel-control-next { right: -110px; border-bottom: 0; }
.top-content .carousel-indicators { bottom: -80px; } .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 li { width: 16px; height: 16px; margin-left: 5px; margin-right: 5px; border-radius: 50%; }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View file

@ -1,278 +0,0 @@
/*
* 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 = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
};
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();
}
};
}));

File diff suppressed because one or more lines are too long

View file

@ -1265,7 +1265,7 @@ if (typeof jQuery === 'undefined') {
title: '', title: '',
delay: 0, delay: 0,
html: false, html: false,
container_carousel: false, container: false,
viewport: { viewport: {
selector: 'body', selector: 'body',
padding: 0 padding: 0
@ -1407,7 +1407,7 @@ if (typeof jQuery === 'undefined') {
.addClass(placement) .addClass(placement)
.data('bs.' + this.type, this) .data('bs.' + this.type, this)
this.options.container_carousel ? $tip.appendTo(this.options.container_carousel) : $tip.insertAfter(this.$element) this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
var pos = this.getPosition() var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth var actualWidth = $tip[0].offsetWidth
@ -1415,13 +1415,13 @@ if (typeof jQuery === 'undefined') {
if (autoPlace) { if (autoPlace) {
var orgPlacement = placement var orgPlacement = placement
var $container_carousel = this.options.container_carousel ? $(this.options.container_carousel) : this.$element.parent() var $container = this.options.container ? $(this.options.container) : this.$element.parent()
var container_carouselDim = this.getPosition($container_carousel) var containerDim = this.getPosition($container)
placement = placement == 'bottom' && pos.bottom + actualHeight > container_carouselDim.bottom ? 'top' : placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
placement == 'top' && pos.top - actualHeight < container_carouselDim.top ? 'bottom' : placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
placement == 'right' && pos.right + actualWidth > container_carouselDim.width ? 'left' : placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
placement == 'left' && pos.left - actualWidth < container_carouselDim.left ? 'right' : placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
placement placement
$tip $tip
@ -2051,11 +2051,11 @@ if (typeof jQuery === 'undefined') {
}) })
} }
Tab.prototype.activate = function (element, container_carousel, callback) { Tab.prototype.activate = function (element, container, callback) {
var $active = container_carousel.find('> .active') var $active = container.find('> .active')
var transition = callback var transition = callback
&& $.support.transition && $.support.transition
&& (($active.length && $active.hasClass('fade')) || !!container_carousel.find('> .fade').length) && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
function next() { function next() {
$active $active

File diff suppressed because one or more lines are too long

View file

@ -2755,7 +2755,7 @@
selector: '(string|boolean)', selector: '(string|boolean)',
placement: '(string|function)', placement: '(string|function)',
offset: '(number|string|function)', offset: '(number|string|function)',
container_carousel: '(string|element|boolean)', container: '(string|element|boolean)',
fallbackPlacement: '(string|array)', fallbackPlacement: '(string|array)',
boundary: '(string|element)', boundary: '(string|element)',
sanitize: 'boolean', sanitize: 'boolean',
@ -2779,7 +2779,7 @@
selector: false, selector: false,
placement: 'top', placement: 'top',
offset: 0, offset: 0,
container_carousel: false, container: false,
fallbackPlacement: 'flip', fallbackPlacement: 'flip',
boundary: 'scrollParent', boundary: 'scrollParent',
sanitize: true, sanitize: true,
@ -2957,12 +2957,12 @@
this.addAttachmentClass(attachment); this.addAttachmentClass(attachment);
var container_carousel = this._getcontainer_carousel(); var container = this._getContainer();
$(tip).data(this.constructor.DATA_KEY, this); $(tip).data(this.constructor.DATA_KEY, this);
if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {
$(tip).appendTo(container_carousel); $(tip).appendTo(container);
} }
$(this.element).trigger(this.constructor.Event.INSERTED); $(this.element).trigger(this.constructor.Event.INSERTED);
@ -3153,16 +3153,16 @@
return offset; return offset;
}; };
_proto._getcontainer_carousel = function _getcontainer_carousel() { _proto._getContainer = function _getContainer() {
if (this.config.container_carousel === false) { if (this.config.container === false) {
return document.body; return document.body;
} }
if (Util.isElement(this.config.container_carousel)) { if (Util.isElement(this.config.container)) {
return $(this.config.container_carousel); return $(this.config.container);
} }
return $(document).find(this.config.container_carousel); return $(document).find(this.config.container);
}; };
_proto._getAttachment = function _getAttachment(placement) { _proto._getAttachment = function _getAttachment(placement) {
@ -4060,10 +4060,10 @@
} // Private } // Private
; ;
_proto._activate = function _activate(element, container_carousel, callback) { _proto._activate = function _activate(element, container, callback) {
var _this2 = this; var _this2 = this;
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 activeElements = container && (container.nodeName === 'UL' || container.nodeName === 'OL') ? $(container).find(Selector$9.ACTIVE_UL) : $(container).children(Selector$9.ACTIVE);
var active = activeElements[0]; var active = activeElements[0];
var isTransitioning = callback && active && $(active).hasClass(ClassName$9.FADE); var isTransitioning = callback && active && $(active).hasClass(ClassName$9.FADE);

File diff suppressed because one or more lines are too long

View file

@ -41,7 +41,18 @@
); );
}); });
// 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() { $('#id_multi_instrumentiste').on('change', function() {
@ -53,8 +64,6 @@
} }
}); });
$('#id_instru').on('change', function() { $('#id_instru').on('change', function() {

View file

@ -1,7 +1,6 @@
{% load static %} {% load static %}
{% load i18n %} {% load i18n %}
{% load changelang %} {% load changelang %}
{% load avatar_tags %}
{% get_current_language as current_language %} {% get_current_language as current_language %}
<!DOCTYPE HTML> <!DOCTYPE HTML>
@ -14,126 +13,56 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>{% block titre %}{% endblock %}</title> <title>{% block titre %}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <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/bootstrap.css' %}">
<link rel="stylesheet" href="{% static 'css/main.css' %}?version=1" /> <link rel="stylesheet" href="{% static 'css/main.css' %}" />
<link rel="stylesheet" href="{% static 'css/add2calendar.css' %}"> {% block extrahead %}{% endblock %}
</head> </head>
<body class="subpage"> <body class="subpage">
<!-- Header --> <!-- 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>
<nav class="navbar navbar-expand-md"> <a href="#menu">Menu</a>
<div class="container-fluid"> </header>
<!-- 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>
<!-- Links --> <!-- Nav -->
<ul class="navbar-nav mr-auto" > <nav id="menu">
<ul class="links">
{% if not user.is_authenticated %} <li><p></p></li>
<li class="nav-item"> <li>{% ifequal current_language "fr" %}
<a class="nav-link" href="{% url 'home' %}"><b>{% trans "Accueil" %}</b></a> <a href="{% changelang "en" %}" >English<span class="image right"><img src="{% static "images/en_flag.jpg" %}"></span></a>
</li> {% else %}
<li class="nav-item"> <a href="{% changelang "fr" %}">Français<span class="image right"><img src="{% static "images/fr_flag.jpg" %}"></span></a>
<a class="nav-link"href="{% url 'calendrier:liste' %}"><b>{% trans "Agenda" %}</b></a> {% endifequal %}</li>
</li> {% if not user.is_authenticated %}
{% else %} <li><a href="{% url 'home' %}">{% trans "Accueil" %}</a></li>
<li class="nav-item"> <li><a href="{% url 'calendrier:liste' %}">{% trans "Agenda" %}</a></li>
<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 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 %}
{% 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 %} {% else %}
<li class="nav-item"><a class="nav-link" href="{% url 'login' %}"><b>{% trans "Se connecter" %}</b></a></li> <li><a href="{% url 'calendrier:home' %}">{% trans "Agenda" %}</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'registration' %}"><b>{% trans "Créer un compte" %}</b></a></li> {% endif %}
<li><a href="{% url 'partitions:liste' %}">{% trans "Répertoire" %}</a></li>
{% endif %} {% if user.is_authenticated %}
<li class="nav-item"> <li><a href="{% url 'trombonoscope:view' %}">{% trans "Trombonoscope" %}</a></li>
{% if current_language == "fr" %} <li><a href="{% url 'pads:list' %}">{% trans "Pads" %}</a></li>
<a class="nav-link" href="{% changelang "en" %}" ><img src="{% static 'images\en_flag.jpg' %}" width="60" height="40" style="vertical-align: middle"></a> {% if user.is_superuser or user.profile.is_chef %}
{% else %} <li><a href="/admin/">{% trans "Administration" %}</a></li>
<a class="nav-link" href="{% changelang "fr" %}" ><img src="{% static 'images\fr_flag.jpg' %}" width="60" height="40" style="vertical-align: middle"></a> {% if user.profile.is_chef %}
<li><a href="{% url 'actu:liste' %}">{% trans "Modifier les actualités" %}</a></li>
{% endif %} {% endif %}
</li> {% endif %}
</ul> <li><a href="{% url 'change_membre' %}">{% trans "Modification du profil" %}</a></li>
<li><a href="{% url 'logout' %}">{% trans "Déconnexion" %}</a></li>
</div> {% else %}
</nav> <li><a href="{% url 'login' %}">{% trans "Se connecter" %}</a></li>
<li><a href="{% url 'registration' %}">{% trans "Créer un compte" %}</a></li>
{% endif %}
</ul>
</nav>
<!-- Main --> <!-- Main -->
@ -145,10 +74,6 @@
<!-- Footer --> <!-- Footer -->
<footer id="footer" style="background-color:rgb(228, 82, 47);"> <footer id="footer" style="background-color:rgb(228, 82, 47);">
<div class="copyright"> <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"> <ul class="icons">
<li><a target="_blank" href="https://www.facebook.com/ernestophone" <li><a target="_blank" href="https://www.facebook.com/ernestophone"
@ -157,58 +82,19 @@
<li><a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ" <li><a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ"
class="icon fa-youtube-play"><span class="label">Youtube</span></a></li> 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> </ul>
</div> </div>
</footer> </footer>
<!-- Scripts --> <!-- Scripts -->
<script src="{% static 'js/jquery.min.js' %}"></script> <script src="{% static 'js/jquery.min.js' %}"></script>
<script src="{% static 'js/jquery.scrolly.min.js' %}"></script> <script src="{% static 'js/jquery.scrolly.min.js' %}"></script>
<script src="{% static 'js/skel.min.js' %}"></script> <script src="{% static 'js/skel.min.js' %}"></script>
<script src="{% static 'js/util.js' %}"></script> <script src="{% static 'js/util.js' %}"></script>
<script src="{% static 'js/main.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"> <script type="text/javascript">
function ouvrirFermerSpoiler(div) function ouvrirFermerSpoiler(div)
{ {
var divContenu = div.getElementsByTagName('div')[1]; var divContenu = div.getElementsByTagName('div')[1];
@ -221,7 +107,5 @@
} }
</script> </script>
{% block script %}
{% endblock %}
</body> </body>
</html> </html>

View file

@ -52,20 +52,9 @@
</div> </div>
<div class ="6u 12u (small)"> <div class ="6u 12u (small)">
<span class="image fit"> <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="" /> <img src="{% static 'images/registration.png' %}" alt="" />
<div style="position:absolute;z-index:1;right:0;bottom:0"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<div href="" class="icon fa-copyright"> lor_tie</div> <a href="" class="icon fa-copyright">lor_tie</a>
{% endif %}
</div> </div>
</span> </span>
</div> </div>

View file

@ -10,16 +10,15 @@
<div class="6u 12u$(small)"> <div class="6u 12u$(small)">
<h2>{% trans "Changement du mot de passe" %} :</h2> <h2>{% trans "Changement du mot de passe" %} :</h2>
{% if error %}
<p>{{ error }}</p>
{% endif %}
{% if success %} {% if success %}
<p>{% trans "Changement enregistré" %} !</p> <p>{% trans "Changement enregistré" %} !</p>
{% endif %} {% endif %}
<form action="{% url 'change_password' %}" method="post"> <form action="{% url 'change_password' %}" method="post">
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<input type="submit" value="{% trans "Valider" %}" /> &nbsp <a href="{% url 'change_membre' %}" class="button alt">{% trans "Retour" %}</a> <input type="submit" value="{% trans "Valider" %}" /> &nbsp; <a href="{% url 'change_membre' %}" class="button alt">{% trans "Retour" %}</a>
</form> </form>
</div></div></div></section></div> </div></div></div></section></div>
{% endblock %} {% endblock %}

View file

@ -1,38 +0,0 @@
{% 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 %}

View file

@ -1,19 +0,0 @@
{% 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 %}

View file

@ -1,19 +0,0 @@
{% 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 %}

View file

@ -1,16 +0,0 @@
{% 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 %}

View file

@ -1,16 +0,0 @@
{% 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 %}

View file

@ -3,7 +3,6 @@
{% load i18n %} {% load i18n %}
{% load halflength %} {% load halflength %}
{% block titre %}{% trans "L'Ernestophone : La fanfare de l'Ecole normale supérieure de Paris" %}{% endblock %} {% 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 %} {% block content %}
<!-- Banner --> <!-- Banner -->
@ -33,12 +32,8 @@
grâce à notre énergie et notre répertoire oscillant entre pop et grâce à notre énergie et notre répertoire oscillant entre pop et
brass band.{% endblocktrans %}</p> brass band.{% endblocktrans %}</p>
</header> </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 --> <!-- Carousel -->
{% if videos %} {% if videos %}
<div id="carousel" class="carousel slide"> <div id="carousel" class="carousel slide">
@ -77,24 +72,17 @@
<span class="sr-only">Next</span> <span class="sr-only">Next</span>
</a> </a>
</div> </div>
</div>
</div>
</div>
</div>
{% endif %} {% endif %}
<!-- End carousel --> <!-- End carousel -->
</div> </div>
</section> </section>
<!-- Two --> <!-- Two -->
<section class="wrapper style2" > <section class="wrapper style2" >
<div class="inner" id="contact"> <div class="inner">
<header> <header>
<h2>{% trans "L'Ernestophone in a nutshell" %}</h2> <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 <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 normale supérieure, (re)créée en septembre 2011, pour le plus
grand bonheur des petits. Et des grands.{% endblocktrans %}</p> grand bonheur des petits. Et des grands.{% endblocktrans %}</p>
@ -167,20 +155,10 @@
{% endfor %} {% endfor %}
<a href="{% url 'partitions:liste' %}" class="button alt fit" >{% trans "Voir le répertoire présent et passé" %}</a> <a href="{% url 'partitions:liste' %}" class="button alt fit" >{% trans "Voir le répertoire présent et passé" %}</a>
<span class="image fit"> <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="" /> <img src="{% static 'images/repertoire.jpg' %}" alt="" />
<div style="position:absolute;z-index:1;right:0;bottom:0"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<div class="icon fa-copyright"> Lucas Gierzack</div> <a href="" class="icon fa-copyright"> Lucas Gierzack</a>
</div> </div>
{% endif %}
</span> </span>
</div> </div>
@ -196,24 +174,12 @@
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 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 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> 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>
<div class="5u 12u$(small)"><div> <div class="5u 12u$(small)"><div>
<span class="image fit"> <span class="image fit"><img src="{% static 'images/join.jpg' %}" alt="" />
{% 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"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a> <a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
</div> </div>
{% endif %}
</span> </span>
</div> </div>
</div> </div>
@ -226,23 +192,12 @@
<div class="tab tab-3 flex flex-3 active"> <div class="tab tab-3 flex flex-3 active">
<div class="box"> <div class="box">
<div><span class="image right"> <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=""/> <img src="{% static 'images/contact.jpg' %}" alt=""/>
<div style="position:absolute;z-index:1;right:0;bottom:0"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a> <a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
</div> </div></span></div><p style="color:white" align="center">{% blocktrans %}Vous préparez un
{% endif %}
</span></div><p style="color:white" align="center">{% blocktrans %}Vous préparez un
évenement et vous recherchez une fanfare dynamique ? N'hésitez évenement et vous recherchez une fanfare dynamique ? N'hésitez
pas à nous envoyer un message par mail ou sur Facebook. Nous serons ravis de venir pas à nous envoyer un message nous serons ravis de venir
fanfaronner pour vous !! Vérifiez notre{% endblocktrans %} <a href="{% url 'calendrier:liste' %}" class="text">{% trans "agenda" %}</a>. <br /> 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" <a target="_blank" href="https://www.facebook.com/ernestophone"
@ -256,12 +211,10 @@
&nbsp; &nbsp;
&nbsp; &nbsp;
&nbsp; &nbsp;
&nbsp;
<a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ" <a target="_blank" href="https://www.youtube.com/channel/UC_RahrdZLoBGpJQHwegV4tQ"
class="icon fa-youtube-play fa-5x"><span class="label">Youtube</span> </a> &nbsp; class="icon fa-youtube-play fa-5x"><span class="label">Youtube</span></a>
&nbsp;
<a target="_blank" href="https://www.instagram.com/ernestophone/" class="icon fa-instagram fa-5x"><span class="label">Instagram</span></a>
</p> </p>
</div> </div>
</div> </div>
@ -270,25 +223,7 @@
</div> </div>
</section> </section>
</div> </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-3.3.1.min.js' %}"></script>
<script src="{% static 'js/jquery-migrate-3.0.0.min.js' %}"></script> <script src="{% static 'js/jquery-migrate-3.0.0.min.js' %}"></script>
<script src="{% static 'js/popper.min.js' %}"></script> <script src="{% static 'js/popper.min.js' %}"></script>

View file

@ -34,22 +34,9 @@
</div> </div>
</div> </div>
<div class="6u 12u$(xsmall)"> <div class="6u 12u$(xsmall)">
<span class="image fit"> <span class="image fit"><img src="{% static 'images/connect.jpg' %}" alt="" /> <div style="position:absolute;z-index:1;right:0;bottom:0">
{% 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> <a href="https://evarin.fr/" target="_blank" class="icon fa-copyright"> Evarin</a>
</div> </div></span>
{% endif %}
</span>
</div> </div>

View file

@ -1,42 +0,0 @@
{% 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 %}
&nbsp <a class="button alt" href="{% url "edit_photo" p.id %}">{% trans "Modifier" %}</a>&nbsp<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 %}

View file

@ -1,23 +0,0 @@
{% 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 %}

View file

@ -12,7 +12,7 @@
<section class="wrapper style1" > <section class="wrapper style1" >
<div class="inner"> <div class="inner">
<h2>{% trans "Créer un compte :" %}</h2> <h2>{% trans "Créer un compte :" %}</h2>
{% if error %} {% if error %}
<p>{{ error }}</p> <p>{{ error }}</p>
{% endif %} {% endif %}
<div class="row uniform"> <div class="row uniform">
@ -48,21 +48,10 @@
</div> </div>
<div class ="6u 12u (small)"> <div class ="6u 12u (small)">
<span class="image fit"> <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="" /> <img src="{% static 'images/registration.png' %}" alt="" />
<div style="position:absolute;z-index:1;right:0;bottom:0"> <div style="position:absolute;z-index:1;right:0;bottom:0">
<div href="" class="icon fa-copyright"> lor_tie</div> <a href="" class="icon fa-copyright">lor_tie</a>
</div> </div>
{%endif%}
</span> </span>
</div> </div>

View file

@ -1,24 +0,0 @@
{% 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 %}

View file

@ -1,15 +0,0 @@
{% 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 %}

View file

@ -1,15 +0,0 @@
{% 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 %}

View file

@ -1,30 +0,0 @@
{% 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> &nbsp<a class="button alt" href="{% url "edit_video" v.id %}">{% trans "Modifier" %}</a>
&nbsp <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 %}

View file

@ -1,15 +0,0 @@
{% 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 %}

View file

@ -3,13 +3,12 @@ from django.utils.safestring import mark_safe
register = template.Library() register = template.Library()
@register.simple_tag @register.simple_tag
def autotranslate(current_language, description, description_en): 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) return mark_safe(description_en)
elif current_language == "fr" and not description: elif(current_language == "fr" and not description):
return mark_safe(description_en) return mark_safe(description_en)
else: else:
return mark_safe(description) return mark_safe(description)

View file

@ -12,7 +12,7 @@ def changelang(context, lang=None, *args, **kwargs):
Usage: {% change_lang 'en' %} Usage: {% change_lang 'en' %}
""" """
path = context["request"].path path = context['request'].path
url_parts = resolve(path) url_parts = resolve(path)
url = path url = path

View file

@ -1,10 +1,8 @@
from django.template import Library
from math import ceil from math import ceil
from django.template import Library
register = Library() register = Library()
@register.filter @register.filter
def half_length(liste): def half_length(liste):
try: try:

View file

@ -1,10 +1,8 @@
from django import template
from datetime import date, timedelta from datetime import date, timedelta
from django import template
register = template.Library() register = template.Library()
@register.filter @register.filter
def modulo(num, val): def modulo(num, val):
return num % val return num % val

View file

@ -0,0 +1,32 @@
from django.contrib.auth import get_user_model
from django.test import Client, TestCase
from django.urls import reverse
User = get_user_model()
class TestPasswordChangeView(TestCase):
def setUp(self):
self.user = User.objects.create_user("alice", password="changeme")
self.url = reverse("change_password")
def test_get(self):
client = Client()
client.force_login(self.user)
resp = client.get(self.url)
self.assertEqual(resp.status_code, 200)
def test_post(self):
client = Client()
client.force_login(self.user)
data = {
"old_password": "changeme",
"new_password1": "s3cr3tp4ss",
"new_password2": "s3cr3tp4ss",
}
resp = client.post(self.url, data)
self.assertEqual(resp.status_code, 200)
client.logout()
self.assertTrue(client.login(username="alice", password="s3cr3tp4ss"))

View file

@ -1,274 +1,113 @@
import os from django.shortcuts import render, redirect
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 from partitions.models import Category
from gestion.forms import ChangeMembreForm, ChangeFormUser,RegistrationFormUser, InscriptionMembreForm
from django.conf import settings
from django.http import HttpResponseRedirect
from gestion.models import ErnestoUser, VideoGallery
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm
from calendrier.forms import ChangeDoodleName
from partitions.decorators import chef_required
from gestion.mixins import ChefRequiredMixin
from django.views.generic import CreateView, DeleteView, ListView, UpdateView
from django.urls import reverse_lazy
from django.shortcuts import render_to_response
import string
import random
def generer(*args): def generer(*args):
caracteres = string.ascii_letters + string.digits caracteres = string.ascii_letters + string.digits
aleatoire = [random.choice(caracteres) for i in range(6)] aleatoire = [random.choice(caracteres) for _ in range(6)]
return "".join(aleatoire) return ''.join(aleatoire)
class Home(TemplateView): def home(request):
template_name = "gestion/index.html" 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):
def dispatch(self, request, *args, **kwargs): return render(request, 'gestion/thanks.html', locals())
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
class MyLoginView(LoginView): @login_required
def changename(request):
template_name = "gestion/login.html" if request.method == 'POST':
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() requbis = request.POST.copy()
form = self.form_class(requbis, instance=request.user) form = ChangeDoodleName(requbis, instance=request.user)
if form.is_valid(): if form.is_valid():
form.save() form.save()
return redirect("change_membre") success = True
return redirect('change_membre')
context = self.get_context_data() else:
context["form"] = form form = ChangeDoodleName(instance=request.user)
return render(request, self.template_name, context) return render(request, 'gestion/changename.html', locals())
class ChangeMembre(LoginRequiredMixin, TemplateView):
comp_form_class = ChangeMembreForm
user_form_class = ChangeFormUser
template_name = "gestion/change.html"
def get_context_data(self, **kwargs): @login_required
context = super().get_context_data(**kwargs) def change_membre(request):
comp_form = self.comp_form_class(instance=self.request.user.profile) if request.method == 'POST':
user_form = self.user_form_class(instance=self.request.user) comp_form = ChangeMembreForm(request.POST, instance=request.user.profile)
context["comp_form"] = comp_form user_form = ChangeFormUser(request.POST, instance=request.user)
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(): if user_form.is_valid() and comp_form.is_valid():
user_form.save() user_form.save()
comp_form.save() comp_form.save()
success = True success = True
return redirect('home')
context = self.get_context_data() else:
context["success"] = success comp_form = ChangeMembreForm(instance=request.user.profile)
context["comp_form"] = comp_form user_form = ChangeFormUser(instance=request.user)
context["user_form"] = user_form return render(request, 'gestion/change.html', locals())
return render(request, self.template_name, context)
class ChangePassword(LoginRequiredMixin, TemplateView): @login_required
form_class = PasswordChangeForm def change_password(request):
template_name = "gestion/changepasswd.html" success = False
if request.method == 'POST':
def get_context_data(self, **kwargs): form = PasswordChangeForm(request.user, data=request.POST)
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()
success = False
form = self.form_class(request.user, data=requbis)
if form.is_valid(): if form.is_valid():
form.save() form.save()
success = True success = True
context = self.get_context_data() else:
context["success"] = success form = PasswordChangeForm(request.user)
context["form"] = form return render(
return render(request, self.template_name, context) request, 'gestion/changepasswd.html', {"form": form, "success": success}
)
class Inscription(TemplateView): def inscription_membre(request):
user_form_class = RegistrationFormUser if request.method == 'POST':
comp_form_class = InscriptionMembreForm
template_name = "gestion/registration.html"
def get_context_data(self, **kwargs): user_form = RegistrationFormUser(request.POST)
context = super().get_context_data(**kwargs) comp_form = InscriptionMembreForm(request.POST)
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
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(): if user_form.is_valid() and comp_form.is_valid():
pseudo = user_form.cleaned_data['username']
if not ( if not (comp_form.cleaned_data['validation']
comp_form.cleaned_data["validation"] == settings.ACCOUNT_CREATION_PASS == settings.ACCOUNT_CREATION_PASS):
): error = "Le champ Validation ne correspond pas à celui attendu"
error = _("Le champ Validation ne correspond pas à celui attendu") return render(request, "gestion/registration.html", locals())
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) member = user_form.save(commit=False)
temp = True temp = True
while temp: while temp:
code = generer() code = generer()
try: try:
ErnestoUser.objects.get(slug=code) ErnestoUser.objects.get(slug=code)
except ErnestoUser.DoesNotExist: except:
temp = False temp = False
member.save() member.save()
(profile, k) = ErnestoUser.objects.get_or_create(user=member, slug=code) (profile, _) = ErnestoUser.objects.get_or_create(user=member,
comp_form = self.comp_form_class(request.POST, instance=profile) slug=code)
comp_form = InscriptionMembreForm(request.POST, instance=profile)
obj = comp_form.save(commit=False) obj = comp_form.save(commit=False)
obj.slug = code obj.slug = code
obj.save() obj.save()
return redirect("thanks") envoi = True
else: return redirect('thanks')
context = self.get_context_data() else:
context["user_form"] = user_form comp_form = InscriptionMembreForm()
context["comp_form"] = comp_form user_form = RegistrationFormUser()
return render(request, self.template_name, context) return render(request, 'gestion/registration.html', locals())
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")

View file

@ -1,6 +0,0 @@
from django.contrib import admin
from .models import Instrument, Reparation
admin.site.register(Instrument)
admin.site.register(Reparation)

View file

@ -1,5 +0,0 @@
from django.apps import AppConfig
class InstrumentsConfig(AppConfig):
name = "instruments"

View file

@ -1,28 +0,0 @@
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",
)

View file

@ -1,174 +0,0 @@
# 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",),
},
),
]

View file

@ -1,22 +0,0 @@
# 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,
),
),
]

View file

@ -1,66 +0,0 @@
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",)

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