first commit

This commit is contained in:
julien 2025-01-14 18:03:28 +01:00
commit eef986d77d
122 changed files with 2464 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.venv/
volumes/

89
README.md Normal file
View File

@ -0,0 +1,89 @@
# taal-academie.arree.bzh
Project structure :
```
.
├── django
│   ├── Dockerfile
│   ├── requirements.txt
│   └── src
│   ├── config
│   ├── development.env
│   ├── home
│   ├── local.env
│   ├── manage.py
│   ├── pages
│   ├── production.env
│   └── workshops
├── compose.dev.yml
├── compose.local.yml
├── compose.prod.yml
├── compose.yml
├── nginx
│   ├── default.conf
│   └── Dockerfile
└── README.md
```
## Deployment with Nerdctl Compose
Can be used as well in Nerdctl root or [rootless](https://docs.docker.com/engine/security/rootless/) mode.
There are three profiles :
* Development : with only the database
* Local : for local testing of the production stack
* Production : Final deployment on the server
### Development
To run the development profile from the project `django/src` directory :
```
$ ( cd ../.. && nerdctl compose -f compose.yml -f compose.dev.yml up -d postgres )
```
Then when calling the `manage.py` script we need to pass `DJANGO_ENV` to load `src/dev.env`, like in the
following example to start the Django development server :
```
$ DJANGO_ENV=dev python manage.py runserver
```
To not have to pass this for each `manage.py` execution you may export `DJANGO_ENV` from your `.bashrc` :
```
$ echo -e "\n# Django development\nexport DJANGO_ENV=dev" >> ~/.bashrc
```
> Need to restart the session !
### Local
To run the local profile from the project `django/src` directory :
```
$ ( cd ../.. && nerdctl compose -f compose.yml -f compose.local.yml up -d )
```
### Production
To run the production profile from the directory where the `compose.yml` file lives :
```
$ nerdctl compose -f compose.yml -f compose.prod.yml up -d
```
At the first launch, it is advised to run the Deployment checklist from `manage.py` to check if there are some security
improvements :
```
$ nerdctl exec -it django_taal-academiearreebzh python /django/manage.py check --deploy
```
Then create an admin user for the Django admin panel :
```
$ nerdctl exec -it django_taal-academiearreebzh python /django/manage.py createsuperuser
```

7
compose.dev.yml Normal file
View File

@ -0,0 +1,7 @@
services:
postgres:
env_file:
- django/src/dev.env
- /srv/dwalin/passwords/taal-academiearreebzh.pass
ports:
- "127.0.0.1:5432:5432"

13
compose.local.yml Normal file
View File

@ -0,0 +1,13 @@
services:
postgres:
env_file:
- django/src/local.env
- /srv/dwalin/passwords/taal-academiearreebzh.pass
django:
env_file:
- django/src/local.env
- /srv/dwalin/passwords/taal-academiearreebzh.pass
nginx:
ports:
- "127.0.0.1:8001:8001"
restart: unless-stopped

12
compose.prod.yml Normal file
View File

@ -0,0 +1,12 @@
services:
postgres:
env_file:
- django/src/prod.env
- /srv/dwalin/passwords/taal-academiearreebzh.pass
django:
env_file:
- django/src/prod.env
- /srv/dwalin/passwords/taal-academiearreebzh.pass
nginx:
ports:
- "127.0.0.1:8001:8001"

33
compose.yml Normal file
View File

@ -0,0 +1,33 @@
services:
postgres:
image: postgres:15-alpine
container_name: taal-academiearreebzh_postgres
volumes:
- ./volumes/postgres:/var/lib/postgresql/data:z
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
django:
build: ./django
container_name: taal-academiearreebzh_django
depends_on:
postgres:
condition: service_healthy
command: sh -c "python manage.py makemigrations &&
python manage.py migrate &&
python manage.py collectstatic --clear --noinput &&
gunicorn config.wsgi --bind 0.0.0.0:8001"
volumes:
- ./volumes/static:/django/static:z
restart: unless-stopped
nginx:
build: ./nginx
container_name: taal-academiearreebzh_nginx
depends_on:
- django
volumes:
- ./volumes/static:/django/static:z
restart: unless-stopped

32
django/Dockerfile Normal file
View File

@ -0,0 +1,32 @@
# Fetching the base image
FROM python:3.12-alpine
# Setting up the work directory
WORKDIR /django
# Preventing python from writing pyc to docker container
ENV PYTHONDONTWRITEBYTECODE 1
# Flushing out python buffer
ENV PYTHONUNBUFFERED 1
# Updating the os
RUN apk update
# Installing python3
RUN apk add python3-dev
# Copying requirement file
COPY ./requirements.txt ./
# Upgrading pip version
RUN pip install --upgrade pip
# Installing Gunicorn
RUN pip install gunicorn
# Installing dependencies
RUN pip install --no-cache-dir -r ./requirements.txt
# Copying all the files in our project
COPY ./src .

10
django/requirements.txt Normal file
View File

@ -0,0 +1,10 @@
asgiref==3.7.2
Django==4.2
django-environ==0.11.2
django-tinymce==3.6.1
django-widget-tweaks==1.5.0
psycopg==3.1.16
psycopg-binary==3.1.16
setuptools==69.0.3
sqlparse==0.4.4
typing_extensions==4.9.0

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

16
django/src/config/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for config project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_asgi_application()

View File

@ -0,0 +1,164 @@
import os
from pathlib import Path
import environ
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env(
# Security
DEBUG=bool,
SECRET_KEY=str,
ALLOWED_HOSTS=list,
CSRF_TRUSTED_ORIGINS=list,
# Database
DATABASE_NAME=str,
DATABASE_USER=str,
DATABASE_PASS=str,
DATABASE_HOST=str,
DATABASE_PORT=int,
# SMTP server
EMAIL_HOST=str,
EMAIL_HOST_USER=str,
EMAIL_HOST_PASSWORD=str,
EMAIL_PORT=int,
EMAIL_USE_SSL=bool,
EMAIL_USE_TLS=bool,
)
# Load environment variables according the DJANGO_ENV value
if os.environ.get('DJANGO_ENV') == 'dev':
environ.Env.read_env(os.path.join(BASE_DIR, 'dev.env'))
elif os.environ.get('DJANGO_ENV') == 'local':
environ.Env.read_env(os.path.join(BASE_DIR, 'local.env'))
else:
environ.Env.read_env(os.path.join(BASE_DIR, 'prod.env'))
# Security
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS')
CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'widget_tweaks',
'home',
'tinymce',
'pages',
'workshops',
]
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',
]
ROOT_URLCONF = 'config.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',
'home.context_processors.current_year',
'home.context_processors.contact',
],
},
},
]
WSGI_APPLICATION = 'config.wsgi.application'
# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': env('DATABASE_NAME'),
'USER': env('DATABASE_USER'),
'PASSWORD': env('DATABASE_PASS'),
'HOST': env('DATABASE_HOST'),
'PORT': env('DATABASE_PORT'),
}
}
# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
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',
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/
LANGUAGE_CODE = 'fr-FR'
TIME_ZONE = 'Europe/Paris'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# SMTP server
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = env('EMAIL_HOST')
EMAIL_HOST_USER = env('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD')
EMAIL_PORT = env('EMAIL_PORT')
EMAIL_USE_SSL = env('EMAIL_USE_SSL')
EMAIL_USE_TLS = env('EMAIL_USE_TLS')

28
django/src/config/urls.py Normal file
View File

@ -0,0 +1,28 @@
"""
URL configuration for config project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home.urls')),
path('pages/', include('pages.urls')),
path('tinymce/', include('tinymce.urls')),
path('workshops/', include('workshops.urls')),
]
admin.site.site_header = 'Administration : taal-academie.arree.bzh'

16
django/src/config/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for config project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_wsgi_application()

30
django/src/dev.env Normal file
View File

@ -0,0 +1,30 @@
#######################################
### Docker
POSTGRES_USER=postgres
POSTGRES_DB=postgres
#POSTGRES_PASSWORD=
#######################################
### Django
# Security
DEBUG=True
#SECRET_KEY=
ALLOWED_HOSTS=127.0.0.1,localhost
CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8001,http://localhost:8001
# Database
DATABASE_NAME=postgres
DATABASE_USER=postgres
#DATABASE_PASS=
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
# SMTP server
EMAIL_HOST=mail.netig.net
EMAIL_HOST_USER=test@netig.net
#EMAIL_HOST_PASSWORD=
EMAIL_PORT=465
EMAIL_USE_SSL=True
EMAIL_USE_TLS=False

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
django/src/home/admin.py Normal file
View File

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

6
django/src/home/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class HomeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'home'

View File

@ -0,0 +1,39 @@
from .forms import ContactForm
from django.contrib import messages
from django.core.mail import send_mail
import datetime
from django.conf import settings
# Create your views here.
def current_year(request):
current_datetime = datetime.datetime.now()
return {
'current_year': current_datetime.year
}
def contact(request):
# if this is a POST request we need to process the form data
if request.method == "POST":
# create a form instance and populate it with data from the request:
form = ContactForm(request.POST)
# check whether it's valid:
if form.is_valid():
name = form.cleaned_data["name"]
mail = form.cleaned_data["mail"]
subject = form.cleaned_data["subject"]
body = form.cleaned_data["body"]
recipients = [settings.EMAIL_HOST_USER]
body = ('Nom de l\'expéditeur :' + '\n' + name + '\n\n' + 'Objet :' + '\n' + subject + '\n\n' + 'Message :'
+ '\n' + body)
send_mail(subject, body, mail, recipients)
messages.success(request, 'Votre message a bien été envoyé !')
form = ContactForm()
return {"form": form}
# if a GET (or any other method) we'll create a blank form
else:
form = ContactForm()
return {"form": form}

8
django/src/home/forms.py Normal file
View File

@ -0,0 +1,8 @@
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=128, label='Votre nom')
mail = forms.EmailField(label='Votre email')
subject = forms.CharField(max_length=256, label='Objet')
body = forms.CharField(widget=forms.Textarea, label='Votre message')

View File

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,892 @@
/* Fonts
------------------------------------------------------------------------ */
@font-face {
font-family: 'Lato';
src: url('/static/home/font/Lato-Regular.woff2') format('woff2'),
url('/static/home/font/Lato-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Lato';
src: url('/static/home/font/Lato-Bold.woff2') format('woff2'),
url('/static/home/font/Lato-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'TeXGyreTermes';
src: url('/static/home/font/TeXGyreTermes-Bold.woff2') format('woff2'),
url('/static/home/font/TeXGyreTermes-Bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'TeXGyreTermes';
src: url('/static/home/font/TeXGyreTermes-Regular.woff2') format('woff2'),
url('/static/home/font/TeXGyreTermes-Regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
/* Reset
------------------------------------------------------------------------ */
body,
html {
margin: 0;
}
p {
margin-top: 0;
}
ul {
margin-top: 0;
}
/* Variables
------------------------------------------------------------------------ */
:root {
--cover__home: url(/static/home/media/taal.webp);
--cover__about: url(/static/home/media/about.webp);
--cover__cooking: url(/static/home/media/buffet.webp);
--cover__drums: url(/static/home/media/drums.webp);
--cover__visual: url(/static/home/media/visual.webp);
--cover__gatka: url(/static/home/media/gatka.webp);
--color__primary: #FC970B;
--color__secondary: #641a40;
--color__ternary: #185833;
--color__neutral: #111;
}
/* Layout
------------------------------------------------------------------------ */
body,
html {
font-family: Lato, sans-serif;
font-size: 20px;
line-height: 1.8rem;
scroll-behavior: smooth;
}
article:first-child {
padding-top: 100px;
}
article {
padding: 40px 0;
}
article:last-child {
margin-bottom: 40px;
}
.content--s,
.content,
.content--l {
padding: 0 40px;
}
.flex--zz > div {
margin-bottom: 60px;
}
.col2 > div,
.col3 > div {
margin-bottom: 60px;
}
/* Cards
------------------------------------------------------------------------ */
.card {
border-radius: 20px;
box-shadow: 0 0 20px var(--color__neutral);
padding: 20px;
display: block;
min-width: 40px;
margin-bottom: 40px;
}
/* Banners
------------------------------------------------------------------------ */
.banner {
background: #641a40;
color: #ffffff;
padding: 40px;
margin-bottom: 60px;
text-align: center;
}
/* Messages
------------------------------------------------------------------------ */
.success {
border-radius: 5px;
padding: 15px 20px;
background: #cccccc;
text-align: center;
}
.warning {
color: #e74c3c;
text-align: center;
}
.error {
border-radius: 5px;
padding: 15px 10px;
background: #e74c3c;
text-align: center;
}
/* Buttons
------------------------------------------------------------------------ */
.button {
background: var(--color__primary);
color: #FFF;
font-size: .8rem;
border: 0;
border-radius: 5px;
padding: 15px 20px;
margin: 20px 0;
}
.button--rev {
background: #fff;
color: var(--color__primary);
}
.button:hover {
text-decoration: none;
color: #FFF;
cursor: pointer;
}
.button--rev:hover {
text-decoration: none;
color: var(--color__primary);
cursor: pointer;
}
/* Titles
------------------------------------------------------------------------ */
h2 {
font-family: 'TeXGyreTermes', serif;
font-size: 2rem;
line-height: 2rem;
font-weight: bold;
text-align: center;
margin-top: 0;
margin-bottom: 100px;
}
h3 {
font-family: 'TeXGyreTermes', serif;
font-size: 1.6rem;
line-height: 1.6rem;
font-weight: bold;
text-align: center;
margin-top: 0;
margin-bottom: 60px;
}
h4 {
font-family: 'TeXGyreTermes', serif;
font-size: 1.4rem;
line-height: 1.2rem;
font-weight: bold;
text-align: center;
margin-top: 0;
margin-bottom: 40px;
}
/* Links
------------------------------------------------------------------------ */
a {
color: var(--color__primary);
font-weight: bold;
text-decoration: none;
}
a:hover {
color: inherit;
text-decoration: underline;
}
.icon img {
opacity: 0.6;
width: 46px;
height: 46px;
transition: opacity 0.3s;
}
.icon:hover img {
opacity: 1;
}
/* Header
------------------------------------------------------------------------ */
header {
position: relative;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}
header::before {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: no-repeat center center / cover fixed var(--cover__home);
filter: brightness(20%);
z-index: -1;
}
header a:hover {
text-decoration: none;
}
header h1 {
font-family: 'TeXGyreTermes', serif;
display: block;
font-size: 4rem;
font-weight: bold;
text-align: center;
color: var(--color__primary);
margin: 0;
}
header h2 {
font-family: 'TeXGyreTermes', serif;
display: block;
font-size: 2rem;
font-weight: normal;
text-align: center;
color: var(--color__primary);
margin: 0;
}
/* Topnav
------------------------------------------------------------------------ */
.topnav {
background: var(--color__primary);
text-align: center;
box-shadow: 0 0 10px #222;
position: sticky;
display: none;
top: 0px;
z-index: 3;
width: 100%;
}
.topnav a {
display: inline-block;
font-size: 1.2rem;
font-weight: bold;
color: #FFF;
opacity: .75;
padding: 10px 10px;
transition: opacity 0.3s;
}
.topnav a:hover {
text-decoration: none;
opacity: 1;
}
/* Sidenav
------------------------------------------------------------------------ */
.menu_icon_sidenav {
z-index: 2;
width: fit-content;
height: auto;
background-color: var(--color__primary);
padding: 10px;
margin: 10px;
cursor: pointer;
position: fixed;
top: 0;
box-shadow: 0 0 10px #222;
border-radius: 100%;
}
.line1,
.line2,
.line3 {
width: 40px;
height: 4px;
margin: 10px 8px;
background-color: #fff;
border-radius: 50px;
transition: 0.2s;
}
.active .line1 {
transform: translate(0px, 15px) rotate(45deg);
}
.active .line2 {
opacity: 0;
}
.active .line3 {
transform: translate(0px, -15px) rotate(-45deg);
}
.sidenav {
width: fit-content;
background-color: #fff;
position: fixed;
text-align: left;
z-index: 1;
opacity: 0;
left: -500px;
pointer-events: none;
transition: 0.3s;
top: 0;
box-shadow: 0 0 10px #222;
overflow: scroll;
}
.active_sidenav {
opacity: .8;
left: 0px;
pointer-events: fill;
position: fixed;
top: 0;
height: 100vh;
}
.sidenav nav {
padding-top: 80px;
margin-right: 40px;
}
.sidenav nav ul li {
list-style: none;
margin-bottom: 20px;
transition: 0.2s;
}
.sidenav nav ul li:hover {
background-color: #c6c6c66f;
border-radius: 8px;
}
.sidenav nav ul li a {
color: #000;
font-size: 1.2rem;
padding: 10px 30px;
display: block;
text-decoration: none;
}
.sidenav nav ul li a:hover {
text-decoration: none;
}
/* Cover
------------------------------------------------------------------------ */
.cover__home {
height: 400px;
background: no-repeat top center / cover var(--cover__home);
}
.cover__about {
height: 400px;
background: no-repeat top center / cover var(--cover__about);
background-attachment: fixed;
}
.cover__cooking {
height: 400px;
background: no-repeat top center / cover var(--cover__cooking);
background-attachment: fixed;
}
.cover__drums {
height: 400px;
background: no-repeat center center / cover var(--cover__drums);
background-attachment: fixed;
}
.cover__visual {
height: 400px;
background: no-repeat top center / cover var(--cover__visual);
background-attachment: fixed;
}
.cover__gatka {
height: 400px;
background: no-repeat top center / cover var(--cover__gatka);
background-attachment: fixed;
}
/* Media
------------------------------------------------------------------------ */
.media {
margin: 20px auto;
border-radius: 10px;
width: 100%;
}
.flex--zz .media {
width: 100%;
}
/* youtube-video-container
------------------------------------------------------------------------ */
.youtube-video-container {
position: relative;
overflow: hidden;
width: 100%;
}
.youtube-video-container::after {
display: block;
content: "";
padding-top: 56.25%;
}
.youtube-video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* About article
------------------------------------------------------------------------ */
.about {
text-align: center;
}
.slogan {
margin: 40px 0 80px 0;
}
.slogan::before,
.slogan::after {
text-align: center;
display: inline-block;
padding: 10px;
position: relative;
top: -10px;
}
.slogan::before {
content: url(/static/home/media/quotes-left.svg);
}
.slogan::after {
content: url(/static/home/media/quotes-right.svg);
}
/* Cooking article
------------------------------------------------------------------------ */
.cooking {
position: relative;
color: #FFF;
text-align: center;
}
.cooking::before {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: no-repeat center center / cover fixed var(--cover__cooking);
filter: brightness(30%);
z-index: -1;
}
/* Drums article
------------------------------------------------------------------------ */
.drums {
text-align: center;
}
/* Gatka article
------------------------------------------------------------------------ */
.gatka {
position: relative;
text-align: center;
}
.gatka p {
text-align: center;
}
.gatka::before {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: no-repeat center center / cover fixed var(--cover__gatka);
filter: brightness(30%);
z-index: -1;
}
.gatka h2,
.gatka .content--s {
position: relative;
color: #FFF;
}
/* Visual article
------------------------------------------------------------------------ */
.visual {
text-align: center;
}
/* workshops article
------------------------------------------------------------------------ */
.workshops {
position: relative;
color: #FFF;
}
.workshops p {
text-align: center;
}
.workshops::before {
content: "";
position: absolute;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
background: var(--color__secondary);
z-index: -1;
}
.workshops h2,
.workshops .content--l {
position: relative;
}
.workshops ul {
margin-bottom: 80px;
}
.workshops .card {
background: #fff;
color: #222;
}
/* Events article
------------------------------------------------------------------------ */
.events p {
text-align: center;
}
.events h4 {
text-decoration: none;
font-weight: bold;
}
/* Contact
------------------------------------------------------------------------ */
.contact p {
font-size: 1.2rem;
}
.contact h2,
.contact .content {
position: relative;
color: var(--color__neutral);
}
.contact-form {
position: relative;
top: -200px;
margin-right: auto;
min-width: 50%;
font-size: 0.8rem;
font-weight: bold;
}
.contact-form input,
select,
textarea {
font-size: 1rem;
padding: 10px;
border-radius: 5px;
border: 1px solid #fff;
flex: 1 1 auto;
margin: 10px 0;
}
input:focus,
textarea:focus {
outline: none;
}
.contact .button {
color: #fff;
}
.contact .button:hover {
color: #fff;
}
.contact-form > * {
display: flex;
}
.contact-form textarea {
min-height: 150px;
max-width: 100%;
box-shadow: 0 0 10px #222;
}
.map {
margin-bottom: 80px;
}
.map iframe {
display: block;
border: 0px;
width: 100%;
height: 400px;
}
.contact .card {
position: relative;
top: -200px;
background: var(--color__ternary);
}
.contact .card h2,
.contact .card h3,
.contact .card p {
color: #fff;
}
.contact .card h3,
.contact .card p {
text-align: left;
}
.contact .card h3 {
font-size: 1.2rem;
line-height: normal;
margin: 0;
}
.contact .card p {
font-size: 0.8rem;
line-height: normal;
}
svg {
display: flex;
align-items: center;
justify-content: left;
height: 64px;
width: auto;
}
.contact-info > div {
display: flex;
gap: 40px;
margin: 60px 0;
align-items: flex-start;
}
/* Press
------------------------------------------------------------------------ */
.press iframe {
width: 100%;
height: 50vw;
}
/* Bottom Bar
------------------------------------------------------------------------ */
.botbar {
display: flex;
background: #000;
color: var(--color__primary);
font-size: 1rem;
justify-content: space-between;
flex-wrap: wrap;
text-align: center;
}
.botbar p {
padding: 10px 20px;
margin-left: auto;
margin-right: auto;
}
/* For more than 680px screens and normal DPI
------------------------------------------------------------------------ */
@media screen and (min-width: 680px) and (max-resolution: 1x) {
h2 {
font-size: 3.2rem;
line-height: 3.2rem;
}
h3 {
font-size: 2rem;
line-height: 2rem;
}
h4 {
font-size: 1.2rem;
line-height: 1.2rem;
}
}
/* For highter resolution screens and normal DPI
------------------------------------------------------------------------ */
@media screen and (min-width: 950px) and (max-resolution: 1x) {
.col2 {
display: grid;
grid-column-gap: 80px;
grid-template-columns: repeat(2, 1fr);
}
.col3 {
display: grid;
grid-column-gap: 80px;
grid-template-columns: repeat(3, 1fr);
}
.col2--1-3 {
display: grid;
grid-column-gap: 80px;
grid-template-columns: 1fr 2fr;
}
header h1 {
font-size: 5rem;
}
header h2 {
font-size: 3rem;
}
.content--s {
max-width: 750px;
margin-left: auto;
margin-right: auto;
}
.cover__home {
height: 689px;
}
.flex--zz {
display: flex;
gap: 40px;
align-items: center;
justify-content: center;
text-align: left;
}
.flex--zz > * {
flex: 1;
}
.flex--zz h3,
.flex--zz h4,
.flex--zz p {
text-align: left;
}
.flex--zz:nth-child(odd) {
flex-direction: row-reverse;
text-align: right;
}
.flex--zz:nth-child(odd) h3,
.flex--zz:nth-child(odd) h4,
.flex--zz:nth-child(odd) p {
text-align: right;
}
.contact-form {
position: relative;
top: -60px;
margin-top: 0;
}
.map iframe {
min-width: 400px;
}
}
@media screen and (min-width: 1250px) and (max-resolution: 1x) {
header h1 {
font-size: 6rem;
}
header h2 {
font-size: 4rem;
}
.menu_icon_sidenav {
display: none;
}
.topnav {
display: block;
}
article {
padding: 60px 0;
}
footer article {
padding: 50px 0;
}
.content {
max-width: 1050px;
margin-left: auto;
margin-right: auto;
}
.col--zz {
gap: 80px;
}
}
@media screen and (min-width: 1600px) and (max-resolution: 1x) {
.content--l {
max-width: 1400px;
margin-left: auto;
margin-right: auto;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,14 @@
let menu_icon_sidenav = document.querySelector(".menu_icon_sidenav");
let sidenav = document.querySelector(".sidenav");
menu_icon_sidenav.onclick = function () {
menu_icon_sidenav.classList.toggle("active");
sidenav.classList.toggle("active_sidenav");
}
document.onclick = function (e) {
if (!menu_icon_sidenav.contains(e.target) && !sidenav.contains(e.target)) {
menu_icon_sidenav.classList.remove("active");
sidenav.classList.remove("active_sidenav");
}
}

View File

@ -0,0 +1,16 @@
// From https://www.w3schools.com/w3css/w3css_slideshow.asp
var slideIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("slider");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
slideIndex++;
if (slideIndex > x.length) {slideIndex = 1}
x[slideIndex-1].style.display = "block";
setTimeout(carousel, 5000); // Change image every 2 seconds
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.001 2.002c-5.522 0-9.999 4.477-9.999 9.999 0 4.99 3.656 9.126 8.437 9.879v-6.988h-2.54v-2.891h2.54V9.798c0-2.508 1.493-3.891 3.776-3.891 1.094 0 2.24.195 2.24.195v2.459h-1.264c-1.24 0-1.628.772-1.628 1.563v1.875h2.771l-.443 2.891h-2.328v6.988C18.344 21.129 22 16.992 22 12.001c0-5.522-4.477-9.999-9.999-9.999z"/></svg>

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>quotes-left</title>
<path d="M7.031 14c3.866 0 7 3.134 7 7s-3.134 7-7 7-7-3.134-7-7l-0.031-1c0-7.732 6.268-14 14-14v4c-2.671 0-5.182 1.040-7.071 2.929-0.364 0.364-0.695 0.751-0.995 1.157 0.357-0.056 0.724-0.086 1.097-0.086zM25.031 14c3.866 0 7 3.134 7 7s-3.134 7-7 7-7-3.134-7-7l-0.031-1c0-7.732 6.268-14 14-14v4c-2.671 0-5.182 1.040-7.071 2.929-0.364 0.364-0.695 0.751-0.995 1.157 0.358-0.056 0.724-0.086 1.097-0.086z"></path>
</svg>

After

Width:  |  Height:  |  Size: 573 B

View File

@ -0,0 +1,5 @@
<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>quotes-right</title>
<path d="M25 20c-3.866 0-7-3.134-7-7s3.134-7 7-7 7 3.134 7 7l0.031 1c0 7.732-6.268 14-14 14v-4c2.671 0 5.182-1.040 7.071-2.929 0.364-0.364 0.695-0.75 0.995-1.157-0.357 0.056-0.724 0.086-1.097 0.086zM7 20c-3.866 0-7-3.134-7-7s3.134-7 7-7 7 3.134 7 7l0.031 1c0 7.732-6.268 14-14 14v-4c2.671 0 5.182-1.040 7.071-2.929 0.364-0.364 0.695-0.75 0.995-1.157-0.357 0.056-0.724 0.086-1.097 0.086z"></path>
</svg>

After

Width:  |  Height:  |  Size: 562 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

View File

@ -0,0 +1,199 @@
<!DOCTYPE html>
{% load static %}
{% load widget_tweaks %}
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}</title>
<meta name="description"
content="TAAL Académie est engagée depuis 2013 dans la promotion des Art Traditionnels de l'Inde et du Pakistan, à travers l'enseignement de l'Art Musical, l'Art Mart...">
<link rel="canonical" href="https://taal-academie.arree.bzh/">
<link rel="icon" type="image/x-icon" href="{% static 'home/media/favicon.png' %}">
<link rel="stylesheet" href="{% static 'home/css/base.css' %}">
</head>
<body>
{% if request.path == '/' %}
<header class="header">
<a class="site-title" href="https://taal-academie.arree.bzh">
<h1>TAAL</h1>
</a>
<a class="site-subtitle" href="https://taal-academie.arree.bzh">
<h2>Académie des Arts Traditionnels de l'Inde</h2>
</a>
<a href="#top">
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" stroke="#FC970B"
style="--darkreader-inline-stroke: #fca122;" data-darkreader-inline-stroke="">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path
d="M5.70711 9.71069C5.31658 10.1012 5.31658 10.7344 5.70711 11.1249L10.5993 16.0123C11.3805 16.7927 12.6463 16.7924 13.4271 16.0117L18.3174 11.1213C18.708 10.7308 18.708 10.0976 18.3174 9.70708C17.9269 9.31655 17.2937 9.31655 16.9032 9.70708L12.7176 13.8927C12.3271 14.2833 11.6939 14.2832 11.3034 13.8927L7.12132 9.71069C6.7308 9.32016 6.09763 9.32016 5.70711 9.71069Z"
fill="#FC970B" style="--darkreader-inline-fill: #c57302;" data-darkreader-inline-fill="">
</path>
</g>
</svg>
</a>
</header>
{% endif %}
<div class="menu_icon_sidenav">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
<div class="topnav">
<nav>
<a href="/#">Accueil</a>
<a href="/#about">Présentation</a>
<a href="/#cooking">Cuisines</a>
<a href="/#drums">Percussions</a>
<a href="/#gatka">Gatka</a>
<a href="/#visual">Arts Visuels</a>
<a href="/#workshops">Cours & Stages</a>
<a href="/#events">Evènements</a>
<a href="#contact">Contact</a>
</nav>
</div>
<div class="sidenav">
<nav>
<ul>
<li><a href="/#">Accueil</a></li>
<li><a href="/#about">Présentation</a></li>
<li><a href="/#cooking">Cuisines</a></li>
<li><a href="/#drums">Percussions</a></li>
<li><a href="/#gatka">Gatka</a></li>
<li><a href="/#visual">Arts Visuels</a></li>
<li><a href="/#workshops">Cours & Stages</a></li>
<li><a href="/#events">Evènements</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
<main class="main" id="top">
{% block content %}{% endblock %}
</main>
<footer>
<div class="contact" id="contact">
<div class="map">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d42450.95469143548!2d-3.9939939182617525!3d48.31853054338251!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x481138baf8c5cf43%3A0x40ca5cd36e56fe0!2s29190%20Brasparts!5e0!3m2!1sfr!2sfr!4v1694695541898!5m2!1sfr!2sfr"
width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>
</div>
<div class="content col2">
<div class="card contact-info">
<h2>Contact</h2>
<div class="contact-address">
<svg width="64px" height="64px" viewBox="0 0 8.4666669 8.4666669" id="svg8" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg" fill="fffff" stroke="fffff">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<defs id="defs2"></defs>
<g id="layer1" transform="translate(0,-288.53332)">
<path
d="m 15.996094,0.99609375 c -6.0632836,0 -10.9980445,4.93673065 -10.9980471,11.00000025 -3.8e-6,10.668737 10.3789061,18.779297 10.3789061,18.779297 0.364612,0.290384 0.881482,0.290384 1.246094,0 0,0 10.380882,-8.11056 10.380859,-18.779297 C 27.003893,5.9328244 22.059377,0.99609375 15.996094,0.99609375 Z m 0,6.00195315 c 2.749573,0 5.00585,2.2484784 5.005859,4.9980471 C 21.001971,14.7457 18.745685,17 15.996094,17 c -2.749591,0 -4.998064,-2.2543 -4.998047,-5.003906 9e-6,-2.7495687 2.248474,-4.9980471 4.998047,-4.9980471 z"
id="path929"
style="color:#ffffff;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#ffffff;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#ffffff;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
transform="matrix(0.26458333,0,0,0.26458333,0,288.53332)"></path>
</g>
</g>
</svg>
<div>
<h3>Adresse</h3>
<p>
24, Prat ar Veguerez<br>
Route de Lannedern<br>
29190 BRASPARTS
</p>
</div>
</div>
<div class="contact-phone">
<svg width="64px" height="64px" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg" stroke="#ffffff">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path
d="M16.5562 12.9062L16.1007 13.359C16.1007 13.359 15.0181 14.4355 12.0631 11.4972C9.10812 8.55901 10.1907 7.48257 10.1907 7.48257L10.4775 7.19738C11.1841 6.49484 11.2507 5.36691 10.6342 4.54348L9.37326 2.85908C8.61028 1.83992 7.13596 1.70529 6.26145 2.57483L4.69185 4.13552C4.25823 4.56668 3.96765 5.12559 4.00289 5.74561C4.09304 7.33182 4.81071 10.7447 8.81536 14.7266C13.0621 18.9492 17.0468 19.117 18.6763 18.9651C19.1917 18.9171 19.6399 18.6546 20.0011 18.2954L21.4217 16.883C22.3806 15.9295 22.1102 14.2949 20.8833 13.628L18.9728 12.5894C18.1672 12.1515 17.1858 12.2801 16.5562 12.9062Z"
fill="#ffffff"></path>
</g>
</svg>
<div>
<h3>Téléphone</h3>
<p>06 24 20 76 09</p>
</div>
</div>
<div class="contact-mail">
<svg width="64px" height="64px" viewBox="0 -3.5 32 32" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" fill="#ffffff" stroke="#ffffff">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<title>mail</title>
<desc>Created with Sketch Beta.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"
sketch:type="MSPage">
<g id="Icon-Set-Filled" sketch:type="MSLayerGroup"
transform="translate(-414.000000, -261.000000)" fill="#ffffff">
<path
d="M430,275.916 L426.684,273.167 L415.115,285.01 L444.591,285.01 L433.235,273.147 L430,275.916 L430,275.916 Z M434.89,271.89 L445.892,283.329 C445.955,283.107 446,282.877 446,282.634 L446,262.862 L434.89,271.89 L434.89,271.89 Z M414,262.816 L414,282.634 C414,282.877 414.045,283.107 414.108,283.329 L425.147,271.927 L414,262.816 L414,262.816 Z M445,261 L415,261 L430,273.019 L445,261 L445,261 Z"
id="mail" sketch:type="MSShapeGroup"></path>
</g>
</g>
</g>
</svg>
<div>
<h3>Email</h3>
<a href="mailto:taal-academie@arree.bzh">taal-academie@arree.bzh</a>
</div>
</div>
</div>
<div class="content">
<form action="#contact" method="post" class="contact-form">
{% csrf_token %}
{% render_field form.name class="contact-form-input" placeholder=form.name.label type="text" %}
{% render_field form.mail class="contact-form-input" placeholder=form.mail.label type="email" %}
{% render_field form.subject class="contact-form-input" placeholder=form.subject.label type="text" %}
{% render_field form.body class="contact-form-input" placeholder=form.body.label type="text" %}
<input type="submit" value="Envoyer" class="button">
{% if messages %}
{% for message in messages %}
<div class="success">
{{ message }}
</div>
{% endfor %}
{% endif %}
</form>
</div>
</div>
</div>
<div class="botbar">
<p>
© {{ current_year }} <a href="https://taal-academie.arree.bzh/#">Académie
des Arts Traditionnels de lInde</a>
</p>
<p>
<a href="/pages/legal#top">Mentions Légales</a>
</p>
<p>
Créé et hébergé par <a href="https://netig.net" target="_blank">NETig</a> !
</p>
</div>
<script src="{% static 'home/js/jquery-3.7.0.min.js' %}"></script>
<script src="{% static 'home/js/slider.js' %}"></script>
<script src="{% static 'home/js/sidenav.js' %}"></script>
</footer>
</body>
</html>

View File

@ -0,0 +1,250 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL - Académie des Arts Traditionnels de l'Inde{% endblock %}
{% block content %}
<!-- <div class="cover cover__home"></div> -->
<article class="about" id="about">
<div class="content--l col2--1-3">
<img class="media" src="{% static 'home/media/portrait.webp' %}" alt="Portrait">
<div>
<h3 class="slogan">Apprenez les Arts Traditionnels de l'Inde avec TAAL Académie</h3>
<p>
TAAL Académie est engagée depuis 2013 dans la promotion des Arts Traditionnels (classiques et folks) de
l'Inde et du Pakistan, à travers l'enseignement de l'<a href="#drums">Art Musical</a> (tabla, pakhawaj,
srikhol, dhol, dholak, dhadh, daf, khartal du Rajasthan, naqqara, konnakol...Sargam), l'<a
href="#gatka">Art Martial</a> (Gatka), les <a href="#visual">Arts Visuels</a> (Rangoli/Kollam), la
Spiritualité (Naad Yoga, Surat Shabad Yoga, Méditation), la <a href="#cooking">Cuisine</a> (indienne,
végétalienne et végétarienne), et bien plus encore...
</p>
<a href="/pages/about" class="button">Plus d'infos &rarr;</a>
</div>
</div>
</article>
<article class="cooking" id="cooking">
<h2>Cuisines</h2>
<div class="content--l col2">
<div>
<img class="media slider" src="{% static 'home/media/kheer_kesar.webp' %}" alt="Kheer Kesar">
<img class="media slider" src="{% static 'home/media/thali.webp' %}" alt="Thali">
<img class="media slider" src="{% static 'home/media/gajar_ka_halwa.webp' %}" alt="Gajar ka Halwa">
</div>
<div>
<p>
Dans ces ateliers de cuisine authentique indienne et végétarienne/végétalienne,
je vous propose d'apprendre à réaliser un Thali du Nord comme du Sud de l'Inde (repas complet et
traditionnel de recettes de tout les jours, faciles à réaliser avec des légumes de saison et locaux,
servis sur le Thali).
</p>
<p>
Des ateliers spécifiques sur la présentation des épices et de leurs vertus, les
différents pains indiens (chapati, paratha, laccha paratha, etc), les crêpes dosa (lacto fermentées)
et
idli (pains cuit à la vapeur) du Sud de l'Inde, les différents condiments (chutney, pickles, acchar)
et
les desserts, avec toujours une option sans lactose, sans gluten, sans sucre sur demande.
</p>
<p>
Nous terminons toujours ces ateliers par la dégustation des recettes réalisées ensemble et
présentées
dans la vaisselle indienne traditionnelle en inox (bartan).
</p>
<a href="/pages/cooking" class="button">Plus d'infos &rarr;</a>
</div>
</div>
</article>
<article class="drums" id="drums">
<div class="content">
<h2>Percussions</h2>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/tabla.webp' %}" alt="Tabla">
<div>
<h3>Tabla</h3>
<p>
Percussion classique de l'Inde du Nord
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/pakhawaj.webp' %}" alt="Pakhawaj">
<div>
<h3>Pakhawaj</h3>
<p>
Percussion Sacrée des Temples et de la musique Dhrupad
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/khartal.webp' %}" alt="Khartal">
<div>
<h3>Khartal</h3>
<p>
Castagnettes virtuoses du Rajasthan
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/dholak.webp' %}" alt="Dholak">
<div>
<h3>Dholak</h3>
<p>
Percussion digitale folk bifaces
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/dhol.webp' %}" alt="Dhol">
<div>
<h3>Dhol</h3>
<p>
Percussion baguettes du Panjab
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/dhadh.webp' %}" alt="Dhadh">
<div>
<h3>Dhadh</h3>
<p>
Percussion digitale des Bardes du Panjab
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/daf.webp' %}" alt="Daf">
<div>
<h3>Daf</h3>
<p>
Tambour digital sur cadre
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/konnakol.webp' %}" alt="Konnakol">
<div>
<h3>Konnakol</h3>
<p>
Percussion vocale de l'Inde du Sud
</p>
<a href="/pages/drums" class="button">Plus d'infos &rarr;</a>
</div>
</div>
</div>
</article>
<article class="gatka" id="gatka">
<h2>Gatka & Shakti Yoga</h2>
<div class="content--s">
<div>
<h3>Le Gatka... pour faire l'expérience de la Grâce</h3>
<p>
Le Gatka est un art martial ancien qui a fait ses preuves à travers de nombreuses batailles et
existe
dans le Nord de l'Inde depuis des milliers d'années.
<p>
</p>
Exercice autant spirituel que physique, le Gatka est basé sur le principe d'unification de l'esprit, de
l'âme et du corps, par le rythme de la vie, nous entraînant à être capable de se défendre nous-mêmes.
<p>
</p>
En plus de donner à l'élève des talents défensifs, il permet également à l'individu, de garder l'esprit
alerte et réactif, de maintenir le corps dans des conditions presque parfaites et rendre l'âme sans
aucune peur, compatissante et tranquille.
<p>
</p>
Gatka signifie « Grâce » et « arrêt de la pensée », ou encore « état d'extase ». Ceci est rendu possible
grâce à l'ensemble des mouvements du Gatka, basés sur le « 8 »; le signe de l'infini.
<p>
</p>
Nous pratiquerons le Shakti Yoga qui a le pouvoir d'éveiller et renforcer la lionne et le lion
intérieur, aidant à maîtriser nos peurs et notre destin, et ainsi devenir Un avec Tout.
</p>
<a href="/pages/gatka" class="button">Plus d'infos &rarr;</a>
</div>
</div>
</article>
<article class="visual" id="visual">
<div class="content--l">
<h2>Arts Visuels</h2>
<div class="col3">
<div>
<h3>Rangoli & Kolam</h3>
<img class="media" src="{% static 'home/media/kolam.webp' %}" alt="Rangoli & Kolam">
<p>Arts Visuels Indiens</p>
<a href="/pages/visual" class="button">Plus d'infos &rarr;</a>
</div>
<div>
<h3>Calligraphie</h3>
<img class="media" src="{% static 'home/media/calligraphy.webp' %}" alt="Calligraphie">
<p>Hindi & Gurmukhi au Kalam</p>
<a href="/pages/visual" class="button">Plus d'infos &rarr;</a>
</div>
<div>
<h3>Entrelacs Celtiques</h3>
<img class="media" src="{% static 'home/media/entrelac.webp' %}" alt="Entrelacs Celtiques">
<p>Issus des Manuscrits Irlandais</p>
<a href="/pages/visual" class="button">Plus d'infos &rarr;</a>
</div>
</div>
</div>
</article>
<article class="workshops" id="workshops">
<div class="content col2">
<div>
<h2>Cours & Stages</h2>
<p>Des Cours et Ateliers sont proposés à Brasparts, dans le Finistère et les départements voisins :</p>
</div>
<ul>
<li><strong>Rythmes indiens et Konnakol</strong> (percussion vocale du Sud de l'Inde)</li>
<li><strong>Percussions folks et classiques du Nord de l'Inde</strong></li>
<li><strong>Chant indien</strong> (Sargam)</li>
<li><strong>Arts visuels</strong> (Kollam/Rangoli)</li>
<li><strong>Art Martial indien</strong> (Gatka)</li>
<li><strong>Cuisine indienne végétarienne et vegan</strong></li>
<li><strong>Alimentation Vivante et Consciente</strong></li>
<li><strong>Yoga et méditation</strong> (Shakti yoga, Naad yoga, Surat Shabad yoga)</li>
<li><strong>Vaastu</strong> (géobiologie indienne/Feng Shui sacré de l'Inde)</li>
</ul>
</div>
<div class="content col2">
{% block workshops %}{% endblock %}
</div>
<div class="content">
<p>&rarr; Si vous êtes intéréssé(e) par un cours ou atelier non programmé n'hésitez pas à nous <a
href="#contact">contacter</a>.</p>
</div>
</article>
<article class="events" id="events">
<div class="content">
<h2>Évenements à venir</h2>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/affiche_2023-08-27.webp' %}" alt="Affiche">
<div>
<h3>Telenn ar Sterennoù, le 27 août 2023</h3>
<h4>Andrea Seki</h4>
<p>Compositions originales et inédites pour Harpe Néo Celtique Fx Loop Chants</p>
<h4>Harjit Singh</h4>
<p>Percussions Indiennes</p>
</div>
</div>
<div class="flex--zz">
<img class="media" src="{% static 'home/media/affiche_2023-08-23.webp' %}" alt="Affiche">
<div>
<h3>Telenn ar Sterennoù, le 23 août 2023</h3>
<h4>Andrea Seki</h4>
<p>Compositions originales et inédites pour Harpe Néo Celtique Fx Loop Chants</p>
<h4>Harjit Singh</h4>
<p>Percussions Indiennes</p>
</div>
</div>
</div>
</article>
{% endblock %}

3
django/src/home/tests.py Normal file
View File

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

6
django/src/home/urls.py Normal file
View File

@ -0,0 +1,6 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]

9
django/src/home/views.py Normal file
View File

@ -0,0 +1,9 @@
from django.shortcuts import render
from workshops.models import Workshop
# Create your views here.
def index(request):
workshops = Workshop.objects.all()
data = {'workshops': workshops}
return render(request, 'workshops/index.html', data)

32
django/src/local.env Normal file
View File

@ -0,0 +1,32 @@
#######################################
### Docker
POSTGRES_USER=postgres
POSTGRES_DB=postgres
#POSTGRES_PASSWORD=
DJANGO_ENV=local
#######################################
### Django
# Security
DEBUG=False
#SECRET_KEY=
ALLOWED_HOSTS=127.0.0.1,localhost
CSRF_TRUSTED_ORIGINS=http://127.0.0.1:8001,http://localhost:8001
# Database
DATABASE_NAME=postgres
DATABASE_USER=postgres
#DATABASE_PASS=
DATABASE_HOST=taal-academiearreebzh_postgres
DATABASE_PORT=5432
# SMTP server
EMAIL_HOST=mail.netig.net
EMAIL_HOST_USER=test@netig.net
#EMAIL_HOST_PASSWORD=
EMAIL_PORT=465
EMAIL_USE_SSL=True
EMAIL_USE_TLS=False

22
django/src/manage.py Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

6
django/src/pages/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class PagesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'pages'

View File

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,30 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Présentation{% endblock %}
{% block content %}
<div class="cover cover__about"></div>
<article>
<h2>Bio</h2>
<div class="content">
<p>
Diplômé des Arts Graphiques et des Arts Plastiques, Harjit Singh commence ses études de batterie en
1984, et
étudie le tabla, dès 1993 en Inde auprès des plus grands maîtres de la tradition classique, puis toutes
les
percussions folks et classiques du Nord de l'Inde (pakhawaj et jorhi, dholak, dhol, naqara, khartals du
Rajasthan), ainsi que le chant indien, la vièle sarangi et le Gatka (Art Martial indien) en 1999, qu'il
enseigne depuis à tout les publics, en Bretagne, en France et en Europe. Il anime pendant dix ans, à la
Cité
de la musique, des ateliers pédagogiques.
</p>
<p>
Il accompagne régulièrement la danse indienne et récitals de musique hindustani, ainsi que des créations
plus contemporaines et transversales, compose pour le cinéma et la télévision et anime également des
stages
de cuisine indienne et alimentation vivante.
</p>
</div>
</article>
{% endblock %}

View File

@ -0,0 +1,127 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Cuisines{% endblock %}
{% block content %}
<div class="cover cover__cooking"></div>
<article>
<h2>Cuisines</h2>
<div class="banner">
<h3>Idées cadeau à offrir pour les fêtes et toute lannée</h3>
<p>(dans la limite des places disponibles)</p>
<h4>Offrez des Cartes Cadeau pour un Atelier de Cuisine Indienne</h4>
<p>
Ces ateliers (voir Descriptif d'un atelier) de 4h se déroulent de 15h à 19h (+ temps du repas) et
certains pourront aussi se dérouler en matinée (9h-13h) selon la demande.
Faites-moi savoir les dates que souhaiteriez réserver, afin que je vous envoie des Cartes Cadeaux
dès
que possible.
</p>
</div>
<div class="content">
<h3>Atelier de Cuisine Indienne Végéta*ienne</h3>
<p>
Lieu : Cuisine de la salle des fêtes<br>
362 Impasse de la Salle des Fêtes, 29190 Brasparts
</p>
<p>
Durée : 4 h (+ temps du repas)
</p>
<p>
Langue : Français, Anglais
</p>
<h4>Venez apprendre à cuisiner avec les épices de l'Inde</h4>
<p>
Dans cet atelier de cuisine authentique indienne et végétarienne/végétalienne*, je vous propose
d'apprendre
à réaliser un thali du Nord ou du Sud de l'Inde (repas complet et traditionnel de recettes de tout les
jours, faciles à réaliser avec des légumes de saison et locaux, servi sur le thali) comprenant :
</p>
<ul>
<li>1 entrée</li>
<li>1 plat de légumineuses (dal) ou 1 plat de légumes</li>
<li>1 accompagnement (pains indiens/chapati/paratha)</li>
<li>1 dessert</li>
</ul>
<p>
Tout les ingrédients sont issus de l'agriculture biologique (sauf quelques épices indiennes que je
commande
en Inde)
</p>
<p>
Déroulement de l'atelier :
</p>
<ul>
<li>Présentation des épices et de leurs vertus.</li>
<li>Confection des plats et des galettes de pains.</li>
<li>Nous terminerons cet atelier par la dégustation des recettes réalisées ensemble et présentées dans
la
vaisselle indienne traditionnelle en inox (bartan)
</li>
</ul>
<p>Prévoir :</p>
<ul>
<li>un tablier</li>
<li>un rouleau à pâtisserie pour la confection des pains</li>
<li>un couteau de cuisine</li>
<li>une planche à découper</li>
<li>de quoi noter les recettes</li>
<li>le temps de repas au delà de 19h</li>
</ul>
<p>
Tarif : 40 euros par participant-e
</p>
<p>
Informations et inscription via taal.academie@gmail.com ou taal-academie@arree.bzh
06 24 20 76 09 taal-academie.arree.bzh > pour découvrir les autres dates d'atelier (1 à 2 fois par mois)<br>
</p>
<p>
*(précisez-moi vos intolérances et allergies lactose, gluten, sucre, oignon, piment, ...)
</p>
<p>
Au plaisir de partager avec vous ces saveurs de l'Inde, qui enchantent mon quotidien depuis 30 ans, dans
la
joie et la bonne humeur !<br>
</p>
<p>
Harjit
</p>
<p>
<strong>Ces ateliers peuvent se dérouler chez vous, dès que vous avez un groupe de personnes intéressées
(15
maximum) et l'espace (une cuisine équipée ou non) pour accueillir un atelier (9H -13H ou 15h - 19h +
temps
du repas)</strong>
</p>
<h3><br>Chef à domicile</h3>
<p>
Pour vos déjeuner ou dîner entre amis, fêtes, anniversaires, ... je me déplace dans le Finistère et
proche
Cotes d'Armor, Morbihan pour vous faire découvrir la gastronomie de la cuisine indienne authentique et
vous
proposer un menu complet végétarien ou végétalien/vegan*, servi dans la vaisselle indienne (thali en
inox),
cuisiné au feu de bois et livré chez vous ou cuisiné sur place (les dernières préparations seront
cuisinées
sur place - chapati, paratha,...) pour une fraîcheur optimale.
</p>
<p>
*(précisez-moi vos intolérances et allergies lactose, gluten, sucre, oignon, piment, ...)
</p>
<p>
Menus au choix :
</p>
<ul>
<li>Inde du nord (Cachemire, Panjab, Rajasthan, Gujarat, ...)</li>
<li>Inde de l'Est (Bengal, Orissa)</li>
<li>Inde du Sud (Maharastra, Kerala, Tamil Nadu, ...)</li>
</ul>
<br>
<div class="press">
<iframe
src="https://www.letelegramme.fr/finistere/brasparts-29190/ils-sinitient-a-la-cuisine-indienne-a-brasparts-6467105.php"></iframe>
</div>
</div>
</article>
{% endblock %}

View File

@ -0,0 +1,16 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Percussions{% endblock %}
{% block content %}
<div class="cover cover__drums"></div>
<article>
<h2>Percussions</h2>
<div class="content">
<p>
En cours de rédaction...
</p>
</div>
</article>
{% endblock %}

View File

@ -0,0 +1,66 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Gatka{% endblock %}
{% block content %}
<div class="cover cover__gatka"></div>
<article>
<h2>Gatka</h2>
<div class="content--l col2">
<div>
<h3>Harjit Singh</h3>
<p>
Après avoir senti très tôt l'appel de l'Épée, et dédié sa vie à la musique et à l'art, Harjit Singh
commence
par pratiquer l'escrime dans ses jeunes années, avec un Maître d'Arme, en France.
</p>
<p>
Ses études de graphisme et d'arts plastiques terminées, il débute dès 1993, le long apprentissage
traditionnel des rythmes et percussions classiques et folks Hindustani (tabla, pakhawaj, naqara,
dhol et
dholak...), auprès de différents Maîtres, en Inde du Nord.
</p>
<p>
Il y découvre les traditions du Panjab dès 1999, là où naît son amour pour le Gatka, et le Dharma
Sikh.
</p>
<p>
Il rejoint depuis le premier Akharaa (espace d'entraînement) de Gatka, dans le premier Gurdwara
(lieu de
culte Sikh) près de Paris et se produit dans toute l'Europe au sein du groupe 'Miri Piri Gatka
Akharaa'.
Aujourd'hui, Harjit Singh ouvre au grand public pour la première fois en Bretagne l'enseignement du
Gatka
associé au Shakti Yoga.
</p>
<p>
Longtemps enseigné dans l'enceinte des temples Sikhs, et transmis aux seuls initiés baptisés par
l'Amrit
et
adoubés par l'épée, le Gatka est un art martial que les Sikhs ont développé au plus haut niveau.
</p>
<p>
En rendant le Gatka accessible à tous, Harjit Singh souhaite offrir à chacun-e l'expérience de la
Grâce,
la
rencontre avec sa dimension divine et son guerrier intérieur.
</p>
</div>
<div>
<div class="youtube-video-container">
<iframe width="1195" height="672" src="https://www.youtube.com/embed/9taHckciFrI"
title="LE GATKA AU 33EME FESTIVAL DES ARTS MARTIAUX" frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen></iframe>
</div>
<p>Démonstration de Gatka au 33ème festival des arts martiaux<br>
Tradition : Shastar Vidya / Gatka / Raj Yoga</p>
<a class="icon" href="https://www.facebook.com/gatkashaktiyoga" target="_blank"><img
src="{% static 'home/media/facebook.svg' %}" width="46px" height="46px" alt="Facebook">
</a>
</div>
</div>
</article>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Mentions légales{% endblock %}
{% block content %}
<article>
<h2>Mentions Légales</h2>
<div class="content--s col2">
<div>
Siret : 815 370 952 00013<br>
RNA : W931011248<br>
Création : 15/02/2013<br>
Publication : 02/03/2013<br>
</ul>
</div>
<div>
<p>
Harjit Singh<br>
24 Prat ar Veguerez<br>
Route de Lannedern<br>
29190 BRASPARTS<br>
</p>
</div>
</div>
</article>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% extends 'home/base.html' %}
{% load static %}
{% block title %}TAAL : Arts visuels{% endblock %}
{% block content %}
<div class="cover cover__visual"></div>
<article>
<h2>Arts Visuels</h2>
<div class="content">
<h3>Rangoli & Kolam</h3>
<p>
En Inde, perdure malgré la mondialisation, une tradition ancestrale transmise de générations en
générations, bien souvent féminines.
</p>
<p>
L'art des Rangoli (Nord de l'Inde) ou Kolam (Sud de l'Inde), englobe le réalisation de mandalas
éphémères car réalisés à la poudre de riz, tracés à même le sol devant les maisons. Les couleurs
sont
utilisées pour les grandes occasions.
</p>
<p>
Un art quotidien pour célébrer la vie, le vivant, la Nature et accueillir le Divin dans sa demeure
pour
protéger ses habitants.
</p>
<p>
Un art accessible à tous et à tout age
</p>
</div>
<div class="content">
<h3>Calligraphie</h3>
<p>
En cours de rédaction...
</p>
</div>
<div class="content">
<h3>Entrelacs Celtiques</h3>
<p>
En cours de rédaction...
</p>
</div>
</article>
{% endblock %}

View File

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

11
django/src/pages/urls.py Normal file
View File

@ -0,0 +1,11 @@
from django.urls import path
from . import views
urlpatterns = [
path('about/', views.about, name='about'),
path('cooking/', views.cooking, name='cooking'),
path('drums/', views.drums, name='drums'),
path('gatka/', views.gatka, name='gatka'),
path('visual/', views.visual, name='visual'),
path('legal/', views.legal, name='legal'),
]

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