Skip to content

Task Hierarchy filtering #35

@elimisteve

Description

@elimisteve
  • StatusFilter component, to filter tasks by status
    • Should be analogous to a Gmail-style check list, with all boxes checked by default
  • AssignerFilter component, which filters task by assignee (task.assigned_to)
    • Should be a multi-select with no boxes checked by default

By default, show all tasks with all statuses and assignees (or no assignee).

Potential special case: if no username is specified in its filter/search component, include all tasks, not just tasks assigned to usernames in an empty array, which would show no tasks rather than all of them :-).

Should be able to tweak then reuse the filtering logic from the RightPanel TaskDetails:

taskMatches = (tasks) => {
const { taskListFilter } = this.props.rightPanel;
const taskListFilterTrimmed = taskListFilter.trim();
const filters = this.parseTaskListFilter();
const matches = {};
let task;
let status;
let statusNot;
let assigned_to;
let dueBefore;
let due_date;
let dueAfter;
gidInTasks:
for (let gid in tasks) {
if (taskListFilterTrimmed === '') {
matches[gid] = true;
continue;
}
task = tasks[gid];
let matchStatus = false;
let matchAssignedTo = false;
let matchDueDate = false;
let matchTitle = false;
const taskStatusLower = task.status.toLowerCase();
for (let i in filters.status) {
status = filters.status[i];
if (taskStatusLower.startsWith(status.toLowerCase())) {
matchStatus = true;
break;
}
}
if (!matchStatus && filters.status.length > 0) {
// Status didn't match && filtering on status => Not an overall match
continue;
}
for (let i in filters.statusNot) {
statusNot = filters.statusNot[i];
if (taskStatusLower.startsWith(statusNot.toLowerCase())) {
// Not all anti-statuses matched && filtering on not-status
// => Not an overall match
continue gidInTasks;
}
}
for (let i in filters.assigned_to) {
assigned_to = filters.assigned_to[i];
if (task.assigned_to_pursuance_id === null
&&
((task.assigned_to || '').startsWith(assigned_to)
||
(task.assigned_to === null &&
assigned_to === '-'))) {
matchAssignedTo = true;
break;
}
}
if (!matchAssignedTo && filters.assigned_to.length > 0) {
// Assignee didn't match && filtering on assignee => Not an overall match
continue;
}
for (let i in filters.due_date) {
due_date = filters.due_date[i];
if ((task.due_date || '').startsWith(due_date) ||
(task.due_date === null && due_date === '-')) {
matchDueDate = true;
break;
}
}
if (!matchDueDate && filters.due_date.length > 0) {
// Due date didn't match && filtering on due date => Not an overall match
continue;
}
for (let i in filters.dueBefore) {
dueBefore = filters.dueBefore[i];
// Treating null as neither before nor after any date
if (!task.due_date || task.due_date.localeCompare(dueBefore) >= 0) {
continue gidInTasks;
}
}
for (let i in filters.dueAfter) {
dueAfter = filters.dueAfter[i];
// Treating null as after all dates
if (task.due_date && task.due_date.localeCompare(dueAfter) < 0) {
continue gidInTasks;
}
}
if (task.title.toLowerCase().indexOf(filters.title.toLowerCase()) !== -1) {
matchTitle = true;
}
if (!matchTitle && filters.title.length > 0) {
// Title didn't match && filtering on title => Not an overall match
continue;
}
matches[gid] = true;
}
return matches;
}
.

@Iancam Here you go!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions