From 5970ac3427a73b362daf01e0cb150b287d902705 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 10 Oct 2018 10:45:56 +0200 Subject: [PATCH 1/3] update objective progress items --- client/src/components/modules/Module.vue | 47 +++++++++++- .../src/components/modules/ObjectiveGroup.vue | 20 ----- .../modules/ObjectiveGroupControl.vue | 75 +++++++++++++++++++ client/src/graphql/gql/moduleDetailsQuery.gql | 8 ++ .../gql/mutations/updateObjectiveProgress.gql | 5 ++ client/src/styles/_objective-group.scss | 26 +++++++ client/src/styles/main.scss | 1 + server/api/schema.py | 3 +- server/objectives/models.py | 1 - server/objectives/mutations.py | 32 ++++++++ 10 files changed, 195 insertions(+), 23 deletions(-) create mode 100644 client/src/components/modules/ObjectiveGroupControl.vue create mode 100644 client/src/graphql/gql/mutations/updateObjectiveProgress.gql create mode 100644 client/src/styles/_objective-group.scss create mode 100644 server/objectives/mutations.py diff --git a/client/src/components/modules/Module.vue b/client/src/components/modules/Module.vue index 2ddc5285..a63d7724 100644 --- a/client/src/components/modules/Module.vue +++ b/client/src/components/modules/Module.vue @@ -11,16 +11,25 @@ +

Alles klar?

+ diff --git a/client/src/components/modules/ObjectiveGroup.vue b/client/src/components/modules/ObjectiveGroup.vue index 3c2e07cc..f19d8308 100644 --- a/client/src/components/modules/ObjectiveGroup.vue +++ b/client/src/components/modules/ObjectiveGroup.vue @@ -26,23 +26,3 @@ } } - - diff --git a/client/src/components/modules/ObjectiveGroupControl.vue b/client/src/components/modules/ObjectiveGroupControl.vue new file mode 100644 index 00000000..12193cfa --- /dev/null +++ b/client/src/components/modules/ObjectiveGroupControl.vue @@ -0,0 +1,75 @@ + + + + diff --git a/client/src/graphql/gql/moduleDetailsQuery.gql b/client/src/graphql/gql/moduleDetailsQuery.gql index 82f7c160..4e6c6a45 100644 --- a/client/src/graphql/gql/moduleDetailsQuery.gql +++ b/client/src/graphql/gql/moduleDetailsQuery.gql @@ -25,6 +25,14 @@ query ModulesQuery($slug: String!) { node { id text + objectiveprogressstatusSet { + edges { + node { + id + done + } + } + } } } } diff --git a/client/src/graphql/gql/mutations/updateObjectiveProgress.gql b/client/src/graphql/gql/mutations/updateObjectiveProgress.gql new file mode 100644 index 00000000..b68179d9 --- /dev/null +++ b/client/src/graphql/gql/mutations/updateObjectiveProgress.gql @@ -0,0 +1,5 @@ +mutation UpdateObjectiveProgressInput($input: UpdateObjectiveProgressInput!) { + updateObjectiveProgress(input: $input){ + success + } +} diff --git a/client/src/styles/_objective-group.scss b/client/src/styles/_objective-group.scss new file mode 100644 index 00000000..686f1de8 --- /dev/null +++ b/client/src/styles/_objective-group.scss @@ -0,0 +1,26 @@ +@import 'variables'; + +.objective-group { + background-color: $color-lightgrey; + padding: 17px; + margin-bottom: 35px; + + &--control { + background-color: $color-brand-light; + } + + &__objective-list { + padding-left: 20px; + list-style: disc; + + &--no-list { + list-style: none; + padding-left: 0; + } + } + + &__objective { + margin-bottom: 28px; + line-height: 1.5; + } +} diff --git a/client/src/styles/main.scss b/client/src/styles/main.scss index 3dc726df..6c8b595a 100644 --- a/client/src/styles/main.scss +++ b/client/src/styles/main.scss @@ -10,3 +10,4 @@ @import "forms"; @import "uploadcare_overwrite"; @import "help-text"; +@import "objective-group"; diff --git a/server/api/schema.py b/server/api/schema.py index d8105f50..efb66fe0 100644 --- a/server/api/schema.py +++ b/server/api/schema.py @@ -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') diff --git a/server/objectives/models.py b/server/objectives/models.py index 5d986d0d..d4538c0b 100644 --- a/server/objectives/models.py +++ b/server/objectives/models.py @@ -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 diff --git a/server/objectives/mutations.py b/server/objectives/mutations.py new file mode 100644 index 00000000..417aa9ce --- /dev/null +++ b/server/objectives/mutations.py @@ -0,0 +1,32 @@ +import graphene +from graphene import relay +from api.utils import get_object +from objectives.models import ObjectiveProgressStatus, Objective + + +class UpdateObjectiveProgress(relay.ClientIDMutation): + class Input: + id = graphene.ID(required=True, description="The ID of the objective") + done = graphene.Boolean(required=True) + + success = graphene.Boolean() + errors = graphene.List(graphene.String) + + @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 + try: + objective_progress = ObjectiveProgressStatus.objects.filter(objective=objective)[0] + except IndexError: + objective_progress = ObjectiveProgressStatus(objective=objective, user=info.context.user) + + objective_progress.done = done + objective_progress.save() + + return cls(success=True) + + +class ObjectiveMutations: + update_objective_progress = UpdateObjectiveProgress.Field() From 5dd77eab5d3366e1c9d15168dbb20abd228330e8 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 11 Oct 2018 14:12:47 +0200 Subject: [PATCH 2/3] use cache for update, incorperate feedback --- client/src/components/modules/Module.vue | 42 ++++++++----------- .../modules/ObjectiveGroupControl.vue | 20 ++++----- client/src/graphql/client.js | 3 +- client/src/graphql/gql/moduleDetailsQuery.gql | 4 +- .../gql/mutations/updateObjectiveProgress.gql | 12 +++++- client/src/graphql/gql/objectiveQuery.gql | 13 ++++++ server/objectives/models.py | 6 ++- server/objectives/mutations.py | 13 +++--- 8 files changed, 66 insertions(+), 47 deletions(-) create mode 100644 client/src/graphql/gql/objectiveQuery.gql diff --git a/client/src/components/modules/Module.vue b/client/src/components/modules/Module.vue index a63d7724..4604315c 100644 --- a/client/src/components/modules/Module.vue +++ b/client/src/components/modules/Module.vue @@ -25,6 +25,7 @@ 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: { @@ -60,32 +61,25 @@ 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}); + } + } catch (e) { + // Query did not exist in the cache, and apollo throws a generic Error. Do nothing + } } - }).then(() => { - this.updateProgress(done, objectiveId); - }); + }) }, - updateProgress(done, objectiveId) { - this.module.objectiveGroups.map(group => { - const objective = this.findObjective(objectiveId, group); - if (objective) { - this.setStatusOnProgress(objective, done); - } - }); - }, - findObjective(objectiveId, group) { - return group.objectiveSet.filter(objective => { - return objective.id === objectiveId - })[0]; - }, - setStatusOnProgress(objective, done) { - if (objective.objectiveprogressstatusSet.length > 0) { - objective.objectiveprogressstatusSet[0].done = done - } else { - objective.objectiveprogressstatusSet = [{ done }] // in case the progress object did not exist - } - } - }, + } } diff --git a/client/src/components/modules/ObjectiveGroupControl.vue b/client/src/components/modules/ObjectiveGroupControl.vue index 12193cfa..3b2ae1b0 100644 --- a/client/src/components/modules/ObjectiveGroupControl.vue +++ b/client/src/components/modules/ObjectiveGroupControl.vue @@ -3,15 +3,13 @@

{{group.title}}

@@ -37,13 +35,13 @@ this.$emit('updateObjectiveProgress', checked, objective.id); }, objectiveIsDone(objective) { - return objective.objectiveprogressstatusSet.length > 0 && objective.objectiveprogressstatusSet[0].done + return objective.objectiveProgress.length > 0 && objective.objectiveProgress[0].done } }, computed: { objectives() { - return this.group.objectiveSet.map(objective => { + return this.group.objectives.map(objective => { return Object.assign({}, objective, { done: this.objectiveIsDone(objective) }) }); } diff --git a/client/src/graphql/client.js b/client/src/graphql/client.js index cfe714df..11fef5ab 100644 --- a/client/src/graphql/client.js +++ b/client/src/graphql/client.js @@ -42,7 +42,8 @@ const cache = new InMemoryCache({ cacheRedirects: { Query: { contentBlock: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ContentBlockNode', 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}) } } }); diff --git a/client/src/graphql/gql/moduleDetailsQuery.gql b/client/src/graphql/gql/moduleDetailsQuery.gql index 4e6c6a45..d87d7bb1 100644 --- a/client/src/graphql/gql/moduleDetailsQuery.gql +++ b/client/src/graphql/gql/moduleDetailsQuery.gql @@ -20,12 +20,12 @@ query ModulesQuery($slug: String!) { node { id title - objectiveSet { + objectives { edges { node { id text - objectiveprogressstatusSet { + objectiveProgress { edges { node { id diff --git a/client/src/graphql/gql/mutations/updateObjectiveProgress.gql b/client/src/graphql/gql/mutations/updateObjectiveProgress.gql index b68179d9..9f939931 100644 --- a/client/src/graphql/gql/mutations/updateObjectiveProgress.gql +++ b/client/src/graphql/gql/mutations/updateObjectiveProgress.gql @@ -1,5 +1,15 @@ mutation UpdateObjectiveProgressInput($input: UpdateObjectiveProgressInput!) { updateObjectiveProgress(input: $input){ - success + objective { + id + objectiveProgress { + edges { + node { + id + done + } + } + } + } } } diff --git a/client/src/graphql/gql/objectiveQuery.gql b/client/src/graphql/gql/objectiveQuery.gql new file mode 100644 index 00000000..a8509d6c --- /dev/null +++ b/client/src/graphql/gql/objectiveQuery.gql @@ -0,0 +1,13 @@ +query ObjectiveQuery($id: ID!) { + objective(id: $id) { + id + objectiveProgress { + edges { + node { + id + done + } + } + } + } +} diff --git a/server/objectives/models.py b/server/objectives/models.py index d4538c0b..e323a841 100644 --- a/server/objectives/models.py +++ b/server/objectives/models.py @@ -24,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) @@ -36,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): diff --git a/server/objectives/mutations.py b/server/objectives/mutations.py index 417aa9ce..92bc4d97 100644 --- a/server/objectives/mutations.py +++ b/server/objectives/mutations.py @@ -2,6 +2,7 @@ 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): @@ -9,23 +10,23 @@ class UpdateObjectiveProgress(relay.ClientIDMutation): id = graphene.ID(required=True, description="The ID of the objective") done = graphene.Boolean(required=True) - success = graphene.Boolean() 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 - try: - objective_progress = ObjectiveProgressStatus.objects.filter(objective=objective)[0] - except IndexError: - objective_progress = ObjectiveProgressStatus(objective=objective, user=info.context.user) + objective_progress, created = ObjectiveProgressStatus.objects.get_or_create( + objective=objective, + user=info.context.user + ) objective_progress.done = done objective_progress.save() - return cls(success=True) + return cls(objective=objective) class ObjectiveMutations: From cf01aa2bf912f263928b87da67d6395c53e39df9 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 11 Oct 2018 15:08:35 +0200 Subject: [PATCH 3/3] =?UTF-8?q?add=20missing=20variables=20to=20update,=20?= =?UTF-8?q?remove=20confusing=20class=20name=20=F0=9F=A4=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/modules/Module.vue | 2 +- client/src/components/modules/ObjectiveGroupControl.vue | 6 +++++- client/src/styles/_objective-group.scss | 4 ---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/components/modules/Module.vue b/client/src/components/modules/Module.vue index 4604315c..8df4e046 100644 --- a/client/src/components/modules/Module.vue +++ b/client/src/components/modules/Module.vue @@ -71,7 +71,7 @@ if (data.objective.objectiveProgress.edges.length > 0) { data.objective.objectiveProgress.edges[0].node.done = done; } - store.writeQuery({query: OBJECTIVE_QUERY, data}); + store.writeQuery({query: OBJECTIVE_QUERY, data, variables}); } } catch (e) { // Query did not exist in the cache, and apollo throws a generic Error. Do nothing diff --git a/client/src/components/modules/ObjectiveGroupControl.vue b/client/src/components/modules/ObjectiveGroupControl.vue index 3b2ae1b0..3aa68918 100644 --- a/client/src/components/modules/ObjectiveGroupControl.vue +++ b/client/src/components/modules/ObjectiveGroupControl.vue @@ -1,5 +1,5 @@