From ebabe7e6d8211e1b6e8f979985ddfd86179b0223 Mon Sep 17 00:00:00 2001 From: Danil-Bodry Date: Sat, 18 Apr 2026 12:25:58 +0300 Subject: [PATCH] up --- frontend/src/views/AdminSettings.vue | 135 +++++++++++++++--- .../java/su/xserver/iikocon/MainVerticle.java | 14 ++ .../su/xserver/iikocon/SettingsService.java | 106 ++++++++++++++ 3 files changed, 237 insertions(+), 18 deletions(-) diff --git a/frontend/src/views/AdminSettings.vue b/frontend/src/views/AdminSettings.vue index 1f065e8..41e4048 100644 --- a/frontend/src/views/AdminSettings.vue +++ b/frontend/src/views/AdminSettings.vue @@ -2,36 +2,135 @@

Application Settings

-
-
- - + +
+ + + + + + + + + +
+ + Enabled +
+ + + + +

+ {{ field.description }} +

+
+ +
+ +
- + +
+ {{ message }} +
diff --git a/src/main/java/su/xserver/iikocon/MainVerticle.java b/src/main/java/su/xserver/iikocon/MainVerticle.java index 82d731c..cc48843 100644 --- a/src/main/java/su/xserver/iikocon/MainVerticle.java +++ b/src/main/java/su/xserver/iikocon/MainVerticle.java @@ -304,6 +304,20 @@ public class MainVerticle extends AbstractVerticle { .onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage())); }); + // Получить метаданные всех настроек (для построения формы) + router.get("/api/settings/meta").handler(rc -> { + settingsService.getMetadata() + .onSuccess(meta -> rc.response().putHeader("Content-Type", "application/json").end(meta.encode())) + .onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage())); + }); + +// Получить все настройки со значениями по умолчанию + router.get("/api/settings/all").handler(rc -> { + settingsService.getAllWithDefaults() + .onSuccess(settings -> rc.response().putHeader("Content-Type", "application/json").end(settings.encode())) + .onFailure(err -> rc.response().setStatusCode(500).end(err.getMessage())); + }); + // Обновление настроек (админ) router.put("/api/admin/settings").handler(rc -> { JsonObject body = rc.body().asJsonObject(); diff --git a/src/main/java/su/xserver/iikocon/SettingsService.java b/src/main/java/su/xserver/iikocon/SettingsService.java index d48c3b2..7b8abdf 100644 --- a/src/main/java/su/xserver/iikocon/SettingsService.java +++ b/src/main/java/su/xserver/iikocon/SettingsService.java @@ -1,6 +1,7 @@ package su.xserver.iikocon; import io.vertx.core.Future; +import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.templates.SqlTemplate; @@ -12,6 +13,111 @@ public class SettingsService { public SettingsService(Pool pool) { this.pool = pool; } + public Future getMetadata() { + JsonArray meta = new JsonArray(); + meta.add(new JsonObject() + .put("key", "site_name") + .put("label", "Site Name") + .put("description", "The name of the application shown in the header and title") + .put("type", "text") + .put("required", true) + ); + meta.add(new JsonObject() + .put("key", "site_description") + .put("label", "Site Description") + .put("description", "Brief description for SEO and meta tags") + .put("type", "textarea") + .put("rows", 2) + ); + meta.add(new JsonObject() + .put("key", "theme") + .put("label", "Theme") + .put("description", "Default color scheme") + .put("type", "select") + .put("options", new JsonArray() + .add(new JsonObject().put("value", "light").put("label", "Light")) + .add(new JsonObject().put("value", "dark").put("label", "Dark")) + .add(new JsonObject().put("value", "auto").put("label", "Auto (system preference)")) + ) + ); + meta.add(new JsonObject() + .put("key", "items_per_page") + .put("label", "Items Per Page") + .put("description", "Number of items shown in tables") + .put("type", "number") + .put("required", true) + ); + meta.add(new JsonObject() + .put("key", "enable_registration") + .put("label", "Allow Public Registration") + .put("description", "If disabled, only admin can create users") + .put("type", "boolean") + ); + meta.add(new JsonObject() + .put("key", "maintenance_mode") + .put("label", "Maintenance Mode") + .put("description", "When enabled, only admins can access the site") + .put("type", "boolean") + ); + meta.add(new JsonObject() + .put("key", "default_language") + .put("label", "Default Language") + .put("description", "Interface language") + .put("type", "select") + .put("options", new JsonArray() + .add(new JsonObject().put("value", "en").put("label", "English")) + .add(new JsonObject().put("value", "ru").put("label", "Русский")) + .add(new JsonObject().put("value", "es").put("label", "Español")) + ) + ); + meta.add(new JsonObject() + .put("key", "session_timeout_minutes") + .put("label", "Session Timeout (minutes)") + .put("description", "How long until inactive users are logged out") + .put("type", "number") + .put("required", true) + ); + meta.add(new JsonObject() + .put("key", "logo_url") + .put("label", "Logo URL") + .put("description", "Path or URL to custom logo image") + .put("type", "text") + ); + return Future.succeededFuture(meta); + } + + public Future getAllWithDefaults() { + return getAll().compose(values -> { + JsonObject result = new JsonObject(); + // Получаем метаданные, чтобы знать ключи + return getMetadata().map(meta -> { + for (Object item : meta) { + JsonObject m = (JsonObject) item; + String key = m.getString("key"); + String defaultValue = getDefaultValueByKey(key); + String current = values.getString(key); + result.put(key, current != null ? current : defaultValue); + } + return result; + }); + }); + } + + private String getDefaultValueByKey(String key) { + return switch (key) { + case "site_name" -> "Admin Panel"; + case "site_description" -> ""; + case "theme" -> "light"; + case "items_per_page" -> "20"; + case "enable_registration" -> "true"; + case "maintenance_mode" -> "false"; + case "default_language" -> "en"; + case "session_timeout_minutes" -> "60"; + case "logo_url" -> ""; + default -> ""; + }; + } + public Future initDatabase() { String createTable = """ CREATE TABLE IF NOT EXISTS app_settings (