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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions