main

mattermost/focalboard

Last updated at: 29/12/2023 09:43

tableGroupHeaderRow.tsx

TLDR

This file contains the TableGroupHeaderRow component which is a part of the Demo Projects project. The component is used to render a group header row in a table view. It allows users to hide groups, add cards to groups, edit group titles, and perform other group-related actions.

Methods

There are no additional methods in this file.

Classes

There are no additional classes in this file.

// 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 {FormattedMessage, useIntl} from 'react-intl'

import {Constants} from '../../constants'
import {IPropertyOption, Board, IPropertyTemplate, BoardGroup} from '../../blocks/board'
import {BoardView} from '../../blocks/boardView'
import {useSortable} from '../../hooks/sortable'
import mutator from '../../mutator'
import Button from '../../widgets/buttons/button'
import IconButton from '../../widgets/buttons/iconButton'
import AddIcon from '../../widgets/icons/add'
import DeleteIcon from '../../widgets/icons/delete'
import CompassIcon from '../../widgets/icons/compassIcon'
import HideIcon from '../../widgets/icons/hide'
import OptionsIcon from '../../widgets/icons/options'
import Menu from '../../widgets/menu'
import MenuWrapper from '../../widgets/menuWrapper'
import Editable from '../../widgets/editable'
import Label from '../../widgets/label'

import {useColumnResize} from './tableColumnResizeContext'

type Props = {
    board: Board
    activeView: BoardView
    group: BoardGroup
    groupByProperty?: IPropertyTemplate
    readonly: boolean
    hideGroup: (groupByOptionId: string) => void
    addCard: (groupByOptionId?: string) => Promise<void>
    propertyNameChanged: (option: IPropertyOption, text: string) => Promise<void>
    onDrop: (srcOption: IPropertyOption, dstOption?: IPropertyOption) => 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 intl = useIntl()
    const columnResize = useColumnResize()

    useEffect(() => {
        setGroupTitle(group.option.value)
    }, [group.option.value])
    let className = 'octo-group-header-cell'
    if (isOver) {
        className += ' dragover'
    }
    if (activeView.fields.collapsedOptionIds.indexOf(group.option.id || 'undefined') < 0) {
        className += ' expanded'
    }

    const canEditOption = groupByProperty?.type !== 'person' && group.option.id

    return (
        <div
            key={group.option.id + 'header'}
            ref={groupHeaderRef}
            style={{opacity: isDragging ? 0.5 : 1}}
            className={className}
        >
            <div
                className='octo-table-cell'
                style={{width: columnResize.width(Constants.titleColumnId)}}
                ref={(ref) => columnResize.updateRef(group.option.id, Constants.titleColumnId, ref)}
            >
                <IconButton
                    icon={
                        <CompassIcon
                            icon='menu-right'
                        />}
                    onClick={() => (props.readonly ? {} : props.hideGroup(group.option.id || 'undefined'))}
                    className={`octo-table-cell__expand ${props.readonly ? 'readonly' : ''}`}
                />

                {!group.option.id &&
                    <Label
                        title={intl.formatMessage({
                            id: 'BoardComponent.no-property-title',
                            defaultMessage: 'Items with an empty {property} property will go here. This column cannot be removed.',
                        }, {property: groupByProperty?.name})}
                    >
                        <FormattedMessage
                            id='BoardComponent.no-property'
                            defaultMessage='No {property}'
                            values={{
                                property: groupByProperty?.name,
                            }}
                        />
                    </Label>}
                {groupByProperty?.type === 'person' &&
                    <Label>
                        {groupTitle}
                    </Label>}
                {canEditOption &&
                    <Label color={group.option.color}>
                        <Editable
                            value={groupTitle}
                            placeholderText='New Select'
                            onChange={setGroupTitle}
                            onSave={() => {
                                if (groupTitle.trim() === '') {
                                    setGroupTitle(group.option.value)
                                }
                                props.propertyNameChanged(group.option, groupTitle)
                            }}
                            onCancel={() => {
                                setGroupTitle(group.option.value)
                            }}
                            readonly={props.readonly || !group.option.id}
                            spellCheck={true}
                        />
                    </Label>}
            </div>
            <Button>{`${group.cards.length}`}</Button>
            {!props.readonly &&
                <>
                    <MenuWrapper>
                        <IconButton icon={<OptionsIcon/>}/>
                        <Menu>
                            <Menu.Text
                                id='hide'
                                icon={<HideIcon/>}
                                name={intl.formatMessage({id: 'BoardComponent.hide', defaultMessage: 'Hide'})}
                                onClick={() => mutator.hideViewColumn(board.id, activeView, group.option.id || '')}
                            />
                            {canEditOption &&
                                <>
                                    <Menu.Text
                                        id='delete'
                                        icon={<DeleteIcon/>}
                                        name={intl.formatMessage({id: 'BoardComponent.delete', defaultMessage: 'Delete'})}
                                        onClick={() => mutator.deletePropertyOption(board.id, board.cardProperties, groupByProperty!, group.option)}
                                    />
                                    <Menu.Separator/>
                                    {Object.entries(Constants.menuColors).map(([key, color]) => (
                                        <Menu.Color
                                            key={key}
                                            id={key}
                                            name={color}
                                            onClick={() => mutator.changePropertyOptionColor(board.id, board.cardProperties, groupByProperty!, group.option, key)}
                                        />
                                    ))}
                                </>}
                        </Menu>
                    </MenuWrapper>
                    <IconButton
                        icon={<AddIcon/>}
                        onClick={() => props.addCard(group.option.id)}
                    />
                </>
            }
        </div>
    )
}

export default React.memo(TableGroupHeaderRow)