Add content to bookmark on Activity page

Resolves MS-903 #complete
This commit is contained in:
Ramon Wenger 2024-03-11 11:47:09 +01:00
parent 3cdbfa8abf
commit 7af5f07137
9 changed files with 1330 additions and 1961 deletions

3175
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@
"@babel/preset-stage-2": "^7.0.0",
"@babel/preset-typescript": "^7.16.7",
"@babel/runtime": "^7.5.4",
"@graphql-codegen/cli": "^5.0.0",
"@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/client-preset": "^4.1.0",
"@graphql-tools/jest-transform": "^1.2.2",
"@graphql-tools/mock": "^8.6.5",
@ -84,7 +84,7 @@
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-vue": "^9.6.0",
"graphql": "^16.3.0",
"graphql-config": "^4.3.0",
"graphql-config": "^5.0.3",
"graphql-tag": "^2.10.1",
"graphql-tools": "^8.2.5",
"jest": "^29.2.2",

View File

@ -1,3 +1,4 @@
/* eslint-disable */
import { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core';
import { FragmentDefinitionNode } from 'graphql';
import { Incremental } from './graphql';

View File

@ -38,7 +38,7 @@ const documents = {
"\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n ": types.ContentBlockHighlightsWithIdOnlyFragmentFragmentDoc,
"\n mutation UpdateInstrumentBookmark($input: UpdateInstrumentBookmarkInput!) {\n updateInstrumentBookmark(input: $input) {\n success\n }\n }\n ": types.UpdateInstrumentBookmarkDocument,
"\n mutation UpdateContentBookmark($input: UpdateContentBookmarkInput!) {\n updateContentBookmark(input: $input) {\n success\n }\n }\n ": types.UpdateContentBookmarkDocument,
"\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n ": types.MyActivitiesQueryDocument,
"\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n content\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n content\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n content\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n content\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n ": types.MyActivitiesQueryDocument,
"\n query ChapterQuery($id: ID!) {\n chapter(id: $id) {\n path\n }\n }\n ": types.ChapterQueryDocument,
"\n query ContentBlockQuery($id: ID!) {\n contentBlock(id: $id) {\n path\n }\n }\n ": types.ContentBlockQueryDocument,
"\n fragment InstrumentParts on InstrumentNode {\n id\n title\n intro\n slug\n language\n bookmarks {\n uuid\n note {\n id\n text\n }\n }\n type {\n id\n name\n category {\n id\n name\n foreground\n background\n }\n type\n }\n contents\n highlights {\n ...HighlightParts\n }\n }\n": types.InstrumentPartsFragmentDoc,
@ -166,7 +166,7 @@ export function graphql(source: "\n mutation UpdateContentBookmark($input:
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n "): (typeof documents)["\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n "];
export function graphql(source: "\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n content\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n content\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n content\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n content\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n "): (typeof documents)["\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n content\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n content\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n content\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n content\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n "];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,31 @@
<template>
<div>
Lesezeichen: <span>{{ content }}</span>
<div v-if="item.note">Notiz: {{ item.note.text }}</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
interface Item {
content: string;
note: {
text: string;
};
}
export interface Props {
item: Item;
}
const props = defineProps<Props>();
const stripHtml = (htmlString) => {
return htmlString.replace(/<[^>]*>?/gm, '') || '';
};
const content = computed(() => {
const strippedText = stripHtml(props.item.content) || '';
if (strippedText.length > 50) {
return strippedText.substring(0, 50) + '...';
}
return strippedText;
});
</script>

View File

@ -66,8 +66,7 @@
v-if="selectedCategory === BOOKMARKS"
v-slot="{ item }"
>
<div>Lesezeichen: {{ item.id }}</div>
<div v-if="item.note">Notiz: {{ item.note.text }}</div>
<bookmark :item="item" />
</instrument-activity-list>
<activity-list
:topics="bookmarkTopics"
@ -75,8 +74,7 @@
v-if="selectedCategory === BOOKMARKS"
v-slot="{ item }"
>
<div>Lesezeichen: {{ item.id }}</div>
<div v-if="item.note">Notiz: {{ item.note.text }}</div>
<bookmark :item="item" />
</activity-list>
<activity-list
:topics="submissionsTopics"
@ -106,6 +104,7 @@ import { ref, computed } from 'vue';
import ActivityList from '@/components/profile/ActivityList.vue';
import InstrumentActivityList from '@/components/profile/InstrumentActivityList.vue';
import LoadingMessage from '@/components/ui/LoadingMessage.vue';
import Bookmark from '@/components/Bookmark.vue';
import { TopicNode } from '@/__generated__/graphql';
const HIGHLIGHTS = 'highlights';
@ -131,6 +130,7 @@ const { result, loading } = useQuery(
bookmarks {
... on InstrumentBookmarkNode {
path
content
}
}
}
@ -151,6 +151,7 @@ const { result, loading } = useQuery(
path
}
path
content
note {
id
text
@ -160,6 +161,7 @@ const { result, loading } = useQuery(
id
uuid
path
content
contentBlock {
id
path
@ -171,6 +173,7 @@ const { result, loading } = useQuery(
}
... on ModuleBookmarkNode {
path
content
note {
id
text

View File

@ -1,3 +1,4 @@
import uuid
import graphene
from basicknowledge.queries import InstrumentNode
from books.schema.nodes import ContentBlockNode, ModuleNode
@ -16,6 +17,32 @@ from notes.models import (
logger = get_logger(__name__)
content_dict = {
'assignment': 'Auftrag',
'basic_knowledge': '',
'survey': 'Übung',
'image_block': 'Bild',
'link_block': 'Link',
'solution': 'Lösung',
'video_block': 'Video',
'document_block': 'Dokument',
'infogram_block': 'Infografik',
'genially_block': 'Infografik',
'thinglink_block': 'Infografik',
'subtitle': 'Titel',
'instruction': 'Anweisung',
'cms_document_block': 'Dokument',
}
def find_content(content_list, bookmark):
found = (content for content in content_list if uuid.UUID(content['id']) == bookmark.uuid)
content = next(found, None)
if content is None:
return ''
if content['type'] in ['text_block', 'subtitle', 'solution', 'basic_knowledge']:
return content['value']['text']
return content_dict.get(content['type'], '')
class NoteNode(DjangoObjectType):
pk = graphene.Int()
@ -33,6 +60,7 @@ class ContentBlockBookmarkNode(DjangoObjectType):
uuid = graphene.UUID()
note = graphene.Field(NoteNode)
path = graphene.String()
content = graphene.String()
class Meta:
model = ContentBlockBookmark
@ -44,10 +72,17 @@ class ContentBlockBookmarkNode(DjangoObjectType):
def resolve_path(root: ContentBlockBookmark, info, **kwargs):
return root.content_block.route
@staticmethod
def resolve_content(root: ContentBlockBookmark, info, **kwargs):
contents = root.content_block.contents.raw_data
return find_content(contents, root)
class ModuleBookmarkNode(DjangoObjectType):
note = graphene.Field(NoteNode)
path = graphene.String()
content = graphene.String()
class Meta:
model = ModuleBookmark
@ -57,10 +92,15 @@ class ModuleBookmarkNode(DjangoObjectType):
def resolve_path(root: ModuleBookmark, info, **kwargs):
return root.module.route
@staticmethod
def resolve_content(root: ModuleBookmark, info, **kwargs):
return root.module.intro
class ChapterBookmarkNode(DjangoObjectType):
note = graphene.Field(NoteNode)
path = graphene.String()
content = graphene.String()
class Meta:
model = ChapterBookmark
@ -72,11 +112,17 @@ class ChapterBookmarkNode(DjangoObjectType):
def resolve_path(root: ChapterBookmark, info, **kwargs):
return root.chapter.route
@staticmethod
def resolve_content(root: ChapterBookmark, info, **kwargs):
return root.chapter.description
class InstrumentBookmarkNode(DjangoObjectType):
uuid = graphene.UUID()
note = graphene.Field(NoteNode)
path = graphene.String(required=True)
content = graphene.String()
class Meta:
model = InstrumentBookmark
@ -88,6 +134,11 @@ class InstrumentBookmarkNode(DjangoObjectType):
def resolve_path(root: InstrumentBookmark, info, **kwargs):
return root.instrument.route
@staticmethod
def resolve_content(root: InstrumentBookmark, info, **kwargs):
contents = root.instrument.contents.raw_data
return find_content(contents, root)
class BookmarkNode(graphene.Union):
class Meta:

View File

@ -363,6 +363,7 @@ type ContentBlockBookmarkNode implements Node {
uuid: UUID
contentBlock: ContentBlockNode!
path: String
content: String
}
type NoteNode implements Node {
@ -383,6 +384,7 @@ type ModuleBookmarkNode {
note: NoteNode
module: ModuleNode!
path: String
content: String
}
type ChapterBookmarkNode implements Node {
@ -392,6 +394,7 @@ type ChapterBookmarkNode implements Node {
note: NoteNode
chapter: ChapterNode!
path: String
content: String
}
type ChapterNode implements Node & ChapterInterface {
@ -426,6 +429,7 @@ type InstrumentBookmarkNode implements Node {
uuid: UUID
instrument: InstrumentNode!
path: String!
content: String
}
"""