групировка фаилов
This commit is contained in:
@@ -103,29 +103,6 @@ function removeEditFile(index) {
|
|||||||
document.getElementById('edit-files').files = dataTransfer.files;
|
document.getElementById('edit-files').files = dataTransfer.files;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadTaskFiles(taskId) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/tasks/${taskId}/files`);
|
|
||||||
const files = await response.json();
|
|
||||||
|
|
||||||
const container = document.getElementById(`files-${taskId}`);
|
|
||||||
if (container) {
|
|
||||||
if (files.length === 0) {
|
|
||||||
container.innerHTML = '<strong>Файлы:</strong> <span class="files-placeholder">скрыто</span>';
|
|
||||||
} else {
|
|
||||||
container.innerHTML = `
|
|
||||||
<strong>Файлы:</strong>
|
|
||||||
<div class="file-icons-container">
|
|
||||||
${files.map(file => renderFileIcon(file)).join('')}
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Ошибка загрузки файлов:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderFileIcon(file) {
|
function renderFileIcon(file) {
|
||||||
// Исправляем кодировку имени файла
|
// Исправляем кодировку имени файла
|
||||||
const fixEncoding = (str) => {
|
const fixEncoding = (str) => {
|
||||||
|
|||||||
217
public/ui.js
217
public/ui.js
@@ -115,46 +115,7 @@ ${currentUser && currentUser.login === 'kalugin.o' ? `<button class="manage-assi
|
|||||||
|
|
||||||
<div class="file-list" id="files-${task.id}">
|
<div class="file-list" id="files-${task.id}">
|
||||||
<strong>Файлы:</strong>
|
<strong>Файлы:</strong>
|
||||||
${task.files && task.files.length > 0 ?
|
${task.files && task.files.length > 0 ? renderGroupedFiles(task) : '<span class="no-files">нет файлов</span>'}
|
||||||
`<div class="file-icons-container">
|
|
||||||
${task.files.map(file => {
|
|
||||||
// Определяем, может ли пользователь видеть этот файл
|
|
||||||
let canSeeFile = false;
|
|
||||||
|
|
||||||
// 1. Администратор видит все файлы
|
|
||||||
if (currentUser.role === 'admin') {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// 2. Создатель задачи видит все файлы
|
|
||||||
else if (parseInt(task.created_by) === currentUser.id) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// 3. Исполнитель видит:
|
|
||||||
// - Файлы, загруженные создателем
|
|
||||||
// - Свои файлы
|
|
||||||
else {
|
|
||||||
// Получаем ID создателя задачи
|
|
||||||
const creatorId = parseInt(task.created_by);
|
|
||||||
|
|
||||||
// Файл загружен создателем
|
|
||||||
if (parseInt(file.user_id) === creatorId) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// Файл загружен текущим пользователем (исполнителем)
|
|
||||||
else if (parseInt(file.user_id) === currentUser.id) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// Если файл загружен другим исполнителем - не показываем
|
|
||||||
else {
|
|
||||||
canSeeFile = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return canSeeFile ? renderFileIcon(file) : '';
|
|
||||||
}).join('')}
|
|
||||||
</div>` :
|
|
||||||
'<span class="no-files">нет файлов</span>'
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -656,81 +617,36 @@ function closeAddFileModal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для загрузки файлов задачи (если её еще нет)
|
// Обновленная функция для загрузки файлов задачи
|
||||||
async function loadTaskFiles(taskId) {
|
async function loadTaskFiles(taskId) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/tasks/${taskId}/files`);
|
const response = await fetch(`/api/tasks/${taskId}/files`);
|
||||||
const allFiles = await response.json();
|
const allFiles = await response.json(); // Получаем ВСЕ файлы
|
||||||
|
|
||||||
// Получаем задачу для определения создателя
|
// Получаем задачу
|
||||||
const taskIndex = tasks.findIndex(t => t.id === taskId);
|
const taskIndex = tasks.findIndex(t => t.id === taskId);
|
||||||
if (taskIndex === -1) {
|
if (taskIndex === -1) {
|
||||||
console.error('Задача не найдена:', taskId);
|
console.error('Задача не найдена:', taskId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const task = tasks[taskIndex];
|
// Сохраняем ВСЕ файлы в задаче (не фильтруем здесь!)
|
||||||
const creatorId = parseInt(task.created_by);
|
tasks[taskIndex].files = allFiles;
|
||||||
|
|
||||||
// Фильтруем файлы по тем же правилам, что и в HTML
|
// Обновляем отображение файлов с помощью renderGroupedFiles
|
||||||
const filteredFiles = allFiles.filter(file => {
|
// Она сама отфильтрует что показывать
|
||||||
// Определяем, может ли пользователь видеть этот файл
|
|
||||||
let canSeeFile = false;
|
|
||||||
|
|
||||||
// 1. Администратор видит все файлы
|
|
||||||
if (currentUser.role === 'admin') {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// 2. Создатель задачи видит все файлы
|
|
||||||
else if (creatorId === currentUser.id) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// 3. Исполнитель видит:
|
|
||||||
// - Файлы, загруженные создателем
|
|
||||||
// - Свои файлы
|
|
||||||
else {
|
|
||||||
const fileUserId = parseInt(file.user_id);
|
|
||||||
|
|
||||||
// Файл загружен создателем
|
|
||||||
if (fileUserId === creatorId) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// Файл загружен текущим пользователем (исполнителем)
|
|
||||||
else if (fileUserId === currentUser.id) {
|
|
||||||
canSeeFile = true;
|
|
||||||
}
|
|
||||||
// Если файл загружен другим исполнителем - не показываем
|
|
||||||
else {
|
|
||||||
canSeeFile = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return canSeeFile;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обновляем отфильтрованные файлы в задаче
|
|
||||||
tasks[taskIndex].files = filteredFiles;
|
|
||||||
|
|
||||||
// Обновляем отображение файлов
|
|
||||||
const fileContainer = document.getElementById(`files-${taskId}`);
|
const fileContainer = document.getElementById(`files-${taskId}`);
|
||||||
if (fileContainer) {
|
if (fileContainer) {
|
||||||
const fileList = fileContainer.querySelector('.file-icons-container');
|
fileContainer.innerHTML = `
|
||||||
if (fileList) {
|
<strong>Файлы:</strong>
|
||||||
fileList.innerHTML = filteredFiles.map(file => renderFileIcon(file)).join('');
|
${allFiles.length > 0 ? renderGroupedFiles(tasks[taskIndex]) : '<span class="no-files">нет файлов</span>'}
|
||||||
} else {
|
`;
|
||||||
fileContainer.innerHTML = `
|
|
||||||
<strong>Файлы:</strong>
|
|
||||||
${filteredFiles.length > 0 ?
|
|
||||||
`<div class="file-icons-container">${filteredFiles.map(file => renderFileIcon(file)).join('')}</div>` :
|
|
||||||
'<span class="no-files">нет файлов</span>'
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка загрузки файлов:', error);
|
console.error('Ошибка загрузки файлов:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для выбора типа задачи
|
// Функция для выбора типа задачи
|
||||||
function selectTaskType(type) {
|
function selectTaskType(type) {
|
||||||
// Убираем активный класс со всех кнопок
|
// Убираем активный класс со всех кнопок
|
||||||
@@ -1317,4 +1233,111 @@ function closeManageAssigneesModal() {
|
|||||||
modal.parentElement.remove();
|
modal.parentElement.remove();
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обновленная функция рендеринга файлов с группировкой по пользователям
|
||||||
|
// Обновленная функция рендеринга файлов с группировкой по пользователям
|
||||||
|
function renderGroupedFiles(task) {
|
||||||
|
if (!task.files || task.files.length === 0) {
|
||||||
|
return '<span class="no-files">нет файлов</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Группируем ВСЕ файлы по пользователю, который их загрузил
|
||||||
|
const filesByUploader = {};
|
||||||
|
|
||||||
|
// ВАЖНО: Используем все файлы задачи, а не отфильтрованные
|
||||||
|
task.files.forEach(file => {
|
||||||
|
const uploaderId = file.user_id;
|
||||||
|
const uploaderName = file.user_name || 'Неизвестный пользователь';
|
||||||
|
|
||||||
|
if (!filesByUploader[uploaderId]) {
|
||||||
|
filesByUploader[uploaderId] = {
|
||||||
|
name: uploaderName,
|
||||||
|
id: uploaderId,
|
||||||
|
files: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
filesByUploader[uploaderId].files.push(file);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Определяем, какие группы (загрузчики) может видеть текущий пользователь
|
||||||
|
const visibleGroups = [];
|
||||||
|
|
||||||
|
for (const uploaderId in filesByUploader) {
|
||||||
|
const uploaderGroup = filesByUploader[uploaderId];
|
||||||
|
const uploaderIdNum = parseInt(uploaderId);
|
||||||
|
|
||||||
|
// Проверяем, может ли текущий пользователь видеть файлы этого загрузчика
|
||||||
|
let canSeeThisUploader = false;
|
||||||
|
|
||||||
|
// 1. Администратор видит все файлы всех загрузчиков
|
||||||
|
if (currentUser.role === 'admin') {
|
||||||
|
canSeeThisUploader = true;
|
||||||
|
}
|
||||||
|
// 2. Создатель задачи видит все файлы всех загрузчиков
|
||||||
|
else if (parseInt(task.created_by) === currentUser.id) {
|
||||||
|
canSeeThisUploader = true;
|
||||||
|
}
|
||||||
|
// 3. Исполнитель видит:
|
||||||
|
// - Файлы создателя задачи
|
||||||
|
// - Свои файлы (если он их загрузил)
|
||||||
|
else {
|
||||||
|
const creatorId = parseInt(task.created_by);
|
||||||
|
|
||||||
|
// Файлы загружены создателем задачи
|
||||||
|
if (uploaderIdNum === creatorId) {
|
||||||
|
canSeeThisUploader = true;
|
||||||
|
}
|
||||||
|
// Файлы загружены текущим пользователем
|
||||||
|
else if (uploaderIdNum === currentUser.id) {
|
||||||
|
canSeeThisUploader = true;
|
||||||
|
}
|
||||||
|
// Если файлы загружены другим исполнителем - не показываем эту группу
|
||||||
|
else {
|
||||||
|
canSeeThisUploader = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если текущий пользователь может видеть эту группу, добавляем её
|
||||||
|
if (canSeeThisUploader) {
|
||||||
|
// В группе показываем ТОЛЬКО файлы этого загрузчика
|
||||||
|
visibleGroups.push({
|
||||||
|
name: uploaderGroup.name,
|
||||||
|
id: uploaderGroup.id,
|
||||||
|
files: uploaderGroup.files // Все файлы этого загрузчика
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visibleGroups.length === 0) {
|
||||||
|
return '<span class="no-files">нет файлов</span>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Рендерим только видимые группы
|
||||||
|
// Если файлы загружены только одним пользователем, показываем просто список
|
||||||
|
if (visibleGroups.length === 1) {
|
||||||
|
const uploader = visibleGroups[0];
|
||||||
|
return `
|
||||||
|
<div class="file-group single-user">
|
||||||
|
<div class="file-group-header">
|
||||||
|
<strong>${uploader.name}:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="file-icons-container">
|
||||||
|
${uploader.files.map(file => renderFileIcon(file)).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Если файлы загружены несколькими пользователями, группируем
|
||||||
|
return visibleGroups.map(uploader => `
|
||||||
|
<div class="file-group">
|
||||||
|
<div class="file-group-header">
|
||||||
|
<strong>${uploader.name}:</strong>
|
||||||
|
</div>
|
||||||
|
<div class="file-icons-container">
|
||||||
|
${uploader.files.map(file => renderFileIcon(file)).join('')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user