From 0530c3c0dc1ce739122495048cd34833e7773ca4 Mon Sep 17 00:00:00 2001 From: Yanic Olivier Date: Mon, 22 Jul 2019 09:57:32 -0400 Subject: [PATCH] Add pages app to manage information page --- requirements.txt | 3 ++ .../apiVolontaria/apiVolontaria/settings.py | 9 +++- source/apiVolontaria/apiVolontaria/urls.py | 5 ++ source/apiVolontaria/pages/__init__.py | 0 source/apiVolontaria/pages/admin.py | 16 ++++++ .../pages/migrations/0001_initial.py | 29 +++++++++++ .../migrations/0002_auto_20190509_1544.py | 22 ++++++++ .../pages/migrations/__init__.py | 0 source/apiVolontaria/pages/models.py | 19 +++++++ source/apiVolontaria/pages/serializers.py | 21 ++++++++ source/apiVolontaria/pages/tests/__init__.py | 0 .../pages/tests/tests_model_InfoSection.py | 22 ++++++++ .../pages/tests/tests_view_InfoPageView.py | 52 +++++++++++++++++++ source/apiVolontaria/pages/urls.py | 17 ++++++ source/apiVolontaria/pages/views.py | 10 ++++ 15 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 source/apiVolontaria/pages/__init__.py create mode 100644 source/apiVolontaria/pages/admin.py create mode 100644 source/apiVolontaria/pages/migrations/0001_initial.py create mode 100644 source/apiVolontaria/pages/migrations/0002_auto_20190509_1544.py create mode 100644 source/apiVolontaria/pages/migrations/__init__.py create mode 100644 source/apiVolontaria/pages/models.py create mode 100644 source/apiVolontaria/pages/serializers.py create mode 100644 source/apiVolontaria/pages/tests/__init__.py create mode 100644 source/apiVolontaria/pages/tests/tests_model_InfoSection.py create mode 100644 source/apiVolontaria/pages/tests/tests_view_InfoPageView.py create mode 100644 source/apiVolontaria/pages/urls.py create mode 100644 source/apiVolontaria/pages/views.py diff --git a/requirements.txt b/requirements.txt index 7826c8e3..bf3e7852 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,6 @@ factory-boy==2.10.0 django-import-export==1.2.0 django-anymail==6.1 coreapi==2.3.3 +django-orderable==6.0.1 +django-ckeditor==5.7.1 +django-reversion==3.0.3 diff --git a/source/apiVolontaria/apiVolontaria/settings.py b/source/apiVolontaria/apiVolontaria/settings.py index ec9249a2..c9d4d286 100644 --- a/source/apiVolontaria/apiVolontaria/settings.py +++ b/source/apiVolontaria/apiVolontaria/settings.py @@ -42,11 +42,16 @@ 'rest_framework_docs', 'rest_framework.authtoken', 'corsheaders', + 'import_export', + 'anymail', + 'orderable', + 'ckeditor', + 'reversion', + 'apiVolontaria', 'volunteer', 'location', - 'import_export', - 'anymail' + 'pages', ] MIDDLEWARE = [ diff --git a/source/apiVolontaria/apiVolontaria/urls.py b/source/apiVolontaria/apiVolontaria/urls.py index 477b46ba..44905e75 100644 --- a/source/apiVolontaria/apiVolontaria/urls.py +++ b/source/apiVolontaria/apiVolontaria/urls.py @@ -77,6 +77,11 @@ r'^location/', include('location.urls', namespace="location"), ), + # Pages + url( + r'^pages/', + include('pages.urls', namespace="pages"), + ), # DOCUMENTATION SWAGGER path( 'docs/', diff --git a/source/apiVolontaria/pages/__init__.py b/source/apiVolontaria/pages/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/apiVolontaria/pages/admin.py b/source/apiVolontaria/pages/admin.py new file mode 100644 index 00000000..e6338f1a --- /dev/null +++ b/source/apiVolontaria/pages/admin.py @@ -0,0 +1,16 @@ +from django.contrib import admin +from orderable.admin import OrderableAdmin +from reversion.admin import VersionAdmin + +from .models import InfoSection + + +@admin.register(InfoSection) +class InfoSectionAdmin(OrderableAdmin, VersionAdmin): + list_display = ('sort_order_display', 'is_active', 'is_accordion', 'title') + list_display_links = ('title',) + list_editable = ('is_active', 'is_accordion') + + fields = ('is_active', 'is_accordion', 'title', 'content', ) + + search_fields = ('content', 'title', ) diff --git a/source/apiVolontaria/pages/migrations/0001_initial.py b/source/apiVolontaria/pages/migrations/0001_initial.py new file mode 100644 index 00000000..70b81a9f --- /dev/null +++ b/source/apiVolontaria/pages/migrations/0001_initial.py @@ -0,0 +1,29 @@ +# Generated by Django 2.1.5 on 2019-05-03 13:45 + +import ckeditor.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='InfoSection', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('sort_order', models.IntegerField(blank=True, db_index=True)), + ('is_active', models.BooleanField(default=True, verbose_name='Actif')), + ('title', models.CharField(max_length=255, verbose_name='Titre')), + ('content', ckeditor.fields.RichTextField(verbose_name='Contenu')), + ], + options={ + 'ordering': ['sort_order'], + 'abstract': False, + }, + ), + ] diff --git a/source/apiVolontaria/pages/migrations/0002_auto_20190509_1544.py b/source/apiVolontaria/pages/migrations/0002_auto_20190509_1544.py new file mode 100644 index 00000000..54c65374 --- /dev/null +++ b/source/apiVolontaria/pages/migrations/0002_auto_20190509_1544.py @@ -0,0 +1,22 @@ +# Generated by Django 2.1.5 on 2019-05-09 19:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pages', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='infosection', + options={'ordering': ['sort_order'], 'verbose_name': 'Section page informations', 'verbose_name_plural': 'Sections page informations'}, + ), + migrations.AddField( + model_name='infosection', + name='is_accordion', + field=models.BooleanField(default=True, verbose_name='Accordeon'), + ), + ] diff --git a/source/apiVolontaria/pages/migrations/__init__.py b/source/apiVolontaria/pages/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/apiVolontaria/pages/models.py b/source/apiVolontaria/pages/models.py new file mode 100644 index 00000000..ea5bc557 --- /dev/null +++ b/source/apiVolontaria/pages/models.py @@ -0,0 +1,19 @@ +from django.db import models +from orderable.models import Orderable +from ckeditor.fields import RichTextField +from django.utils.translation import gettext_lazy as _ + + +class InfoSection(Orderable): + + is_active = models.BooleanField(_('Active'), default=True) + title = models.CharField(_('title'), max_length=255) + content = RichTextField(_('Content')) + is_accordion = models.BooleanField(_('Accordion'), default=True) + + class Meta(Orderable.Meta): + verbose_name = _('Information Page section') + verbose_name_plural = _('Information Page sections') + + def __str__(self): + return '{0} (ID-{1})'.format(self.title, self.pk) diff --git a/source/apiVolontaria/pages/serializers.py b/source/apiVolontaria/pages/serializers.py new file mode 100644 index 00000000..4a30d666 --- /dev/null +++ b/source/apiVolontaria/pages/serializers.py @@ -0,0 +1,21 @@ +from rest_framework import serializers + +from .models import InfoSection + + +class InfoPageSerializer(serializers.ModelSerializer): + + class Meta: + model = InfoSection + fields = ( + 'id', + 'is_accordion', + 'title', + 'content', + ) + read_only_fields = ( + 'id', + 'is_accordion', + 'title', + 'content', + ) diff --git a/source/apiVolontaria/pages/tests/__init__.py b/source/apiVolontaria/pages/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/source/apiVolontaria/pages/tests/tests_model_InfoSection.py b/source/apiVolontaria/pages/tests/tests_model_InfoSection.py new file mode 100644 index 00000000..3008fc40 --- /dev/null +++ b/source/apiVolontaria/pages/tests/tests_model_InfoSection.py @@ -0,0 +1,22 @@ +from rest_framework.test import APITransactionTestCase + +from ..models import InfoSection + + +class InfoSectionTests(APITransactionTestCase): + + def setUp(self): + pass + + def test_create_info_section(self): + """ + Ensure we can create a new InfoSection + """ + info_section = InfoSection.objects.create( + is_active=True, + title='My title', + content='My Content', + ) + + self.assertEqual(info_section.title, 'My title') + self.assertEqual(info_section.content, 'My Content') diff --git a/source/apiVolontaria/pages/tests/tests_view_InfoPageView.py b/source/apiVolontaria/pages/tests/tests_view_InfoPageView.py new file mode 100644 index 00000000..e666637e --- /dev/null +++ b/source/apiVolontaria/pages/tests/tests_view_InfoPageView.py @@ -0,0 +1,52 @@ +import json + +from rest_framework import status +from rest_framework.test import APIClient, APITestCase + +from django.urls import reverse + +from apiVolontaria.factories import UserFactory, AdminFactory +from ..models import InfoSection + + +class InfoPageViewTests(APITestCase): + + def setUp(self): + self.client = APIClient() + + self.user = UserFactory() + self.user.set_password('Test123!') + self.user.save() + + self.admin = AdminFactory() + self.admin.set_password('Test123!') + self.admin.save() + + self.info_section = InfoSection.objects.create( + title='my title', + content='my content', + ) + + def test_list_info_sections(self): + """ + Ensure we can list info sections. + """ + + data = [ + { + 'id': self.info_section.pk, + 'is_accordion': True, + 'title': self.info_section.title, + 'content': self.info_section.content + } + ] + + self.client.force_authenticate(user=self.user) + + response = self.client.get('/pages/info') + + response_parsed = json.loads(response.content) + + self.assertEqual(response_parsed['results'], data) + self.assertEqual(response_parsed['count'], 1) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/source/apiVolontaria/pages/urls.py b/source/apiVolontaria/pages/urls.py new file mode 100644 index 00000000..67705565 --- /dev/null +++ b/source/apiVolontaria/pages/urls.py @@ -0,0 +1,17 @@ +from django.conf.urls import include, url +from rest_framework.urlpatterns import format_suffix_patterns + +from . import views + +app_name = 'pages' + +urlpatterns = format_suffix_patterns( + [ + # Information page + url( + r'^info$', + views.InfoPageView.as_view(), + name='info', + ), + ] +) diff --git a/source/apiVolontaria/pages/views.py b/source/apiVolontaria/pages/views.py new file mode 100644 index 00000000..f69ee42f --- /dev/null +++ b/source/apiVolontaria/pages/views.py @@ -0,0 +1,10 @@ +from rest_framework import generics + +from .models import InfoSection +from .serializers import InfoPageSerializer + + +class InfoPageView(generics.ListAPIView): + permission_classes = () + serializer_class = InfoPageSerializer + queryset = InfoSection.objects.filter(is_active=True)