Add notes to chapters and modules
This commit is contained in:
parent
f6f61aaf05
commit
3f66ce5a0f
|
|
@ -4,8 +4,11 @@
|
||||||
|
|
||||||
<bookmark-actions
|
<bookmark-actions
|
||||||
class="chapter__bookmark-actions"
|
class="chapter__bookmark-actions"
|
||||||
|
@add-note="addNote"
|
||||||
|
@edit-note="editNote"
|
||||||
:bookmarked="chapter.bookmark"
|
:bookmarked="chapter.bookmark"
|
||||||
@bookmark="bookmark(!chapter.bookmark)"
|
@bookmark="bookmark(!chapter.bookmark)"
|
||||||
|
:note="chapter.bookmark.note"
|
||||||
></bookmark-actions>
|
></bookmark-actions>
|
||||||
<p class="chapter__description">
|
<p class="chapter__description">
|
||||||
{{chapter.description}}
|
{{chapter.description}}
|
||||||
|
|
@ -109,7 +112,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
addNote(id) {
|
||||||
|
this.$store.dispatch('addNote', {
|
||||||
|
content: id,
|
||||||
|
parent: this.chapter.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
editNote() {
|
||||||
|
this.$store.dispatch('editNote', this.chapter.bookmark.note);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@
|
||||||
<div class="module__intro-wrapper">
|
<div class="module__intro-wrapper">
|
||||||
<bookmark-actions
|
<bookmark-actions
|
||||||
class="module__bookmark-actions"
|
class="module__bookmark-actions"
|
||||||
|
@add-note="addNote"
|
||||||
|
@edit-note="editNote"
|
||||||
:bookmarked="module.bookmark"
|
:bookmarked="module.bookmark"
|
||||||
|
:note="module.bookmark.note"
|
||||||
@bookmark="bookmark(!module.bookmark)"></bookmark-actions>
|
@bookmark="bookmark(!module.bookmark)"></bookmark-actions>
|
||||||
<div class="module__intro" v-html="module.intro"></div>
|
<div class="module__intro" v-html="module.intro"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -168,7 +171,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
addNote(id) {
|
||||||
|
this.$store.dispatch('addNote', {
|
||||||
|
content: id,
|
||||||
|
parent: this.module.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
editNote() {
|
||||||
|
this.$store.dispatch('editNote', this.module.bookmark.note);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,8 @@
|
||||||
<script>
|
<script>
|
||||||
import NoteForm from '@/components/notes/NoteForm';
|
import NoteForm from '@/components/notes/NoteForm';
|
||||||
|
|
||||||
import ADD_NOTE_MUTATION from '@/graphql/gql/mutations/addNote.gql';
|
|
||||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
|
||||||
|
|
||||||
import {mapGetters} from 'vuex';
|
import {mapGetters} from 'vuex';
|
||||||
|
import {constructNoteMutation} from '@/helpers/new-note-mutation.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -22,68 +20,32 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['currentContent', 'currentContentBlock'])
|
...mapGetters(['currentContent', 'currentContentBlock', 'currentNoteParent'])
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
addNote(note) {
|
addNote(n) {
|
||||||
const content = this.currentContent;
|
const content = this.currentContent;
|
||||||
const contentBlock = this.currentContentBlock;
|
const contentBlock = this.currentContentBlock;
|
||||||
const text = note.text;
|
const parent = this.currentNoteParent;
|
||||||
|
const text = n.text;
|
||||||
this.$apollo.mutate({
|
let note = {};
|
||||||
mutation: ADD_NOTE_MUTATION,
|
if (content > '') {
|
||||||
variables: {
|
note = {
|
||||||
input: {
|
content,
|
||||||
note: {
|
contentBlock,
|
||||||
content,
|
text
|
||||||
contentBlock,
|
|
||||||
text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update: (store, {data: {addNote: {note}}}) => {
|
|
||||||
const query = CONTENT_BLOCK_QUERY;
|
|
||||||
const variables = {id: contentBlock};
|
|
||||||
const data = store.readQuery({
|
|
||||||
query,
|
|
||||||
variables
|
|
||||||
});
|
|
||||||
|
|
||||||
const bookmarks = data.contentBlock.bookmarks;
|
|
||||||
|
|
||||||
let index = bookmarks.findIndex(element => {
|
|
||||||
return element.uuid === content;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (index > -1) {
|
|
||||||
let el = bookmarks[index];
|
|
||||||
el.note = note;
|
|
||||||
bookmarks.splice(index, 1, el);
|
|
||||||
}
|
|
||||||
|
|
||||||
data.contentBlock.bookmarks = bookmarks;
|
|
||||||
|
|
||||||
store.writeQuery({
|
|
||||||
data,
|
|
||||||
query,
|
|
||||||
variables
|
|
||||||
});
|
|
||||||
},
|
|
||||||
optimisticResponse: {
|
|
||||||
__typename: 'Mutation',
|
|
||||||
addNote: {
|
|
||||||
__typename: 'AddNotePayload',
|
|
||||||
note: {
|
|
||||||
__typename: 'NoteNode',
|
|
||||||
id: -1,
|
|
||||||
text: text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).then(() => {
|
} else {
|
||||||
this.$store.dispatch('hideModal');
|
note = {
|
||||||
});
|
parent,
|
||||||
|
text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$apollo
|
||||||
|
.mutate(constructNoteMutation(note))
|
||||||
|
.then(this.hide);
|
||||||
},
|
},
|
||||||
hide() {
|
hide() {
|
||||||
this.$store.dispatch('hideModal');
|
this.$store.dispatch('hideModal');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import ADD_NOTE_MUTATION from '@/graphql/gql/mutations/addNote.gql';
|
||||||
|
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
||||||
|
import CHAPTER_QUERY from '@/graphql/gql/chapterQuery.gql';
|
||||||
|
import MODULE_QUERY from '@/graphql/gql/moduleByIdQuery.gql';
|
||||||
|
|
||||||
|
const getBlockType = id => atob(id).split(':')[0]
|
||||||
|
|
||||||
|
export const constructNoteMutation = (n) => {
|
||||||
|
let update = () => {
|
||||||
|
};
|
||||||
|
|
||||||
|
if (n.contentBlock) {
|
||||||
|
update = (store, {data: {addNote: {note}}}) => {
|
||||||
|
const query = CONTENT_BLOCK_QUERY;
|
||||||
|
const variables = {id: n.contentBlock};
|
||||||
|
const data = store.readQuery({
|
||||||
|
query,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
|
||||||
|
const bookmarks = data.contentBlock.bookmarks;
|
||||||
|
|
||||||
|
let index = bookmarks.findIndex(element => {
|
||||||
|
return element.uuid === n.content;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
let el = bookmarks[index];
|
||||||
|
el.note = note;
|
||||||
|
bookmarks.splice(index, 1, el);
|
||||||
|
}
|
||||||
|
|
||||||
|
data.contentBlock.bookmarks = bookmarks;
|
||||||
|
|
||||||
|
store.writeQuery({
|
||||||
|
data,
|
||||||
|
query,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
update = (store, {data: {addNote: {note}}}) => {
|
||||||
|
const type = getBlockType(n.parent) === 'ChapterNode' ? 'chapter' : 'module';
|
||||||
|
const query = type === 'chapter' ? CHAPTER_QUERY : MODULE_QUERY;
|
||||||
|
const variables = {id: n.parent};
|
||||||
|
const data = store.readQuery({
|
||||||
|
query,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
|
||||||
|
const bookmark = data[type].bookmark;
|
||||||
|
|
||||||
|
bookmark.note = note;
|
||||||
|
|
||||||
|
data[type].bookmark = bookmark;
|
||||||
|
|
||||||
|
store.writeQuery({
|
||||||
|
data,
|
||||||
|
query,
|
||||||
|
variables
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
mutation: ADD_NOTE_MUTATION,
|
||||||
|
variables: {
|
||||||
|
input: {
|
||||||
|
note: n
|
||||||
|
}
|
||||||
|
},
|
||||||
|
update,
|
||||||
|
optimisticResponse: {
|
||||||
|
__typename: 'Mutation',
|
||||||
|
addNote: {
|
||||||
|
__typename: 'AddNotePayload',
|
||||||
|
note: {
|
||||||
|
__typename: 'NoteNode',
|
||||||
|
id: -1,
|
||||||
|
text: n.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -22,6 +22,7 @@ export default new Vuex.Store({
|
||||||
parentProject: null,
|
parentProject: null,
|
||||||
currentNote: null,
|
currentNote: null,
|
||||||
currentProjectEntry: null,
|
currentProjectEntry: null,
|
||||||
|
currentNoteParent: '',
|
||||||
imageUrl: '',
|
imageUrl: '',
|
||||||
infographic: {
|
infographic: {
|
||||||
id: 0,
|
id: 0,
|
||||||
|
|
@ -46,6 +47,7 @@ export default new Vuex.Store({
|
||||||
currentContent: state => state.currentContent,
|
currentContent: state => state.currentContent,
|
||||||
currentContentBlock: state => state.currentContentBlock,
|
currentContentBlock: state => state.currentContentBlock,
|
||||||
currentNote: state => state.currentNote,
|
currentNote: state => state.currentNote,
|
||||||
|
currentNoteParent: state => state.currentNoteParent,
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
|
@ -61,6 +63,7 @@ export default new Vuex.Store({
|
||||||
commit('setCurrentRoomEntry', '');
|
commit('setCurrentRoomEntry', '');
|
||||||
commit('setCurrentContent', '');
|
commit('setCurrentContent', '');
|
||||||
commit('setCurrentContentBlock', '');
|
commit('setCurrentContentBlock', '');
|
||||||
|
commit('setCurrentNoteParent', '');
|
||||||
commit('setContentBlockPosition', {});
|
commit('setContentBlockPosition', {});
|
||||||
commit('setParentRoom', null);
|
commit('setParentRoom', null);
|
||||||
commit('setParentModule', '');
|
commit('setParentModule', '');
|
||||||
|
|
@ -126,8 +129,12 @@ export default new Vuex.Store({
|
||||||
dispatch('showModal', 'edit-project-entry-wizard');
|
dispatch('showModal', 'edit-project-entry-wizard');
|
||||||
},
|
},
|
||||||
addNote({commit, dispatch}, payload) {
|
addNote({commit, dispatch}, payload) {
|
||||||
commit('setCurrentContentBlock', payload.contentBlock);
|
if (payload.contentBlock) {
|
||||||
commit('setCurrentContent', payload.content);
|
commit('setCurrentContentBlock', payload.contentBlock);
|
||||||
|
commit('setCurrentContent', payload.content);
|
||||||
|
} else {
|
||||||
|
commit('setCurrentNoteParent', payload.parent);
|
||||||
|
}
|
||||||
dispatch('showModal', 'new-note-wizard');
|
dispatch('showModal', 'new-note-wizard');
|
||||||
},
|
},
|
||||||
editNote({commit, dispatch}, payload) {
|
editNote({commit, dispatch}, payload) {
|
||||||
|
|
@ -240,6 +247,9 @@ export default new Vuex.Store({
|
||||||
},
|
},
|
||||||
setEditModule(state, payload) {
|
setEditModule(state, payload) {
|
||||||
state.editModule = payload;
|
state.editModule = payload;
|
||||||
|
},
|
||||||
|
setCurrentNoteParent(state, payload) {
|
||||||
|
state.currentNoteParent = payload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,9 @@ from graphene import InputObjectType
|
||||||
|
|
||||||
|
|
||||||
class AddNoteArgument(InputObjectType):
|
class AddNoteArgument(InputObjectType):
|
||||||
content = graphene.UUID(required=True)
|
content = graphene.UUID()
|
||||||
content_block = graphene.ID(required=True)
|
content_block = graphene.ID()
|
||||||
|
parent = graphene.ID()
|
||||||
text = graphene.String(required=True)
|
text = graphene.String(required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ from builtins import PermissionError
|
||||||
import graphene
|
import graphene
|
||||||
import json
|
import json
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
|
from graphql_relay import from_global_id
|
||||||
|
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from books.models import ContentBlock, Chapter, Module
|
from books.models import ContentBlock, Chapter, Module
|
||||||
|
|
@ -56,16 +57,32 @@ class AddNote(relay.ClientIDMutation):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
note = kwargs.get('note')
|
note = kwargs.get('note')
|
||||||
content_uuid = note.get('content')
|
content_uuid = note.get('content', '')
|
||||||
content_block_id = note.get('content_block')
|
content_block_id = note.get('content_block', '')
|
||||||
content_block = get_object(ContentBlock, content_block_id)
|
parent = note.get('parent')
|
||||||
text = note.get('text')
|
text = note.get('text')
|
||||||
|
|
||||||
bookmark = ContentBlockBookmark.objects.get(
|
if content_uuid != '':
|
||||||
content_block=content_block,
|
content_block = get_object(ContentBlock, content_block_id)
|
||||||
uuid=content_uuid,
|
|
||||||
user=user
|
bookmark = ContentBlockBookmark.objects.get(
|
||||||
)
|
content_block=content_block,
|
||||||
|
uuid=content_uuid,
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
type, id = from_global_id(parent)
|
||||||
|
print(type)
|
||||||
|
if type == 'ModuleNode':
|
||||||
|
bookmark = ModuleBookmark.objects.get(
|
||||||
|
module__id=id,
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
bookmark = ChapterBookmark.objects.get(
|
||||||
|
chapter__id=id,
|
||||||
|
user=user
|
||||||
|
)
|
||||||
|
|
||||||
bookmark.note = Note.objects.create(text=text)
|
bookmark.note = Note.objects.create(text=text)
|
||||||
bookmark.save()
|
bookmark.save()
|
||||||
|
|
@ -88,13 +105,16 @@ class UpdateNote(relay.ClientIDMutation):
|
||||||
text = note.get('text')
|
text = note.get('text')
|
||||||
note = get_object(Note, id)
|
note = get_object(Note, id)
|
||||||
|
|
||||||
if note.contentblockbookmark.user != user:
|
if hasattr(note, 'contentblockbookmark') and note.contentblockbookmark.user != user \
|
||||||
|
or hasattr(note, 'chapterbookmark') and note.chapterbookmark.user != user \
|
||||||
|
or hasattr(note, 'modulebookmark') and note.modulebookmark.user != user:
|
||||||
raise PermissionError
|
raise PermissionError
|
||||||
|
|
||||||
note.text = text
|
note.text = text
|
||||||
note.save()
|
note.save()
|
||||||
return cls(note=note)
|
return cls(note=note)
|
||||||
|
|
||||||
|
|
||||||
class UpdateChapterBookmark(relay.ClientIDMutation):
|
class UpdateChapterBookmark(relay.ClientIDMutation):
|
||||||
class Input:
|
class Input:
|
||||||
chapter = graphene.ID(required=True)
|
chapter = graphene.ID(required=True)
|
||||||
|
|
@ -153,7 +173,6 @@ class UpdateModuleBookmark(relay.ClientIDMutation):
|
||||||
return cls(success=True)
|
return cls(success=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NoteMutations:
|
class NoteMutations:
|
||||||
add_note = AddNote.Field()
|
add_note = AddNote.Field()
|
||||||
update_note = UpdateNote.Field()
|
update_note = UpdateNote.Field()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue