Merged in feature/instrument-notes (pull request #43)
Feature/instrument notes Approved-by: Christian Cueni <christian.cueni@iterativ.ch>
This commit is contained in:
commit
0d6a7522f2
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
methods: {
|
||||
hideModal() {
|
||||
this.$store.dispatch('resetCurrentContentBlock');
|
||||
this.$store.dispatch('resetCurrentNoteBlock');
|
||||
this.$store.dispatch('hideModal');
|
||||
},
|
||||
saveContentBlock(contentBlock) {
|
||||
|
|
@ -67,7 +67,7 @@
|
|||
return {
|
||||
query: CONTENT_BLOCK_QUERY,
|
||||
variables: {
|
||||
id: store.state.currentContentBlock
|
||||
id: store.state.currentNoteBlock
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@
|
|||
import Solution from '@/components/content-blocks/Solution';
|
||||
import BookmarkActions from '@/components/notes/BookmarkActions';
|
||||
|
||||
import UPDATE_CONTENT_BOOKMARK from '@/graphql/gql/mutations/updateContentBookmark.gql';
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
||||
import {constructContentComponentBookmarkMutation} from '@/helpers/update-content-bookmark-mutation';
|
||||
|
||||
export default {
|
||||
props: ['component', 'parent', 'bookmarks', 'notes', 'root'],
|
||||
|
|
@ -84,63 +83,15 @@
|
|||
addNote(id) {
|
||||
this.$store.dispatch('addNote', {
|
||||
content: id,
|
||||
contentBlock: this.root
|
||||
type: this.parent.__typename,
|
||||
block: this.root
|
||||
});
|
||||
},
|
||||
editNote() {
|
||||
this.$store.dispatch('editNote', this.note);
|
||||
},
|
||||
bookmarkContent(uuid, bookmarked) {
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_CONTENT_BOOKMARK,
|
||||
variables: {
|
||||
input: {
|
||||
uuid,
|
||||
contentBlock: this.root,
|
||||
bookmarked
|
||||
}
|
||||
},
|
||||
update: (store, response) => {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: this.root};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
|
||||
if (bookmarked) {
|
||||
bookmarks.push({
|
||||
note: null,
|
||||
uuid: uuid,
|
||||
__typename: 'ContentBlockBookmarkNode'
|
||||
});
|
||||
} else {
|
||||
let index = bookmarks.findIndex(element => {
|
||||
return element.uuid === uuid;
|
||||
});
|
||||
if (index > -1) {
|
||||
bookmarks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data.contentBlock.bookmarks = bookmarks;
|
||||
|
||||
store.writeQuery({
|
||||
data,
|
||||
query,
|
||||
variables
|
||||
});
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateContentBookmark: {
|
||||
__typename: 'UpdateContentBookmarkPayload',
|
||||
success: true
|
||||
}
|
||||
}
|
||||
});
|
||||
this.$apollo.mutate(constructContentComponentBookmarkMutation(uuid, bookmarked, this.parent, this.root));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import UPDATE_NOTE_MUTATION from '@/graphql/gql/mutations/updateNote.gql';
|
||||
import MODULE_DETAILS_QUERY from '@/graphql/gql/moduleDetailsQuery.gql';
|
||||
import INSTRUMENT_QUERY from '@/graphql/gql/instrumentQuery.gql';
|
||||
|
||||
import {mapGetters} from 'vuex';
|
||||
|
||||
|
|
@ -21,6 +22,9 @@
|
|||
|
||||
methods: {
|
||||
editNote(note) {
|
||||
const slug = this.$route.params.slug;
|
||||
const routeName = this.$route.name;
|
||||
|
||||
this.$apollo.mutate({
|
||||
mutation: UPDATE_NOTE_MUTATION,
|
||||
variables: {
|
||||
|
|
@ -28,12 +32,25 @@
|
|||
note
|
||||
}
|
||||
},
|
||||
refetchQueries: [{
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug: this.$route.params.slug
|
||||
refetchQueries() {
|
||||
let query;
|
||||
if (routeName === 'instrument') {
|
||||
query = {
|
||||
query: INSTRUMENT_QUERY,
|
||||
variables: {
|
||||
slug
|
||||
}
|
||||
}
|
||||
} else {
|
||||
query = {
|
||||
query: MODULE_DETAILS_QUERY,
|
||||
variables: {
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
return [query];
|
||||
}
|
||||
}).then(() => {
|
||||
this.$store.dispatch('hideModal');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,21 +20,23 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['currentContent', 'currentContentBlock', 'currentNoteParent'])
|
||||
...mapGetters(['currentContent', 'currentNoteBlock', 'currentNoteParent', 'noteType'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
addNote(n) {
|
||||
const content = this.currentContent;
|
||||
const contentBlock = this.currentContentBlock;
|
||||
const block = this.currentNoteBlock;
|
||||
const parent = this.currentNoteParent;
|
||||
const type = this.noteType;
|
||||
const text = n.text;
|
||||
let note = {};
|
||||
if (content > '') {
|
||||
note = {
|
||||
content,
|
||||
contentBlock,
|
||||
text
|
||||
block,
|
||||
text,
|
||||
type
|
||||
}
|
||||
} else {
|
||||
note = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {InMemoryCache} from 'apollo-cache-inmemory/lib/index'
|
||||
import {InMemoryCache, defaultDataIdFromObject} from 'apollo-cache-inmemory/lib/index'
|
||||
import {createHttpLink} from 'apollo-link-http'
|
||||
import {ApolloClient} from 'apollo-client'
|
||||
import {ApolloLink} from 'apollo-link'
|
||||
|
|
@ -43,6 +43,14 @@ export default function (uri) {
|
|||
const composedLink = ApolloLink.from([createOmitTypenameLink, consoleLink, httpLink]);
|
||||
|
||||
const cache = new InMemoryCache({
|
||||
dataIdFromObject: obj => {
|
||||
switch (obj.__typename) {
|
||||
case 'InstrumentNode':
|
||||
return `${obj.__typename}:${obj.slug}`;
|
||||
default:
|
||||
return defaultDataIdFromObject(obj);
|
||||
}
|
||||
},
|
||||
cacheRedirects: {
|
||||
Query: {
|
||||
contentBlock: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ContentBlockNode', id: args.id}),
|
||||
|
|
@ -51,7 +59,7 @@ export default function (uri) {
|
|||
objective: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveNode', id: args.id}),
|
||||
objectiveGroup: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveGroupNode', id: args.id}),
|
||||
// todo: remove, the new client seems to cache this correctly by itself
|
||||
// module: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ModuleNode', id: args.id}),
|
||||
// module: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ModuleNode', id: args.slug}),
|
||||
projectEntry: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ProjectEntryNode', id: args.id}),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
query BookQuery {
|
||||
books {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
topics {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
teaser
|
||||
description
|
||||
modules {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
title
|
||||
slug
|
||||
teaser
|
||||
heroImage
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
fragment InstrumentParts on InstrumentNode {
|
||||
id
|
||||
title
|
||||
slug
|
||||
bookmarks {
|
||||
uuid
|
||||
note {
|
||||
id
|
||||
text
|
||||
}
|
||||
}
|
||||
type
|
||||
contents
|
||||
}
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
#import "./fragments/instrumentParts.gql"
|
||||
query InstrumentQuery($slug: String!){
|
||||
instrument(slug: $slug) {
|
||||
id
|
||||
title
|
||||
slug
|
||||
type
|
||||
contents
|
||||
...InstrumentParts
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
#import "./fragments/instrumentParts.gql"
|
||||
query InstrumentQuery($id: ID!){
|
||||
instrument(id: $id) {
|
||||
...InstrumentParts
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
mutation UpdateInstrumentBookmark($input: UpdateInstrumentBookmarkInput!) {
|
||||
updateInstrumentBookmark(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
|
|
@ -2,41 +2,68 @@ 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';
|
||||
import INSTRUMENT_FRAGMENT from '@/graphql/gql/fragments/instrumentParts.gql';
|
||||
|
||||
const getBlockType = id => atob(id).split(':')[0]
|
||||
const getBlockType = id => atob(id).split(':')[0];
|
||||
const compareUuid = note => element => element.uuid === note.content;
|
||||
|
||||
export const constructNoteMutation = (n) => {
|
||||
let update = () => {
|
||||
};
|
||||
|
||||
if (n.contentBlock) { // has a content block, so it is a content block bookmark
|
||||
if (n.block) { // has a block, so it is a content block or instrument bookmark
|
||||
update = (store, {data: {addNote: {note}}}) => {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: n.contentBlock};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
if (n.type === 'ContentBlockNode') {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: n.block};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
|
||||
let index = bookmarks.findIndex(element => {
|
||||
return element.uuid === n.content;
|
||||
});
|
||||
let index = bookmarks.findIndex(compareUuid(n));
|
||||
|
||||
if (index > -1) {
|
||||
let el = bookmarks[index];
|
||||
el.note = note;
|
||||
bookmarks.splice(index, 1, el);
|
||||
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 {
|
||||
const fragment = INSTRUMENT_FRAGMENT;
|
||||
const id = `InstrumentNode:${n.block}`;
|
||||
const data = store.readFragment({
|
||||
fragment,
|
||||
id
|
||||
});
|
||||
|
||||
const bookmarks = data.bookmarks;
|
||||
|
||||
let index = bookmarks.findIndex(compareUuid(n));
|
||||
|
||||
if (index > -1) {
|
||||
let el = bookmarks[index];
|
||||
el.note = note;
|
||||
bookmarks.splice(index, 1, el);
|
||||
}
|
||||
|
||||
data.bookmarks = bookmarks;
|
||||
|
||||
store.writeFragment({
|
||||
data,
|
||||
fragment,
|
||||
id
|
||||
});
|
||||
}
|
||||
|
||||
data.contentBlock.bookmarks = bookmarks;
|
||||
|
||||
store.writeQuery({
|
||||
data,
|
||||
query,
|
||||
variables
|
||||
});
|
||||
};
|
||||
} else { // it's a chapter bookmark or a module bookmark
|
||||
update = (store, {data: {addNote: {note}}}) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
import UPDATE_CONTENT_BOOKMARK from '@/graphql/gql/mutations/updateContentBookmark.gql';
|
||||
import UPDATE_INSTRUMENT_BOOKMARK from '@/graphql/gql/mutations/updateInstrumentBookmark.gql';
|
||||
import CONTENT_BLOCK_QUERY from '@/graphql/gql/contentBlockQuery.gql';
|
||||
import INSTRUMENT_FRAGMENT from '@/graphql/gql/fragments/instrumentParts.gql';
|
||||
|
||||
const compareUuid = uuid => element => element.uuid === uuid;
|
||||
|
||||
export const constructContentComponentBookmarkMutation = (uuid, bookmarked, parent, root) => {
|
||||
let mutation = {};
|
||||
|
||||
if (parent.__typename === 'ContentBlockNode') {
|
||||
mutation = {
|
||||
mutation: UPDATE_CONTENT_BOOKMARK,
|
||||
variables: {
|
||||
input: {
|
||||
uuid,
|
||||
contentBlock: root,
|
||||
bookmarked
|
||||
}
|
||||
},
|
||||
update: (store, response) => {
|
||||
const query = CONTENT_BLOCK_QUERY;
|
||||
const variables = {id: root};
|
||||
const data = store.readQuery({
|
||||
query,
|
||||
variables
|
||||
});
|
||||
|
||||
const bookmarks = data.contentBlock.bookmarks;
|
||||
|
||||
if (bookmarked) {
|
||||
bookmarks.push({
|
||||
note: null,
|
||||
uuid,
|
||||
__typename: 'ContentBlockBookmarkNode'
|
||||
});
|
||||
} else {
|
||||
let index = bookmarks.findIndex(compareUuid(uuid));
|
||||
if (index > -1) {
|
||||
bookmarks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data.contentBlock.bookmarks = bookmarks;
|
||||
|
||||
store.writeQuery({
|
||||
data,
|
||||
query,
|
||||
variables
|
||||
});
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateContentBookmark: {
|
||||
__typename: 'UpdateContentBookmarkPayload',
|
||||
success: true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mutation = {
|
||||
mutation: UPDATE_INSTRUMENT_BOOKMARK,
|
||||
variables: {
|
||||
input: {
|
||||
uuid,
|
||||
instrument: root,
|
||||
bookmarked
|
||||
}
|
||||
},
|
||||
update: (store, response) => {
|
||||
const fragment = INSTRUMENT_FRAGMENT;
|
||||
const id = `InstrumentNode:${root}`;
|
||||
const data = store.readFragment({
|
||||
fragment,
|
||||
id
|
||||
});
|
||||
|
||||
const bookmarks = data.bookmarks;
|
||||
|
||||
if (bookmarked) {
|
||||
bookmarks.push({
|
||||
note: null,
|
||||
uuid,
|
||||
__typename: 'InstrumentBookmarkNode'
|
||||
})
|
||||
} else {
|
||||
let index = bookmarks.findIndex(compareUuid(uuid));
|
||||
if (index > -1) {
|
||||
bookmarks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data.bookmarks = bookmarks;
|
||||
|
||||
store.writeFragment({
|
||||
data,
|
||||
fragment,
|
||||
id
|
||||
});
|
||||
},
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateInstrumentBookmark: {
|
||||
__typename: 'UpdateInstrumentBookmarkPayload',
|
||||
success: true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return mutation;
|
||||
};
|
||||
|
|
@ -2,11 +2,15 @@
|
|||
<div class="instrument">
|
||||
<h1 class="instrument__title">{{instrument.title}}</h1>
|
||||
|
||||
<component v-for="component in instrument.contents"
|
||||
:key="component.id"
|
||||
:is="component.type"
|
||||
v-bind="component">
|
||||
</component>
|
||||
<content-component v-for="component in instrument.contents"
|
||||
:key="component.id"
|
||||
:component="component"
|
||||
:root="instrument.slug"
|
||||
:parent="instrument"
|
||||
:bookmarks="instrument.bookmarks"
|
||||
:notes="instrument.notes"
|
||||
>
|
||||
</content-component>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -14,17 +18,7 @@
|
|||
<script>
|
||||
import INSTRUMENT_QUERY from '@/graphql/gql/instrumentQuery.gql';
|
||||
|
||||
import TextBlock from '@/components/content-blocks/TextBlock';
|
||||
import InstrumentWidget from '@/components/content-blocks/InstrumentWidget';
|
||||
import ImageBlock from '@/components/content-blocks/ImageBlock';
|
||||
import ImageUrlBlock from '@/components/content-blocks/ImageUrlBlock';
|
||||
import VideoBlock from '@/components/content-blocks/VideoBlock';
|
||||
import LinkBlock from '@/components/content-blocks/LinkBlock';
|
||||
import DocumentBlock from '@/components/content-blocks/DocumentBlock';
|
||||
import SectionTitleBlock from '@/components/content-blocks/SectionTitleBlock';
|
||||
import SubtitleBlock from '@/components/content-blocks/SubtitleBlock';
|
||||
import GeniallyBlock from '@/components/content-blocks/GeniallyBlock';
|
||||
import ThinglinkBlock from '@/components/content-blocks/ThinglinkBlock';
|
||||
import ContentComponent from '@/components/content-blocks/ContentComponent';
|
||||
|
||||
export default {
|
||||
apollo: {
|
||||
|
|
@ -39,18 +33,7 @@
|
|||
},
|
||||
|
||||
components: {
|
||||
'text_block': TextBlock,
|
||||
'basic_knowledge': InstrumentWidget, // for legacy
|
||||
'instrument': InstrumentWidget,
|
||||
'image_block': ImageBlock,
|
||||
'image_url_block': ImageUrlBlock,
|
||||
'video_block': VideoBlock,
|
||||
'link_block': LinkBlock,
|
||||
'document_block': DocumentBlock,
|
||||
'section_title': SectionTitleBlock,
|
||||
'subtitle': SubtitleBlock,
|
||||
'genially_block': GeniallyBlock,
|
||||
'thinglink_block': ThinglinkBlock
|
||||
ContentComponent
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ export default new Vuex.Store({
|
|||
contentBlockPosition: {},
|
||||
scrollPosition: 0,
|
||||
currentContent: '',
|
||||
currentContentBlock: '',
|
||||
currentNoteBlock: '',
|
||||
noteType: '',
|
||||
currentRoomEntry: '',
|
||||
parentRoom: null,
|
||||
parentModule: '',
|
||||
|
|
@ -46,9 +47,10 @@ export default new Vuex.Store({
|
|||
editModule: state => state.editModule,
|
||||
currentObjectiveGroup: state => state.currentObjectiveGroup,
|
||||
currentContent: state => state.currentContent,
|
||||
currentContentBlock: state => state.currentContentBlock,
|
||||
currentNoteBlock: state => state.currentNoteBlock,
|
||||
currentNote: state => state.currentNote,
|
||||
currentNoteParent: state => state.currentNoteParent,
|
||||
noteType: state => state.noteType,
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
|
@ -63,7 +65,7 @@ export default new Vuex.Store({
|
|||
resetModalState({commit}) {
|
||||
commit('setCurrentRoomEntry', '');
|
||||
commit('setCurrentContent', '');
|
||||
commit('setCurrentContentBlock', '');
|
||||
commit('setCurrentNoteBlock', '');
|
||||
commit('setCurrentNoteParent', '');
|
||||
commit('setContentBlockPosition', {});
|
||||
commit('setParentRoom', null);
|
||||
|
|
@ -80,15 +82,16 @@ export default new Vuex.Store({
|
|||
});
|
||||
commit('setVimeoId', null);
|
||||
commit('setCurrentNote', null);
|
||||
commit('setNoteType', '');
|
||||
},
|
||||
resetContentBlockPosition({commit}) {
|
||||
commit('setContentBlockPosition', {});
|
||||
},
|
||||
resetCurrentContentBlock({commit}) {
|
||||
commit('setCurrentContentBlock', '');
|
||||
resetCurrentNoteBlock({commit}) {
|
||||
commit('setCurrentNoteBlock', '');
|
||||
},
|
||||
editContentBlock({commit, dispatch}, payload) {
|
||||
commit('setCurrentContentBlock', payload);
|
||||
commit('setCurrentNoteBlock', payload);
|
||||
dispatch('showModal', 'edit-content-block-wizard');
|
||||
},
|
||||
addContentBlock({commit, dispatch}, payload) {
|
||||
|
|
@ -130,8 +133,9 @@ export default new Vuex.Store({
|
|||
dispatch('showModal', 'edit-project-entry-wizard');
|
||||
},
|
||||
addNote({commit, dispatch}, payload) {
|
||||
if (payload.contentBlock) {
|
||||
commit('setCurrentContentBlock', payload.contentBlock);
|
||||
if (payload.block) {
|
||||
commit('setCurrentNoteBlock', payload.block);
|
||||
commit('setNoteType', payload.type);
|
||||
commit('setCurrentContent', payload.content);
|
||||
} else {
|
||||
commit('setCurrentNoteParent', payload.parent);
|
||||
|
|
@ -197,8 +201,8 @@ export default new Vuex.Store({
|
|||
setCurrentContent(state, payload) {
|
||||
state.currentContent = payload;
|
||||
},
|
||||
setCurrentContentBlock(state, payload) {
|
||||
state.currentContentBlock = payload;
|
||||
setCurrentNoteBlock(state, payload) {
|
||||
state.currentNoteBlock = payload;
|
||||
},
|
||||
setParentRoom(state, payload) {
|
||||
state.parentRoom = payload;
|
||||
|
|
@ -251,6 +255,9 @@ export default new Vuex.Store({
|
|||
},
|
||||
setCurrentNoteParent(state, payload) {
|
||||
state.currentNoteParent = payload;
|
||||
},
|
||||
setNoteType(state, payload) {
|
||||
state.noteType = payload;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -4,10 +4,14 @@ from graphene_django import DjangoObjectType
|
|||
from graphene_django.filter import DjangoFilterConnectionField
|
||||
|
||||
from api.utils import get_object
|
||||
from notes.models import InstrumentBookmark
|
||||
from notes.schema import InstrumentBookmarkNode
|
||||
from .models import BasicKnowledge
|
||||
|
||||
|
||||
class BasicKnowledgeNode(DjangoObjectType):
|
||||
class InstrumentNode(DjangoObjectType):
|
||||
bookmarks = graphene.List(InstrumentBookmarkNode)
|
||||
|
||||
class Meta:
|
||||
model = BasicKnowledge
|
||||
filter_fields = ['slug', 'type']
|
||||
|
|
@ -16,17 +20,23 @@ class BasicKnowledgeNode(DjangoObjectType):
|
|||
'slug', 'title', 'type', 'contents',
|
||||
]
|
||||
|
||||
def resolve_bookmarks(self, info, **kwargs):
|
||||
return InstrumentBookmark.objects.filter(
|
||||
user=info.context.user,
|
||||
instrument=self
|
||||
)
|
||||
|
||||
|
||||
class BasicKnowledgeQuery(object):
|
||||
instrument = graphene.Field(BasicKnowledgeNode, slug=graphene.String(), id=graphene.ID())
|
||||
instruments = DjangoFilterConnectionField(BasicKnowledgeNode)
|
||||
instrument = graphene.Field(InstrumentNode, slug=graphene.String(), id=graphene.ID())
|
||||
instruments = DjangoFilterConnectionField(InstrumentNode)
|
||||
|
||||
def resolve_instrument(self, info, **kwargs):
|
||||
slug = kwargs.get('slug')
|
||||
room_id = kwargs.get('id')
|
||||
instrument_id = kwargs.get('id')
|
||||
|
||||
if room_id is not None:
|
||||
return get_object(BasicKnowledge, room_id)
|
||||
if instrument_id is not None:
|
||||
return get_object(BasicKnowledge, instrument_id)
|
||||
if slug is not None:
|
||||
return BasicKnowledge.objects.get(slug=slug)
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class ContentBlockNode(DjangoObjectType):
|
|||
def resolve_contents(self, info, **kwargs):
|
||||
updated_stream_data = []
|
||||
for content in self.contents.stream_data:
|
||||
if not are_solutions_enabled_for(info.context.user, self.module) and content['type'] == 'solution':
|
||||
if content['type'] == 'solution' and not are_solutions_enabled_for(info.context.user, self.module):
|
||||
continue
|
||||
|
||||
if content['type'] == 'content_list_item':
|
||||
|
|
@ -85,18 +85,21 @@ class ChapterNode(DjangoObjectType):
|
|||
def resolve_content_blocks(self, info, **kwargs):
|
||||
user = info.context.user
|
||||
school_classes = user.school_classes.values_list('pk')
|
||||
by_parent = ContentBlock.get_by_parent(self).prefetch_related(
|
||||
'visible_for__schoolclass').prefetch_related(
|
||||
'hidden_for__schoolclass')
|
||||
|
||||
if user.has_perm('users.can_manage_school_class_content'): # teacher
|
||||
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False)
|
||||
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
||||
publisher_content_blocks = by_parent.filter(user_created=False)
|
||||
user_created_content_blocks = by_parent.filter(user_created=True, owner=user)
|
||||
else: # student
|
||||
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False).exclude(
|
||||
publisher_content_blocks = by_parent.filter(user_created=False).exclude(
|
||||
hidden_for__in=school_classes)
|
||||
|
||||
self_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
||||
self_created_content_blocks = by_parent.filter(user_created=True, owner=user)
|
||||
|
||||
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True,
|
||||
visible_for__in=school_classes).union(
|
||||
user_created_content_blocks = by_parent.filter(user_created=True,
|
||||
visible_for__in=school_classes).union(
|
||||
self_created_content_blocks)
|
||||
|
||||
return publisher_content_blocks.union(user_created_content_blocks)
|
||||
|
|
@ -180,6 +183,12 @@ class ModuleNode(DjangoObjectType):
|
|||
chapters = Chapter.objects.live().descendant_of(self)
|
||||
return ChapterBookmark.objects.filter(chapter__in=chapters, user=user)
|
||||
|
||||
def resolve_objective_groups(self, root, **kwargs):
|
||||
return self.objective_groups.all() \
|
||||
.prefetch_related('hidden_for__schoolclass') \
|
||||
.prefetch_related('visible_for__schoolclass') \
|
||||
.prefetch_related('objectives__objective_progress')
|
||||
|
||||
|
||||
class TopicNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
|
|
@ -278,6 +287,7 @@ class BookQuery(object):
|
|||
elif slug is not None:
|
||||
module = Module.objects.get(slug=slug)
|
||||
|
||||
|
||||
return module
|
||||
|
||||
def resolve_topic(self, info, **kwargs):
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ if DEBUG:
|
|||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'whitenoise.middleware.WhiteNoiseMiddleware',
|
||||
'django.middleware.gzip.GZipMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware'
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from graphene import InputObjectType
|
|||
|
||||
class AddNoteArgument(InputObjectType):
|
||||
content = graphene.UUID()
|
||||
content_block = graphene.ID()
|
||||
block = graphene.String()
|
||||
type = graphene.String()
|
||||
parent = graphene.ID()
|
||||
text = graphene.String(required=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 2.0.6 on 2020-01-08 12:54
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('basicknowledge', '0004_auto_20191128_1601'),
|
||||
('notes', '0002_chapterbookmark_modulebookmark'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='InstrumentBookmark',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('uuid', models.UUIDField(unique=True)),
|
||||
('instrument', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='basicknowledge.BasicKnowledge')),
|
||||
('note', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='notes.Note')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -28,3 +28,7 @@ class ModuleBookmark(Bookmark):
|
|||
|
||||
class ChapterBookmark(Bookmark):
|
||||
chapter = models.ForeignKey('books.Chapter', on_delete=models.CASCADE)
|
||||
|
||||
class InstrumentBookmark(Bookmark):
|
||||
uuid = models.UUIDField(unique=True)
|
||||
instrument = models.ForeignKey('basicknowledge.BasicKnowledge', on_delete=models.CASCADE)
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ from graphene import relay
|
|||
from graphql_relay import from_global_id
|
||||
|
||||
from api.utils import get_object
|
||||
from basicknowledge.models import BasicKnowledge
|
||||
from books.models import ContentBlock, Chapter, Module
|
||||
from notes.inputs import AddNoteArgument, UpdateNoteArgument
|
||||
from notes.models import ContentBlockBookmark, Note, ChapterBookmark, ModuleBookmark
|
||||
from notes.models import ContentBlockBookmark, Note, ChapterBookmark, ModuleBookmark, InstrumentBookmark
|
||||
from notes.schema import NoteNode
|
||||
|
||||
|
||||
|
|
@ -58,18 +59,27 @@ class AddNote(relay.ClientIDMutation):
|
|||
|
||||
note = kwargs.get('note')
|
||||
content_uuid = note.get('content', '')
|
||||
content_block_id = note.get('content_block', '')
|
||||
content_block_id = note.get('block', '')
|
||||
parent = note.get('parent')
|
||||
text = note.get('text')
|
||||
|
||||
if content_uuid != '':
|
||||
content_block = get_object(ContentBlock, content_block_id)
|
||||
type = note.get('type')
|
||||
if type == 'ContentBlockNode':
|
||||
content_block = get_object(ContentBlock, content_block_id)
|
||||
|
||||
bookmark = ContentBlockBookmark.objects.get(
|
||||
content_block=content_block,
|
||||
uuid=content_uuid,
|
||||
user=user
|
||||
)
|
||||
bookmark = ContentBlockBookmark.objects.get(
|
||||
content_block=content_block,
|
||||
uuid=content_uuid,
|
||||
user=user
|
||||
)
|
||||
else:
|
||||
instrument = BasicKnowledge.objects.get(slug=content_block_id)
|
||||
bookmark = InstrumentBookmark.objects.get(
|
||||
instrument=instrument,
|
||||
uuid=content_uuid,
|
||||
user=user
|
||||
)
|
||||
else:
|
||||
type, id = from_global_id(parent)
|
||||
if type == 'ModuleNode':
|
||||
|
|
@ -172,9 +182,43 @@ class UpdateModuleBookmark(relay.ClientIDMutation):
|
|||
return cls(success=True)
|
||||
|
||||
|
||||
class UpdateInstrumentBookmark(relay.ClientIDMutation):
|
||||
class Input:
|
||||
uuid = graphene.UUID(required=True)
|
||||
instrument = graphene.String(required=True)
|
||||
bookmarked = graphene.Boolean(required=True)
|
||||
|
||||
success = graphene.Boolean()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||
user = info.context.user
|
||||
instrument_slug = kwargs.get('instrument')
|
||||
uuid = kwargs.get('uuid')
|
||||
bookmarked = kwargs.get('bookmarked')
|
||||
|
||||
instrument = BasicKnowledge.objects.get(slug=instrument_slug)
|
||||
|
||||
if bookmarked:
|
||||
InstrumentBookmark.objects.create(
|
||||
instrument=instrument,
|
||||
uuid=uuid,
|
||||
user=user
|
||||
)
|
||||
else:
|
||||
InstrumentBookmark.objects.get(
|
||||
instrument=instrument,
|
||||
uuid=uuid,
|
||||
user=user
|
||||
).delete()
|
||||
|
||||
return cls(success=True)
|
||||
|
||||
|
||||
class NoteMutations:
|
||||
add_note = AddNote.Field()
|
||||
update_note = UpdateNote.Field()
|
||||
update_content_bookmark = UpdateContentBookmark.Field()
|
||||
update_chapter_bookmark = UpdateChapterBookmark.Field()
|
||||
update_module_bookmark = UpdateModuleBookmark.Field()
|
||||
update_instrument_bookmark = UpdateInstrumentBookmark.Field()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import graphene
|
|||
from graphene import relay
|
||||
from graphene_django import DjangoObjectType
|
||||
|
||||
from notes.models import Note, ContentBlockBookmark, ModuleBookmark, ChapterBookmark
|
||||
from notes.models import Note, ContentBlockBookmark, ModuleBookmark, ChapterBookmark, InstrumentBookmark
|
||||
|
||||
|
||||
class NoteNode(DjangoObjectType):
|
||||
|
|
@ -17,7 +17,6 @@ class NoteNode(DjangoObjectType):
|
|||
|
||||
|
||||
class ContentBlockBookmarkNode(DjangoObjectType):
|
||||
# note = graphene.
|
||||
uuid = graphene.UUID()
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
|
|
@ -41,3 +40,13 @@ class ChapterBookmarkNode(DjangoObjectType):
|
|||
model = ChapterBookmark
|
||||
filter_fields = []
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
|
||||
class InstrumentBookmarkNode(DjangoObjectType):
|
||||
uuid = graphene.UUID()
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
class Meta:
|
||||
model = InstrumentBookmark
|
||||
filter_fields = []
|
||||
interfaces = (relay.Node,)
|
||||
|
|
|
|||
Loading…
Reference in New Issue