mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-21 13:38:56 +02:00
making the grouped table list flat to prepare for virtualization
This commit is contained in:
parent
31b7734f85
commit
19007c486a
@ -188,27 +188,27 @@ const Table = (props: Props): JSX.Element => {
|
||||
{/* Table rows */}
|
||||
<div className='table-row-container'>
|
||||
{activeView.fields.groupById &&
|
||||
visibleGroups.map((group) => {
|
||||
return (
|
||||
<TableGroup
|
||||
key={group.option.id}
|
||||
board={board}
|
||||
activeView={activeView}
|
||||
groupByProperty={groupByProperty}
|
||||
group={group}
|
||||
readonly={props.readonly || !canEditCards}
|
||||
selectedCardIds={props.selectedCardIds}
|
||||
cardIdToFocusOnRender={props.cardIdToFocusOnRender}
|
||||
hideGroup={hideGroup}
|
||||
addCard={props.addCard}
|
||||
showCard={props.showCard}
|
||||
propertyNameChanged={propertyNameChanged}
|
||||
onCardClicked={props.onCardClicked}
|
||||
onDropToGroupHeader={onDropToGroupHeader}
|
||||
onDropToCard={onDropToCard}
|
||||
onDropToGroup={onDropToGroup}
|
||||
/>)
|
||||
})
|
||||
visibleGroups.map((group) => {
|
||||
return (
|
||||
<TableGroup
|
||||
key={group.option.id}
|
||||
board={board}
|
||||
activeView={activeView}
|
||||
groupByProperty={groupByProperty}
|
||||
group={group}
|
||||
readonly={props.readonly || !canEditCards}
|
||||
selectedCardIds={props.selectedCardIds}
|
||||
cardIdToFocusOnRender={props.cardIdToFocusOnRender}
|
||||
hideGroup={hideGroup}
|
||||
addCard={props.addCard}
|
||||
showCard={props.showCard}
|
||||
propertyNameChanged={propertyNameChanged}
|
||||
onCardClicked={props.onCardClicked}
|
||||
onDropToGroupHeader={onDropToGroupHeader}
|
||||
onDropToCard={onDropToCard}
|
||||
onDropToGroup={onDropToGroup}
|
||||
/>)
|
||||
})
|
||||
}
|
||||
|
||||
{/* No Grouping, Rows, one per card */}
|
||||
@ -224,6 +224,7 @@ const Table = (props: Props): JSX.Element => {
|
||||
addCard={props.addCard}
|
||||
onCardClicked={props.onCardClicked}
|
||||
onDrop={onDropToCard}
|
||||
useVirtualizedList={true}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
@ -32,31 +32,9 @@ type Props = {
|
||||
|
||||
const TableGroup = (props: Props): JSX.Element => {
|
||||
const {board, activeView, group, onDropToGroup, groupByProperty} = props
|
||||
const groupId = group.option.id
|
||||
|
||||
const [{isOver}, drop] = useDrop(() => ({
|
||||
accept: 'card',
|
||||
collect: (monitor) => ({
|
||||
isOver: monitor.isOver(),
|
||||
}),
|
||||
drop: (item: Card, monitor) => {
|
||||
if (monitor.isOver({shallow: true})) {
|
||||
onDropToGroup(item, groupId, '')
|
||||
}
|
||||
},
|
||||
}), [onDropToGroup, groupId])
|
||||
|
||||
let className = 'octo-table-group'
|
||||
if (isOver) {
|
||||
className += ' dragover'
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={drop}
|
||||
className={className}
|
||||
key={group.option.id}
|
||||
>
|
||||
<>
|
||||
<TableGroupHeaderRow
|
||||
group={group}
|
||||
board={board}
|
||||
@ -67,6 +45,8 @@ const TableGroup = (props: Props): JSX.Element => {
|
||||
readonly={props.readonly}
|
||||
propertyNameChanged={props.propertyNameChanged}
|
||||
onDrop={props.onDropToGroupHeader}
|
||||
key={group.option.id}
|
||||
onDropToGroup={onDropToGroup}
|
||||
/>
|
||||
|
||||
{(group.cards.length > 0) &&
|
||||
@ -81,8 +61,10 @@ const TableGroup = (props: Props): JSX.Element => {
|
||||
addCard={props.addCard}
|
||||
onCardClicked={props.onCardClicked}
|
||||
onDrop={props.onDropToCard}
|
||||
useVirtualizedList={false}
|
||||
/>}
|
||||
</div>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ test('should match snapshot, no groups', async () => {
|
||||
type: 'text',
|
||||
options: [{id: 'property1', value: 'Property 1', color: ''}],
|
||||
}}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
@ -89,6 +90,7 @@ test('should match snapshot with Group', async () => {
|
||||
addCard={jest.fn()}
|
||||
propertyNameChanged={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
@ -107,6 +109,7 @@ test('should match snapshot on read only', async () => {
|
||||
addCard={jest.fn()}
|
||||
propertyNameChanged={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
@ -130,6 +133,7 @@ test('should match snapshot, hide group', async () => {
|
||||
addCard={jest.fn()}
|
||||
propertyNameChanged={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
@ -158,6 +162,7 @@ test('should match snapshot, add new', async () => {
|
||||
addCard={addNew}
|
||||
propertyNameChanged={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
@ -184,6 +189,7 @@ test('should match snapshot, edit title', async () => {
|
||||
addCard={jest.fn()}
|
||||
propertyNameChanged={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
onDropToGroup={jest.fn()}
|
||||
/>
|
||||
</Wrapper>,
|
||||
)
|
||||
|
@ -1,13 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
/* eslint-disable max-lines */
|
||||
import React, {useState, useEffect} from 'react'
|
||||
import React, {useState, useEffect, useRef} from 'react'
|
||||
import {FormattedMessage, useIntl} from 'react-intl'
|
||||
import {useDrag, useDrop} from 'react-dnd'
|
||||
|
||||
import {Constants} from '../../constants'
|
||||
import {IPropertyOption, Board, IPropertyTemplate, BoardGroup} from '../../blocks/board'
|
||||
import {BoardView} from '../../blocks/boardView'
|
||||
import {useSortable} from '../../hooks/sortable'
|
||||
import {Card} from '../../blocks/card'
|
||||
import mutator from '../../mutator'
|
||||
import Button from '../../widgets/buttons/button'
|
||||
import IconButton from '../../widgets/buttons/iconButton'
|
||||
@ -33,13 +34,42 @@ type Props = {
|
||||
addCard: (groupByOptionId?: string) => Promise<void>
|
||||
propertyNameChanged: (option: IPropertyOption, text: string) => Promise<void>
|
||||
onDrop: (srcOption: IPropertyOption, dstOption?: IPropertyOption) => void
|
||||
onDropToGroup: (srcCard: Card, groupID: string, dstCardID: string) => void
|
||||
}
|
||||
|
||||
const TableGroupHeaderRow = (props: Props): JSX.Element => {
|
||||
const {board, activeView, group, groupByProperty} = props
|
||||
const [groupTitle, setGroupTitle] = useState(group.option.value)
|
||||
|
||||
const [isDragging, isOver, groupHeaderRef] = useSortable('groupHeader', group.option, !props.readonly, props.onDrop)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const [{isDragging}, drag] = useDrag(() => ({
|
||||
type: 'groupHeader',
|
||||
item: group.option,
|
||||
collect: (monitor) => ({
|
||||
isDragging: monitor.isDragging(),
|
||||
}),
|
||||
canDrag: () => !props.readonly,
|
||||
}), ['groupHeader', group.option, props.readonly])
|
||||
|
||||
const [{isOver}, drop] = useDrop(() => ({
|
||||
accept: ['groupHeader', 'card'],
|
||||
collect: (monitor) => ({
|
||||
isOver: monitor.isOver(),
|
||||
}),
|
||||
drop: (dragItem: IPropertyOption | Card, monitor) => {
|
||||
// @ts-ignore
|
||||
if (dragItem?.type === 'card' && monitor.isOver({shallow: true})) {
|
||||
// @ts-ignore
|
||||
props.onDropToGroup(dragItem, group.option.id, '')
|
||||
return;
|
||||
}
|
||||
// @ts-ignore
|
||||
props.onDrop(dragItem, group.option)
|
||||
},
|
||||
canDrop: () => !props.readonly,
|
||||
}), [group.option, props.onDrop, props.readonly])
|
||||
drop(drag(ref))
|
||||
|
||||
const intl = useIntl()
|
||||
const columnResize = useColumnResize()
|
||||
|
||||
@ -59,7 +89,7 @@ const TableGroupHeaderRow = (props: Props): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
key={group.option.id + 'header'}
|
||||
ref={groupHeaderRef}
|
||||
ref={ref}
|
||||
style={{opacity: isDragging ? 0.5 : 1}}
|
||||
className={className}
|
||||
>
|
||||
|
@ -74,6 +74,7 @@ describe('components/table/TableRows', () => {
|
||||
addCard={addCard}
|
||||
onCardClicked={jest.fn()}
|
||||
onDrop={jest.fn()}
|
||||
useVirtualizedList={false}
|
||||
/>
|
||||
</ColumnResizeProvider>
|
||||
</ReduxProvider>,
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React, {useCallback} from 'react'
|
||||
import {FixedSizeList, ListChildComponentProps} from 'react-window';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import {FixedSizeList, ListChildComponentProps} from 'react-window'
|
||||
import AutoSizer from 'react-virtualized-auto-sizer'
|
||||
|
||||
import {Card} from '../../blocks/card'
|
||||
import {Board} from '../../blocks/board'
|
||||
@ -23,21 +23,50 @@ type Props = {
|
||||
addCard: (groupByOptionId?: string) => Promise<void>
|
||||
onCardClicked: (e: React.MouseEvent, card: Card) => void
|
||||
onDrop: (srcCard: Card, dstCard: Card) => void
|
||||
useVirtualizedList: boolean
|
||||
}
|
||||
|
||||
const TableRows = (props: Props): JSX.Element => {
|
||||
const {board, cards, activeView} = props
|
||||
const {board, cards, activeView, useVirtualizedList} = props
|
||||
|
||||
const onClickRow = useCallback((e: React.MouseEvent<HTMLDivElement>, card: Card) => {
|
||||
props.onCardClicked(e, card)
|
||||
}, [props.onCardClicked])
|
||||
|
||||
if (!useVirtualizedList) {
|
||||
return (
|
||||
<>
|
||||
{cards.map((card, idx) => {
|
||||
return (
|
||||
<TableRow
|
||||
key={card.id + card.updateAt}
|
||||
board={board}
|
||||
columnWidths={activeView.fields.columnWidths}
|
||||
isManualSort={activeView.fields.sortOptions.length === 0}
|
||||
groupById={activeView.fields.groupById}
|
||||
visiblePropertyIds={activeView.fields.visiblePropertyIds}
|
||||
collapsedOptionIds={activeView.fields.collapsedOptionIds}
|
||||
card={card}
|
||||
addCard={props.addCard}
|
||||
isSelected={props.selectedCardIds.includes(card.id)}
|
||||
focusOnMount={props.cardIdToFocusOnRender === card.id}
|
||||
isLastCard={idx === (cards.length - 1)}
|
||||
onClick={onClickRow}
|
||||
showCard={props.showCard}
|
||||
readonly={props.readonly}
|
||||
onDrop={props.onDrop}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const isItemLoaded = (index: number) => {
|
||||
return index < cards.length;
|
||||
};
|
||||
}
|
||||
|
||||
const Item = ({index, style}: ListChildComponentProps) => {
|
||||
|
||||
const card = cards[index]
|
||||
if (isItemLoaded(index)) {
|
||||
return (
|
||||
@ -72,13 +101,13 @@ const TableRows = (props: Props): JSX.Element => {
|
||||
}
|
||||
|
||||
return (
|
||||
<AutoSizer>
|
||||
{({height, width}) => (
|
||||
<AutoSizer disableWidth>
|
||||
{({height}) => (
|
||||
<FixedSizeList
|
||||
height={height}
|
||||
itemCount={1828}
|
||||
itemSize={44}
|
||||
width={width}
|
||||
width={'100%'}
|
||||
>
|
||||
{Item}
|
||||
</FixedSizeList>
|
||||
|
Loading…
Reference in New Issue
Block a user