Skip to content

Commit

Permalink
Merge pull request #238 from jespino/react-dnd
Browse files Browse the repository at this point in the history
Migrating all drag and drop into react-dnd
  • Loading branch information
jespino authored Apr 8, 2021
2 parents cfb2da8 + 74e8cb1 commit 7320f1e
Show file tree
Hide file tree
Showing 24 changed files with 656 additions and 548 deletions.
66 changes: 64 additions & 2 deletions webapp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"marked": ">=2.0.1",
"nanoevents": "^5.1.13",
"react": "^17.0.2",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dnd-touch-backend": "^14.0.0",
"react-dom": "^17.0.2",
"react-hot-keys": "^2.6.2",
"react-hotkeys-hook": "^3.3.0",
Expand Down
144 changes: 75 additions & 69 deletions webapp/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
Route,
Switch,
} from 'react-router-dom'
import {DndProvider} from 'react-dnd'
import {HTML5Backend} from 'react-dnd-html5-backend'
import {TouchBackend} from 'react-dnd-touch-backend'

import {FlashMessages} from './components/flashMessages'
import {getCurrentLanguage, getMessages, storeLanguage} from './i18n'
Expand All @@ -18,6 +21,7 @@ import ErrorPage from './pages/errorPage'
import LoginPage from './pages/loginPage'
import RegisterPage from './pages/registerPage'
import {IUser, UserContext} from './user'
import {Utils} from './utils'

type State = {
language: string,
Expand Down Expand Up @@ -51,78 +55,80 @@ export default class App extends React.PureComponent<unknown, State> {
locale={this.state.language}
messages={getMessages(this.state.language)}
>
<UserContext.Provider value={this.state.user}>
<FlashMessages milliseconds={2000}/>
<Router forceRefresh={true}>
<div id='frame'>
<div id='main'>
<Switch>
<Route path='/error'>
<ErrorPage/>
</Route>
<Route path='/login'>
<LoginPage/>
</Route>
<Route path='/register'>
<RegisterPage/>
</Route>
<Route path='/change_password'>
<ChangePasswordPage/>
</Route>
<Route path='/shared'>
<BoardPage
workspaceId='0'
readonly={true}
setLanguage={this.setAndStoreLanguage}
<DndProvider backend={Utils.isMobile() ? TouchBackend : HTML5Backend}>
<UserContext.Provider value={this.state.user}>
<FlashMessages milliseconds={2000}/>
<Router forceRefresh={true}>
<div id='frame'>
<div id='main'>
<Switch>
<Route path='/error'>
<ErrorPage/>
</Route>
<Route path='/login'>
<LoginPage/>
</Route>
<Route path='/register'>
<RegisterPage/>
</Route>
<Route path='/change_password'>
<ChangePasswordPage/>
</Route>
<Route path='/shared'>
<BoardPage
workspaceId='0'
readonly={true}
setLanguage={this.setAndStoreLanguage}
/>
</Route>
<Route path='/board'>
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
<BoardPage
workspaceId='0'
setLanguage={this.setAndStoreLanguage}
/>
</Route>
<Route
path='/workspace/:workspaceId/shared'
render={({match}) => {
return (
<BoardPage
workspaceId={match.params.workspaceId}
readonly={true}
setLanguage={this.setAndStoreLanguage}
/>
)
}}
/>
</Route>
<Route path='/board'>
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
<BoardPage
workspaceId='0'
setLanguage={this.setAndStoreLanguage}
<Route
path='/workspace/:workspaceId/'
render={({match}) => {
if (this.state.initialLoad && !this.state.user) {
const redirectUrl = `/workspace/${match.params.workspaceId}/`
const loginUrl = `/login?r=${encodeURIComponent(redirectUrl)}`
return <Redirect to={loginUrl}/>
}
return (
<BoardPage
workspaceId={match.params.workspaceId}
setLanguage={this.setAndStoreLanguage}
/>
)
}}
/>
</Route>
<Route
path='/workspace/:workspaceId/shared'
render={({match}) => {
return (
<BoardPage
workspaceId={match.params.workspaceId}
readonly={true}
setLanguage={this.setAndStoreLanguage}
/>
)
}}
/>
<Route
path='/workspace/:workspaceId/'
render={({match}) => {
if (this.state.initialLoad && !this.state.user) {
const redirectUrl = `/workspace/${match.params.workspaceId}/`
const loginUrl = `/login?r=${encodeURIComponent(redirectUrl)}`
return <Redirect to={loginUrl}/>
}
return (
<BoardPage
workspaceId={match.params.workspaceId}
setLanguage={this.setAndStoreLanguage}
/>
)
}}
/>
<Route path='/'>
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
<BoardPage
workspaceId='0'
setLanguage={this.setAndStoreLanguage}
/>
</Route>
</Switch>
<Route path='/'>
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
<BoardPage
workspaceId='0'
setLanguage={this.setAndStoreLanguage}
/>
</Route>
</Switch>
</div>
</div>
</div>
</Router>
</UserContext.Provider>
</Router>
</UserContext.Provider>
</DndProvider>
</IntlProvider>
)
}
Expand Down
18 changes: 18 additions & 0 deletions webapp/src/components/cardDetail/cardDetailContents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import React from 'react'
import {injectIntl, IntlShape} from 'react-intl'

import {IContentBlock} from '../../blocks/contentBlock'
import {MutableTextBlock} from '../../blocks/textBlock'
import mutator from '../../mutator'
import {CardTree} from '../../viewModel/cardTree'
Expand Down Expand Up @@ -32,6 +33,22 @@ function addTextBlock(card: Card, intl: IntlShape, text: string): void {
})
}

function moveBlock(card: Card, srcBlock: IContentBlock, dstBlock: IContentBlock, intl: IntlShape): void {
let contentOrder = card.contentOrder.slice()
const isDraggingDown = contentOrder.indexOf(srcBlock.id) <= contentOrder.indexOf(dstBlock.id)
contentOrder = contentOrder.filter((id) => srcBlock.id !== id)
let destIndex = contentOrder.indexOf(dstBlock.id)
if (isDraggingDown) {
destIndex += 1
}
contentOrder.splice(destIndex, 0, srcBlock.id)

mutator.performAsUndoGroup(async () => {
const description = intl.formatMessage({id: 'CardDetail.moveContent', defaultMessage: 'move card content'})
await mutator.changeCardContentOrder(card, contentOrder, description)
})
}

const CardDetailContents = React.memo((props: Props) => {
const {cardTree} = props
if (!cardTree) {
Expand All @@ -49,6 +66,7 @@ const CardDetailContents = React.memo((props: Props) => {
card={card}
contents={cardTree.contents}
readonly={props.readonly}
onDrop={(src, dst) => moveBlock(card, src, dst, props.intl)}
/>
))}
</div>
Expand Down
3 changes: 3 additions & 0 deletions webapp/src/components/contentBlock.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
> .octo-block-margin {
flex: 0 0 auto;
}
.ImageElement {
pointer-events: none;
}
}
13 changes: 12 additions & 1 deletion webapp/src/components/contentBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import SortDownIcon from '../widgets/icons/sortDown'
import SortUpIcon from '../widgets/icons/sortUp'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
import useSortable from '../hooks/sortable'

import ContentElement from './content/contentElement'
import AddContentMenuItem from './addContentMenuItem'
Expand All @@ -28,14 +29,24 @@ type Props = {
contents: readonly IContentBlock[]
readonly: boolean
intl: IntlShape
onDrop: (srctBlock: IContentBlock, dstBlock: IContentBlock) => void
}

const ContentBlock = React.memo((props: Props): JSX.Element => {
const {intl, card, contents, block, readonly} = props
const [isDragging, isOver, contentRef] = useSortable('content', block, true, props.onDrop)

const index = contents.indexOf(block)
let className = 'ContentBlock octo-block'
if (isOver) {
className += ' dragover'
}
return (
<div className='ContentBlock octo-block'>
<div
className={className}
style={{opacity: isDragging ? 0.5 : 1}}
ref={contentRef}
>
<div className='octo-block-margin'>
{!props.readonly &&
<MenuWrapper>
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/components/gallery/gallery.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
color: rgba(var(--body-color), 0.3);
cursor: pointer;
width: 280px;
min-height: 200px;
min-height: 160px;
display: flex;
flex-direction: column;
align-items: center;
Expand Down
Loading

0 comments on commit 7320f1e

Please sign in to comment.