From 6568d60f0ffebb19fc0296de34919f073516b724 Mon Sep 17 00:00:00 2001
From: NathanViaud <nathan.viaud@inria.fr>
Date: Thu, 25 May 2023 17:42:00 +0200
Subject: [PATCH] Replacing Quill by tinymce

---
 package-lock.json                             |   1 +
 package.json                                  |   1 +
 .../forms/components/inputs/GenericInput.vue  |   2 +-
 .../forms/components/inputs/HtmlInput.vue     |  45 ++--
 .../forms/components/inputs/QuillEditor.vue   | 192 ++++++++++++++++++
 5 files changed, 207 insertions(+), 34 deletions(-)
 create mode 100644 src/features/forms/components/inputs/QuillEditor.vue

diff --git a/package-lock.json b/package-lock.json
index 8c3565a1..ca988b9d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
         "pinia": "^2.0.28",
         "sass": "^1.56.2",
         "serve-static": "^1.15.0",
+        "tinymce": "^6.4.2",
         "vue": "3.3",
         "vue-router": "^4.1.6",
         "vue-tippy": "^6.0.0",
diff --git a/package.json b/package.json
index ae5c8db6..af50f823 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
     "pinia": "^2.0.28",
     "sass": "^1.56.2",
     "serve-static": "^1.15.0",
+    "tinymce": "^6.4.2",
     "vue": "3.3",
     "vue-router": "^4.1.6",
     "vue-tippy": "^6.0.0",
diff --git a/src/features/forms/components/inputs/GenericInput.vue b/src/features/forms/components/inputs/GenericInput.vue
index 99fbf01a..8c76525c 100644
--- a/src/features/forms/components/inputs/GenericInput.vue
+++ b/src/features/forms/components/inputs/GenericInput.vue
@@ -37,7 +37,7 @@ const emit = defineEmits<{
         :inside-card="insideCard"
         @input="emit('input', $event)"
     />
-    <HtmlInput 
+    <HtmlInput
         v-if="input.type === 'html'"
         :label="input.label"
         :placeholder="input.placeholder"
diff --git a/src/features/forms/components/inputs/HtmlInput.vue b/src/features/forms/components/inputs/HtmlInput.vue
index a7a7ad5f..d11ec84e 100644
--- a/src/features/forms/components/inputs/HtmlInput.vue
+++ b/src/features/forms/components/inputs/HtmlInput.vue
@@ -1,8 +1,6 @@
 <script setup lang="ts">
 import Editor from '@tinymce/tinymce-vue';
-import { getTinymce } from '@tinymce/tinymce-vue/lib/cjs/main/ts/TinyMCE';
 import { Ref, ref, watch } from 'vue';
-import {graphService} from '@/src/shared/services';
 
 const props = defineProps<{
     label: string;
@@ -19,6 +17,7 @@ const editor = ref(null);
 const content: Ref<string> = ref('');
 
 function textChange() {
+    console.log('textChange');
     emit('input', content.value);
 }
 
@@ -36,8 +35,8 @@ watch(
     }
 );
 
-const plugins = 'image link lists template code';
-const toolbar = 'bold italic alignleft aligncenter alignright link image bullist numlist outdent indent template code';
+const plugins = 'bold italic underline lists align link image searchreplace visualblocks preview wordcount code fullscreen media table template help textpattern';
+const toolbar = 'undo redo | bold italic underline | alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | link image | help | template | code';
 
 const template = `
     <details style="border: 1px solid lightgray; border-radius: 4px; padding: .5em .5em 0 .5em">
@@ -51,26 +50,8 @@ function init() {
     content.value = props.inputValue;
 }
 
-async function drop(event) {
-    const file = event.dataTransfer.files[0];
-    if (!file) return;
-    const url = await graphService.importFile(file.path);
-    const editor = getTinymce().activeEditor;
-    editor.setContent(editor.getContent() + `<img alt="" src="${url}"/>`);
-}
-
-function handleFilePicker(callback) {
-    const input = document.createElement('input');
-    input.type = 'file';
-    document.body.appendChild(input);
-    input.click();
-    input.addEventListener('change', async (e: any) => {
-        const fileInput = e.target as HTMLInputElement;
-        const file = fileInput.files[0];
-        if (!file) return;
-        const url = await graphService.importFile(file.path);
-        callback(url);
-    });
+function drop(event) {
+    console.log('drop', event);
 }
 
 </script>
@@ -84,18 +65,16 @@ function handleFilePicker(callback) {
         :plugins="plugins"
         :toolbar="toolbar"
         :init="{
-            menubar: false,
-            statusbar: false,
+            menubar: 'file edit view insert custom',
             templates: [
-                { title: 'Plier/déplier', content: template, description: 'Plier/déplier avec titre et contenu' }
+                { title: 'title 1', content: template, description: 'this is a test template' }
             ],
-            file_picker_types: 'image',
-            file_picker_callback: handleFilePicker,
-            link_default_target: '_blank',
-            link_target_list: false,
-            paste_data_images: false
+            file_picker_callback:(callback, value, meta) => {
+                console.log('file_picker_callback', callback, value, meta);
+                drop(value);
+            }
         }"
         @init="init"
-        @drop.stop.prevent="drop"
+        @drop="drop"
     />
 </template>
\ No newline at end of file
diff --git a/src/features/forms/components/inputs/QuillEditor.vue b/src/features/forms/components/inputs/QuillEditor.vue
new file mode 100644
index 00000000..35a1b8f0
--- /dev/null
+++ b/src/features/forms/components/inputs/QuillEditor.vue
@@ -0,0 +1,192 @@
+<!-- TODO: Delete this legacy component -->
+
+<script setup lang="ts">
+import { QuillEditor, Quill } from '@vueup/vue-quill';
+import '@vueup/vue-quill/dist/vue-quill.snow.css';
+import ImageUploader from 'quill-image-uploader/src/quill.imageUploader';
+import { Ref, ref, watch } from 'vue';
+import { graphService } from '@/src/shared/services';
+//@ts-ignore
+import htmlEditButton from 'quill-html-edit-button';
+
+const props = defineProps<{
+    label: string;
+    inputValue: string;
+    placeholder?: string;
+    insideCard?: boolean;
+}>();
+
+const emit = defineEmits<{
+    (e: 'input', value: string): void;
+}>();
+
+const toolbar = [
+    [
+        'bold',
+        'italic',
+        'underline',
+        { 'list': 'ordered' },
+        { 'list': 'bullet' },
+        { 'align': null},
+        {'align': 'center'},
+        {'align': 'right'}, 
+        'link',
+        'image'
+    ]
+];
+
+const image = Quill.import('formats/image');
+
+image.sanitize = function(url) {
+    return url;
+};
+
+const modules = [
+    {
+        name: 'imageUploader',
+        module: ImageUploader,
+        options: {
+            upload: (file) => graphService.importFile(file.path)
+        }, 
+    },
+    {
+        name: 'htmlEditButton',
+        module: htmlEditButton,
+        option: {
+            debug: true,
+        }
+    }
+];
+
+const qlEditor = ref(null);
+
+const content: Ref<string> = ref('');
+    
+
+function textChange() {
+    emit('input', content.value);
+}
+
+function initQuill() {
+    content.value = props.inputValue;
+}
+
+watch(
+    () => props.inputValue,
+    () => {
+        content.value = props.inputValue;
+    }
+);
+
+</script>
+
+<template>
+    <label for="ql-editor">{{ label }}</label>
+    <QuillEditor
+        id="ql-editor"
+        ref="qlEditor"
+        v-model:content="content"
+        content-type="html"
+        theme="snow"
+        :class="{ 'ql-card': insideCard }"
+        :modules="modules"
+        :toolbar="toolbar"
+        :placeholder="placeholder"
+        @text-change="textChange"
+        @ready="initQuill"
+    />
+</template>
+
+<style lang="scss">
+
+.ql {
+    &-toolbar {
+        border: none !important;
+        &:hover {
+            border-radius: 8px;
+        }
+    }
+    &-container {
+        border: 1px solid var(--border) !important;
+        border-radius: 4px;
+        background-color: var(--item-background);
+        margin-bottom: 1.5rem;
+        &:focus-within {
+            border: 1px solid var(--editor-blue) !important;
+            box-shadow: 0 1px 8px 0 var(--editor-blue-shadow);
+        }
+    }
+    &-editor {
+        min-height: 10rem;
+        padding: .5rem;
+        font-size: 1rem;
+        color: var(--text);
+        width: 24rem;
+
+        p {
+            margin-bottom: .5rem;
+        }
+    }
+
+    &-active {
+        background-color: transparent !important;
+        &:hover {
+            background-color: #F3F4F6 !important;
+        }
+    }
+
+    &-formats {
+        button:hover {
+            border-radius: 4px;
+            background-color: #F3F4F6 !important;
+        }
+    }
+
+    &-card {
+        margin-bottom: 1rem;
+    }
+}
+
+.ql-active .ql-stroke {
+    stroke: var(--editor-blue) !important;
+}
+
+.ql-active .ql-fill {
+    fill: var(--editor-blue) !important;
+}
+
+.ql-active:hover {
+    background-color: var(--) !important;
+}
+
+.ql-blank::before {
+    color: var(--editor-grayblue) !important;
+    font-style: normal !important;
+    left: 0.5rem !important;
+}
+
+// Quill Edit button
+
+.ql-html {
+    &-textContainer {
+        background: white;
+    }
+    
+    &-textArea {
+        border: 1px solid var(--border);
+    }
+
+    &-buttonOk, &-buttonCancel {
+        border: none;
+        cursor: pointer;
+        color: var(--text);
+        border-radius: 6px;
+        transition: box-shadow .2s ease-in-out;
+        padding: .5rem 1rem;
+        
+        &:hover {
+            box-shadow: 0 1px 8px 0 var(--shadow-outer);
+        }
+    }
+}
+</style>
-- 
GitLab