Add Feedback container component

This commit is contained in:
Christian Cueni 2019-11-14 11:11:58 +01:00
parent ad07ada2f2
commit d3a81e17d8
11 changed files with 207 additions and 46 deletions

View File

@ -4,7 +4,7 @@
<p class="assignment-with-submissions__text">{{assignment.assignment}}</p>
<div>
<a class="button button--primary submissions-page__back" @click="back">Aufgabe im Modul anzeigen</a>
<a class="button button--primary submissions-page__back" @click="$emit('back')">Aufgabe im Modul anzeigen</a>
</div>
<div class="assignment-with-submissions__solution" v-if="assignment.solution">

View File

@ -7,20 +7,20 @@
<solution :value="solution" v-if="assignment.solution"></solution>
<template v-if="isStudent">
<div class="assignment__submission">
<div class="assignment__submission submissionform-container">
<div class="assignment__inputs">
<div class="submissionform-container__inputs">
<submission-form
@input="saveInput"
:submission="submission"
:input-text="submission.text"
:saved="!unsaved"
:final="final"
></submission-form>
</div>
<div class="assignment__actions" v-if="!final">
<div class="submissionform-container__actions" v-if="!final">
<button
class="assignment__submit button button--primary button--white-bg"
class="submissionform-container__submit button button--primary button--white-bg"
@click="turnIn"
>Ergebnis mit Lehrperson teilen
</button>
@ -265,26 +265,5 @@
color: $color-charcoal-dark;
}
}
&__submission {
@include input-box-shadow;
background-color: $color-white;
border-radius: $input-border-radius;
border: 1px solid $color-silver;
padding: $medium-spacing;
}
&__inputs {
margin-bottom: 12px;
}
&__submit {
margin-right: $medium-spacing;
}
&__actions {
display: flex;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,50 @@
<template>
<div class="feedback__submission submissionform-container">
<div class="submissionform-container__inputs">
<submission-form
@input="saveInput"
:input-text="feedback.text"
:saved="saved"
:final="final"
:placeholder="placeholder"
></submission-form>
</div>
<div class="submissionform-container__actions" v-if="!final">
<button class="submissionform-container__submit button button--primary button--white-bg"
@click="$emit('turnIn')"
>{{action}}
</button>
</div>
<!-- <final-submission :submission="assignment.submission" v-if="final" @reopen="reopen"></final-submission> -->
</div>
</template>
<script>
import SubmissionForm from '@/components/content-blocks/assignment/SubmissionForm';
export default {
components: {
SubmissionForm
},
props: ['feedback', 'saved', 'placeholder', 'action'],
computed: {
final() {
return !!this.feedback && this.feedback.final
}
},
methods: {
saveInput(input) {
this.$emit('saveInput', input);
}
},
}
</script>
<style scoped lang="scss">
</style>

View File

@ -4,9 +4,9 @@
v-auto-grow
rows="1"
class="submission-form__textarea"
placeholder="Ergebnis erfassen"
:placeholder="placeholder"
:readonly="final"
:value="submission.text"
:value="inputText"
@input="$emit('input', $event.target.value)"
></textarea>
<div class="submission-form__save-status submission-form__save-status--saved" v-if="saved">
@ -23,8 +23,15 @@
import LoadingIcon from '@/components/icons/LoadingIcon';
export default {
props: ['submission', 'saved', 'final'],
props: {
inputText: String,
saved: Boolean,
final: Boolean,
placeholder: {
type: String,
default: 'Ergebnis erfassen'
}
},
components: {
TickCircleIcon,
LoadingIcon

View File

@ -0,0 +1,9 @@
mutation UpdateSubmissionFeedback($input: UpdateSubmissionFeedbackInput!) {
updateSubmissionFeedback(input: $input){
successful
updatedSubmissionFeedback {
id
text
}
}
}

View File

@ -9,6 +9,11 @@ query StudentSubmissions($id: ID!) {
}
assignment {
title
assignment
}
submissionfeedback {
text
final
}
}
}

View File

@ -1,10 +1,12 @@
<template>
<div class="article submission-page">
<div class="article__header">
<h1 class="article__title">{{studentSubmission.assignment.title}}</h1>
<h2 class="article__subtitle">{{fullName}}</h2>
<!-- <h1 class="article__title">{{studentSubmission.assignment.title}}</h1> -->
<h1>Aufgabe</h1>
<p>{{studentSubmission.assignment.assignment}}</p>
</div>
<div class="article__content article-content">
<h2 class="article__subtitle">Ergebnis von {{fullName}}</h2>
<p v-if="studentSubmission.document && studentSubmission.document.length > 0" class="article-content__document">
<a :href="studentSubmission.document" class="entry-document__link link" target="_blank">
<student-submission-document :document="studentSubmission.document"></student-submission-document>
@ -12,21 +14,38 @@
</p>
<p class="article-content__text" v-html="text"></p>
</div>
<div class="feedback__submission">
<feedback-form
:feedback="studentSubmission.submissionfeedback"
@turnIn="turnIn"
@saveInput="saveInput"
:placholder="'Feedback erfassen'"
:action="'Feedback teilen'"
:saved="!unsaved"
/>
</div>
</div>
</template>
<script>
import {newLineToParagraph} from '@/helpers/text';
import debounce from 'lodash/debounce';
import StudentSubmissionDocument from '@/components/StudentSubmissionDocument';
import STUDENT_SUBMISSIONS_QUERY from '@/graphql/gql/studentSubmissionQuery.gql';
import UPDATE_FEEDBACK_MUTATION from '@/graphql/gql/mutations/updateFeedback.gql';
import FeedbackForm from '@/components/content-blocks/assignment/FeedbackForm';
export default {
components: {
StudentSubmissionDocument
StudentSubmissionDocument,
FeedbackForm
},
computed: {
final() {
return !!this.studentSubmission && this.studentSubmission.final;
},
text() {
return newLineToParagraph(this.studentSubmission.text);
},
@ -48,6 +67,73 @@
},
},
methods: {
_save: debounce(function () {
const that = this;
this.saving++;
this.$apollo.mutate({
mutation: UPDATE_FEEDBACK_MUTATION,
variables: {
input: {
submissionFeedback: {
studentSubmission: this.studentSubmission.id,
text: this.studentSubmission.submissionfeedback.text,
final: this.studentSubmission.submissionfeedback.final
}
}
},
update(store, {data: {updateSubmissionFeedback: {successful, updatedSubmissionFeedback}}}) {
try {
if (successful) {
const query = STUDENT_SUBMISSIONS_QUERY;
const variables = {
id: that.studentSubmission.id
};
const data = store.readQuery({query, variables});
data.studentSubmission = Object.assign({}, that.studentSubmission);
store.writeQuery({query, variables, data});
}
} catch (e) {
console.error(e);
// Query did not exist in the cache, and apollo throws a generic Error. Do nothing
}
}
}).then(() => {
this.saving--;
if (this.saving === 0) {
this.unsaved = false;
}
});
}, 500),
saveInput: function (feedbackText) {
this.unsaved = true;
/*
We update the assignment on this component, so the changes are reflected on it. The server does not return
the updated entity, to prevent the UI to update when the user is entering his input
*/
this.studentSubmission = Object.assign({}, this.studentSubmission, {
submissionfeedback: Object.assign({}, this.studentSubmission.submissionfeedback, {text: feedbackText})
})
this._save();
},
turnIn() {
this.$apollo.mutate({
mutation: UPDATE_FEEDBACK_MUTATION,
variables: {
input: {
submissionFeedback: {
studentSubmission: this.studentSubmission.id,
text: this.studentSubmission.submissionfeedback.text,
final: true
}
}
}
});
},
},
data() {
return {
studentSubmission: {
@ -59,8 +145,14 @@
lastName: ''
},
text: '',
document: ''
}
document: '',
submissionfeedback: {
text: '',
final: false
}
},
unsaved: false,
saving: 0
}
}
}

View File

@ -2,14 +2,14 @@
<div class="submissions-page skillbox__content">
<h2 class="submissions-page__heading">Aufgabe</h2>
<assignment-with-submissions v-if="!$apollo.queries.assignment.loading"
:assignment="assignment"></assignment-with-submissions>
:assignment="assignment"
@back="back"></assignment-with-submissions>
</div>
</template>
<script>
import AssignmentWithSubmissions from '@/components/AssignmentWithSubmissions';
import ASSIGNMENT_WITH_SUBMISSIONS_QUERY from '@/graphql/gql/assignmentWithSubmissionsQuery.gql';
export default {
@ -61,6 +61,4 @@
margin-top: 2rem;
}
</style>

View File

@ -0,0 +1,23 @@
@import '@/styles/_mixins.scss';
.submissionform-container {
@include input-box-shadow;
background-color: $color-white;
border-radius: $input-border-radius;
border: 1px solid $color-silver;
padding: $medium-spacing;
&__inputs {
margin-bottom: 12px;
}
&__submit {
margin-right: $medium-spacing;
}
&__actions {
display: flex;
align-items: center;
}
}

View File

@ -20,4 +20,5 @@
@import "solutions";
@import "password_forms";
@import "public-page";
@import "student-submission"
@import "student-submission";
@import "submissionform-container";

View File

@ -1,11 +1,8 @@
import graphene
from graphene import relay
from graphene_django.filter import DjangoFilterConnectionField
from rest_framework.exceptions import PermissionDenied
from api.utils import get_by_id_or_slug
from assignments.models import StudentSubmission, SubmissionFeedback
from assignments.schema.types import AssignmentNode, StudentSubmissionNode, SubmissionFeedbackNode
from assignments.models import StudentSubmission
from assignments.schema.types import AssignmentNode, StudentSubmissionNode
class AssignmentsQuery(object):