Действия
This commit is contained in:
@@ -1,10 +1,14 @@
|
|||||||
// nav-task-actions.js – выпадающее меню действий задачи
|
// nav-task-actions.js – модальное окно с действиями задачи (сетка 3 колонки, центрированное)
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
// Управление логированием: установите window.navTaskActionsLog = 1 для включения логов
|
||||||
|
const LOG_ENABLED = 0;
|
||||||
|
function log(...args) {
|
||||||
|
if (LOG_ENABLED) console.log(...args);
|
||||||
|
}
|
||||||
// Сбор доступных действий для конкретной задачи
|
// Сбор доступных действий для конкретной задачи
|
||||||
function buildActionsForTask(task) {
|
function buildActionsForTask(task) {
|
||||||
console.log('buildActionsForTask called with task', task);
|
//log('buildActionsForTask called with task', task);
|
||||||
const taskId = task.id;
|
const taskId = task.id;
|
||||||
const isDeleted = task.status === 'deleted';
|
const isDeleted = task.status === 'deleted';
|
||||||
const isClosed = task.closed_at !== null;
|
const isClosed = task.closed_at !== null;
|
||||||
@@ -15,43 +19,86 @@
|
|||||||
|
|
||||||
// Действия для активных (не удалённых, не закрытых) задач
|
// Действия для активных (не удалённых, не закрытых) задач
|
||||||
if (!isDeleted && !isClosed) {
|
if (!isDeleted && !isClosed) {
|
||||||
if (typeof openTaskChat === 'function') actions.push({ label: '💬 Чат', handler: () => openTaskChat(taskId) });
|
if (typeof openTaskChat === 'function') {
|
||||||
if (typeof openAddFileModal === 'function') actions.push({ label: '📎 Добавить файл', handler: () => openAddFileModal(taskId) });
|
actions.push({ label: '💬 Чат', handler: () => openTaskChat(taskId) });
|
||||||
|
log('nav-task-actions openTaskChat yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions openTaskChat not');
|
||||||
|
}
|
||||||
|
if (typeof openAddFileModal === 'function') {
|
||||||
|
actions.push({ label: '📎 Добавить файл', handler: () => openAddFileModal(taskId) });
|
||||||
|
log('nav-task-actions openAddFileModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions openAddFileModal not');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Специальные пользователи
|
// Специальные пользователи
|
||||||
if (window.currentUser && window.currentUser.login === 'minicrm') {
|
if (window.currentUser && window.currentUser.login === 'minicrm') {
|
||||||
if (typeof openEditModal === 'function') actions.push({ label: '✏️ Редактировать', handler: () => openEditModal(taskId) });
|
if (typeof openEditModal === 'function') {
|
||||||
}
|
actions.push({ label: '✏️ Редактировать', handler: () => openEditModal(taskId) });
|
||||||
if (window.currentUser && window.currentUser.login === 'kalugin.o') {
|
log('nav-task-actions openEditModal yes');
|
||||||
if (typeof openManageAssigneesModal === 'function') actions.push({ label: '👥 Управление исполнителями', handler: () => openManageAssigneesModal(taskId) });
|
} else {
|
||||||
}
|
log('nav-task-actions openEditModal not');
|
||||||
|
}
|
||||||
|
////}
|
||||||
|
//if (window.currentUser && window.currentUser.login === 'kalugin.o') {
|
||||||
|
if (typeof openManageAssigneesModal === 'function') {
|
||||||
|
actions.push({ label: '👥 Управление исполнителями', handler: () => openManageAssigneesModal(taskId) });
|
||||||
|
log('nav-task-actions openManageAssigneesModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions openManageAssigneesModal not');
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// Администраторы и роль tasks
|
// Администраторы и роль tasks
|
||||||
if (window.currentUser && (window.currentUser.role === 'admin' || (window.currentUser.role === 'tasks' && canEdit))) {
|
//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 assignAdd_openModal === 'function') {
|
||||||
if (typeof assignRemove_openModal === 'function') actions.push({ label: '🧑💼❌ Удалить исполнителя', handler: () => assignRemove_openModal(taskId) });
|
actions.push({ label: '🧑💼➕ Добавить исполнителя', handler: () => assignAdd_openModal(taskId) });
|
||||||
}
|
log('nav-task-actions assignAdd_openModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions assignAdd_openModal not');
|
||||||
|
}
|
||||||
|
if (typeof assignRemove_openModal === 'function') {
|
||||||
|
actions.push({ label: '🧑💼❌ Удалить исполнителя', handler: () => assignRemove_openModal(taskId) });
|
||||||
|
log('nav-task-actions assignRemove_openModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions assignRemove_openModal not');
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// Копия – доступна всем, у кого есть кнопка
|
// Копия – доступна всем, у кого есть кнопка
|
||||||
if (typeof openCopyModal === 'function') actions.push({ label: '📋 Создать копию', handler: () => openCopyModal(taskId) });
|
if (typeof openCopyModal === 'function') {
|
||||||
|
actions.push({ label: '📋 Создать копию', handler: () => openCopyModal(taskId) });
|
||||||
|
log('nav-task-actions assignRemove_openModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions assignRemove_openModal not');
|
||||||
|
}
|
||||||
|
|
||||||
// Доработка для документа (исполнитель)
|
// Доработка для документа (исполнитель)
|
||||||
if (task.task_type === 'document' && userRole === 'Исполнитель') {
|
//if (task.task_type === 'document' && userRole === 'Исполнитель') {
|
||||||
if (typeof openReworkModal === 'function') actions.push({ label: '🔄 Переделать документ', handler: () => openReworkModal(taskId) });
|
if (typeof openReworkModal === 'function') {
|
||||||
}
|
actions.push({ label: '🔄 Переделать документ', handler: () => openReworkModal(taskId) });
|
||||||
|
log('nav-task-actions assignRemove_openModal yes');
|
||||||
|
} else {
|
||||||
|
log('nav-task-actions assignRemove_openModal not');
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
|
||||||
// Доработка и изменение срока для необычных задач (исполнитель)
|
// Доработка и изменение срока для необычных задач (исполнитель)
|
||||||
if (!isDeleted && !isClosed && task.task_type !== 'regular' &&
|
//if (!isDeleted && !isClosed && task.task_type !== 'regular' &&task.assignments && task.assignments.some(a => parseInt(a.user_id) === window.currentUser?.id)) {
|
||||||
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 openReworkModal === 'function') actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId) });
|
log('nav-task-actions openReworkModal yes');
|
||||||
if (typeof openChangeDeadlineModal === 'function') actions.push({ label: '📅 Изменить срок', handler: () => openChangeDeadlineModal(taskId) });
|
} else {log('nav-task-actions openReworkModal not');}
|
||||||
}
|
if (typeof openChangeDeadlineModal === 'function') { actions.push({ label: '📅 Изменить срок', handler: () => openChangeDeadlineModal(taskId) });
|
||||||
|
log('nav-task-actions openChangeDeadlineModal yes');
|
||||||
|
} else {log('nav-task-actions openChangeDeadlineModal not');}
|
||||||
|
//}
|
||||||
|
|
||||||
// Закрытие (только minicrm)
|
// Закрытие (только minicrm)
|
||||||
if (window.currentUser && window.currentUser.login === 'minicrm') {
|
//if (window.currentUser && window.currentUser.login === 'minicrm') {
|
||||||
if (typeof closeTask === 'function') actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId) });
|
if (typeof closeTask === 'function') actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId) });
|
||||||
}
|
//}
|
||||||
|
|
||||||
// Удаление (если есть права)
|
// Удаление (если есть права)
|
||||||
if (canEdit && !isDeleted && !isClosed) {
|
if (canEdit && !isDeleted && !isClosed) {
|
||||||
@@ -67,12 +114,12 @@
|
|||||||
if (isDeleted && window.currentUser?.role === 'admin') {
|
if (isDeleted && window.currentUser?.role === 'admin') {
|
||||||
if (typeof restoreTask === 'function') actions.push({ label: '↶ Восстановить', handler: () => restoreTask(taskId) });
|
if (typeof restoreTask === 'function') actions.push({ label: '↶ Восстановить', handler: () => restoreTask(taskId) });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
console.log('Actions built:', actions);
|
//log('Actions built:', actions);
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Рендеринг кнопки меню (без встроенного dropdown)
|
// Рендеринг кнопки меню
|
||||||
window.renderTaskActions = function(task) {
|
window.renderTaskActions = function(task) {
|
||||||
if (!task) return '';
|
if (!task) return '';
|
||||||
return `
|
return `
|
||||||
@@ -82,9 +129,9 @@
|
|||||||
`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Удалить текущее меню, если есть
|
// Удалить модальное окно, если оно есть
|
||||||
function removeCurrentMenu() {
|
function removeModal() {
|
||||||
const existing = document.getElementById('task-action-menu');
|
const existing = document.getElementById('task-action-modal');
|
||||||
if (existing) existing.remove();
|
if (existing) existing.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,12 +140,11 @@
|
|||||||
const menuBtn = e.target.closest('.task-actions-menu-btn');
|
const menuBtn = e.target.closest('.task-actions-menu-btn');
|
||||||
if (!menuBtn) return;
|
if (!menuBtn) return;
|
||||||
|
|
||||||
console.log('Menu button clicked', menuBtn);
|
//log('Menu button clicked', menuBtn);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
// Удаляем предыдущее меню
|
removeModal();
|
||||||
removeCurrentMenu();
|
|
||||||
|
|
||||||
const taskId = menuBtn.dataset.taskId;
|
const taskId = menuBtn.dataset.taskId;
|
||||||
if (!taskId) {
|
if (!taskId) {
|
||||||
@@ -112,63 +158,116 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Построить список действий
|
|
||||||
const actions = buildActionsForTask(task);
|
const actions = buildActionsForTask(task);
|
||||||
if (actions.length === 0) {
|
if (actions.length === 0) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаём элемент меню
|
// Создаём затемнение
|
||||||
const menu = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
menu.id = 'task-action-menu';
|
overlay.id = 'task-action-modal';
|
||||||
menu.className = 'task-actions-dropdown';
|
overlay.style.position = 'fixed';
|
||||||
menu.style.position = 'absolute';
|
overlay.style.top = '0';
|
||||||
menu.style.zIndex = '10000';
|
overlay.style.left = '0';
|
||||||
menu.style.backgroundColor = 'white';
|
overlay.style.width = '100%';
|
||||||
menu.style.border = '1px solid #ccc';
|
overlay.style.height = '100%';
|
||||||
menu.style.borderRadius = '8px';
|
overlay.style.backgroundColor = 'rgba(0,0,0,0.5)';
|
||||||
menu.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
overlay.style.zIndex = '10000';
|
||||||
menu.style.minWidth = '200px';
|
overlay.style.display = 'flex';
|
||||||
menu.style.padding = '8px 0';
|
overlay.style.alignItems = 'center';
|
||||||
|
overlay.style.justifyContent = 'center';
|
||||||
|
|
||||||
|
// Создаём контейнер модального окна
|
||||||
|
const modal = document.createElement('div');
|
||||||
|
modal.style.backgroundColor = 'white';
|
||||||
|
modal.style.borderRadius = '12px';
|
||||||
|
modal.style.padding = '25px';
|
||||||
|
modal.style.maxWidth = '500px';
|
||||||
|
modal.style.width = '90%';
|
||||||
|
modal.style.boxShadow = '0 10px 40px rgba(0,0,0,0.2)';
|
||||||
|
modal.style.position = 'relative';
|
||||||
|
modal.style.maxHeight = '85vh';
|
||||||
|
modal.style.overflowY = 'auto';
|
||||||
|
|
||||||
|
// Заголовок
|
||||||
|
const header = document.createElement('div');
|
||||||
|
header.style.display = 'flex';
|
||||||
|
header.style.justifyContent = 'space-between';
|
||||||
|
header.style.alignItems = 'center';
|
||||||
|
header.style.marginBottom = '20px';
|
||||||
|
header.style.paddingBottom = '10px';
|
||||||
|
header.style.borderBottom = '1px solid #eee';
|
||||||
|
|
||||||
|
const title = document.createElement('h3');
|
||||||
|
title.style.margin = '0';
|
||||||
|
title.style.fontSize = '18px';
|
||||||
|
title.style.color = '#333';
|
||||||
|
title.textContent = `Действия для задачи #${taskId}`;
|
||||||
|
|
||||||
|
const closeBtn = document.createElement('span');
|
||||||
|
closeBtn.innerHTML = '×';
|
||||||
|
closeBtn.style.fontSize = '28px';
|
||||||
|
closeBtn.style.fontWeight = 'bold';
|
||||||
|
closeBtn.style.cursor = 'pointer';
|
||||||
|
closeBtn.style.color = '#999';
|
||||||
|
closeBtn.style.transition = 'color 0.2s';
|
||||||
|
closeBtn.onmouseover = () => closeBtn.style.color = '#e74c3c';
|
||||||
|
closeBtn.onmouseout = () => closeBtn.style.color = '#999';
|
||||||
|
closeBtn.onclick = () => removeModal();
|
||||||
|
|
||||||
|
header.appendChild(title);
|
||||||
|
header.appendChild(closeBtn);
|
||||||
|
modal.appendChild(header);
|
||||||
|
|
||||||
|
// Сетка кнопок (flex-wrap с 3 колонками)
|
||||||
|
const grid = document.createElement('div');
|
||||||
|
grid.style.display = 'flex';
|
||||||
|
grid.style.flexWrap = 'wrap';
|
||||||
|
grid.style.gap = '10px';
|
||||||
|
grid.style.justifyContent = 'center';
|
||||||
|
|
||||||
// Заполняем пунктами
|
|
||||||
actions.forEach(a => {
|
actions.forEach(a => {
|
||||||
const item = document.createElement('div');
|
const btn = document.createElement('button');
|
||||||
item.className = 'menu-item';
|
btn.textContent = a.label;
|
||||||
item.textContent = a.label;
|
btn.style.flex = '0 0 calc(33.333% - 10px)';
|
||||||
item.style.padding = '10px 16px';
|
btn.style.minWidth = '120px';
|
||||||
item.style.cursor = 'pointer';
|
btn.style.padding = '12px 8px';
|
||||||
item.style.fontSize = '14px';
|
btn.style.border = 'none';
|
||||||
item.style.color = '#333';
|
btn.style.borderRadius = '8px';
|
||||||
item.style.transition = 'background 0.2s';
|
btn.style.backgroundColor = '#3498db';
|
||||||
item.addEventListener('mouseenter', () => { item.style.backgroundColor = '#f8f9fa'; });
|
btn.style.color = 'white';
|
||||||
item.addEventListener('mouseleave', () => { item.style.backgroundColor = 'transparent'; });
|
btn.style.fontSize = '14px';
|
||||||
item.addEventListener('click', (event) => {
|
btn.style.fontWeight = '500';
|
||||||
|
btn.style.cursor = 'pointer';
|
||||||
|
btn.style.transition = 'all 0.2s';
|
||||||
|
btn.style.boxShadow = '0 2px 5px rgba(52,152,219,0.3)';
|
||||||
|
|
||||||
|
btn.onmouseover = () => {
|
||||||
|
btn.style.transform = 'translateY(-2px)';
|
||||||
|
btn.style.boxShadow = '0 4px 10px rgba(52,152,219,0.4)';
|
||||||
|
};
|
||||||
|
btn.onmouseout = () => {
|
||||||
|
btn.style.transform = 'translateY(0)';
|
||||||
|
btn.style.boxShadow = '0 2px 5px rgba(52,152,219,0.3)';
|
||||||
|
};
|
||||||
|
btn.onclick = (event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
a.handler();
|
a.handler();
|
||||||
removeCurrentMenu();
|
removeModal();
|
||||||
});
|
};
|
||||||
menu.appendChild(item);
|
|
||||||
|
grid.appendChild(btn);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Позиционируем
|
modal.appendChild(grid);
|
||||||
const rect = menuBtn.getBoundingClientRect();
|
overlay.appendChild(modal);
|
||||||
menu.style.top = (rect.bottom + window.scrollY) + 'px';
|
document.body.appendChild(overlay);
|
||||||
menu.style.left = (rect.left + window.scrollX) + 'px';
|
|
||||||
|
|
||||||
// Добавляем в body
|
// Закрытие по клику на затемнение
|
||||||
document.body.appendChild(menu);
|
overlay.addEventListener('click', function(event) {
|
||||||
|
if (event.target === overlay) {
|
||||||
// Закрытие при клике вне меню
|
removeModal();
|
||||||
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');
|
//console.log('nav-task-actions.js loaded (centered modal)');
|
||||||
})();
|
})();
|
||||||
Reference in New Issue
Block a user