task-file

This commit is contained in:
2026-02-02 22:04:38 +05:00
parent ce0952844f
commit 77504d9130
5 changed files with 219 additions and 17 deletions

View File

@@ -79,6 +79,7 @@ function renderTasks() {
<div class="task-content ${isExpanded ? 'expanded' : ''}">
<div class="task-actions">
${!isDeleted && !isClosed ? `
${canEdit ? `<button class="add-file-btn" onclick="openAddFileModal(${task.id})" title="Добавить файл">📎</button>` : ''}
${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>` : ''}
@@ -246,7 +247,7 @@ function renderAssignment(assignment, taskId, canEdit) {
${assignment.start_date || assignment.due_date ? `
<div class="assignment-dates">
${assignment.start_date ? `<small>Начало: ${formatDateTime(assignment.start_date)}</small>` : ''}
${assignment.due_date ? `<small>2Выполнить до: ${formatDateTime(assignment.due_date)}</small>` : ''}
${assignment.due_date ? `<small>Выполнить до: ${formatDateTime(assignment.due_date)}</small>` : ''}
</div>
` : ''}
${assignment.rework_comment ? `
@@ -363,15 +364,8 @@ function getUserRoleInTask(task) {
if (currentUser.role === 'admin') return 'Администратор';
// Создатель задачи всегда должен иметь право редактировать свою задачу
if (parseInt(task.created_by) === currentUser.id) {
if (task.assignments && task.assignments.length > 0) {
const assignedToOthers = task.assignments.some(assignment =>
parseInt(assignment.user_id) !== currentUser.id
);
if (assignedToOthers) {
return 'Создатель (только просмотр)';
}
}
return 'Создатель';
}
@@ -468,4 +462,182 @@ async function viewTaskDetails(taskId) {
} catch (error) {
console.error('Ошибка загрузки деталей задачи:', error);
}
}
// Функция для открытия модального окна добавления файла
function openAddFileModal(taskId) {
// Находим задачу
const task = tasks.find(t => t.id === taskId);
if (!task) {
alert('Задача не найдена');
return;
}
// Проверяем права
if (!canUserAddFilesToTask(task)) {
alert('У вас нет прав для добавления файлов к этой задаче');
return;
}
// Создаем модальное окно
const modalHtml = `
<div class="modal" id="add-file-modal">
<div class="modal-content">
<div class="modal-header">
<h3>Добавить файл к задаче: "${task.title}"</h3>
<span class="close" onclick="closeAddFileModal()">&times;</span>
</div>
<div class="modal-body">
<form id="add-file-form">
<input type="hidden" name="task_id" value="${taskId}">
<div class="form-group">
<label for="file-input">Выберите файл:</label>
<input type="file" id="file-input" name="files" multiple>
<small>Максимальный размер: 10MB</small>
</div>
<div class="form-group">
<label for="file-description">Описание файла (необязательно):</label>
<textarea id="file-description" name="description" rows="3"
placeholder="Описание файла..."></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn-cancel" onclick="closeAddFileModal()">Отмена</button>
<button type="submit" class="btn-primary">Добавить файл</button>
</div>
</form>
</div>
</div>
</div>
`;
// Добавляем модальное окно в DOM
const modalContainer = document.createElement('div');
modalContainer.innerHTML = modalHtml;
document.body.appendChild(modalContainer);
// Обработчик отправки формы
document.getElementById('add-file-form').addEventListener('submit', async function(e) {
e.preventDefault();
const fileInput = document.getElementById('file-input');
const description = document.getElementById('file-description').value;
if (fileInput.files.length === 0) {
alert('Выберите файл для загрузки');
return;
}
const file = fileInput.files[0];
const formData = new FormData();
// Пробуем сначала 'files', затем 'file'
formData.append('files', file); // Или 'file' в зависимости от сервера
formData.append('task_id', taskId);
if (description) {
formData.append('description', description);
}
try {
// Попробуем с полем 'files' (скорее всего это правильное имя)
let response = await fetch(`/api/tasks/${taskId}/files`, {
method: 'POST',
body: formData
});
if (!response.ok) {
// Попробуем с полем 'file'
console.log('Попытка с именем поля "file"...');
formData.delete('files');
formData.append('file', file);
response = await fetch(`/api/tasks/${taskId}/files`, {
method: 'POST',
body: formData
});
}
if (response.ok) {
alert('Файл успешно добавлен');
await loadTaskFiles(taskId);
closeAddFileModal();
// Обновляем задачу, если она развернута
if (expandedTasks.has(taskId)) {
renderTasks();
}
} else {
const errorText = await response.text();
console.error('Ошибка сервера:', errorText);
alert(`Ошибка при добавлении файла: ${response.status} ${response.statusText}`);
}
} catch (error) {
console.error('Ошибка:', error);
alert('Сетевая ошибка при добавлении файла: ' + error.message);
}
});
// Показываем модальное окно
setTimeout(() => {
document.getElementById('add-file-modal').style.display = 'block';
}, 10);
}
// Функция для закрытия модального окна добавления файла
function closeAddFileModal() {
const modal = document.getElementById('add-file-modal');
if (modal) {
modal.style.display = 'none';
// Удаляем модальное окно из DOM через некоторое время
setTimeout(() => {
modal.parentElement.remove();
}, 300);
}
}
// Функция для закрытия модального окна добавления файла
function closeAddFileModal() {
const modal = document.getElementById('add-file-modal');
if (modal) {
modal.style.display = 'none';
// Удаляем модальное окно из DOM через некоторое время
setTimeout(() => {
modal.parentElement.remove();
}, 300);
}
}
// Функция для загрузки файлов задачи (если её еще нет)
async function loadTaskFiles(taskId) {
try {
const response = await fetch(`/api/tasks/${taskId}/files`);
const files = await response.json();
// Обновляем файлы в задаче
const taskIndex = tasks.findIndex(t => t.id === taskId);
if (taskIndex !== -1) {
tasks[taskIndex].files = files;
}
// Обновляем отображение файлов
const fileContainer = document.getElementById(`files-${taskId}`);
if (fileContainer) {
const fileList = fileContainer.querySelector('.file-icons-container');
if (fileList) {
fileList.innerHTML = files.map(file => renderFileIcon(file)).join('');
} else {
fileContainer.innerHTML = `
<strong>Файлы:</strong>
${files.length > 0 ?
`<div class="file-icons-container">${files.map(file => renderFileIcon(file)).join('')}</div>` :
'<span class="no-files">нет файлов</span>'
}
`;
}
}
} catch (error) {
console.error('Ошибка загрузки файлов:', error);
}
}