Allow uploading pictures into description by drag&drop them

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2019-05-29 17:47:52 +02:00
parent fe65a478f0
commit c0abbf3d3e
3 changed files with 98 additions and 5 deletions

View File

@ -162,12 +162,11 @@ import {
History, History,
Placeholder, Placeholder,
Mention, Mention,
Image,
} from 'tiptap-extensions'; } from 'tiptap-extensions';
import tippy, { Instance } from 'tippy.js'; import tippy, { Instance } from 'tippy.js';
import { SEARCH_PERSONS } from '@/graphql/search'; import { SEARCH_PERSONS } from '@/graphql/search';
import { IActor } from '@/types/actor'; import { IActor } from '@/types/actor';
import Image from '@/components/Editor/Image';
@Component({ @Component({
components: { EditorContent, EditorMenuBar, EditorMenuBubble }, components: { EditorContent, EditorMenuBar, EditorMenuBubble },

View File

@ -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);
}
},
},
},
}),
];
}
}

View File

@ -1,10 +1,10 @@
import gql from 'graphql-tag'; import gql from 'graphql-tag';
export const UPLOAD_PICTURE = gql` export const UPLOAD_PICTURE = gql`
mutation { mutation UploadPicture($file: Upload!, $alt: String, $name: String!){
uploadPicture(file: "file") { uploadPicture(file: $file, alt: $alt, name: $name) {
url, url,
url_thumbnail id
} }
} }
`; `;