From b361c942c0772c535387376baabbec1b21ed89dc Mon Sep 17 00:00:00 2001
From: rhenck <richard.henck@iqb.hu-berlin.de>
Date: Fri, 21 Jan 2022 14:06:37 +0100
Subject: [PATCH] Fix cloze element to find child elements in lists and
 blockquotes

---
 .../common/ui-elements/cloze/cloze-element.ts | 32 +++++++++++++----
 projects/editor/src/app/util/cloze-parser.ts  | 34 ++++++++++++++-----
 2 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/projects/common/ui-elements/cloze/cloze-element.ts b/projects/common/ui-elements/cloze/cloze-element.ts
index 747c5fe6b..1beb29757 100644
--- a/projects/common/ui-elements/cloze/cloze-element.ts
+++ b/projects/common/ui-elements/cloze/cloze-element.ts
@@ -46,12 +46,32 @@ export class ClozeElement extends CompoundElement implements PositionedElement,
   }
 
   getChildElements(): InputElement[] {
-    return this.document.content
-      .filter((paragraph: ClozeDocumentParagraph) => paragraph.content) // filter empty paragraphs
-      .map((paragraph: ClozeDocumentParagraph) => paragraph.content // get custom paragraph parts
-        .filter((word: ClozeDocumentPart) => ['TextField', 'DropList', 'ToggleButton'].includes(word.type)))
-      .reduce((accumulator: any[], currentValue: any) => accumulator // put all collected paragraph parts into one list
-        .concat(currentValue.map((node: ClozeDocumentPart) => node.attrs?.model)), []); // model is in node.attrs.model
+    const elementList: InputElement[] = [];
+    this.document.content.forEach((documentPart: any) => {
+      if (documentPart.type === 'paragraph') {
+        elementList.push(...ClozeElement.getParagraphCustomElements(documentPart));
+      } else if (documentPart.type === 'bulletList' || documentPart.type === 'orderedList') {
+        documentPart.content.forEach((listItem: any) => {
+          listItem.content.forEach((listItemParagraph: any) => {
+            elementList.push(...ClozeElement.getParagraphCustomElements(listItemParagraph));
+          });
+        });
+      } else if (documentPart.type === 'blockquote') {
+        documentPart.content.forEach((blockQuoteItem: any) => {
+          elementList.push(...ClozeElement.getParagraphCustomElements(blockQuoteItem));
+        });
+      }
+    });
+    return elementList;
+  }
+
+  private static getParagraphCustomElements(documentPart: any): InputElement[] {
+    console.log('fff', documentPart);
+    return documentPart.content
+      .filter((word: ClozeDocumentPart) => ['TextField', 'DropList', 'ToggleButton'].includes(word.type))
+      .reduce((accumulator: any[], currentValue: any) => {
+        return accumulator.concat(currentValue.attrs.model);
+      }, []);
   }
 
   private handleBackwardsCompatibility(serializedElement: Partial<UIElement>): void {
diff --git a/projects/editor/src/app/util/cloze-parser.ts b/projects/editor/src/app/util/cloze-parser.ts
index 7805dcd3e..2f4b031b0 100644
--- a/projects/editor/src/app/util/cloze-parser.ts
+++ b/projects/editor/src/app/util/cloze-parser.ts
@@ -6,19 +6,35 @@ import { ToggleButtonElement } from '../../../../common/ui-elements/toggle-butto
 
 export abstract class ClozeParser {
   static setMissingIDs(clozeJSON: ClozeDocument, idService: IdService): ClozeDocument {
-    clozeJSON.content.forEach((paragraph: any) => {
-      paragraph.content?.forEach((node: any) => {
-        if (['ToggleButton', 'DropList', 'TextField'].includes(node.type) &&
-            node.attrs.model.id === 'id_placeholder') {
-          // create element anew because the TextEditor can't create multiple element instances
-          node.attrs.model = ClozeParser.createElement(node.attrs.model);
-          node.attrs.model.id = idService.getNewID(node.attrs.model.type);
-        }
-      });
+    clozeJSON.content.forEach((node: any) => {
+      if (node.type === 'paragraph') {
+        ClozeParser.createSubNodeElements(node, idService);
+      } else if (node.type === 'bulletList' || node.type === 'orderedList') {
+        node.content.forEach((listItem: any) => {
+          listItem.content.forEach((listItemParagraph: any) => {
+            ClozeParser.createSubNodeElements(listItemParagraph, idService);
+          });
+        });
+      } else if (node.type === 'blockquote') {
+        node.content.forEach((blockQuoteItem: any) => {
+          ClozeParser.createSubNodeElements(blockQuoteItem, idService);
+        });
+      }
     });
     return clozeJSON;
   }
 
+  // create element anew because the TextEditor can't create multiple element instances
+  private static createSubNodeElements(node: any, idService: IdService) {
+    node.content?.forEach((subNode: any) => {
+      if (['ToggleButton', 'DropList', 'TextField'].includes(subNode.type) &&
+        subNode.attrs.model.id === 'id_placeholder') {
+        subNode.attrs.model = ClozeParser.createElement(subNode.attrs.model);
+        subNode.attrs.model.id = idService.getNewID(subNode.attrs.model.type);
+      }
+    });
+  }
+
   private static createElement(elementModel: Partial<UIElement>): InputElement {
     let newElement: InputElement;
     switch (elementModel.type) {
-- 
GitLab