made installer and seperated stuff into diferent files
This commit is contained in:
181
ProjectKiln/app/js/home/task_list.js
Normal file
181
ProjectKiln/app/js/home/task_list.js
Normal file
@@ -0,0 +1,181 @@
|
||||
async function loadProjectTasks(projectId, page = 1, pushHistory = true) {
|
||||
const view = showView('taskListView');
|
||||
|
||||
if (!view) return;
|
||||
|
||||
if (pushHistory) {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set('page', 'home');
|
||||
url.searchParams.set('project', projectId);
|
||||
url.searchParams.set('tasks', '1');
|
||||
url.searchParams.delete('task');
|
||||
url.searchParams.delete('version');
|
||||
url.searchParams.delete('profile');
|
||||
url.searchParams.delete('admin');
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
|
||||
currentProjectTaskProject = projectId;
|
||||
setText('taskListProjectKey', projectId);
|
||||
setText('taskListTitle', `${projectId} Tasks`);
|
||||
|
||||
const container = document.getElementById('taskListContainer');
|
||||
const empty = document.getElementById('taskListEmpty');
|
||||
|
||||
container.innerHTML = '<div class="version-task-loading">Loading tasks...</div>';
|
||||
empty.hidden = true;
|
||||
currentProjectTasks = [];
|
||||
projectTaskPagination = null;
|
||||
|
||||
const result = await apiGet('/api/task.php', {
|
||||
api: 'ListTasksByProject',
|
||||
project_id: projectId,
|
||||
page,
|
||||
per_page: taskTablePageSize,
|
||||
sort: projectTaskSort.field,
|
||||
direction: projectTaskSort.direction
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
container.innerHTML = '<div class="alert alert-danger mb-0">Could not load tasks.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.tasks.length) {
|
||||
container.innerHTML = '';
|
||||
empty.hidden = false;
|
||||
renderTaskTablePagination('project');
|
||||
return;
|
||||
}
|
||||
|
||||
currentProjectTasks = await normalizeTaskTableRows(result.tasks);
|
||||
projectTaskPagination = result.pagination ?? null;
|
||||
renderTaskTable('project');
|
||||
}
|
||||
|
||||
async function normalizeTaskTableRows(tasks) {
|
||||
const [types, priorities] = await Promise.all([
|
||||
getTaskTypes(),
|
||||
getTaskPriorities()
|
||||
]);
|
||||
|
||||
return tasks.map((task) => {
|
||||
const normalizedTask = typeof task === 'string'
|
||||
? { id: task, title: '', type: null, priority: null }
|
||||
: task;
|
||||
|
||||
const type = types.find((item) => String(item.id) === String(normalizedTask.type)) ?? null;
|
||||
const priority = priorities.find((item) => String(item.id) === String(normalizedTask.priority)) ?? null;
|
||||
|
||||
return {
|
||||
...normalizedTask,
|
||||
typeOption: type,
|
||||
priorityOption: priority,
|
||||
typeName: type?.name ?? '',
|
||||
priorityName: priority?.name ?? '',
|
||||
statusName: normalizedTask.status_state?.name ?? '',
|
||||
statusColor: normalizedTask.status_state?.color ?? '',
|
||||
assigneeUser: normalizedTask.assignee
|
||||
? {
|
||||
id: normalizedTask.assignee,
|
||||
name: normalizedTask.assignee_name ?? `User ${normalizedTask.assignee}`,
|
||||
picture: normalizedTask.assignee_picture ?? null
|
||||
}
|
||||
: null,
|
||||
assigneeName: normalizedTask.assignee_name ?? ''
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function renderTaskTable(kind) {
|
||||
const isVersion = kind === 'version';
|
||||
const list = document.getElementById(isVersion ? 'versionTaskList' : 'taskListContainer');
|
||||
const empty = document.getElementById(isVersion ? 'versionTaskEmpty' : 'taskListEmpty');
|
||||
const tasks = isVersion ? currentVersionTasks : currentProjectTasks;
|
||||
|
||||
if (!list || !empty) return;
|
||||
|
||||
updateTaskTableSortButtons(kind);
|
||||
|
||||
list.innerHTML = '';
|
||||
empty.hidden = tasks.length > 0;
|
||||
|
||||
tasks.forEach((task) => {
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'version-task-row version-task-item';
|
||||
button.innerHTML = `
|
||||
<span class="version-task-id">${escapeHtml(task.id)}</span>
|
||||
<span class="version-task-title">${escapeHtml(task.title || '-')}</span>
|
||||
<span>${renderMetaBadge(task.typeOption)}</span>
|
||||
<span>${renderMetaBadge(task.priorityOption)}</span>
|
||||
<span>${renderUser(task.assigneeUser)}</span>
|
||||
<span>${renderTaskTableStatus(task)}</span>
|
||||
`;
|
||||
button.addEventListener('click', () => loadTask(task.id));
|
||||
|
||||
list.appendChild(button);
|
||||
});
|
||||
|
||||
renderTaskTablePagination(kind);
|
||||
}
|
||||
|
||||
function renderTaskTableStatus(task) {
|
||||
if (!task.statusName) return '-';
|
||||
|
||||
const color = task.statusColor || '#6c757d';
|
||||
|
||||
return `
|
||||
<span class="version-task-status" style="--task-status-color: ${escapeHtml(color)}">
|
||||
${escapeHtml(task.statusName)}
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
|
||||
function renderTaskTablePagination(kind) {
|
||||
const isVersion = kind === 'version';
|
||||
const pagination = isVersion ? versionTaskPagination : projectTaskPagination;
|
||||
const container = document.getElementById(isVersion ? 'versionTaskPagination' : 'projectTaskPagination');
|
||||
|
||||
if (!container) return;
|
||||
|
||||
if (!pagination || pagination.total <= pagination.per_page) {
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const start = ((pagination.page - 1) * pagination.per_page) + 1;
|
||||
const end = Math.min(pagination.total, pagination.page * pagination.per_page);
|
||||
|
||||
container.innerHTML = `
|
||||
<span>${escapeHtml(start)}-${escapeHtml(end)} of ${escapeHtml(pagination.total)}</span>
|
||||
<div class="version-task-page-actions">
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-task-page="${escapeHtml(kind)}" data-page="${escapeHtml(pagination.page - 1)}" ${pagination.page <= 1 ? 'disabled' : ''}>
|
||||
<i class="fa-solid fa-chevron-left"></i>
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-secondary" type="button" data-task-page="${escapeHtml(kind)}" data-page="${escapeHtml(pagination.page + 1)}" ${pagination.page >= pagination.total_pages ? 'disabled' : ''}>
|
||||
<i class="fa-solid fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function updateTaskTableSortButtons(kind) {
|
||||
const isVersion = kind === 'version';
|
||||
const selector = isVersion ? '[data-version-task-sort]' : '[data-project-task-sort]';
|
||||
const state = isVersion ? versionTaskSort : projectTaskSort;
|
||||
|
||||
document.querySelectorAll(selector).forEach((button) => {
|
||||
const field = isVersion ? button.dataset.versionTaskSort : button.dataset.projectTaskSort;
|
||||
const isActive = field === state.field;
|
||||
const icon = button.querySelector('i');
|
||||
|
||||
button.classList.toggle('is-active', isActive);
|
||||
|
||||
if (!icon) return;
|
||||
|
||||
icon.className = isActive
|
||||
? `fa-solid ${state.direction === 'asc' ? 'fa-sort-up' : 'fa-sort-down'}`
|
||||
: 'fa-solid fa-sort';
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user