From 429ac2235c6d86117ee17324d844fe6c4fb10769 Mon Sep 17 00:00:00 2001
From: Ruben Bimberg <ruben.bimberg@mni.thm.de>
Date: Wed, 1 Sep 2021 21:29:51 +0200
Subject: [PATCH] Finish implementing deepl

---
 .../moderator-comment-list.component.ts       |  1 -
 .../create-comment.component.ts               | 34 ++++++-
 .../deep-ldialog/deep-ldialog.component.html  | 25 ++++++
 .../deep-ldialog/deep-ldialog.component.scss  | 20 +++++
 .../deep-ldialog.component.spec.ts            | 26 ++++++
 .../deep-ldialog/deep-ldialog.component.ts    | 90 +++++++++++++++++++
 .../spacy-dialog/spacy-dialog.component.ts    |  4 +-
 src/app/components/shared/shared.module.ts    |  4 +-
 .../view-comment-data.component.ts            | 12 +--
 .../write-comment/write-comment.component.ts  |  3 -
 src/app/utils/create-comment-wrapper.ts       |  4 +-
 src/assets/i18n/creator/de.json               |  7 ++
 src/assets/i18n/creator/en.json               |  7 ++
 src/assets/i18n/participant/de.json           |  7 ++
 src/assets/i18n/participant/en.json           |  7 ++
 15 files changed, 232 insertions(+), 19 deletions(-)
 create mode 100644 src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.html
 create mode 100644 src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.scss
 create mode 100644 src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.spec.ts
 create mode 100644 src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.ts

diff --git a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
index 854f7595a..b062e1ea3 100644
--- a/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
+++ b/src/app/components/moderator/moderator-comment-list/moderator-comment-list.component.ts
@@ -19,7 +19,6 @@ import { ModeratorsComponent } from '../../creator/_dialogs/moderators/moderator
 import { TagsComponent } from '../../creator/_dialogs/tags/tags.component';
 import { DeleteCommentsComponent } from '../../creator/_dialogs/delete-comments/delete-comments.component';
 import { Export } from '../../../models/export';
-import { CreateCommentComponent } from '../../shared/_dialogs/create-comment/create-comment.component';
 import { NotificationService } from '../../../services/util/notification.service';
 import { BonusTokenService } from '../../../services/http/bonus-token.service';
 import { CommentFilter, Period } from '../../../utils/filter-options';
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 00d57e8ff..6d2293ef2 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
@@ -4,12 +4,13 @@ import { NotificationService } from '../../../../services/util/notification.serv
 import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 import { TranslateService } from '@ngx-translate/core';
 import { User } from '../../../../models/user';
-import { CommentListComponent } from '../../comment-list/comment-list.component';
 import { EventService } from '../../../../services/util/event.service';
 import { SpacyDialogComponent } from '../spacy-dialog/spacy-dialog.component';
 import { LanguagetoolService, Language } from '../../../../services/http/languagetool.service';
 import { CreateCommentKeywords } from '../../../../utils/create-comment-keywords';
 import { WriteCommentComponent } from '../../write-comment/write-comment.component';
+import { DeepLDialogComponent } from '../deep-ldialog/deep-ldialog.component';
+import { DeepLService } from '../../../../services/http/deep-l.service';
 
 @Component({
   selector: 'app-submit-comment',
@@ -19,7 +20,6 @@ import { WriteCommentComponent } from '../../write-comment/write-comment.compone
 export class CreateCommentComponent implements OnInit {
 
   @ViewChild(WriteCommentComponent) commentComponent: WriteCommentComponent;
-  comment: Comment;
   user: User;
   roomId: string;
   tags: string[];
@@ -27,11 +27,12 @@ export class CreateCommentComponent implements OnInit {
 
   constructor(
     private notification: NotificationService,
-    public dialogRef: MatDialogRef<CommentListComponent>,
+    public dialogRef: MatDialogRef<CreateCommentComponent>,
     private translateService: TranslateService,
     public dialog: MatDialog,
     public languagetoolService: LanguagetoolService,
     public eventService: EventService,
+    private deeplService: DeepLService,
     @Inject(MAT_DIALOG_DATA) public data: any) {
   }
 
@@ -51,7 +52,32 @@ export class CreateCommentComponent implements OnInit {
     comment.createdFromLecturer = this.user.role > 0;
     comment.tag = tag;
     this.isSendingToSpacy = true;
-    this.openSpacyDialog(comment, text);
+    this.openDeeplDialog(body, text, (newBody: string, newText: string) => {
+      comment.body = newBody;
+      this.openSpacyDialog(comment, newText);
+    });
+  }
+
+  openDeeplDialog(body: string, text: string, onClose: (data: string, text: string) => void) {
+    this.deeplService.improveTextStyle(text).subscribe(improvedText => {
+      this.isSendingToSpacy = false;
+      this.dialog.open(DeepLDialogComponent, {
+        width: '900px',
+        maxWidth: '100%',
+        data: {
+          body,
+          text,
+          improvedText
+        }
+      }).afterClosed().subscribe((res) => {
+        if (res) {
+          onClose(res.body, res.text);
+        }
+      });
+    }, (_) => {
+      this.isSendingToSpacy = false;
+      onClose(body, text);
+    });
   }
 
   openSpacyDialog(comment: Comment, rawText: string): void {
diff --git a/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.html b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.html
new file mode 100644
index 000000000..56e44687a
--- /dev/null
+++ b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.html
@@ -0,0 +1,25 @@
+<h2>{{'deepl.header' | translate}}</h2>
+<div mat-dialog-content>
+  <label id="deepl-radio-group-label">{{'deepl.label' | translate}}</label>
+  <br>
+  <mat-radio-group
+    aria-labelledby="deepl-radio-group-label"
+    [(ngModel)]="radioButtonValue">
+    <mat-radio-button [value]="normalValue">
+      <strong>{{'deepl.option-normal' | translate}}</strong>
+      <app-view-comment-data [currentData]="normalValue.body"></app-view-comment-data>
+    </mat-radio-button>
+    <br>
+    <mat-radio-button [value]="improvedValue">
+      <strong>{{'deepl.option-improved' | translate}}</strong>
+      <app-view-comment-data [currentData]="improvedValue.body"></app-view-comment-data>
+    </mat-radio-button>
+  </mat-radio-group>
+</div>
+
+<app-dialog-action-buttons
+  [buttonsLabelSection]="'comment-page'"
+  [confirmButtonLabel]="'continue'"
+  [cancelButtonClickAction]="buildCloseDialogActionCallback()"
+  [confirmButtonClickAction]="buildSubmitBodyActionCallback()">
+</app-dialog-action-buttons>
diff --git a/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.scss b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.scss
new file mode 100644
index 000000000..a667f841e
--- /dev/null
+++ b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.scss
@@ -0,0 +1,20 @@
+::ng-deep {
+
+  mat-radio-button {
+    width: 100%;
+  }
+
+  .mat-radio-label {
+    width: calc(100% - 16px) !important;
+  }
+
+  .mat-radio-label-content {
+    width: 100%;
+  }
+
+  app-view-comment-data > div {
+    background: var(--surface);
+    border-radius: 10px;
+    padding: 7px;
+  }
+}
diff --git a/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.spec.ts b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.spec.ts
new file mode 100644
index 000000000..4b6a83115
--- /dev/null
+++ b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.spec.ts
@@ -0,0 +1,26 @@
+/*import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeepLDialogComponent } from './deep-ldialog.component';
+
+describe('DeepLDialogComponent', () => {
+  let component: DeepLDialogComponent;
+  let fixture: ComponentFixture<DeepLDialogComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ DeepLDialogComponent ]
+    })
+    .compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(DeepLDialogComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
+ */
diff --git a/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.ts b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.ts
new file mode 100644
index 000000000..9a835d9ec
--- /dev/null
+++ b/src/app/components/shared/_dialogs/deep-ldialog/deep-ldialog.component.ts
@@ -0,0 +1,90 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { ViewCommentDataComponent } from '../../view-comment-data/view-comment-data.component';
+
+interface ResultValue {
+  body: string;
+  text: string;
+}
+
+@Component({
+  selector: 'app-deep-ldialog',
+  templateUrl: './deep-ldialog.component.html',
+  styleUrls: ['./deep-ldialog.component.scss']
+})
+export class DeepLDialogComponent implements OnInit {
+
+  radioButtonValue: ResultValue;
+  normalValue: ResultValue;
+  improvedValue: ResultValue;
+
+  constructor(
+    private dialogRef: MatDialogRef<DeepLDialogComponent>,
+    @Inject(MAT_DIALOG_DATA) public data: any) {
+  }
+
+  ngOnInit(): void {
+    this.normalValue = {
+      body: this.data.body,
+      text: this.data.text
+    };
+    const sentences = this.data.improvedText.split('\n').filter(sent => sent.length > 0);
+    const delta = ViewCommentDataComponent.getDeltaFromData(this.data.body);
+    if (delta === null) {
+      setTimeout(() => this.dialogRef.close(this.normalValue));
+      return;
+    }
+    const ops = delta.ops;
+    let i = 0;
+    let sentenceIndex = 0;
+    let lastFoundIndex = -1;
+    for (; i < ops.length && sentenceIndex < sentences.length; i++) {
+      const data = ops[i]['insert'];
+      if (typeof data !== 'string') {
+        continue;
+      }
+      if (data === '\n') {
+        continue;
+      }
+      const endsNewline = data.endsWith('\n');
+      const mod = (endsNewline ? -1 : 0) + (data.startsWith('\n') ? -1 : 0);
+      const occurrence = data.split('\n').length + mod;
+      ops[i]['insert'] = sentences.slice(sentenceIndex, sentenceIndex + occurrence).join('\n') +
+        (endsNewline ? '\n' : '');
+      sentenceIndex += occurrence;
+      lastFoundIndex = i;
+    }
+    for (let j = ops.length - 1; j >= i; j--) {
+      const data = ops[i]['insert'];
+      if (data === 'string' && data.trim().length) {
+        ops.splice(j, 1);
+      }
+    }
+    if (sentenceIndex < sentences.length) {
+      if (lastFoundIndex < 0) {
+        setTimeout(() => this.dialogRef.close(this.normalValue));
+        return;
+      }
+      let data = ops[i]['insert'];
+      const endsNewline = data.endsWith('\n');
+      if (endsNewline) {
+        data = data.substring(0, data.length - 1);
+      }
+      ops[i]['insert'] = data + sentences.slice(sentenceIndex).join('\n') + (endsNewline ? '\n' : '');
+    }
+    this.improvedValue = {
+      body: ViewCommentDataComponent.getDataFromDelta(delta),
+      text: this.data.improvedText
+    };
+    this.radioButtonValue = this.normalValue;
+  }
+
+  buildCloseDialogActionCallback(): () => void {
+    return () => this.dialogRef.close();
+  }
+
+  buildSubmitBodyActionCallback(): () => void {
+    return () => this.dialogRef.close(this.radioButtonValue);
+  }
+
+}
diff --git a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
index dd6c33c93..c2bb0e109 100644
--- a/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
+++ b/src/app/components/shared/_dialogs/spacy-dialog/spacy-dialog.component.ts
@@ -1,7 +1,5 @@
 import { AfterContentInit, Component, Inject, OnInit, ViewChild } from '@angular/core';
 import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
-
-import { CreateCommentComponent } from '../create-comment/create-comment.component';
 import { SpacyService, SpacyKeyword } from '../../../../services/http/spacy.service';
 import { LanguagetoolService } from '../../../../services/http/languagetool.service';
 import { Comment } from '../../../../models/comment';
@@ -39,7 +37,7 @@ export class SpacyDialogComponent implements OnInit, AfterContentInit {
   constructor(
     protected langService: LanguagetoolService,
     private spacyService: SpacyService,
-    public dialogRef: MatDialogRef<CreateCommentComponent>,
+    public dialogRef: MatDialogRef<SpacyDialogComponent>,
     @Inject(MAT_DIALOG_DATA) public data) {
   }
 
diff --git a/src/app/components/shared/shared.module.ts b/src/app/components/shared/shared.module.ts
index 87b4f5a8e..75057040a 100644
--- a/src/app/components/shared/shared.module.ts
+++ b/src/app/components/shared/shared.module.ts
@@ -51,6 +51,7 @@ import { CustomMarkdownComponent } from './custom-markdown/custom-markdown.compo
 import { ScrollIntoViewDirective } from '../../directives/scroll-into-view.directive';
 import { QuillModule } from 'ngx-quill';
 import { ViewCommentDataComponent } from './view-comment-data/view-comment-data.component';
+import { DeepLDialogComponent } from './_dialogs/deep-ldialog/deep-ldialog.component';
 
 @NgModule({
   imports: [
@@ -107,7 +108,8 @@ import { ViewCommentDataComponent } from './view-comment-data/view-comment-data.
     WriteCommentComponent,
     CustomMarkdownComponent,
     ScrollIntoViewDirective,
-    ViewCommentDataComponent
+    ViewCommentDataComponent,
+    DeepLDialogComponent
   ],
   exports: [
     RoomJoinComponent,
diff --git a/src/app/components/shared/view-comment-data/view-comment-data.component.ts b/src/app/components/shared/view-comment-data/view-comment-data.component.ts
index 6f28e5e7b..ccf7af27b 100644
--- a/src/app/components/shared/view-comment-data/view-comment-data.component.ts
+++ b/src/app/components/shared/view-comment-data/view-comment-data.component.ts
@@ -42,7 +42,7 @@ export class ViewCommentDataComponent implements OnInit, AfterViewInit {
   }
 
   get currentData(): string {
-    return this._currentData;
+    return this._currentData || '';
   }
 
   @Input() maxTextCharacters = 500;
@@ -66,7 +66,7 @@ export class ViewCommentDataComponent implements OnInit, AfterViewInit {
       }
     }
   };
-  private _currentData = '';
+  private _currentData = null;
 
   constructor(private languageService: LanguageService,
               private translateService: TranslateService,
@@ -79,7 +79,7 @@ export class ViewCommentDataComponent implements OnInit, AfterViewInit {
     });
   }
 
-  private static getDataFromDelta(contentDelta) {
+  public static getDataFromDelta(contentDelta) {
     return JSON.stringify(contentDelta.ops.map(op => {
       let hasOnlyInsert = true;
       for (const key in op) {
@@ -92,7 +92,7 @@ export class ViewCommentDataComponent implements OnInit, AfterViewInit {
     }));
   }
 
-  private static getDeltaFromData(jsonData: string) {
+  public static getDeltaFromData(jsonData: string) {
     return {
       ops: JSON.parse(jsonData).map(elem => {
         if (!elem['insert']) {
@@ -135,7 +135,9 @@ export class ViewCommentDataComponent implements OnInit, AfterViewInit {
         if (this.markEvents && this.markEvents.onCreate) {
           this.markEvents.onCreate(this.editorErrorLayer.nativeElement, this.tooltipContainer.nativeElement, this.editor);
         }
-        this.set(this._currentData);
+        if (this._currentData) {
+          this.set(this._currentData);
+        }
         (this.editor.editorElem.firstElementChild as HTMLElement).focus();
         this.syncErrorLayer();
         setTimeout(() => this.syncErrorLayer(), 200); // animations?
diff --git a/src/app/components/shared/write-comment/write-comment.component.ts b/src/app/components/shared/write-comment/write-comment.component.ts
index a39b0b731..324be593f 100644
--- a/src/app/components/shared/write-comment/write-comment.component.ts
+++ b/src/app/components/shared/write-comment/write-comment.component.ts
@@ -93,9 +93,6 @@ export class WriteCommentComponent implements OnInit {
   }
 
   checkGrammar() {
-    this.deepl.improveTextStyle(this.commentData.currentText).subscribe(str => {
-      console.log(str);
-    });
     this.grammarCheck(this.commentData.currentText, this.langSelect && this.langSelect.nativeElement);
   }
 
diff --git a/src/app/utils/create-comment-wrapper.ts b/src/app/utils/create-comment-wrapper.ts
index 1408a49eb..93706c1c2 100644
--- a/src/app/utils/create-comment-wrapper.ts
+++ b/src/app/utils/create-comment-wrapper.ts
@@ -22,8 +22,8 @@ export class CreateCommentWrapper {
   openCreateDialog(user: User): Observable<Comment> {
     const dialogRef = this.dialog.open(CreateCommentComponent, {
       width: '900px',
-      maxWidth: 'calc( 100% - 50px )',
-      maxHeight: 'calc( 100vh - 50px )',
+      maxWidth: '100%',
+      maxHeight: 'calc( 100vh - 20px )',
       autoFocus: false,
     });
     dialogRef.componentInstance.user = user;
diff --git a/src/assets/i18n/creator/de.json b/src/assets/i18n/creator/de.json
index 161e2d184..ef9be59cd 100644
--- a/src/assets/i18n/creator/de.json
+++ b/src/assets/i18n/creator/de.json
@@ -125,6 +125,7 @@
     "answer": "Frage kommentieren",
     "save-answer": "Speichern",
     "comment-answered": "Antwort wurde gespeichert.",
+    "continue": "Weiter",
     "edit-answer": "Bearbeiten",
     "delete-answer": "Löschen",
     "really-delete-answer": "Willst du deine Antwort wirklich löschen?",
@@ -235,6 +236,12 @@
     "undo": "Rückgängig",
     "yes": "Ja"
   },
+  "deepl": {
+    "header": "DeepL Unterstützung",
+    "label": "Wähle einen Text",
+    "option-normal": "Eingegebener Text",
+    "option-improved": "Stilistisch verbesserter Text"
+  },
   "home-page": {
     "create-session": "Neue Sitzung",
     "created-1": "Die Sitzung »",
diff --git a/src/assets/i18n/creator/en.json b/src/assets/i18n/creator/en.json
index 751372cd2..1a1be02ce 100644
--- a/src/assets/i18n/creator/en.json
+++ b/src/assets/i18n/creator/en.json
@@ -125,6 +125,7 @@
     "answer": "Comment this question",
     "save-answer": "Save",
     "comment-answered": "Answer has been sent.",
+    "continue": "Continue",
     "edit-answer": "Edit",
     "delete-answer": "Delete",
     "really-delete-answer": "Do you really want to delete this answer?",
@@ -236,6 +237,12 @@
     "undo": "Undo",
     "yes": "Yes"
   },
+  "deepl": {
+    "header": "DeepL Support",
+    "label": "Choose a text",
+    "option-normal": "Entered text",
+    "option-improved": "Stylistically improved text"
+  },
   "home-page": {
     "create-session": "New session",
     "created-1": "Session »",
diff --git a/src/assets/i18n/participant/de.json b/src/assets/i18n/participant/de.json
index e6ba2fec8..d034aa1e2 100644
--- a/src/assets/i18n/participant/de.json
+++ b/src/assets/i18n/participant/de.json
@@ -119,6 +119,7 @@
     "abort": "Abbrechen",
     "ask-question-description": "Gib hier deine Frage ein!",
     "save-answer": "Speichern",
+    "continue": "Weiter",
     "delete-answer": "Löschen",
     "cancel": "Abbrechen",
     "cancel-description": "Abbrechen",
@@ -163,6 +164,12 @@
     "upvote": "positiv",
     "downvote": "negativ"
   },
+  "deepl": {
+    "header": "DeepL Unterstützung",
+    "label": "Wähle einen Text",
+    "option-normal": "Eingegebener Text",
+    "option-improved": "Stilistisch verbesserter Text"
+  },
   "home-page": {
     "exactly-8": "Ein Raum-Code hat genau 8 Ziffern.",
     "no-room-found": "Es wurde kein Raum mit diesem Raum-Code gefunden.",
diff --git a/src/assets/i18n/participant/en.json b/src/assets/i18n/participant/en.json
index 2a1328180..613bb84bd 100644
--- a/src/assets/i18n/participant/en.json
+++ b/src/assets/i18n/participant/en.json
@@ -129,6 +129,7 @@
     "abort": "Cancel",
     "ask-question-description": "Enter your question …",
     "save-answer": "Save",
+    "continue": "Continue",
     "delete-answer": "Delete",
     "cancel": "Cancel",
     "cancel-description": "Cancel",
@@ -172,6 +173,12 @@
     "upvote": "upvotes",
     "downvote": "downvotes"
   },
+  "deepl": {
+    "header": "DeepL Support",
+    "label": "Choose a text",
+    "option-normal": "Entered text",
+    "option-improved": "Stylistically improved text"
+  },
   "home-page": {
     "exactly-8": "A key is a combination of 8 digits.",
     "no-room-found": "No session found with this key",
-- 
GitLab