import $ from 'jquery'; import { JSONRPC } from '@/json-rpc.js'; // --- Глобальное состояние --- let tokens = []; /** * @private * Загружает текущий список токенов. * @returns {Promise} */ async function loadTokens() { try { // Запрос списка токенов tokens = await JSONRPC.Auth.listTokens(); tokens = tokens || []; return true; } catch (e) { console.error("Ошибка при загрузке токенов:", e); tokens = []; return false; } } /** * @private * Рендерит список токенов и кнопки управления. */ function renderTokenList() { const $listContainer = $('#api-token-container'); // Кнопка "Создать токен" const createButtonHtml = ` `; if (tokens.length === 0) { $listContainer.html(createButtonHtml + '

Активных API токенов не найдено.

'); attachEventHandlers(); return; } let listHtml = tokens.map(item => { // Мы НЕ показываем полный токен, показываем только его начало/конец для идентификации const displayToken = item.token ? `${item.token.substring(0, 8)}...${item.token.substring(item.token.length - 4)}` : 'Неизвестный токен'; return `
  • ${item.description}
    Ключ: ${displayToken}
  • `; }).join(''); const html = ` ${createButtonHtml} `; $listContainer.html(html); attachEventHandlers(); } /** * @private * Отображает модальное окно для создания токена. */ function showCreateTokenModal() { // Используем простое модальное окно jQuery для минимализма const description = prompt("Введите описание для нового API токена (например, 'Токен для Telegram бота'):"); if (description === null) { return; // Пользователь нажал Отмена } if (description.trim() === "") { alert("Описание токена не может быть пустым."); return; } createToken(description.trim()); } /** * @private * Логика создания токена и обновления UI. * @param {string} description - Описание токена. */ async function createToken(description) { const $btn = $('#create-token-btn'); const $message = $('#token-status-message'); $message.hide().removeClass('error-message').addClass('success-message'); $btn.prop('disabled', true).text('Создание...'); try { const newTokenValue = await JSONRPC.Auth.createAPIToken(description); if (!newTokenValue) { throw new Error("Сервер не вернул токен."); } // Показываем токен пользователю ОДИН раз prompt("ВАЖНО: Ваш новый токен API. Сохраните его, он больше не будет показан!", newTokenValue); // Перезагружаем список await loadTokens(); renderTokenList(); $message.text(`Токен "${description}" успешно создан.`).show(); } catch (e) { console.error('Ошибка создания токена:', e); $message.removeClass('success-message').addClass('error-message').text('Ошибка при создании токена.').show(); } finally { $btn.prop('disabled', false).text('Создать токен API'); setTimeout(() => $message.fadeOut(), 8000); } } /** * @private * Логика удаления токена. * @param {string} token - Токен для удаления. */ async function deleteToken(token) { if (!confirm("Вы уверены, что хотите удалить этот API токен?")) { return; } const $item = $(`li.token-item[data-full-token="${token}"]`); $item.addClass('deleting').css('opacity', 0.5); // Визуальная обратная связь try { await JSONRPC.Auth.removeToken(token); // Удаляем из локального состояния tokens = tokens.filter(item => item.token !== token); // Перерисовываем список renderTokenList(); const $message = $('#token-status-message'); $message.text('Токен успешно удален.').addClass('success-message').show(); } catch (e) { console.error('Ошибка удаления токена:', e); $item.removeClass('deleting').css('opacity', 1); // Восстанавливаем, если ошибка const $message = $('#token-status-message'); $message.removeClass('success-message').addClass('error-message').text('Ошибка при удалении токена.').show(); } } /** * @private * Прикрепление обработчиков событий. */ function attachEventHandlers() { $('#create-token-btn').off('click').on('click', showCreateTokenModal); // Делегирование для кнопок удаления (они перерисовываются) $('#api-token-container').off('click', '.delete-token-btn').on('click', '.delete-token-btn', function() { const tokenToDelete = $(this).data('token'); if (tokenToDelete) { deleteToken(tokenToDelete); } }); } // --- Функции для роутера --- export const APITokensPage = { render: () => { return `

    API Токены

    Загрузка токенов...

    `; }, mount: async () => { const success = await loadTokens(); if (success) { renderTokenList(); } else { $('#api-token-container').html('

    Не удалось загрузить токены. Проверьте соединение с сервером.

    '); } }, unmount: () => { tokens = []; $('#api-token-container').off(); // Удаляем все обработчики } };