From 75811d7f4485d9eaa40b376e29d1783085f97a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Wed, 7 Apr 2021 20:18:44 +0200 Subject: [PATCH] Adding preliminary (not-working) gallery manual sort --- webapp/src/components/gallery/gallery.tsx | 23 ++++++++++++++ webapp/src/components/gallery/galleryCard.tsx | 31 +++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/gallery/gallery.tsx b/webapp/src/components/gallery/gallery.tsx index 4d26fc9b2..d42715cb1 100644 --- a/webapp/src/components/gallery/gallery.tsx +++ b/webapp/src/components/gallery/gallery.tsx @@ -4,6 +4,8 @@ import React, {useState, useEffect} from 'react' import {FormattedMessage} from 'react-intl' import {Card} from '../../blocks/card' +import mutator from '../../mutator' +import {Utils} from '../../utils' import {BoardTree} from '../../viewModel/boardTree' import {CardTree, MutableCardTree} from '../../viewModel/cardTree' import useCardListener from '../../hooks/cardListener' @@ -25,6 +27,26 @@ const Gallery = (props: Props): JSX.Element => { const visiblePropertyTemplates = boardTree.board.cardProperties.filter((template) => boardTree.activeView.visiblePropertyIds.includes(template.id)) const [cardTrees, setCardTrees] = useState<{[key: string]: CardTree | undefined}>({}) + const onDropToCard = async (srcCard: Card, dstCard: Card) => { + Utils.log(`onDropToCard: ${dstCard.title}`) + const {selectedCardIds} = props + const {activeView} = boardTree + + const draggedCardIds = Array.from(new Set(selectedCardIds).add(srcCard.id)) + + const description = draggedCardIds.length > 1 ? `drag ${draggedCardIds.length} cards` : 'drag card' + + // Update dstCard order + let cardOrder = [...activeView.cardOrder] + cardOrder = cardOrder.filter((id) => !draggedCardIds.includes(id)) + const destIndex = cardOrder.indexOf(dstCard.id) + cardOrder.splice(destIndex, 0, ...draggedCardIds) + + await mutator.performAsUndoGroup(async () => { + await mutator.changeViewCardOrder(activeView, cardOrder, description) + }) + } + useCardListener( cards.map((c) => c.id), async (blocks) => { @@ -62,6 +84,7 @@ const Gallery = (props: Props): JSX.Element => { visiblePropertyTemplates={visiblePropertyTemplates} isSelected={props.selectedCardIds.includes(card.id)} readonly={props.readonly} + onDrop={onDropToCard} /> ) } diff --git a/webapp/src/components/gallery/galleryCard.tsx b/webapp/src/components/gallery/galleryCard.tsx index 71ff4b1f6..9287828e6 100644 --- a/webapp/src/components/gallery/galleryCard.tsx +++ b/webapp/src/components/gallery/galleryCard.tsx @@ -1,7 +1,8 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React from 'react' +import React, {useRef} from 'react' import {FormattedMessage, injectIntl, IntlShape} from 'react-intl' +import {useDrag, useDrop} from 'react-dnd' import {IPropertyTemplate} from '../../blocks/board' import {Card} from '../../blocks/card' @@ -29,20 +30,46 @@ type Props = { isSelected: boolean intl: IntlShape readonly: boolean + onDrop: (srcCard: Card, dstCard: Card) => void } const GalleryCard = React.memo((props: Props) => { const {cardTree} = props + const cardRef = useRef(null) + const [{isDragging}, drag] = useDrag(() => ({ + type: 'card', + item: cardTree.card, + collect: (monitor) => ({ + isDragging: monitor.isDragging(), + }), + }), [cardTree]) + const [{isOver}, drop] = useDrop(() => ({ + accept: 'card', + collect: (monitor) => ({ + isOver: monitor.isOver(), + }), + drop: (item: Card) => { + props.onDrop(item, cardTree.card) + }, + }), [cardTree]) const visiblePropertyTemplates = props.visiblePropertyTemplates || [] let images: IContentBlock[] = [] images = cardTree.contents.filter((content) => content.type === 'image') + let className = props.isSelected ? 'GalleryCard selected' : 'GalleryCard' + if (isOver) { + className += ' dragover' + } + + drop(drag(cardRef)) return (
props.onClick(e, cardTree.card)} + style={{opacity: isDragging ? 0.5 : 1}} + ref={cardRef} > {!props.readonly &&