feat: add task filtering and search (#16)

This commit is contained in:
2026-03-04 18:08:12 -08:00
parent 1f17d44ee2
commit fa5e1887f4
3 changed files with 196 additions and 0 deletions

View File

@@ -68,6 +68,112 @@ const COLUMNS = {
};
let wikiPages = [];
let allTasks = [];
let taskFilters = { search: '', status: '', assignee: '', priority: '' };
async function loadTasks() {
const res = await fetch('/api/tasks');
allTasks = await res.json();
// Populate assignee filter dropdown
const assigneeFilter = document.getElementById('filter-assignee');
if (assigneeFilter) {
const assignees = [...new Set(allTasks.map(t => t.assignee).filter(Boolean))];
assigneeFilter.innerHTML = '<option value="">All Assignees</option>' +
assignees.map(a => `<option value="${a}">${a}</option>`).join('');
}
applyTaskFilters();
}
function applyTaskFilters() {
let filtered = [...allTasks];
// Search filter
if (taskFilters.search) {
const search = taskFilters.search.toLowerCase();
filtered = filtered.filter(t =>
t.title.toLowerCase().includes(search) ||
(t.description && t.description.toLowerCase().includes(search))
);
}
// Status filter
if (taskFilters.status) {
filtered = filtered.filter(t => t.status === taskFilters.status);
}
// Assignee filter
if (taskFilters.assignee) {
filtered = filtered.filter(t => t.assignee === taskFilters.assignee);
}
// Priority filter
if (taskFilters.priority) {
filtered = filtered.filter(t => t.priority === taskFilters.priority);
}
// Reset columns
Object.keys(COLUMNS).forEach((status) => {
COLUMNS[status].tasks = [];
});
// Distribute filtered tasks to columns
filtered.forEach((task) => {
if (COLUMNS[task.status]) {
COLUMNS[task.status].tasks.push(task);
}
});
renderBoard();
}
function initTaskFilters() {
const searchInput = document.getElementById('task-search');
const statusFilter = document.getElementById('filter-status');
const assigneeFilter = document.getElementById('filter-assignee');
const priorityFilter = document.getElementById('filter-priority');
const clearBtn = document.getElementById('clear-filters');
if (searchInput) {
searchInput.addEventListener('input', (e) => {
taskFilters.search = e.target.value;
applyTaskFilters();
});
}
if (statusFilter) {
statusFilter.addEventListener('change', (e) => {
taskFilters.status = e.target.value;
applyTaskFilters();
});
}
if (assigneeFilter) {
assigneeFilter.addEventListener('change', (e) => {
taskFilters.assignee = e.target.value;
applyTaskFilters();
});
}
if (priorityFilter) {
priorityFilter.addEventListener('change', (e) => {
taskFilters.priority = e.target.value;
applyTaskFilters();
});
}
if (clearBtn) {
clearBtn.addEventListener('click', () => {
taskFilters = { search: '', status: '', assignee: '', priority: '' };
if (searchInput) searchInput.value = '';
if (statusFilter) statusFilter.value = '';
if (assigneeFilter) assigneeFilter.value = '';
if (priorityFilter) priorityFilter.value = '';
applyTaskFilters();
});
}
}
let currentWikiPage = null;
let allAgents = [];
let usageStats = null;
@@ -225,6 +331,7 @@ function initTasksPage() {
loadTasks();
});
initTaskFilters();
populateAgentDropdown();
loadTasks();
}