import json import uuid import graphene from basicknowledge.models import BasicKnowledge from basicknowledge.queries import InstrumentNode from books.schema.nodes import ContentBlockNode, ModuleNode from books.schema.nodes.chapter import ChapterNode from core.logger import get_logger from graphene import relay from graphene_django import DjangoObjectType from notes.models import ( ChapterBookmark, ContentBlockBookmark, Highlight, InstrumentBookmark, ModuleBookmark, Note, ) 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', } from collections import deque def find_content_bfs(data, target_id): """ breadth-first search to find an object by its ID in a nested dictionary structure """ # Initialize a queue with the initial data list queue = deque(data) # Traverse through the data using BFS while queue: current = queue.popleft() # Check if the current dictionary has the target_id if current.get("id", "") == target_id: return current # If 'value' in current and it is a list, extend the queue with the items in 'value' if isinstance(current.get("value"), list): queue.extend(current["value"]) return None # If no matching ID is found def find_content(content_list, bookmark): content = find_content_bfs(content_list, str(bookmark.uuid)) if not content: logger.warn(f"Content not found: {bookmark.uuid}") return '' if content['type'] in ['text_block', 'subtitle', 'solution', 'section_title']: return content['value'].get('text', '') if content['type'] in ['basic_knowledge']: description = content['value'].get('description', '') if not description: try: return BasicKnowledge.objects.get(pk=content['value']['basic_knowledge']).title except BasicKnowledge.DoesNotExist: return '' return description if content_dict.get(content['type'], '') == "": logger.warn(f"Content type not found: {content['type']}") return content_dict.get(content['type'], '') class NoteNode(DjangoObjectType): pk = graphene.Int() class Meta: model = Note fields = "__all__" interfaces = (relay.Node,) def resolve_pk(self, *args, **kwargs): return self.id class ContentBlockBookmarkNode(DjangoObjectType): uuid = graphene.UUID() note = graphene.Field(NoteNode) path = graphene.String() content = graphene.String() class Meta: model = ContentBlockBookmark fields = "__all__" filter_fields = [] interfaces = (relay.Node,) @staticmethod 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 fields = "__all__" @staticmethod 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 fields = "__all__" filter_fields = [] interfaces = (relay.Node,) @staticmethod 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 fields = "__all__" filter_fields = [] interfaces = (relay.Node,) @staticmethod 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: types = ( ContentBlockBookmarkNode, ModuleBookmarkNode, ChapterBookmarkNode, InstrumentBookmarkNode, ) class HighlightableNode(graphene.Union): class Meta: types = (ContentBlockNode, InstrumentNode, ModuleNode, ChapterNode) class HighlightNode(DjangoObjectType): page = graphene.Field(HighlightableNode, required=True) class Meta: model = Highlight fields = "__all__" filter_fields = [] interfaces = (relay.Node,) @staticmethod def resolve_page(root: Highlight, *args, **kwargs): return root.page.specific