From 2a2e4690ff2d721fb4bfa6535a895a09cf50cf86 Mon Sep 17 00:00:00 2001
From: Thomas Citharel <tcit@tcit.fr>
Date: Wed, 29 May 2019 17:47:52 +0200
Subject: [PATCH] Allow uploading pictures into description by drag&drop them

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
---
 js/src/components/Editor.vue      |  3 +-
 js/src/components/Editor/Image.ts | 94 +++++++++++++++++++++++++++++++
 js/src/graphql/upload.ts          |  6 +-
 3 files changed, 98 insertions(+), 5 deletions(-)
 create mode 100644 js/src/components/Editor/Image.ts

diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue
index b16b616f7..8ff091c86 100644
--- a/js/src/components/Editor.vue
+++ b/js/src/components/Editor.vue
@@ -162,12 +162,11 @@ import {
     History,
     Placeholder,
     Mention,
-    Image,
 } from 'tiptap-extensions';
 import tippy, { Instance } from 'tippy.js';
 import { SEARCH_PERSONS } from '@/graphql/search';
 import { IActor } from '@/types/actor';
-
+import Image from '@/components/Editor/Image';
 
 @Component({
   components: { EditorContent, EditorMenuBar, EditorMenuBubble },
diff --git a/js/src/components/Editor/Image.ts b/js/src/components/Editor/Image.ts
new file mode 100644
index 000000000..26304776c
--- /dev/null
+++ b/js/src/components/Editor/Image.ts
@@ -0,0 +1,94 @@
+import { Node, Plugin } from 'tiptap';
+import { UPLOAD_PICTURE } from '@/graphql/upload';
+import { apolloProvider } from '@/vue-apollo';
+import ApolloClient from 'apollo-client';
+import { InMemoryCache } from 'apollo-cache-inmemory';
+
+export default class Image extends Node {
+
+  get name() {
+    return 'image';
+  }
+
+  get schema() {
+    return {
+      inline: true,
+      attrs: {
+        src: {},
+        alt: {
+          default: null,
+        },
+        title: {
+          default: null,
+        },
+      },
+      group: 'inline',
+      draggable: true,
+      parseDOM: [
+        {
+          tag: 'img[src]',
+          getAttrs: dom => ({
+            src: dom.getAttribute('src'),
+            title: dom.getAttribute('title'),
+            alt: dom.getAttribute('alt'),
+          }),
+        },
+      ],
+      toDOM: node => ['img', node.attrs],
+    };
+  }
+
+  commands({ type }) {
+    return attrs => (state, dispatch) => {
+      const { selection } = state;
+      const position = selection.$cursor ? selection.$cursor.pos : selection.$to.pos;
+      const node = type.create(attrs);
+      const transaction = state.tr.insert(position, node);
+      dispatch(transaction);
+    };
+  }
+
+  get plugins() {
+    return [
+      new Plugin({
+        props: {
+          handleDOMEvents: {
+            async drop(view, event: DragEvent) {
+              if (!(event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files.length)) {
+                return;
+              }
+
+              const images = Array
+                                .from(event.dataTransfer.files)
+                                .filter((file: any) => (/image/i).test(file.type));
+
+              if (images.length === 0) {
+                return;
+              }
+
+              event.preventDefault();
+
+              const { schema } = view.state;
+              const coordinates = view.posAtCoords({ left: event.clientX, top: event.clientY });
+              const client = apolloProvider.defaultClient as ApolloClient<InMemoryCache>;
+
+              for (const image of images) {
+                const { data } = await client.mutate({
+                  mutation: UPLOAD_PICTURE,
+                  variables: {
+                    file: image,
+                    name: image.name,
+                  },
+                });
+                const node = schema.nodes.image.create({ src: data.uploadPicture.url });
+                const transaction = view.state.tr.insert(coordinates.pos, node);
+                view.dispatch(transaction);
+              }
+            },
+          },
+        },
+      }),
+    ];
+  }
+
+}
diff --git a/js/src/graphql/upload.ts b/js/src/graphql/upload.ts
index 138b5d2d3..490e08389 100644
--- a/js/src/graphql/upload.ts
+++ b/js/src/graphql/upload.ts
@@ -1,10 +1,10 @@
 import gql from 'graphql-tag';
 
 export const UPLOAD_PICTURE = gql`
-    mutation {
-        uploadPicture(file: "file") {
+    mutation UploadPicture($file: Upload!, $alt: String, $name: String!){
+        uploadPicture(file: $file, alt: $alt, name: $name) {
             url,
-            url_thumbnail
+            id
         }
     }
 `;