use activity data in frontent
This commit is contained in:
parent
fa98141f3c
commit
59d88d5143
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div :class="{'no-scroll': showModal || showMobileNavigation}" class="app">
|
||||
<div :class="{'no-scroll': showModal || showMobileNavigation}" class="app" id="app">
|
||||
<component :is="showModal" v-if="showModal"></component>
|
||||
<component :is="layout"></component>
|
||||
<mobile-navigation v-if="showMobileNavigation"></mobile-navigation>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<router-link to="/me">
|
||||
<router-link to="/me/activity">
|
||||
<div class="user-widget" :class="{'user-widget--is-profile': isProfile}">
|
||||
<user-icon class="user-widget__avatar" :src="avatar"></user-icon>
|
||||
<span class="user-widget__name">{{firstName}} {{lastName}}</span>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="assignment">
|
||||
<h3 class="assignment__title">{{assignment.title}}</h3>
|
||||
<h3 class="assignment__title" :id="assignment.id.replace(/=/g, '')">{{assignment.title}}</h3>
|
||||
<p class="assignment__assignment-text">
|
||||
{{assignment.assignment}}
|
||||
</p>
|
||||
|
|
@ -67,6 +67,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex';
|
||||
import ASSIGNMENT_QUERY from '@/graphql/gql/assignmentQuery.gql';
|
||||
import ME_QUERY from '@/graphql/gql/meQuery.gql';
|
||||
import UPDATE_ASSIGNMENT_MUTATION from '@/graphql/gql/mutations/updateAssignmentMutation.gql';
|
||||
|
|
@ -92,6 +93,7 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['scrollToAssignmentId']),
|
||||
final() {
|
||||
return !!this.submission && this.submission.final
|
||||
},
|
||||
|
|
@ -109,6 +111,7 @@
|
|||
},
|
||||
|
||||
methods: {
|
||||
...mapActions(['scrollToAssignmentReady']),
|
||||
_save: debounce(function (submission) {
|
||||
this.saving++;
|
||||
this.$apollo.mutate({
|
||||
|
|
@ -196,6 +199,9 @@
|
|||
result({data}) {
|
||||
this.assignment = cloneDeep(data.assignment);
|
||||
this.assignment.submission = Object.assign(this.initialSubmission(), this.assignment.submission);
|
||||
if (this.assignment.id === this.scrollToAssignmentId) {
|
||||
this.$nextTick(() => this.scrollToAssignmentReady(true));
|
||||
}
|
||||
}
|
||||
},
|
||||
me: {
|
||||
|
|
|
|||
|
|
@ -1,34 +1,14 @@
|
|||
<template>
|
||||
<div class="module-activity">
|
||||
<h3 class="module-activity__module-name">Geld und Kauf - Modul 9</h3>
|
||||
<h2 class="module-activity__title">Ökololololologie</h2>
|
||||
<h3 class="module-activity__module-name">{{moduleTitle}}</h3>
|
||||
<h2 class="module-activity__title">{{title}}</h2>
|
||||
<div class="module-activity__tasks activity-tasks">
|
||||
<h4 class="activity-tasks__title">Aufträge</h4>
|
||||
<ol class="activity-tasks__task-list task-list">
|
||||
<li class="task-list__item task-item">
|
||||
<h5 class="task-item__title">Auftrag x, Begründung</h5>
|
||||
<p class="task-item__submission">"eine Antwrotasdfasdfasdf"</p>
|
||||
</li>
|
||||
<li class="task-list__item task-item">
|
||||
<h5 class="task-item__title">Auftrag x, Begründung</h5>
|
||||
<p class="task-item__submission">"eine Antwrotasdfasdfasdf"</p>
|
||||
</li>
|
||||
<li class="task-list__item task-item">
|
||||
<h5 class="task-item__title">Auftrag x, Begründung</h5>
|
||||
<p class="task-item__submission">"eine Antwrotasdfasdfasdf"</p>
|
||||
</li>
|
||||
<li class="task-list__item task-item">
|
||||
<h5 class="task-item__title">Auftrag x, Begründung</h5>
|
||||
<p class="task-item__submission">"eine Antwrotasdfasdfasdf"</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="module-activity__tasks activity-tasks">
|
||||
<h4 class="activity-tasks__title activity-tasks__title--alternative">Basiswissen</h4>
|
||||
<ol class="activity-tasks__task-list task-list">
|
||||
<li class="task-list__item task-item">
|
||||
<h5 class="task-item__title">Auftrag x, Begründung</h5>:
|
||||
<p class="task-item__submission">"eine Antwrotasdfasdfasdf"</p>
|
||||
<li v-for="activity in activities" :key="activity.key" class="task-list__item task-item">
|
||||
<h5 class="task-item__title">{{activity.assignmentTitle}}</h5>
|
||||
<p class="task-item__submission">{{activity.answer}}</p>
|
||||
<a href="#" @click="goToAssignment(activity)"><chevron-right class="task-item__chevron"></chevron-right></a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
|
@ -37,7 +17,25 @@
|
|||
|
||||
<script>
|
||||
|
||||
import { mapActions } from 'vuex'
|
||||
import ChevronRight from '@/components/icons/ChevronRight';
|
||||
|
||||
export default {
|
||||
props: ['metaTitle', 'title', 'activities', 'topic', 'slug'],
|
||||
components: {ChevronRight},
|
||||
computed: {
|
||||
moduleTitle () {
|
||||
return `${this.topic.title} - ${this.metaTitle}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['scrollToAssignmentId']),
|
||||
goToAssignment (activity) {
|
||||
const url = `/module/${this.slug}/`;
|
||||
this.scrollToAssignmentId(activity.assignmentId);
|
||||
this.$router.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -70,7 +68,9 @@
|
|||
.task-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-left: $medium-spacing;
|
||||
justify-content: space-between;
|
||||
|
||||
$line-height: 50px;
|
||||
|
||||
&__title {
|
||||
&::after {
|
||||
|
|
@ -79,9 +79,23 @@
|
|||
margin-right: $medium-spacing;
|
||||
}
|
||||
|
||||
&__submission {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__title, &__submission {
|
||||
line-height: 50px;
|
||||
height: 50px;
|
||||
line-height: $line-height;
|
||||
height: $line-height;
|
||||
}
|
||||
|
||||
&__chevron {
|
||||
line-height: $line-height;
|
||||
height: $medium-spacing;
|
||||
vertical-align: middle;
|
||||
position: relative;
|
||||
top: ($line-height - $medium-spacing) / 2;
|
||||
fill: $color-brand;
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
query {
|
||||
myActivity {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
text
|
||||
assignment {
|
||||
id
|
||||
title
|
||||
module {
|
||||
title
|
||||
metaTitle
|
||||
slug
|
||||
id
|
||||
topic {
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +1,59 @@
|
|||
<template>
|
||||
<div class="activity">
|
||||
<h1 class="activity__header">Meine Aktivität</h1>
|
||||
<module-activity class="activity"></module-activity>
|
||||
<module-activity class="activity"></module-activity>
|
||||
<module-activity class="activity"></module-activity>
|
||||
<div class="modules">
|
||||
<module-activity v-for="moduleId in Object.keys(modules)" v-bind="modules[moduleId]" :key="moduleId" class="activity"></module-activity>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import ModuleActivity from '@/components/profile/ModuleActivity';
|
||||
import MY_ACTIVITY_QUERY from '@/graphql/gql/myActivity.gql'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ModuleActivity
|
||||
},
|
||||
|
||||
// apollo: {
|
||||
// schoolClasses: {
|
||||
// query: MY_SCHOOL_CLASSES_QUERY,
|
||||
// update(data) {
|
||||
// return this.$getRidOfEdges(data).me.schoolClasses
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
apollo: {
|
||||
submissions: {
|
||||
query: MY_ACTIVITY_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).myActivity;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
activities: []
|
||||
submissions: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
computed: {
|
||||
modules () {
|
||||
let modules = {};
|
||||
|
||||
this.submissions.map((submission) => {
|
||||
let activity = {
|
||||
assignmentId: submission.assignment.id,
|
||||
assignmentTitle: submission.assignment.title,
|
||||
answer: submission.text
|
||||
};
|
||||
|
||||
const module = submission.assignment.module
|
||||
if (!(module.id in modules)) {
|
||||
modules[module.id] = {
|
||||
...module,
|
||||
activities: []
|
||||
}
|
||||
}
|
||||
|
||||
modules[module.id].activities = [...modules[module.id].activities, activity];
|
||||
});
|
||||
return modules
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapActions } from 'vuex'
|
||||
import ASSIGNMENTS_QUERY from '@/graphql/gql/assignmentsQuery.gql';
|
||||
import {moduleQuery} from '@/graphql/queries';
|
||||
|
||||
|
|
@ -13,18 +14,60 @@
|
|||
Module
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions(['scrollToAssignmentReady']),
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['scrollToAssignmentId']),
|
||||
},
|
||||
|
||||
apollo: {
|
||||
module: moduleQuery,
|
||||
assignments: {
|
||||
query: ASSIGNMENTS_QUERY
|
||||
assignments() {
|
||||
return {
|
||||
query: ASSIGNMENTS_QUERY
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
module: {},
|
||||
assignments: []
|
||||
assignments: [],
|
||||
isScrolling: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$store.subscribe((mutation, state) => {
|
||||
if (mutation.type === 'setScrollToAssignmentReady' && state.scrollToAssignmentReady && !this.isScrolling) {
|
||||
this.isScrolling = true;
|
||||
// this.$nextTick(() => {
|
||||
let options = {
|
||||
container: '#app',
|
||||
easing: 'ease-in',
|
||||
offset: -60,
|
||||
force: true,
|
||||
cancelable: true,
|
||||
onStart: (element) => {
|
||||
},
|
||||
onDone: (element) => {
|
||||
this.scrollToAssignmentReady(false);
|
||||
this.isScrolling = false;
|
||||
},
|
||||
onCancel: function() {
|
||||
// scrolling has been interrupted
|
||||
},
|
||||
x: false,
|
||||
y: true
|
||||
};
|
||||
this.$scrollTo(`#${this.scrollToAssignmentId.replace(/=/g, '')}`, 1000, options);
|
||||
// })
|
||||
}
|
||||
})
|
||||
},
|
||||
beforeDestroy () {
|
||||
this.scrollToAssignmentReady(false);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -79,15 +79,12 @@ const routes = [
|
|||
},
|
||||
{
|
||||
path: '/me',
|
||||
name: 'profile',
|
||||
component: profilePage,
|
||||
meta: {
|
||||
isProfile: true
|
||||
},
|
||||
children: [
|
||||
{path: 'password-change', name: 'pw-change', component: passwordChange, meta: {isProfile: true}},
|
||||
{path: 'myclasses', name: 'my-classes', component: myClasses, meta: {isProfile: true}},
|
||||
{path: 'activity', name: 'activity', component: activity, meta: {isProfile: true}},
|
||||
{path: '', name: 'profile-activity', component: activity, meta: {isProfile: true}},
|
||||
]
|
||||
},
|
||||
{path: '*', component: p404}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ export default new Vuex.Store({
|
|||
id: 0,
|
||||
type: ''
|
||||
},
|
||||
vimeoId: null
|
||||
vimeoId: null,
|
||||
scrollToAssignmentId: '',
|
||||
scrollToAssignmentReady: false
|
||||
},
|
||||
|
||||
getters: {
|
||||
|
|
@ -34,7 +36,9 @@ export default new Vuex.Store({
|
|||
},
|
||||
showMobileNavigation: state => {
|
||||
return state.showMobileNavigation
|
||||
}
|
||||
},
|
||||
scrollToAssignmentId: state => state.scrollToAssignmentId,
|
||||
scrollToAssignmentReady: state => state.scrollToAssignmentReady,
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
|
@ -118,6 +122,12 @@ export default new Vuex.Store({
|
|||
},
|
||||
showMobileNavigation({commit}, payload) {
|
||||
commit('setShowMobileNavigation', payload);
|
||||
},
|
||||
scrollToAssignmentId({commit}, payload) {
|
||||
commit('setScrollToAssignmentId', payload);
|
||||
},
|
||||
scrollToAssignmentReady({commit}, payload) {
|
||||
commit('setScrollToAssignmentReady', payload);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -172,6 +182,12 @@ export default new Vuex.Store({
|
|||
},
|
||||
setShowMobileNavigation(state, payload) {
|
||||
state.showMobileNavigation = payload;
|
||||
},
|
||||
setScrollToAssignmentId(state, payload) {
|
||||
state.scrollToAssignmentId = payload;
|
||||
},
|
||||
setScrollToAssignmentReady(state, payload) {
|
||||
state.scrollToAssignmentReady = payload;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ class StudentSubmissionQuery(object):
|
|||
|
||||
|
||||
class MyActivityQuery(object):
|
||||
# my_activity = relay.Node.Field(StudentSubmissionNode)
|
||||
my_activity = DjangoFilterConnectionField(StudentSubmissionNode)
|
||||
|
||||
def resolve_my_activity(self, info, **kwargs):
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ class MyAssignemntsText(DefaultUserTestCase):
|
|||
myActivity {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
text
|
||||
assignment {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,13 +67,14 @@ class ChapterNode(DjangoObjectType):
|
|||
class ModuleNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
chapters = DjangoFilterConnectionField(ChapterNode)
|
||||
topic = graphene.Field('books.schema.queries.TopicNode')
|
||||
hero_image = graphene.String()
|
||||
solutions_enabled = graphene.Boolean()
|
||||
|
||||
class Meta:
|
||||
model = Module
|
||||
only_fields = [
|
||||
'slug', 'title', 'meta_title', 'teaser', 'intro', 'objective_groups', 'assignments', 'hero_image'
|
||||
'slug', 'title', 'meta_title', 'teaser', 'intro', 'objective_groups', 'assignments', 'hero_image', 'topic'
|
||||
]
|
||||
filter_fields = {
|
||||
'slug': ['exact', 'icontains', 'in'],
|
||||
|
|
@ -91,6 +92,10 @@ class ModuleNode(DjangoObjectType):
|
|||
def resolve_chapters(self, info, **kwargs):
|
||||
return Chapter.get_by_parent(self)
|
||||
|
||||
def resolve_topic(self, info, **kwargs):
|
||||
some = self.get_parent().specific
|
||||
return self.get_parent().specific
|
||||
|
||||
def resolve_solutions_enabled(self, info, **kwargs):
|
||||
return self.solutions_enabled_by.filter(pk=info.context.user.pk).exists()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue