Files
minicrm/public/nav-task-actions.js
2026-03-04 17:27:27 +05:00

174 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// nav-task-actions.js выпадающее меню действий задачи
(function() {
'use strict';
// Сбор доступных действий для конкретной задачи
function buildActionsForTask(task) {
console.log('buildActionsForTask called with task', task);
const taskId = task.id;
const isDeleted = task.status === 'deleted';
const isClosed = task.closed_at !== null;
const userRole = window.getUserRoleInTask ? window.getUserRoleInTask(task) : 'Наблюдатель';
const canEdit = window.canUserEditTask ? window.canUserEditTask(task) : false;
const actions = [];
// Действия для активных (не удалённых, не закрытых) задач
if (!isDeleted && !isClosed) {
if (typeof openTaskChat === 'function') actions.push({ label: '💬 Чат', handler: () => openTaskChat(taskId) });
if (typeof openAddFileModal === 'function') actions.push({ label: '📎 Добавить файл', handler: () => openAddFileModal(taskId) });
}
// Специальные пользователи
if (window.currentUser && window.currentUser.login === 'minicrm') {
if (typeof openEditModal === 'function') actions.push({ label: '✏️ Редактировать', handler: () => openEditModal(taskId) });
}
if (window.currentUser && window.currentUser.login === 'kalugin.o') {
if (typeof openManageAssigneesModal === 'function') actions.push({ label: '👥 Управление исполнителями', handler: () => openManageAssigneesModal(taskId) });
}
// Администраторы и роль tasks
if (window.currentUser && (window.currentUser.role === 'admin' || (window.currentUser.role === 'tasks' && canEdit))) {
if (typeof assignAdd_openModal === 'function') actions.push({ label: '🧑‍💼➕ Добавить исполнителя', handler: () => assignAdd_openModal(taskId) });
if (typeof assignRemove_openModal === 'function') actions.push({ label: '🧑‍💼❌ Удалить исполнителя', handler: () => assignRemove_openModal(taskId) });
}
// Копия доступна всем, у кого есть кнопка
if (typeof openCopyModal === 'function') actions.push({ label: '📋 Создать копию', handler: () => openCopyModal(taskId) });
// Доработка для документа (исполнитель)
if (task.task_type === 'document' && userRole === 'Исполнитель') {
if (typeof openReworkModal === 'function') actions.push({ label: '🔄 Переделать документ', handler: () => openReworkModal(taskId) });
}
// Доработка и изменение срока для необычных задач (исполнитель)
if (!isDeleted && !isClosed && task.task_type !== 'regular' &&
task.assignments && task.assignments.some(a => parseInt(a.user_id) === window.currentUser?.id)) {
if (typeof openReworkModal === 'function') actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId) });
if (typeof openChangeDeadlineModal === 'function') actions.push({ label: '📅 Изменить срок', handler: () => openChangeDeadlineModal(taskId) });
}
// Закрытие (только minicrm)
if (window.currentUser && window.currentUser.login === 'minicrm') {
if (typeof closeTask === 'function') actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId) });
}
// Удаление (если есть права)
if (canEdit && !isDeleted && !isClosed) {
if (typeof deleteTask === 'function') actions.push({ label: '🗑️ Удалить', handler: () => deleteTask(taskId) });
}
// Открытие закрытой задачи
if (isClosed && canEdit) {
if (typeof reopenTask === 'function') actions.push({ label: '🔓 Открыть задачу', handler: () => reopenTask(taskId) });
}
// Восстановление удалённой (только админ)
if (isDeleted && window.currentUser?.role === 'admin') {
if (typeof restoreTask === 'function') actions.push({ label: '↶ Восстановить', handler: () => restoreTask(taskId) });
}
console.log('Actions built:', actions);
return actions;
}
// Рендеринг кнопки меню (без встроенного dropdown)
window.renderTaskActions = function(task) {
if (!task) return '';
return `
<div class="task-actions-menu-container">
<button class="task-actions-menu-btn" data-task-id="${task.id}">⋮ Действия</button>
</div>
`;
};
// Удалить текущее меню, если есть
function removeCurrentMenu() {
const existing = document.getElementById('task-action-menu');
if (existing) existing.remove();
}
// Обработчик клика на кнопку меню
document.addEventListener('click', function(e) {
const menuBtn = e.target.closest('.task-actions-menu-btn');
if (!menuBtn) return;
console.log('Menu button clicked', menuBtn);
e.preventDefault();
e.stopPropagation();
// Удаляем предыдущее меню
removeCurrentMenu();
const taskId = menuBtn.dataset.taskId;
if (!taskId) {
console.error('No task id found on button');
return;
}
const task = window.tasks?.find(t => t.id == taskId);
if (!task) {
console.error('Task not found for id', taskId);
return;
}
// Построить список действий
const actions = buildActionsForTask(task);
if (actions.length === 0) {
return;
}
// Создаём элемент меню
const menu = document.createElement('div');
menu.id = 'task-action-menu';
menu.className = 'task-actions-dropdown';
menu.style.position = 'absolute';
menu.style.zIndex = '10000';
menu.style.backgroundColor = 'white';
menu.style.border = '1px solid #ccc';
menu.style.borderRadius = '8px';
menu.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
menu.style.minWidth = '200px';
menu.style.padding = '8px 0';
// Заполняем пунктами
actions.forEach(a => {
const item = document.createElement('div');
item.className = 'menu-item';
item.textContent = a.label;
item.style.padding = '10px 16px';
item.style.cursor = 'pointer';
item.style.fontSize = '14px';
item.style.color = '#333';
item.style.transition = 'background 0.2s';
item.addEventListener('mouseenter', () => { item.style.backgroundColor = '#f8f9fa'; });
item.addEventListener('mouseleave', () => { item.style.backgroundColor = 'transparent'; });
item.addEventListener('click', (event) => {
event.stopPropagation();
a.handler();
removeCurrentMenu();
});
menu.appendChild(item);
});
// Позиционируем
const rect = menuBtn.getBoundingClientRect();
menu.style.top = (rect.bottom + window.scrollY) + 'px';
menu.style.left = (rect.left + window.scrollX) + 'px';
// Добавляем в body
document.body.appendChild(menu);
// Закрытие при клике вне меню
setTimeout(() => {
document.addEventListener('click', function closeMenu(e) {
if (!menu.contains(e.target) && !menuBtn.contains(e.target)) {
removeCurrentMenu();
document.removeEventListener('click', closeMenu);
}
});
}, 0);
});
console.log('nav-task-actions.js loaded');
})();