Проблема: Редакторы документов (OnlyOffice, Collabora) не установлены в Nextcloud Решение: Добавлены дополнительные варианты открытия файлов Изменения: - crm_extensions/nextcloud_editor/js/nextcloud-editor.js: * Убран параметр editing=false для Files App * Добавлены варианты: download_direct, view_only * Улучшена логика fallback при ошибках Добавлены тестовые страницы: - test_nc_open.html - тест разных редакторов - simple_test.html - простое модальное окно с вариантами Варианты открытия: 1. Files App (показать файл в менеджере) 2. Прямое скачивание через WebDAV 3. Просмотр (если поддерживается браузером) Теперь кнопка Nextcloud будет работать даже без установленных редакторов
466 lines
19 KiB
JavaScript
466 lines
19 KiB
JavaScript
/**
|
||
* Nextcloud Editor Integration JavaScript
|
||
* JavaScript для интеграции редактора документов Nextcloud
|
||
*/
|
||
|
||
/**
|
||
* Открытие редактора Nextcloud для документа
|
||
*/
|
||
function openNextcloudEditor(recordId, fileName) {
|
||
console.log('🚀 NEXTCLOUD EDITOR: Function called!', recordId, fileName);
|
||
|
||
// Сначала тестируем debug API
|
||
console.log('🔍 Testing debug API...');
|
||
$.ajax({
|
||
url: '/crm_extensions/file_storage/api/debug_api.php',
|
||
method: 'GET',
|
||
dataType: 'json',
|
||
success: function(debugResponse) {
|
||
console.log('✅ Debug API works:', debugResponse);
|
||
|
||
// Теперь тестируем простой API
|
||
testSimpleAPI(recordId, fileName);
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('❌ Debug API failed:', error);
|
||
console.error('Response:', xhr.responseText);
|
||
|
||
// Все равно пытаемся вызвать основной API
|
||
callMainAPI(recordId, fileName);
|
||
}
|
||
});
|
||
}
|
||
|
||
function testSimpleAPI(recordId, fileName) {
|
||
console.log('🧪 Testing simple API...', recordId, fileName);
|
||
|
||
$.ajax({
|
||
url: '/crm_extensions/file_storage/api/simple_test.php',
|
||
method: 'GET',
|
||
data: {
|
||
recordId: recordId,
|
||
fileName: fileName
|
||
},
|
||
dataType: 'json',
|
||
success: function(response) {
|
||
console.log('✅ Simple API works:', response);
|
||
|
||
if (response.success) {
|
||
// Если простой API работает, пробуем открыть редактор напрямую
|
||
console.log('🎯 Opening editor directly...');
|
||
|
||
// Создаем различные варианты URL прямо в JavaScript
|
||
const urls = createEditUrls(response.data.edit_url, recordId, fileName, response.data.file_id);
|
||
|
||
openEditor(urls.recommended, {
|
||
...response.data,
|
||
urls: urls.all,
|
||
recommended: 'correct_path'
|
||
});
|
||
} else {
|
||
console.error('❌ Simple API error:', response.error);
|
||
showError('Ошибка простого API: ' + response.error);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('❌ Simple API failed:', error);
|
||
console.error('❌ Response:', xhr.responseText);
|
||
|
||
// Если простой 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';
|
||
const encodedFileName = encodeURIComponent(fileName);
|
||
const filePath = `/crm/crm2/CRM_Active_Files/Documents/${recordId}/${encodedFileName}`;
|
||
|
||
const urls = {
|
||
'correct_path': fileId ? `${baseUrl}/apps/files/files/${fileId}?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=true` : `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}`,
|
||
'collabora_path': `${baseUrl}/apps/richdocuments/open?path=${filePath}`,
|
||
'onlyoffice_path': `${baseUrl}/apps/onlyoffice/open?path=${filePath}`,
|
||
'files_manager': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}`,
|
||
'collabora_id': fileId ? `${baseUrl}/apps/richdocuments/index?fileId=${fileId}` : null,
|
||
'onlyoffice_id': fileId ? `${baseUrl}/apps/onlyoffice?fileId=${fileId}` : null,
|
||
'files_app': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=${encodedFileName}&action=edit`,
|
||
'simple_files': `${baseUrl}/apps/files/?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}`,
|
||
'download_direct': `${baseUrl}/remote.php/dav/files/admin${filePath}`,
|
||
'view_only': `${baseUrl}/apps/files/files/${fileId}?dir=/crm/crm2/CRM_Active_Files/Documents/${recordId}&openfile=true&view=1`
|
||
};
|
||
|
||
// Убираем null значения
|
||
Object.keys(urls).forEach(key => {
|
||
if (urls[key] === null) {
|
||
delete urls[key];
|
||
}
|
||
});
|
||
|
||
return {
|
||
all: urls,
|
||
recommended: urls.correct_path
|
||
};
|
||
}
|
||
|
||
function getEditUrls(recordId, fileName, simpleData) {
|
||
console.log('🔗 Getting edit URLs...');
|
||
|
||
$.ajax({
|
||
url: '/crm_extensions/file_storage/api/get_edit_urls.php',
|
||
method: 'GET',
|
||
data: {
|
||
recordId: 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: '/crm_extensions/file_storage/api/prepare_edit.php',
|
||
method: 'GET',
|
||
data: {
|
||
recordId: 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>×</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');
|
||
}
|
||
|
||
// Автоматическое подключение при загрузке страницы
|
||
$(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');
|
||
}
|
||
}); |