From 8672172b7cff247eea7cfe91d9ce5f1396b47235 Mon Sep 17 00:00:00 2001
From: Ruben Bimberg <ruben.bimberg@mni.thm.de>
Date: Wed, 4 Aug 2021 10:25:14 +0200
Subject: [PATCH] Fix issues with the comment creation

Some changes were not updated correctly
and wrong data were displayed in the preview.

[Ticket: #214][Ticket: #215][Ticket: #216]
---
 .../create-comment.component.html             |   6 +-
 .../create-comment.component.ts               |   1 +
 .../comment-answer.component.html             |  12 +-
 .../comment-answer.component.ts               |   1 +
 src/app/utils/grammar-checker.ts              | 157 +++++++++---------
 5 files changed, 94 insertions(+), 83 deletions(-)

diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
index 66e9ee29f..02b9130f9 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.html
@@ -36,7 +36,7 @@
         </mat-form-field>
       </div>
     </div>
-    <mat-tab-group>
+    <mat-tab-group (selectedTabChange)="tempEditView = commentBody.innerText">
       <mat-tab label="{{ 'comment-page.write-comment' | translate }}">
         <ars-row [height]="12"></ars-row>
         <ars-row>
@@ -70,7 +70,7 @@
             </mat-hint>
             <mat-hint align="end">
               <span aria-hidden="true">
-                {{commentBody.innerHTML.length}} / {{user.role === 3 ? 1000 : 500}}
+                {{commentBody.innerText.length}} / {{user.role === 3 ? 1000 : 500}}
               </span>
             </mat-hint>
             <span *ngIf="!grammarChecker.hasSpellcheckConfidence">
@@ -89,7 +89,7 @@
         <ars-row [height]="12"></ars-row>
         <ars-row>
           <markdown katex emoji lineNumbers lineHighlight
-                    [data]="commentBody.innerText"></markdown>
+                    [data]="tempEditView"></markdown>
         </ars-row>
       </mat-tab>
     </mat-tab-group>
diff --git a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
index e7e23677a..b282c5bef 100644
--- a/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
+++ b/src/app/components/shared/_dialogs/create-comment/create-comment.component.ts
@@ -25,6 +25,7 @@ export class CreateCommentComponent implements OnInit {
   selectedTag: string;
   isSendingToSpacy = false;
   grammarChecker: GrammarChecker;
+  tempEditView: string;
 
   constructor(
     private notification: NotificationService,
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.html b/src/app/components/shared/comment-answer/comment-answer.component.html
index aab408107..edae65f08 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.html
+++ b/src/app/components/shared/comment-answer/comment-answer.component.html
@@ -47,7 +47,7 @@
         </button>
       </div>
       <div *ngIf="!isStudent && (edit || !answer)">
-        <mat-tab-group [dynamicHeight]="false">
+        <mat-tab-group [dynamicHeight]="false" (selectedTabChange)="tempEditView = commentBody.innerText">
           <mat-tab label="{{'comment-page.your-answer' | translate}}">
             <mat-divider></mat-divider>
             <mat-form-field class="input-block">
@@ -63,7 +63,7 @@
                 #commentBody
                 aria-labelledby="ask-question-description"
                 autofocus
-                (input)="grammarChecker.maxLength(commentBody, 2000); answer = commentBody.innerText"
+                (input)="grammarChecker.maxLength(commentBody, 2000);"
                 id="answer-input">
               </div>
               <mat-hint align="start">
@@ -73,15 +73,15 @@
               </mat-hint>
               <mat-hint align="end">
             <span aria-hidden="true">
-              {{ answer ? answer.length : 0 }} / 2000
+              {{ commentBody.innerText ? commentBody.innerText.length : 0 }} / 2000
             </span>
               </mat-hint>
             </mat-form-field>
           </mat-tab>
           <mat-tab label="{{'session.preview' | translate}}"
-                   [disabled]="!answer">
+                   [disabled]="!commentBody.innerText">
             <markdown class="images" katex emoji lineNumbers lineHighlight
-                      [data]="answer"></markdown>
+                      [data]="tempEditView"></markdown>
           </mat-tab>
         </mat-tab-group>
         <ars-row ars-flex-box class="spellcheck">
@@ -100,7 +100,7 @@
           </ars-col>
           <ars-col style="display: flex; flex-direction: row;">
             <button mat-raised-button
-                    *ngIf="answer"
+                    *ngIf="answer || commentBody.innerText"
                     class="delete"
                     style="display: inline-block"
                     (click)="openDeleteAnswerDialog()">
diff --git a/src/app/components/shared/comment-answer/comment-answer.component.ts b/src/app/components/shared/comment-answer/comment-answer.component.ts
index 291f7d7da..14c8144cc 100644
--- a/src/app/components/shared/comment-answer/comment-answer.component.ts
+++ b/src/app/components/shared/comment-answer/comment-answer.component.ts
@@ -30,6 +30,7 @@ export class CommentAnswerComponent implements OnInit {
   edit = false;
 
   grammarChecker: GrammarChecker;
+  tempEditView: string;
 
   @ViewChild('commentBody') commentBody: ElementRef<HTMLDivElement>;
 
diff --git a/src/app/utils/grammar-checker.ts b/src/app/utils/grammar-checker.ts
index 2524e73a9..9e40714c8 100644
--- a/src/app/utils/grammar-checker.ts
+++ b/src/app/utils/grammar-checker.ts
@@ -15,8 +15,9 @@ export class GrammarChecker {
   onDocumentClick(e) {
     const container = document.getElementsByClassName('dropdownBlock');
     Array.prototype.forEach.call(container, (elem) => {
-      if (!elem.contains(e.target) && (!(e.target as Node).parentElement.classList.contains('markUp')
-        || (e.target as HTMLElement).dataset.id !== ((elem as Node).parentElement as HTMLElement).dataset.id)) {
+      const hasMarkup = (e.target as Node).parentElement ? (e.target as Node).parentElement.classList.contains('markUp') : false;
+      if (!elem.contains(e.target) && (!hasMarkup ||
+        (e.target as HTMLElement).dataset.id !== (elem as Node).parentElement.dataset.id)) {
         (elem as HTMLElement).style.display = 'none';
       }
     });
@@ -48,9 +49,13 @@ export class GrammarChecker {
   }
 
   grammarCheck(commentBody: HTMLDivElement): void {
+    this.onDocumentClick({
+      target: document
+    });
     const wrongWords: string[] = [];
     this.isSpellchecking = true;
     this.hasSpellcheckConfidence = true;
+    const unfilteredText = commentBody.innerText;
     const text = CreateCommentKeywords.cleaningFunction(commentBody.innerText);
     this.checkSpellings(text).subscribe((wordsCheck) => {
       if (!this.checkLanguageConfidence(wordsCheck)) {
@@ -70,84 +75,88 @@ export class GrammarChecker {
         }
         document.getElementById('langSelect').innerHTML = this.newLang;
       }
-      if (wordsCheck.matches.length > 0) {
-        wordsCheck.matches.forEach(grammarError => {
-          const wrongWord = commentBody.innerText.slice(grammarError.offset, grammarError.offset + grammarError.length);
-          wrongWords.push(wrongWord);
-        });
-
-        let html = '';
-        let lastFound = text.length;
-        this.checkSpellings(text).subscribe((res) => {
-          for (let i = res.matches.length - 1; i >= 0; i--) {
-            const end = res.matches[i].offset + res.matches[i].length;
-            const start = res.matches[i].offset;
-            const wrongWord = text.slice(start, end);
-
-            if (wrongWords.includes(wrongWord)) {
-              const suggestions: any[] = res.matches[i].replacements;
-              let displayOptions = 3;
-              let suggestionsHTML = '';
-
-              if (!suggestions.length) {
-                suggestionsHTML = '<span style="color: black; display: block; text-align: center;">' + res.matches[i].message + '</span>';
-              }
+      if (wordsCheck.matches.length <= 0) {
+        return;
+      }
+      wordsCheck.matches.forEach(grammarError => {
+        const wrongWord = text.slice(grammarError.offset, grammarError.offset + grammarError.length);
+        wrongWords.push(wrongWord);
+      });
+
+      let html = '';
+      let lastFound = unfilteredText.length;
+      this.checkSpellings(unfilteredText).subscribe((res) => {
+        for (let i = res.matches.length - 1; i >= 0; i--) {
+          const end = res.matches[i].offset + res.matches[i].length;
+          const start = res.matches[i].offset;
+          const wrongWord = unfilteredText.slice(start, end);
+
+          if (!wrongWords.includes(wrongWord)) {
+            continue;
+          }
 
-              if (suggestions.length < displayOptions) {
-                displayOptions = suggestions.length;
-              }
+          const suggestions: any[] = res.matches[i].replacements;
+          let displayOptions = 3;
+          let suggestionsHTML = '';
 
-              for (let j = 0; j < displayOptions; j++) {
-                // eslint-disable-next-line max-len
-                suggestionsHTML += '<span class="suggestions"' + ' style="color: black; display: block; text-align: center; cursor: pointer;">' + suggestions[j].value + '</span>';
-              }
+          if (!suggestions.length) {
+            suggestionsHTML = '<span style="color: black; display: block; text-align: center;">' + res.matches[i].message + '</span>';
+          }
+
+          if (suggestions.length < displayOptions) {
+            displayOptions = suggestions.length;
+          }
 
-              const replacement =
-                '<div class="markUp" data-id="' + i + '" style="position: relative; display: inline-block; border-bottom: 1px dotted black">' +
-                '<span data-id="' + i + '" style="text-decoration: underline wavy red; cursor: pointer;">' +
-                wrongWord +
-                '</span>' +
-                // eslint-disable-next-line max-len
-                '<div class="dropdownBlock" style="display: none; width: 160px; background-color: white; border-style: solid; border-color: var(--primary); color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; position: absolute; z-index: 1000; bottom: 100%;">' +
-                suggestionsHTML +
-                '</div>' +
-                '</div>';
-
-              html = replacement + text.slice(end, lastFound) + html;
-              lastFound = res.matches[i].offset;
-            }
+          for (let j = 0; j < displayOptions; j++) {
+            // eslint-disable-next-line max-len
+            suggestionsHTML += '<span class="suggestions"' + ' style="color: black; display: block; text-align: center; cursor: pointer;">' + suggestions[j].value + '</span>';
           }
-          commentBody.innerHTML = text.slice(0, lastFound) + html;
-
-          setTimeout(() => {
-            Array.from(document.getElementsByClassName('markUp')).forEach(markup => {
-              markup.addEventListener('click', () => {
-                ((markup as HTMLElement).lastChild as HTMLElement).style.display = 'block';
-                const rectdiv = (document.getElementById('answer-input')).getBoundingClientRect();
-                const rectmarkup = markup.getBoundingClientRect();
-                let offset;
-                if (rectmarkup.x + rectmarkup.width / 2 > rectdiv.right - 80) {
-                  offset = rectdiv.right - rectmarkup.x - rectmarkup.width;
-                  ((markup as HTMLElement).lastChild as HTMLElement).style.right = -offset + 'px';
-                } else if (rectmarkup.x + rectmarkup.width / 2 < rectdiv.left + 80) {
-                  offset = rectmarkup.x - rectdiv.left;
-                  ((markup as HTMLElement).lastChild as HTMLElement).style.left = -offset + 'px';
-                } else {
-                  ((markup as HTMLElement).lastChild as HTMLElement).style.left = '50%';
-                  ((markup as HTMLElement).lastChild as HTMLElement).style.marginLeft = '-80px';
-                }
-                setTimeout(() => {
-                  Array.from(document.getElementsByClassName('suggestions')).forEach(suggestion => {
-                    suggestion.addEventListener('click', () => {
-                      suggestion.parentElement.parentElement.outerHTML = suggestion.innerHTML;
-                    });
+
+          const replacement =
+            '<div class="markUp" data-id="' + i + '" style="position: relative; display: inline-block; border-bottom: 1px dotted black">' +
+            '<span data-id="' + i + '" style="text-decoration: underline wavy red; cursor: pointer;">' +
+            wrongWord +
+            '</span>' +
+            // eslint-disable-next-line max-len
+            '<div class="dropdownBlock" style="display: none; width: 160px; background-color: white; border-style: solid; border-color: var(--primary); color: #fff; text-align: center; border-radius: 6px; padding: 5px 0; position: absolute; z-index: 1000; bottom: 100%;">' +
+            suggestionsHTML +
+            '</div>' +
+            '</div>';
+
+          html = replacement + unfilteredText.slice(end, lastFound) + html;
+          lastFound = res.matches[i].offset;
+        }
+        commentBody.innerHTML = unfilteredText.slice(0, lastFound) + html;
+
+        setTimeout(() => {
+          Array.from(document.getElementsByClassName('markUp')).forEach((markup: HTMLElement) => {
+            markup.addEventListener('click', () => {
+              const lastChild = markup.lastChild as HTMLElement;
+              lastChild.style.display = 'block';
+              const rectdiv = (document.getElementById('answer-input')).getBoundingClientRect();
+              const rectmarkup = markup.getBoundingClientRect();
+              let offset;
+              if (rectmarkup.x + rectmarkup.width / 2 > rectdiv.right - 80) {
+                offset = rectdiv.right - rectmarkup.x - rectmarkup.width;
+                lastChild.style.right = -offset + 'px';
+              } else if (rectmarkup.x + rectmarkup.width / 2 < rectdiv.left + 80) {
+                offset = rectmarkup.x - rectdiv.left;
+                lastChild.style.left = -offset + 'px';
+              } else {
+                lastChild.style.left = '50%';
+                lastChild.style.marginLeft = '-80px';
+              }
+              setTimeout(() => {
+                Array.from(document.getElementsByClassName('suggestions')).forEach(suggestion => {
+                  suggestion.addEventListener('click', () => {
+                    suggestion.parentElement.parentElement.outerHTML = suggestion.innerHTML;
                   });
-                }, 500);
-              });
+                });
+              }, 500);
             });
-          }, 500);
-        });
-      }
+          });
+        }, 500);
+      });
     }, () => '', () => {
       this.isSpellchecking = false;
     });
-- 
GitLab