r
This commit is contained in:
138
public/script.js
138
public/script.js
@@ -2,7 +2,7 @@ let currentUser = null;
|
||||
let users = [];
|
||||
let tasks = [];
|
||||
let filteredUsers = [];
|
||||
|
||||
let expandedTasks = new Set();
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
checkAuth();
|
||||
setupEventListeners();
|
||||
@@ -284,6 +284,7 @@ function renderTasks() {
|
||||
}
|
||||
|
||||
container.innerHTML = filteredTasks.map(task => {
|
||||
const isExpanded = expandedTasks.has(task.id);
|
||||
const overallStatus = getTaskOverallStatus(task);
|
||||
const statusClass = getStatusClass(overallStatus);
|
||||
const isDeleted = task.status === 'deleted';
|
||||
@@ -296,78 +297,93 @@ function renderTasks() {
|
||||
|
||||
return `
|
||||
<div class="task-card ${isDeleted ? 'deleted' : ''} ${isClosed ? 'closed' : ''}">
|
||||
<div class="task-actions">
|
||||
${!isDeleted && !isClosed ? `
|
||||
${canEdit ? `<button class="edit-btn" onclick="openEditModal(${task.id})" title="Редактировать">✏️</button>` : ''}
|
||||
<button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button>
|
||||
${canEdit ? `<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Вернуть на доработку">🔄</button>` : ''}
|
||||
${canEdit ? `<button class="close-btn" onclick="closeTask(${task.id})" title="Закрыть задачу">🔒</button>` : ''}
|
||||
${canEdit ? `<button class="delete-btn" onclick="deleteTask(${task.id})" title="Удалить">🗑️</button>` : ''}
|
||||
` : ''}
|
||||
${isClosed && canEdit ? `
|
||||
<button class="reopen-btn" onclick="reopenTask(${task.id})" title="Открыть задачу">🔓</button>
|
||||
` : ''}
|
||||
${isDeleted && currentUser.role === 'admin' ? `
|
||||
<button class="restore-btn" onclick="restoreTask(${task.id})" title="Восстановить">↶</button>
|
||||
` : ''}
|
||||
</div>
|
||||
|
||||
<div class="task-header">
|
||||
<div class="task-title">
|
||||
${task.title}
|
||||
${isDeleted ? '<span class="deleted-badge">Удалена</span>' : ''}
|
||||
${isClosed ? '<span class="closed-badge">Закрыта</span>' : ''}
|
||||
${isCopy ? '<span class="copy-badge">Копия</span>' : ''}
|
||||
${timeLeftInfo ? `<span class="deadline-badge ${timeLeftInfo.class}">${timeLeftInfo.text}</span>` : ''}
|
||||
<span class="role-badge ${getRoleBadgeClass(userRole)}">${userRole}</span>
|
||||
<div class="task-title" onclick="toggleTask(${task.id})" style="cursor: pointer; display: flex; justify-content: space-between; align-items: center;">
|
||||
<div style="flex: 1;">
|
||||
<span class="task-number">Задача №${task.id}</span>
|
||||
<strong>${task.title}</strong>
|
||||
${isDeleted ? '<span class="deleted-badge">Удалена</span>' : ''}
|
||||
${isClosed ? '<span class="closed-badge">Закрыта</span>' : ''}
|
||||
${isCopy ? '<span class="copy-badge">Копия</span>' : ''}
|
||||
${timeLeftInfo ? `<span class="deadline-badge ${timeLeftInfo.class}">${timeLeftInfo.text}</span>` : ''}
|
||||
<span class="role-badge ${getRoleBadgeClass(userRole)}">${userRole}</span>
|
||||
</div>
|
||||
<div class="task-status ${statusClass}">${getStatusText(overallStatus)}</div>
|
||||
<div class="expand-icon" style="margin-left: 10px; transition: transform 0.3s; transform: rotate(${isExpanded ? '180deg' : '0deg'});">
|
||||
▼
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-status ${statusClass}">${getStatusText(overallStatus)}</div>
|
||||
</div>
|
||||
|
||||
${isCopy && task.original_task_title ? `
|
||||
<div class="task-original">
|
||||
<small>Оригинал: "${task.original_task_title}" (создал: ${task.original_creator_name})</small>
|
||||
<div class="task-content" style="display: ${isExpanded ? 'block' : 'none'};">
|
||||
<div class="task-actions">
|
||||
${!isDeleted && !isClosed ? `
|
||||
${canEdit ? `<button class="edit-btn" onclick="openEditModal(${task.id})" title="Редактировать">✏️</button>` : ''}
|
||||
<button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button>
|
||||
${canEdit ? `<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Вернуть на доработку">🔄</button>` : ''}
|
||||
${canEdit ? `<button class="close-btn" onclick="closeTask(${task.id})" title="Закрыть задачу">🔒</button>` : ''}
|
||||
${canEdit ? `<button class="delete-btn" onclick="deleteTask(${task.id})" title="Удалить">🗑️</button>` : ''}
|
||||
` : ''}
|
||||
${isClosed && canEdit ? `
|
||||
<button class="reopen-btn" onclick="reopenTask(${task.id})" title="Открыть задачу">🔓</button>
|
||||
` : ''}
|
||||
${isDeleted && currentUser.role === 'admin' ? `
|
||||
<button class="restore-btn" onclick="restoreTask(${task.id})" title="Восстановить">↶</button>
|
||||
` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="task-description">${task.description || 'Нет описания'}</div>
|
||||
|
||||
${task.rework_comment ? `
|
||||
<div class="rework-comment">
|
||||
<strong>Комментарий к доработке:</strong> ${task.rework_comment}
|
||||
|
||||
${isCopy && task.original_task_title ? `
|
||||
<div class="task-original">
|
||||
<small>Оригинал: "${task.original_task_title}" (создал: ${task.original_creator_name})</small>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="task-description">${task.description || 'Нет описания'}</div>
|
||||
|
||||
${task.rework_comment ? `
|
||||
<div class="rework-comment">
|
||||
<strong>Комментарий к доработке:</strong> ${task.rework_comment}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${task.start_date || task.due_date ? `
|
||||
<div class="task-dates">
|
||||
<div><strong>Создана:</strong> ${formatDateTime(task.start_date || task.created_at)}</div>
|
||||
${task.due_date ? `<div><strong>Выполнить до:</strong> ${formatDateTime(task.due_date)}</div>` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="task-assignments">
|
||||
<strong>Исполнители:</strong>
|
||||
${task.assignments && task.assignments.length > 0 ?
|
||||
task.assignments.map(assignment => renderAssignment(assignment, task.id, canEdit)).join('') :
|
||||
'<div>Не назначены</div>'
|
||||
}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${task.start_date || task.due_date ? `
|
||||
<div class="task-dates">
|
||||
<div><strong>Создана:</strong> ${formatDateTime(task.start_date || task.created_at)}</div>
|
||||
${task.due_date ? `<div><strong>Выполнить до:</strong> ${formatDateTime(task.due_date)}</div>` : ''}
|
||||
|
||||
<div class="file-list" id="files-${task.id}">
|
||||
<strong>Файлы:</strong>
|
||||
<div class="loading">Загрузка...</div>
|
||||
</div>
|
||||
|
||||
<div class="task-meta">
|
||||
<small>Создана: ${formatDateTime(task.created_at)} | Автор: ${task.creator_name}</small>
|
||||
${task.deleted_at ? `<br><small>Удалена: ${formatDateTime(task.deleted_at)}</small>` : ''}
|
||||
${task.closed_at ? `<br><small>Закрыта: ${formatDateTime(task.closed_at)}</small>` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<div class="task-assignments">
|
||||
<strong>Исполнители:</strong>
|
||||
${task.assignments && task.assignments.length > 0 ?
|
||||
task.assignments.map(assignment => renderAssignment(assignment, task.id, canEdit)).join('') :
|
||||
'<div>Не назначены</div>'
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="file-list" id="files-${task.id}">
|
||||
<strong>Файлы:</strong>
|
||||
<div class="loading">Загрузка...</div>
|
||||
</div>
|
||||
|
||||
<div class="task-meta">
|
||||
<small>Создана: ${formatDateTime(task.created_at)} | Автор: ${task.creator_name}</small>
|
||||
${task.deleted_at ? `<br><small>Удалена: ${formatDateTime(task.deleted_at)}</small>` : ''}
|
||||
${task.closed_at ? `<br><small>Закрыта: ${formatDateTime(task.closed_at)}</small>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
|
||||
function toggleTask(taskId) {
|
||||
if (expandedTasks.has(taskId)) {
|
||||
expandedTasks.delete(taskId);
|
||||
} else {
|
||||
expandedTasks.add(taskId);
|
||||
}
|
||||
renderTasks();
|
||||
}
|
||||
function getTimeLeftInfo(task) {
|
||||
if (!task.due_date || task.closed_at) return null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user