Implement task filters
This commit is contained in:
parent
a26d1ba7c0
commit
3fee542a8f
106
src/Board.tsx
106
src/Board.tsx
@ -4,6 +4,7 @@ import TaskItem from './TaskItem';
|
|||||||
import { paramCase } from 'param-case';
|
import { paramCase } from 'param-case';
|
||||||
import VSCodeApi from "./VSCodeApi";
|
import VSCodeApi from "./VSCodeApi";
|
||||||
|
|
||||||
|
// Called when a task item has finished being dragged
|
||||||
const onDragEnd = (result, columns, setColumns, vscode: VSCodeApi) => {
|
const onDragEnd = (result, columns, setColumns, vscode: VSCodeApi) => {
|
||||||
|
|
||||||
// No destination means the item was dragged to an invalid location
|
// No destination means the item was dragged to an invalid location
|
||||||
@ -55,6 +56,78 @@ const onDragEnd = (result, columns, setColumns, vscode: VSCodeApi) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if a task's due date is in the past
|
||||||
|
const checkOverdue = (task: KanbnTask) => {
|
||||||
|
if ('due' in task.metadata && task.metadata.due !== undefined) {
|
||||||
|
return Date.parse(task.metadata.due) < (new Date()).getTime();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A list of property names that can be filtered
|
||||||
|
const filterProperties = [
|
||||||
|
'description',
|
||||||
|
'assigned',
|
||||||
|
'tag',
|
||||||
|
'relation'
|
||||||
|
];
|
||||||
|
|
||||||
|
// Filter tasks according to the filter string
|
||||||
|
const filterTask = (task: KanbnTask, taskFilter: string) => {
|
||||||
|
let result = true;
|
||||||
|
taskFilter.split(' ').forEach(f => {
|
||||||
|
const parts = f.split(':').map(p => p.toLowerCase());
|
||||||
|
|
||||||
|
// This filter section doesn't contain a property name
|
||||||
|
if (parts.length === 1) {
|
||||||
|
|
||||||
|
// Filter for overdue tasks
|
||||||
|
if (parts[0] === 'overdue') {
|
||||||
|
if (!checkOverdue(task)) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter task id or name
|
||||||
|
if (
|
||||||
|
!task.id.toLowerCase().includes(parts[0]) &&
|
||||||
|
!task.name.toLowerCase().includes(parts[0])
|
||||||
|
) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this filter section contains a property name and value, check the value against the property
|
||||||
|
if (parts.length === 2 && filterProperties.indexOf(parts[0]) !== -1) {
|
||||||
|
|
||||||
|
// Filter by property value
|
||||||
|
let propertyValue = '';
|
||||||
|
switch (parts[0]) {
|
||||||
|
case 'description':
|
||||||
|
propertyValue = task.description;
|
||||||
|
break;
|
||||||
|
case 'assigned':
|
||||||
|
propertyValue = task.metadata.assigned || '';
|
||||||
|
break;
|
||||||
|
case 'tag':
|
||||||
|
propertyValue = (task.metadata.tags || []).join(' ');
|
||||||
|
break;
|
||||||
|
case 'relation':
|
||||||
|
propertyValue = task.relations.map(relation => `${relation.type} ${relation.task}`).join(' ');
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if (!propertyValue.toLowerCase().includes(parts[1])) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
const Board = ({ name, description, columns, startedColumns, completedColumns, dateFormat, vscode }: {
|
const Board = ({ name, description, columns, startedColumns, completedColumns, dateFormat, vscode }: {
|
||||||
name: string,
|
name: string,
|
||||||
description: string,
|
description: string,
|
||||||
@ -65,9 +138,12 @@ const Board = ({ name, description, columns, startedColumns, completedColumns, d
|
|||||||
vscode: VSCodeApi
|
vscode: VSCodeApi
|
||||||
}) => {
|
}) => {
|
||||||
const [, setColumns] = useState(columns);
|
const [, setColumns] = useState(columns);
|
||||||
|
const [taskFilter, setTaskFilter] = useState('');
|
||||||
|
|
||||||
const filterTasks = () => {
|
// Called when the filter form is submitted
|
||||||
console.log();
|
const filterTasks = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
setTaskFilter((document.querySelector('.kanbn-filter-input') as HTMLInputElement).value);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -76,17 +152,19 @@ const Board = ({ name, description, columns, startedColumns, completedColumns, d
|
|||||||
<h1 className="kanbn-header-name">
|
<h1 className="kanbn-header-name">
|
||||||
<p>{name}</p>
|
<p>{name}</p>
|
||||||
<div className="kanbn-filter">
|
<div className="kanbn-filter">
|
||||||
<input
|
<form>
|
||||||
className="kanbn-filter-input"
|
<input
|
||||||
placeholder="Filter tasks"
|
className="kanbn-filter-input"
|
||||||
/>
|
placeholder="Filter tasks"
|
||||||
<button
|
/>
|
||||||
type="button"
|
<button
|
||||||
className="kanbn-filter-button"
|
type="submit"
|
||||||
onClick={filterTasks}
|
className="kanbn-filter-button"
|
||||||
>
|
onClick={filterTasks}
|
||||||
<i className="codicon codicon-filter"></i>
|
>
|
||||||
</button>
|
<i className="codicon codicon-filter"></i>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="kanbn-header-description">
|
<p className="kanbn-header-description">
|
||||||
@ -143,7 +221,7 @@ const Board = ({ name, description, columns, startedColumns, completedColumns, d
|
|||||||
snapshot.isDraggingOver ? 'drag-over' : null
|
snapshot.isDraggingOver ? 'drag-over' : null
|
||||||
].filter(i => i).join(' ')}
|
].filter(i => i).join(' ')}
|
||||||
>
|
>
|
||||||
{column.map((task, position) => <TaskItem
|
{column.filter(task => filterTask(task, taskFilter)).map((task, position) => <TaskItem
|
||||||
task={task}
|
task={task}
|
||||||
position={position}
|
position={position}
|
||||||
dateFormat={dateFormat}
|
dateFormat={dateFormat}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user