Реквизиты

This commit is contained in:
2026-03-26 17:53:56 +05:00
parent f5f4f12ff1
commit 635683020c

View File

@@ -1,18 +1,188 @@
// nav-task-actions.js модальное окно с действиями задачи (сетка 3 колонки, центрированное) // nav-task-actions.js модальное окно с действиями задачи (сетка 3 колонки, центрированное)
(function() { (function() {
'use strict'; 'use strict';
// Управление логированием: установите window.navTaskActionsLog = 1 для включения логов
const LOG_ENABLED = 0; const LOG_ENABLED = 0;
function log(...args) { function log(...args) {
if (LOG_ENABLED) console.log(...args); if (LOG_ENABLED) console.log(...args);
} }
log('currentUser:', currentUser); // ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ ДЛЯ РЕКВИЗИТОВ ==========
//log('currentUser.role:', currentUser.role); function escapeHtml(str) {
if (!str) return '';
return String(str).replace(/[&<>]/g, function(m) {
if (m === '&') return '&amp;';
if (m === '<') return '&lt;';
if (m === '>') return '&gt;';
return m;
});
}
function updateTaskCardDisplay(taskId, data) {
const taskCards = document.querySelectorAll(`[data-task-id="${taskId}"]`);
taskCards.forEach(card => {
let docContainer = card.querySelector('.document-fields-display');
if (!docContainer) {
docContainer = document.createElement('div');
docContainer.className = 'document-fields-display';
const header = card.querySelector('.task-header');
if (header) header.after(docContainer);
else card.prepend(docContainer);
}
let html = '<div style="margin: 8px 0; padding: 5px; background-color: #f5f5f5; border-radius: 4px; font-size: 0.9em;">';
if (data.document_n) html += `<span style="margin-right: 15px;"><strong>№:</strong> ${escapeHtml(data.document_n)}</span>`;
if (data.document_d) html += `<span style="margin-right: 15px;"><strong>Дата:</strong> ${escapeHtml(data.document_d)}</span>`;
if (data.document_a) html += `<span><strong>Автор:</strong> ${escapeHtml(data.document_a)}</span>`;
if (!data.document_n && !data.document_d) html += '<span style="color: #999;">Нет данных документа</span>';
html += '</div>';
docContainer.innerHTML = html;
});
}
async function openDocumentFieldsModal(taskId) {
const existing = document.getElementById('doc-fields-modal');
if (existing) existing.remove();
// Загружаем текущие поля
let fields = { document_n: '', document_d: '', document_a: '' };
try {
const response = await fetch(`/api/tasks/${taskId}/document-fields`);
if (response.ok) {
const result = await response.json();
fields = result.data || {};
}
} catch (error) {
console.error('Ошибка загрузки реквизитов:', error);
}
// Преобразуем дату из ДД.ММ.ГГГГ в YYYY-MM-DD для input type="date"
let dateValue = '';
if (fields.document_d) {
const parts = fields.document_d.split('.');
if (parts.length === 3) {
dateValue = `${parts[2]}-${parts[1]}-${parts[0]}`;
}
}
// Проверяем права на редактирование
let canEdit = false;
const hasFields = !!(fields.document_n || fields.document_d);
if (hasFields) {
canEdit = fields.document_a === currentUser?.login;
} else {
try {
const groupsRes = await fetch(`/api2/idusers/user/${currentUser.id}/groups`);
if (groupsRes.ok) {
const groups = await groupsRes.json();
canEdit = groups.some(g => g === 'Подписант' || g === 'Секретарь' || g.includes('Подписант') || g.includes('Секретарь'));
}
} catch (error) {
console.error('Ошибка проверки групп:', error);
}
}
// Создаём модальное окно
const modal = document.createElement('div');
modal.id = 'doc-fields-modal';
modal.className = 'modal';
modal.style.display = 'flex';
modal.style.alignItems = 'center';
modal.style.justifyContent = 'center';
modal.style.zIndex = '10001';
modal.innerHTML = `
<div class="modal-content" style="max-width: 500px;">
<div class="modal-header">
<h3>📄 Реквизиты документа</h3>
<span class="close" onclick="window.closeDocFieldsModal()">&times;</span>
</div>
<div class="modal-body">
<div class="form-group">
<label for="doc-number">Номер документа</label>
<input type="text" id="doc-number" class="form-control" value="${escapeHtml(fields.document_n || '')}" ${!canEdit ? 'readonly' : ''}>
</div>
<div class="form-group">
<label for="doc-date">Дата документа</label>
<input type="date" id="doc-date" class="form-control" value="${dateValue}" ${!canEdit ? 'readonly' : ''}>
</div>
<div class="form-group">
<label for="doc-author">Автор (логин)</label>
<input type="text" id="doc-author" class="form-control" value="${escapeHtml(fields.document_a || currentUser?.login || '')}" readonly>
</div>
${!canEdit && hasFields ? '<div class="alert alert-warning">⚠️ Вы не можете редактировать реквизиты, так как они уже заполнены другим пользователем.</div>' : ''}
${!canEdit && !hasFields ? '<div class="alert alert-warning">⚠️ У вас нет прав для указания реквизитов.</div>' : ''}
</div>
<div class="modal-footer">
<button class="btn-secondary" onclick="window.closeDocFieldsModal()">Отмена</button>
${canEdit ? `<button class="btn-primary" id="save-doc-fields">Сохранить</button>` : ''}
</div>
</div>
`;
document.body.appendChild(modal);
window.closeDocFieldsModal = function() {
const m = document.getElementById('doc-fields-modal');
if (m) m.remove();
delete window.closeDocFieldsModal;
};
modal.addEventListener('click', (e) => {
if (e.target === modal) window.closeDocFieldsModal();
});
if (canEdit) {
const saveBtn = document.getElementById('save-doc-fields');
saveBtn.addEventListener('click', async () => {
const number = document.getElementById('doc-number').value.trim();
const dateInput = document.getElementById('doc-date');
let formattedDate = '';
if (dateInput.value) {
// Преобразуем YYYY-MM-DD в ДД.ММ.ГГГГ
const parts = dateInput.value.split('-');
if (parts.length === 3) {
formattedDate = `${parts[2]}.${parts[1]}.${parts[0]}`;
}
}
const author = document.getElementById('doc-author').value.trim() || currentUser?.login;
saveBtn.disabled = true;
saveBtn.textContent = 'Сохранение...';
try {
const response = await fetch(`/api/tasks/${taskId}/document-fields`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
document_n: number || null,
document_d: formattedDate || null,
document_a: author
})
});
const result = await response.json();
if (response.ok && result.success) {
alert('✅ Реквизиты сохранены');
window.closeDocFieldsModal();
const task = window.tasks?.find(t => t.id == taskId);
if (task) task.document_fields = result.data;
updateTaskCardDisplay(taskId, result.data);
if (typeof loadTasks === 'function') loadTasks();
} else {
alert('❌ Ошибка: ' + (result.error || 'Неизвестная ошибка'));
}
} catch (error) {
console.error('Ошибка сохранения:', error);
alert('Сетевая ошибка');
} finally {
saveBtn.disabled = false;
saveBtn.textContent = 'Сохранить';
}
});
}
}
// ========== ОСНОВНАЯ ЛОГИКА МЕНЮ ДЕЙСТВИЙ ==========
// Сбор доступных действий для конкретной задачи // Сбор доступных действий для конкретной задачи
function buildActionsForTask(task) { function buildActionsForTask(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;
@@ -20,168 +190,146 @@
const canEdit = window.canUserEditTask ? window.canUserEditTask(task) : false; const canEdit = window.canUserEditTask ? window.canUserEditTask(task) : false;
const actions = []; const actions = [];
// ==== ДОБАВЛЕННЫЙ БЛОК: кнопки для текущего исполнителя
if (currentUser && !isDeleted && !isClosed) { // ==== ДОБАВЛЕННЫЙ БЛОК: кнопки для текущего исполнителя
const myAssignment = task.assignments?.find(a => parseInt(a.user_id) === currentUser.id); if (currentUser && !isDeleted && !isClosed) {
if (myAssignment) { const myAssignment = task.assignments?.find(a => parseInt(a.user_id) === currentUser.id);
// Кнопка "Приступить" (если статус 'assigned') if (myAssignment) {
if (myAssignment.status === 'assigned') { if (myAssignment.status === 'assigned') {
actions.push({ actions.push({
label: '▶️ Приступить', label: '▶️ Приступить',
handler: () => window.updateStatus(taskId, currentUser.id, 'in_progress'), handler: () => window.updateStatus(taskId, currentUser.id, 'in_progress'),
primary: true primary: true
}); });
}
if (['in_progress', 'overdue', 'rework'].includes(myAssignment.status)) {
const isDocumentTask = task.task_type === 'document';
const handler = isDocumentTask
? () => window.openDocumentCompleteModal(taskId, currentUser.id)
: () => window.updateStatus(taskId, currentUser.id, 'completed');
actions.push({
label: '✅ Выполнено',
handler: handler,
primary: true
});
}
}
} }
// Кнопка "Выполнено" (если статус 'in_progress', 'overdue' или 'rework')
if (['in_progress', 'overdue', 'rework'].includes(myAssignment.status)) {
const isDocumentTask = task.task_type === 'document';
const handler = isDocumentTask
? () => window.openDocumentCompleteModal(taskId, currentUser.id)
: () => window.updateStatus(taskId, currentUser.id, 'completed');
actions.push({
label: '✅ Выполнено',
handler: handler,
primary: true
});
}
}
}
// Копия доступна всем, у кого есть кнопка // Копия доступна всем, у кого есть кнопка
if (typeof openCopyModal === 'function') { if (typeof openCopyModal === 'function') {
actions.push({ label: '📋 Создать копию', actions.push({
label: '📋 Создать копию',
handler: () => openCopyModal(taskId), handler: () => openCopyModal(taskId),
primary: true primary: true
}); });
log('nav-task-actions assignRemove_openModal yes'); }
} else {
log('nav-task-actions assignRemove_openModal not');
}
// Действия для активных (не удалённых, не закрытых) задач // Действия для активных (не удалённых, не закрытых) задач
if (!isDeleted && !isClosed && currentUser.login === 'minicrm') { if (!isDeleted && !isClosed && currentUser.login === 'minicrm') {
if (typeof openTaskChat === 'function') { if (typeof openTaskChat === 'function') {
actions.push({ label: '💬 Чат', handler: () => openTaskChat(taskId) }); actions.push({ label: '💬 Чат', handler: () => openTaskChat(taskId) });
log('nav-task-actions openTaskChat yes');
} else {
log('nav-task-actions openTaskChat not');
} }
if (typeof openAddFileModal === 'function') { if (typeof openAddFileModal === 'function') {
actions.push({ label: '📎 Добавить файл', handler: () => openAddFileModal(taskId) }); actions.push({ label: '📎 Добавить файл', handler: () => openAddFileModal(taskId) });
log('nav-task-actions openAddFileModal yes');
} else {
log('nav-task-actions openAddFileModal not');
} }
} }
// Специальные пользователи // Специальные пользователи
if (currentUser && currentUser.login === 'minicrm') { if (currentUser && currentUser.login === 'minicrm') {
if (typeof openEditModal === 'function') { if (typeof openEditModal === 'function') {
actions.push({ label: '✏️ Редактировать', handler: () => openEditModal(taskId) }); actions.push({ label: '✏️ Редактировать', handler: () => openEditModal(taskId) });
log('nav-task-actions openEditModal yes');
} else {
log('nav-task-actions openEditModal not');
} }
////}
//if (currentUser && currentUser.login === 'kalugin.o') {
if (typeof openManageAssigneesModal === 'function') { if (typeof openManageAssigneesModal === 'function') {
actions.push({ label: '👥 Управление исполнителями', handler: () => openManageAssigneesModal(taskId) }); actions.push({ label: '👥 Управление исполнителями', handler: () => openManageAssigneesModal(taskId) });
log('nav-task-actions openManageAssigneesModal yes');
} else {
log('nav-task-actions openManageAssigneesModal not');
} }
} }
// Подписание (только для документов, если текущий пользователь - исполнитель)
if (!isDeleted && !isClosed && task.task_type === 'document' && currentUser && task.assignments?.some(a => parseInt(a.user_id) === currentUser.id)) {
if (typeof window.signTask === 'function') {
actions.push({
label: '✍️ Подписать',
handler: () => window.signTask(taskId, currentUser.id),
admin: true // primary_task
});
}
}
// ${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin'
// Администраторы и роль tasks
if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) {
// Подписание (только для документов, если текущий пользователь - исполнитель)
if (!isDeleted && !isClosed && task.task_type === 'document' && currentUser && task.assignments?.some(a => parseInt(a.user_id) === currentUser.id)) {
if (typeof window.signTask === 'function') {
actions.push({
label: '✍️ Подписать',
handler: () => window.signTask(taskId, currentUser.id),
admin: true
});
}
}
// Реквизиты документа (для задач типа document)
if (!isDeleted && !isClosed && task.task_type === 'document' && currentUser && task.assignments?.some(a => parseInt(a.user_id) === currentUser.id)) {
actions.push({
label: '📄 Реквизиты',
handler: () => openDocumentFieldsModal(taskId),
admin: false
});
}
// Администраторы и роль tasks
if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) {
if (typeof assignAdd_openModal === 'function') { if (typeof assignAdd_openModal === 'function') {
actions.push({ label: '🧑‍💼➕ Добавить исполнителя', actions.push({
label: '🧑‍💼➕ Добавить исполнителя',
handler: () => assignAdd_openModal(taskId), handler: () => assignAdd_openModal(taskId),
admin: true admin: true
}); });
log('nav-task-actions assignAdd_openModal yes');
} else {
log('nav-task-actions assignAdd_openModal not');
} }
if (typeof assignRemove_openModal === 'function') { if (typeof assignRemove_openModal === 'function') {
actions.push({ label: '🧑‍💼❌ Удалить исполнителя', actions.push({
label: '🧑‍💼❌ Удалить исполнителя',
handler: () => assignRemove_openModal(taskId), handler: () => assignRemove_openModal(taskId),
admin: true admin: true
}); });
log('nav-task-actions assignRemove_openModal yes');
} else {
log('nav-task-actions assignRemove_openModal not');
} }
//} if (currentUser && (currentUser.role === 'admin' && currentUser.login === 'minicrm')) {
// Доработка для документа (исполнитель) if (typeof openReworkModal === 'function') {
if (currentUser && (currentUser.role === 'admin' && currentUser.login === 'minicrm')) { 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');
} }
} }
}
// Кнопка "Создать ознакомление" для админов и tasks // Кнопка "Создать ознакомление" для админов и tasks
if (currentUser && (currentUser.role === 'admin' || currentUser.role === 'tasks')) { if (currentUser && (currentUser.role === 'admin' || currentUser.role === 'tasks')) {
actions.push({ actions.push({
label: '📖 Создать ознакомление', label: '📖 Создать ознакомление',
handler: () => openAcquaintanceModal(task.id), handler: () => openAcquaintanceModal(task.id),
primary: true // можно отнести к админским или отдельной категории primary: true
}); });
} }
// Доработка и изменение срока для необычных задач (исполнитель) // Доработка и изменение срока для необычных задач (исполнитель)
if (!isDeleted && !isClosed && task.task_type !== 'regular' && task.assignments && task.assignments.some(a => parseInt(a.user_id) === currentUser?.id)) { if (!isDeleted && !isClosed && task.task_type !== 'regular' && task.assignments && task.assignments.some(a => parseInt(a.user_id) === currentUser?.id)) {
if (typeof openReworkModal === 'function') { actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId),primary_task: true}); if (typeof openReworkModal === 'function') {
log('nav-task-actions openReworkModal yes'); actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId), primary_task: true });
} else {log('nav-task-actions openReworkModal not');} }
if (typeof openChangeDeadlineModal === 'function') { actions.push({ label: '📅 Изменить срок', handler: () => openChangeDeadlineModal(taskId),primary_task: true }); if (typeof openChangeDeadlineModal === 'function') {
log('nav-task-actions openChangeDeadlineModal yes'); actions.push({ label: '📅 Изменить срок', handler: () => openChangeDeadlineModal(taskId), primary_task: true });
} else {log('nav-task-actions openChangeDeadlineModal not');} }
} }
if (!isDeleted && !isClosed && task.task_type == 'regular') { if (!isDeleted && !isClosed && task.task_type == 'regular') {
if (typeof closeTask === 'function') { actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId),admin: true }); if (typeof closeTask === 'function') {
log('nav-task-actions closeTask yes'); actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId), admin: true });
} else {log('nav-task-actions closeTask not');} }
} }
if (canEdit && !isDeleted && !isClosed && currentUser.role === 'admin') {
if (typeof deleteTask === 'function') actions.push({ label: '🗑️ Удалить', handler: () => deleteTask(taskId) });
}
if (currentUser && currentUser.login === 'minicrm') {
// Закрытие (только minicrm)
//if (window.currentUser && window.currentUser.login === 'minicrm') {
if (typeof closeTask === 'function') actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId) });
//}
// Удаление (если есть права)
if (canEdit && !isDeleted && !isClosed && currentUser.role === 'admin') { if (canEdit && !isDeleted && !isClosed && currentUser.role === 'admin') {
if (typeof deleteTask === 'function') actions.push({ label: '🗑️ Удалить', handler: () => deleteTask(taskId) }); if (typeof deleteTask === 'function') actions.push({ label: '🗑️ Удалить', handler: () => deleteTask(taskId) });
} }
// Открытие закрытой задачи if (currentUser && currentUser.login === 'minicrm') {
if (isClosed && canEdit) { if (typeof closeTask === 'function') actions.push({ label: '🔒 Закрыть задачу', handler: () => closeTask(taskId) });
if (typeof reopenTask === 'function') actions.push({ label: '🔓 Открыть задачу', handler: () => reopenTask(taskId) }); if (canEdit && !isDeleted && !isClosed && currentUser.role === 'admin') {
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) });
}
} }
// Восстановление удалённой (только админ)
if (isDeleted && window.currentUser?.role === 'admin') {
if (typeof restoreTask === 'function') actions.push({ label: '↶ Восстановить', handler: () => restoreTask(taskId) });
}
}
//log('Actions built:', actions);
return actions; return actions;
} }
@@ -206,7 +354,6 @@ if (currentUser && currentUser.login === 'minicrm') {
const menuBtn = e.target.closest('.task-actions-menu-btn'); const menuBtn = e.target.closest('.task-actions-menu-btn');
if (!menuBtn) return; if (!menuBtn) return;
//log('Menu button clicked', menuBtn);
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@@ -227,12 +374,11 @@ if (currentUser && currentUser.login === 'minicrm') {
const actions = buildActionsForTask(task); const actions = buildActionsForTask(task);
if (actions.length === 0) return; if (actions.length === 0) return;
// primary
const primaryActions = actions.filter(a => a.primary); const primaryActions = actions.filter(a => a.primary);
const adminActions = actions.filter(a => a.admin && !a.primary); const adminActions = actions.filter(a => a.admin && !a.primary);
const taskActions = actions.filter(a => a.primary_task && !a.primary && !a.primary); const taskActions = actions.filter(a => a.primary_task && !a.primary && !a.primary);
const userActions = actions.filter(a => !a.primary && !a.admin && !a.primary_task); const userActions = actions.filter(a => !a.primary && !a.admin && !a.primary_task);
// Создаём затемнение
const overlay = document.createElement('div'); const overlay = document.createElement('div');
overlay.id = 'task-action-modal'; overlay.id = 'task-action-modal';
overlay.style.position = 'fixed'; overlay.style.position = 'fixed';
@@ -246,7 +392,6 @@ if (currentUser && currentUser.login === 'minicrm') {
overlay.style.alignItems = 'center'; overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center'; overlay.style.justifyContent = 'center';
// Создаём контейнер модального окна
const modal = document.createElement('div'); const modal = document.createElement('div');
modal.style.backgroundColor = 'white'; modal.style.backgroundColor = 'white';
modal.style.borderRadius = '12px'; modal.style.borderRadius = '12px';
@@ -258,7 +403,6 @@ if (currentUser && currentUser.login === 'minicrm') {
modal.style.maxHeight = '85vh'; modal.style.maxHeight = '85vh';
modal.style.overflowY = 'auto'; modal.style.overflowY = 'auto';
// Заголовок
const header = document.createElement('div'); const header = document.createElement('div');
header.style.display = 'flex'; header.style.display = 'flex';
header.style.justifyContent = 'space-between'; header.style.justifyContent = 'space-between';
@@ -290,140 +434,142 @@ if (currentUser && currentUser.login === 'minicrm') {
header.appendChild(closeBtn); header.appendChild(closeBtn);
modal.appendChild(header); modal.appendChild(header);
// === БЛОК: primary actions === // БЛОК: primary actions
if (primaryActions.length > 0) { if (primaryActions.length > 0) {
const primaryContainer = document.createElement('div'); const primaryContainer = document.createElement('div');
primaryContainer.style.marginBottom = '20px'; primaryContainer.style.marginBottom = '20px';
primaryActions.forEach(a => { primaryActions.forEach(a => {
const btn = document.createElement('button'); const btn = document.createElement('button');
btn.textContent = a.label; btn.textContent = a.label;
btn.style.cssText = ` btn.style.cssText = `
width: 100%; width: 100%;
padding: 14px; padding: 14px;
background-color: #27ae60; background-color: #27ae60;
color: white; color: white;
border: none; border: none;
border-radius: 8px; border-radius: 8px;
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
transition: background-color 0.2s; transition: background-color 0.2s;
margin-bottom: 10px; margin-bottom: 10px;
`; `;
btn.onmouseover = () => { btn.style.backgroundColor = '#229954'; }; btn.onmouseover = () => { btn.style.backgroundColor = '#229954'; };
btn.onmouseout = () => { btn.style.backgroundColor = '#27ae60'; }; btn.onmouseout = () => { btn.style.backgroundColor = '#27ae60'; };
btn.onclick = (event) => { btn.onclick = (event) => {
event.stopPropagation(); event.stopPropagation();
a.handler(); a.handler();
removeModal(); removeModal();
}; };
primaryContainer.appendChild(btn); primaryContainer.appendChild(btn);
}); });
modal.appendChild(primaryContainer); modal.appendChild(primaryContainer);
} }
// === Блок taskActions ===
if (taskActions.length > 0) { // БЛОК: taskActions
const taskContainer = document.createElement('div'); if (taskActions.length > 0) {
taskContainer.style.marginBottom = '20px'; const taskContainer = document.createElement('div');
taskActions.forEach(a => { taskContainer.style.marginBottom = '20px';
const btn = document.createElement('button'); taskActions.forEach(a => {
btn.textContent = a.label; const btn = document.createElement('button');
btn.style.cssText = ` btn.textContent = a.label;
width: 100%; btn.style.cssText = `
padding: 14px; width: 100%;
background-color: #dfc63cff; // цвет padding: 14px;
color: white; background-color: #dfc63cff;
border: none; color: white;
border-radius: 8px; border: none;
font-size: 16px; border-radius: 8px;
font-weight: 500; font-size: 16px;
cursor: pointer; font-weight: 500;
transition: background-color 0.2s; cursor: pointer;
margin-bottom: 10px; transition: background-color 0.2s;
`; margin-bottom: 10px;
btn.onmouseover = () => btn.style.backgroundColor = '#dfc63cff'; `;
btn.onmouseout = () => btn.style.backgroundColor = '#dfc63cff'; btn.onmouseover = () => btn.style.backgroundColor = '#dfc63cff';
btn.onclick = (event) => { btn.onmouseout = () => btn.style.backgroundColor = '#dfc63cff';
event.stopPropagation(); btn.onclick = (event) => {
a.handler(); event.stopPropagation();
removeModal(); a.handler();
}; removeModal();
taskContainer.appendChild(btn); };
}); taskContainer.appendChild(btn);
modal.appendChild(taskContainer); });
} modal.appendChild(taskContainer);
// === Блок admin === }
if (adminActions.length > 0) {
const adminContainer = document.createElement('div'); // БЛОК: admin
adminContainer.style.marginBottom = '20px'; if (adminActions.length > 0) {
adminActions.forEach(a => { const adminContainer = document.createElement('div');
const btn = document.createElement('button'); adminContainer.style.marginBottom = '20px';
btn.textContent = a.label; adminActions.forEach(a => {
btn.style.cssText = ` const btn = document.createElement('button');
width: 100%; btn.textContent = a.label;
padding: 14px; btn.style.cssText = `
background-color: #e74c3c; // красный цвет для админских width: 100%;
color: white; padding: 14px;
border: none; background-color: #e74c3c;
border-radius: 8px; color: white;
font-size: 16px; border: none;
font-weight: 500; border-radius: 8px;
cursor: pointer; font-size: 16px;
transition: background-color 0.2s; font-weight: 500;
margin-bottom: 10px; cursor: pointer;
`; transition: background-color 0.2s;
btn.onmouseover = () => btn.style.backgroundColor = '#c0392b'; margin-bottom: 10px;
btn.onmouseout = () => btn.style.backgroundColor = '#e74c3c'; `;
btn.onclick = (event) => { btn.onmouseover = () => btn.style.backgroundColor = '#c0392b';
event.stopPropagation(); btn.onmouseout = () => btn.style.backgroundColor = '#e74c3c';
a.handler(); btn.onclick = (event) => {
removeModal(); event.stopPropagation();
}; a.handler();
adminContainer.appendChild(btn); removeModal();
}); };
modal.appendChild(adminContainer); adminContainer.appendChild(btn);
} });
modal.appendChild(adminContainer);
}
// БЛОК: остальные (user)
if (userActions.length > 0) {
const grid = document.createElement('div');
grid.style.cssText = `
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
`;
userActions.forEach(a => {
const btn = document.createElement('button');
btn.textContent = a.label;
btn.style.cssText = `
flex: 0 0 calc(33.333% - 10px);
min-width: 120px;
padding: 12px 8px;
border: none;
border-radius: 8px;
background-color: #3498db;
color: white;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s;
`;
btn.onmouseover = () => btn.style.backgroundColor = '#2980b9';
btn.onmouseout = () => btn.style.backgroundColor = '#3498db';
btn.onclick = (event) => {
event.stopPropagation();
a.handler();
removeModal();
};
grid.appendChild(btn);
});
modal.appendChild(grid);
}
// === Блок остальных (user) ===
if (userActions.length > 0) {
const grid = document.createElement('div');
grid.style.cssText = `
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
`;
userActions.forEach(a => {
const btn = document.createElement('button');
btn.textContent = a.label;
btn.style.cssText = `
flex: 0 0 calc(33.333% - 10px);
min-width: 120px;
padding: 12px 8px;
border: none;
border-radius: 8px;
background-color: #3498db;
color: white;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s;
`;
btn.onmouseover = () => btn.style.backgroundColor = '#2980b9';
btn.onmouseout = () => btn.style.backgroundColor = '#3498db';
btn.onclick = (event) => {
event.stopPropagation();
a.handler();
removeModal();
};
grid.appendChild(btn);
});
modal.appendChild(grid);
}
overlay.appendChild(modal); overlay.appendChild(modal);
document.body.appendChild(overlay); document.body.appendChild(overlay);
// Закрытие по клику на затемнение
overlay.addEventListener('click', function(event) { overlay.addEventListener('click', function(event) {
if (event.target === overlay) { if (event.target === overlay) {
removeModal(); removeModal();
@@ -431,5 +577,11 @@ if (userActions.length > 0) {
}); });
}); });
// Экспортируем функции для использования в HTML (например, closeDocFieldsModal)
window.closeDocFieldsModal = function() {
const m = document.getElementById('doc-fields-modal');
if (m) m.remove();
};
//console.log('nav-task-actions.js loaded (centered modal)'); //console.log('nav-task-actions.js loaded (centered modal)');
})(); })();