mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-08-24 16:05:07 +03:00
Refactor configuration editor to always display line numbers and update UI elements for better user experience. Replace toggle functionality with a fixed display of line numbers. Enhance notification messages and confirmation dialogs with translation support for improved localization.
This commit is contained in:
parent
9e11f76fc3
commit
1c61269877
5 changed files with 179 additions and 117 deletions
|
@ -15,6 +15,12 @@ function initJSONEditor() {
|
||||||
// Update line numbers
|
// Update line numbers
|
||||||
updateLineNumbers();
|
updateLineNumbers();
|
||||||
|
|
||||||
|
// Always enable line numbers since toggle was removed
|
||||||
|
const editorWrapper = document.querySelector('.editor-wrapper');
|
||||||
|
if (editorWrapper) {
|
||||||
|
editorWrapper.classList.add('with-line-numbers');
|
||||||
|
}
|
||||||
|
|
||||||
// Add event listeners
|
// Add event listeners
|
||||||
textarea.addEventListener('input', function() {
|
textarea.addEventListener('input', function() {
|
||||||
updateLineNumbers();
|
updateLineNumbers();
|
||||||
|
@ -58,20 +64,7 @@ function syncLineNumbers() {
|
||||||
lineNumbersContainer.scrollTop = textarea.scrollTop;
|
lineNumbersContainer.scrollTop = textarea.scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle line numbers visibility
|
|
||||||
function toggleLineNumbers() {
|
|
||||||
const checkbox = document.getElementById('line-numbers');
|
|
||||||
const lineNumbersContainer = document.getElementById('line-numbers-container');
|
|
||||||
const editorWrapper = document.querySelector('.editor-wrapper');
|
|
||||||
|
|
||||||
if (checkbox.checked) {
|
|
||||||
lineNumbersContainer.style.display = 'block';
|
|
||||||
editorWrapper.classList.add('with-line-numbers');
|
|
||||||
} else {
|
|
||||||
lineNumbersContainer.style.display = 'none';
|
|
||||||
editorWrapper.classList.remove('with-line-numbers');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle special editor keydown events
|
// Handle special editor keydown events
|
||||||
function handleEditorKeydown(event) {
|
function handleEditorKeydown(event) {
|
||||||
|
@ -150,13 +143,13 @@ function updateEditorStatus() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (textarea.value.trim() === '') {
|
if (textarea.value.trim() === '') {
|
||||||
statusElement.textContent = 'Пустая конфигурация';
|
statusElement.innerHTML = '<span data-key="empty_config">Пустая конфигурация</span>';
|
||||||
statusElement.className = 'status-text warning';
|
statusElement.className = 'status-text warning';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON.parse(textarea.value);
|
JSON.parse(textarea.value);
|
||||||
statusElement.textContent = 'Валидный JSON';
|
statusElement.innerHTML = '<span data-key="valid_json"></span>';
|
||||||
statusElement.className = 'status-text success';
|
statusElement.className = 'status-text success';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
statusElement.textContent = `Ошибка JSON: ${error.message}`;
|
statusElement.textContent = `Ошибка JSON: ${error.message}`;
|
||||||
|
@ -176,7 +169,7 @@ function updateCursorPosition() {
|
||||||
const line = beforeCursor.split('\n').length;
|
const line = beforeCursor.split('\n').length;
|
||||||
const column = beforeCursor.length - beforeCursor.lastIndexOf('\n');
|
const column = beforeCursor.length - beforeCursor.lastIndexOf('\n');
|
||||||
|
|
||||||
cursorElement.textContent = `Строка ${line}, Столбец ${column}`;
|
cursorElement.innerHTML = `<span data-key="line">Строка</span> ${line}, <span data-key="column">Столбец</span> ${column}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format JSON with proper indentation
|
// Format JSON with proper indentation
|
||||||
|
@ -191,7 +184,10 @@ function formatJSON() {
|
||||||
textarea.value = formatted;
|
textarea.value = formatted;
|
||||||
updateLineNumbers();
|
updateLineNumbers();
|
||||||
updateEditorStatus();
|
updateEditorStatus();
|
||||||
showNotification('JSON отформатирован', 'success');
|
const formattedMessage = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['json_formatted']
|
||||||
|
? window.translations[currentLanguage]['json_formatted']
|
||||||
|
: 'JSON отформатирован';
|
||||||
|
showNotification(formattedMessage, 'success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showNotification(`Ошибка форматирования: ${error.message}`, 'error');
|
showNotification(`Ошибка форматирования: ${error.message}`, 'error');
|
||||||
}
|
}
|
||||||
|
@ -205,7 +201,10 @@ function validateJSON() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSON.parse(textarea.value);
|
JSON.parse(textarea.value);
|
||||||
showNotification('JSON конфигурация валидна', 'success');
|
const validationMessage = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['json_validation_success']
|
||||||
|
? window.translations[currentLanguage]['json_validation_success']
|
||||||
|
: 'JSON конфигурация валидна';
|
||||||
|
showNotification(validationMessage, 'success');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
showNotification(`Ошибка валидации JSON: ${error.message}`, 'error');
|
showNotification(`Ошибка валидации JSON: ${error.message}`, 'error');
|
||||||
}
|
}
|
||||||
|
@ -246,9 +245,15 @@ async function saveConfiguration(restart = false) {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
currentConfigJSON = textarea.value;
|
currentConfigJSON = textarea.value;
|
||||||
if (restart) {
|
if (restart) {
|
||||||
showNotification('Конфигурация сохранена. Сервер перезапускается...', 'success');
|
const restartMessage = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['config_saved_restarting']
|
||||||
|
? window.translations[currentLanguage]['config_saved_restarting']
|
||||||
|
: 'Конфигурация сохранена. Сервер перезапускается...';
|
||||||
|
showNotification(restartMessage, 'success');
|
||||||
} else {
|
} else {
|
||||||
showNotification('Конфигурация сохранена успешно', 'success');
|
const successMessage = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['config_saved_success']
|
||||||
|
? window.translations[currentLanguage]['config_saved_success']
|
||||||
|
: 'Конфигурация сохранена успешно';
|
||||||
|
showNotification(successMessage, 'success');
|
||||||
}
|
}
|
||||||
onConfigChange(); // Update button states
|
onConfigChange(); // Update button states
|
||||||
} else {
|
} else {
|
||||||
|
@ -262,11 +267,22 @@ async function saveConfiguration(restart = false) {
|
||||||
|
|
||||||
// Save configuration and restart server
|
// Save configuration and restart server
|
||||||
async function saveAndRestartConfiguration() {
|
async function saveAndRestartConfiguration() {
|
||||||
const confirmation = confirm('Сохранить конфигурацию и перезапустить сервер?\n\nВнимание: Соединение будет прервано на время перезапуска.');
|
const title = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['save_and_restart_title']
|
||||||
|
? window.translations[currentLanguage]['save_and_restart_title']
|
||||||
|
: 'Сохранить и перезапустить';
|
||||||
|
|
||||||
if (confirmation) {
|
const message = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['save_and_restart_message']
|
||||||
await saveConfiguration(true);
|
? window.translations[currentLanguage]['save_and_restart_message']
|
||||||
}
|
: 'Сохранить конфигурацию и перезапустить сервер?\n\nВнимание: Соединение будет прервано на время перезапуска.';
|
||||||
|
|
||||||
|
showConfirmModal({
|
||||||
|
title: title,
|
||||||
|
message: message,
|
||||||
|
type: 'danger',
|
||||||
|
onConfirm: async () => {
|
||||||
|
await saveConfiguration(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh configuration from server
|
// Refresh configuration from server
|
||||||
|
@ -275,18 +291,31 @@ async function refreshConfiguration() {
|
||||||
|
|
||||||
// Check if there are unsaved changes
|
// Check if there are unsaved changes
|
||||||
if (textarea && textarea.value !== currentConfigJSON) {
|
if (textarea && textarea.value !== currentConfigJSON) {
|
||||||
const confirmation = confirm('У вас есть несохраненные изменения. Продолжить обновление?');
|
const title = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['refresh_unsaved_changes_title']
|
||||||
if (!confirmation) {
|
? window.translations[currentLanguage]['refresh_unsaved_changes_title']
|
||||||
return;
|
: 'Несохраненные изменения';
|
||||||
}
|
|
||||||
|
const message = window.translations && window.translations[currentLanguage] && window.translations[currentLanguage]['refresh_unsaved_changes_message']
|
||||||
|
? window.translations[currentLanguage]['refresh_unsaved_changes_message']
|
||||||
|
: 'У вас есть несохраненные изменения. Продолжить обновление?';
|
||||||
|
|
||||||
|
showConfirmModal({
|
||||||
|
title: title,
|
||||||
|
message: message,
|
||||||
|
type: 'warning',
|
||||||
|
onConfirm: async () => {
|
||||||
|
try {
|
||||||
|
await loadConfiguration();
|
||||||
|
showNotification('Конфигурация обновлена', 'success');
|
||||||
|
} catch (error) {
|
||||||
|
showNotification('Ошибка обновления конфигурации', 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
await loadConfiguration();
|
|
||||||
showNotification('Конфигурация обновлена', 'success');
|
|
||||||
} catch (error) {
|
|
||||||
showNotification('Ошибка обновления конфигурации', 'error');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update configuration status
|
// Update configuration status
|
||||||
|
|
|
@ -55,29 +55,10 @@ function renderConfigEditor() {
|
||||||
<span class="config-path" title="${configMeta.path}">${configMeta.path}</span>
|
<span class="config-path" title="${configMeta.path}">${configMeta.path}</span>
|
||||||
<span class="config-format ${configMeta.format}">${configMeta.format.toUpperCase()}</span>
|
<span class="config-format ${configMeta.format}">${configMeta.format.toUpperCase()}</span>
|
||||||
<span class="config-status ${configMeta.isWritable ? 'writable' : 'readonly'}">
|
<span class="config-status ${configMeta.isWritable ? 'writable' : 'readonly'}">
|
||||||
${configMeta.isWritable ? '✏️ Редактируемый' : '🔒 Только чтение'}
|
${configMeta.isWritable ? '✏️ <span data-key="editable">Редактируемый</span>' : '🔒 <span data-key="readonly">Только чтение</span>'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="config-actions">
|
|
||||||
<button onclick="refreshConfiguration()" class="action-btn refresh-btn" data-key="refresh">
|
|
||||||
🔄 Обновить
|
|
||||||
</button>
|
|
||||||
<button onclick="formatJSON()" class="action-btn format-btn" data-key="format">
|
|
||||||
📝 Форматировать
|
|
||||||
</button>
|
|
||||||
<button onclick="validateJSON()" class="action-btn validate-btn" data-key="validate">
|
|
||||||
✓ Проверить
|
|
||||||
</button>
|
|
||||||
${configMeta.isWritable ? `
|
|
||||||
<button onclick="saveConfiguration()" class="action-btn save-btn" data-key="save_config">
|
|
||||||
💾 Сохранить
|
|
||||||
</button>
|
|
||||||
<button onclick="saveAndRestartConfiguration()" class="action-btn restart-btn" data-key="save_and_restart">
|
|
||||||
🔄 Сохранить и перезапустить
|
|
||||||
</button>
|
|
||||||
` : ''}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="config-editor-container">
|
<div class="config-editor-container">
|
||||||
|
@ -85,10 +66,25 @@ function renderConfigEditor() {
|
||||||
<div class="editor-header">
|
<div class="editor-header">
|
||||||
<span class="editor-title" data-key="json_configuration">JSON Конфигурация</span>
|
<span class="editor-title" data-key="json_configuration">JSON Конфигурация</span>
|
||||||
<div class="editor-controls">
|
<div class="editor-controls">
|
||||||
<span class="line-numbers-toggle">
|
<div class="action-buttons-group">
|
||||||
<input type="checkbox" id="line-numbers" checked onchange="toggleLineNumbers()">
|
<div onclick="refreshConfiguration()" class="action-btn">
|
||||||
<label for="line-numbers" data-key="line_numbers">Номера строк</label>
|
<span data-key="refresh">Обновить</span>
|
||||||
</span>
|
</div>
|
||||||
|
<div onclick="formatJSON()" class="action-btn">
|
||||||
|
<span data-key="format">Форматировать</span>
|
||||||
|
</div>
|
||||||
|
<div onclick="validateJSON()" class="action-btn">
|
||||||
|
<span data-key="validate">Проверить</span>
|
||||||
|
</div>
|
||||||
|
${configMeta.isWritable ? `
|
||||||
|
<div onclick="saveConfiguration()" class="action-btn">
|
||||||
|
<span data-key="save_config">Сохранить</span>
|
||||||
|
</div>
|
||||||
|
<div onclick="saveAndRestartConfiguration()" class="action-btn">
|
||||||
|
<span data-key="save_and_restart">Сохранить и перезапустить</span>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor-wrapper">
|
<div class="editor-wrapper">
|
||||||
|
|
|
@ -108,7 +108,7 @@ window.translations.en = {
|
||||||
'format': 'Format',
|
'format': 'Format',
|
||||||
'validate': 'Validate',
|
'validate': 'Validate',
|
||||||
'json_configuration': 'JSON Configuration',
|
'json_configuration': 'JSON Configuration',
|
||||||
'line_numbers': 'Line Numbers',
|
|
||||||
'config_save_success': 'Configuration saved successfully',
|
'config_save_success': 'Configuration saved successfully',
|
||||||
'config_save_error': 'Error saving configuration',
|
'config_save_error': 'Error saving configuration',
|
||||||
'config_load_error': 'Error loading configuration',
|
'config_load_error': 'Error loading configuration',
|
||||||
|
@ -116,5 +116,27 @@ window.translations.en = {
|
||||||
'config_save_confirm_title': 'Confirm Save',
|
'config_save_confirm_title': 'Confirm Save',
|
||||||
'config_save_confirm_text': 'Are you sure you want to save changes to the configuration file?',
|
'config_save_confirm_text': 'Are you sure you want to save changes to the configuration file?',
|
||||||
'config_backup_info': 'Backup will be created automatically',
|
'config_backup_info': 'Backup will be created automatically',
|
||||||
'config_warning': '⚠️ Warning: Incorrect configuration may cause node failure!'
|
'config_warning': '⚠️ Warning: Incorrect configuration may cause node failure!',
|
||||||
|
|
||||||
|
// Editor status translations
|
||||||
|
'editable': 'Editable',
|
||||||
|
'readonly': 'Read Only',
|
||||||
|
'empty_config': 'Empty Configuration',
|
||||||
|
'valid_json': 'Valid JSON',
|
||||||
|
'line': 'Line',
|
||||||
|
'column': 'Column',
|
||||||
|
|
||||||
|
// Configuration save messages
|
||||||
|
'config_saved_restarting': 'Configuration saved. Server is restarting...',
|
||||||
|
'config_saved_success': 'Configuration saved successfully',
|
||||||
|
|
||||||
|
// Validation messages
|
||||||
|
'json_validation_success': 'JSON configuration is valid',
|
||||||
|
'json_formatted': 'JSON formatted',
|
||||||
|
|
||||||
|
// Confirmation dialogs
|
||||||
|
'save_and_restart_title': 'Save and Restart',
|
||||||
|
'save_and_restart_message': 'Save configuration and restart server?\n\nWarning: Connection will be interrupted during restart.',
|
||||||
|
'refresh_unsaved_changes_title': 'Unsaved Changes',
|
||||||
|
'refresh_unsaved_changes_message': 'You have unsaved changes. Continue refreshing?'
|
||||||
};
|
};
|
|
@ -108,7 +108,7 @@ window.translations.ru = {
|
||||||
'format': 'Форматировать',
|
'format': 'Форматировать',
|
||||||
'validate': 'Проверить',
|
'validate': 'Проверить',
|
||||||
'json_configuration': 'JSON Конфигурация',
|
'json_configuration': 'JSON Конфигурация',
|
||||||
'line_numbers': 'Номера строк',
|
|
||||||
'config_save_success': 'Конфигурация сохранена успешно',
|
'config_save_success': 'Конфигурация сохранена успешно',
|
||||||
'config_save_error': 'Ошибка сохранения конфигурации',
|
'config_save_error': 'Ошибка сохранения конфигурации',
|
||||||
'config_load_error': 'Ошибка загрузки конфигурации',
|
'config_load_error': 'Ошибка загрузки конфигурации',
|
||||||
|
@ -116,5 +116,27 @@ window.translations.ru = {
|
||||||
'config_save_confirm_title': 'Подтверждение сохранения',
|
'config_save_confirm_title': 'Подтверждение сохранения',
|
||||||
'config_save_confirm_text': 'Вы уверены, что хотите сохранить изменения в конфигурационный файл?',
|
'config_save_confirm_text': 'Вы уверены, что хотите сохранить изменения в конфигурационный файл?',
|
||||||
'config_backup_info': 'Резервная копия будет создана автоматически',
|
'config_backup_info': 'Резервная копия будет создана автоматически',
|
||||||
'config_warning': '⚠️ Внимание: Неправильная конфигурация может привести к сбою работы узла!'
|
'config_warning': '⚠️ Внимание: Неправильная конфигурация может привести к сбою работы узла!',
|
||||||
|
|
||||||
|
// Editor status translations
|
||||||
|
'editable': 'Редактируемый',
|
||||||
|
'readonly': 'Только чтение',
|
||||||
|
'empty_config': 'Пустая конфигурация',
|
||||||
|
'valid_json': 'Валидный JSON',
|
||||||
|
'line': 'Строка',
|
||||||
|
'column': 'Столбец',
|
||||||
|
|
||||||
|
// Configuration save messages
|
||||||
|
'config_saved_restarting': 'Конфигурация сохранена. Сервер перезапускается...',
|
||||||
|
'config_saved_success': 'Конфигурация сохранена успешно',
|
||||||
|
|
||||||
|
// Validation messages
|
||||||
|
'json_validation_success': 'JSON конфигурация валидна',
|
||||||
|
'json_formatted': 'JSON отформатирован',
|
||||||
|
|
||||||
|
// Confirmation dialogs
|
||||||
|
'save_and_restart_title': 'Сохранить и перезапустить',
|
||||||
|
'save_and_restart_message': 'Сохранить конфигурацию и перезапустить сервер?\n\nВнимание: Соединение будет прервано на время перезапуска.',
|
||||||
|
'refresh_unsaved_changes_title': 'Несохраненные изменения',
|
||||||
|
'refresh_unsaved_changes_message': 'У вас есть несохраненные изменения. Продолжить обновление?'
|
||||||
};
|
};
|
|
@ -1539,7 +1539,6 @@ button[onclick="copyNodeKey()"]:hover {
|
||||||
|
|
||||||
/* Configuration Editor Styles */
|
/* Configuration Editor Styles */
|
||||||
.config-container {
|
.config-container {
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
@ -1556,6 +1555,11 @@ button[onclick="copyNodeKey()"]:hover {
|
||||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.config-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.config-info h3 {
|
.config-info h3 {
|
||||||
margin: 0 0 10px 0;
|
margin: 0 0 10px 0;
|
||||||
color: var(--text-heading);
|
color: var(--text-heading);
|
||||||
|
@ -1617,31 +1621,7 @@ button[onclick="copyNodeKey()"]:hover {
|
||||||
color: var(--text-warning);
|
color: var(--text-warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.refresh-btn {
|
|
||||||
background: var(--bg-nav-active);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-btn {
|
|
||||||
background: var(--bg-success-dark);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-btn.modified {
|
|
||||||
background: var(--bg-warning-dark);
|
|
||||||
animation: pulse 2s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pulse {
|
|
||||||
0% { opacity: 1; }
|
|
||||||
50% { opacity: 0.7; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configuration Groups */
|
/* Configuration Groups */
|
||||||
.config-groups {
|
.config-groups {
|
||||||
|
@ -1943,17 +1923,7 @@ input:checked + .slider:before {
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line-numbers-toggle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
font-size: 0.9em;
|
|
||||||
color: var(--text-muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-numbers-toggle input[type="checkbox"] {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor-wrapper {
|
.editor-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -2050,24 +2020,34 @@ input:checked + .slider:before {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Additional action buttons */
|
/* Action buttons group */
|
||||||
.format-btn {
|
.action-buttons-group {
|
||||||
background: var(--bg-nav-active);
|
display: flex;
|
||||||
color: white;
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.validate-btn {
|
.action-buttons-group .action-btn {
|
||||||
background: var(--bg-warning-dark);
|
background: var(--bg-nav-item);
|
||||||
color: white;
|
color: var(--text-nav);
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
margin: 0;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.restart-btn {
|
.action-buttons-group .action-btn:hover {
|
||||||
background: var(--text-error);
|
background: var(--bg-nav-hover);
|
||||||
color: white;
|
transform: translateY(-1px);
|
||||||
}
|
|
||||||
|
|
||||||
.restart-btn:hover {
|
|
||||||
background: #c62828;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* JSON Syntax highlighting (basic) */
|
/* JSON Syntax highlighting (basic) */
|
||||||
|
@ -2105,13 +2085,16 @@ input:checked + .slider:before {
|
||||||
padding-left: 45px;
|
padding-left: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.config-actions {
|
.action-buttons-group {
|
||||||
flex-wrap: wrap;
|
flex-direction: row;
|
||||||
|
gap: 4px;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-btn {
|
.action-buttons-group .action-btn {
|
||||||
flex: 1;
|
flex: none;
|
||||||
min-width: 120px;
|
min-width: auto;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2127,4 +2110,14 @@ input:checked + .slider:before {
|
||||||
[data-theme="dark"] .json-editor {
|
[data-theme="dark"] .json-editor {
|
||||||
background: var(--bg-info-card);
|
background: var(--bg-info-card);
|
||||||
color: var(--text-body);
|
color: var(--text-body);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme support for action buttons */
|
||||||
|
[data-theme="dark"] .action-buttons-group .action-btn {
|
||||||
|
color: var(--text-nav);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .action-buttons-group .action-btn:hover {
|
||||||
|
background: var(--bg-nav-hover);
|
||||||
|
transform: translateY(-1px);
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue