действия подписать
This commit is contained in:
@@ -88,7 +88,16 @@ if (currentUser && !isDeleted && !isClosed) {
|
|||||||
log('nav-task-actions openManageAssigneesModal not');
|
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'
|
// ${currentUser && currentUser.role === 'tasks' && canEdit || currentUser.role === 'admin'
|
||||||
// Администраторы и роль tasks
|
// Администраторы и роль tasks
|
||||||
if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) {
|
if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks' && canEdit))) {
|
||||||
@@ -122,6 +131,7 @@ if (currentUser && (currentUser.role === 'admin' || (currentUser.role === 'tasks
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Доработка и изменение срока для необычных задач (исполнитель)
|
// Доработка и изменение срока для необычных задач (исполнитель)
|
||||||
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') { actions.push({ label: '🔄 Доработка', handler: () => openReworkModal(taskId),primary_task: true});
|
||||||
@@ -131,7 +141,7 @@ if (typeof openChangeDeadlineModal === 'function') { actions.push({ label: '📅
|
|||||||
log('nav-task-actions openChangeDeadlineModal yes');
|
log('nav-task-actions openChangeDeadlineModal yes');
|
||||||
} else {log('nav-task-actions openChangeDeadlineModal not');}
|
} else {log('nav-task-actions openChangeDeadlineModal not');}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentUser && currentUser.login === 'minicrm') {
|
if (currentUser && currentUser.login === 'minicrm') {
|
||||||
// Закрытие (только minicrm)
|
// Закрытие (только minicrm)
|
||||||
//if (window.currentUser && window.currentUser.login === 'minicrm') {
|
//if (window.currentUser && window.currentUser.login === 'minicrm') {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// signature.js - Универсальный скрипт для подписания задач
|
// signature.js - Универсальный скрипт для подписания задач (только логика, без встройки в интерфейс)
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
usersEndpoint: '/api/users',
|
usersEndpoint: '/api/users',
|
||||||
replaceEndpoint: '/api/tasks/${taskId}/replace-assignee',
|
replaceEndpoint: '/api/tasks/${taskId}/replace-assignee',
|
||||||
replaceAllEndpoint: '/api/tasks/${taskId}/replace-all-assignees',
|
replaceAllEndpoint: '/api/tasks/${taskId}/replace-all-assignees',
|
||||||
taskTypeDocument: 'document' // Тип задачи "Документ"
|
taskTypeDocument: 'document'
|
||||||
};
|
};
|
||||||
|
|
||||||
// Текущий пользователь
|
// Текущий пользователь
|
||||||
@@ -24,9 +24,6 @@
|
|||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.user) {
|
if (data.user) {
|
||||||
currentUser = data.user;
|
currentUser = data.user;
|
||||||
////console.log('✅ Signature: текущий пользователь', currentUser);
|
|
||||||
|
|
||||||
// Проверяем, является ли пользователь подписантом
|
|
||||||
await checkIfUserIsSigner();
|
await checkIfUserIsSigner();
|
||||||
}
|
}
|
||||||
return currentUser;
|
return currentUser;
|
||||||
@@ -39,19 +36,13 @@
|
|||||||
// Проверка, является ли текущий пользователь подписантом
|
// Проверка, является ли текущий пользователь подписантом
|
||||||
async function checkIfUserIsSigner() {
|
async function checkIfUserIsSigner() {
|
||||||
if (!currentUser) return false;
|
if (!currentUser) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Получаем всех подписантов
|
|
||||||
const signers = await getSigners();
|
const signers = await getSigners();
|
||||||
|
|
||||||
// Проверяем, есть ли текущий пользователь в списке подписантов
|
|
||||||
isCurrentUserSigner = signers.some(signer =>
|
isCurrentUserSigner = signers.some(signer =>
|
||||||
signer.id === currentUser.id ||
|
signer.id === currentUser.id ||
|
||||||
signer.login === currentUser.login ||
|
signer.login === currentUser.login ||
|
||||||
signer.name === currentUser.name
|
signer.name === currentUser.name
|
||||||
);
|
);
|
||||||
|
|
||||||
////console.log('✅ Signature: пользователь является подписантом?', isCurrentUserSigner);
|
|
||||||
return isCurrentUserSigner;
|
return isCurrentUserSigner;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ Signature: ошибка проверки подписанта', error);
|
console.error('❌ Signature: ошибка проверки подписанта', error);
|
||||||
@@ -64,7 +55,6 @@
|
|||||||
try {
|
try {
|
||||||
const response = await fetch(CONFIG.apiEndpoint);
|
const response = await fetch(CONFIG.apiEndpoint);
|
||||||
if (!response.ok) return await getSignersFallback();
|
if (!response.ok) return await getSignersFallback();
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const signers = data.filter(user =>
|
const signers = data.filter(user =>
|
||||||
user.is_active && (
|
user.is_active && (
|
||||||
@@ -73,7 +63,6 @@
|
|||||||
user.ldap_group?.toLowerCase().includes(CONFIG.signerGroup.toLowerCase())
|
user.ldap_group?.toLowerCase().includes(CONFIG.signerGroup.toLowerCase())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return signers.map(s => ({
|
return signers.map(s => ({
|
||||||
id: s.user_id,
|
id: s.user_id,
|
||||||
name: s.user_name || s.login || 'Неизвестно',
|
name: s.user_name || s.login || 'Неизвестно',
|
||||||
@@ -99,9 +88,7 @@
|
|||||||
|
|
||||||
// Основная функция подписания
|
// Основная функция подписания
|
||||||
window.signTask = async function(taskId, userId) {
|
window.signTask = async function(taskId, userId) {
|
||||||
// Если userId не передан, используем текущего пользователя
|
|
||||||
const targetUserId = userId || currentUser?.id;
|
const targetUserId = userId || currentUser?.id;
|
||||||
|
|
||||||
if (!targetUserId) {
|
if (!targetUserId) {
|
||||||
alert('❌ Не удалось определить текущего пользователя');
|
alert('❌ Не удалось определить текущего пользователя');
|
||||||
return false;
|
return false;
|
||||||
@@ -109,7 +96,6 @@
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const signers = await getSigners();
|
const signers = await getSigners();
|
||||||
|
|
||||||
if (!signers.length) {
|
if (!signers.length) {
|
||||||
alert('❌ Секретари не найдены в системе');
|
alert('❌ Секретари не найдены в системе');
|
||||||
return false;
|
return false;
|
||||||
@@ -119,11 +105,9 @@
|
|||||||
const msg = signers.length === 1
|
const msg = signers.length === 1
|
||||||
? `✍️ Назначить подписанта?\n\n${names}`
|
? `✍️ Назначить подписанта?\n\n${names}`
|
||||||
: `✍️ Назначить подписантов?\n\n${names}`;
|
: `✍️ Назначить подписантов?\n\n${names}`;
|
||||||
|
|
||||||
if (!confirm(msg)) return false;
|
if (!confirm(msg)) return false;
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
|
|
||||||
if (signers.length > 1) {
|
if (signers.length > 1) {
|
||||||
const url = CONFIG.replaceAllEndpoint.replace('${taskId}', taskId);
|
const url = CONFIG.replaceAllEndpoint.replace('${taskId}', taskId);
|
||||||
response = await fetch(url, {
|
response = await fetch(url, {
|
||||||
@@ -145,16 +129,14 @@
|
|||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
alert(`✅ Задача ${signers.length > 1 ? 'назначена подписантам' : 'переназначена подписанту'}`);
|
alert(`✅ Задача ${signers.length > 1 ? 'назначена подписантам' : 'переназначена подписанту'}`);
|
||||||
// Пробуем перезагрузить задачи разными способами
|
// Пробуем перезагрузить задачи
|
||||||
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
|
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
|
||||||
window.TasksType.loadTasks();
|
window.TasksType.loadTasks();
|
||||||
} else if (window.loadTasks && typeof window.loadTasks === 'function') {
|
} else if (window.loadTasks && typeof window.loadTasks === 'function') {
|
||||||
window.loadTasks();
|
window.loadTasks();
|
||||||
} else {
|
} else {
|
||||||
// Если нет функций загрузки, просто обновляем страницу
|
|
||||||
setTimeout(() => window.location.reload(), 1500);
|
setTimeout(() => window.location.reload(), 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
const err = await response.json();
|
const err = await response.json();
|
||||||
@@ -168,7 +150,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Обновление статуса задачи
|
// Обновление статуса задачи (может пригодиться)
|
||||||
window.updateTaskStatus = async function(taskId, userId, status) {
|
window.updateTaskStatus = async function(taskId, userId, status) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/tasks/${taskId}/status`, {
|
const response = await fetch(`/api/tasks/${taskId}/status`, {
|
||||||
@@ -176,7 +158,6 @@
|
|||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ userId, status })
|
body: JSON.stringify({ userId, status })
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
|
if (window.TasksType && typeof window.TasksType.loadTasks === 'function') {
|
||||||
window.TasksType.loadTasks();
|
window.TasksType.loadTasks();
|
||||||
@@ -196,142 +177,10 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Получение типа задачи из элемента карточки
|
// Инициализация: получаем данные текущего пользователя (без добавления кнопок)
|
||||||
function getTaskTypeFromCard(card) {
|
|
||||||
// Ищем элемент с типом задачи
|
|
||||||
const typeElement = card.querySelector('.task-type-badge, .task-type');
|
|
||||||
if (typeElement) {
|
|
||||||
const classList = typeElement.className;
|
|
||||||
if (classList.includes('document') || classList.includes('Документ')) {
|
|
||||||
return 'document';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Пробуем найти по тексту
|
|
||||||
const cardText = card.textContent || '';
|
|
||||||
if (cardText.includes('Документ') || cardText.includes('document')) {
|
|
||||||
return 'document';
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Функция для добавления кнопок в существующие карточки задач
|
|
||||||
window.addSignatureButtons = function() {
|
|
||||||
// Показываем кнопку только если пользователь является подписантом
|
|
||||||
if (!currentUser || isCurrentUserSigner) return;
|
|
||||||
|
|
||||||
document.querySelectorAll('[data-task-id]').forEach(card => {
|
|
||||||
// Проверяем, есть ли уже кнопка
|
|
||||||
if (card.querySelector('.signature-btn')) return;
|
|
||||||
|
|
||||||
// Проверяем тип задачи - только для документов
|
|
||||||
const taskType = getTaskTypeFromCard(card);
|
|
||||||
if (taskType !== CONFIG.taskTypeDocument) return;
|
|
||||||
|
|
||||||
const taskId = card.dataset.taskId;
|
|
||||||
|
|
||||||
// Ищем контейнер action-buttons
|
|
||||||
const actionsContainer = card.querySelector('.action-buttons');
|
|
||||||
|
|
||||||
if (actionsContainer) {
|
|
||||||
const btn = document.createElement('button');
|
|
||||||
btn.className = 'signature-btn action-btn sign-btn';
|
|
||||||
btn.innerHTML = '✍️ Подписать';
|
|
||||||
btn.onclick = (e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
window.signTask(taskId, currentUser.id);
|
|
||||||
};
|
|
||||||
btn.title = 'Передать подписанту';
|
|
||||||
actionsContainer.appendChild(btn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Наблюдатель за изменениями DOM для динамической добавления кнопок
|
|
||||||
function observeDOM() {
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
|
||||||
mutations.forEach((mutation) => {
|
|
||||||
if (mutation.addedNodes.length) {
|
|
||||||
window.addSignatureButtons();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(document.body, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Функция для получения отображаемого имени типа задачи
|
|
||||||
function getTaskTypeDisplayName(type) {
|
|
||||||
const typeMap = {
|
|
||||||
'document': 'Документ',
|
|
||||||
'task': 'Задача',
|
|
||||||
'bug': 'Ошибка',
|
|
||||||
'request': 'Заявка'
|
|
||||||
};
|
|
||||||
return typeMap[type] || type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Инициализация при загрузке страницы
|
|
||||||
async function init() {
|
async function init() {
|
||||||
//console.log('🔄 Signature module initializing...');
|
|
||||||
|
|
||||||
// Получаем текущего пользователя и проверяем, является ли он подписантом
|
|
||||||
await getCurrentUser();
|
await getCurrentUser();
|
||||||
|
console.log('✅ Signature module loaded (UI integration removed)');
|
||||||
// Добавляем кнопки на существующие карточки только если пользователь подписант
|
|
||||||
setTimeout(() => {
|
|
||||||
if (isCurrentUserSigner) {
|
|
||||||
window.addSignatureButtons();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// Запускаем наблюдение за DOM
|
|
||||||
observeDOM();
|
|
||||||
|
|
||||||
// Перехватываем функцию рендеринга TasksType если она существует
|
|
||||||
if (window.TasksType && window.TasksType.renderExpandedContent) {
|
|
||||||
const originalRender = window.TasksType.renderExpandedContent;
|
|
||||||
window.TasksType.renderExpandedContent = function(task) {
|
|
||||||
let html = originalRender ? originalRender(task) : '';
|
|
||||||
|
|
||||||
// Добавляем кнопку подписания в развернутое содержимое только для документов и если пользователь подписант
|
|
||||||
if (currentUser && isCurrentUserSigner && task.task_type === CONFIG.taskTypeDocument) {
|
|
||||||
|
|
||||||
// Создаем контейнер action-buttons если его нет
|
|
||||||
if (!html.includes('action-buttons')) {
|
|
||||||
const signButton = `
|
|
||||||
<div class="action-buttons" style="margin-bottom: 10px;">
|
|
||||||
<button class="action-btn sign-btn" onclick="signTask(${task.id}, ${currentUser.id})" title="Передать подписанту">
|
|
||||||
✍️ Подписать
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// Вставляем кнопки после заголовка
|
|
||||||
html = html.replace('<div class="tasks-type-header">',
|
|
||||||
'<div class="tasks-type-header">' + signButton);
|
|
||||||
} else {
|
|
||||||
// Добавляем кнопку в существующий контейнер
|
|
||||||
const signButton = `
|
|
||||||
<button class="action-btn sign-btn" onclick="signTask(${task.id}, ${currentUser.id})" title="Передать подписанту">
|
|
||||||
✍️ Подписать
|
|
||||||
</button>
|
|
||||||
`;
|
|
||||||
|
|
||||||
html = html.replace('</div><div class="tasks-type-description">',
|
|
||||||
signButton + '</div><div class="tasks-type-description">');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
////console.log('✅ Signature module loaded. User is signer:', isCurrentUserSigner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Запускаем инициализацию после загрузки DOM
|
// Запускаем инициализацию после загрузки DOM
|
||||||
|
|||||||
Reference in New Issue
Block a user