1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-07 18:03:48 +00:00

kanban supports collapse (#7437)

* kanban supports collapse

* optimize

* optimize ui

---------

Co-authored-by: zhouwenxuan <aries@Mac.local>
This commit is contained in:
Aries
2025-02-08 17:56:36 +08:00
committed by GitHub
parent 65ef9f704b
commit cb3af6e66a
5 changed files with 108 additions and 59 deletions

View File

@@ -35,7 +35,7 @@
}
.file-details-collapse .file-details-collapse-header .file-details-collapse-header-operation:hover {
background-color: #DBDBDB;
background-color: #EFEFEF;
cursor: pointer;
border-radius: 3px;
}

View File

@@ -27,3 +27,25 @@
color: #666666;
margin-left: 12px;
}
.sf-metadata-view-kanban-board-header .board-header-operation-btn {
display: flex;
align-items: flex-end;
}
.board-header-operation-btn .kanban-header-op-btn {
width: 20px;
height: 20px;
display: flex;
justify-content: center;
align-items: center;
margin-left: 0.5rem;
color: #666666;
cursor: pointer;
border-radius: 3px;
}
.board-header-operation-btn .kanban-header-op-btn.kanban-header-collapse-btn:hover,
.board-header-operation-btn .kanban-header-op-btn.kanban-more-operations-toggle:hover {
background-color: #EFEFEF;
}

View File

@@ -1,5 +1,6 @@
import React, { useCallback, useMemo, useState } from 'react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import CellFormatter from '../../../../../components/cell-formatter';
import { gettext } from '../../../../../../utils/constants';
import OpMenu from './op-menu';
@@ -7,9 +8,11 @@ import { CellType } from '../../../../../constants';
import './index.css';
const Header = ({ readonly, haveFreezed, value, groupByColumn, cardsQuantity, onDelete, onFreezed, onUnFreezed }) => {
const Header = ({ readonly, haveFreezed, value, groupByColumn, cardsQuantity, onDelete, onFreezed, onUnFreezed, isCollapsed, onCollapse }) => {
const [active, setActive] = useState(false);
const headerRef = useRef();
const onMouseEnter = useCallback(() => {
if (haveFreezed) return;
setActive(true);
@@ -20,10 +23,14 @@ const Header = ({ readonly, haveFreezed, value, groupByColumn, cardsQuantity, on
setActive(false);
}, [haveFreezed]);
const handelUnFreezed = useCallback((keepActive) => {
const keepActive = useCallback((event) => {
return event.target.className?.includes('kanban-header-op-btn') || event.target === headerRef.current;
}, []);
const handelUnFreezed = useCallback((event) => {
onUnFreezed();
!keepActive && setActive(false);
}, [onUnFreezed]);
!keepActive(event) && setActive(false);
}, [onUnFreezed, keepActive]);
const titleValue = useMemo(() => {
if (!value || !groupByColumn) return null;
@@ -31,9 +38,14 @@ const Header = ({ readonly, haveFreezed, value, groupByColumn, cardsQuantity, on
return value;
}, [value, groupByColumn]);
const handleCollapse = useCallback((event) => {
onCollapse();
!keepActive(event) && setActive(false);
}, [onCollapse, keepActive]);
return (
<div className="sf-metadata-view-kanban-board-header" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
<div className="sf-metadata-view-kanban-board-header-title">
<div className="sf-metadata-view-kanban-board-header-title" ref={headerRef}>
{value ? (
<CellFormatter value={titleValue} field={groupByColumn} readonly={true} />
) : (
@@ -41,8 +53,15 @@ const Header = ({ readonly, haveFreezed, value, groupByColumn, cardsQuantity, on
)}
<span className="cards-quantity">{cardsQuantity}</span>
</div>
{value && !readonly && active && (
<OpMenu onDelete={onDelete} onFreezed={onFreezed} onUnFreezed={handelUnFreezed} />
{active && (
<div className="board-header-operation-btn">
{value && !readonly && <OpMenu onDelete={onDelete} onFreezed={onFreezed} onUnFreezed={handelUnFreezed} />}
<i
className={classNames('sf3-font sf3-font-down kanban-header-op-btn kanban-header-collapse-btn', { 'rotate-90': isCollapsed })}
title={isCollapsed ? gettext('Expand') : gettext('Collapse')}
onClick={handleCollapse}>
</i>
</div>
)}
</div>
);

View File

@@ -9,8 +9,7 @@ const OpMenu = ({ onDelete, onFreezed, onUnFreezed }) => {
const toggle = useCallback((event) => {
event.stopPropagation();
if (isShow) {
const isClickToggleBtn = event.target.className?.includes('kanban-more-operations-toggle');
onUnFreezed(isClickToggleBtn);
onUnFreezed(event);
} else {
onFreezed();
}
@@ -35,7 +34,7 @@ const OpMenu = ({ onDelete, onFreezed, onUnFreezed }) => {
tag="i"
role="button"
tabIndex="0"
className="sf-dropdown-toggle sf3-font-more sf3-font kanban-more-operations-toggle"
className="sf-dropdown-toggle sf3-font-more sf3-font kanban-header-op-btn kanban-more-operations-toggle"
title={gettext('More operations')}
aria-label={gettext('More operations')}
data-toggle="dropdown"

View File

@@ -31,6 +31,7 @@ const Board = ({
onContextMenu,
}) => {
const [isDraggingOver, setDraggingOver] = useState(false);
const [isCollapsed, setCollapsed] = useState(false);
const boardName = useMemo(() => `sf_metadata_kanban_board_${board.key}`, [board]);
const cardsQuantity = useMemo(() => board.children.length, [board.children]);
@@ -54,6 +55,10 @@ const Board = ({
setTimeout(() => updateDragging(false), 0);
}, [isDraggingOver, onMove, updateDragging]);
const onCollapse = useCallback(() => {
setCollapsed(!isCollapsed);
}, [isCollapsed]);
return (
<section draggable={false} className="sf-metadata-view-kanban-board">
<Header
@@ -65,7 +70,10 @@ const Board = ({
onDelete={() => deleteOption(board.key)}
onFreezed={onFreezed}
onUnFreezed={onUnFreezed}
isCollapsed={isCollapsed}
onCollapse={onCollapse}
/>
{!isCollapsed && (
<Container
orientation="vertical"
groupName={boardName}
@@ -114,6 +122,7 @@ const Board = ({
);
})}
</Container>
)}
</section>
);
};