Enable scrolling to the content blocks in a module
This commit is contained in:
parent
65a09fb9c7
commit
9fb8e13c1c
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="chapter">
|
<div class="chapter" :data-scrollto="chapter.id">
|
||||||
<h3 :id="'chapter-' + index">{{chapter.title}}</h3>
|
<h3 :id="'chapter-' + index">{{chapter.title}}</h3>
|
||||||
|
|
||||||
<bookmark-actions
|
<bookmark-actions
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="content-component" :class="{'content-component--bookmarked': bookmarked}">
|
<div class="content-component"
|
||||||
|
:class="{'content-component--bookmarked': bookmarked}"
|
||||||
|
:data-scrollto="component.id">
|
||||||
<bookmark-actions
|
<bookmark-actions
|
||||||
v-if="showBookmarkActions"
|
v-if="showBookmarkActions"
|
||||||
@add-note="addNote(component.id)"
|
@add-note="addNote(component.id)"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="survey-block">
|
<div class="survey-block" :data-scrollto="value.id">
|
||||||
<router-link class="button button--primary"
|
<router-link class="button button--primary"
|
||||||
:to="{name: 'survey', params: {id:value.id}}">Übung anzeigen
|
:to="{name: 'survey', params: {id:value.id}}">Übung anzeigen
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="assignment" :data-scrollto="assignment.id">
|
<div class="assignment" :data-scrollto="value.id">
|
||||||
<p class="assignment__assignment-text">
|
<p class="assignment__assignment-text">
|
||||||
{{assignment.assignment}}
|
{{assignment.assignment}}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="module-activity__entry module-activity-entry"
|
<div class="module-activity__entry module-activity-entry"
|
||||||
v-for="submission in module.mySubmissions"
|
v-for="submission in module.mySubmissions"
|
||||||
:key="submission.id"
|
:key="submission.id"
|
||||||
@click="goToAssignment(submission.assignment.id)">
|
@click="goTo(submission.assignment.id)">
|
||||||
<h3 class="module-activity-entry__title">Aufgabe & Ergebnis</h3>
|
<h3 class="module-activity-entry__title">Aufgabe & Ergebnis</h3>
|
||||||
<p class="module-activity-entry__text">
|
<p class="module-activity-entry__text">
|
||||||
{{submission.text}}
|
{{submission.text}}
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="module-activity__entry module-activity-entry"
|
<div class="module-activity__entry module-activity-entry"
|
||||||
v-for="answer in module.myAnswers"
|
v-for="answer in module.myAnswers"
|
||||||
:key="answer.id">
|
:key="answer.id"
|
||||||
|
@click="goTo(answer.survey.id)">
|
||||||
<h3 class="module-activity-entry__title">Übung</h3>
|
<h3 class="module-activity-entry__title">Übung</h3>
|
||||||
<p class="module-activity-entry__text">
|
<p class="module-activity-entry__text">
|
||||||
{{answer.survey.title}}
|
{{answer.survey.title}}
|
||||||
|
|
@ -23,12 +24,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="module-activity__entry"
|
<div class="module-activity__entry"
|
||||||
v-for="bookmark in module.myContentBookmarks"
|
v-for="bookmark in module.myContentBookmarks"
|
||||||
:key="bookmark.id">
|
:key="bookmark.id"
|
||||||
|
@click="goTo(bookmark.uuid)">
|
||||||
<content-bookmark :bookmark="bookmark"></content-bookmark>
|
<content-bookmark :bookmark="bookmark"></content-bookmark>
|
||||||
</div>
|
</div>
|
||||||
<div class="module-activity__entry"
|
<div class="module-activity__entry"
|
||||||
v-for="bookmark in module.myChapterBookmarks"
|
v-for="bookmark in module.myChapterBookmarks"
|
||||||
:key="bookmark.id">
|
:key="bookmark.id"
|
||||||
|
@click="goTo(bookmark.chapter.id)">
|
||||||
<h3 class="module-activity-entry__title">Lesezeichen</h3>
|
<h3 class="module-activity-entry__title">Lesezeichen</h3>
|
||||||
<p class="module-activity-entry__text">
|
<p class="module-activity-entry__text">
|
||||||
{{bookmark.chapter.description}}
|
{{bookmark.chapter.description}}
|
||||||
|
|
@ -51,6 +54,8 @@
|
||||||
import {mapActions} from 'vuex'
|
import {mapActions} from 'vuex'
|
||||||
import ContentBookmark from '@/components/profile/ContentBookmark';
|
import ContentBookmark from '@/components/profile/ContentBookmark';
|
||||||
|
|
||||||
|
import SCROLL_TO_MUTATION from '@/graphql/gql/local/mutations/scrollTo.gql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['module'],
|
props: ['module'],
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -74,9 +79,14 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['scrollToAssignmentId']),
|
...mapActions(['scrollToAssignmentId']),
|
||||||
goToAssignment(id) {
|
goTo(scrollTo) {
|
||||||
const url = `/module/${this.module.slug}/`;
|
const url = `/module/${this.module.slug}/`;
|
||||||
this.scrollToAssignmentId(id);
|
this.$apollo.mutate({
|
||||||
|
mutation: SCROLL_TO_MUTATION,
|
||||||
|
variables: {
|
||||||
|
scrollTo
|
||||||
|
}
|
||||||
|
});
|
||||||
this.$router.push(url);
|
this.$router.push(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
mutation($scrollTo: String!) {
|
||||||
|
scrollTo(scrollTo: $scrollTo) @client
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
query ScrollPosition {
|
||||||
|
scrollPosition @client {
|
||||||
|
scrollTo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,9 +3,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters, mapActions } from 'vuex'
|
import {mapGetters, mapActions} from 'vuex'
|
||||||
import ASSIGNMENTS_QUERY from '@/graphql/gql/assignmentsQuery.gql';
|
import ASSIGNMENTS_QUERY from '@/graphql/gql/assignmentsQuery.gql';
|
||||||
import {moduleQuery} from '@/graphql/queries';
|
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
|
||||||
|
|
||||||
|
import SCROLL_POSITION from '@/graphql/gql/local/scrollPosition.gql';
|
||||||
|
import SCROLL_TO_MUTATION from '@/graphql/gql/local/mutations/scrollTo.gql';
|
||||||
|
|
||||||
import Module from '@/components/modules/Module.vue';
|
import Module from '@/components/modules/Module.vue';
|
||||||
|
|
||||||
|
|
@ -16,23 +19,65 @@
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
...mapActions(['scrollToAssignmentReady', 'scrollingToAssignment']),
|
...mapActions(['scrollToAssignmentReady', 'scrollingToAssignment']),
|
||||||
|
scrollTo() {
|
||||||
|
if (this.scrollPosition && this.scrollPosition.scrollTo) {
|
||||||
|
let options = {
|
||||||
|
container: 'body',
|
||||||
|
easing: 'ease',
|
||||||
|
offset: -60,
|
||||||
|
onStart: (element) => {
|
||||||
|
},
|
||||||
|
onDone: (element) => {
|
||||||
|
},
|
||||||
|
onCancel: function () {
|
||||||
|
// scrolling has been interrupted
|
||||||
|
},
|
||||||
|
x: false,
|
||||||
|
y: true
|
||||||
|
};
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$scrollTo(`[data-scrollto="${this.scrollPosition.scrollTo}"]`, 1000, options);
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: SCROLL_TO_MUTATION,
|
||||||
|
variables: {
|
||||||
|
scrollTo: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 250); // unfortunately this timeout is needed as it is hard to tell when everything is rendered
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
scrollToAssignmentId: 'scrollToAssignmentId',
|
editModule: 'editModule'
|
||||||
isScrollingToAssignment: 'scrollingToAssignment',
|
}),
|
||||||
editModule: 'editModule'
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
module: moduleQuery,
|
module() {
|
||||||
|
return {
|
||||||
|
query: MODULE_DETAILS_QUERY,
|
||||||
|
variables: {
|
||||||
|
slug: this.$route.params.slug
|
||||||
|
},
|
||||||
|
update(data) {
|
||||||
|
return this.$getRidOfEdges(data).module || {};
|
||||||
|
},
|
||||||
|
result() {
|
||||||
|
// scroll only after the module has been loaded completely
|
||||||
|
this.scrollTo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
assignments() {
|
assignments() {
|
||||||
return {
|
return {
|
||||||
query: ASSIGNMENTS_QUERY
|
query: ASSIGNMENTS_QUERY
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
scrollPosition: {
|
||||||
|
query: SCROLL_POSITION
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -41,34 +86,5 @@
|
||||||
assignments: []
|
assignments: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
|
||||||
this.$store.subscribe((mutation, state) => {
|
|
||||||
if (mutation.type === 'setScrollToAssignmentReady' && mutation.payload && !this.isScrollingToAssignment) {
|
|
||||||
this.scrollingToAssignment(true);
|
|
||||||
let options = {
|
|
||||||
container: 'body',
|
|
||||||
easing: 'ease',
|
|
||||||
offset: -60,
|
|
||||||
onStart: (element) => {
|
|
||||||
},
|
|
||||||
onDone: (element) => {
|
|
||||||
this.scrollToAssignmentReady(false);
|
|
||||||
this.scrollingToAssignment(false);
|
|
||||||
},
|
|
||||||
onCancel: function() {
|
|
||||||
// scrolling has been interrupted
|
|
||||||
},
|
|
||||||
x: false,
|
|
||||||
y: true
|
|
||||||
};
|
|
||||||
setTimeout(() => {
|
|
||||||
this.$scrollTo(`[data-scrollto="${this.scrollToAssignmentId}"]`, 1000, options);
|
|
||||||
}, 250) // unfortunately this timeout is needed as it is hard to tell when everything is rendered
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
beforeDestroy () {
|
|
||||||
this.scrollToAssignmentReady(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -225,34 +225,35 @@ class BookNode(DjangoObjectType):
|
||||||
return Topic.get_by_parent(self)
|
return Topic.get_by_parent(self)
|
||||||
|
|
||||||
|
|
||||||
class FilteredChapterNode(DjangoObjectType):
|
# todo: do we need this?
|
||||||
content_blocks = DjangoFilterConnectionField(ContentBlockNode)
|
# class FilteredChapterNode(DjangoObjectType):
|
||||||
|
# content_blocks = DjangoFilterConnectionField(ContentBlockNode)
|
||||||
class Meta:
|
#
|
||||||
model = Chapter
|
# class Meta:
|
||||||
only_fields = [
|
# model = Chapter
|
||||||
'slug', 'title', 'description',
|
# only_fields = [
|
||||||
]
|
# 'slug', 'title', 'description',
|
||||||
filter_fields = [
|
# ]
|
||||||
'slug', 'title',
|
# filter_fields = [
|
||||||
]
|
# 'slug', 'title',
|
||||||
interfaces = (relay.Node,)
|
# ]
|
||||||
|
# interfaces = (relay.Node,)
|
||||||
def resolve_content_blocks(self, *args, **kwargs):
|
#
|
||||||
return ContentBlock.get_by_parent(self)
|
# def resolve_content_blocks(self, *args, **kwargs):
|
||||||
|
# return ContentBlock.get_by_parent(self)
|
||||||
|
|
||||||
|
|
||||||
class BookQuery(object):
|
class BookQuery(object):
|
||||||
book = relay.Node.Field(BookNode)
|
book = relay.Node.Field(BookNode)
|
||||||
topic = graphene.Field(TopicNode, slug=graphene.String())
|
topic = graphene.Field(TopicNode, slug=graphene.String())
|
||||||
module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID())
|
module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID())
|
||||||
chapter = relay.Node.Field(FilteredChapterNode)
|
chapter = relay.Node.Field(ChapterNode)
|
||||||
content_block = relay.Node.Field(ContentBlockNode)
|
content_block = relay.Node.Field(ContentBlockNode)
|
||||||
|
|
||||||
books = DjangoFilterConnectionField(BookNode)
|
books = DjangoFilterConnectionField(BookNode)
|
||||||
topics = DjangoFilterConnectionField(TopicNode)
|
topics = DjangoFilterConnectionField(TopicNode)
|
||||||
modules = DjangoFilterConnectionField(ModuleNode)
|
modules = DjangoFilterConnectionField(ModuleNode)
|
||||||
chapters = DjangoFilterConnectionField(FilteredChapterNode)
|
chapters = DjangoFilterConnectionField(ChapterNode)
|
||||||
|
|
||||||
def resolve_books(self, *args, **kwargs):
|
def resolve_books(self, *args, **kwargs):
|
||||||
return Book.objects.filter(**kwargs).live()
|
return Book.objects.filter(**kwargs).live()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue