diff --git a/deployment/Dockerfile b/deployment/Dockerfile index 0ef795c..5cab593 100644 --- a/deployment/Dockerfile +++ b/deployment/Dockerfile @@ -5,7 +5,7 @@ WORKDIR /usr/src/app RUN --mount=type=cache,target=/var/cache/apt \ apt-get update && \ - apt-get install --no-install-recommends -y build-essential libpq-dev \ + apt-get install --no-install-recommends -y build-essential libpq-dev gettext \ && rm -rf /var/lib/apt/lists/* diff --git a/deployment/scripts/backend/start.sh b/deployment/scripts/backend/start.sh index b6b7994..5256b42 100644 --- a/deployment/scripts/backend/start.sh +++ b/deployment/scripts/backend/start.sh @@ -4,10 +4,12 @@ if [ "$APP_ENV" != "prod" ]; then python manage.py makemigrations --noinput python manage.py migrate --noinput + python manage.py compilemessages python manage.py runserver "$APP_HOST":"$APP_PORT" else python manage.py makemigrations --noinput python manage.py migrate --noinput python manage.py collectstatic --noinput + python manage.py compilemessages gunicorn "$APP_NAME".wsgi:application --bind "$APP_HOST":"$APP_PORT" --workers 3 --log-level=info fi diff --git a/src/agenda_culturel/admin.py b/src/agenda_culturel/admin.py new file mode 100644 index 0000000..023636f --- /dev/null +++ b/src/agenda_culturel/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin +from .models import Event + +admin.site.register(Event) \ No newline at end of file diff --git a/src/agenda_culturel/locale/fr_FR/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr_FR/LC_MESSAGES/django.po new file mode 100644 index 0000000..56b93b6 --- /dev/null +++ b/src/agenda_culturel/locale/fr_FR/LC_MESSAGES/django.po @@ -0,0 +1,134 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-10-14 15:29+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: agenda_culturel/models.py:15 +msgid "Published" +msgstr "Publié" + +#: agenda_culturel/models.py:16 +msgid "Trash" +msgstr "Corbeille" + +#: agenda_culturel/models.py:17 +msgid "Draft" +msgstr "Brouillon" + +#: agenda_culturel/models.py:24 +msgid "Title" +msgstr "Titre" + +#: agenda_culturel/models.py:24 +msgid "Short title" +msgstr "Titre court" + +#: agenda_culturel/models.py:26 +msgid "Status" +msgstr "Status" + +#: agenda_culturel/models.py:28 +msgid "Day of the event" +msgstr "Date de l'événement" + +#: agenda_culturel/models.py:29 +msgid "Starting time" +msgstr "Heure de début" + +#: agenda_culturel/models.py:31 +msgid "End day of the event" +msgstr "Fin de l'événement" + +#: agenda_culturel/models.py:31 +msgid "End day of the event, only required if different from the start day." +msgstr "" +"Date de fin de l'événement, uniquement nécessaire s'il est différent du " +"premier jour de l'événement" + +#: agenda_culturel/models.py:32 +msgid "Final time" +msgstr "Heure de fin" + +#: agenda_culturel/models.py:34 +msgid "Location" +msgstr "Localisation" + +#: agenda_culturel/models.py:34 +msgid "Address of the event" +msgstr "Adresse de l'événement" + +#: agenda_culturel/models.py:36 +msgid "Description" +msgstr "Description" + +#: agenda_culturel/models.py:36 +msgid "General description of the event" +msgstr "Description générale de l'événement" + +#: agenda_culturel/models.py:38 +msgid "Illustration" +msgstr "Illustration" + +#: agenda_culturel/models.py:38 +msgid "URL of the illustration image" +msgstr "URL de l'image illustrative" + +#: agenda_culturel/models.py:39 +msgid "Illustration description" +msgstr "Description de l'illustration" + +#: agenda_culturel/models.py:39 +msgid "Alternative text used by screen readers for the image" +msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" + +#: agenda_culturel/models.py:41 +msgid "URLs" +msgstr "URLs" + +#: agenda_culturel/models.py:41 +msgid "List of all the urls where this event can be found." +msgstr "Liste de toutes les urls où l'événement peut être trouvé." + +#: agenda_culturel/models.py:55 +msgid "Event" +msgstr "Événement" + +#: agenda_culturel/models.py:56 +msgid "Events" +msgstr "Événements" + +#: agenda_culturel/views.py:11 +msgid "this_week" +msgstr "cette_semaine" + +#: agenda_culturel/views.py:12 +msgid "this_weekend" +msgstr "ce_weekend" + +#: agenda_culturel/views.py:13 +msgid "next_week" +msgstr "semaine_prochaine" + +#: agenda_culturel/views.py:14 +msgid "this_month" +msgstr "ce_mois_ci" + +#: agenda_culturel/views.py:15 +#, fuzzy +#| msgid "next_mont" +msgid "next_month" +msgstr "mois_prochain" diff --git a/src/agenda_culturel/migrations/0001_initial.py b/src/agenda_culturel/migrations/0001_initial.py new file mode 100644 index 0000000..0925219 --- /dev/null +++ b/src/agenda_culturel/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# Generated by Django 4.2.1 on 2023-10-14 09:53 + +import django.contrib.postgres.fields +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('slug', models.SlugField(editable=False, unique=True)), + ('created_date', models.DateTimeField(auto_now_add=True)), + ('modified_date', models.DateTimeField(auto_now=True)), + ('title', models.CharField(help_text='Short title', max_length=512, verbose_name='Title')), + ('status', models.CharField(choices=[('published', 'Published'), ('trash', 'Trash'), ('draft', 'draft')], default='published', max_length=20, verbose_name='Status')), + ('start_day', models.DateField(help_text='Day of the event', verbose_name='Day of the event')), + ('start_time', models.TimeField(help_text='Starting time', verbose_name='Starting time')), + ('end_day', models.DateField(help_text='End day of the event, only required if different from the start day.', verbose_name='End day of the event')), + ('end_time', models.TimeField(help_text='Final time', verbose_name='Final time')), + ('location', models.CharField(help_text='Address of the event', max_length=512, verbose_name='Location')), + ('description', models.TextField(blank=True, help_text='General description of the event', null=True, verbose_name='Description')), + ('image', models.URLField(help_text='URL of the illustration image', verbose_name='Illustration')), + ('image_alt', models.CharField(help_text='Alternative text used by screen readers for the image', max_length=512, verbose_name='Illustration description')), + ('reference_urls', django.contrib.postgres.fields.ArrayField(base_field=models.URLField(), help_text='List of all the urls where this event can be found.', size=None, verbose_name='URLs')), + ], + ), + ] diff --git a/src/agenda_culturel/migrations/0002_alter_event_end_day_alter_event_end_time_and_more.py b/src/agenda_culturel/migrations/0002_alter_event_end_day_alter_event_end_time_and_more.py new file mode 100644 index 0000000..a76eea1 --- /dev/null +++ b/src/agenda_culturel/migrations/0002_alter_event_end_day_alter_event_end_time_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 4.2.1 on 2023-10-14 10:04 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda_culturel', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='end_day', + field=models.DateField(blank=True, help_text='End day of the event, only required if different from the start day.', null=True, verbose_name='End day of the event'), + ), + migrations.AlterField( + model_name='event', + name='end_time', + field=models.TimeField(blank=True, help_text='Final time', null=True, verbose_name='Final time'), + ), + migrations.AlterField( + model_name='event', + name='image', + field=models.URLField(blank=True, help_text='URL of the illustration image', null=True, verbose_name='Illustration'), + ), + migrations.AlterField( + model_name='event', + name='image_alt', + field=models.CharField(blank=True, help_text='Alternative text used by screen readers for the image', max_length=512, null=True, verbose_name='Illustration description'), + ), + migrations.AlterField( + model_name='event', + name='reference_urls', + field=django.contrib.postgres.fields.ArrayField(base_field=models.URLField(), blank=True, help_text='List of all the urls where this event can be found.', null=True, size=None, verbose_name='URLs'), + ), + migrations.AlterField( + model_name='event', + name='start_time', + field=models.TimeField(blank=True, help_text='Starting time', null=True, verbose_name='Starting time'), + ), + ] diff --git a/src/agenda_culturel/migrations/__init__.py b/src/agenda_culturel/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py new file mode 100644 index 0000000..eeb46be --- /dev/null +++ b/src/agenda_culturel/models.py @@ -0,0 +1,56 @@ +from django.db import models +from django.contrib.postgres.fields import ArrayField +from django.utils.translation import gettext_lazy as _ +from django.template.defaultfilters import slugify # new +from django.urls import reverse +import uuid + +from django.template.defaultfilters import date as _date +from datetime import datetime + + +class Event(models.Model): + + class STATUS(models.TextChoices): + PUBLISHED = "published", _("Published") + TRASH = "trash", _("Trash") + DRAFT = "draft", _("Draft") + + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + slug = models.SlugField(null=False, unique=True, editable=False) + created_date = models.DateTimeField(auto_now_add=True) + modified_date = models.DateTimeField(auto_now=True) + + title = models.CharField(verbose_name=_('Title'), help_text=_('Short title'), max_length=512) + + status = models.CharField(_("Status"), max_length=20, choices=STATUS.choices, default=STATUS.PUBLISHED) + + start_day = models.DateField(verbose_name=_('Day of the event'), help_text=_('Day of the event')) + start_time = models.TimeField(verbose_name=_('Starting time'), help_text=_('Starting time'), blank=True, null=True) + + end_day = models.DateField(verbose_name=_('End day of the event'), help_text=_('End day of the event, only required if different from the start day.'), blank=True, null=True) + end_time = models.TimeField(verbose_name=_('Final time'), help_text=_('Final time'), blank=True, null=True) + + location = models.CharField(verbose_name=_('Location'), help_text=_('Address of the event'), max_length=512) + + description = models.TextField(verbose_name=_('Description'), help_text=_('General description of the event'), blank=True, null=True) + + image = models.URLField(verbose_name=_('Illustration'), help_text=_("URL of the illustration image"), max_length=200, blank=True, null=True) + image_alt = models.CharField(verbose_name=_('Illustration description'), help_text=_('Alternative text used by screen readers for the image'), blank=True, null=True, max_length=512) + + reference_urls = ArrayField(models.URLField(max_length=200), verbose_name=_('URLs'), help_text=_("List of all the urls where this event can be found."), blank=True, null=True) + + def get_absolute_url(self): + return reverse("view_event", kwargs={"slug": self.slug}) + + def save(self, *args, **kwargs): # new + if not self.slug: + self.slug = slugify(str(self.id) + "-" + self.title) + return super().save(*args, **kwargs) + + def __str__(self): + return _date(self.start_day) + ": " + self.title + + class Meta: + verbose_name = _('Event') + verbose_name_plural = _('Events') \ No newline at end of file diff --git a/src/agenda_culturel/settings/base.py b/src/agenda_culturel/settings/base.py index 260f28b..7435eb1 100644 --- a/src/agenda_culturel/settings/base.py +++ b/src/agenda_culturel/settings/base.py @@ -35,7 +35,7 @@ INSTALLED_APPS = [ "django.contrib.messages", "django.contrib.staticfiles", "corsheaders", - "test_app", + "agenda_culturel", ] MIDDLEWARE = [ @@ -105,9 +105,9 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/4.2/topics/i18n/ -LANGUAGE_CODE = "en-us" +LANGUAGE_CODE = "fr-fr" -TIME_ZONE = "UTC" +TIME_ZONE = "Europe/Paris" USE_I18N = True diff --git a/src/agenda_culturel/templates/agenda_culturel/event.html b/src/agenda_culturel/templates/agenda_culturel/event.html new file mode 100644 index 0000000..28b1dd4 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/event.html @@ -0,0 +1 @@ +

{{ object.title }}

diff --git a/src/agenda_culturel/templates/agenda_culturel/home.html b/src/agenda_culturel/templates/agenda_culturel/home.html new file mode 100644 index 0000000..901c0d6 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/home.html @@ -0,0 +1,8 @@ +

Événements

+ \ No newline at end of file diff --git a/src/agenda_culturel/templates/agenda_culturel/list.html b/src/agenda_culturel/templates/agenda_culturel/list.html new file mode 100644 index 0000000..64c4818 --- /dev/null +++ b/src/agenda_culturel/templates/agenda_culturel/list.html @@ -0,0 +1 @@ +ça marche \ No newline at end of file diff --git a/src/agenda_culturel/urls.py b/src/agenda_culturel/urls.py index 3ad4b1d..a0f0e72 100644 --- a/src/agenda_culturel/urls.py +++ b/src/agenda_culturel/urls.py @@ -2,9 +2,15 @@ from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from django.urls import path, include +from django.urls import path, include, re_path + + +from .views import * urlpatterns = [ + path("", EventListView.as_view(), name="home"), + re_path(r'^(?P' + '|'.join([dm.value for dm in DisplayModes]) + ')/$', view_interval, name='view_interval'), + path("event/", EventDetailView.as_view(), name="view_event"), path("admin/", admin.site.urls), path("test_app/", include("test_app.urls")), ] diff --git a/src/agenda_culturel/views.py b/src/agenda_culturel/views.py new file mode 100644 index 0000000..a12bfc9 --- /dev/null +++ b/src/agenda_culturel/views.py @@ -0,0 +1,36 @@ +from django.shortcuts import render +from django.views.generic import ListView, DetailView +from .models import Event +from django.utils import timezone +from enum import StrEnum + +from django.utils.translation import gettext as _ + + +class DisplayModes(StrEnum): + this_week = _("this_week") + this_weekend = _("this_weekend") + next_week = _("next_week") + this_month = _("this_month") + next_month = _("next_month") + +def view_interval(request, mode): + + context = {} + return render(request, 'agenda_culturel/list.html', context) + + +class EventListView(ListView): + model = Event + template_name = "agenda_culturel/home.html" + + + +class EventDetailView(DetailView): + model = Event + template_name = "agenda_culturel/event.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["now"] = timezone.now() + return context \ No newline at end of file