Большое обновление GUI интерфейс

Большое обновление GUI интерфейс

- Добавлен фраемворr Walles
- Удалена консольная версия
- Проработан интерфейс и дизайн
- Добавлено кеширование для быстрой реакции.
- Сделан .ps1 сборщик для удобной сборки проекта.
- Обновлён Readme
This commit is contained in:
2025-11-14 08:40:25 +07:00
parent 752f294392
commit 02ae56b78c
93 changed files with 7477 additions and 3504 deletions

View File

@@ -0,0 +1,101 @@
/* ============================================
Modal Manager
Управление модальными окнами
============================================ */
import { $, addClass, removeClass } from '../utils/dom.js';
/**
* Класс для управления модальными окнами
*/
export class Modal {
constructor() {
this.overlay = $('modalOverlay');
this.title = $('modalTitle');
this.content = $('modalContent');
this.closeBtn = $('modalCloseBtn');
this.cancelBtn = $('modalCancelBtn');
this.saveBtn = $('modalSaveBtn');
this.fieldEditorOverlay = $('fieldEditorOverlay');
this.init();
}
init() {
if (this.closeBtn) {
this.closeBtn.addEventListener('click', () => this.close());
}
if (this.cancelBtn) {
this.cancelBtn.addEventListener('click', () => this.close());
}
if (this.saveBtn) {
this.saveBtn.addEventListener('click', () => {
if (window.saveModalData) {
window.saveModalData();
}
});
}
if (this.overlay) {
this.overlay.addEventListener('click', (e) => {
if (e.target === this.overlay) {
this.close();
}
});
}
}
/**
* Открыть модальное окно
* @param {string} title - Заголовок
* @param {string} htmlContent - HTML контент
*/
open(title, htmlContent) {
if (this.title) this.title.textContent = title;
if (this.content) this.content.innerHTML = htmlContent;
if (this.overlay) addClass(this.overlay, 'show');
}
/**
* Закрыть модальное окно
*/
close() {
if (this.overlay) removeClass(this.overlay, 'show');
}
/**
* Установить обработчик сохранения
* @param {Function} callback - Функция обратного вызова
*/
onSave(callback) {
if (this.saveBtn) {
this.saveBtn.onclick = callback;
}
}
/**
* Открыть редактор поля
* @param {string} title - Заголовок
* @param {string} htmlContent - HTML контент
*/
openFieldEditor(title, htmlContent) {
const fieldTitle = $('fieldEditorTitle');
const fieldContent = $('fieldEditorContent');
if (fieldTitle) fieldTitle.textContent = title;
if (fieldContent) fieldContent.innerHTML = htmlContent;
if (this.fieldEditorOverlay) addClass(this.fieldEditorOverlay, 'show');
}
/**
* Закрыть редактор поля
*/
closeFieldEditor() {
if (this.fieldEditorOverlay) removeClass(this.fieldEditorOverlay, 'show');
}
}
// Глобальный экземпляр модального окна
export const modal = new Modal();

View File

@@ -0,0 +1,67 @@
/* ============================================
Navigation
Управление навигацией
============================================ */
import { $, $$, hide, show, removeClass, addClass } from '../utils/dom.js';
/**
* Класс для управления навигацией
*/
export class Navigation {
constructor() {
this.navItems = $$('.nav-item');
this.sections = {
services: $('sectionServices'),
sites: $('sectionSites'),
proxy: $('sectionProxy'),
settings: $('sectionSettings'),
vaccess: $('sectionVAccessEditor')
};
this.init();
}
init() {
this.navItems.forEach((item, index) => {
item.addEventListener('click', () => this.navigate(index));
});
}
navigate(index) {
// Убираем active со всех навигационных элементов
this.navItems.forEach(nav => removeClass(nav, 'active'));
addClass(this.navItems[index], 'active');
// Скрываем все секции
this.hideAllSections();
// Показываем нужные секции
if (index === 0) {
// Главная - всё кроме настроек
show(this.sections.services);
show(this.sections.sites);
show(this.sections.proxy);
} else if (index === 3) {
// Настройки
show(this.sections.settings);
// Загружаем конфигурацию при открытии
if (window.loadConfig) {
window.loadConfig();
}
}
}
hideAllSections() {
Object.values(this.sections).forEach(section => {
if (section) hide(section);
});
}
showDashboard() {
this.hideAllSections();
show(this.sections.services);
show(this.sections.sites);
show(this.sections.proxy);
}
}

View File

@@ -0,0 +1,81 @@
/* ============================================
Notification System
Система уведомлений
============================================ */
import { $, addClass, removeClass } from '../utils/dom.js';
/**
* Класс для управления уведомлениями
*/
export class NotificationManager {
constructor() {
this.container = $('notification');
this.loader = $('appLoader');
}
/**
* Показать уведомление
* @param {string} message - Текст сообщения
* @param {string} type - Тип (success, error)
* @param {number} duration - Длительность показа (мс)
*/
show(message, type = 'success', duration = 1000) {
if (!this.container) return;
const icon = type === 'success'
? '<i class="fas fa-check-circle"></i>'
: '<i class="fas fa-exclamation-circle"></i>';
this.container.innerHTML = `
<div class="notification-content">
<div class="notification-icon">${icon}</div>
<div class="notification-text">${message}</div>
</div>
`;
this.container.className = `notification show ${type}`;
setTimeout(() => {
removeClass(this.container, 'show');
}, duration);
}
/**
* Показать успешное уведомление
* @param {string} message - Текст сообщения
* @param {number} duration - Длительность
*/
success(message, duration = 1000) {
this.show(message, 'success', duration);
}
/**
* Показать уведомление об ошибке
* @param {string} message - Текст сообщения
* @param {number} duration - Длительность
*/
error(message, duration = 2000) {
this.show(message, 'error', duration);
}
/**
* Скрыть загрузчик приложения
*/
hideLoader() {
if (!this.loader) return;
setTimeout(() => {
addClass(this.loader, 'hide');
setTimeout(() => {
if (this.loader.parentNode) {
this.loader.remove();
}
}, 500);
}, 1500);
}
}
// Глобальный экземпляр менеджера уведомлений
export const notification = new NotificationManager();

View File

@@ -0,0 +1,51 @@
/* ============================================
Window Controls
Управление окном приложения
============================================ */
import { $, addClass } from '../utils/dom.js';
/**
* Класс для управления окном
*/
export class WindowControls {
constructor() {
this.minimizeBtn = $('minimizeBtn');
this.maximizeBtn = $('maximizeBtn');
this.closeBtn = $('closeBtn');
this.init();
}
init() {
if (this.minimizeBtn) {
this.minimizeBtn.addEventListener('click', () => this.minimize());
}
if (this.maximizeBtn) {
this.maximizeBtn.addEventListener('click', () => this.maximize());
}
if (this.closeBtn) {
this.closeBtn.addEventListener('click', () => this.close());
}
}
minimize() {
if (window.runtime?.WindowMinimise) {
window.runtime.WindowMinimise();
}
}
maximize() {
if (window.runtime?.WindowToggleMaximise) {
window.runtime.WindowToggleMaximise();
}
}
close() {
if (window.runtime?.Quit) {
window.runtime.Quit();
}
}
}