Merge branch 'feature/user-created-content-blocks'
This commit is contained in:
commit
4d1e156f9f
|
|
@ -6,6 +6,8 @@
|
||||||
{{chapter.description}}
|
{{chapter.description}}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<add-content-block-button :parent="chapter.id"></add-content-block-button>
|
||||||
|
|
||||||
<content-block :contentBlock="contentBlock"
|
<content-block :contentBlock="contentBlock"
|
||||||
:key="contentBlock.id" v-for="contentBlock in filteredContentBlocks">
|
:key="contentBlock.id" v-for="contentBlock in filteredContentBlocks">
|
||||||
</content-block>
|
</content-block>
|
||||||
|
|
@ -14,12 +16,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ContentBlock from '@/components/ContentBlock';
|
import ContentBlock from '@/components/ContentBlock';
|
||||||
|
import AddContentBlockButton from '@/components/AddContentBlockButton';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['chapter', 'index'],
|
props: ['chapter', 'index'],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
ContentBlock,
|
ContentBlock,
|
||||||
|
AddContentBlockButton
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content-block__container">
|
<div class="content-block__container">
|
||||||
<div class="content-block" :class="specialClass">
|
<div class="content-block" :class="specialClass">
|
||||||
<div v-if="canChangeContentBlock" class="content-block__actions">
|
<div class="content-block__actions">
|
||||||
<a @click="toggleVisibility()" class="content-block__visibility-button">
|
<a @click="toggleVisibility()" v-if="canManageContent" class="content-block__visibility-button">
|
||||||
<eye-icon class="content-block__action-icon"></eye-icon>
|
<eye-icon class="content-block__action-icon"></eye-icon>
|
||||||
</a>
|
</a>
|
||||||
<visibility-popover
|
<visibility-popover
|
||||||
|
|
@ -10,12 +10,12 @@
|
||||||
:content-block="contentBlock"
|
:content-block="contentBlock"
|
||||||
class="content-block__visibility-menu"
|
class="content-block__visibility-menu"
|
||||||
></visibility-popover>
|
></visibility-popover>
|
||||||
<a @click="editContentBlock()">
|
<a @click="editContentBlock()" v-if="contentBlock.userCreated">
|
||||||
<pen-icon class="content-block__action-icon"></pen-icon>
|
<pen-icon class="content-block__action-icon"></pen-icon>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="content-block__title">{{contentBlock.title}}</h4>
|
<h4 class="content-block__title">{{contentBlock.title}} {{contentBlock.userCreated}}</h4>
|
||||||
|
|
||||||
<component v-for="component in contentBlock.contents"
|
<component v-for="component in contentBlock.contents"
|
||||||
:key="component.id"
|
:key="component.id"
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<add-content-block-button v-if="canChangeContentBlock" :after="contentBlock.id"></add-content-block-button>
|
<add-content-block-button :after="contentBlock.id"></add-content-block-button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -70,8 +70,8 @@
|
||||||
specialClass() {
|
specialClass() {
|
||||||
return `content-block--${this.contentBlock.type.toLowerCase()}`
|
return `content-block--${this.contentBlock.type.toLowerCase()}`
|
||||||
},
|
},
|
||||||
canChangeContentBlock() {
|
canManageContent() {
|
||||||
return this.me.permissions.includes('user.can_edit_modules');
|
return this.me.permissions.includes('users.can_manage_school_class_content');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ fragment ContentBlockParts on ContentBlockNode {
|
||||||
title
|
title
|
||||||
type
|
type
|
||||||
contents
|
contents
|
||||||
|
userCreated
|
||||||
hiddenFor {
|
hiddenFor {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
|
|
@ -12,4 +13,12 @@ fragment ContentBlockParts on ContentBlockNode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
visibleFor {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from filteredbook.schema import BookQuery
|
||||||
from objectives.schema import ObjectivesQuery
|
from objectives.schema import ObjectivesQuery
|
||||||
from rooms.mutations import RoomMutations
|
from rooms.mutations import RoomMutations
|
||||||
from rooms.schema import RoomsQuery
|
from rooms.schema import RoomsQuery
|
||||||
from user.schema import UsersQuery
|
from users.schema import UsersQuery
|
||||||
|
|
||||||
|
|
||||||
class Query(UsersQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery, graphene.ObjectType):
|
class Query(UsersQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery, graphene.ObjectType):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
@ -12,8 +12,8 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('wagtailcore', '0040_page_draft_title'),
|
|
||||||
('wagtailimages', '0021_image_file_hash'),
|
('wagtailimages', '0021_image_file_hash'),
|
||||||
|
('wagtailcore', '0040_page_draft_title'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
@ -44,6 +44,7 @@ class Migration(migrations.Migration):
|
||||||
name='ContentBlock',
|
name='ContentBlock',
|
||||||
fields=[
|
fields=[
|
||||||
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
|
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
|
||||||
|
('user_created', models.BooleanField(default=False)),
|
||||||
('contents', wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())])), ('basic_knowledge', wagtail.core.blocks.StructBlock([('description', wagtail.core.blocks.RichTextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('assignment', wagtail.core.blocks.StructBlock([('assignment_id', wagtail.core.blocks.IntegerBlock())])), ('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())])), ('task', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())], icon='tick')), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True)),
|
('contents', wagtail.core.fields.StreamField([('text_block', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())])), ('basic_knowledge', wagtail.core.blocks.StructBlock([('description', wagtail.core.blocks.RichTextBlock()), ('url', wagtail.core.blocks.URLBlock())])), ('assignment', wagtail.core.blocks.StructBlock([('assignment_id', wagtail.core.blocks.IntegerBlock())])), ('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())])), ('task', wagtail.core.blocks.StructBlock([('text', wagtail.core.blocks.RichTextBlock())], icon='tick')), ('video_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())])), ('document_block', wagtail.core.blocks.StructBlock([('url', wagtail.core.blocks.URLBlock())]))], blank=True, null=True)),
|
||||||
('type', models.CharField(choices=[('plain', 'Normal'), ('yellow', 'Gelb'), ('green', 'Grün'), ('blue', 'Blau')], default='plain', max_length=100)),
|
('type', models.CharField(choices=[('plain', 'Normal'), ('yellow', 'Gelb'), ('green', 'Grün'), ('blue', 'Blau')], default='plain', max_length=100)),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0001_initial'),
|
||||||
|
('books', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contentblock',
|
||||||
|
name='hidden_for',
|
||||||
|
field=models.ManyToManyField(related_name='hidden_content_blocks', to='users.SchoolClass'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='contentblock',
|
||||||
|
name='visible_for',
|
||||||
|
field=models.ManyToManyField(related_name='visible_content_blocks', to='users.SchoolClass'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('books', '0001_initial'),
|
|
||||||
('user', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='contentblock',
|
|
||||||
name='hidden_for',
|
|
||||||
field=models.ManyToManyField(to='user.SchoolClass'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
@ -4,11 +4,12 @@ from django.db import models
|
||||||
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList, StreamFieldPanel
|
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList, StreamFieldPanel
|
||||||
from wagtail.core.fields import StreamField
|
from wagtail.core.fields import StreamField
|
||||||
from wagtail.images.blocks import ImageChooserBlock
|
from wagtail.images.blocks import ImageChooserBlock
|
||||||
|
from wagtail.core import hooks
|
||||||
|
|
||||||
from books.blocks import TextBlock, BasicKnowledgeBlock, LinkBlock, VideoBlock, DocumentBlock, \
|
from books.blocks import TextBlock, BasicKnowledgeBlock, LinkBlock, VideoBlock, DocumentBlock, \
|
||||||
ImageUrlBlock, AssignmentBlock
|
ImageUrlBlock, AssignmentBlock
|
||||||
from core.wagtail_utils import StrictHierarchyPage
|
from core.wagtail_utils import StrictHierarchyPage
|
||||||
from user.models import SchoolClass
|
from users.models import SchoolClass
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
@ -30,7 +31,9 @@ class ContentBlock(StrictHierarchyPage):
|
||||||
(BLUE, 'Blau'),
|
(BLUE, 'Blau'),
|
||||||
)
|
)
|
||||||
|
|
||||||
hidden_for = models.ManyToManyField(SchoolClass)
|
hidden_for = models.ManyToManyField(SchoolClass, related_name='hidden_content_blocks')
|
||||||
|
visible_for = models.ManyToManyField(SchoolClass, related_name='visible_content_blocks')
|
||||||
|
user_created = models.BooleanField(default=False)
|
||||||
|
|
||||||
contents = StreamField([
|
contents = StreamField([
|
||||||
('text_block', TextBlock()),
|
('text_block', TextBlock()),
|
||||||
|
|
@ -69,3 +72,10 @@ class ContentBlock(StrictHierarchyPage):
|
||||||
|
|
||||||
parent_page_types = ['books.Chapter']
|
parent_page_types = ['books.Chapter']
|
||||||
subpage_types = []
|
subpage_types = []
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.register('construct_explorer_page_queryset')
|
||||||
|
def remove_user_created_content_blocks_from_menu(parent_page, pages, request):
|
||||||
|
if parent_page.content_type.model == 'chapter':
|
||||||
|
return ContentBlock.get_by_parent(parent_page.specific).exclude(user_created=True)
|
||||||
|
return pages
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ 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')
|
||||||
|
|
||||||
new_content_block = ContentBlock(title=title)
|
new_content_block = ContentBlock(title=title, user_created=True, owner=context.user)
|
||||||
|
|
||||||
if parent is not None:
|
if parent is not None:
|
||||||
parent_chapter = get_object(Chapter, parent).specific
|
parent_chapter = get_object(Chapter, parent).specific
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ class ContentBlockNode(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ContentBlock
|
model = ContentBlock
|
||||||
only_fields = [
|
only_fields = [
|
||||||
'slug', 'title', 'type', 'contents', 'hidden_for'
|
'slug', 'title', 'type', 'contents', 'hidden_for', 'visible_for', 'user_created'
|
||||||
]
|
]
|
||||||
filter_fields = [
|
filter_fields = [
|
||||||
'slug', 'title',
|
'slug', 'title',
|
||||||
|
|
@ -31,8 +31,29 @@ class ChapterNode(DjangoObjectType):
|
||||||
]
|
]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
def resolve_content_blocks(self, *args, **kwargs):
|
def resolve_content_blocks(self, info, **kwargs):
|
||||||
return ContentBlock.get_by_parent(self)
|
user = info.context.user
|
||||||
|
school_classes = user.school_classes.values_list('pk')
|
||||||
|
|
||||||
|
if user.has_perm('users.can_manage_school_class_content'): # teacher
|
||||||
|
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False)
|
||||||
|
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
||||||
|
else: # student
|
||||||
|
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False).exclude(
|
||||||
|
hidden_for__in=school_classes)
|
||||||
|
|
||||||
|
self_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
||||||
|
|
||||||
|
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True,
|
||||||
|
visible_for__in=school_classes).union(
|
||||||
|
self_created_content_blocks)
|
||||||
|
|
||||||
|
return publisher_content_blocks.union(user_created_content_blocks)
|
||||||
|
|
||||||
|
# if user.has_perm('users.can_manage_school_class_content'):
|
||||||
|
# return ContentBlock.get_by_parent(self)
|
||||||
|
# else:
|
||||||
|
# return ContentBlock.get_by_parent(self)
|
||||||
|
|
||||||
|
|
||||||
class ModuleNode(DjangoObjectType):
|
class ModuleNode(DjangoObjectType):
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from wagtail.core.models import Page
|
||||||
from books.factories import BookFactory, TopicFactory, ModuleFactory, ChapterFactory, ContentBlockFactory
|
from books.factories import BookFactory, TopicFactory, ModuleFactory, ChapterFactory, ContentBlockFactory
|
||||||
from core.factories import UserFactory
|
from core.factories import UserFactory
|
||||||
from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory
|
from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory
|
||||||
from user.services import create_school_with_users
|
from users.services import create_school_with_users
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ from wagtail.core.models import Site
|
||||||
|
|
||||||
from rooms.factories import RoomFactory, RoomEntryFactory
|
from rooms.factories import RoomFactory, RoomEntryFactory
|
||||||
from rooms.models import Room
|
from rooms.models import Room
|
||||||
from user.factories import SchoolClassFactory
|
from users.factories import SchoolClassFactory
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ if not DEBUG:
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'core',
|
'core',
|
||||||
'api',
|
'api',
|
||||||
'user',
|
'users',
|
||||||
'books',
|
'books',
|
||||||
'objectives',
|
'objectives',
|
||||||
'rooms',
|
'rooms',
|
||||||
|
|
@ -144,7 +144,7 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Django custom user
|
# Django custom user
|
||||||
AUTH_USER_MODEL = 'user.User'
|
AUTH_USER_MODEL = 'users.User'
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
@ -10,9 +10,9 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
('books', '0002_contentblock_hidden_for'),
|
|
||||||
('objectives', '0001_initial'),
|
('objectives', '0001_initial'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('books', '0002_auto_20181010_0825'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
@ -9,7 +9,7 @@ from wagtail.core.rich_text import RichText
|
||||||
from books.factories import TextBlockFactory, ImageUrlBlockFactory, LinkBlockFactory
|
from books.factories import TextBlockFactory, ImageUrlBlockFactory, LinkBlockFactory
|
||||||
from core.factories import fake, fake_paragraph
|
from core.factories import fake, fake_paragraph
|
||||||
from rooms.models import Room, RoomEntry
|
from rooms.models import Room, RoomEntry
|
||||||
from user.models import SchoolClass
|
from users.models import SchoolClass
|
||||||
|
|
||||||
|
|
||||||
class RoomFactory(factory.django.DjangoModelFactory):
|
class RoomFactory(factory.django.DjangoModelFactory):
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import graphene
|
||||||
from graphene import InputObjectType
|
from graphene import InputObjectType
|
||||||
|
|
||||||
from books.schema.inputs import ContentElementInput
|
from books.schema.inputs import ContentElementInput
|
||||||
from user.inputs import SchoolClassInput
|
from users.inputs import SchoolClassInput
|
||||||
|
|
||||||
|
|
||||||
class RoomInput(InputObjectType):
|
class RoomInput(InputObjectType):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django_extensions.db.fields
|
import django_extensions.db.fields
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
@ -11,8 +11,8 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('users', '0001_initial'),
|
||||||
('rooms', '0001_initial'),
|
('rooms', '0001_initial'),
|
||||||
('user', '0001_initial'),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
|
|
@ -29,6 +29,6 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='room',
|
model_name='room',
|
||||||
name='school_class',
|
name='school_class',
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.SchoolClass'),
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.SchoolClass'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
@ -5,7 +5,7 @@ from wagtail.core.fields import StreamField
|
||||||
|
|
||||||
from books.blocks import ImageUrlBlock, LinkBlock, VideoBlock
|
from books.blocks import ImageUrlBlock, LinkBlock, VideoBlock
|
||||||
from books.models import ContentBlock, TextBlock
|
from books.models import ContentBlock, TextBlock
|
||||||
from user.models import SchoolClass
|
from users.models import SchoolClass
|
||||||
|
|
||||||
|
|
||||||
class Room(TitleSlugDescriptionModel):
|
class Room(TitleSlugDescriptionModel):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from rooms.inputs import UpdateRoomArgument, AddRoomArgument, AddRoomEntryArgume
|
||||||
from rooms.models import Room
|
from rooms.models import Room
|
||||||
from rooms.schema import RoomNode, RoomEntryNode
|
from rooms.schema import RoomNode, RoomEntryNode
|
||||||
from rooms.serializers import RoomSerializer, RoomEntrySerializer
|
from rooms.serializers import RoomSerializer, RoomEntrySerializer
|
||||||
from user.models import SchoolClass
|
from users.models import SchoolClass
|
||||||
|
|
||||||
|
|
||||||
class MutateRoom(relay.ClientIDMutation):
|
class MutateRoom(relay.ClientIDMutation):
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from graphene_django.rest_framework.mutation import SerializerMutation
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from rooms.models import Room, RoomEntry
|
from rooms.models import Room, RoomEntry
|
||||||
from rooms.serializers import RoomSerializer
|
from rooms.serializers import RoomSerializer
|
||||||
from user.schema import UserNode
|
from users.schema import UserNode
|
||||||
|
|
||||||
|
|
||||||
class RoomEntryNode(DjangoObjectType):
|
class RoomEntryNode(DjangoObjectType):
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class UserConfig(AppConfig):
|
class UserConfig(AppConfig):
|
||||||
name = 'user'
|
name = 'users'
|
||||||
|
|
@ -2,7 +2,7 @@ import random
|
||||||
|
|
||||||
import factory
|
import factory
|
||||||
|
|
||||||
from user.models import SchoolClass
|
from users.models import SchoolClass
|
||||||
|
|
||||||
class_types = ['DA', 'KV', 'INF', 'EE']
|
class_types = ['DA', 'KV', 'INF', 'EE']
|
||||||
class_suffix = ['A', 'B', 'C', 'D', 'E']
|
class_suffix = ['A', 'B', 'C', 'D', 'E']
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Generated by Django 2.0.6 on 2018-10-05 09:24
|
# Generated by Django 2.0.6 on 2018-10-10 08:25
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
|
|
@ -7,7 +7,7 @@ import django.core.validators
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
import user.models
|
import users.models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
@ -59,8 +59,8 @@ class Migration(migrations.Migration):
|
||||||
('name', models.CharField(max_length=100)),
|
('name', models.CharField(max_length=100)),
|
||||||
('year', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1900), django.core.validators.MaxValueValidator(2200)])),
|
('year', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1900), django.core.validators.MaxValueValidator(2200)])),
|
||||||
('is_deleted', models.BooleanField(default=False)),
|
('is_deleted', models.BooleanField(default=False)),
|
||||||
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.School')),
|
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.School')),
|
||||||
('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
|
('users', models.ManyToManyField(related_name='school_classes', to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
|
@ -70,20 +70,20 @@ class Migration(migrations.Migration):
|
||||||
('key', models.CharField(max_length=100, verbose_name='Key')),
|
('key', models.CharField(max_length=100, verbose_name='Key')),
|
||||||
('name', models.CharField(max_length=100, verbose_name='Name')),
|
('name', models.CharField(max_length=100, verbose_name='Name')),
|
||||||
('role_permission', models.ManyToManyField(blank=True, related_name='role_set', related_query_name='role', to='auth.Permission', verbose_name='Role permission')),
|
('role_permission', models.ManyToManyField(blank=True, related_name='role_set', related_query_name='role', to='auth.Permission', verbose_name='Role permission')),
|
||||||
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.School')),
|
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.School')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'permissions': (('can_edit_modules', 'Can create new contentblocks'),),
|
'permissions': (('can_manage_school_class_content', 'Can manage contents for assigned school clases'),),
|
||||||
},
|
},
|
||||||
managers=[
|
managers=[
|
||||||
('objects', user.models.SchoolRoleManager()),
|
('objects', users.models.SchoolRoleManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='UserSchoolRole',
|
name='UserSchoolRole',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('school_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.SchoolRole')),
|
('school_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.SchoolRole')),
|
||||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -27,6 +27,9 @@ class User(AbstractUser):
|
||||||
django_permissions = super().get_all_permissions(obj)
|
django_permissions = super().get_all_permissions(obj)
|
||||||
return django_permissions.union(self.get_school_permissions(School.objects.get(pk=DEFAULT_SCHOOL_ID)))
|
return django_permissions.union(self.get_school_permissions(School.objects.get(pk=DEFAULT_SCHOOL_ID)))
|
||||||
|
|
||||||
|
def has_perm(self, perm, obj=None):
|
||||||
|
return super(User, self).has_perm(perm, obj) or perm in self.get_all_permissions(obj)
|
||||||
|
|
||||||
|
|
||||||
class School(models.Model):
|
class School(models.Model):
|
||||||
name = models.CharField(_(u'Name'), max_length=100, null=False, blank=False)
|
name = models.CharField(_(u'Name'), max_length=100, null=False, blank=False)
|
||||||
|
|
@ -87,10 +90,10 @@ class SchoolRoleManager(models.Manager):
|
||||||
role = self.create(name=value, school=school, key=key)
|
role = self.create(name=value, school=school, key=key)
|
||||||
role.save()
|
role.save()
|
||||||
|
|
||||||
can_edit_modules, = self._create_default_permissions()
|
can_manage_school_class_content, = self._create_default_permissions()
|
||||||
|
|
||||||
if key == "teacher":
|
if key == "teacher":
|
||||||
role.role_permission.add(can_edit_modules.id)
|
role.role_permission.add(can_manage_school_class_content.id)
|
||||||
|
|
||||||
# elif key == "school_admin":
|
# elif key == "school_admin":
|
||||||
# role.role_permission.add()
|
# role.role_permission.add()
|
||||||
|
|
@ -122,9 +125,9 @@ class SchoolRoleManager(models.Manager):
|
||||||
#edit_own_comments = Permission.objects.get(content_type=content_type, codename="can_edit_own_comments")
|
#edit_own_comments = Permission.objects.get(content_type=content_type, codename="can_edit_own_comments")
|
||||||
#delete_comments = Permission.objects.get(content_type=content_type, codename="can_delete_comments")
|
#delete_comments = Permission.objects.get(content_type=content_type, codename="can_delete_comments")
|
||||||
#admin_school = Permission.objects.get(content_type=content_type, codename="can_admin_school")
|
#admin_school = Permission.objects.get(content_type=content_type, codename="can_admin_school")
|
||||||
can_edit_modules = Permission.objects.get(content_type=content_type, codename='can_edit_modules')
|
can_manage_school_class_content = Permission.objects.get(content_type=content_type, codename='can_manage_school_class_content')
|
||||||
|
|
||||||
return can_edit_modules,
|
return can_manage_school_class_content,
|
||||||
|
|
||||||
|
|
||||||
class SchoolRole(models.Model):
|
class SchoolRole(models.Model):
|
||||||
|
|
@ -159,7 +162,7 @@ class SchoolRole(models.Model):
|
||||||
# ("can_edit_events", "Can edit events"),
|
# ("can_edit_events", "Can edit events"),
|
||||||
# ("can_edit_own_comments", "Can edit own comments"),
|
# ("can_edit_own_comments", "Can edit own comments"),
|
||||||
# ("can_delete_comments", "Can delete comments"),
|
# ("can_delete_comments", "Can delete comments"),
|
||||||
('can_edit_modules', 'Can create new contentblocks'),
|
('can_manage_school_class_content', 'Can manage contents for assigned school clases'),
|
||||||
# ("can_admin_school", "Can admin school"),
|
# ("can_admin_school", "Can admin school"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@ from graphene import relay
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
|
|
||||||
from user.models import SchoolClass, User
|
from users.models import SchoolClass, User
|
||||||
|
|
||||||
|
|
||||||
class UserNode(DjangoObjectType):
|
class UserNode(DjangoObjectType):
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from core.factories import UserFactory
|
from core.factories import UserFactory
|
||||||
from user.factories import SchoolClassFactory
|
from users.factories import SchoolClassFactory
|
||||||
from user.models import School, SchoolRole, UserSchoolRole, DEFAULT_SCHOOL_ID
|
from users.models import School, SchoolRole, UserSchoolRole, DEFAULT_SCHOOL_ID
|
||||||
|
|
||||||
|
|
||||||
def create_school_with_users(school_name):
|
def create_school_with_users(school_name):
|
||||||
Loading…
Reference in New Issue