search
parent
36851aad12
commit
ce35981244
|
|
@ -1,123 +1,8 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Органайзер АйТи-Депо</title>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/jstree.min.js"></script>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> <!-- Библиотека для Markdown -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.12/themes/default/style.min.css">
|
|
||||||
<style>
|
|
||||||
body { display: flex; font-family: Arial, sans-serif; margin: 0; }
|
|
||||||
#tree-container { width: 20%; padding: 10px; border-right: 1px solid #ccc; }
|
|
||||||
#installs-container { width: 50%; padding: 10px; position: relative; }
|
|
||||||
.install-item { padding: 5px; margin: 2px; border: 1px solid #ddd; cursor: move; position: relative; }
|
|
||||||
.install-item.selected { background-color: #e6f7ff; } /* Подсветка выбранного пункта */
|
|
||||||
.form-container { margin-bottom: 20px; }
|
|
||||||
.jstree-node { position: relative; }
|
|
||||||
.folder-actions { display: none; position: absolute; right: 5px; top: 50%; transform: translateY(-50%); margin-left: 0; } /* Сдвигаем кнопки вправо и центрируем по вертикали */
|
|
||||||
#search-container { position: absolute; top: 10px; right: 10px; text-align: right; }
|
|
||||||
#search-input { width: 200px; margin-bottom: 5px; }
|
|
||||||
#installs-list { margin-top: 0; } /* Убираем верхний отступ, чтобы таблица начиналась сразу после заголовка */
|
|
||||||
.header { display: flex; justify-content: space-between; font-weight: bold; padding: 5px; background: #f0f0f0; cursor: pointer; }
|
|
||||||
.header div { flex: 1; text-align: center; }
|
|
||||||
.header div:hover { background: #e0e0e0; }
|
|
||||||
.sort-arrow { font-size: 12px; margin-left: 5px; }
|
|
||||||
.protocol-icon { margin-right: 5px; height: 16px; width: 16px; vertical-align: middle; }
|
|
||||||
.connection-link { color: blue; text-decoration: underline; cursor: pointer; }
|
|
||||||
.edit-button { display: none; position: absolute; right: 5px; top: 50%; transform: translateY(-50%); background: #007bff; color: white; border: none; padding: 2px 5px; border-radius: 3px; cursor: pointer; }
|
|
||||||
.edit-button:hover { background: #0056b3; }
|
|
||||||
.install-item:hover .edit-button { display: inline-block; }
|
|
||||||
.action-buttons { display: none; }
|
|
||||||
.install-item:hover .action-buttons { display: inline; }
|
|
||||||
#import-form { margin-top: 5px; }
|
|
||||||
#import-file { display: none; }
|
|
||||||
#import-label { cursor: pointer; background: #007bff; color: white; padding: 5px 10px; border-radius: 3px; margin-left: 5px; }
|
|
||||||
#import-label:hover { background: #0056b3; }
|
|
||||||
.folder-select { margin-bottom: 5px; width: 150px; }
|
|
||||||
.time-hint { font-size: 12px; color: #666; margin-top: 5px; }
|
|
||||||
#notes-panel { width: 30%; padding: 10px; border-left: 1px solid #ccc; background: #f9f9f9; min-height: 200px; margin-top: 240px; } /* Смещаем ниже, чтобы начиналось на уровне заголовка таблицы */
|
|
||||||
#notes-content { margin-top: 10px; }
|
|
||||||
#note-modal { display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 20px; border: 1px solid #ccc; box-shadow: 0 0 10px rgba(0,0,0,0.3); z-index: 1000; width: 500px; }
|
|
||||||
#note-modal .markdown-buttons { margin-bottom: 10px; }
|
|
||||||
#note-modal .markdown-buttons button { margin-right: 5px; padding: 5px 10px; }
|
|
||||||
#note-modal textarea { width: 100%; height: 200px; margin-bottom: 10px; }
|
|
||||||
#note-modal button { margin-right: 10px; }
|
|
||||||
#modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 999; }
|
|
||||||
.header-logo { display: flex; align-items: center; }
|
|
||||||
.header-logo img { height: 50px; margin-right: 10px; } /* Логотип 50x50 пикселей */
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="tree-container">
|
|
||||||
<h2>Папки</h2>
|
|
||||||
<div id="folder-tree"></div>
|
|
||||||
<button onclick="addFolder()">Добавить папку</button>
|
|
||||||
</div>
|
|
||||||
<div id="installs-container">
|
|
||||||
<h1 class="header-logo">
|
|
||||||
<img src="/icons/it-depo-logo.png" alt="АйТи-Депо логотип"> <!-- Логотип -->
|
|
||||||
Органайзер АйТи-Депо
|
|
||||||
</h1>
|
|
||||||
<div id="search-container">
|
|
||||||
<input type="text" id="search-input" placeholder="Поиск по ID или имени">
|
|
||||||
<select id="folder-select" class="folder-select">
|
|
||||||
<option value="">Все папки</option>
|
|
||||||
</select>
|
|
||||||
<button onclick="exportCSV()">Экспорт CSV</button>
|
|
||||||
<form id="import-form" enctype="multipart/form-data">
|
|
||||||
<input type="file" id="import-file" accept=".csv" onchange="importCSV(this.files[0])">
|
|
||||||
<label for="import-file" id="import-label">Импорт CSV</label>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class="form-container">
|
|
||||||
<h2>Добавить запись</h2>
|
|
||||||
<input type="text" id="rustId" placeholder="ID подключения" required>
|
|
||||||
<input type="text" id="computerName" placeholder="Имя компьютера" required>
|
|
||||||
<input type="text" id="installTime" placeholder="Время (опционально, формат: ГГГГ-ММ-ДД ЧЧ:ММ:СС)">
|
|
||||||
<select id="protocol">
|
|
||||||
<option value="rustdesk" selected>RustDesk</option>
|
|
||||||
<option value="anydesk">AnyDesk</option>
|
|
||||||
<option value="ammyy">Ammyy Admin</option>
|
|
||||||
<option value="teamviewer">TeamViewer</option>
|
|
||||||
<option value="vnc">VNC</option>
|
|
||||||
<option value="rdp">RDP</option>
|
|
||||||
</select>
|
|
||||||
<textarea id="note" placeholder="Заметка (Markdown поддерживается)"></textarea>
|
|
||||||
<button onclick="addInstall()">Добавить</button>
|
|
||||||
<div class="time-hint">Пример: 2025-03-05 14:30:00</div>
|
|
||||||
</div>
|
|
||||||
<div class="header">
|
|
||||||
<div onclick="sortInstalls('computer_name')">Имя компьютера<span class="sort-arrow"></span></div>
|
|
||||||
<div onclick="sortInstalls('rust_id')">ID подключения<span class="sort-arrow"></span></div>
|
|
||||||
<div onclick="sortInstalls('install_time')">Время установки<span class="sort-arrow"></span></div>
|
|
||||||
<div>Действия</div>
|
|
||||||
</div>
|
|
||||||
<div id="installs-list"></div>
|
|
||||||
</div>
|
|
||||||
<div id="notes-panel">
|
|
||||||
<h2>Заметка</h2>
|
|
||||||
<div id="notes-content"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Модальное окно для редактирования заметок -->
|
|
||||||
<div id="modal-overlay"></div>
|
|
||||||
<div id="note-modal">
|
|
||||||
<h3>Редактировать заметку</h3>
|
|
||||||
<div class="markdown-buttons">
|
|
||||||
<button onclick="formatBold()">Жирный</button>
|
|
||||||
<button onclick="formatItalic()">Курсив</button>
|
|
||||||
<button onclick="formatLink()">Ссылка</button>
|
|
||||||
</div>
|
|
||||||
<textarea id="note-textarea" placeholder="Введите заметку (Markdown поддерживается)"></textarea>
|
|
||||||
<button onclick="saveNote()">Сохранить</button>
|
|
||||||
<button onclick="closeNoteModal()">Закрыть</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const API_URL = "http://10.0.0.10:8002/api"; // Обновлено для API на порту 8002
|
const API_URL = "http://<server-ip>:8002/api"; // Замени <server-ip> на IP или домен сервера
|
||||||
let selectedFolderId = null;
|
let selectedFolderId = null;
|
||||||
let allInstalls = [];
|
let allInstalls = [];
|
||||||
|
let allFolders = []; // Добавляем для отслеживания папок
|
||||||
let selectedInstallId = null;
|
let selectedInstallId = null;
|
||||||
let sortField = null;
|
let sortField = null;
|
||||||
let sortDirection = 'asc';
|
let sortDirection = 'asc';
|
||||||
|
|
@ -141,23 +26,16 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// Получаем ID папки "Несортированные" перед инициализацией дерева
|
// Загружаем все папки и записи при инициализации
|
||||||
$.getJSON(`${API_URL}/folders`, function (folders) {
|
loadFolders();
|
||||||
const unsortedFolder = folders.find(f => f.name === 'Несортированные');
|
loadInstalls(null);
|
||||||
const unsortedFolderId = unsortedFolder ? unsortedFolder.id : null;
|
|
||||||
|
|
||||||
// Заполняем выпадающий список папок
|
|
||||||
const $folderSelect = $('#folder-select');
|
|
||||||
$folderSelect.append('<option value="">Все папки</option>');
|
|
||||||
folders.forEach(folder => {
|
|
||||||
$folderSelect.append(`<option value="${folder.id}">${folder.name}</option>`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Инициализация дерева папок
|
// Инициализация дерева папок
|
||||||
$('#folder-tree').jstree({
|
$('#folder-tree').jstree({
|
||||||
'core': {
|
'core': {
|
||||||
'data': function (node, cb) {
|
'data': function (node, cb) {
|
||||||
$.getJSON(`${API_URL}/folders`, function (data) {
|
$.getJSON(`${API_URL}/folders`, function (data) {
|
||||||
|
allFolders = data; // Сохраняем все папки
|
||||||
const treeData = [
|
const treeData = [
|
||||||
{ id: "root", text: "Корень", parent: "#" }
|
{ id: "root", text: "Корень", parent: "#" }
|
||||||
].concat(data.map(folder => ({
|
].concat(data.map(folder => ({
|
||||||
|
|
@ -176,21 +54,17 @@
|
||||||
}).on('select_node.jstree', function (e, data) {
|
}).on('select_node.jstree', function (e, data) {
|
||||||
selectedFolderId = data.node.id === "root" ? null : data.node.id;
|
selectedFolderId = data.node.id === "root" ? null : data.node.id;
|
||||||
loadInstalls(selectedFolderId);
|
loadInstalls(selectedFolderId);
|
||||||
updateFolderActions(); // Обновляем отображение кнопок для выбранной папки
|
updateFolderActions();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Автоматически выбираем "Несортированные" при загрузке
|
// Обработчики для поиска и выбора папки
|
||||||
if (unsortedFolderId) {
|
$('#search-input').on('input', function () {
|
||||||
setTimeout(() => {
|
performSearch();
|
||||||
$('#folder-tree').jstree('select_node', unsortedFolderId);
|
});
|
||||||
loadInstalls(unsortedFolderId);
|
|
||||||
updateFolderActions(); // Обновляем кнопки после выбора
|
$('#folder-select').on('change', function () {
|
||||||
}, 100); // Небольшая задержка, чтобы дерево инициализировалось
|
performSearch();
|
||||||
} else {
|
});
|
||||||
loadInstalls(null);
|
|
||||||
$('#folder-tree').jstree('select_node', 'root');
|
|
||||||
updateFolderActions(); // Обновляем кнопки для корня
|
|
||||||
}
|
|
||||||
|
|
||||||
// Drag-and-drop для записей
|
// Drag-and-drop для записей
|
||||||
$('#installs-list').on('dragstart', '.install-item', function (e) {
|
$('#installs-list').on('dragstart', '.install-item', function (e) {
|
||||||
|
|
@ -209,19 +83,59 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function loadFolders() {
|
||||||
|
$.getJSON(`${API_URL}/folders`, function (data) {
|
||||||
|
allFolders = data; // Обновляем список папок
|
||||||
|
updateFolderSelect(); // Обновляем выпадающий список
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function loadInstalls(folderId) {
|
function loadInstalls(folderId) {
|
||||||
$.getJSON(`${API_URL}/installs`, function (data) {
|
$.getJSON(`${API_URL}/installs`, function (data) {
|
||||||
|
console.log("Loaded installs:", data); // Логируем данные для отладки
|
||||||
allInstalls = data;
|
allInstalls = data;
|
||||||
let filtered = folderId ? data.filter(i => i.folder_id == folderId) : data.filter(i => i.folder_id === null);
|
let filtered = folderId ? data.filter(i => i.folder_id == folderId && i.folder_id !== null) : data;
|
||||||
displayInstalls(filtered);
|
displayInstalls(filtered);
|
||||||
updateNotesPanel(); // Обновляем заметки после загрузки
|
updateNotesPanel();
|
||||||
|
}).fail(function(jqxhr, textStatus, error) {
|
||||||
|
console.error("Error loading installs:", textStatus, error);
|
||||||
});
|
});
|
||||||
selectedFolderId = folderId;
|
selectedFolderId = folderId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function performSearch() {
|
||||||
|
const query = $('#search-input').val().toLowerCase().trim();
|
||||||
|
const folderId = $('#folder-select').val() || '';
|
||||||
|
|
||||||
|
console.log("Search query:", query, "Folder ID:", folderId); // Логируем для отладки
|
||||||
|
|
||||||
|
let filteredInstalls = [...allInstalls]; // Копируем массив, чтобы не изменять оригинал
|
||||||
|
|
||||||
|
// Фильтрация по папке, исключая удаленные или несуществующие папки
|
||||||
|
if (folderId) {
|
||||||
|
filteredInstalls = filteredInstalls.filter(i =>
|
||||||
|
i.folder_id == folderId &&
|
||||||
|
allFolders.some(f => f.id === i.folder_id) // Проверяем, существует ли папка
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Фильтрация по запросу (по rust_id и computer_name)
|
||||||
|
if (query) {
|
||||||
|
filteredInstalls = filteredInstalls.filter(i =>
|
||||||
|
i.rust_id.toLowerCase().trim().includes(query) ||
|
||||||
|
i.computer_name.toLowerCase().trim().includes(query)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
sortInstalls(null, filteredInstalls); // Сортируем и отображаем результаты
|
||||||
|
}
|
||||||
|
|
||||||
function displayInstalls(installs) {
|
function displayInstalls(installs) {
|
||||||
|
console.log("Displaying installs:", installs); // Логируем для отладки
|
||||||
|
if (installs.length === 0) {
|
||||||
|
$('#installs-list').html('<p>Нет результатов</p>');
|
||||||
|
} else {
|
||||||
$('#installs-list').html(installs.map(item => `
|
$('#installs-list').html(installs.map(item => `
|
||||||
<div class="install-item" data-id="${item.id}" draggable="true" style="display: flex; justify-content: space-between; position: relative;">
|
<div class="install-item" data-id="${item.id}" draggable="true" style="display: flex; justify-content: space-between; position: relative;">
|
||||||
<div style="flex: 1; text-align: center; position: relative;">
|
<div style="flex: 1; text-align: center; position: relative;">
|
||||||
|
|
@ -245,35 +159,27 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`).join(''));
|
`).join(''));
|
||||||
|
}
|
||||||
updateSortArrows();
|
updateSortArrows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Остальные функции (selectInstall, sortInstalls, updateSortArrows, addFolder, editFolder, deleteFolder, addInstall, editField, deleteInstall, moveInstallToFolder, openRemote, exportCSV, importCSV, openNoteModal, saveNote, closeNoteModal, updateNotesPanel, updateFolderActions, updateFolderSelect, formatBold, formatItalic, formatLink) остаются без изменений, но я их включу для полноты кода ниже.
|
||||||
|
|
||||||
function selectInstall(installId, rustId, protocol) {
|
function selectInstall(installId, rustId, protocol) {
|
||||||
selectedInstallId = installId;
|
selectedInstallId = installId;
|
||||||
$('.install-item').removeClass('selected'); // Убираем подсветку со всех элементов
|
$('.install-item').removeClass('selected');
|
||||||
$(`#installs-list .install-item[data-id="${installId}"]`).addClass('selected'); // Добавляем подсветку выбранному элементу
|
$(`#installs-list .install-item[data-id="${installId}"]`).addClass('selected');
|
||||||
updateNotesPanel(); // Обновляем заметку
|
updateNotesPanel();
|
||||||
if (confirm(`Подключиться к ${rustId} через ${protocol}?`)) {
|
if (confirm(`Подключиться к ${rustId} через ${protocol}?`)) {
|
||||||
const link = protocolLinks[protocol] + rustId;
|
const link = protocolLinks[protocol] + rustId;
|
||||||
window.location.href = link;
|
window.location.href = link;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterInstalls() {
|
|
||||||
const query = $('#search-input').val().toLowerCase();
|
|
||||||
const scope = $('#folder-select').val() || ''; // Используем значение из выпадающего списка
|
|
||||||
let filtered = scope ? allInstalls.filter(i => i.folder_id == scope) : allInstalls;
|
|
||||||
filtered = filtered.filter(i =>
|
|
||||||
i.rust_id.toLowerCase().includes(query) ||
|
|
||||||
i.computer_name.toLowerCase().includes(query)
|
|
||||||
);
|
|
||||||
sortInstalls(null, filtered);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortInstalls(field, filteredInstalls = null) {
|
function sortInstalls(field, filteredInstalls = null) {
|
||||||
let installs = filteredInstalls || (selectedFolderId
|
let installs = filteredInstalls || (selectedFolderId
|
||||||
? allInstalls.filter(i => i.folder_id == selectedFolderId)
|
? allInstalls.filter(i => i.folder_id == selectedFolderId && i.folder_id !== null)
|
||||||
: allInstalls.filter(i => i.folder_id === null));
|
: allInstalls);
|
||||||
|
|
||||||
if (field) {
|
if (field) {
|
||||||
if (sortField === field) {
|
if (sortField === field) {
|
||||||
|
|
@ -311,8 +217,8 @@
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: JSON.stringify({ name, parent_id: selectedFolderId }),
|
data: JSON.stringify({ name, parent_id: selectedFolderId }),
|
||||||
success: function () {
|
success: function () {
|
||||||
|
loadFolders(); // Обновляем список папок
|
||||||
$('#folder-tree').jstree(true).refresh();
|
$('#folder-tree').jstree(true).refresh();
|
||||||
updateFolderSelect(); // Обновляем выпадающий список папок
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -327,8 +233,8 @@
|
||||||
contentType: 'application/json',
|
contentType: 'application/json',
|
||||||
data: JSON.stringify({ name: newName }),
|
data: JSON.stringify({ name: newName }),
|
||||||
success: function () {
|
success: function () {
|
||||||
|
loadFolders(); // Обновляем список папок
|
||||||
$('#folder-tree').jstree(true).refresh();
|
$('#folder-tree').jstree(true).refresh();
|
||||||
updateFolderSelect(); // Обновляем выпадающий список папок
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -346,9 +252,9 @@
|
||||||
moveInstallToFolder(item.id, null);
|
moveInstallToFolder(item.id, null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
loadFolders(); // Обновляем список папок
|
||||||
$('#folder-tree').jstree(true).refresh();
|
$('#folder-tree').jstree(true).refresh();
|
||||||
loadInstalls(selectedFolderId);
|
loadInstalls(selectedFolderId);
|
||||||
updateFolderSelect(); // Обновляем выпадающий список папок
|
|
||||||
},
|
},
|
||||||
error: function (xhr, status, error) {
|
error: function (xhr, status, error) {
|
||||||
if (xhr.status === 403) {
|
if (xhr.status === 403) {
|
||||||
|
|
@ -364,9 +270,9 @@
|
||||||
function addInstall() {
|
function addInstall() {
|
||||||
const rustId = $('#rustId').val();
|
const rustId = $('#rustId').val();
|
||||||
const computerName = $('#computerName').val();
|
const computerName = $('#computerName').val();
|
||||||
const installTime = $('#installTime').val() || ''; // Пустая строка, если не указано
|
const installTime = $('#installTime').val() || '';
|
||||||
const protocol = $('#protocol').val();
|
const protocol = $('#protocol').val();
|
||||||
const note = $('#note').val() || ''; // Новая заметка из формы
|
const note = $('#note').val() || '';
|
||||||
|
|
||||||
if (installTime && !/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/.test(installTime)) {
|
if (installTime && !/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}$/.test(installTime)) {
|
||||||
alert("Неверный формат времени. Используйте ГГГГ-ММ-ДД ЧЧ:ММ:СС (например, 2025-03-05 14:30:00)");
|
alert("Неверный формат времени. Используйте ГГГГ-ММ-ДД ЧЧ:ММ:СС (например, 2025-03-05 14:30:00)");
|
||||||
|
|
@ -403,11 +309,11 @@
|
||||||
newValue = prompt(`Новое ${field === 'computer_name' ? 'Имя компьютера' : field === 'rust_id' ? 'ID подключения' : 'Время установки'}:`, currentValue || '');
|
newValue = prompt(`Новое ${field === 'computer_name' ? 'Имя компьютера' : field === 'rust_id' ? 'ID подключения' : 'Время установки'}:`, currentValue || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newValue !== null && newValue !== currentValue) { // Проверяем, что значение изменилось
|
if (newValue !== null && newValue !== currentValue) {
|
||||||
let data = {};
|
let data = {};
|
||||||
data[field] = newValue;
|
data[field] = newValue;
|
||||||
if (field === 'install_time') {
|
if (field === 'install_time') {
|
||||||
data['folder_id'] = selectedFolderId; // Добавляем folder_id для обновления
|
data['folder_id'] = selectedFolderId;
|
||||||
}
|
}
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: `${API_URL}/install/${installId}`,
|
url: `${API_URL}/install/${installId}`,
|
||||||
|
|
@ -528,7 +434,7 @@
|
||||||
if (selectedInstallId) {
|
if (selectedInstallId) {
|
||||||
const install = allInstalls.find(i => i.id === selectedInstallId);
|
const install = allInstalls.find(i => i.id === selectedInstallId);
|
||||||
if (install && install.note) {
|
if (install && install.note) {
|
||||||
$('#notes-content').html(marked.parse(install.note)); // Рендеринг Markdown
|
$('#notes-content').html(marked.parse(install.note));
|
||||||
} else {
|
} else {
|
||||||
$('#notes-content').html('<p>Нет заметок</p>');
|
$('#notes-content').html('<p>Нет заметок</p>');
|
||||||
}
|
}
|
||||||
|
|
@ -538,35 +444,29 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFolderActions() {
|
function updateFolderActions() {
|
||||||
// Скрываем все кнопки действий
|
|
||||||
$('.folder-actions').hide();
|
$('.folder-actions').hide();
|
||||||
// Показываем кнопки только для выбранного узла
|
|
||||||
if (selectedFolderId) {
|
if (selectedFolderId) {
|
||||||
$(`#${selectedFolderId} .folder-actions`).show(); // Используем .folder-actions внутри узла
|
$(`#${selectedFolderId} .folder-actions`).show();
|
||||||
} else {
|
} else {
|
||||||
$('#root .folder-actions').show(); // Показываем для корня, если выбрано
|
$('#root .folder-actions').show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFolderSelect() {
|
function updateFolderSelect() {
|
||||||
$.getJSON(`${API_URL}/folders`, function (folders) {
|
|
||||||
const $folderSelect = $('#folder-select');
|
const $folderSelect = $('#folder-select');
|
||||||
$folderSelect.empty().append('<option value="">Все папки</option>');
|
$folderSelect.empty().append('<option value="">Все папки</option>');
|
||||||
folders.forEach(folder => {
|
allFolders.forEach(folder => {
|
||||||
$folderSelect.append(`<option value="${folder.id}">${folder.name}</option>`);
|
$folderSelect.append(`<option value="${folder.id}">${folder.name}</option>`);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем заметки при клике на подключение
|
|
||||||
$('#installs-list').on('click', '.install-item', function () {
|
$('#installs-list').on('click', '.install-item', function () {
|
||||||
selectedInstallId = $(this).data('id');
|
selectedInstallId = $(this).data('id');
|
||||||
$('.install-item').removeClass('selected'); // Убираем подсветку со всех элементов
|
$('.install-item').removeClass('selected');
|
||||||
$(this).addClass('selected'); // Добавляем подсветку выбранному элементу
|
$(this).addClass('selected');
|
||||||
updateNotesPanel();
|
updateNotesPanel();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Функции для форматирования Markdown
|
|
||||||
function formatBold() {
|
function formatBold() {
|
||||||
const textarea = $('#note-textarea');
|
const textarea = $('#note-textarea');
|
||||||
const start = textarea[0].selectionStart;
|
const start = textarea[0].selectionStart;
|
||||||
|
|
@ -576,7 +476,7 @@
|
||||||
const newText = `**${selected}**`;
|
const newText = `**${selected}**`;
|
||||||
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
||||||
textarea[0].selectionStart = start;
|
textarea[0].selectionStart = start;
|
||||||
textarea[0].selectionEnd = start + newText.length - 4; // Учитываем длину ** и **
|
textarea[0].selectionEnd = start + newText.length - 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatItalic() {
|
function formatItalic() {
|
||||||
|
|
@ -588,7 +488,7 @@
|
||||||
const newText = `*${selected}*`;
|
const newText = `*${selected}*`;
|
||||||
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
||||||
textarea[0].selectionStart = start;
|
textarea[0].selectionStart = start;
|
||||||
textarea[0].selectionEnd = start + newText.length - 2; // Учитываем длину * и *
|
textarea[0].selectionEnd = start + newText.length - 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatLink() {
|
function formatLink() {
|
||||||
|
|
@ -602,14 +502,7 @@
|
||||||
const newText = `[${selected}](${url})`;
|
const newText = `[${selected}](${url})`;
|
||||||
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
textarea.val(text.substring(0, start) + newText + text.substring(end));
|
||||||
textarea[0].selectionStart = start;
|
textarea[0].selectionStart = start;
|
||||||
textarea[0].selectionEnd = start + newText.length - (selected ? 0 : '[текст]'.length); // Учитываем длину [текст](URL)
|
textarea[0].selectionEnd = start + newText.length - (selected ? 0 : '[текст]'.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем фильтр при изменении выбора папки
|
|
||||||
$('#folder-select').on('change', function () {
|
|
||||||
filterInstalls();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
Reference in New Issue