diff --git a/scratch/settings.py b/scratch/settings.py index 1f811d3..a65736c 100644 --- a/scratch/settings.py +++ b/scratch/settings.py @@ -104,9 +104,9 @@ AUTH_PASSWORD_VALIDATORS = [ # Internationalization # https://docs.djangoproject.com/en/4.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'fr-fr' -TIME_ZONE = 'UTC' +TIME_ZONE = 'Europe/Paris' USE_I18N = True diff --git a/scratch_show/forms.py b/scratch_show/forms.py index ec4ebd8..7b0b5d4 100644 --- a/scratch_show/forms.py +++ b/scratch_show/forms.py @@ -1,8 +1,25 @@ +import re + from django import forms from . import models + +SCRATCH_ID_REGEX = re.compile(r'https://scratch\.mit\.edu/projects/([0-9]+)') + +def get_scratch_id_from_url(url): + match = SCRATCH_ID_REGEX.search(url) + return int(match.group(1)) + + +class ScratchURLField(forms.URLField): + def clean(self, value): + url = super().clean(value) + scratch_id = get_scratch_id_from_url(url) + return scratch_id + + class ScratchProjectAddForm(forms.ModelForm): - url = forms.URLField(label='Lien Scratch du projet (URL)') + url = ScratchURLField(label='Lien Scratch du projet (URL)') class Meta: fields = ('name', 'author_name', 'url') diff --git a/scratch_show/migrations/0001_initial.py b/scratch_show/migrations/0001_initial.py index 79f9a75..05917d0 100644 --- a/scratch_show/migrations/0001_initial.py +++ b/scratch_show/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 4.0.4 on 2022-05-13 00:55 +# Generated by Django 4.0.4 on 2022-05-13 05:27 import datetime +import django.core.validators from django.db import migrations, models import django.db.models.deletion @@ -28,7 +29,7 @@ class Migration(migrations.Migration): ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=128, verbose_name='Nom du projet')), ('author_name', models.CharField(max_length=128, verbose_name='Auteur')), - ('project_id', models.PositiveBigIntegerField(unique=True, verbose_name='Scratch project id')), + ('project_url', models.URLField(validators=[django.core.validators.RegexValidator(regex='https?://scratch\\.mit\\.edu/projects/([0-9]+)/?')], verbose_name='Scratch project url')), ('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='scratch_show.event')), ], ), diff --git a/scratch_show/models.py b/scratch_show/models.py index c0edc55..892ee36 100644 --- a/scratch_show/models.py +++ b/scratch_show/models.py @@ -2,6 +2,7 @@ from datetime import date from django.db import models from django.urls import reverse +from django.core.validators import RegexValidator class Event(models.Model): name = models.CharField("Nom de l'évènement", max_length=128) @@ -12,7 +13,7 @@ class Event(models.Model): class ScratchProject(models.Model): name = models.CharField('Nom du projet', max_length=128) author_name = models.CharField('Auteur', max_length=128) - project_id = models.PositiveBigIntegerField('Scratch project id', unique=True) + project_url = models.URLField('Scratch project url', validators=[RegexValidator(regex=r'https?://scratch\.mit\.edu/projects/([0-9]+)/?')]) event = models.ForeignKey(Event, on_delete=models.CASCADE) def get_absolute_url(self): diff --git a/scratch_show/static/scratch_show/base.css b/scratch_show/static/scratch_show/base.css new file mode 100644 index 0000000..e589506 --- /dev/null +++ b/scratch_show/static/scratch_show/base.css @@ -0,0 +1,155 @@ +@font-face { + font-family: "Helvetica Neue"; + src: url("fonts/helveticaneue.woff2") format("woff2"); +} + +@font-face { + font-family: "Helvetica"; + src: url("fonts/helvetica.woff2") format("woff2"); +} + +h1, h2, h3, h4, h5, h6 { + font-family: "Helvetica Neue", sans-serif; +} + +h1 { + font-size: 2em; + margin-bottom: 1em; +} + +:root { + --text-color: #282828; + --bg-color: #f9f9f9; +} + +body { + font-family: "Helvetica", sans-serif; + font-size: 1.3em; + margin: 0; + padding: 0; + color: var(--text-color); + background-color: var(--bg-color); +} + +header.site-header { + background-color: #35479A; + text-align: center; + color: var(--bg-color); + padding: 0.4em 1em; + display: flex; + align-items: center; + height: 3.4em; +} + +header.site-header img { + width: 56px; + margin-right: 1em; +} + +.container { + margin-left: auto; + margin-right: auto; + width: 868px; +} + +h1.site-title { + margin: 0; + font-size: 1.4em; +} + +h1.article-title { + margin: 0; + font-size: 3em; +} + +.article-subtitle { + color: #575757; + font-weight: 500; +} + +.article-title-box { + height: 15em; + text-align: center; + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + background-color: #ededed; + margin-bottom: 4em; +} + +.article-container { + display: flex; + align-items: center; + align-content: flex-start; + justify-content: flex-start; +} + +a.code-stub-button { + text-decoration: none; + border-radius: 6px; + background-color: #35479a; + color: white; + padding: 0.5em 0.8em; + font-weight: 600; + display: inline-block; + text-align: center; + line-height: 28px; +} + +.home-title-box { + background-color: #222; + color: whitesmoke; + text-align: center; + padding: 2em 0; +} + +.site-header-title { + margin: 0; + font-size: 5em; +} + +.site-header-subtitle { + color: #ccc; +} + +.article-list { + list-style-type: none; + max-width: 690px; + margin-left: auto; + margin-right: auto; + padding: 0 1em; +} + +.article-item { + display: block; + background: lightgray; + margin: 1em 0; + padding: 1em; +} + +.article-item h2 { + font-size: 1.2em; + margin: 0; +} + +.article-item a { + text-decoration: none; + color: inherit; + display: block; + padding: 0; +} + +img { + max-width: 100%; +} + +.header-home-link { + display: flex; + text-decoration: none; + align-items: center; +} + +.header-home-link:visited { + color: inherit; +} diff --git a/scratch_show/static/scratch_show/favicon.png b/scratch_show/static/scratch_show/favicon.png new file mode 100644 index 0000000..67bffcf Binary files /dev/null and b/scratch_show/static/scratch_show/favicon.png differ diff --git a/scratch_show/static/scratch_show/fonts/helvetica.woff2 b/scratch_show/static/scratch_show/fonts/helvetica.woff2 new file mode 100644 index 0000000..494b31a Binary files /dev/null and b/scratch_show/static/scratch_show/fonts/helvetica.woff2 differ diff --git a/scratch_show/static/scratch_show/fonts/helveticaneue.woff2 b/scratch_show/static/scratch_show/fonts/helveticaneue.woff2 new file mode 100644 index 0000000..4aa8574 Binary files /dev/null and b/scratch_show/static/scratch_show/fonts/helveticaneue.woff2 differ diff --git a/scratch_show/templates/scratch_show/base.html b/scratch_show/templates/scratch_show/base.html new file mode 100644 index 0000000..2f5350e --- /dev/null +++ b/scratch_show/templates/scratch_show/base.html @@ -0,0 +1,27 @@ +{% load static %} + + + + + + + Ateliers Scratch by Prologin + + + + + + +
+
+ {% block content %} + {% endblock %} +
+
+ + diff --git a/scratch_show/templates/scratch_show/event_detail.html b/scratch_show/templates/scratch_show/event_detail.html new file mode 100644 index 0000000..8e689bf --- /dev/null +++ b/scratch_show/templates/scratch_show/event_detail.html @@ -0,0 +1,15 @@ +{% extends 'scratch_show/base.html' %} + +{% block content %} + +

{{ event.name }}, le {{ event.date|date }}

+ + + +{% endblock %} diff --git a/scratch_show/templates/scratch_show/index.html b/scratch_show/templates/scratch_show/index.html new file mode 100644 index 0000000..4f06db7 --- /dev/null +++ b/scratch_show/templates/scratch_show/index.html @@ -0,0 +1,21 @@ +{% extends 'scratch_show/base.html' %} + +{% block content %} + +{% if current_event %} +

Atelier en cours: {{ current_event.name }}

+ +Clique ici pour ajouter ton projet ! +{% endif %} + +

Ateliers passés

+ + + +{% endblock %} diff --git a/scratch_show/templates/scratch_show/scratchproject_detail.html b/scratch_show/templates/scratch_show/scratchproject_detail.html index 42e1b31..0b7a203 100644 --- a/scratch_show/templates/scratch_show/scratchproject_detail.html +++ b/scratch_show/templates/scratch_show/scratchproject_detail.html @@ -1,4 +1,10 @@ +{% extends 'scratch_show/base.html' %} + +{% block content %} +

{{ object.name }}

Créateur : {{ object.author_name }}

- + + +{% endblock %} diff --git a/scratch_show/templates/scratch_show/scratchproject_form.html b/scratch_show/templates/scratch_show/scratchproject_form.html index 256405a..65e01d0 100644 --- a/scratch_show/templates/scratch_show/scratchproject_form.html +++ b/scratch_show/templates/scratch_show/scratchproject_form.html @@ -1,4 +1,11 @@ +{% extends 'scratch_show/base.html' %} + +{% block content %} + +
{% csrf_token %} {{ form.as_p }}
+ +{% endblock %} diff --git a/scratch_show/urls.py b/scratch_show/urls.py index f6304ab..c5bf494 100644 --- a/scratch_show/urls.py +++ b/scratch_show/urls.py @@ -4,6 +4,8 @@ from . import views app_name = 'scratch_show' urlpatterns = [ + path('', views.IndexView.as_view(), name='index'), path('add', views.ScratchProjectAddView.as_view(), name='project-add'), - path('project/', views.ScratchProjectDetailView.as_view(), name='project-detail'), + path('project//', views.ScratchProjectDetailView.as_view(), name='project-detail'), + path('event//', views.EventDetailView.as_view(), name='event-detail'), ] diff --git a/scratch_show/views.py b/scratch_show/views.py index db76a11..c5c09c3 100644 --- a/scratch_show/views.py +++ b/scratch_show/views.py @@ -1,34 +1,44 @@ -import re - from django.shortcuts import get_object_or_404 from django.utils import timezone -from django.views.generic.edit import CreateView +from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView +from django.views.generic.edit import CreateView +from django.core.exceptions import ValidationError from . import forms, models -SCRATCH_ID_REGEX = re.compile(r'https://scratch\.mit\.edu/projects/([0-9]+)') +class IndexView(TemplateView): + template_name = "scratch_show/index.html" -def get_scratch_id_from_url(url): - match = SCRATCH_ID_REGEX.search(url) - return int(match.group(1)) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + today = timezone.now().date() + context['current_event'] = models.Event.objects.filter(date=today).first() + context['past_events'] = models.Event.objects.exclude(date=today).order_by('-date') + return context class ScratchProjectAddView(CreateView): - form_class = forms.ScratchProjectAddForm - template_name = 'scratch_show/scratchproject_form.html' + model = models.ScratchProject + fields = ['name', 'author_name', 'project_url'] def dispatch(self, request, *args, **kwargs): self.event = get_object_or_404(models.Event, date=timezone.now().date(), accept_projects=True) return super().dispatch(request, *args, **kwargs) def form_valid(self, form): - url = form.cleaned_data['url'] - form.instance.project_id = get_scratch_id_from_url(url) form.instance.event = self.event return super().form_valid(form) class ScratchProjectDetailView(DetailView): model = models.ScratchProject + +class EventDetailView(DetailView): + model = models.Event + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['projects'] = models.ScratchProject.objects.filter(event=context['object'].pk) + return context