From 5a042bb11578e70b11f8c86f078a0238119b777a Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 20 May 2020 11:55:06 +0200 Subject: [PATCH 01/15] Add models and graphql --- server/api/schema_public.py | 14 ++++------- .../migrations/0006_auto_20200520_0954.py | 21 ++++++++++++++++ .../migrations/0021_auto_20200520_0954.py | 24 +++++++++++++++++++ server/core/settings.py | 1 + server/newsteaser/__init__.py | 0 server/newsteaser/apps.py | 5 ++++ server/newsteaser/models.py | 11 +++++++++ server/newsteaser/schema.py | 20 ++++++++++++++++ server/users/mutations_public.py | 10 -------- 9 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 server/basicknowledge/migrations/0006_auto_20200520_0954.py create mode 100644 server/books/migrations/0021_auto_20200520_0954.py create mode 100644 server/newsteaser/__init__.py create mode 100644 server/newsteaser/apps.py create mode 100644 server/newsteaser/models.py create mode 100644 server/newsteaser/schema.py diff --git a/server/api/schema_public.py b/server/api/schema_public.py index 1f643dae..1ee5e028 100644 --- a/server/api/schema_public.py +++ b/server/api/schema_public.py @@ -2,6 +2,7 @@ import graphene from django.conf import settings from graphene_django.debug import DjangoDebug +from newsteaser.schema import AllNewsTeasersQuery from users.mutations_public import UserMutations from registration.mutations_public import RegistrationMutations @@ -12,16 +13,11 @@ class Mutation(UserMutations, RegistrationMutations, graphene.ObjectType): debug = graphene.Field(DjangoDebug, name='__debug') -# graphene neets some kind of schema in order to create a schema -class DummyQuery(object): - meaning_of_life = graphene.Int() +class Query(AllNewsTeasersQuery, graphene.ObjectType): + node = graphene.relay.Node.Field() - def resolve_meaning_of_life(self, info, **kwargs): - return 42 - - -class Query(DummyQuery, graphene.ObjectType): - pass + if settings.DEBUG: + debug = graphene.Field(DjangoDebug, name='_debug') schema = graphene.Schema(mutation=Mutation, query=Query) diff --git a/server/basicknowledge/migrations/0006_auto_20200520_0954.py b/server/basicknowledge/migrations/0006_auto_20200520_0954.py new file mode 100644 index 00000000..2e19d313 --- /dev/null +++ b/server/basicknowledge/migrations/0006_auto_20200520_0954.py @@ -0,0 +1,21 @@ +# Generated by Django 2.1.15 on 2020-05-20 09:54 + +from django.db import migrations +import wagtail.core.blocks +import wagtail.core.fields +import wagtail.images.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('basicknowledge', '0005_auto_20200408_0834'), + ] + + operations = [ + migrations.AlterField( + model_name='basicknowledge', + name='contents', + field=wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock(features=['bold', 'ul', 'brand', 'secondary']))])), ('image_block', wagtail.images.blocks.ImageChooserBlock()), ('link_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('section_title', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock())])), ('infogram_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock()), ('title', wagtail.core.blocks.TextBlock())])), ('genially_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('thinglink_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('subtitle', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock())]))], blank=True, null=True), + ), + ] diff --git a/server/books/migrations/0021_auto_20200520_0954.py b/server/books/migrations/0021_auto_20200520_0954.py new file mode 100644 index 00000000..157e632a --- /dev/null +++ b/server/books/migrations/0021_auto_20200520_0954.py @@ -0,0 +1,24 @@ +# Generated by Django 2.1.15 on 2020-05-20 09:54 + +import assignments.models +from django.db import migrations +import surveys.models +import wagtail.core.blocks +import wagtail.core.fields +import wagtail.images.blocks +import wagtail.snippets.blocks + + +class Migration(migrations.Migration): + + dependencies = [ + ('books', '0020_topic_instructions'), + ] + + operations = [ + migrations.AlterField( + model_name='contentblock', + name='contents', + field=wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock(features=['ul']))])), ('basic_knowledge', wagtail.core.blocks.StructBlock([('description', wagtail.core.blocks.RichTextBlock(required=False)), ('basic_knowledge', wagtail.core.blocks.PageChooserBlock(required=True, target_model=['basicknowledge.BasicKnowledge']))])), ('assignment', wagtail.core.blocks.StructBlock([('assignment_id', wagtail.snippets.blocks.SnippetChooserBlock(assignments.models.Assignment))])), ('survey', wagtail.core.blocks.StructBlock([('survey_id', wagtail.snippets.blocks.SnippetChooserBlock(surveys.models.Survey))])), ('image_block', wagtail.images.blocks.ImageChooserBlock()), ('image_url_block', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('link_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('solution', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock(features=['ul']))], icon='tick')), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('infogram_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock()), ('title', wagtail.core.blocks.TextBlock())])), ('genially_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('thinglink_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('subtitle', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock())])), ('instruction', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock()), ('text', wagtail.core.blocks.TextBlock(required=False))])), ('module_room_slug', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.TextBlock())])), ('content_list_item', wagtail.core.blocks.StreamBlock([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock(features=['ul']))])), ('basic_knowledge', wagtail.core.blocks.StructBlock([('description', wagtail.core.blocks.RichTextBlock(required=False)), ('basic_knowledge', wagtail.core.blocks.PageChooserBlock(required=True, target_model=['basicknowledge.BasicKnowledge']))])), ('assignment', wagtail.core.blocks.StructBlock([('assignment_id', wagtail.snippets.blocks.SnippetChooserBlock(assignments.models.Assignment))])), ('survey', wagtail.core.blocks.StructBlock([('survey_id', wagtail.snippets.blocks.SnippetChooserBlock(surveys.models.Survey))])), ('image_block', wagtail.images.blocks.ImageChooserBlock()), ('image_url_block', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('link_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('solution', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock(features=['ul']))], icon='tick')), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('infogram_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock()), ('title', wagtail.core.blocks.TextBlock())])), ('genially_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('thinglink_block', wagtail.core.blocks.StructBlock([('id', wagtail.core.blocks.TextBlock())])), ('subtitle', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.TextBlock())])), ('instruction', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock()), ('text', wagtail.core.blocks.TextBlock(required=False))])), ('module_room_slug', wagtail.core.blocks.StructBlock([('title', wagtail.core.blocks.TextBlock())]))]))], blank=True, null=True), + ), + ] diff --git a/server/core/settings.py b/server/core/settings.py index d96c84d3..741d7749 100644 --- a/server/core/settings.py +++ b/server/core/settings.py @@ -57,6 +57,7 @@ INSTALLED_APPS = [ 'surveys', 'notes', 'registration', + 'newsteaser', 'wagtail.contrib.forms', 'wagtail.contrib.redirects', diff --git a/server/newsteaser/__init__.py b/server/newsteaser/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/newsteaser/apps.py b/server/newsteaser/apps.py new file mode 100644 index 00000000..874c4b14 --- /dev/null +++ b/server/newsteaser/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class UserConfig(AppConfig): + name = 'newsteaser' diff --git a/server/newsteaser/models.py b/server/newsteaser/models.py new file mode 100644 index 00000000..283996ba --- /dev/null +++ b/server/newsteaser/models.py @@ -0,0 +1,11 @@ +from django.utils.translation import ugettext_lazy as _ +from django.db import models + + +class NewsTeaser(models.Model): + image_url = models.URLField(_('Image URL'), blank=False, null=True) + title = models.CharField(_('Title'), max_length=300, blank=False, null=False) + description = models.TextField(_('Description'), blank=False, null=True) + date = models.DateField(blank=False, null=True) + order_id = models.IntegerField(blank=False, null=False, default=-1) + news_article_url = models.URLField(_('News Article URL'), blank=False, null=True) diff --git a/server/newsteaser/schema.py b/server/newsteaser/schema.py new file mode 100644 index 00000000..2cd39079 --- /dev/null +++ b/server/newsteaser/schema.py @@ -0,0 +1,20 @@ +from graphene import relay +from graphene_django import DjangoObjectType +from graphene_django.filter import DjangoFilterConnectionField + +from newsteaser.models import NewsTeaser + + +class NewsTeaserNode(DjangoObjectType): + + class Meta: + model = NewsTeaser + filter_fields = [] + interfaces = (relay.Node,) + + +class AllNewsTeasersQuery(object): + articles = DjangoFilterConnectionField(NewsTeaserNode) + + def resolve_articles(self, info, **kwargs): + return AllNewsTeasersQuery.objects.all() diff --git a/server/users/mutations_public.py b/server/users/mutations_public.py index 4ed9a3ae..0e262b7d 100644 --- a/server/users/mutations_public.py +++ b/server/users/mutations_public.py @@ -1,13 +1,3 @@ -# -*- coding: utf-8 -*- -# -# ITerativ GmbH -# http://www.iterativ.ch/ -# -# Copyright (c) 2019 ITerativ GmbH. All rights reserved. -# -# Created on 2019-10-01 -# @author: chrigu - import graphene from django.conf import settings from django.contrib.auth import authenticate, login From c904a0101ace4671995c5aa21242c10f038fa1a9 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 20 May 2020 13:14:19 +0200 Subject: [PATCH 02/15] Add migrations, add admin, fix query --- server/newsteaser/admin.py | 9 +++++++ server/newsteaser/migrations/0001_initial.py | 26 ++++++++++++++++++++ server/newsteaser/migrations/__init__.py | 0 server/newsteaser/models.py | 3 +++ server/newsteaser/schema.py | 2 +- 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 server/newsteaser/admin.py create mode 100644 server/newsteaser/migrations/0001_initial.py create mode 100644 server/newsteaser/migrations/__init__.py diff --git a/server/newsteaser/admin.py b/server/newsteaser/admin.py new file mode 100644 index 00000000..838b177c --- /dev/null +++ b/server/newsteaser/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin +from newsteaser.models import NewsTeaser + + +@admin.register(NewsTeaser) +class NewsTeaserAdmin(admin.ModelAdmin): + list_display = ('title', 'date', 'order_id') + list_filter = ('title',) + diff --git a/server/newsteaser/migrations/0001_initial.py b/server/newsteaser/migrations/0001_initial.py new file mode 100644 index 00000000..ed0e4131 --- /dev/null +++ b/server/newsteaser/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 2.1.15 on 2020-05-20 10:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='NewsTeaser', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image_url', models.URLField(null=True, verbose_name='Image URL')), + ('title', models.CharField(max_length=300, verbose_name='Title')), + ('description', models.TextField(null=True, verbose_name='Description')), + ('date', models.DateField(null=True)), + ('order_id', models.IntegerField(default=-1)), + ('news_article_url', models.URLField(null=True, verbose_name='News Article URL')), + ], + ), + ] diff --git a/server/newsteaser/migrations/__init__.py b/server/newsteaser/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/newsteaser/models.py b/server/newsteaser/models.py index 283996ba..4878934c 100644 --- a/server/newsteaser/models.py +++ b/server/newsteaser/models.py @@ -9,3 +9,6 @@ class NewsTeaser(models.Model): date = models.DateField(blank=False, null=True) order_id = models.IntegerField(blank=False, null=False, default=-1) news_article_url = models.URLField(_('News Article URL'), blank=False, null=True) + + def __str__(self): + return '{}'.format(self.title) diff --git a/server/newsteaser/schema.py b/server/newsteaser/schema.py index 2cd39079..e0f57041 100644 --- a/server/newsteaser/schema.py +++ b/server/newsteaser/schema.py @@ -17,4 +17,4 @@ class AllNewsTeasersQuery(object): articles = DjangoFilterConnectionField(NewsTeaserNode) def resolve_articles(self, info, **kwargs): - return AllNewsTeasersQuery.objects.all() + return NewsTeaser.objects.all() From 6933e10a7f201a5ec3b6c703ffa207cea83be723 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 20 May 2020 15:42:50 +0200 Subject: [PATCH 03/15] Add news page, add field --- client/src/graphql/gql/newsTeasersQuery.gql | 14 +++++ client/src/pages/news.vue | 58 +++++++++++++++++++ client/src/router/index.js | 6 ++ server/api/schema_public.py | 2 +- server/newsteaser/migrations/0001_initial.py | 3 +- server/newsteaser/models.py | 1 + .../{schema.py => schema_public.py} | 4 +- 7 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 client/src/graphql/gql/newsTeasersQuery.gql create mode 100644 client/src/pages/news.vue rename server/newsteaser/{schema.py => schema_public.py} (77%) diff --git a/client/src/graphql/gql/newsTeasersQuery.gql b/client/src/graphql/gql/newsTeasersQuery.gql new file mode 100644 index 00000000..e5d993ff --- /dev/null +++ b/client/src/graphql/gql/newsTeasersQuery.gql @@ -0,0 +1,14 @@ +query NewsTeasers { + newsTeasers { + edges { + node { + id + description + title + imageUrl + newsArticleUrl + date + } + } + } +} diff --git a/client/src/pages/news.vue b/client/src/pages/news.vue new file mode 100644 index 00000000..96b2296e --- /dev/null +++ b/client/src/pages/news.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/client/src/router/index.js b/client/src/router/index.js index 44214e50..b2fc18f5 100644 --- a/client/src/router/index.js +++ b/client/src/router/index.js @@ -39,6 +39,7 @@ import joinClass from '@/pages/joinClass' import oldClasses from '@/pages/oldClasses'; import createClass from '@/pages/createClass'; import showCode from '@/pages/showCode'; +import news from '@/pages/news'; import store from '@/store/index'; @@ -199,6 +200,11 @@ const routes = [ public: true } }, + { + path: '/news', + component: news, + name: 'news' + }, {path: '/styleguide', component: styleGuidePage}, {path: '*', component: p404} ]; diff --git a/server/api/schema_public.py b/server/api/schema_public.py index 1ee5e028..5e070259 100644 --- a/server/api/schema_public.py +++ b/server/api/schema_public.py @@ -2,7 +2,7 @@ import graphene from django.conf import settings from graphene_django.debug import DjangoDebug -from newsteaser.schema import AllNewsTeasersQuery +from newsteaser.schema_public import AllNewsTeasersQuery from users.mutations_public import UserMutations from registration.mutations_public import RegistrationMutations diff --git a/server/newsteaser/migrations/0001_initial.py b/server/newsteaser/migrations/0001_initial.py index ed0e4131..f24f0031 100644 --- a/server/newsteaser/migrations/0001_initial.py +++ b/server/newsteaser/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 2.1.15 on 2020-05-20 10:57 +# Generated by Django 2.1.15 on 2020-05-20 13:39 from django.db import migrations, models @@ -21,6 +21,7 @@ class Migration(migrations.Migration): ('date', models.DateField(null=True)), ('order_id', models.IntegerField(default=-1)), ('news_article_url', models.URLField(null=True, verbose_name='News Article URL')), + ('image_source', models.CharField(max_length=100, verbose_name='Image Source')), ], ), ] diff --git a/server/newsteaser/models.py b/server/newsteaser/models.py index 4878934c..13511e6b 100644 --- a/server/newsteaser/models.py +++ b/server/newsteaser/models.py @@ -9,6 +9,7 @@ class NewsTeaser(models.Model): date = models.DateField(blank=False, null=True) order_id = models.IntegerField(blank=False, null=False, default=-1) news_article_url = models.URLField(_('News Article URL'), blank=False, null=True) + image_source = models.CharField(_('Image Source'), max_length=100, blank=False, null=False) def __str__(self): return '{}'.format(self.title) diff --git a/server/newsteaser/schema.py b/server/newsteaser/schema_public.py similarity index 77% rename from server/newsteaser/schema.py rename to server/newsteaser/schema_public.py index e0f57041..6af526f4 100644 --- a/server/newsteaser/schema.py +++ b/server/newsteaser/schema_public.py @@ -14,7 +14,7 @@ class NewsTeaserNode(DjangoObjectType): class AllNewsTeasersQuery(object): - articles = DjangoFilterConnectionField(NewsTeaserNode) + news_teasers = DjangoFilterConnectionField(NewsTeaserNode) - def resolve_articles(self, info, **kwargs): + def resolve_news_teasers(self, info, **kwargs): return NewsTeaser.objects.all() From 03a8b354664821f82753d7dbbe7f0d7a8b02704b Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Mon, 25 May 2020 12:41:12 +0200 Subject: [PATCH 04/15] Add source, add tests --- client/src/graphql/gql/newsTeasersQuery.gql | 1 + server/newsteaser/factories.py | 21 ++++++++++ server/newsteaser/schema_public.py | 2 +- server/newsteaser/tests/__init__.py | 0 server/newsteaser/tests/test_newsteaser.py | 43 +++++++++++++++++++++ server/users/tests/test_usersettings.py | 9 ----- 6 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 server/newsteaser/factories.py create mode 100644 server/newsteaser/tests/__init__.py create mode 100644 server/newsteaser/tests/test_newsteaser.py diff --git a/client/src/graphql/gql/newsTeasersQuery.gql b/client/src/graphql/gql/newsTeasersQuery.gql index e5d993ff..50511061 100644 --- a/client/src/graphql/gql/newsTeasersQuery.gql +++ b/client/src/graphql/gql/newsTeasersQuery.gql @@ -8,6 +8,7 @@ query NewsTeasers { imageUrl newsArticleUrl date + imageSource } } } diff --git a/server/newsteaser/factories.py b/server/newsteaser/factories.py new file mode 100644 index 00000000..fb440afa --- /dev/null +++ b/server/newsteaser/factories.py @@ -0,0 +1,21 @@ +import datetime +import random + +import factory +from factory.fuzzy import FuzzyDateTime +from pytz import UTC + +from core.factories import fake, fake_title +from newsteaser.models import NewsTeaser + + +class NewsTeaserFactory(factory.django.DjangoModelFactory): + class Meta: + model = NewsTeaser + + title = factory.LazyAttribute(lambda x: fake_title(max_words=2)) + description = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(4, 8))) + image_url = factory.LazyAttribute(lambda x: 'https://picsum.photos/600/400/?random') + news_article_url = factory.LazyAttribute(lambda x: 'https://myskillbox-abu-news.webflow.io/brexit') + date = FuzzyDateTime(datetime.datetime(2020, 1, 1, tzinfo=UTC)) + image_source = factory.LazyAttribute(lambda x: 'https://picsum.photos/600/400/?random') diff --git a/server/newsteaser/schema_public.py b/server/newsteaser/schema_public.py index 6af526f4..0fa41ebd 100644 --- a/server/newsteaser/schema_public.py +++ b/server/newsteaser/schema_public.py @@ -17,4 +17,4 @@ class AllNewsTeasersQuery(object): news_teasers = DjangoFilterConnectionField(NewsTeaserNode) def resolve_news_teasers(self, info, **kwargs): - return NewsTeaser.objects.all() + return NewsTeaser.objects.all().order_by('order_id') diff --git a/server/newsteaser/tests/__init__.py b/server/newsteaser/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/newsteaser/tests/test_newsteaser.py b/server/newsteaser/tests/test_newsteaser.py new file mode 100644 index 00000000..d244f7bc --- /dev/null +++ b/server/newsteaser/tests/test_newsteaser.py @@ -0,0 +1,43 @@ +from unittest import TestCase +from graphene.test import Client + +from api.schema_public import schema +from newsteaser.factories import NewsTeaserFactory + + +class NewsTeaserTests(TestCase): + def setUp(self): + self.news_teaser1 = NewsTeaserFactory(order_id=1) + self.news_teaser2 = NewsTeaserFactory(order_id=2) + + self.client = Client(schema=schema) + + + def make_query(self): + query = ''' + query NewsTeasers { + newsTeasers { + edges { + node { + id + description + title + imageUrl + newsArticleUrl + date + imageSource + } + } + } + } + ''' + + return self.client.execute(query) + + def test_public_can_get_news_teaser(self): + result = self.make_query() + self.assertIsNone(result.get('errors')) + news_teasers = result.get('data').get('newsTeasers').get('edges') + self.assertEqual(news_teasers[0].get('node').get('title'), self.news_teaser1.title) + self.assertEqual(news_teasers[1].get('node').get('title'), self.news_teaser2.title) + diff --git a/server/users/tests/test_usersettings.py b/server/users/tests/test_usersettings.py index 147bd223..6b5be5c3 100644 --- a/server/users/tests/test_usersettings.py +++ b/server/users/tests/test_usersettings.py @@ -1,12 +1,3 @@ -# -*- coding: utf-8 -*- -# -# ITerativ GmbH -# http://www.iterativ.ch/ -# -# Copyright (c) 2019 ITerativ GmbH. All rights reserved. -# -# Created on 2019-07-24 -# @author: chrigu from django.contrib.sessions.middleware import SessionMiddleware from django.test import TestCase, RequestFactory from graphene.test import Client From 7d153be053294f029b67bef555943c0737699336 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Mon, 25 May 2020 13:17:12 +0200 Subject: [PATCH 05/15] Add newsteaser dummy data --- server/core/management/commands/dummy_data.py | 1 + server/core/management/commands/dummy_rooms.py | 3 --- server/newsteaser/management/__init__.py | 0 server/newsteaser/management/commands/__init__.py | 0 .../newsteaser/management/commands/dummy_news.py | 14 ++++++++++++++ 5 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 server/newsteaser/management/__init__.py create mode 100644 server/newsteaser/management/commands/__init__.py create mode 100644 server/newsteaser/management/commands/dummy_news.py diff --git a/server/core/management/commands/dummy_data.py b/server/core/management/commands/dummy_data.py index fee625f8..60513856 100644 --- a/server/core/management/commands/dummy_data.py +++ b/server/core/management/commands/dummy_data.py @@ -112,4 +112,5 @@ class Command(BaseCommand): # now create all and rooms management.call_command('dummy_rooms', verbosity=0) + management.call_command('dummy_news', verbosity=0) diff --git a/server/core/management/commands/dummy_rooms.py b/server/core/management/commands/dummy_rooms.py index da5bf02f..2c2a7175 100644 --- a/server/core/management/commands/dummy_rooms.py +++ b/server/core/management/commands/dummy_rooms.py @@ -3,13 +3,10 @@ import random import shutil from django.conf import settings -from django.contrib.auth import get_user_model from django.core.management import BaseCommand -from wagtail.core.models import Site from rooms.factories import RoomFactory, RoomEntryFactory from rooms.models import Room -from users.factories import SchoolClassFactory data = [ { diff --git a/server/newsteaser/management/__init__.py b/server/newsteaser/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/newsteaser/management/commands/__init__.py b/server/newsteaser/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/newsteaser/management/commands/dummy_news.py b/server/newsteaser/management/commands/dummy_news.py new file mode 100644 index 00000000..d614e26d --- /dev/null +++ b/server/newsteaser/management/commands/dummy_news.py @@ -0,0 +1,14 @@ +from django.core.management import BaseCommand + +from newsteaser.factories import NewsTeaserFactory +from newsteaser.models import NewsTeaser + + +class Command(BaseCommand): + + def handle(self, *args, **options): + NewsTeaser.objects.all().delete() + + for index in range(9): + NewsTeaserFactory() + From 8ce54013114edea1ac410408004a9e11ed267ae8 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Mon, 25 May 2020 15:36:55 +0200 Subject: [PATCH 06/15] Add basic grid --- client/src/components/NewsTeasers.vue | 82 ++++++++++++++++++++++ client/src/pages/news.vue | 47 +++---------- server/newsteaser/factories.py | 4 +- server/newsteaser/tests/test_newsteaser.py | 1 - 4 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 client/src/components/NewsTeasers.vue diff --git a/client/src/components/NewsTeasers.vue b/client/src/components/NewsTeasers.vue new file mode 100644 index 00000000..98b65e29 --- /dev/null +++ b/client/src/components/NewsTeasers.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/client/src/pages/news.vue b/client/src/pages/news.vue index 96b2296e..bc24398b 100644 --- a/client/src/pages/news.vue +++ b/client/src/pages/news.vue @@ -1,44 +1,16 @@ @@ -47,12 +19,11 @@ @import "@/styles/_functions.scss"; @import "@/styles/_mixins.scss"; - .teasers { - display: -ms-grid; - @supports (display: grid) { - display: grid; - } - grid-template-rows: 300px 300px; - -ms-grid-rows: auto 1fr 65px; + $news_width: 550px; + $image_height: 254px; + + .news { + padding: 0 $large-spacing; } + diff --git a/server/newsteaser/factories.py b/server/newsteaser/factories.py index fb440afa..1c5cc99f 100644 --- a/server/newsteaser/factories.py +++ b/server/newsteaser/factories.py @@ -15,7 +15,7 @@ class NewsTeaserFactory(factory.django.DjangoModelFactory): title = factory.LazyAttribute(lambda x: fake_title(max_words=2)) description = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(4, 8))) - image_url = factory.LazyAttribute(lambda x: 'https://picsum.photos/600/400/?random') + image_url = factory.LazyAttribute(lambda x: 'https://picsum.photos/550/257/?random') news_article_url = factory.LazyAttribute(lambda x: 'https://myskillbox-abu-news.webflow.io/brexit') date = FuzzyDateTime(datetime.datetime(2020, 1, 1, tzinfo=UTC)) - image_source = factory.LazyAttribute(lambda x: 'https://picsum.photos/600/400/?random') + image_source = factory.LazyAttribute(lambda x: 'https://picsum.photos/550/257/?random') diff --git a/server/newsteaser/tests/test_newsteaser.py b/server/newsteaser/tests/test_newsteaser.py index d244f7bc..c8c3f611 100644 --- a/server/newsteaser/tests/test_newsteaser.py +++ b/server/newsteaser/tests/test_newsteaser.py @@ -12,7 +12,6 @@ class NewsTeaserTests(TestCase): self.client = Client(schema=schema) - def make_query(self): query = ''' query NewsTeasers { From 12c5bf8d903becb6337c409eefe23b02fd341afe Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 27 May 2020 11:51:43 +0200 Subject: [PATCH 07/15] Format date, style source --- client/src/components/NewsTeasers.vue | 16 +++++++++++----- client/src/graphql/gql/newsTeasersQuery.gql | 2 +- client/src/pages/news.vue | 13 ++++++++----- server/newsteaser/schema_public.py | 8 +++++++- server/newsteaser/tests/test_newsteaser.py | 2 +- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/client/src/components/NewsTeasers.vue b/client/src/components/NewsTeasers.vue index 98b65e29..5f599024 100644 --- a/client/src/components/NewsTeasers.vue +++ b/client/src/components/NewsTeasers.vue @@ -2,10 +2,10 @@
-

{{teaser.imageSource}}

-

{{teaser.title}}

+

Quelle

+

{{teaser.title}}

{{teaser.description}}

-

{{teaser.date}}

+

{{teaser.displayDate}}

@@ -67,16 +67,22 @@ .teaser { + margin-bottom: $large-spacing; + &__image { display: block; max-width: 100%; - // max-height: 100%; - // width: auto; height: auto; @include desktop { max-width: $news_width; } } + + &__date { + font-family: $sans-serif-font-family; + font-weight: $font-weight-regular; + color: $color-silver-dark; + } } diff --git a/client/src/graphql/gql/newsTeasersQuery.gql b/client/src/graphql/gql/newsTeasersQuery.gql index 50511061..b6036c34 100644 --- a/client/src/graphql/gql/newsTeasersQuery.gql +++ b/client/src/graphql/gql/newsTeasersQuery.gql @@ -7,7 +7,7 @@ query NewsTeasers { title imageUrl newsArticleUrl - date + displayDate imageSource } } diff --git a/client/src/pages/news.vue b/client/src/pages/news.vue index bc24398b..47d0358d 100644 --- a/client/src/pages/news.vue +++ b/client/src/pages/news.vue @@ -1,6 +1,6 @@ @@ -16,14 +16,17 @@ diff --git a/server/newsteaser/schema_public.py b/server/newsteaser/schema_public.py index 0fa41ebd..f7810d3f 100644 --- a/server/newsteaser/schema_public.py +++ b/server/newsteaser/schema_public.py @@ -1,3 +1,4 @@ +import graphene from graphene import relay from graphene_django import DjangoObjectType from graphene_django.filter import DjangoFilterConnectionField @@ -6,15 +7,20 @@ from newsteaser.models import NewsTeaser class NewsTeaserNode(DjangoObjectType): + display_date = graphene.String() class Meta: model = NewsTeaser - filter_fields = [] + filter_fields = ['date',] interfaces = (relay.Node,) + def resolve_display_date(self, *args, **kwargs): + return self.date.strftime("%d. %B %Y") + class AllNewsTeasersQuery(object): news_teasers = DjangoFilterConnectionField(NewsTeaserNode) def resolve_news_teasers(self, info, **kwargs): return NewsTeaser.objects.all().order_by('order_id') + diff --git a/server/newsteaser/tests/test_newsteaser.py b/server/newsteaser/tests/test_newsteaser.py index c8c3f611..4cf3f98d 100644 --- a/server/newsteaser/tests/test_newsteaser.py +++ b/server/newsteaser/tests/test_newsteaser.py @@ -23,7 +23,7 @@ class NewsTeaserTests(TestCase): title imageUrl newsArticleUrl - date + displayDate imageSource } } From 1437f465de4f6cbc5bda25c83bc6f7e50c4e47c4 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 28 May 2020 08:41:15 +0200 Subject: [PATCH 08/15] Add tiny font, update date language --- client/src/components/NewsTeasers.vue | 10 +++++++++- client/src/styles/_typography.scss | 7 +++++++ server/core/settings.py | 1 - server/newsteaser/schema_public.py | 3 +++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/components/NewsTeasers.vue b/client/src/components/NewsTeasers.vue index 5f599024..4ed433c0 100644 --- a/client/src/components/NewsTeasers.vue +++ b/client/src/components/NewsTeasers.vue @@ -2,7 +2,7 @@
-

Quelle

+

Quelle {{teaser.imageSource}}

{{teaser.title}}

{{teaser.description}}

{{teaser.displayDate}}

@@ -79,6 +79,14 @@ } } + &__image-source { + line-height: 25px; + } + + &__description { + margin-bottom: $large-spacing; + } + &__date { font-family: $sans-serif-font-family; font-weight: $font-weight-regular; diff --git a/client/src/styles/_typography.scss b/client/src/styles/_typography.scss index e6a43a5a..9a960524 100644 --- a/client/src/styles/_typography.scss +++ b/client/src/styles/_typography.scss @@ -80,3 +80,10 @@ input, textarea, select, button { font-family: $sans-serif-font-family; color: $color-brand-dark; } + +.tiny { + font-size: 0.6875rem; //11px + font-family: $sans-serif-font-family; + font-weight: $font-weight-regular; + color: $color-silver-dark; +} diff --git a/server/core/settings.py b/server/core/settings.py index 741d7749..66757e9a 100644 --- a/server/core/settings.py +++ b/server/core/settings.py @@ -399,4 +399,3 @@ TASKBASE_BASEURL = os.environ.get("TASKBASE_BASEURL") TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner' TEST_OUTPUT_DIR = './test-reports/' TEST_OUTPUT_VERBOSE = 1 - diff --git a/server/newsteaser/schema_public.py b/server/newsteaser/schema_public.py index f7810d3f..d5c56bc6 100644 --- a/server/newsteaser/schema_public.py +++ b/server/newsteaser/schema_public.py @@ -1,3 +1,5 @@ +import locale + import graphene from graphene import relay from graphene_django import DjangoObjectType @@ -15,6 +17,7 @@ class NewsTeaserNode(DjangoObjectType): interfaces = (relay.Node,) def resolve_display_date(self, *args, **kwargs): + locale.setlocale(locale.LC_TIME, "de_DE") return self.date.strftime("%d. %B %Y") From abfed20a96e944880652f1636f9b6995893122ce Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 28 May 2020 09:27:26 +0200 Subject: [PATCH 09/15] Handle locale fail --- server/newsteaser/schema_public.py | 36 ++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/server/newsteaser/schema_public.py b/server/newsteaser/schema_public.py index d5c56bc6..690631d9 100644 --- a/server/newsteaser/schema_public.py +++ b/server/newsteaser/schema_public.py @@ -16,9 +16,41 @@ class NewsTeaserNode(DjangoObjectType): filter_fields = ['date',] interfaces = (relay.Node,) + def _month_to_german_string(self, date): + if date == 1: + month = 'Januar' + elif date == 2: + month = 'Februar' + elif date == 3: + month = 'März' + elif date == 4: + month = 'April' + elif date == 5: + month = 'Mai' + elif date == 6: + month = 'Juni' + elif date == 7: + month = 'Juli' + elif date == 8: + month = 'August' + elif date == 9: + month = 'September' + elif date == 10: + month = 'Oktober' + elif date == 11: + month = 'November' + elif date == 12: + month = 'Dezember' + return month + def resolve_display_date(self, *args, **kwargs): - locale.setlocale(locale.LC_TIME, "de_DE") - return self.date.strftime("%d. %B %Y") + # play it safe, locale might not be installed in platform + try: + locale.setlocale(locale.LC_TIME, "de_DE") + return self.date.strftime("%-d. %B %Y") + except: + month = self._month_to_german_string(self.date) + return f'{self.date.day}. {month}. {self.date.year}' class AllNewsTeasersQuery(object): From ca6adf75e18b76afec53461bdd9e16ef8cf9f09f Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 28 May 2020 09:58:19 +0200 Subject: [PATCH 10/15] Move month to string to file --- server/newsteaser/date_helper.py | 26 ++++++++++++++++++++++++++ server/newsteaser/schema_public.py | 30 ++---------------------------- 2 files changed, 28 insertions(+), 28 deletions(-) create mode 100644 server/newsteaser/date_helper.py diff --git a/server/newsteaser/date_helper.py b/server/newsteaser/date_helper.py new file mode 100644 index 00000000..62f199a8 --- /dev/null +++ b/server/newsteaser/date_helper.py @@ -0,0 +1,26 @@ +def month_to_german_string(month): + if month == 1: + month = 'Januar' + elif month == 2: + month = 'Februar' + elif month == 3: + month = 'März' + elif month == 4: + month = 'April' + elif month == 5: + month = 'Mai' + elif month == 6: + month = 'Juni' + elif month == 7: + month = 'Juli' + elif month == 8: + month = 'August' + elif month == 9: + month = 'September' + elif month == 10: + month = 'Oktober' + elif month == 11: + month = 'November' + elif month == 12: + month = 'Dezember' + return month diff --git a/server/newsteaser/schema_public.py b/server/newsteaser/schema_public.py index 690631d9..afbac9ae 100644 --- a/server/newsteaser/schema_public.py +++ b/server/newsteaser/schema_public.py @@ -5,6 +5,7 @@ from graphene import relay from graphene_django import DjangoObjectType from graphene_django.filter import DjangoFilterConnectionField +from newsteaser.date_helper import month_to_german_string from newsteaser.models import NewsTeaser @@ -16,40 +17,13 @@ class NewsTeaserNode(DjangoObjectType): filter_fields = ['date',] interfaces = (relay.Node,) - def _month_to_german_string(self, date): - if date == 1: - month = 'Januar' - elif date == 2: - month = 'Februar' - elif date == 3: - month = 'März' - elif date == 4: - month = 'April' - elif date == 5: - month = 'Mai' - elif date == 6: - month = 'Juni' - elif date == 7: - month = 'Juli' - elif date == 8: - month = 'August' - elif date == 9: - month = 'September' - elif date == 10: - month = 'Oktober' - elif date == 11: - month = 'November' - elif date == 12: - month = 'Dezember' - return month - def resolve_display_date(self, *args, **kwargs): # play it safe, locale might not be installed in platform try: locale.setlocale(locale.LC_TIME, "de_DE") return self.date.strftime("%-d. %B %Y") except: - month = self._month_to_german_string(self.date) + month = month_to_german_string(self.date.month) return f'{self.date.day}. {month}. {self.date.year}' From deeab23088f56ebfa62da2d563362e845c2bf24a Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 28 May 2020 13:56:18 +0200 Subject: [PATCH 11/15] Add link, align date on bottom --- client/src/components/NewsTeasers.vue | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/client/src/components/NewsTeasers.vue b/client/src/components/NewsTeasers.vue index 4ed433c0..53bba750 100644 --- a/client/src/components/NewsTeasers.vue +++ b/client/src/components/NewsTeasers.vue @@ -1,11 +1,13 @@ @@ -68,6 +70,7 @@ .teaser { margin-bottom: $large-spacing; + position: relative; &__image { display: block; @@ -91,6 +94,9 @@ font-family: $sans-serif-font-family; font-weight: $font-weight-regular; color: $color-silver-dark; + position: absolute; + bottom: 0; + left: 0; } } From c4943c8975adfdfad712340410719de060167bee Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 3 Jun 2020 07:07:18 +0200 Subject: [PATCH 12/15] Rename class --- client/src/components/NewsTeasers.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/NewsTeasers.vue b/client/src/components/NewsTeasers.vue index 53bba750..168d0be6 100644 --- a/client/src/components/NewsTeasers.vue +++ b/client/src/components/NewsTeasers.vue @@ -1,6 +1,6 @@ diff --git a/client/src/components/inputs/BaseInput.vue b/client/src/components/inputs/BaseInput.vue index 0c9ffad0..f6142b1b 100644 --- a/client/src/components/inputs/BaseInput.vue +++ b/client/src/components/inputs/BaseInput.vue @@ -12,9 +12,12 @@ - {{ label }} - - + {{ label }} + diff --git a/client/src/pages/registration.vue b/client/src/pages/registration.vue index cfcd7cf1..b179c6e8 100644 --- a/client/src/pages/registration.vue +++ b/client/src/pages/registration.vue @@ -199,41 +199,47 @@ for="password2" class="skillboxform-input__label">Passwort wiederholen {{ errors.first('password-confirmation') }}
- Hiermit akzeptiere ich die AGB und - Datenschutzbestimmungen + Hiermit akzeptiere ich die AGB und + Datenschutzbestimmungen Sie müssen hier zustimmen, damit Sie sich registrieren können.