502 lines
21 KiB
JavaScript
502 lines
21 KiB
JavaScript
// main.js - Главный файл инициализации
|
||
let currentTaskView = 'all'; // 'all', 'my_assigned', 'assigned_to_me'
|
||
let allTasksCache = []; // Кэш всех задач
|
||
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
checkAuth();
|
||
setupEventListeners();
|
||
|
||
// Инициализация выбора времени
|
||
initializeTimeSelectors();
|
||
|
||
// Инициализация фильтра
|
||
const taskViewFilter = document.getElementById('task-view-filter');
|
||
if (taskViewFilter) {
|
||
taskViewFilter.value = currentTaskView;
|
||
}
|
||
|
||
// По умолчанию показываем секцию задач
|
||
showSection('tasks');
|
||
});
|
||
|
||
function setupEventListeners() {
|
||
// Форма входа
|
||
document.getElementById('login-form').addEventListener('submit', login);
|
||
|
||
// Формы задач
|
||
document.getElementById('create-task-form').addEventListener('submit', createTask);
|
||
document.getElementById('edit-task-form').addEventListener('submit', updateTask);
|
||
document.getElementById('copy-task-form').addEventListener('submit', copyTask);
|
||
document.getElementById('edit-assignment-form').addEventListener('submit', updateAssignment);
|
||
document.getElementById('rework-task-form').addEventListener('submit', sendForRework);
|
||
|
||
// Файлы
|
||
document.getElementById('files').addEventListener('change', updateFileList);
|
||
document.getElementById('edit-files').addEventListener('change', updateEditFileList);
|
||
|
||
// Настройки уведомлений
|
||
const notificationForm = document.getElementById('notification-settings-form');
|
||
if (notificationForm) {
|
||
notificationForm.addEventListener('submit', saveNotificationSettings);
|
||
}
|
||
|
||
// Инициализация загрузки файлов
|
||
initializeFileUploads();
|
||
}
|
||
|
||
// Функция для изменения вида задач
|
||
function changeTaskView() {
|
||
const select = document.getElementById('task-view-filter');
|
||
currentTaskView = select.value;
|
||
loadTasks();
|
||
}
|
||
|
||
// Переопределяем функцию loadTasks для фильтрации
|
||
(function() {
|
||
// Сохраняем оригинальную функцию loadTasks
|
||
const originalLoadTasks = window.loadTasks;
|
||
|
||
// Создаем новую функцию
|
||
window.loadTasks = async function() {
|
||
// Вызываем оригинальную функцию
|
||
if (typeof originalLoadTasks === 'function') {
|
||
await originalLoadTasks();
|
||
}
|
||
|
||
// Кэшируем все задачи
|
||
if (window.tasks && Array.isArray(window.tasks)) {
|
||
allTasksCache = [...window.tasks];
|
||
|
||
// Фильтруем задачи в зависимости от выбранного вида
|
||
if (currentTaskView !== 'all' && currentUser) {
|
||
let filteredTasks = [];
|
||
|
||
if (currentTaskView === 'my_assigned') {
|
||
// Показываем задачи, которые я назначил (я - создатель)
|
||
filteredTasks = window.tasks.filter(task => {
|
||
return parseInt(task.created_by) === currentUser.id;
|
||
});
|
||
|
||
} else if (currentTaskView === 'assigned_to_me') {
|
||
// Показываем задачи, назначенные мне (я - исполнитель)
|
||
filteredTasks = window.tasks.filter(task => {
|
||
// Проверяем, назначена ли задача текущему пользователю
|
||
if (task.assignments && Array.isArray(task.assignments)) {
|
||
return task.assignments.some(assignment =>
|
||
parseInt(assignment.user_id) === currentUser.id
|
||
);
|
||
}
|
||
return false;
|
||
});
|
||
}
|
||
|
||
// Обновляем глобальный массив задач
|
||
window.tasks = filteredTasks;
|
||
|
||
// Перерисовываем задачи
|
||
if (window.renderTasks && typeof window.renderTasks === 'function') {
|
||
window.renderTasks();
|
||
}
|
||
}
|
||
}
|
||
};
|
||
})();
|
||
|
||
// Обновленная функция для создания задачи
|
||
async function createTask(event) {
|
||
event.preventDefault();
|
||
|
||
if (!currentUser) {
|
||
alert('Требуется аутентификация');
|
||
return;
|
||
}
|
||
|
||
const title = document.getElementById('title').value;
|
||
const description = document.getElementById('description').value;
|
||
const taskType = document.getElementById('task-type').value;
|
||
|
||
// Получаем полную дату и время из отдельных полей
|
||
const fullDateTime = getFullDateTime('due-date', 'due-time');
|
||
|
||
if (!title || !fullDateTime) {
|
||
alert('Название задачи и дата выполнения обязательны');
|
||
return;
|
||
}
|
||
|
||
if (selectedUsers.length === 0) {
|
||
alert('Выберите хотя бы одного исполнителя');
|
||
return;
|
||
}
|
||
// Дополнительная проверка для задач типа "document"
|
||
if (taskType === 'document' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - секретари
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'Секретарь' ||
|
||
(typeof group === 'string' && group.includes('Секретарь'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задач типа "Согласование документа" можно выбирать только пользователей с правом "согласовать документы"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "it"
|
||
if (taskType === 'it' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - it
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'ИТ специалист' ||
|
||
(typeof group === 'string' && group.includes('ИТ специалист'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "ИТ специалист"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "ahch"
|
||
if (taskType === 'ahch' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - it
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'АХЧ' ||
|
||
(typeof group === 'string' && group.includes('АХЧ'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "сотрудники АХЧ"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "psychologist"
|
||
if (taskType === 'psychologist' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - it
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'психолог' ||
|
||
(typeof group === 'string' && group.includes('психолог'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "сотрудники психологи"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "speech_therapist"
|
||
if (taskType === 'speech_therapist' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - speech_therapist
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'логопед' ||
|
||
(typeof group === 'string' && group.includes('логопед'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "сотрудники логопеды"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "hr"
|
||
if (taskType === 'hr' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - hr
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'Диспетчер' ||
|
||
(typeof group === 'string' && group.includes('Диспетчер'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "Диспетчер расписания"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "certificate"
|
||
if (taskType === 'certificate' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - certificate
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'Администрация' ||
|
||
(typeof group === 'string' && group.includes('Администрация'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "секретари и завучи"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// Дополнительная проверка для задач типа "e_journal"
|
||
if (taskType === 'e_journal' && selectedUsers.length > 0) {
|
||
// Проверяем, что все выбранные пользователи - e_journal
|
||
for (const userId of selectedUsers) {
|
||
const groups = await getUserGroups(userId);
|
||
const hasSecretaryGroup = groups.some(group =>
|
||
group.name === 'Админ ЭЖ' ||
|
||
(typeof group === 'string' && group.includes('Админ ЭЖ'))
|
||
);
|
||
|
||
if (!hasSecretaryGroup) {
|
||
alert('Для задачи можно выбирать только пользователей из группы "администраторы электронного журнала"');
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
const formData = new FormData();
|
||
formData.append('title', title);
|
||
formData.append('description', description);
|
||
formData.append('taskType', taskType);
|
||
formData.append('dueDate', fullDateTime);
|
||
|
||
selectedUsers.forEach(userId => {
|
||
formData.append('assignedUsers', userId);
|
||
});
|
||
|
||
const files = document.getElementById('files').files;
|
||
for (let i = 0; i < files.length; i++) {
|
||
formData.append('files', files[i]);
|
||
}
|
||
|
||
// Проверка прав для типа "regular"
|
||
const userGroups = currentUser?.groups || [];
|
||
const isAdmin = currentUser?.role === 'admin';
|
||
const hasTasksGroup = currentUser?.role === 'tasks';
|
||
const hasSecretaryGroup = currentUser?.role === 'secretary';
|
||
|
||
if (taskType === 'regular' && !(isAdmin || hasTasksGroup || hasSecretaryGroup)) {
|
||
alert('У вас нет прав для создания обычных задач. Выберите другой тип задачи.');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch('/api/tasks', {
|
||
method: 'POST',
|
||
body: formData
|
||
});
|
||
|
||
if (response.ok) {
|
||
alert('Задача успешно создана!');
|
||
|
||
// Сброс формы
|
||
document.getElementById('create-task-form').reset();
|
||
document.getElementById('file-list').innerHTML = '';
|
||
document.getElementById('user-search').value = '';
|
||
selectedUsers = [];
|
||
|
||
// Сбрасываем дату и время
|
||
const tomorrow = new Date();
|
||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||
document.getElementById('due-date').value = tomorrow.toISOString().split('T')[0];
|
||
document.getElementById('due-time').value = '12:00';
|
||
|
||
// Сбрасываем активные кнопки
|
||
const timeButtons = document.querySelectorAll('.time-btn');
|
||
timeButtons.forEach(btn => btn.classList.remove('active'));
|
||
if (timeButtons.length > 0) {
|
||
timeButtons[0].classList.add('active');
|
||
}
|
||
|
||
// Обновляем отображение кнопок
|
||
updateDateTimeDisplay();
|
||
|
||
// Обновляем список пользователей
|
||
renderUsersChecklist();
|
||
|
||
// Загружаем задачи и логи
|
||
loadTasks();
|
||
loadActivityLogs();
|
||
|
||
// Показываем секцию задач
|
||
showSection('tasks');
|
||
} else {
|
||
const error = await response.json();
|
||
alert(error.error || 'Ошибка создания задачи');
|
||
}
|
||
} catch (error) {
|
||
console.error('Ошибка:', error);
|
||
alert('Ошибка создания задачи');
|
||
}
|
||
}
|
||
|
||
// Обновленная функция открытия модального окна редактирования
|
||
async function openEditModal(taskId) {
|
||
try {
|
||
const response = await fetch(`/api/tasks/${taskId}`);
|
||
if (!response.ok) {
|
||
if (response.status === 404) {
|
||
alert('Задача не найдена или у вас нет прав доступа');
|
||
}
|
||
throw new Error('Ошибка загрузки задачи');
|
||
}
|
||
|
||
const task = await response.json();
|
||
|
||
if (!canUserEditTask(task)) {
|
||
alert('У вас нет прав для редактирования этой задачи');
|
||
return;
|
||
}
|
||
|
||
document.getElementById('edit-task-id').value = task.id;
|
||
document.getElementById('edit-title').value = task.title;
|
||
document.getElementById('edit-description').value = task.description || '';
|
||
|
||
// Устанавливаем дату и время с помощью новой функции
|
||
setDateTimeForEdit(task.due_date);
|
||
|
||
// Устанавливаем выбранных пользователей
|
||
editSelectedUsers = task.assignments ? task.assignments.map(a => a.user_id) : [];
|
||
renderEditUsersChecklist(users);
|
||
|
||
// Показываем существующие файлы
|
||
currentEditTaskFiles = task.files || [];
|
||
updateEditFileList();
|
||
|
||
document.getElementById('edit-task-modal').style.display = 'block';
|
||
} catch (error) {
|
||
console.error('Ошибка:', error);
|
||
alert('Ошибка загрузки задачи');
|
||
}
|
||
}
|
||
|
||
// Обновленная функция обновления задачи
|
||
async function updateTask(event) {
|
||
event.preventDefault();
|
||
|
||
const taskId = document.getElementById('edit-task-id').value;
|
||
const title = document.getElementById('edit-title').value;
|
||
const description = document.getElementById('edit-description').value;
|
||
|
||
// Получаем полную дату и время из отдельных полей
|
||
const fullDateTime = getFullDateTime('edit-due-date', 'edit-due-time');
|
||
|
||
if (!fullDateTime) {
|
||
alert('Дата и время выполнения обязательны');
|
||
return;
|
||
}
|
||
|
||
// Используем editSelectedUsers
|
||
const assignedUserIds = editSelectedUsers;
|
||
|
||
const formData = new FormData();
|
||
formData.append('title', title);
|
||
formData.append('description', description);
|
||
formData.append('assignedUsers', JSON.stringify(assignedUserIds));
|
||
formData.append('dueDate', fullDateTime);
|
||
|
||
const files = document.getElementById('edit-files').files;
|
||
for (let i = 0; i < files.length; i++) {
|
||
formData.append('files', files[i]);
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/tasks/${taskId}`, {
|
||
method: 'PUT',
|
||
body: formData
|
||
});
|
||
|
||
if (response.ok) {
|
||
alert('Задача успешно обновлена!');
|
||
closeEditModal();
|
||
loadTasks();
|
||
loadActivityLogs();
|
||
} else {
|
||
const error = await response.json();
|
||
alert(error.error || 'Ошибка обновления задачи');
|
||
}
|
||
} catch (error) {
|
||
console.error('Ошибка:', error);
|
||
alert('Ошибка обновления задачи');
|
||
}
|
||
}
|
||
|
||
// Обновленная функция создания копии задачи
|
||
async function copyTask(event) {
|
||
event.preventDefault();
|
||
|
||
const taskId = document.getElementById('copy-task-id').value;
|
||
|
||
// Получаем полную дату и время из отдельных полей
|
||
const fullDateTime = getFullDateTime('copy-due-date', 'copy-due-time');
|
||
|
||
if (!fullDateTime) {
|
||
alert('Дата и время выполнения обязательны для копии задачи');
|
||
return;
|
||
}
|
||
|
||
// Используем copySelectedUsers
|
||
const assignedUserIds = copySelectedUsers;
|
||
|
||
if (assignedUserIds.length === 0) {
|
||
alert('Выберите хотя бы одного исполнителя для копии задачи');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`/api/tasks/${taskId}/copy`, {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
assignedUsers: assignedUserIds,
|
||
dueDate: fullDateTime
|
||
})
|
||
});
|
||
|
||
if (response.ok) {
|
||
alert('Копия задачи успешно создана!');
|
||
closeCopyModal();
|
||
loadTasks();
|
||
loadActivityLogs();
|
||
} else {
|
||
const error = await response.json();
|
||
alert(error.error || 'Ошибка создания копии задачи');
|
||
}
|
||
} catch (error) {
|
||
console.error('Ошибка:', error);
|
||
alert('Ошибка создания копии задачи');
|
||
}
|
||
}
|
||
|
||
// Функция для отображения секции
|
||
function showSection(sectionName) {
|
||
document.querySelectorAll('.section').forEach(section => {
|
||
section.classList.remove('active');
|
||
});
|
||
|
||
document.getElementById(sectionName + '-section').classList.add('active');
|
||
|
||
if (sectionName === 'tasks') {
|
||
loadTasks();
|
||
} else if (sectionName === 'logs') {
|
||
loadActivityLogs();
|
||
} else if (sectionName === 'kanban') {
|
||
loadKanbanTasks();
|
||
}
|
||
|
||
// Загрузка профиля при переходе в личный кабинет
|
||
if (sectionName === 'profile') {
|
||
loadUserProfile();
|
||
loadNotificationSettings();
|
||
}
|
||
}
|
||
|
||
// Функция для отображения Канбан доски
|
||
function showKanbanSection() {
|
||
showSection('kanban');
|
||
}
|
||
|