Add paste/drop images on cards (#987)
* Add paste/drop images on cards * Fix eslint
This commit is contained in:
parent
249a8c23a4
commit
727641f3db
2 changed files with 65 additions and 0 deletions
|
@ -21,6 +21,7 @@ import CommentsList from './commentsList'
|
||||||
import CardDetailContents from './cardDetailContents'
|
import CardDetailContents from './cardDetailContents'
|
||||||
import CardDetailContentsMenu from './cardDetailContentsMenu'
|
import CardDetailContentsMenu from './cardDetailContentsMenu'
|
||||||
import CardDetailProperties from './cardDetailProperties'
|
import CardDetailProperties from './cardDetailProperties'
|
||||||
|
import useImagePaste from './imagePaste'
|
||||||
|
|
||||||
import './cardDetail.scss'
|
import './cardDetail.scss'
|
||||||
|
|
||||||
|
@ -49,6 +50,8 @@ const CardDetail = (props: Props): JSX.Element|null => {
|
||||||
const saveTitleRef = useRef<() => void>(saveTitle)
|
const saveTitleRef = useRef<() => void>(saveTitle)
|
||||||
saveTitleRef.current = saveTitle
|
saveTitleRef.current = saveTitle
|
||||||
|
|
||||||
|
useImagePaste(card.id, card.fields.contentOrder, card.rootId)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!title) {
|
if (!title) {
|
||||||
titleRef.current?.focus()
|
titleRef.current?.focus()
|
||||||
|
|
62
webapp/src/components/cardDetail/imagePaste.tsx
Normal file
62
webapp/src/components/cardDetail/imagePaste.tsx
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import {useEffect, useCallback} from 'react'
|
||||||
|
|
||||||
|
import {ImageBlock, createImageBlock} from '../../blocks/imageBlock'
|
||||||
|
import octoClient from '../../octoClient'
|
||||||
|
import mutator from '../../mutator'
|
||||||
|
|
||||||
|
export default function useImagePaste(cardId: string, contentOrder: Array<string | string[]>, rootId: string): void {
|
||||||
|
const uploadItems = useCallback(async (items: FileList) => {
|
||||||
|
let newImage: File|null = null
|
||||||
|
const uploads: Promise<string|undefined>[] = []
|
||||||
|
for (const item of items) {
|
||||||
|
newImage = item
|
||||||
|
if (newImage?.type.indexOf('image/') === 0) {
|
||||||
|
uploads.push(octoClient.uploadFile(rootId, newImage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploaded = await Promise.all(uploads)
|
||||||
|
const blocksToInsert: ImageBlock[] = []
|
||||||
|
for (const fileId of uploaded) {
|
||||||
|
if (!fileId) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const block = createImageBlock()
|
||||||
|
block.parentId = cardId
|
||||||
|
block.rootId = rootId
|
||||||
|
block.fields.fileId = fileId || ''
|
||||||
|
blocksToInsert.push(block)
|
||||||
|
}
|
||||||
|
mutator.performAsUndoGroup(async () => {
|
||||||
|
await mutator.insertBlocks(blocksToInsert, 'pasted images')
|
||||||
|
const newContentOrder = [...contentOrder, ...blocksToInsert.map((b: ImageBlock) => b.id)]
|
||||||
|
return mutator.changeCardContentOrder(cardId, contentOrder, newContentOrder, 'paste image')
|
||||||
|
})
|
||||||
|
}, [cardId, contentOrder, rootId])
|
||||||
|
|
||||||
|
const onDrop = useCallback((event: DragEvent): void => {
|
||||||
|
if (event.dataTransfer) {
|
||||||
|
const items = event.dataTransfer.files
|
||||||
|
uploadItems(items)
|
||||||
|
}
|
||||||
|
}, [uploadItems])
|
||||||
|
|
||||||
|
const onPaste = useCallback((event: ClipboardEvent): void => {
|
||||||
|
if (event.clipboardData) {
|
||||||
|
const items = event.clipboardData.files
|
||||||
|
uploadItems(items)
|
||||||
|
}
|
||||||
|
}, [uploadItems])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener('paste', onPaste)
|
||||||
|
document.addEventListener('drop', onDrop)
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener('paste', onPaste)
|
||||||
|
document.removeEventListener('drop', onDrop)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
}
|
Loading…
Reference in a new issue