feat: Add ability to hide completed tasks (#1210)

This commit is contained in:
Symon Baikov
2025-07-21 18:33:02 +02:00
committed by GitHub
parent fc9c94b3b6
commit d8fbf2f909
17 changed files with 158 additions and 55 deletions
@@ -35,8 +35,9 @@ const EditStep = React.memo(({ taskListId, onClose }) => {
() => ({
name: taskList.name,
showOnFrontOfCard: taskList.showOnFrontOfCard,
hideCompletedTasks: taskList.hideCompletedTasks,
}),
[taskList.name, taskList.showOnFrontOfCard],
[taskList.name, taskList.showOnFrontOfCard, taskList.hideCompletedTasks],
);
const [data, handleFieldChange] = useForm(() => ({
@@ -44,6 +45,7 @@ const EditStep = React.memo(({ taskListId, onClose }) => {
context: 'title',
}),
showOnFrontOfCard: true,
hideCompletedTasks: false,
...defaultData,
}));
@@ -3,13 +3,14 @@
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
*/
import React, { useMemo } from 'react';
import React, { useCallback, useMemo } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { useSelector } from 'react-redux';
import { Draggable } from 'react-beautiful-dnd';
import { Button, Icon } from 'semantic-ui-react';
import { useToggle } from '../../../../lib/hooks';
import selectors from '../../../../selectors';
import { usePopupInClosableContext } from '../../../../hooks';
@@ -29,8 +30,16 @@ const Item = React.memo(({ id, index }) => {
return !!boardMembership && boardMembership.role === BoardMembershipRoles.EDITOR;
});
const [isCompletedVisible, toggleCompletedVisible] = useToggle();
const handleToggleCompletedVisibleClick = useCallback(() => {
toggleCompletedVisible();
}, [toggleCompletedVisible]);
const EditPopup = usePopupInClosableContext(EditStep);
const withActions = taskList.hideCompletedTasks || canEdit;
return (
<Draggable
draggableId={`task-list:${id}`}
@@ -51,20 +60,37 @@ const Item = React.memo(({ id, index }) => {
<div
className={classNames(
styles.moduleHeader,
canEdit && styles.moduleHeaderEditable,
withActions && styles.moduleHeaderWithActions,
taskList.hideCompletedTasks && canEdit && styles.both,
)}
>
{taskList.isPersisted && canEdit && (
<EditPopup taskListId={taskList.id}>
<Button className={styles.editButton}>
<Icon fitted name="pencil" size="small" />
</Button>
</EditPopup>
{taskList.isPersisted && withActions && (
<div className={classNames(styles.actions)}>
{taskList.hideCompletedTasks && (
<Button
className={styles.button}
onClick={handleToggleCompletedVisibleClick}
>
<Icon
fitted
name={isCompletedVisible ? 'eye slash' : 'eye'}
size="small"
/>
</Button>
)}
{canEdit && (
<EditPopup taskListId={taskList.id}>
<Button className={styles.button}>
<Icon fitted name="pencil" size="small" />
</Button>
</EditPopup>
)}
</div>
)}
<span className={styles.moduleHeaderTitle}>{taskList.name}</span>
</div>
</div>
<TaskList id={id} />
<TaskList id={id} isCompletedVisible={isCompletedVisible} />
</div>
</div>
);
@@ -4,7 +4,15 @@
*/
:global(#app) {
.editButton {
.actions {
display: flex;
gap: 2px;
position: absolute;
right: 0;
top: 4px;
}
.button {
background: transparent;
box-shadow: none;
line-height: 28px;
@@ -12,9 +20,6 @@
min-height: auto;
opacity: 0;
padding: 0;
position: absolute;
right: 0;
top: 4px;
width: 28px;
&:hover {
@@ -32,14 +37,18 @@
padding: 6px 0;
}
.moduleHeaderEditable {
.moduleHeaderWithActions {
padding-right: 32px;
&:hover {
.editButton {
.button {
opacity: 1;
}
}
&.both {
padding-right: 62px;
}
}
.moduleHeaderTitle {