Add snapshot module detail query
This commit is contained in:
parent
a71f893e0b
commit
85a3131680
|
|
@ -0,0 +1,12 @@
|
||||||
|
query SnapshotDetail($id: ID!) {
|
||||||
|
snapshot(id: $id) {
|
||||||
|
id
|
||||||
|
chapters {
|
||||||
|
id
|
||||||
|
description
|
||||||
|
title
|
||||||
|
titleHidden
|
||||||
|
descriptionHidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,12 @@
|
||||||
<div>
|
<div>
|
||||||
Hello
|
Hello
|
||||||
{{ id }}
|
{{ id }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SNAPSHOT_DETAIL_QUERY from 'gql/queries/snapshots/details.gql';
|
import SNAPSHOT_DETAIL_QUERY from '@/graphql/gql/queries/snapshots/detail.gql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -17,7 +18,15 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
snapshot: SNAPSHOT_DETAIL_QUERY,
|
snapshot: {
|
||||||
|
query: SNAPSHOT_DETAIL_QUERY,
|
||||||
|
variables() {
|
||||||
|
return {
|
||||||
|
id: this.id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,8 @@ class ChapterSnapshot(models.Model):
|
||||||
class SnapshotManager(models.Manager):
|
class SnapshotManager(models.Manager):
|
||||||
def create_snapshot(self, module, school_class, user, *args, **kwargs):
|
def create_snapshot(self, module, school_class, user, *args, **kwargs):
|
||||||
snapshot = self.create(module=module, creator=user, *args, **kwargs)
|
snapshot = self.create(module=module, creator=user, *args, **kwargs)
|
||||||
chapters_with_hidden_properties = Chapter.get_by_parent(module).filter(
|
chapters = Chapter.get_by_parent(module)
|
||||||
Q(description_hidden_for=school_class)
|
for chapter in chapters:
|
||||||
| Q(title_hidden_for=school_class)
|
|
||||||
)
|
|
||||||
for chapter in chapters_with_hidden_properties:
|
|
||||||
ChapterSnapshot.objects.create(
|
ChapterSnapshot.objects.create(
|
||||||
chapter=chapter,
|
chapter=chapter,
|
||||||
snapshot=snapshot,
|
snapshot=snapshot,
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,5 @@ from graphene import relay
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
|
|
||||||
class ChapterInterface(relay.Node):
|
class ChapterInterface(relay.Node):
|
||||||
content_blocks = DjangoFilterConnectionField('books.schema.nodes.ContentBlockNode')
|
description = graphene.String()
|
||||||
|
title = graphene.String()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import graphene
|
||||||
|
from graphene import relay
|
||||||
|
|
||||||
|
from api.graphene_wagtail import GenericStreamFieldType
|
||||||
|
|
||||||
|
class ContentBlockType(graphene.Enum):
|
||||||
|
NORMAL = 'normal'
|
||||||
|
BASE_COMMUNICATION = 'base_communication'
|
||||||
|
TASK = 'task'
|
||||||
|
BASE_SOCIETY = 'base_society'
|
||||||
|
BASE_INTERDISCIPLINARY = 'base_interdisciplinary'
|
||||||
|
|
||||||
|
|
||||||
|
class ContentBlockInterface(relay.Node):
|
||||||
|
title = graphene.String()
|
||||||
|
contents = GenericStreamFieldType()
|
||||||
|
type = ContentBlockType()
|
||||||
|
|
@ -4,6 +4,14 @@ from graphene import relay
|
||||||
|
|
||||||
class ModuleInterface(relay.Node):
|
class ModuleInterface(relay.Node):
|
||||||
pk = graphene.Int()
|
pk = graphene.Int()
|
||||||
|
hero_image = graphene.String()
|
||||||
|
topic = graphene.Field('books.schema.nodes.TopicNode')
|
||||||
|
|
||||||
def resolve_pk(self, info, **kwargs):
|
@staticmethod
|
||||||
return self.id
|
def resolve_pk(parent, info, **kwargs):
|
||||||
|
return parent.id
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_hero_image(parent, info, **kwargs):
|
||||||
|
if parent.hero_image:
|
||||||
|
return parent.hero_image.file.url
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import graphene
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
|
||||||
from books.models import Chapter, ContentBlock
|
from books.models import Chapter, ContentBlock
|
||||||
|
|
@ -13,6 +14,7 @@ from notes.schema import ChapterBookmarkNode
|
||||||
|
|
||||||
class ChapterNode(DjangoObjectType):
|
class ChapterNode(DjangoObjectType):
|
||||||
bookmark = graphene.Field(ChapterBookmarkNode)
|
bookmark = graphene.Field(ChapterBookmarkNode)
|
||||||
|
content_blocks = DjangoFilterConnectionField('books.schema.nodes.ContentBlockNode')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Chapter
|
model = Chapter
|
||||||
|
|
@ -50,7 +52,7 @@ class ChapterNode(DjangoObjectType):
|
||||||
).first()
|
).first()
|
||||||
|
|
||||||
|
|
||||||
class SnapshotChapterNode(DjangoObjectType):
|
class ChapterInSnapshotNode(DjangoObjectType):
|
||||||
title_hidden = graphene.Boolean()
|
title_hidden = graphene.Boolean()
|
||||||
description_hidden = graphene.Boolean()
|
description_hidden = graphene.Boolean()
|
||||||
title = graphene.String()
|
title = graphene.String()
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphene import relay
|
from graphene import relay, ObjectType
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
|
||||||
from books.models import ContentBlock
|
from books.models import ContentBlock
|
||||||
|
from books.schema.interfaces.contentblock import ContentBlockInterface
|
||||||
from books.utils import are_solutions_enabled_for
|
from books.utils import are_solutions_enabled_for
|
||||||
from notes.models import ContentBlockBookmark
|
from notes.models import ContentBlockBookmark
|
||||||
from notes.schema import ContentBlockBookmarkNode
|
from notes.schema import ContentBlockBookmarkNode
|
||||||
|
|
@ -39,8 +40,6 @@ class ContentBlockNode(DjangoObjectType):
|
||||||
mine = graphene.Boolean()
|
mine = graphene.Boolean()
|
||||||
bookmarks = graphene.List(ContentBlockBookmarkNode)
|
bookmarks = graphene.List(ContentBlockBookmarkNode)
|
||||||
|
|
||||||
# contents = graphene.List(ContentNode)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ContentBlock
|
model = ContentBlock
|
||||||
only_fields = [
|
only_fields = [
|
||||||
|
|
@ -49,7 +48,7 @@ class ContentBlockNode(DjangoObjectType):
|
||||||
filter_fields = [
|
filter_fields = [
|
||||||
'slug', 'title',
|
'slug', 'title',
|
||||||
]
|
]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (ContentBlockInterface,)
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -79,6 +78,7 @@ class ContentBlockNode(DjangoObjectType):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def process_module_room_slug_block(content):
|
def process_module_room_slug_block(content):
|
||||||
if content['type'] == 'module_room_slug':
|
if content['type'] == 'module_room_slug':
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,6 @@ from surveys.schema import AnswerNode
|
||||||
|
|
||||||
|
|
||||||
class ModuleNode(DjangoObjectType):
|
class ModuleNode(DjangoObjectType):
|
||||||
chapters = DjangoFilterConnectionField(ChapterNode)
|
|
||||||
topic = graphene.Field('books.schema.nodes.TopicNode')
|
|
||||||
hero_image = graphene.String()
|
|
||||||
solutions_enabled = graphene.Boolean()
|
|
||||||
bookmark = graphene.Field(ModuleBookmarkNode)
|
|
||||||
my_submissions = DjangoFilterConnectionField(StudentSubmissionNode)
|
|
||||||
my_answers = DjangoFilterConnectionField(AnswerNode)
|
|
||||||
my_content_bookmarks = DjangoFilterConnectionField(ContentBlockBookmarkNode)
|
|
||||||
my_chapter_bookmarks = DjangoFilterConnectionField(ChapterBookmarkNode)
|
|
||||||
snapshots = graphene.List('books.schema.nodes.SnapshotNode')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Module
|
model = Module
|
||||||
only_fields = [
|
only_fields = [
|
||||||
|
|
@ -37,9 +26,16 @@ class ModuleNode(DjangoObjectType):
|
||||||
}
|
}
|
||||||
interfaces = (ModuleInterface, )
|
interfaces = (ModuleInterface, )
|
||||||
|
|
||||||
def resolve_hero_image(self, info, **kwargs):
|
|
||||||
if self.hero_image:
|
chapters = DjangoFilterConnectionField(ChapterNode)
|
||||||
return self.hero_image.file.url
|
solutions_enabled = graphene.Boolean()
|
||||||
|
bookmark = graphene.Field(ModuleBookmarkNode)
|
||||||
|
my_submissions = DjangoFilterConnectionField(StudentSubmissionNode)
|
||||||
|
my_answers = DjangoFilterConnectionField(AnswerNode)
|
||||||
|
my_content_bookmarks = DjangoFilterConnectionField(ContentBlockBookmarkNode)
|
||||||
|
my_chapter_bookmarks = DjangoFilterConnectionField(ChapterBookmarkNode)
|
||||||
|
snapshots = graphene.List('books.schema.nodes.SnapshotNode')
|
||||||
|
|
||||||
|
|
||||||
def resolve_chapters(self, info, **kwargs):
|
def resolve_chapters(self, info, **kwargs):
|
||||||
return Chapter.get_by_parent(self)
|
return Chapter.get_by_parent(self)
|
||||||
|
|
@ -88,8 +84,9 @@ class ModuleNode(DjangoObjectType):
|
||||||
return parent.objective_groups.all() \
|
return parent.objective_groups.all() \
|
||||||
.prefetch_related('hidden_for')
|
.prefetch_related('hidden_for')
|
||||||
|
|
||||||
def resolve_snapshots(self, info, **kwargs):
|
@staticmethod
|
||||||
return self.snapshots.all()
|
def resolve_snapshots(parent, info, **kwargs):
|
||||||
|
return parent.snapshots.all()
|
||||||
|
|
||||||
class RecentModuleNode(DjangoObjectType):
|
class RecentModuleNode(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,88 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphene import relay
|
from django.db.models import Q
|
||||||
|
from graphene import relay, ObjectType
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from .chapter import SnapshotChapterNode
|
|
||||||
|
from . import ChapterInSnapshotNode
|
||||||
|
|
||||||
from books.models.snapshot import Snapshot
|
from books.models.snapshot import Snapshot
|
||||||
|
from ..interfaces import ModuleInterface, ChapterInterface
|
||||||
|
from ..interfaces.contentblock import ContentBlockInterface
|
||||||
|
from ...models import Module, Chapter, ChapterSnapshot, ContentBlock
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotContentBlock:
|
||||||
|
def __init__(self, content_block, snapshot):
|
||||||
|
self.title = content_block.title
|
||||||
|
self.contents = content_block.title
|
||||||
|
self.type = content_block.type
|
||||||
|
self.hidden = snapshot.hidden_content_blocks.filter(id=content_block.id).exists()
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotChapter:
|
||||||
|
def __init__(self, chapter, snapshot, description_hidden=False, title_hidden=False):
|
||||||
|
self.title = chapter.title
|
||||||
|
self.description = chapter.description
|
||||||
|
self.title_hidden = title_hidden
|
||||||
|
self.description_hidden = description_hidden
|
||||||
|
self.content_blocks = []
|
||||||
|
base_qs = ContentBlock.get_by_parent(chapter)
|
||||||
|
without_owner = Q(owner__isnull=True)
|
||||||
|
this_snapshot = Q(contentblocksnapshot__snapshot=snapshot)
|
||||||
|
self.content_blocks = [
|
||||||
|
SnapshotContentBlock(
|
||||||
|
content_block=content_block,
|
||||||
|
snapshot=snapshot
|
||||||
|
) for content_block in
|
||||||
|
base_qs.filter(without_owner | this_snapshot)
|
||||||
|
]
|
||||||
|
# all from module without owner
|
||||||
|
# all with snapshotcontentblock with this snapshot
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotContentBlockNode(ObjectType):
|
||||||
|
class Meta:
|
||||||
|
interfaces = (ContentBlockInterface,)
|
||||||
|
|
||||||
|
hidden = graphene.Boolean()
|
||||||
|
|
||||||
|
|
||||||
|
class SnapshotChapterNode(ObjectType):
|
||||||
|
class Meta:
|
||||||
|
interfaces = (ChapterInterface,)
|
||||||
|
|
||||||
|
content_blocks = graphene.List(SnapshotContentBlockNode)
|
||||||
|
description_hidden = graphene.Boolean()
|
||||||
|
title_hidden = graphene.Boolean()
|
||||||
|
|
||||||
|
|
||||||
class SnapshotNode(DjangoObjectType):
|
class SnapshotNode(DjangoObjectType):
|
||||||
title = graphene.String()
|
title = graphene.String()
|
||||||
|
# chapters = graphene.Field(SnapshotChapterNode)
|
||||||
|
snapshot_chapters = DjangoFilterConnectionField(ChapterInSnapshotNode)
|
||||||
|
chapters = graphene.List(SnapshotChapterNode)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Snapshot
|
model = Snapshot
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
# chapters = relay.ConnectionField('books.schema.connections.ChapterSnapshotConnection')
|
@staticmethod
|
||||||
chapters = DjangoFilterConnectionField(SnapshotChapterNode)
|
def resolve_snapshot_chapters(parent, info, **kwargs):
|
||||||
|
|
||||||
def resolve_chapters(self, info, **kwargs):
|
|
||||||
# return Chapter.objects.filter(chapter_snapshots__snapshot=self)
|
# return Chapter.objects.filter(chapter_snapshots__snapshot=self)
|
||||||
return self.chapters.through.objects.all()
|
return parent.chapters.through.objects.all()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_chapters(parent, info, **kwargs):
|
||||||
|
return [
|
||||||
|
SnapshotChapter(
|
||||||
|
chapter_snapshot.chapter,
|
||||||
|
snapshot=parent,
|
||||||
|
title_hidden=chapter_snapshot.title_hidden,
|
||||||
|
description_hidden=chapter_snapshot.description_hidden
|
||||||
|
)
|
||||||
|
for chapter_snapshot in parent.chapters.through.objects.all()
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_title(parent, info, **kwargs):
|
def resolve_title(parent, info, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from core.logger import get_logger
|
from core.logger import get_logger
|
||||||
|
|
||||||
from ..models import Book, Topic, Module, Chapter
|
from ..models import Book, Topic, Module, Chapter, Snapshot
|
||||||
from .nodes import ContentBlockNode, ChapterNode, ModuleNode, TopicNode
|
from .nodes import ContentBlockNode, ChapterNode, ModuleNode, TopicNode, SnapshotNode
|
||||||
from .connections import TopicConnection, ModuleConnection
|
from .connections import TopicConnection, ModuleConnection
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
@ -18,6 +18,7 @@ class BookQuery(object):
|
||||||
module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID())
|
module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID())
|
||||||
chapter = relay.Node.Field(ChapterNode)
|
chapter = relay.Node.Field(ChapterNode)
|
||||||
content_block = relay.Node.Field(ContentBlockNode)
|
content_block = relay.Node.Field(ContentBlockNode)
|
||||||
|
snapshot = relay.Node.Field(SnapshotNode)
|
||||||
|
|
||||||
topics = relay.ConnectionField(TopicConnection)
|
topics = relay.ConnectionField(TopicConnection)
|
||||||
modules = relay.ConnectionField(ModuleConnection)
|
modules = relay.ConnectionField(ModuleConnection)
|
||||||
|
|
@ -35,6 +36,11 @@ class BookQuery(object):
|
||||||
def resolve_chapters(self, *args, **kwargs):
|
def resolve_chapters(self, *args, **kwargs):
|
||||||
return Chapter.objects.filter(**kwargs).live()
|
return Chapter.objects.filter(**kwargs).live()
|
||||||
|
|
||||||
|
def resolve_snapshot(self, info, **kwargs):
|
||||||
|
id = kwargs.get('id')
|
||||||
|
snapshot = get_object(Snapshot, id)
|
||||||
|
return snapshot
|
||||||
|
|
||||||
def resolve_module(self, info, **kwargs):
|
def resolve_module(self, info, **kwargs):
|
||||||
slug = kwargs.get('slug')
|
slug = kwargs.get('slug')
|
||||||
id = kwargs.get('id')
|
id = kwargs.get('id')
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from graphql_relay import to_global_id, from_global_id
|
||||||
|
|
||||||
from api.schema import schema
|
from api.schema import schema
|
||||||
from books.factories import ModuleFactory, ChapterFactory, ContentBlockFactory
|
from books.factories import ModuleFactory, ChapterFactory, ContentBlockFactory
|
||||||
from books.models import Snapshot
|
from books.models import Snapshot, ChapterSnapshot
|
||||||
from users.models import User, SchoolClass
|
from users.models import User, SchoolClass
|
||||||
from users.services import create_users
|
from users.services import create_users
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ mutation CreateSnapshot($input: CreateSnapshotInput!) {
|
||||||
creator {
|
creator {
|
||||||
username
|
username
|
||||||
}
|
}
|
||||||
chapters {
|
snapshotChapters {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
id
|
||||||
|
|
@ -87,6 +87,26 @@ mutation ApplySnapshot($input: ApplySnapshotInput!) {
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
SNAPSHOT_MODULE_QUERY = """
|
||||||
|
query SnapshotDetail($id: ID!) {
|
||||||
|
snapshot(id: $id) {
|
||||||
|
id
|
||||||
|
chapters {
|
||||||
|
id
|
||||||
|
description
|
||||||
|
title
|
||||||
|
titleHidden
|
||||||
|
descriptionHidden
|
||||||
|
contentBlocks {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
hidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def edges_to_array(entity):
|
def edges_to_array(entity):
|
||||||
return [edge['node'] for edge in entity.get('edges')]
|
return [edge['node'] for edge in entity.get('edges')]
|
||||||
|
|
@ -103,6 +123,7 @@ class CreateSnapshotTestCase(TestCase):
|
||||||
|
|
||||||
# module M has a chapter
|
# module M has a chapter
|
||||||
self.chapter = ChapterFactory(parent=self.module, slug='some-chapter')
|
self.chapter = ChapterFactory(parent=self.module, slug='some-chapter')
|
||||||
|
ChapterFactory(parent=self.module, slug='some-other-chapter')
|
||||||
|
|
||||||
# chapter has some content blocks a, b, c
|
# chapter has some content blocks a, b, c
|
||||||
self.title_visible = 'visible'
|
self.title_visible = 'visible'
|
||||||
|
|
@ -169,7 +190,7 @@ class CreateSnapshotTestCase(TestCase):
|
||||||
})
|
})
|
||||||
self.assertIsNone(result.get('errors'))
|
self.assertIsNone(result.get('errors'))
|
||||||
snapshot = result.get('data').get('createSnapshot').get('snapshot')
|
snapshot = result.get('data').get('createSnapshot').get('snapshot')
|
||||||
chapter = snapshot.get('chapters').get('edges')[0]['node']
|
chapter = snapshot.get('snapshotChapters').get('edges')[0]['node']
|
||||||
|
|
||||||
self.assertIsNotNone(snapshot.get('created'))
|
self.assertIsNotNone(snapshot.get('created'))
|
||||||
self.assertEqual(snapshot.get('creator').get('username'), self.teacher.username)
|
self.assertEqual(snapshot.get('creator').get('username'), self.teacher.username)
|
||||||
|
|
@ -182,6 +203,7 @@ class CreateSnapshotTestCase(TestCase):
|
||||||
self.assertEqual(len(content_blocks), 2)
|
self.assertEqual(len(content_blocks), 2)
|
||||||
self.assertEqual(content_blocks[0]['title'], self.title_visible)
|
self.assertEqual(content_blocks[0]['title'], self.title_visible)
|
||||||
self.assertEqual(content_blocks[1]['title'], self.title_custom)
|
self.assertEqual(content_blocks[1]['title'], self.title_custom)
|
||||||
|
self.assertEqual(ChapterSnapshot.objects.count(), 2)
|
||||||
|
|
||||||
def test_apply_snapshot(self):
|
def test_apply_snapshot(self):
|
||||||
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
||||||
|
|
@ -201,3 +223,23 @@ class CreateSnapshotTestCase(TestCase):
|
||||||
})
|
})
|
||||||
self.assertIsNone(result.get('errors'))
|
self.assertIsNone(result.get('errors'))
|
||||||
self._test_module_visibility(client, school_class_name)
|
self._test_module_visibility(client, school_class_name)
|
||||||
|
|
||||||
|
def test_display_snapshot_module(self):
|
||||||
|
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
||||||
|
user=self.teacher)
|
||||||
|
id = to_global_id('SnapshotNode', self.snapshot.id)
|
||||||
|
snapshot_result = self.client.execute(SNAPSHOT_MODULE_QUERY, variables={
|
||||||
|
'id': id
|
||||||
|
})
|
||||||
|
self.assertIsNone(snapshot_result.get('errors'))
|
||||||
|
snapshot = snapshot_result.get('data').get('snapshot')
|
||||||
|
chapters = snapshot.get('chapters')
|
||||||
|
self.assertEqual(len(chapters), 2)
|
||||||
|
chapter = chapters[0]
|
||||||
|
content_blocks = chapter.get('contentBlocks')
|
||||||
|
self.assertEqual(len(content_blocks), 3)
|
||||||
|
first, second, third = content_blocks
|
||||||
|
self.assertEqual(first['title'], 'visible')
|
||||||
|
self.assertEqual(second['title'], 'hidden')
|
||||||
|
self.assertEqual(second['hidden'], True)
|
||||||
|
self.assertEqual(third['title'], 'custom')
|
||||||
|
|
|
||||||
|
|
@ -218,20 +218,41 @@ type ChapterBookmarkNodeEdge {
|
||||||
cursor: String!
|
cursor: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChapterInSnapshotNode implements ChapterInterface {
|
||||||
|
id: ID!
|
||||||
|
chapter: ChapterNode!
|
||||||
|
snapshot: SnapshotNode!
|
||||||
|
titleHidden: Boolean
|
||||||
|
descriptionHidden: Boolean
|
||||||
|
description: String
|
||||||
|
title: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChapterInSnapshotNodeConnection {
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
edges: [ChapterInSnapshotNodeEdge]!
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChapterInSnapshotNodeEdge {
|
||||||
|
node: ChapterInSnapshotNode
|
||||||
|
cursor: String!
|
||||||
|
}
|
||||||
|
|
||||||
interface ChapterInterface {
|
interface ChapterInterface {
|
||||||
id: ID!
|
id: ID!
|
||||||
contentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection
|
description: String
|
||||||
|
title: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChapterNode implements ChapterInterface {
|
type ChapterNode implements ChapterInterface {
|
||||||
title: String!
|
title: String
|
||||||
slug: String!
|
slug: String!
|
||||||
description: String!
|
description: String
|
||||||
titleHiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
titleHiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
||||||
descriptionHiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
descriptionHiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
||||||
id: ID!
|
id: ID!
|
||||||
contentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection
|
|
||||||
bookmark: ChapterBookmarkNode
|
bookmark: ChapterBookmarkNode
|
||||||
|
contentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChapterNodeConnection {
|
type ChapterNodeConnection {
|
||||||
|
|
@ -278,14 +299,21 @@ input ContentBlockInput {
|
||||||
visibility: [UserGroupBlockVisibility]
|
visibility: [UserGroupBlockVisibility]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContentBlockNode implements Node {
|
interface ContentBlockInterface {
|
||||||
title: String!
|
id: ID!
|
||||||
|
title: String
|
||||||
|
contents: GenericStreamFieldType
|
||||||
|
type: ContentBlockType
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContentBlockNode implements ContentBlockInterface {
|
||||||
|
title: String
|
||||||
slug: String!
|
slug: String!
|
||||||
hiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
hiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
||||||
visibleFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
visibleFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
|
||||||
userCreated: Boolean!
|
userCreated: Boolean!
|
||||||
contents: GenericStreamFieldType
|
contents: GenericStreamFieldType
|
||||||
type: ContentBlockType!
|
type: ContentBlockType
|
||||||
id: ID!
|
id: ID!
|
||||||
mine: Boolean
|
mine: Boolean
|
||||||
bookmarks: [ContentBlockBookmarkNode]
|
bookmarks: [ContentBlockBookmarkNode]
|
||||||
|
|
@ -438,6 +466,7 @@ type CustomQuery {
|
||||||
module(slug: String, id: ID): ModuleNode
|
module(slug: String, id: ID): ModuleNode
|
||||||
chapter(id: ID!): ChapterNode
|
chapter(id: ID!): ChapterNode
|
||||||
contentBlock(id: ID!): ContentBlockNode
|
contentBlock(id: ID!): ContentBlockNode
|
||||||
|
snapshot(id: ID!): SnapshotNode
|
||||||
topics(before: String, after: String, first: Int, last: Int): TopicConnection
|
topics(before: String, after: String, first: Int, last: Int): TopicConnection
|
||||||
modules(before: String, after: String, first: Int, last: Int): ModuleConnection
|
modules(before: String, after: String, first: Int, last: Int): ModuleConnection
|
||||||
chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection
|
chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection
|
||||||
|
|
@ -638,6 +667,8 @@ type ModuleEdge {
|
||||||
interface ModuleInterface {
|
interface ModuleInterface {
|
||||||
id: ID!
|
id: ID!
|
||||||
pk: Int
|
pk: Int
|
||||||
|
heroImage: String
|
||||||
|
topic: TopicNode
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleNode implements ModuleInterface {
|
type ModuleNode implements ModuleInterface {
|
||||||
|
|
@ -651,8 +682,8 @@ type ModuleNode implements ModuleInterface {
|
||||||
objectiveGroups(offset: Int, before: String, after: String, first: Int, last: Int, title: String, module_Slug: String): ObjectiveGroupNodeConnection!
|
objectiveGroups(offset: Int, before: String, after: String, first: Int, last: Int, title: String, module_Slug: String): ObjectiveGroupNodeConnection!
|
||||||
id: ID!
|
id: ID!
|
||||||
pk: Int
|
pk: Int
|
||||||
chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection
|
|
||||||
topic: TopicNode
|
topic: TopicNode
|
||||||
|
chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection
|
||||||
solutionsEnabled: Boolean
|
solutionsEnabled: Boolean
|
||||||
bookmark: ModuleBookmarkNode
|
bookmark: ModuleBookmarkNode
|
||||||
mySubmissions(offset: Int, before: String, after: String, first: Int, last: Int): StudentSubmissionNodeConnection
|
mySubmissions(offset: Int, before: String, after: String, first: Int, last: Int): StudentSubmissionNodeConnection
|
||||||
|
|
@ -882,34 +913,31 @@ type SchoolClassNodeEdge {
|
||||||
|
|
||||||
type SnapshotChapterNode implements ChapterInterface {
|
type SnapshotChapterNode implements ChapterInterface {
|
||||||
id: ID!
|
id: ID!
|
||||||
chapter: ChapterNode!
|
|
||||||
snapshot: SnapshotNode!
|
|
||||||
titleHidden: Boolean
|
|
||||||
descriptionHidden: Boolean
|
|
||||||
contentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection
|
|
||||||
title: String
|
|
||||||
description: String
|
description: String
|
||||||
|
title: String
|
||||||
|
contentBlocks: [SnapshotContentBlockNode]
|
||||||
|
descriptionHidden: Boolean
|
||||||
|
titleHidden: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type SnapshotChapterNodeConnection {
|
type SnapshotContentBlockNode implements ContentBlockInterface {
|
||||||
pageInfo: PageInfo!
|
id: ID!
|
||||||
edges: [SnapshotChapterNodeEdge]!
|
title: String
|
||||||
}
|
contents: GenericStreamFieldType
|
||||||
|
type: ContentBlockType
|
||||||
type SnapshotChapterNodeEdge {
|
hidden: Boolean
|
||||||
node: SnapshotChapterNode
|
|
||||||
cursor: String!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SnapshotNode implements Node {
|
type SnapshotNode implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
module: ModuleNode!
|
module: ModuleNode!
|
||||||
chapters(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): SnapshotChapterNodeConnection
|
chapters: [SnapshotChapterNode]
|
||||||
hiddenContentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection!
|
hiddenContentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection!
|
||||||
created: DateTime!
|
created: DateTime!
|
||||||
creator: UserNode
|
creator: UserNode
|
||||||
chapterSnapshots(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): SnapshotChapterNodeConnection!
|
chapterSnapshots(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): ChapterInSnapshotNodeConnection!
|
||||||
title: String
|
title: String
|
||||||
|
snapshotChapters(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): ChapterInSnapshotNodeConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
input SpellCheckInput {
|
input SpellCheckInput {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue