переделал ui
This commit is contained in:
190
public/ui.js
190
public/ui.js
@@ -8,16 +8,18 @@ function showSection(sectionName) {
|
||||
document.getElementById(sectionName + '-section').classList.add('active');
|
||||
|
||||
if (sectionName === 'tasks') {
|
||||
loadTasks();
|
||||
loadTasks(); // из tasks.js
|
||||
} else if (sectionName === 'logs') {
|
||||
loadActivityLogs();
|
||||
} else if (sectionName === 'kanban') {
|
||||
loadKanbanTasks();
|
||||
} else if (sectionName === 'mytasks') {
|
||||
console.log('загружаю loadMyTasks');
|
||||
window.currentTaskView = 'my_assigned';
|
||||
loadTasks();
|
||||
} else if (sectionName === 'runtasks') {
|
||||
console.log('загружаю loadRunTasks');
|
||||
window.currentTaskView = 'assigned_to_me';
|
||||
loadTasks();
|
||||
}
|
||||
|
||||
@@ -27,6 +29,7 @@ function showSection(sectionName) {
|
||||
loadNotificationSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// Вызываем добавление стилей при загрузке страницы
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
addDocumentFieldsStyles();
|
||||
@@ -99,60 +102,16 @@ function renderDocumentFields(taskId, fields) {
|
||||
`;
|
||||
}
|
||||
|
||||
// Обновленная функция loadTasks для загрузки полей документа
|
||||
async function loadTasks() {
|
||||
try {
|
||||
const response = await fetch('/api/tasks');
|
||||
tasks = await response.json();
|
||||
|
||||
// Загружаем поля документа для каждой задачи типа "document"
|
||||
for (const task of tasks) {
|
||||
if (task.task_type === 'document') {
|
||||
try {
|
||||
const docResponse = await fetch(`/api/tasks/${task.id}/document-fields`);
|
||||
if (docResponse.ok) {
|
||||
const docData = await docResponse.json();
|
||||
task.document_fields = docData.data || {};
|
||||
} else {
|
||||
task.document_fields = {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Ошибка загрузки полей документа для задачи ${task.id}:`, error);
|
||||
task.document_fields = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Определяем активную секцию и рендерим в соответствующий контейнер
|
||||
const activeSection = document.querySelector('.section.active');
|
||||
if (activeSection) {
|
||||
const sectionId = activeSection.id;
|
||||
if (sectionId === 'mytasks-section') {
|
||||
renderTasksInContainer('mytasks-list');
|
||||
} else if (sectionId === 'runtasks-section') {
|
||||
renderTasksInContainer('runtasks-list');
|
||||
} else {
|
||||
renderTasks();
|
||||
}
|
||||
} else {
|
||||
renderTasks();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка загрузки задач:', error);
|
||||
const container = document.getElementById('tasks-list');
|
||||
if (container) {
|
||||
container.innerHTML = '<div class="error">Ошибка загрузки задач</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
// ========== УДАЛЕНА функция loadTasks – теперь используется общая из tasks.js ==========
|
||||
|
||||
// Функция рендеринга задач в общий контейнер (секция "Все задачи")
|
||||
function renderTasks() {
|
||||
const container = document.getElementById('tasks-list');
|
||||
const showDeleted = document.getElementById('show-deleted')?.checked || false;
|
||||
|
||||
let filteredTasks = tasks;
|
||||
let filteredTasks = window.tasks;
|
||||
if (!showDeleted) {
|
||||
filteredTasks = tasks.filter(task => task.status === 'active');
|
||||
filteredTasks = window.tasks.filter(task => task.status === 'active');
|
||||
}
|
||||
|
||||
if (filteredTasks.length === 0) {
|
||||
@@ -277,6 +236,130 @@ ${task.assignments && task.assignments.length > 0 ?
|
||||
}).join('');
|
||||
}
|
||||
|
||||
// Функция для рендеринга задач в указанный контейнер (для секций mytasks и runtasks)
|
||||
function renderTasksInContainer(containerId, tasksArray) {
|
||||
const container = document.getElementById(containerId);
|
||||
if (!container) return;
|
||||
|
||||
if (!tasksArray || tasksArray.length === 0) {
|
||||
container.innerHTML = '<div class="loading">Задачи не найдены</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = tasksArray.map(task => {
|
||||
const isExpanded = expandedTasks.has(task.id);
|
||||
const overallStatus = getTaskOverallStatus(task);
|
||||
const statusClass = getStatusClass(overallStatus);
|
||||
const isDeleted = task.status === 'deleted';
|
||||
const isClosed = task.closed_at !== null;
|
||||
const userRole = getUserRoleInTask(task);
|
||||
const canEdit = canUserEditTask(task);
|
||||
const isCopy = task.original_task_id !== null;
|
||||
const timeLeftInfo = getTimeLeftInfo(task);
|
||||
const documentFields = task.document_fields || {};
|
||||
|
||||
// Тот же шаблон, что и в renderTasks
|
||||
return `
|
||||
<div class="task-card ${isDeleted ? 'deleted' : ''} ${isClosed ? 'closed' : ''}" data-task-id="${task.id}">
|
||||
<div class="task-header">
|
||||
<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>
|
||||
${task.assignments && task.assignments.length > 0 ? `<span class="task-number">${task.assignments.map(a => a.user_login || a.user_name).join(', ')}</span>` : ''}
|
||||
</div>
|
||||
<span class="task-status ${statusClass}">
|
||||
Выполнить до: ${formatDateTime(task.due_date || task.created_at)}
|
||||
</span>
|
||||
<div class="expand-icon" style="margin-left: 10px; transition: transform 0.3s; transform: rotate(${isExpanded ? '180deg' : '0deg'});">
|
||||
▼
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-content ${isExpanded ? 'expanded' : ''}">
|
||||
${isExpanded ? `
|
||||
<div class="task-actions">
|
||||
${!isDeleted && !isClosed ? `
|
||||
<button class="copy-btn" onclick="openTaskChat(${task.id})" title="Открыть чат">💬</button>
|
||||
<button class="add-file-btn" onclick="openAddFileModal(${task.id})" title="Добавить файл">📎</button>
|
||||
${currentUser && currentUser.login === 'minicrm' ? `<button class="edit-btn" onclick="openEditModal(${task.id})" title="Редактировать">✏️</button>` : ''}
|
||||
${currentUser && currentUser.login === 'kalugin.o' ? `<button class="manage-assignees-btn" onclick="openManageAssigneesModal(${task.id})" title="Управление исполнителями">👥</button>` : ''}
|
||||
${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin' ? `<button class="manage-assignees-btn" onclick="assignAdd_openModal(${task.id})" title="Управление исполнителями">🧑💼➕Добавить</button>` : ''}
|
||||
${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin' ? `<button class="manage-assignees-btn" onclick="assignRemove_openModal(${task.id})" title="Управление исполнителями">🧑💼❌Удалить</button>` : ''}
|
||||
<button class="copy-btn" onclick="openCopyModal(${task.id})" title="Создать копию">📋</button>
|
||||
${currentUser && currentUser.login === 'minicrm' ? `<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Вернуть на доработку">🔄</button>` : ''}
|
||||
|
||||
<!-- Кнопка переделки документа для исполнителей -->
|
||||
${task.task_type === 'document' && userRole === 'Исполнитель' ? `<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Переделать документ">🔄Переделать</button>` : ''}
|
||||
|
||||
${!isDeleted && !isClosed && task.task_type !== 'regular' && task.assignments && task.assignments.some(a => parseInt(a.user_id) === currentUser.id) ? `
|
||||
<button class="rework-btn" onclick="openReworkModal(${task.id})" title="Вернуть на доработку">🔄Доработка</button>
|
||||
<button class="change-deadline-btn" onclick="openChangeDeadlineModal(${task.id})" title="Изменить срок">📅</button>
|
||||
` : ''}
|
||||
|
||||
${currentUser && currentUser.login === 'minicrm' ? `<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>
|
||||
` : ''}
|
||||
|
||||
${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.task_type === 'document' ? renderDocumentFields(task.id, documentFields) : ''}
|
||||
|
||||
<div class="file-list" id="files-${task.id}">
|
||||
<strong>Файлы:</strong>
|
||||
${task.files && task.files.length > 0 ? renderGroupedFilesWithDelete(task) : '<span class="no-files">нет файлов</span>'}
|
||||
</div>
|
||||
|
||||
<div class="task-assignments">
|
||||
<strong>Исполнители:</strong>
|
||||
${task.assignments && task.assignments.length > 0 ?
|
||||
renderAssignmentList(task.assignments, task.id, canEdit) :
|
||||
'<div>Не назначены</div>'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="task-meta">
|
||||
<small>
|
||||
Создана: ${formatDateTime(task.start_date || task.created_at)}
|
||||
| Выполнить до: ${formatDateTime(task.due_date || task.created_at)}
|
||||
| Автор: ${task.creator_name}
|
||||
| Тип: ${task.task_type ? `<span class="task-type-badge ${task.task_type}">${getTaskTypeDisplayName(task.task_type)}</span>` : ''}
|
||||
</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 renderAssignmentList(assignments, taskId, canEdit) {
|
||||
if (!assignments || assignments.length === 0) {
|
||||
@@ -502,9 +585,9 @@ function toggleTask(taskId) {
|
||||
if (activeSection) {
|
||||
const sectionId = activeSection.id;
|
||||
if (sectionId === 'mytasks-section') {
|
||||
renderTasksInContainer('mytasks-list');
|
||||
renderTasksInContainer('mytasks-list', window.tasks);
|
||||
} else if (sectionId === 'runtasks-section') {
|
||||
renderTasksInContainer('runtasks-list');
|
||||
renderTasksInContainer('runtasks-list', window.tasks);
|
||||
} else if (sectionId === 'tasks-section') {
|
||||
renderTasks();
|
||||
}
|
||||
@@ -1942,6 +2025,7 @@ function renderGroupedFiles(task) {
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// ++++++++++++++++++++++++++++++ кнопки изменения срока задачи для исполнителей ++++++++++++++++++++++++++++++
|
||||
// Функция для открытия модального окна изменения срока задачи
|
||||
function openChangeDeadlineModal(taskId) {
|
||||
@@ -2013,7 +2097,6 @@ function openChangeDeadlineModal(taskId) {
|
||||
}, 10);
|
||||
}
|
||||
|
||||
// Функция закрытия модального окна
|
||||
function closeChangeDeadlineModal() {
|
||||
const modal = document.getElementById('change-deadline-modal');
|
||||
if (modal) {
|
||||
@@ -2024,7 +2107,6 @@ function closeChangeDeadlineModal() {
|
||||
}
|
||||
}
|
||||
|
||||
// Функция отправки изменения срока
|
||||
async function submitDeadlineChange(taskId) {
|
||||
const newDate = document.getElementById('new-deadline-date').value;
|
||||
const comment = document.getElementById('deadline-change-comment').value.trim();
|
||||
@@ -2110,4 +2192,4 @@ async function submitDeadlineChange(taskId) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// ++++++++++++++++++++++++++++++ кнопки изменения срока задачи для исполнителей ++++++++++++++++++++++++++++++
|
||||
// ++++++++++++++++++++++++++++++ конец кнопок изменения срока ++++++++++++++++++++++++++++++
|
||||
Reference in New Issue
Block a user