Add note update mutation

This commit is contained in:
Ramon Wenger 2019-10-12 08:54:20 +02:00
parent 62460d58ab
commit 1d5603ed5f
13 changed files with 246 additions and 37 deletions

View File

@ -23,6 +23,7 @@
import EditProjectEntryWizard from '@/components/portfolio/EditProjectEntryWizard';
import NewObjectiveWizard from '@/components/objective-groups/NewObjectiveWizard';
import NewNoteWizard from '@/components/notes/NewNoteWizard';
import EditNoteWizard from '@/components/notes/EditNoteWizard';
import FullscreenImage from '@/components/FullscreenImage';
import FullscreenInfographic from '@/components/FullscreenInfographic';
import FullscreenVideo from '@/components/FullscreenVideo';
@ -50,6 +51,7 @@
EditProjectEntryWizard,
NewObjectiveWizard,
NewNoteWizard,
EditNoteWizard,
FullscreenImage,
FullscreenInfographic,
FullscreenVideo

View File

@ -22,7 +22,9 @@
:key="component.id"
:component="component"
:parent="contentBlock.id"
:bookmarks="contentBlock.bookmarks">
:bookmarks="contentBlock.bookmarks"
:notes="contentBlock.notes"
>
</content-component>
</div>

View File

@ -2,8 +2,10 @@
<div class="content-component" :class="{'content-component--bookmarked': bookmarked}">
<bookmark-actions
@add-note="addNote(component.id)"
@edit-note="editNote"
@bookmark="bookmarkContent(component.id, !bookmarked)"
:bookmarked="bookmarked"></bookmark-actions>
:bookmarked="bookmarked"
:note="note"></bookmark-actions>
<component
:is="component.type"
v-bind="component">
@ -33,7 +35,7 @@
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
export default {
props: ['component', 'parent', 'bookmarks'],
props: ['component', 'parent', 'bookmarks', 'notes'],
components: {
'text_block': TextBlock,
@ -58,6 +60,10 @@
computed: {
bookmarked() {
return !!this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
},
note() {
const bookmark = this.bookmarks.find(bookmark => bookmark.uuid === this.component.id);
return bookmark && bookmark.note;
}
},
@ -68,6 +74,9 @@
contentBlock: this.parent
});
},
editNote() {
this.$store.dispatch('editNote', this.note);
},
bookmarkContent(uuid, bookmarked) {
this.$apollo.mutate({
mutation: UPDATE_CONTENT_BOOKMARK,

View File

@ -4,9 +4,11 @@
:class="{'bookmark-actions__action--bookmarked': bookmarked}">
<bookmark-icon :bookmarked="bookmarked"></bookmark-icon>
</a>
<a class="bookmark-actions__action" v-if="bookmarked" @click="$emit('add-note')">
<a class="bookmark-actions__action" v-if="bookmarked && !note" @click="$emit('add-note')">
<add-note-icon></add-note-icon>
<note-icon v-if="false"></note-icon>
</a>
<a class="bookmark-actions__action bookmark-actions__action--noted" @click="$emit('edit-note')" v-if="note">
<note-icon></note-icon>
</a>
</div>
</template>
@ -17,7 +19,7 @@
import NoteIcon from '@/components/icons/NoteIcon';
export default {
props: ['bookmarked'],
props: ['bookmarked', 'note'],
components: {
BookmarkIcon,
AddNoteIcon,
@ -43,8 +45,9 @@
&__action {
opacity: 0;
transition: opacity 0.3s;
cursor: pointer;
&--bookmarked {
&--bookmarked, &--noted {
opacity: 1;
}
}

View File

@ -0,0 +1,46 @@
<template>
<note-form @save="editNote" @hide="hide" :note="currentNote"></note-form>
</template>
<script>
import NoteForm from '@/components/notes/NoteForm';
import UPDATE_NOTE_MUTATION from '@/graphql/gql/mutations/updateNote.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
import {mapGetters} from 'vuex';
export default {
components: {
NoteForm
},
computed: {
...mapGetters(['currentNote'])
},
methods: {
editNote(note) {
this.$apollo.mutate({
mutation: UPDATE_NOTE_MUTATION,
variables: {
input: {
note
}
},
refetchQueries: [{
query: MODULE_DETAILS_QUERY,
variables: {
slug: this.$route.params.slug
}
}]
}).then(() => {
this.$store.dispatch('hideModal');
});
},
hide() {
this.$store.dispatch('hideModal');
}
}
}
</script>

View File

@ -1,35 +1,23 @@
<template>
<modal :hide-header="true" :small="true">
<modal-input v-on:input="note = $event"
placeholder="Notiz erfassen"
:value="note"
></modal-input>
<div slot="footer">
<a class="button button--primary" data-cy="modal-save-button"
@click="addNote(note)">Speichern</a>
<a class="button" @click="hide">Löschen</a>
</div>
</modal>
<note-form @save="addNote" @hide="hide" :note="note"></note-form>
</template>
<script>
import Modal from '@/components/Modal';
import ModalInput from '@/components/ModalInput';
import NoteForm from '@/components/notes/NoteForm';
import ADD_NOTE_MUTATION from '@/graphql/gql/mutations/addNote.gql';
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
import {mapGetters} from 'vuex';
export default {
components: {
Modal,
ModalInput
NoteForm
},
data() {
return {
note: ''
note: {}
}
},
@ -38,7 +26,7 @@
},
methods: {
addNote(text) {
addNote(note) {
this.$apollo.mutate({
mutation: ADD_NOTE_MUTATION,
variables: {
@ -46,12 +34,19 @@
note: {
content: this.currentContent,
contentBlock: this.currentContentBlock,
text
text: note.text
}
}
}
},
refetchQueries: [{
query: MODULE_DETAILS_QUERY,
variables: {
slug: this.$route.params.slug
}
}]
}).then(() => {
this.$store.dispatch('hideModal');
});
console.log(note);
},
hide() {
this.$store.dispatch('hideModal');

View File

@ -0,0 +1,38 @@
<template>
<modal :hide-header="true" :small="true">
<modal-input v-on:input="localNote.text = $event"
placeholder="Notiz erfassen"
:value="localNote.text"
></modal-input>
<div slot="footer">
<a class="button button--primary" data-cy="modal-save-button"
@click="$emit('save', localNote)">Speichern</a>
<a class="button" @click="$emit('hide')">Löschen</a>
</div>
</modal>
</template>
<script>
import Modal from '@/components/Modal';
import ModalInput from '@/components/ModalInput';
export default {
props: ['note'],
components: {
Modal,
ModalInput
},
data() {
return {
localNote: Object.assign({},
{
...this.note
}
)
}
}
}
</script>

View File

@ -0,0 +1,8 @@
mutation UpdateNote($input: UpdateNoteInput!) {
updateNote(input: $input) {
note {
id
text
}
}
}

View File

@ -20,6 +20,7 @@ export default new Vuex.Store({
objectiveGroupType: '',
currentObjectiveGroup: '',
parentProject: null,
currentNote: null,
currentProjectEntry: null,
imageUrl: '',
infographic: {
@ -43,7 +44,8 @@ export default new Vuex.Store({
editModule: state => state.editModule,
currentObjectiveGroup: state => state.currentObjectiveGroup,
currentContent: state => state.currentContent,
currentContentBlock: state => state.currentContentBlock
currentContentBlock: state => state.currentContentBlock,
currentNote: state => state.currentNote,
},
actions: {
@ -73,6 +75,7 @@ export default new Vuex.Store({
type: ''
});
commit('setVimeoId', null);
commit('setCurrentNote', null);
},
resetContentBlockPosition({commit}) {
commit('setContentBlockPosition', {});
@ -127,6 +130,10 @@ export default new Vuex.Store({
commit('setCurrentContent', payload.content);
dispatch('showModal', 'new-note-wizard');
},
editNote({commit, dispatch}, payload) {
commit('setCurrentNote', payload);
dispatch('showModal', 'edit-note-wizard');
},
showFullscreenImage({commit, dispatch}, payload) {
commit('setImageUrl', payload);
dispatch('showModal', 'fullscreen-image');
@ -152,7 +159,6 @@ export default new Vuex.Store({
if (payload && !state.scrollingToAssignment) {
commit('setScrollingToAssignment', true);
}
;
if (!payload && state.scrollingToAssignment) {
commit('setScrollingToAssignment', false);
@ -189,6 +195,9 @@ export default new Vuex.Store({
setParentRoom(state, payload) {
state.parentRoom = payload;
},
setCurrentNote(state, payload) {
state.currentNote = payload;
},
setCurrentRoomEntry(state, payload) {
state.currentRoomEntry = payload;
},

View File

@ -0,0 +1,21 @@
# Generated by Django 2.0.6 on 2019-10-10 09:52
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('notes', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('books', '0014_auto_20190912_1228'),
]
operations = [
migrations.AddField(
model_name='contentblock',
name='bookmarks',
field=models.ManyToManyField(related_name='bookmarked_content_blocks', through='notes.ContentBlockBookmark', to=settings.AUTH_USER_MODEL),
),
]

View File

@ -7,3 +7,7 @@ class AddNoteArgument(InputObjectType):
content_block = graphene.ID(required=True)
text = graphene.String(required=True)
class UpdateNoteArgument(InputObjectType):
id = graphene.ID(required=True)
text = graphene.String(required=True)

View File

@ -0,0 +1,46 @@
# Generated by Django 2.0.6 on 2019-10-10 09:52
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('books', '0014_auto_20190912_1228'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='ContentBlockBookmark',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(unique=True)),
('content_block', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.ContentBlock')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Note',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField()),
],
),
migrations.AddField(
model_name='contentblockbookmark',
name='note',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='notes.Note'),
),
migrations.AddField(
model_name='contentblockbookmark',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -1,16 +1,19 @@
from builtins import PermissionError
import graphene
import json
from graphene import relay
from api.utils import get_object
from books.models import ContentBlock
from notes.inputs import AddNoteArgument
from notes.inputs import AddNoteArgument, UpdateNoteArgument
from notes.models import ContentBlockBookmark, Note
from notes.schema import NoteNode
class UpdateContentBookmark(relay.ClientIDMutation):
class Input:
id = graphene.String(required=True)
uuid = graphene.UUID(required=True)
content_block = graphene.ID(required=True)
bookmarked = graphene.Boolean(required=True)
@ -19,7 +22,7 @@ class UpdateContentBookmark(relay.ClientIDMutation):
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
id = kwargs.get('id')
uuid = kwargs.get('uuid')
user = info.context.user
content_block_id = kwargs.get('content_block')
bookmarked = kwargs.get('bookmarked')
@ -29,20 +32,19 @@ class UpdateContentBookmark(relay.ClientIDMutation):
if bookmarked:
ContentBlockBookmark.objects.create(
content_block=content_block,
id=id,
uuid=uuid,
user=user
)
else:
ContentBlockBookmark.objects.get(
content_block=content_block,
id=id,
uuid=uuid,
user=user
).delete()
return cls(success=True)
class AddNote(relay.ClientIDMutation):
class Input:
note = graphene.Argument(AddNoteArgument)
@ -61,7 +63,7 @@ class AddNote(relay.ClientIDMutation):
bookmark = ContentBlockBookmark.objects.get(
content_block=content_block,
id=content_uuid,
uuid=content_uuid,
user=user
)
@ -71,6 +73,30 @@ class AddNote(relay.ClientIDMutation):
return cls(note=bookmark.note)
class UpdateNote(relay.ClientIDMutation):
class Input:
note = graphene.Argument(UpdateNoteArgument)
note = graphene.Field(NoteNode)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
user = info.context.user
note = kwargs.get('note')
id = note.get('id')
text = note.get('text')
note = get_object(Note, id)
if note.contentblockbookmark.user != user:
raise PermissionError
note.text = text
note.save()
return cls(note=note)
class NoteMutations:
add_note = AddNote.Field()
update_note = UpdateNote.Field()
update_content_bookmark = UpdateContentBookmark.Field()