Skip to content

Commit

Permalink
Merge branch 'sf_update_fork' into sf_update_fork_fix_conflit
Browse files Browse the repository at this point in the history
  • Loading branch information
SebastienReuiller authored Jan 10, 2025
2 parents d0bab59 + 4744e50 commit 1258684
Show file tree
Hide file tree
Showing 34 changed files with 1,087 additions and 99 deletions.
10 changes: 10 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ S3_KEY_ID=
S3_KEY_SECRET=
S3_BUCKET_NAME=
S3_BUCKET_REGION=eu-west-3

# S3_LOCATION: If the S3 bucket is shared, add a unique folder name
S3_LOCATION=

Expand All @@ -41,3 +42,12 @@ EMAIL_SSL_CERTFILE=
WAGTAIL_PASSWORD_RESET_ENABLED=False
# WAGTAIL_PASSWORD_RESET_ENABLED: set to true to be able to send the email
# from the DEFAULT_FROM_EMAIL through the defined SMTP parameters

# SF_ALLOW_RAW_HTML_BLOCKS: devs who create migrations should put this variable to True
SF_ALLOW_RAW_HTML_BLOCKS=False

AIRTABLE_API_KEY=
AIRTABLE_BASE_KEY=
AIRTABLE_TABLE_NAME="Liste des formations et parcours [Public]"
AIRTABLE_TABLE_NAME_THEME="Familles thématiques"
AIRTABLE_TABLE_NAME_ORGA="Organisations"
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10
FROM python:3.11

EXPOSE ${CONTAINER_PORT}

Expand Down
24 changes: 24 additions & 0 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"wagtailmenus",
"wagtail_localize",
"wagtail_localize.locales",
"wagtail_airtable",
"taggit",
"wagtail.api.v2",
"rest_framework",
Expand All @@ -82,6 +83,7 @@
"blog",
"events",
"forms",
"formations",
]

# Only add these on a dev machine, outside of tests
Expand Down Expand Up @@ -337,6 +339,28 @@ def show_toolbar(request):

WAGTAIL_PASSWORD_RESET_ENABLED = os.getenv("WAGTAIL_PASSWORD_RESET_ENABLED", False)

# Wagtail Airtable
AIRTABLE_API_KEY = os.getenv("AIRTABLE_API_KEY")
WAGTAIL_AIRTABLE_ENABLED = True
WAGTAIL_AIRTABLE_DEBUG = True
WAGTAIL_AIRTABLE_SAVE_SYNC = False

AIRTABLE_IMPORT_SETTINGS = {
"formations.FormationPage": {
"AIRTABLE_BASE_KEY": os.getenv("AIRTABLE_BASE_KEY"),
"AIRTABLE_TABLE_NAME": os.getenv("AIRTABLE_TABLE_NAME"),
"AIRTABLE_TABLE_NAME_THEME": os.getenv("AIRTABLE_TABLE_NAME_THEME"),
"AIRTABLE_TABLE_NAME_ORGA": os.getenv("AIRTABLE_TABLE_NAME_ORGA"),
"AIRTABLE_UNIQUE_IDENTIFIER": {
"Wagtail Page ID": "pk",
},
"AIRTABLE_SERIALIZER": "formations.serializers.FormationPageSerializer",
"AIRTABLE_IMPORT_ALLOWED": True,
"PARENT_PAGE_ID": "formations.utils.get_parent_page_of_formation_page",
"AUTO_PUBLISH_NEW_PAGES": True,
}
}

# CSRF
CSRF_TRUSTED_ORIGINS = []
for host in ALLOWED_HOSTS:
Expand Down
2 changes: 2 additions & 0 deletions config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
path(settings.WAGTAILADMIN_PATH, include(wagtailadmin_urls)),
path("documents/", include(wagtaildocs_urls)),
path("api/v2/", api_router.urls),
path("", include("formations.urls")),
path("", include("content_manager.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

urlpatterns += i18n_patterns(
Expand Down
35 changes: 35 additions & 0 deletions content_manager/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import factory
from wagtail.models import Page

from content_manager.models import ContentPage


class PageFactory(factory.django.DjangoModelFactory):
class Meta:
abstract = True

# override the _create method, to establish parent-child relationship between page and home
@classmethod
def _create(cls, model_class, *args, **kwargs):
parent = Page.objects.filter(slug="home").first()
page = model_class(*args, **kwargs)
parent.add_child(instance=page)
return page


class ContentPageFactory(PageFactory):
"""Generates ContentPage() objects for unit tests."""

class Meta:
model = ContentPage

class Params:
with_seo_title = factory.Trait(
seo_title=factory.Faker("sentence", nb_words=5, variable_nb_words=True, locale="fr_FR")
)
with_search_description = factory.Trait(
search_description=factory.Faker("sentence", nb_words=10, variable_nb_words=True, locale="fr_FR")
)

slug = factory.Faker("slug")
title = factory.Faker("sentence", nb_words=5, locale="fr_FR")
4 changes: 2 additions & 2 deletions content_manager/templates/content_manager/blocks/heading.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{% load static wagtailcore_tags wagtailimages_tags %}
{% if page.header_image or page.header_color_class %}
{% image page.header_image fill-1200x350 as bg_img %}
{% image page.header_image original as bg_img %}
<div class="cmsfr-hero{% if page.header_large %} cmsfr-hero-large{% endif %}{% if page.header_darken %} cmsfr-background-dark{% endif %}"
style="{% if page.header_image %}background-image: {% if page.header_darken %}linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)),{% endif %}url({{ bg_img.url }});
{% elif page.header_color_class %}background-color: var(--background-alt-{{ page.header_color_class }});
{% endif %} min-height: 350px">
{% if page.header_with_title or page.header_cta_buttons or page.header_cta_link and page.header_cta_label %}
<div class="fr-container fr-py-8w">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col fr-col-12{% if not page.header_large %}fr-col-md-6{% endif %}">
<div class="fr-col fr-col-12{% if not page.header_large %} fr-col-md-6{% endif %}">
{% if page.header_with_title %}
<h1 {% if block.value.large %}class="fr-display--sm"{% endif %}>
{{ page.title }}
Expand Down
31 changes: 31 additions & 0 deletions content_manager/templates/content_manager/breadcrumb.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% if self.get_ancestors|length > 1 %}
<div class="fr-container fr-mt-1w">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12">
<nav role="navigation" class="fr-breadcrumb" aria-label="vous êtes ici :">
<button type="button"
class="fr-breadcrumb__button"
aria-expanded="false"
aria-controls="breadcrumb-1">
Voir le fil d’Ariane
</button>
<div class="fr-collapse" id="breadcrumb-1">
<ol class="fr-breadcrumb__list">
{% for link in self.get_ancestors %}
{% if link.is_root == False %}
<li>
<a class="fr-breadcrumb__link" href="{{ link.url }}">{{ link.title }}</a>
</li>
{% endif %}
{% endfor %}
<li>
<a aria-current="page"
class="fr-breadcrumb__link router-link-exact-active">{{ page.title }}</a>
</li>
</ol>
</div>
</nav>
</div>
</div>
</div>
{% endif %}
Empty file added formations/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions formations/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class FormationsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "formations"
16 changes: 16 additions & 0 deletions formations/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.db import models


class Kind(models.TextChoices):
FORMATION = "formation", "Formation"
PARCOURS = "parcours", "Parcours"
CYCLE = "cycle", "Cycle"
SEMINAIRE = "séminaire", "Séminaire"
UNIVERSITE = "université d'été", "Université d'été"
PROGRAMME = "programme", "Programme"


class Attendance(models.TextChoices):
ENLIGNE = "enligne", "En ligne"
PRESENTIEL = "présentiel", "Présentiel"
HYBRIDE = "hybride", "Hybride"
70 changes: 70 additions & 0 deletions formations/factories.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import factory
import factory.fuzzy

from content_manager.factories import ContentPageFactory
from formations.enums import Attendance, Kind
from formations.models import FormationPage, Organizer, TargetAudience, Theme


class TargetAudienceFactory(factory.django.DjangoModelFactory):
class Meta:
model = TargetAudience

name = factory.Faker("sentence", nb_words=3, locale="fr_FR")


class ThemeFactory(factory.django.DjangoModelFactory):
class Meta:
model = Theme

name = factory.Faker("sentence", nb_words=3, locale="fr_FR")
airtable_id = factory.Faker("random_int", min=0, max=10000)


class OrganizerFactory(factory.django.DjangoModelFactory):
class Meta:
model = Organizer

name = factory.Faker("sentence", nb_words=3, locale="fr_FR")
airtable_id = factory.Faker("random_int", min=0, max=10000)


class FormationPageFactory(ContentPageFactory):
class Meta:
model = FormationPage

name = factory.Faker("sentence", nb_words=3, locale="fr_FR")
kind = factory.fuzzy.FuzzyChoice(Kind.values)
short_description = factory.Faker("sentence", nb_words=15, locale="fr_FR")
knowledge_at_the_end = factory.Faker("sentence", nb_words=15, locale="fr_FR")
duration = factory.Faker("sentence", nb_words=1, locale="fr_FR")
registration_link = factory.Faker("url")
image_url = factory.Faker("url")
attendance = factory.fuzzy.FuzzyChoice(Attendance.values)

@factory.post_generation
def target_audience(self, create, extracted, **kwargs):
if not create:
return

if extracted:
for audience in extracted:
self.target_audience.add(audience)

@factory.post_generation
def themes(self, create, extracted, **kwargs):
if not create:
return

if extracted:
for theme in extracted:
self.themes.add(theme)

@factory.post_generation
def organizers(self, create, extracted, **kwargs):
if not create:
return

if extracted:
for organizer in extracted:
self.organizers.add(organizer)
17 changes: 17 additions & 0 deletions formations/form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django import forms

from formations.models import Theme


class FormationsFilterForm(forms.Form):
themes = forms.ModelMultipleChoiceField(
label="Thématiques",
queryset=Theme.objects.filter(formationpage__isnull=False).distinct(),
widget=forms.CheckboxSelectMultiple(
attrs={
"class": "form-checkbox fr-input vh",
"onchange": "this.form.submit()",
}
),
required=False,
)
59 changes: 59 additions & 0 deletions formations/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Generated by Django 4.1.10 on 2023-09-29 09:25

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
initial = True

dependencies = [
("wagtailcore", "0078_referenceindex"),
]

operations = [
migrations.CreateModel(
name="FormationPage",
fields=[
(
"page_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="wagtailcore.page",
),
),
("airtable_record_id", models.CharField(blank=True, db_index=True, max_length=35)),
("name", models.CharField(max_length=255, verbose_name="Intitulé")),
(
"kind",
models.CharField(
blank=True,
choices=[
("formation", "Formation"),
("parcours", "Parcours"),
("cycle", "Cycle"),
("séminaire", "Séminaire"),
("université d'été", "Université d'été"),
("programme", "Programme"),
],
max_length=20,
verbose_name="Type",
),
),
("short_description", models.TextField(blank=True, verbose_name="Descriptif court")),
("knowledge_at_the_end", models.TextField(blank=True, verbose_name="À la fin, vous saurez")),
("duration", models.IntegerField(blank=True, null=True, verbose_name="Durée (min)")),
("registration_link", models.URLField(blank=True, max_length=255, verbose_name="Lien d'inscription")),
("image_url", models.URLField(blank=True, null=True, verbose_name="URL Image")),
("visible", models.TextField(blank=True, verbose_name="Visible")),
],
options={
"verbose_name": "Page Formation/Parcours",
},
bases=("wagtailcore.page", models.Model),
),
]
Loading

0 comments on commit 1258684

Please sign in to comment.