Merged in feature/colors (pull request #3)

Feature/colors

Approved-by: Ramon Wenger <ramon.wenger@iterativ.ch>
This commit is contained in:
Christian Cueni 2018-10-17 12:34:16 +00:00 committed by Ramon Wenger
commit 13a9812ba0
18 changed files with 147 additions and 54 deletions

View File

@ -137,6 +137,7 @@
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/styles/_variables.scss"; @import "@/styles/_variables.scss";
@import "@/styles/_mixins.scss";
.content-block { .content-block {
margin-bottom: 2.5em; margin-bottom: 2.5em;
@ -167,14 +168,16 @@
top: 40px; top: 40px;
} }
&--yellow { &--base_communication {
background-color: rgba($color-accent-1, 0.15); @include content-box($color-accent-1);
border: 1px solid $color-accent-1;
padding: 15px;
/deep/ .button {
border-color: $color-accent-1;
} }
&--task {
@include content-box($color-brand);
}
&--base_society {
@include content-box($color-accent-2);
} }
/deep/ p { /deep/ p {

View File

@ -5,7 +5,12 @@
:placeholder="titlePlaceholder" :placeholder="titlePlaceholder"
:value="localContentBlock.title" :value="localContentBlock.title"
:error="error"></modal-input> :error="error"></modal-input>
<checkbox :checked="localContentBlock.isAssignment"
:item="localContentBlock"
:label="'Aufgabe'"
@input="setContentBlockType"
class="contents-form__task"
></checkbox>
<modal-input v-if="blockType === 'RoomEntry'" <modal-input v-if="blockType === 'RoomEntry'"
placeholder="Untertitel für Raumeintrag erfassen" placeholder="Untertitel für Raumeintrag erfassen"
v-model="localContentBlock.subtitle"></modal-input> v-model="localContentBlock.subtitle"></modal-input>
@ -68,6 +73,7 @@
import AssignmentForm from '@/components/content-forms/AssignmentForm'; import AssignmentForm from '@/components/content-forms/AssignmentForm';
import TextForm from '@/components/content-forms/TextForm'; import TextForm from '@/components/content-forms/TextForm';
import TrashIcon from '@/components/icons/TrashIcon'; import TrashIcon from '@/components/icons/TrashIcon';
import Checkbox from '@/components/Checkbox';
export default { export default {
props: { props: {
@ -89,7 +95,8 @@
DocumentForm, DocumentForm,
AssignmentForm, AssignmentForm,
TextForm, TextForm,
TrashIcon TrashIcon,
Checkbox
}, },
data() { data() {
@ -99,7 +106,8 @@
title: this.contentBlock.title, title: this.contentBlock.title,
contents: [...this.contentBlock.contents], contents: [...this.contentBlock.contents],
id: this.contentBlock.id || undefined, id: this.contentBlock.id || undefined,
subtitle: this.contentBlock.subtitle subtitle: this.contentBlock.subtitle,
isAssignment: this.contentBlock.type && this.contentBlock.type === 'TASK'
}) })
} }
}, },
@ -229,6 +237,9 @@
return false; return false;
} }
this.$emit('save', this.localContentBlock); this.$emit('save', this.localContentBlock);
},
setContentBlockType(checked, localContentBlock) {
this.localContentBlock.isAssignment = checked;
} }
} }
} }
@ -274,5 +285,9 @@
&__add { &__add {
grid-column: 1 / span 2; grid-column: 1 / span 2;
} }
&__task {
margin: 15px 0 10px;
}
} }
</style> </style>

View File

@ -14,6 +14,7 @@
import EDIT_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/mutateContentBlock.gql'; import EDIT_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/mutateContentBlock.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql'; import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql'; import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
import { setUserBlockType } from '@/helpers/content-block'
export default { export default {
components: { components: {
@ -32,7 +33,8 @@
input: { input: {
contentBlock: { contentBlock: {
title: contentBlock.title, title: contentBlock.title,
contents: contentBlock.contents.filter(value => Object.keys(value).length > 0) contents: contentBlock.contents.filter(value => Object.keys(value).length > 0),
type: setUserBlockType(contentBlock.isAssignment)
}, },
id: contentBlock.id id: contentBlock.id
} }

View File

@ -8,11 +8,11 @@
<script> <script>
import ContentsForm from '@/components/content-block-form/ContentsForm'; import ContentsForm from '@/components/content-block-form/ContentsForm';
import store from '@/store/index'; import store from '@/store/index';
import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql'; import NEW_CONTENT_BLOCK_MUTATION from '@/graphql/gql/mutations/addContentBlock.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql'; import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
import { setUserBlockType } from '@/helpers/content-block'
export default { export default {
components: { components: {
@ -31,7 +31,8 @@
input: { input: {
contentBlock: { contentBlock: {
title: contentBlock.title, title: contentBlock.title,
contents: contentBlock.contents.filter(value => Object.keys(value).length > 0) contents: contentBlock.contents.filter(value => Object.keys(value).length > 0),
type: setUserBlockType(contentBlock.isAssignment)
}, },
after: this.$store.state.contentBlockPosition.after, after: this.$store.state.contentBlockPosition.after,
parent: this.$store.state.contentBlockPosition.parent parent: this.$store.state.contentBlockPosition.parent

View File

@ -17,7 +17,7 @@
margin-bottom: 30px; margin-bottom: 30px;
align-items: start; align-items: start;
background-color: $color-brand-light; background-color: $color-brand-light;
padding: 20px; padding: 20px, 0;
border-radius: $default-border-radius; border-radius: $default-border-radius;
} }
</style> </style>

View File

@ -177,9 +177,6 @@
.assignment { .assignment {
margin-bottom: 2em; margin-bottom: 2em;
padding: 20px;
border-radius: $default-border-radius;
background-color: $color-brand-light;
&__title { &__title {
font-size: toRem(17px); font-size: toRem(17px);

View File

@ -1,10 +1,9 @@
#import "../fragments/contentBlockParts.gql"
mutation AddContentBlock($input: AddContentBlockInput!) { mutation AddContentBlock($input: AddContentBlockInput!) {
addContentBlock(input: $input) { addContentBlock(input: $input) {
newContentBlock { newContentBlock {
id ...ContentBlockParts
title
slug
contents
} }
errors errors
clientMutationId clientMutationId

View File

@ -1,4 +1,5 @@
#import "../fragments/contentBlockParts.gql" #import "../fragments/contentBlockParts.gql"
mutation MutateContentBlock($input: MutateContentBlockInput!) { mutation MutateContentBlock($input: MutateContentBlockInput!) {
mutateContentBlock(input: $input) { mutateContentBlock(input: $input) {
contentBlock { contentBlock {

View File

@ -0,0 +1,3 @@
export function setUserBlockType(isAssignment) {
return isAssignment ? 'TASK' : 'NORMAL';
}

View File

@ -32,3 +32,15 @@
} }
} }
@mixin content-box($main-color) {
background-color: rgba($main-color, 0.15);
padding: 15px;
align-items: start;
border-radius: $default-border-radius;
/deep/ .button {
border-color: $main-color;
background-color: $color-white;
}
}

View File

@ -93,7 +93,7 @@ class ContentBlockFactory(BasePageFactory):
class Meta: class Meta:
model = ContentBlock model = ContentBlock
type = factory.LazyAttribute(lambda x: random.choice(['plain', 'yellow', 'green', 'blue'])) type = factory.LazyAttribute(lambda x: random.choice(['normal', 'base_communication', 'task', 'base_society']))
contents = wagtail_factories.StreamFieldFactory({ contents = wagtail_factories.StreamFieldFactory({
'text_block': TextBlockFactory, 'text_block': TextBlockFactory,

View File

@ -0,0 +1,18 @@
# Generated by Django 2.0.6 on 2018-10-15 12:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('books', '0002_auto_20181011_1345'),
]
operations = [
migrations.AlterField(
model_name='contentblock',
name='type',
field=models.CharField(choices=[('normal', 'Normal'), ('base_communication', 'Basiswissen Sprache & Kommunikation'), ('task', 'Aufgabe'), ('base_society', 'Basiswissen Gesellschaft')], default='normal', max_length=100),
),
]

View File

@ -19,16 +19,16 @@ class ContentBlock(StrictHierarchyPage):
verbose_name = 'Inhaltsblock' verbose_name = 'Inhaltsblock'
verbose_name_plural = 'Inhaltsblöcke' verbose_name_plural = 'Inhaltsblöcke'
PLAIN = 'plain' NORMAL = 'normal'
YELLOW = 'yellow' BASE_COMMUNICATION = 'base_communication'
GREEN = 'green' TASK = 'task'
BLUE = 'blue' BASE_SOCIETY = 'base_society'
TYPE_CHOICES = ( TYPE_CHOICES = (
(PLAIN, 'Normal'), (NORMAL, 'Normal'),
(YELLOW, 'Gelb'), (BASE_COMMUNICATION, 'Basiswissen Sprache & Kommunikation'),
(GREEN, 'Grün'), (TASK, 'Aufgabe'),
(BLUE, 'Blau'), (BASE_SOCIETY, 'Basiswissen Gesellschaft'),
) )
hidden_for = models.ManyToManyField(SchoolClass, related_name='hidden_content_blocks') hidden_for = models.ManyToManyField(SchoolClass, related_name='hidden_content_blocks')
@ -50,7 +50,7 @@ class ContentBlock(StrictHierarchyPage):
type = models.CharField( type = models.CharField(
max_length=100, max_length=100,
choices=TYPE_CHOICES, choices=TYPE_CHOICES,
default=PLAIN default=NORMAL
) )
content_panels = [ content_panels = [

View File

@ -9,7 +9,7 @@ from api.utils import get_object, get_errors
from books.models import ContentBlock, Chapter, SchoolClass from books.models import ContentBlock, Chapter, SchoolClass
from books.schema.inputs import ContentBlockInput from books.schema.inputs import ContentBlockInput
from books.schema.queries import ContentBlockNode from books.schema.queries import ContentBlockNode
from .utils import handle_content_block from .utils import handle_content_block, set_user_defined_block_type
class MutateContentBlock(relay.ClientIDMutation): class MutateContentBlock(relay.ClientIDMutation):
@ -29,6 +29,7 @@ class MutateContentBlock(relay.ClientIDMutation):
title = content_block_data.get('title', None) title = content_block_data.get('title', None)
contents = content_block_data.get('contents', None) contents = content_block_data.get('contents', None)
visibility_list = content_block_data.get('visibility', None) visibility_list = content_block_data.get('visibility', None)
block_type = content_block_data.get('type', ContentBlock.NORMAL)
content_block = get_object(ContentBlock, id_param) content_block = get_object(ContentBlock, id_param)
@ -46,6 +47,8 @@ class MutateContentBlock(relay.ClientIDMutation):
if contents is not None: if contents is not None:
content_block.contents = json.dumps([handle_content_block(c, info.context) for c in contents]) content_block.contents = json.dumps([handle_content_block(c, info.context) for c in contents])
content_block.type = set_user_defined_block_type(block_type)
content_block.save() content_block.save()
return cls(content_block=content_block) return cls(content_block=content_block)
@ -74,8 +77,9 @@ class AddContentBlock(relay.ClientIDMutation):
title = content_block_data.get('title') title = content_block_data.get('title')
contents = content_block_data.get('contents') contents = content_block_data.get('contents')
block_type = set_user_defined_block_type(content_block_data.get('type', ContentBlock.NORMAL))
new_content_block = ContentBlock(title=title, user_created=True, owner=context.user) new_content_block = ContentBlock(title=title, user_created=True, owner=context.user, type=block_type)
if parent is not None: if parent is not None:
parent_chapter = get_object(Chapter, parent).specific parent_chapter = get_object(Chapter, parent).specific

View File

@ -12,6 +12,7 @@ import bleach
import re import re
from assignments.models import Assignment from assignments.models import Assignment
from books.models import ContentBlock
def newlines_to_paragraphs(text): def newlines_to_paragraphs(text):
@ -83,3 +84,10 @@ def handle_content_block(content, context, allowed_blocks=ALLOWED_BLOCKS):
}} }}
return None return None
def set_user_defined_block_type(block_type):
if block_type == ContentBlock.TASK.upper():
return ContentBlock.TASK
else:
return ContentBlock.NORMAL

View File

@ -22,6 +22,7 @@ class ContentBlockNode(DjangoObjectType):
def resolve_mine(self, info, **kwargs): def resolve_mine(self, info, **kwargs):
return self.owner is not None and self.owner.pk == info.context.user.pk return self.owner is not None and self.owner.pk == info.context.user.pk
class ChapterNode(DjangoObjectType): class ChapterNode(DjangoObjectType):
content_blocks = DjangoFilterConnectionField(ContentBlockNode) content_blocks = DjangoFilterConnectionField(ContentBlockNode)

View File

@ -24,7 +24,21 @@ class NewContentBlockMutationTest(TestCase):
def test_add_new_content_block(self): def test_add_new_content_block(self):
self.assertEqual(ContentBlock.objects.count(), 1) self.assertEqual(ContentBlock.objects.count(), 1)
mutation = get_graphql_mutation('addContentBlock.gql') mutation = """
mutation AddContentBlock($input: AddContentBlockInput!) {
addContentBlock(input: $input) {
newContentBlock {
id
title
slug
contents
type
}
errors
clientMutationId
}
}
"""
title = "Hello World" title = "Hello World"
@ -59,7 +73,21 @@ class NewContentBlockMutationTest(TestCase):
def test_addNewContentBlock_withImageUrlBlock(self): def test_addNewContentBlock_withImageUrlBlock(self):
self.assertEqual(ContentBlock.objects.count(), 1) self.assertEqual(ContentBlock.objects.count(), 1)
mutation = get_graphql_mutation('addContentBlock.gql') mutation = """
mutation AddContentBlock($input: AddContentBlockInput!) {
addContentBlock(input: $input) {
newContentBlock {
id
title
slug
contents
type
}
errors
clientMutationId
}
}
"""
title = "Hello World" title = "Hello World"
@ -67,6 +95,7 @@ class NewContentBlockMutationTest(TestCase):
'input': { 'input': {
"contentBlock": { "contentBlock": {
"title": title, "title": title,
"type": "NORMAL",
"contents": [ "contents": [
{ {
"type": "image_url_block", "type": "image_url_block",

View File

@ -83,7 +83,7 @@ data = [
'title': '1.1 Lehrbeginn', 'title': '1.1 Lehrbeginn',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 1', 'title': 'Auftrag 1',
'contents': [ 'contents': [
{ {
@ -102,7 +102,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 2', 'title': 'Auftrag 2',
'contents': [ 'contents': [
{ {
@ -139,7 +139,7 @@ data = [
] ]
}, },
{ {
'type': 'yellow', 'type': 'base_communication',
'title': 'Das Interview', 'title': 'Das Interview',
'contents': [ 'contents': [
{ {
@ -151,7 +151,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 3', 'title': 'Auftrag 3',
'contents': [ 'contents': [
{ {
@ -175,7 +175,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 4', 'title': 'Auftrag 4',
'contents': [ 'contents': [
{ {
@ -199,7 +199,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'normal',
'title': 'Tipp', 'title': 'Tipp',
'contents': [ 'contents': [
{ {
@ -216,7 +216,7 @@ data = [
'title': '1.2 Die drei Lernorte', 'title': '1.2 Die drei Lernorte',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'blue', 'type': 'base_society',
'title': 'Das Berufsbildungssystem', 'title': 'Das Berufsbildungssystem',
'contents': [ 'contents': [
{ {
@ -246,7 +246,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 5', 'title': 'Auftrag 5',
'contents': [ 'contents': [
{ {
@ -271,7 +271,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 6', 'title': 'Auftrag 6',
'contents': [ 'contents': [
{ {
@ -283,7 +283,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 7', 'title': 'Auftrag 7',
'contents': [ 'contents': [
{ {
@ -325,7 +325,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 8', 'title': 'Auftrag 8',
'contents': [ 'contents': [
{ {
@ -381,7 +381,7 @@ data = [
'title': '2.1 Eine Welt ohne Geld?', 'title': '2.1 Eine Welt ohne Geld?',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 1', 'title': 'Auftrag 1',
'contents': [ 'contents': [
{ {
@ -433,7 +433,7 @@ data = [
'title': '2.2 Geld regiert die Welt', 'title': '2.2 Geld regiert die Welt',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 2', 'title': 'Auftrag 2',
'contents': [ 'contents': [
{ {
@ -493,7 +493,7 @@ data = [
'title': '2.3 Funktionen der Geschäftsbanken', 'title': '2.3 Funktionen der Geschäftsbanken',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'yellow', 'type': 'base_communication',
'title': 'Basiswissen: Notizen', 'title': 'Basiswissen: Notizen',
'contents': [ 'contents': [
{ {
@ -505,7 +505,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 3', 'title': 'Auftrag 3',
'contents': [ 'contents': [
{ {
@ -535,7 +535,7 @@ data = [
'title': '2.4 Geld aufbewahren', 'title': '2.4 Geld aufbewahren',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'yellow', 'type': 'base_communication',
'title': 'Basiswissen: Geldanlage', 'title': 'Basiswissen: Geldanlage',
'contents': [ 'contents': [
{ {
@ -547,7 +547,7 @@ data = [
] ]
}, },
{ {
'type': 'yellow', 'type': 'base_communication',
'title': 'Basiswissen: Anlageformen', 'title': 'Basiswissen: Anlageformen',
'contents': [ 'contents': [
{ {
@ -559,7 +559,7 @@ data = [
] ]
}, },
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 4', 'title': 'Auftrag 4',
'contents': [ 'contents': [
{ {
@ -608,7 +608,7 @@ data = [
'title': '2.5 Geldinstitute im Vergleich', 'title': '2.5 Geldinstitute im Vergleich',
'content_blocks': [ 'content_blocks': [
{ {
'type': 'plain', 'type': 'task',
'title': 'Auftrag 5', 'title': 'Auftrag 5',
'contents': [ 'contents': [
{ {