Display snapshot module detail

This commit is contained in:
Ramon Wenger 2021-05-05 00:18:53 +02:00
parent ca549e93e5
commit 70e7dc39a9
9 changed files with 184 additions and 166 deletions

View File

@ -55,154 +55,160 @@
</template>
<script>
import ContentBlock from '@/components/ContentBlock';
import AddContentButton from '@/components/AddContentButton';
import BookmarkActions from '@/components/notes/BookmarkActions';
import VisibilityAction from '@/components/visibility/VisibilityAction';
import ContentBlock from '@/components/ContentBlock';
import AddContentButton from '@/components/AddContentButton';
import BookmarkActions from '@/components/notes/BookmarkActions';
import VisibilityAction from '@/components/visibility/VisibilityAction';
import {mapState} from 'vuex';
import {hidden} from '@/helpers/visibility';
import {CONTENT_TYPE, CHAPTER_DESCRIPTION_TYPE, CHAPTER_TITLE_TYPE} from '@/consts/types';
import {mapState} from 'vuex';
import {hidden} from '@/helpers/visibility';
import {CHAPTER_DESCRIPTION_TYPE, CHAPTER_TITLE_TYPE, CONTENT_TYPE} from '@/consts/types';
import UPDATE_CHAPTER_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateChapterBookmark.gql';
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
import UPDATE_CHAPTER_BOOKMARK_MUTATION from '@/graphql/gql/mutations/updateChapterBookmark.gql';
import CHAPTER_QUERY from '@/graphql/gql/queries/chapterQuery.gql';
import me from '@/mixins/me';
import me from '@/mixins/me';
export default {
props: ['chapter', 'index'],
export default {
props: ['chapter', 'index'],
mixins: [me],
mixins: [me],
components: {
BookmarkActions,
VisibilityAction,
ContentBlock,
AddContentButton
},
computed: {
...mapState(['editModule']),
filteredContentBlocks() {
if (!(this.chapter && this.chapter.contentBlocks)) {
return [];
}
if (this.editModule) {
return this.chapter.contentBlocks;
}
return this.chapter.contentBlocks.filter(contentBlock => !hidden({
block: contentBlock,
schoolClass: this.schoolClass,
type: CONTENT_TYPE
}));
components: {
BookmarkActions,
VisibilityAction,
ContentBlock,
AddContentButton,
},
note() {
if (this.chapter && this.chapter.bookmark) {
return this.chapter.bookmark.note;
}
},
titleGreyedOut() {
return this.textHidden(CHAPTER_TITLE_TYPE) && this.editModule;
},
// never hidden when editing the module
titleHidden() {
return this.textHidden(CHAPTER_TITLE_TYPE) && !this.editModule;
},
descriptionGreyedOut() {
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && this.editModule;
},
// never hidden when editing the module
descriptionHidden() {
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && !this.editModule;
}
},
methods: {
bookmark(bookmarked) {
const id = this.chapter.id;
this.$apollo.mutate({
mutation: UPDATE_CHAPTER_BOOKMARK_MUTATION,
variables: {
input: {
chapter: id,
bookmarked
}
},
update: (store, response) => {
const query = CHAPTER_QUERY;
const variables = {id};
const data = store.readQuery({
query,
variables
});
const chapter = data.chapter;
if (bookmarked) {
chapter.bookmark = {
__typename: 'ChapterBookmarkNode',
note: null
};
} else {
chapter.bookmark = null;
}
data.chapter = chapter;
store.writeQuery({
data,
query,
variables
});
},
optimisticResponse: {
__typename: 'Mutation',
updateChapterBookmark: {
__typename: 'UpdateChapterBookmarkPayload',
success: true
}
computed: {
...mapState(['editModule']),
filteredContentBlocks() {
if (!(this.chapter && this.chapter.contentBlocks)) {
return [];
}
});
if (this.editModule) {
return this.chapter.contentBlocks;
}
return this.chapter.contentBlocks.filter(contentBlock => !hidden({
block: contentBlock,
schoolClass: this.schoolClass,
type: CONTENT_TYPE,
}));
},
note() {
if (this.chapter && this.chapter.bookmark) {
return this.chapter.bookmark.note;
}
},
titleGreyedOut() {
return this.textHidden(CHAPTER_TITLE_TYPE) && this.editModule;
},
// never hidden when editing the module
titleHidden() {
if (this.chapter.titleHidden === true) {
return true;
}
return this.textHidden(CHAPTER_TITLE_TYPE) && !this.editModule;
},
descriptionGreyedOut() {
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && this.editModule;
},
// never hidden when editing the module
descriptionHidden() {
if (this.chapter.descriptionHidden === true) {
return true;
}
return this.textHidden(CHAPTER_DESCRIPTION_TYPE) && !this.editModule;
},
},
addNote(id) {
this.$store.dispatch('addNote', {
content: id,
parent: this.chapter.id
});
},
editNote() {
this.$store.dispatch('editNote', this.chapter.bookmark.note);
},
textHidden(type) {
return hidden({
block: this.chapter,
schoolClass: this.schoolClass,
type
});
}
},
};
methods: {
bookmark(bookmarked) {
const id = this.chapter.id;
this.$apollo.mutate({
mutation: UPDATE_CHAPTER_BOOKMARK_MUTATION,
variables: {
input: {
chapter: id,
bookmarked,
},
},
update: (store, response) => {
const query = CHAPTER_QUERY;
const variables = {id};
const data = store.readQuery({
query,
variables,
});
const chapter = data.chapter;
if (bookmarked) {
chapter.bookmark = {
__typename: 'ChapterBookmarkNode',
note: null,
};
} else {
chapter.bookmark = null;
}
data.chapter = chapter;
store.writeQuery({
data,
query,
variables,
});
},
optimisticResponse: {
__typename: 'Mutation',
updateChapterBookmark: {
__typename: 'UpdateChapterBookmarkPayload',
success: true,
},
},
});
},
addNote(id) {
this.$store.dispatch('addNote', {
content: id,
parent: this.chapter.id,
});
},
editNote() {
this.$store.dispatch('editNote', this.chapter.bookmark.note);
},
textHidden(type) {
return hidden({
block: this.chapter,
schoolClass: this.schoolClass,
type,
});
},
},
};
</script>
<style scoped lang="scss">
@import "@/styles/_mixins.scss";
@import "@/styles/_mixins.scss";
.chapter {
position: relative;
&__bookmark-actions {
margin-top: 3px;
}
&__intro {
.chapter {
position: relative;
}
&__description {
@include lead-paragraph;
&__bookmark-actions {
margin-top: 3px;
}
margin-bottom: $large-spacing;
&__intro {
position: relative;
}
&__description {
@include lead-paragraph;
margin-bottom: $large-spacing;
}
}
}
</style>

View File

@ -70,10 +70,14 @@ export const hidden = ({
visibleFor,
hiddenFor,
titleHiddenFor,
descriptionHiddenFor
descriptionHiddenFor,
hidden
},
schoolClass
}) => {
if (hidden === true) {
return true;
}
switch (type) {
case CONTENT_TYPE:
case OBJECTIVE_TYPE:

View File

@ -1,9 +1,5 @@
<template>
<div>
Hello
{{ id }}
<module :module="snapshot" />
</div>
<module :module="snapshot"/>
</template>
<script>
@ -20,7 +16,7 @@
},
components: {
Module
Module,
},
apollo: {
@ -28,9 +24,9 @@
query: SNAPSHOT_DETAIL_QUERY,
variables() {
return {
id: this.id
id: this.id,
};
}
},
},
},

View File

@ -8,3 +8,7 @@ class ContentBlockInterface(relay.Node):
title = graphene.String()
contents = GenericStreamFieldType()
type = graphene.String()
@staticmethod
def resolve_type(parent, info, **kwargs):
return parent.type

View File

@ -4,7 +4,7 @@ from graphene import relay
class ModuleInterface(relay.Node):
pk = graphene.Int()
hero_image = graphene.String()
hero_image = graphene.String(required=True)
topic = graphene.Field('books.schema.nodes.TopicNode')
@staticmethod

View File

@ -1,16 +1,14 @@
import graphene
from graphene import relay, ObjectType
from graphene_django import DjangoObjectType
from books.models import ContentBlock
from books.schema.interfaces.contentblock import ContentBlockInterface
from books.utils import are_solutions_enabled_for
from core.logger import get_logger
from notes.models import ContentBlockBookmark
from notes.schema import ContentBlockBookmarkNode
from rooms.models import ModuleRoomSlug
from core.logger import get_logger
logger = get_logger(__name__)
@ -39,6 +37,8 @@ def is_solution_and_hidden_for_user(type, user, module):
class ContentBlockNode(DjangoObjectType):
mine = graphene.Boolean()
bookmarks = graphene.List(ContentBlockBookmarkNode)
hidden_for = graphene.List('users.schema.SchoolClassNode')
visible_for = graphene.List('users.schema.SchoolClassNode')
class Meta:
model = ContentBlock
@ -54,10 +54,6 @@ class ContentBlockNode(DjangoObjectType):
def resolve_mine(parent, info, **kwargs):
return parent.owner is not None and parent.owner.pk == info.context.user.pk
@staticmethod
def resolve_type(parent, info, **kwargs):
return parent.type
def resolve_contents(self, info, **kwargs):
updated_stream_data = []
for content in self.contents.stream_data:
@ -82,6 +78,11 @@ class ContentBlockNode(DjangoObjectType):
content_block=self
)
def resolve_hidden_for(parent, info, **kwargs):
return parent.hidden_for.all()
def resolve_visible_for(parent, info, **kwargs):
return parent.visible_for.all()
def process_module_room_slug_block(content):

View File

@ -24,8 +24,7 @@ class ModuleNode(DjangoObjectType):
'slug': ['exact', 'icontains', 'in'],
'title': ['exact', 'icontains', 'in'],
}
interfaces = (ModuleInterface, )
interfaces = (ModuleInterface,)
chapters = DjangoFilterConnectionField(ChapterNode)
solutions_enabled = graphene.Boolean()
@ -36,7 +35,6 @@ class ModuleNode(DjangoObjectType):
my_chapter_bookmarks = DjangoFilterConnectionField(ChapterBookmarkNode)
snapshots = graphene.List('books.schema.nodes.SnapshotNode')
def resolve_chapters(self, info, **kwargs):
return Chapter.get_by_parent(self)
@ -88,6 +86,7 @@ class ModuleNode(DjangoObjectType):
def resolve_snapshots(parent, info, **kwargs):
return parent.snapshots.all()
class RecentModuleNode(DjangoObjectType):
class Meta:
model = RecentModule

View File

@ -17,7 +17,7 @@ class SnapshotContentBlock:
self.id = content_block.id
self.pk = content_block.pk
self.title = content_block.title
self.contents = content_block.title
self.contents = content_block.contents
self.type = content_block.type
self.hidden = snapshot.hidden_content_blocks.filter(id=content_block.id).exists()
@ -61,21 +61,18 @@ class SnapshotChapterNode(ObjectType):
title_hidden = graphene.Boolean()
class SnapshotNode(DjangoObjectType):
title = graphene.String()
# chapters = graphene.Field(SnapshotChapterNode)
snapshot_chapters = DjangoFilterConnectionField(ChapterInSnapshotNode)
chapters = graphene.List(SnapshotChapterNode)
meta_title = graphene.String()
hero_image = graphene.String()
class Meta:
model = Snapshot
interfaces = (relay.Node,)
@staticmethod
def resolve_snapshot_chapters(parent, info, **kwargs):
# return Chapter.objects.filter(chapter_snapshots__snapshot=self)
return parent.chapters.through.objects.all()
@staticmethod
def resolve_chapters(parent, info, **kwargs):
return [
@ -85,9 +82,19 @@ class SnapshotNode(DjangoObjectType):
title_hidden=chapter_snapshot.title_hidden,
description_hidden=chapter_snapshot.description_hidden
)
for chapter_snapshot in parent.chapters.through.objects.all()
for chapter_snapshot in parent.chapters.through.objects.filter(snapshot=parent)
]
@staticmethod
def resolve_title(parent, info, **kwargs):
return parent.__str__()
@staticmethod
def resolve_meta_title(parent, info, **kwargs):
return parent.module.meta_title
@staticmethod
def resolve_hero_image(parent, info, **kwargs):
if parent.module.hero_image:
return parent.module.hero_image.file.url
return ''

View File

@ -252,7 +252,7 @@ type ChapterNode implements ChapterInterface {
descriptionHiddenFor(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection!
id: ID!
bookmark: ChapterBookmarkNode
contentBlocks(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ContentBlockNodeConnection
contentBlocks: [ContentBlockNode]
}
type ChapterNodeConnection {
@ -309,8 +309,8 @@ interface ContentBlockInterface {
type ContentBlockNode implements ContentBlockInterface {
title: String
slug: String!
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!
hiddenFor: [SchoolClassNode]
visibleFor: [SchoolClassNode]
userCreated: Boolean!
contents: GenericStreamFieldType
type: String
@ -659,7 +659,7 @@ type ModuleEdge {
interface ModuleInterface {
id: ID!
pk: Int
heroImage: String
heroImage: String!
topic: TopicNode
}
@ -667,7 +667,7 @@ type ModuleNode implements ModuleInterface {
title: String!
slug: String!
metaTitle: String!
heroImage: String
heroImage: String!
teaser: String!
intro: String!
assignments(offset: Int, before: String, after: String, first: Int, last: Int): AssignmentNodeConnection!
@ -929,7 +929,8 @@ type SnapshotNode implements Node {
creator: UserNode
chapterSnapshots(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): ChapterInSnapshotNodeConnection!
title: String
snapshotChapters(offset: Int, before: String, after: String, first: Int, last: Int, id: ID): ChapterInSnapshotNodeConnection
metaTitle: String
heroImage: String
}
input SpellCheckInput {