// main.js - Главный файл инициализации
window.currentTaskView = 'all'; // 'all', 'my_assigned', 'assigned_to_me'
// прикрепляет переменную к объекту window и использует существующее значение, если оно уже есть
// Кэш всех задач
// let allTasksCache = []; // Повторное выполнение
window.allTasksCache = window.allTasksCache || [];
document.addEventListener('DOMContentLoaded', function() {
checkAuth();
setupEventListeners();
// Инициализация выбора времени
initializeTimeSelectors();
// Инициализация фильтра
const taskViewFilter = document.getElementById('task-view-filter');
if (taskViewFilter) {
taskViewFilter.value = currentTaskView;
}
// По умолчанию показываем секцию задач
showSection('tasks');
});
function setupEventListeners() {
// Форма входа
const loginForm = document.getElementById('login-form');
if (loginForm && !loginForm._hasSubmitListener) {
loginForm.addEventListener('submit', login);
loginForm._hasSubmitListener = true;
}
// Форма создания задачи
const createForm = document.getElementById('create-task-form');
if (createForm && !createForm._hasSubmitListener) {
createForm.addEventListener('submit', createTask);
createForm._hasSubmitListener = true;
}
// Форма редактирования задачи
const editForm = document.getElementById('edit-task-form');
if (editForm && !editForm._hasSubmitListener) {
editForm.addEventListener('submit', updateTask);
editForm._hasSubmitListener = true;
}
// Форма копирования задачи
const copyForm = document.getElementById('copy-task-form');
if (copyForm && !copyForm._hasSubmitListener) {
copyForm.addEventListener('submit', copyTask);
copyForm._hasSubmitListener = true;
}
// Форма редактирования назначения
const editAssignmentForm = document.getElementById('edit-assignment-form');
if (editAssignmentForm && !editAssignmentForm._hasSubmitListener) {
editAssignmentForm.addEventListener('submit', updateAssignment);
editAssignmentForm._hasSubmitListener = true;
}
// Форма доработки
const reworkForm = document.getElementById('rework-task-form');
if (reworkForm && !reworkForm._hasSubmitListener) {
reworkForm.addEventListener('submit', sendForRework);
reworkForm._hasSubmitListener = true;
}
// Файлы
const filesInput = document.getElementById('files');
if (filesInput && !filesInput._hasChangeListener) {
filesInput.addEventListener('change', updateFileList);
filesInput._hasChangeListener = true;
}
const editFilesInput = document.getElementById('edit-files');
if (editFilesInput && !editFilesInput._hasChangeListener) {
editFilesInput.addEventListener('change', updateEditFileList);
editFilesInput._hasChangeListener = true;
}
// Настройки уведомлений
const notificationForm = document.getElementById('notification-settings-form');
if (notificationForm && !notificationForm._hasSubmitListener) {
notificationForm.addEventListener('submit', saveNotificationSettings);
notificationForm._hasSubmitListener = true;
}
// Ознакомление
const acquaintanceForm = document.getElementById('acquaintance-task-form');
if (acquaintanceForm && !acquaintanceForm._hasSubmitListener) {
acquaintanceForm.addEventListener('submit', createAcquaintanceTask);
acquaintanceForm._hasSubmitListener = true;
}
// Инициализация загрузки файлов
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;
let description = document.getElementById('description').value;
const taskType = document.getElementById('task-type').value;
// Для типа it добавляем кабинет и тип проблемы в описание
if (taskType === 'it') {
const cabinet = document.getElementById('it-cabinet').value.trim();
const corpusType = document.getElementById('it-corpus-type').value;
const problemType = document.getElementById('it-problem-type').value;
if (!cabinet || !problemType) {
alert('Для заявки в ИТ необходимо указать номер кабинета и тип проблемы');
return;
}
// Добавляем в конец описания с переносом строки
description = description + '
Кабинет: ' + cabinet + '
Корпус: ' + corpusType + '
Тип проблемы: ' + problemType;
}
// Получаем полную дату и время из отдельных полей
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;
}
}
}
// Дополнительная проверка для задач типа "Social_educator"
if (taskType === 'Social_educator' && selectedUsers.length > 0) {
// Проверяем, что все выбранные пользователи - Social_educator
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();
}
if (sectionName === 'reports') {
if (typeof loadReportData === 'function') {
loadReportData();
}
}
}
// Функция для отображения Канбан доски
function showKanbanSection() {
showSection('kanban');
}
window.setupEventListeners = setupEventListeners;