Merge remote-tracking branch 'origin/feature/objective-control'

This commit is contained in:
Ramon Wenger 2018-10-11 15:44:27 +02:00
commit 9e1c0cd39b
12 changed files with 217 additions and 26 deletions

View File

@ -11,16 +11,26 @@
<objective-group v-for="group in module.objectiveGroups" :key="group.id" :group="group"></objective-group>
<chapter :chapter="chapter" :index="index" v-for="(chapter, index) in module.chapters" :key="chapter.id"></chapter>
<h3 id="objectives">Alles klar?</h3>
<objective-group-control
v-for="(group, index) in module.objectiveGroups"
:key="`${group.id}${index}`"
:group="group"
@updateObjectiveProgress="updateObjectiveProgress"></objective-group-control>
</div>
</template>
<script>
import ObjectiveGroup from '@/components/modules/ObjectiveGroup.vue';
import ObjectiveGroupControl from '@/components/modules/ObjectiveGroupControl.vue';
import Chapter from '@/components/Chapter.vue';
import UPDATE_OBJECTIVE_PROGRESS_MUTATION from '@/graphql/gql/mutations/updateObjectiveProgress.gql';
import OBJECTIVE_QUERY from '@/graphql/gql/objectiveQuery.gql';
export default {
components: {
ObjectiveGroup,
ObjectiveGroupControl,
Chapter
},
@ -40,6 +50,35 @@
},
created() {
},
methods: {
updateObjectiveProgress(done, objectiveId) {
this.$apollo.mutate({
mutation: UPDATE_OBJECTIVE_PROGRESS_MUTATION,
variables: {
input: {
id: objectiveId,
done: done
}
},
update(store, {data: {updateObjectiveProgress: {objective}}}) {
try {
if (objective) {
const variables = {id: objectiveId};
const query = OBJECTIVE_QUERY;
const data = store.readQuery({query, variables});
if (data.objective.objectiveProgress.edges.length > 0) {
data.objective.objectiveProgress.edges[0].node.done = done;
}
store.writeQuery({query: OBJECTIVE_QUERY, data, variables});
}
} catch (e) {
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
}
}
})
},
}
}
</script>

View File

@ -26,23 +26,3 @@
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
.objective-group {
background-color: $color-lightgrey;
padding: 17px;
margin-bottom: 35px;
&__objective-list {
padding-left: 20px;
list-style: disc;
}
&__objective {
margin-bottom: 28px;
line-height: 1.5;
}
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<div class="objective-group objective-group-control">
<h4>{{group.title}}</h4>
<ul class="objective-group__objective-list objective-group__objective-list--no-list">
<li v-if="objectives" class="objective-group__objective" v-for="objective in objectives" :key="objective.id">
<checkbox :checked="objective.done"
:item="objective"
:label="objective.text"
@input="updateObjectiveProgress"
></checkbox>
</li>
</ul>
</div>
</template>
<script>
import Checkbox from '@/components/Checkbox';
export default {
name: 'objective-group-control',
components: {Checkbox},
props: {
group: {
required: true,
type: Object
}
},
methods: {
updateObjectiveProgress(checked, objective) {
this.$emit('updateObjectiveProgress', checked, objective.id);
},
objectiveIsDone(objective) {
return objective.objectiveProgress.length > 0 && objective.objectiveProgress[0].done
}
},
computed: {
objectives() {
return this.group.objectives.map(objective => {
return Object.assign({}, objective, { done: this.objectiveIsDone(objective) })
});
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/_variables.scss";
@import "@/styles/_functions.scss";
.objective-group-control {
background-color: $color-brand-light;
}
.objective-group__objective-list /deep/ {
.base-input-container {
position: relative;
&__checkbox {
background-color: white;
position: absolute;
top: 5px;
}
&__label {
font-family: $serif-font-family;
margin-left: 30px;
}
}
}
</style>

View File

@ -43,7 +43,8 @@ const cache = new InMemoryCache({
Query: {
contentBlock: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ContentBlockNode', id: args.id}),
chapter: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ChapterNode', id: args.id}),
assignment: (_, args, {getCacheKey}) => getCacheKey({__typename: 'AssignmentNode', id: args.id})
assignment: (_, args, {getCacheKey}) => getCacheKey({__typename: 'AssignmentNode', id: args.id}),
objective: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveNode', id: args.id})
}
}
});

View File

@ -20,11 +20,19 @@ query ModulesQuery($slug: String!) {
node {
id
title
objectiveSet {
objectives {
edges {
node {
id
text
objectiveProgress {
edges {
node {
id
done
}
}
}
}
}
}

View File

@ -0,0 +1,15 @@
mutation UpdateObjectiveProgressInput($input: UpdateObjectiveProgressInput!) {
updateObjectiveProgress(input: $input){
objective {
id
objectiveProgress {
edges {
node {
id
done
}
}
}
}
}
}

View File

@ -0,0 +1,13 @@
query ObjectiveQuery($id: ID!) {
objective(id: $id) {
id
objectiveProgress {
edges {
node {
id
done
}
}
}
}
}

View File

@ -0,0 +1,22 @@
@import 'variables';
.objective-group {
background-color: $color-lightgrey;
padding: 17px;
margin-bottom: 35px;
&__objective-list {
padding-left: 20px;
list-style: disc;
&--no-list {
list-style: none;
padding-left: 0;
}
}
&__objective {
margin-bottom: 28px;
line-height: 1.5;
}
}

View File

@ -10,3 +10,4 @@
@import "forms";
@import "uploadcare_overwrite";
@import "help-text";
@import "objective-group";

View File

@ -9,6 +9,7 @@ from assignments.schema.mutations import AssignmentMutations
from assignments.schema.queries import AssignmentsQuery
from books.schema.mutations.main import BookMutations
from filteredbook.schema import BookQuery
from objectives.mutations import ObjectiveMutations
from objectives.schema import ObjectivesQuery
from rooms.mutations import RoomMutations
from rooms.schema import RoomsQuery
@ -22,7 +23,7 @@ class Query(UsersQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery
debug = graphene.Field(DjangoDebug, name='__debug')
class Mutation(BookMutations, RoomMutations, AssignmentMutations, graphene.ObjectType):
class Mutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, graphene.ObjectType):
if settings.DEBUG:
debug = graphene.Field(DjangoDebug, name='__debug')

View File

@ -1,6 +1,5 @@
from django.contrib.auth import get_user_model
from django.db import models
from django_extensions.db.models import TitleDescriptionModel
from books.models import Module
@ -25,7 +24,8 @@ class Objective(models.Model):
verbose_name_plural = 'Lernziele'
text = models.CharField('text', blank=True, null=False, max_length=255)
group = models.ForeignKey(ObjectiveGroup, blank=False, null=False, on_delete=models.CASCADE)
group = models.ForeignKey(ObjectiveGroup, blank=False, null=False, on_delete=models.CASCADE,
related_name='objectives')
def __str__(self):
return 'Objective {}-{}'.format(self.id, self.text)
@ -37,7 +37,8 @@ class ObjectiveProgressStatus(models.Model):
verbose_name_plural = 'Lernzielstatus'
done = models.BooleanField('Lernziel erledigt?', default=False)
objective = models.ForeignKey(Objective, blank=False, null=False, on_delete=models.CASCADE)
objective = models.ForeignKey(Objective, blank=False, null=False, on_delete=models.CASCADE,
related_name='objective_progress')
user = models.ForeignKey(get_user_model(), blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):

View File

@ -0,0 +1,33 @@
import graphene
from graphene import relay
from api.utils import get_object
from objectives.models import ObjectiveProgressStatus, Objective
from objectives.schema import ObjectiveNode
class UpdateObjectiveProgress(relay.ClientIDMutation):
class Input:
id = graphene.ID(required=True, description="The ID of the objective")
done = graphene.Boolean(required=True)
errors = graphene.List(graphene.String)
objective = graphene.Field(ObjectiveNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
objective_id = kwargs.get('id')
done = kwargs.get('done')
objective = get_object(Objective, objective_id) # info.context.user = django user
objective_progress, created = ObjectiveProgressStatus.objects.get_or_create(
objective=objective,
user=info.context.user
)
objective_progress.done = done
objective_progress.save()
return cls(objective=objective)
class ObjectiveMutations:
update_objective_progress = UpdateObjectiveProgress.Field()