Files
crm.clientright.ru/layouts/v7/lib/nextcloud-editor.js

558 lines
24 KiB
JavaScript
Raw Normal View History

/**
* Nextcloud Editor Integration JavaScript
* JavaScript для интеграции редактора документов Nextcloud
*/
/**
* Открытие папки проекта в Nextcloud
*/
function openProjectFolder(projectId, projectName) {
console.log('📁 Opening project folder in Nextcloud:', projectId, projectName);
// Нормализуем имя проекта (убираем пробелы и кавычки)
if (projectName) {
// Убираем кавычки (заменяем на подчёркивание)
projectName = projectName.replace(/"/g, '_');
// Заменяем ВСЕ пробелы на подчёркивания
projectName = projectName.replace(/\s+/g, '_');
}
// Формируем URL для папки проекта в Nextcloud
const folderName = projectName ? `${projectName}_${projectId}` : `project_${projectId}`;
const encodedFolderName = encodeURIComponent(folderName);
const nextcloudUrl = 'https://office.clientright.ru:8443';
2025-11-01 12:22:12 +03:00
// URL для папки проекта в Nextcloud External Storage (со структурой Project/)
const folderUrl = `${nextcloudUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/Project/${encodedFolderName}`;
console.log('🔗 Folder URL:', folderUrl);
// Открываем папку в новом окне
window.open(folderUrl, 'nextcloud_folder', 'width=1200,height=800,scrollbars=yes,resizable=yes');
}
/**
* Открытие редактора Nextcloud для документа
*/
function openNextcloudEditor(recordId, fileName) {
console.log('🚀 NEXTCLOUD EDITOR v2 - ONLYOFFICE + S3: Function called!', recordId, fileName);
// OnlyOffice + S3 Pre-signed URLs (БЫСТРО!)
const redirectUrl = `/crm_extensions/file_storage/api/open_file_v2.php?recordId=${recordId}&fileName=${encodeURIComponent(fileName)}&v=${Date.now()}`;
console.log('🎯 Opening via OnlyOffice v2:', redirectUrl);
// Открываем в новом окне
const win = window.open(redirectUrl, 'nextcloud_editor_' + Date.now(), 'width=1400,height=900,scrollbars=yes,resizable=yes');
if (win) {
console.log('✅ Collabora editor opened successfully');
} else {
console.log('❌ Failed to open editor window - popup blocked');
alert('❌ Не удалось открыть редактор. Проверьте блокировку всплывающих окон.');
}
}
function testSimpleAPI(recordId, fileName) {
console.log('🧪 Testing simple API...', recordId, fileName);
// Пропускаем простой API и сразу идем к основному
console.log('🎯 Skipping simple API, going to main API...');
callMainAPI(recordId, fileName);
}
function createEditUrls(baseEditUrl, recordId, fileName, fileId = 662) {
console.log('🔗 Creating edit URLs in JavaScript...', { fileId, fileName });
// Извлекаем базовый URL из базовой ссылки
const baseUrl = 'https://office.clientright.ru:8443';
const encodedFileName = encodeURIComponent(fileName);
const filePath = `/crm/crm2/CRM_Active_Files/Documents/${recordId}/${encodedFileName}`;
// Токен для RichDocuments (из настроек Nextcloud)
const richDocumentsToken = '1sanuq71b3n4fm1ldkbb';
const urls = {
// ЛУЧШИЙ СПОСОБ! - редирект через нашу промежуточную страницу (БЕЗ CSRF!)
'redirect_to_nextcloud': fileId ? `/crm_extensions/file_storage/api/open_file.php?fileId=${fileId}&fileName=${encodedFileName}&recordId=${recordId}` : null,
// РАБОЧИЙ СПОСОБ! - прямая ссылка на Nextcloud
'files_editing_auto': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=true&openfile=true` : null,
// Вариант без автоматического редактирования
'files_editing': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/&editing=false&openfile=true` : null,
// Collabora Editor
'collabora_editor': fileId ? `${baseUrl}/index.php/apps/richdocuments/index?fileId=${fileId}` : null,
// OnlyOffice Editor
'onlyoffice_editor': fileId ? `${baseUrl}/apps/onlyoffice?fileId=${fileId}` : null,
// Прямое открытие файла
'files_direct': fileId ? `${baseUrl}/apps/files/files/${fileId}` : `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}`,
// Файловый менеджер
'files_manager': `${baseUrl}/apps/files/?dir=/&openfile=${encodedFileName}`
};
// Убираем null значения
Object.keys(urls).forEach(key => {
if (urls[key] === null) {
delete urls[key];
}
});
return {
all: urls,
// РЕДИРЕКТ через нашу страницу - лучший способ (обходит CSRF)
recommended: urls.redirect_to_nextcloud || urls.files_editing_auto || urls.files_editing || urls.collabora_editor
};
}
function getEditUrls(recordId, fileName, simpleData) {
console.log('🔗 Getting edit URLs...');
$.ajax({
url: '/crm_extensions/file_storage/api/get_edit_urls.php',
method: 'GET',
data: {
record: recordId,
fileName: fileName
},
dataType: 'json',
success: function(response) {
console.log('✅ Edit URLs received:', response);
if (response.success) {
// Пробуем открыть рекомендуемый URL
const recommendedUrl = response.data.urls[response.data.recommended];
console.log('🎯 Trying recommended URL:', recommendedUrl);
openEditor(recommendedUrl, {
...simpleData,
urls: response.data.urls,
recommended: response.data.recommended
});
} else {
// Если не получилось, используем простой API
openEditor(simpleData.edit_url, simpleData);
}
},
error: function(xhr, status, error) {
console.error('❌ Failed to get edit URLs:', error);
// Если не получилось, используем простой API
openEditor(simpleData.edit_url, simpleData);
}
});
}
function callMainAPI(recordId, fileName) {
console.log('🎯 Calling main API...', recordId, fileName);
// Показываем прогресс
if (typeof app !== 'undefined' && app.helper && app.helper.showProgress) {
app.helper.showProgress({
message: 'Подготовка файла к редактированию...'
});
}
// Вызываем ПРАВИЛЬНЫЙ API для подготовки файла
$.ajax({
url: '/index.php?module=Documents&action=NcPrepareEdit',
method: 'GET',
data: {
record: recordId,
fileName: fileName
},
dataType: 'json',
success: function(response) {
console.log('📡 API Response:', response);
// Скрываем прогресс
if (typeof app !== 'undefined' && app.helper && app.helper.hideProgress) {
app.helper.hideProgress();
}
if (response.success) {
console.log('✅ File prepared successfully');
// Открываем редактор
openEditor(response.data.edit_url, response.data);
} else {
console.error('❌ API Error:', response.error);
showError('Ошибка подготовки файла: ' + response.error);
}
},
error: function(xhr, status, error) {
console.error('❌ AJAX Error:', error);
console.error('❌ Status:', status);
console.error('❌ Response:', xhr.responseText);
console.error('❌ Status Code:', xhr.status);
// Скрываем прогресс
if (typeof app !== 'undefined' && app.helper && app.helper.hideProgress) {
app.helper.hideProgress();
}
// Показываем подробную ошибку
let errorMessage = 'Ошибка подключения к серверу: ' + error;
if (xhr.responseText) {
errorMessage += '\n\nОтвет сервера:\n' + xhr.responseText;
}
showError(errorMessage);
}
});
}
// Функция для открытия редактора
function openEditor(editUrl, fileData) {
console.log('🎯 Opening editor with URL:', editUrl);
console.log('📋 All available URLs:', fileData.urls);
// Открываем редактор в новом окне
var win = window.open(editUrl, 'nextcloud_editor', 'width=1200,height=800,scrollbars=yes,resizable=yes');
if (win) {
console.log('✅ Editor opened successfully');
// Показываем уведомление об успехе
if (typeof app !== 'undefined' && app.helper && app.helper.showSuccessNotification) {
app.helper.showSuccessNotification({
message: 'Редактор открыт! Файл: ' + fileData.file_name
});
} else {
// alert('✅ Редактор открыт! Файл: ' + fileData.file_name);
}
// Показываем информацию о файле
showFileInfo(fileData);
} else {
console.log('❌ Failed to open editor window - popup blocked or error');
console.log('📋 Showing modal with alternative URLs');
// Показываем модальное окно с альтернативными вариантами
showModalWithUrls(editUrl, fileData);
}
}
// Функция для отображения информации о файле
function showFileInfo(fileData) {
// Проверяем, есть ли нужные поля в fileData
var location = 'Неизвестно';
var nextcloudPath = 'Не указан';
var status = 'Не указан';
if (fileData.file_location && fileData.file_location.type) {
location = fileData.file_location.type === 's3' ? 'S3 хранилище' : 'Локальное хранилище';
}
if (fileData.nextcloud_path) {
nextcloudPath = fileData.nextcloud_path;
}
if (fileData.message) {
status = fileData.message;
}
var infoHtml = `
<div class="alert alert-info" style="margin: 10px 0;">
<h5><i class="fa fa-info-circle"></i> Информация о файле</h5>
<p><strong>Файл:</strong> ${fileData.file_name}</p>
<p><strong>Расположение:</strong> ${location}</p>
<p><strong>Путь в Nextcloud:</strong> ${nextcloudPath}</p>
<p><strong>Статус:</strong> ${status}</p>
</div>
`;
// Если есть альтернативные URL, добавляем их
if (fileData.urls) {
infoHtml += `
<div class="alert alert-warning" style="margin: 10px 0;">
<h6><i class="fa fa-link"></i> Альтернативные способы открытия:</h6>
<div class="btn-group-vertical" style="width: 100%;">
`;
Object.keys(fileData.urls).forEach(function(key) {
const label = key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
const isRecommended = key === fileData.recommended;
const btnClass = isRecommended ? 'btn-success' : 'btn-default';
const icon = isRecommended ? 'fa-star' : 'fa-external-link';
infoHtml += `
<a href="${fileData.urls[key]}" target="_blank" class="btn ${btnClass} btn-sm" style="margin: 2px; text-align: left;">
<i class="fa ${icon}"></i> ${label}${isRecommended ? ' (рекомендуется)' : ''}
</a>
`;
});
infoHtml += `
</div>
</div>
`;
}
// Добавляем информацию в модальное окно или показываем отдельно
if ($('#nextcloudEditModal').length) {
$('#nextcloudEditModal .modal-body').prepend(infoHtml);
} else {
// Создаём временное уведомление
var notification = $('<div class="alert alert-info" style="position: fixed; top: 20px; right: 20px; z-index: 9999; max-width: 400px;">' + infoHtml + '</div>');
$('body').append(notification);
// Автоматически скрываем через 5 секунд
setTimeout(function() {
notification.fadeOut(function() {
notification.remove();
});
}, 5000);
}
}
// Функция для отображения ошибок
function showError(message) {
console.error('🚨 Error:', message);
if (typeof app !== 'undefined' && app.helper && app.helper.showErrorNotification) {
app.helper.showErrorNotification({
message: message
});
} else {
alert('❌ Ошибка: ' + message);
}
}
// Функция для показа модального окна с URL
function showModalWithUrls(editUrl, fileData) {
console.log('📋 Showing modal with URLs for file:', fileData.file_name);
if (fileData.urls) {
// Используем существующую функцию showEditOptions
showEditOptions(fileData.urls, fileData.file_name, fileData.record_id);
} else {
// Если нет альтернативных URL, показываем ошибку
showError('Не удалось открыть редактор. Попробуйте открыть файл вручную в Nextcloud.');
}
}
/**
* Показ вариантов открытия файла
*/
function showEditOptions(urls, fileName, recordId) {
console.log('🎯 Showing edit options for:', fileName);
console.log('📋 Available URLs:', urls);
var buttonsHtml = '';
// Если urls - это объект (новый формат)
if (typeof urls === 'object' && !Array.isArray(urls)) {
Object.keys(urls).forEach(function(key, index) {
const label = key.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
const url = urls[key];
const isRecommended = key === 'correct_path';
const btnClass = isRecommended ? 'btn-success' : 'btn-primary';
const icon = isRecommended ? 'fa-star' : 'fa-external-link';
buttonsHtml += `
<a href="${url}" target="_blank" class="btn ${btnClass} btn-sm" style="margin: 3px; display: block;">
<i class="fa ${icon}"></i> ${label}${isRecommended ? ' (рекомендуется)' : ''}
</a>
`;
});
} else {
// Старый формат - массив URL
var labels = [
'С параметром openfile',
'С action=edit',
'С edit=true',
'Через RichDocuments',
'Через OnlyOffice'
];
var icons = ['fa-file', 'fa-edit', 'fa-pencil', 'fa-file-text', 'fa-file-word-o'];
var colors = ['btn-primary', 'btn-success', 'btn-info', 'btn-warning', 'btn-danger'];
urls.forEach(function(url, index) {
buttonsHtml += `
<a href="${url}" target="_blank" class="btn ${colors[index]} btn-sm" style="margin: 3px; display: block;">
<i class="fa ${icons[index]}"></i> ${labels[index]}
</a>
`;
});
}
var modalHtml = `
<div class="modal fade" id="nextcloudEditModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
<i class="fa fa-edit"></i> Варианты открытия файла
</h4>
<button type="button" class="close" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<p><strong>Файл:</strong> ${fileName}</p>
<p>Попробуйте эти варианты для прямого открытия в редакторе:</p>
<div class="btn-group-vertical" style="width: 100%;">
${buttonsHtml}
</div>
<div class="alert alert-info" style="margin-top: 15px;">
<small><strong>💡 Совет:</strong> Попробуйте варианты сверху вниз. Один из них должен открыть файл сразу в редакторе!</small>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Закрыть</button>
</div>
</div>
</div>
</div>
`;
// Удаляем старое модальное окно
$('#nextcloudEditModal').remove();
// Добавляем новое
$('body').append(modalHtml);
$('#nextcloudEditModal').modal('show');
}
/**
* Синхронизация изменений файла (заглушка)
*/
function syncFileChanges(recordId, fileName) {
console.log('Syncing file changes for:', recordId, fileName);
if (typeof app !== 'undefined' && app.helper && app.helper.showSuccessNotification) {
app.helper.showSuccessNotification({
message: 'Изменения синхронизированы!'
});
} else {
alert('✅ Изменения синхронизированы!');
}
}
/**
* Открытие редактора в новом окне
*/
function openInNewWindow(editUrl) {
window.open(editUrl, 'nextcloud_editor', 'width=1200,height=800,scrollbars=yes,resizable=yes,toolbar=no,location=no');
console.log('Opened Nextcloud editor in new window');
}
// Алиас функции для обратной совместимости
function editInNextcloud(recordId, fileName) {
console.log('📝 editInNextcloud called (alias)');
return openNextcloudEditor(recordId, fileName);
}
2025-11-01 12:22:12 +03:00
/**
* Открытие файла через Nextcloud Files UI (с версионированием)
* Использует Redis индекс для быстрого получения FileID
2025-11-01 12:22:12 +03:00
*/
function openViaNextcloud(recordId, fileName) {
console.log('📚 Opening via Nextcloud Files UI:', recordId);
// Получаем FileID и redirect URL из API
fetch(`/crm_extensions/file_storage/api/nextcloud_open.php?recordId=${recordId}&v=${Date.now()}`)
.then(response => response.json())
.then(data => {
if (data.success) {
console.log('✅ FileID получен:', data.fileId);
console.log('🔗 Redirect URL:', data.redirectUrl);
// Открываем Nextcloud в новом окне
const win = window.open(data.redirectUrl, 'nextcloud_files_' + Date.now(), 'width=1400,height=900,scrollbars=yes,resizable=yes');
if (win) {
console.log('✅ Nextcloud opened successfully');
} else {
console.log('❌ Failed to open window - popup blocked');
alert('❌ Не удалось открыть Nextcloud. Проверьте блокировку всплывающих окон.');
}
} else {
console.error('❌ API error:', data);
alert('❌ Ошибка получения FileID: ' + (data.error || 'Unknown error'));
}
})
.catch(error => {
console.error('❌ Fetch error:', error);
alert('❌ Ошибка подключения к API');
});
2025-11-01 12:22:12 +03:00
}
/**
* Создание нового файла в Nextcloud
* @param {string} module - Модуль CRM (Project, Contacts, Accounts и т.д.)
* @param {string} recordId - ID записи
* @param {string} recordName - Название записи (для имени папки)
* @param {string} fileType - Тип файла (docx, xlsx, pptx)
*/
function createFileInNextcloud(module, recordId, recordName, fileType) {
console.log('🆕 Creating file in Nextcloud:', { module, recordId, recordName, fileType });
// Формируем имя файла по умолчанию
const fileTypeNames = {
'docx': 'Документ',
'xlsx': 'Таблица',
'pptx': 'Презентация'
};
const defaultName = `${fileTypeNames[fileType]}_${new Date().toISOString().split('T')[0]}`;
// Запрашиваем имя файла у пользователя
const fileName = prompt(`Введите название файла (без расширения):`, defaultName);
if (!fileName) {
console.log('❌ File creation cancelled');
return;
}
// Показываем прогресс
if (typeof app !== 'undefined' && app.helper && app.helper.showProgress) {
app.helper.showProgress({
message: 'Создание файла в Nextcloud...'
});
}
// Вызываем скрипт создания
const createUrl = `/crm_extensions/file_storage/api/create_nextcloud_file.php?module=${module}&recordId=${recordId}&recordName=${encodeURIComponent(recordName)}&fileName=${encodeURIComponent(fileName)}&fileType=${fileType}`;
console.log('🎯 Creating file:', createUrl);
// Открываем в новом окне (скрипт создаст файл и откроет редактор)
const win = window.open(createUrl, 'nextcloud_create_' + Date.now(), 'width=1400,height=900,scrollbars=yes,resizable=yes');
// Скрываем прогресс
setTimeout(function() {
if (typeof app !== 'undefined' && app.helper && app.helper.hideProgress) {
app.helper.hideProgress();
}
}, 1000);
if (!win) {
alert('❌ Не удалось открыть Nextcloud. Проверьте блокировку всплывающих окон.');
}
}
// Автоматическое подключение при загрузке страницы
$(document).ready(function() {
console.log('Nextcloud Editor integration loaded');
// Добавляем CSS стили для модального окна
if (!$('#nextcloud-editor-styles').length) {
$('<style id="nextcloud-editor-styles">')
.html(`
.nextcloud-edit-btn {
background: #0082c9;
border-color: #0082c9;
}
.nextcloud-edit-btn:hover {
background: #006ba6;
border-color: #006ba6;
}
`)
.appendTo('head');
}
});