修复问题

This commit is contained in:
2026-08-09 15:30:12 +08:00
parent 6fe0bed78e
commit 4b9dd5c199
15 changed files with 616 additions and 278 deletions
+279 -41
View File
@@ -6,6 +6,7 @@
#include "adminive/adapters/nlohmann_json.hpp"
#include <algorithm>
#include <charconv>
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
@@ -71,9 +72,61 @@ struct Source_Feed_Relation_Row {
std::string feed_key;
std::string feed_name;
};
struct External_Resource_Row {
std::string name;
std::string description;
std::string download_url;
std::uint64_t update_interval_seconds{};
std::int64_t last_updated_at{};
std::size_t row_count{};
std::string state;
};
struct Backend_Config_Row {
std::string section;
std::string path;
std::string value;
};
}
namespace adminive {
template <>
struct Type_Descriptor<ecap::adminive_config::External_Resource_Row> {
static auto get() {
using T = ecap::adminive_config::External_Resource_Row;
return object<T>("external_resource", "外部数据源管理",
ADMINIVE_FIELD_LABEL(T, name, "数据表"),
ADMINIVE_FIELD_LABEL(T, description, "说明"),
ADMINIVE_FIELD_LABEL(T, download_url, "在线来源"),
ADMINIVE_FIELD_LABEL(T, update_interval_seconds, "建议更新周期(秒)"),
ADMINIVE_FIELD_LABEL(T, last_updated_at, "上次更新时间"),
ADMINIVE_FIELD_LABEL(T, row_count, "行数"),
ADMINIVE_FIELD_LABEL(T, state, "状态"));
}
};
template <>
struct Type_View_Descriptor<ecap::adminive_config::External_Resource_Row> {
static Table_View table() {
using T = ecap::adminive_config::External_Resource_Row;
return table_view<T>(column<&T::name>("数据表").search(), column<&T::description>("说明"), column<&T::download_url>("在线来源"), column<&T::row_count>("行数").sort(), column<&T::last_updated_at>("上次更新时间").sort(), column<&T::update_interval_seconds>("建议更新周期(秒)"), column<&T::state>("状态")).titled("外部数据源管理");
}
};
template <>
struct Type_Descriptor<ecap::adminive_config::Backend_Config_Row> {
static auto get() {
using T = ecap::adminive_config::Backend_Config_Row;
return object<T>("backend_config", "后端完整配置",
ADMINIVE_FIELD_LABEL(T, section, "配置分区"),
ADMINIVE_FIELD_LABEL(T, path, "配置项"),
ADMINIVE_FIELD_LABEL(T, value, "当前值"));
}
};
template <>
struct Type_View_Descriptor<ecap::adminive_config::Backend_Config_Row> {
static Table_View table() {
using T = ecap::adminive_config::Backend_Config_Row;
return table_view<T>(column<&T::section>("配置分区").filter(), column<&T::path>("配置项").search(), column<&T::value>("当前值")).titled("后端完整配置(只读)");
}
};
template <>
struct Type_Descriptor<ecap::adminive_config::Data_Source_Row> {
static auto get() {
using T = ecap::adminive_config::Data_Source_Row;
@@ -274,6 +327,38 @@ adminive::Resource_Transaction<Data_feed_Config_Data> data_feed_settings_transac
};
return transaction;
}
adminive::Resource_Transaction<Map_View_Config> map_view_transaction(Global* global) {
adminive::Resource_Transaction<Map_View_Config> transaction;
transaction.prepare = [global](const Map_View_Config& value, const adminive::Request_Context&) {
if(!Map_View_Config::is_scene_mode(value.scene_mode))
throw adminive::Field_Validation_Error("scene_mode", "场景模式必须为 2d 或 3d");
global->map_resources_config.read([&](const auto& resources) {
if(!resources.is_imagery_key(value.map2d.current_imagery_key))
throw adminive::Field_Validation_Error("map2d.current_imagery_key", "影像源不存在");
if(!resources.is_terrain_key(value.map2d.current_terrain_key))
throw adminive::Field_Validation_Error("map2d.current_terrain_key", "地形源不存在");
if(!resources.is_imagery_key(value.map3d.current_imagery_key))
throw adminive::Field_Validation_Error("map3d.current_imagery_key", "影像源不存在");
if(!resources.is_terrain_key(value.map3d.current_terrain_key))
throw adminive::Field_Validation_Error("map3d.current_terrain_key", "地形源不存在");
});
};
transaction.commit = [global](const Map_View_Config& value, const adminive::Request_Context&) {
global->map_resources_config.write([&](auto& resources) {
resources.current_imagery_key = value.scene_mode == "2d" ? value.map2d.current_imagery_key : value.map3d.current_imagery_key;
});
Config::save(Config_Section::map_view, value.to_base_json());
Config::save(Config_Section::map_resources);
};
transaction.rollback = [global](const Map_View_Config& value, const adminive::Request_Context&) {
global->map_resources_config.write([&](auto& resources) {
resources.current_imagery_key = value.scene_mode == "2d" ? value.map2d.current_imagery_key : value.map3d.current_imagery_key;
});
Config::save(Config_Section::map_view, value.to_base_json());
Config::save(Config_Section::map_resources);
};
return transaction;
}
void save_data_sources(Global* global) {
auto patch = Psc::JSON::object();
patch.append({"data_source", global->mode_acs.data_source_config.to_json()});
@@ -404,32 +489,39 @@ Data_Source_Row source_row(const std::shared_ptr<Data_Source>& source) {
row.key = source->key;
row.type = source_type(source->type);
row.enable = source->enabled();
row.config = source->settings.snapshot();
source->settings.read([&](const auto& value) {
row.config = value;
});
row.state = Psc::to_string(source->state);
if(const auto source_value = dynamic_cast<TCP_Client_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.ip = value.ip;
row.port = value.port;
source_value->specific.read([&](const auto& value) {
row.ip = value.ip;
row.port = value.port;
});
} else if(const auto source_value = dynamic_cast<Serial_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.port_name = value.port_name;
row.baud_rate = value.baud_rate;
source_value->specific.read([&](const auto& value) {
row.port_name = value.port_name;
row.baud_rate = value.baud_rate;
});
} else if(const auto source_value = dynamic_cast<File_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.file_path = value.file_path;
row.data_type = value.data_type;
row.play_mode = value.play_mode;
source_value->specific.read([&](const auto& value) {
row.file_path = value.file_path;
row.data_type = value.data_type;
row.play_mode = value.play_mode;
});
} else if(const auto source_value = dynamic_cast<Dll_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.library_path = value.library_path;
row.function_name = value.function_name;
row.data_type = value.data_type;
row.buffer_size = value.buffer_size;
source_value->specific.read([&](const auto& value) {
row.library_path = value.library_path;
row.function_name = value.function_name;
row.data_type = value.data_type;
row.buffer_size = value.buffer_size;
});
} else if(const auto source_value = dynamic_cast<Shared_Memory_Data_Source*>(source.get())) {
const auto value = source_value->specific.snapshot();
row.shared_memory_name = value.shared_memory_name;
row.shared_memory_size = value.shared_memory_size;
row.data_type = value.data_type;
source_value->specific.read([&](const auto& value) {
row.shared_memory_name = value.shared_memory_name;
row.shared_memory_size = value.shared_memory_size;
row.data_type = value.data_type;
});
}
return row;
}
@@ -475,24 +567,31 @@ Data_Feed_Row feed_row(const std::shared_ptr<Data_Feed>& feed) {
row.key = feed->key;
row.type = feed_type(feed->type);
row.enable = feed->enabled();
row.output_format = feed->output_format.snapshot();
row.format = row.output_format.type;
feed->output_format.read([&](const auto& value) {
row.output_format = value;
row.format = value.type;
});
row.state = Psc::to_string(feed->state);
if(const auto feed_value = dynamic_cast<Data_Feed_TCP_Server*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.port = value.port;
row.connect_user_buffer_size = value.connect_user_buffer_size;
row.connect_system_buffer_size = value.connect_system_buffer_size;
feed_value->specific.read([&](const auto& value) {
row.port = value.port;
row.connect_user_buffer_size = value.connect_user_buffer_size;
row.connect_system_buffer_size = value.connect_system_buffer_size;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_UDP_Server*>(feed.get())) {
row.port = feed_value->specific.member<&Data_Feed_UDP_Server_Data::port>().snapshot();
feed_value->specific.read([&](const auto& value) {
row.port = value.port;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_TCP_Client*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.url = value.url;
row.port = value.port;
feed_value->specific.read([&](const auto& value) {
row.url = value.url;
row.port = value.port;
});
} else if(const auto feed_value = dynamic_cast<Data_Feed_UDP_Client*>(feed.get())) {
const auto value = feed_value->specific.snapshot();
row.url = value.url;
row.port = value.port;
feed_value->specific.read([&](const auto& value) {
row.url = value.url;
row.port = value.port;
});
}
return row;
}
@@ -525,13 +624,14 @@ void apply_feed_row(const std::shared_ptr<Data_Feed>& feed, const Data_Feed_Row&
}
Source_Feed_Relation_Row relation_row(const std::shared_ptr<Source_Feed_Relation>& relation) {
Source_Feed_Relation_Row row;
const auto value = relation->settings.snapshot();
row.key = relation->key;
row.type = relation_type(relation->type);
row.enable = value.enable;
row.source_key = value.source_key;
row.feed_key = value.feed_key;
row.feed_name = value.feed_name;
relation->settings.read([&](const auto& value) {
row.enable = value.enable;
row.source_key = value.source_key;
row.feed_key = value.feed_key;
row.feed_name = value.feed_name;
});
return row;
}
void apply_relation_row(const std::shared_ptr<Source_Feed_Relation>& relation, const Source_Feed_Relation_Row& row) {
@@ -570,6 +670,34 @@ std::vector<Source_Feed_Relation_Row> relation_rows(Global* global) {
rows.push_back(relation_row(relation));
return rows;
}
std::vector<External_Resource_Row> external_resource_rows(Global* global) {
std::map<std::string, External_Resource_Status> status_by_name;
for(auto status : global->external_resources_manager.external_database_status())
status_by_name.emplace(status.name, std::move(status));
const auto config = global->external_resources_manager.to_base_json();
const auto* list = config.get("list");
std::vector<External_Resource_Row> rows;
if(!list)
return rows;
rows.reserve(list->children.size());
for(const auto& item : list->children) {
External_Resources_Data value;
value.from_base_json(&item, false);
External_Resource_Row row;
row.name = value.name;
row.description = value.description;
row.download_url = value.download_url;
row.update_interval_seconds = value.update_interval_seconds;
row.last_updated_at = static_cast<std::int64_t>(value.last_updated_at);
const auto status = status_by_name.find(value.name);
if(status != status_by_name.end()) {
row.row_count = status->second.row_count;
row.state = status->second.message;
}
rows.push_back(std::move(row));
}
return rows;
}
Json source_amis_schema() {
return adminive::to_amis_table_schema<Json, Data_Source_Row>("/api/adminive/config/data_sources", adminive::describe_table_view<Data_Source_Row>());
}
@@ -579,11 +707,72 @@ Json feed_amis_schema() {
Json relation_amis_schema() {
return adminive::to_amis_table_schema<Json, Source_Feed_Relation_Row>("/api/adminive/config/source_feed_relations", adminive::describe_table_view<Source_Feed_Relation_Row>());
}
Json external_resource_amis_schema() {
auto schema = adminive::to_amis_table_schema<Json, External_Resource_Row>("/api/adminive/config/external_resources", adminive::describe_table_view<External_Resource_Row>());
auto& crud = schema["body"][0];
const std::string crud_id = "external_resource_table_crud";
crud["headerToolbar"] = Json::array({Json{{"type", "columns-toggler"}, {"draggable", true}}, "reload", Json{{"type", "button"}, {"label", "全部后端下载并导入"}, {"level", "primary"}, {"actionType", "ajax"}, {"api", Json{{"method", "post"}, {"url", "/api/refresh_external_databases"}}}, {"reload", crud_id}}});
auto& columns = crud["columns"];
if(!columns.empty())
columns.erase(columns.end() - 1);
const auto refresh_button = Json{{"type", "button"}, {"label", "后端下载并导入"}, {"level", "link"}, {"actionType", "ajax"}, {"api", Json{{"method", "post"}, {"url", "/api/refresh_external_database"}, {"data", Json{{"name", "${name}"}}}}}, {"reload", crud_id}};
const auto download_button = Json{{"type", "button"}, {"label", "前端下载"}, {"level", "link"}, {"actionType", "url"}, {"url", "${download_url}"}, {"blank", true}, {"disabledOn", "!this.download_url"}};
const auto upload_button = Json{{"type", "button"}, {"label", "离线导入"}, {"level", "link"}, {"actionType", "dialog"}, {"dialog", Json{{"title", "离线导入 ${name}"}, {"body", Json{{"type", "input-file"}, {"name", "file"}, {"label", "数据文件"}, {"accept", ".csv,.gz,.zip,.txt"}, {"receiver", Json{{"method", "post"}, {"url", "/api/upload_external_database"}, {"data", Json{{"name", "${name}"}}}}}}}}}};
const auto clear_button = Json{{"type", "button"}, {"label", "清空数据表"}, {"level", "link"}, {"className", "text-danger"}, {"actionType", "ajax"}, {"confirmText", "确定清空 ${name}"}, {"api", Json{{"method", "post"}, {"url", "/api/clear_external_database_table"}, {"data", Json{{"name", "${name}"}}}}}, {"reload", crud_id}};
columns.push_back(Json{{"type", "operation"}, {"label", "操作"}, {"buttons", Json::array({refresh_button, download_button, upload_button, clear_button})}});
return schema;
}
void append_backend_config_rows(const Json& value, const std::string& section, const std::string& path, std::vector<Backend_Config_Row>& rows) {
if(value.is_object() && !value.empty()) {
for(auto it = value.begin(); it != value.end(); ++it)
append_backend_config_rows(it.value(), section.empty() ? it.key() : section, path.empty() ? it.key() : path + "." + it.key(), rows);
return;
}
if(value.is_array() && !value.empty()) {
for(std::size_t i = 0; i < value.size(); ++i)
append_backend_config_rows(value[i], section, path + "[" + std::to_string(i) + "]", rows);
return;
}
rows.push_back({section, path, value.is_string() ? value.get<std::string>() : value.dump()});
}
std::vector<Backend_Config_Row> backend_config_rows(Global* global) {
const auto config = Json::parse(global->toJson().to_json_string());
std::vector<Backend_Config_Row> rows;
append_backend_config_rows(config, {}, {}, rows);
return rows;
}
Json backend_config_amis_schema() {
auto schema = adminive::to_amis_table_schema<Json, Backend_Config_Row>("/api/adminive/config/backend_config", adminive::describe_table_view<Backend_Config_Row>());
auto& crud = schema["body"][0];
crud["headerToolbar"] = Json::array({Json{{"type", "columns-toggler"}, {"draggable", true}}, "reload"});
auto& columns = crud["columns"];
if(!columns.empty())
columns.erase(columns.end() - 1);
return schema;
}
Json archive_operations_schema() {
const auto formats = Json::array({Json{{"label", "ZIP (.zip)"}, {"value", "zip"}, {"format", "zip"}, {"filter", ""}, {"extension", "zip"}}, Json{{"label", "TAR (.tar)"}, {"value", "tar"}, {"format", "pax"}, {"filter", ""}, {"extension", "tar"}}, Json{{"label", "TAR.GZ (.tar.gz)"}, {"value", "tar.gz"}, {"format", "pax"}, {"filter", "gzip"}, {"extension", "tar.gz"}}, Json{{"label", "TAR.XZ (.tar.xz)"}, {"value", "tar.xz"}, {"format", "pax"}, {"filter", "xz"}, {"extension", "tar.xz"}}, Json{{"label", "TAR.ZST (.tar.zst)"}, {"value", "tar.zst"}, {"format", "pax"}, {"filter", "zstd"}, {"extension", "tar.zst"}}, Json{{"label", "TAR.BZ2 (.tar.bz2)"}, {"value", "tar.bz2"}, {"format", "pax"}, {"filter", "bzip2"}, {"extension", "tar.bz2"}}, Json{{"label", "TAR.LZ4 (.tar.lz4)"}, {"value", "tar.lz4"}, {"format", "pax"}, {"filter", "lz4"}, {"extension", "tar.lz4"}}, Json{{"label", "7Z (.7z)"}, {"value", "7z"}, {"format", "7zip"}, {"filter", ""}, {"extension", "7z"}}});
return Json{{"title", "导入导出"}, {"formats", std::move(formats)}, {"exports", Json::array({Json{{"name", "版本"}, {"api", "/api/export_version"}, {"allow_version_selection", true}}, Json{{"name", "日志"}, {"api", "/api/export_logs"}, {"allow_version_selection", false}}})}, {"import_api", "/api/import_version"}, {"import_accept", ".tar.zstd,.tar.zst,.tar.gz,.tgz,.tar.xz,.txz,.tar.bz2,.tbz2,.tar.lz4,.zip,.7z,.rar,.tar,.cpio,.iso,.xar"}};
}
Json cesium_models_schema(Global* global) {
Json aircraft_types = Json::array();
global->map_model_config.read([&](const auto& config) {
for(const auto& [key, value] : config.aircraft_models) {
static_cast<void>(value);
aircraft_types.push_back(key);
}
});
return Json{{"title", "Cesium 模型设置"}, {"data_api", "/map/models"}, {"upload_accept", ".glb"}, {"aircraft_types", std::move(aircraft_types)}};
}
Json system_actions_schema() {
return Json{{"type", "panel"}, {"title", "设备操作"}, {"body", Json::array({Json{{"type", "button"}, {"label", "重启 FPGA 设备"}, {"level", "primary"}, {"actionType", "ajax"}, {"confirmText", "确定重启 FPGA 设备?"}, {"api", Json{{"method", "post"}, {"url", "/api/restart_device"}}}}})}};
}
class Adminive_Config_Resources {
public:
explicit Adminive_Config_Resources(Global* global) : global_(global),
mode_acs_resource_(global->mode_acs.settings, mode_acs_path, mode_acs_transaction()),
data_feed_settings_resource_(global->mode_acs.data_feed_config.settings, data_feed_settings_path, data_feed_settings_transaction()),
map_view_resource_(global->map_view_config, map_view_path, map_view_transaction(global)),
mlat_resource_(global->mlat.settings, mlat_path, value_section_transaction<MLAT_Config_Data>(Config_Section::mlat)),
cesium_graphics_resource_(global->cesium_graphics_config.settings, cesium_graphics_path, value_section_transaction<Cesium_Graphics_Config_Data>(Config_Section::cesium_graphics)) {
}
@@ -591,16 +780,49 @@ public:
auto& app = drogon::app();
mode_acs_resource_.bind(app);
data_feed_settings_resource_.bind(app);
map_view_resource_.bind(app);
mlat_resource_.bind(app);
cesium_graphics_resource_.bind(app);
bind_data_sources(app);
bind_data_feeds(app);
bind_relations(app);
bind_external_resources(app);
bind_backend_config(app);
app.registerHandler(manifest_path, [this](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(manifest())));
}, {drogon::Get});
}
private:
void bind_backend_config(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
app.registerHandler(backend_config_path + "/descriptor", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_descriptor_json<Json, Backend_Config_Row>())));
}, get);
app.registerHandler(backend_config_path + "/view", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_view_json<Json, Backend_Config_Row>(adminive::describe_table_view<Backend_Config_Row>()))));
}, get);
app.registerHandler(backend_config_path + "/amis", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(backend_config_amis_schema())));
}, get);
app.registerHandler(backend_config_path, [this](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(list_response<Backend_Config_Row>(backend_config_path, backend_config_rows(global_), read_collection_query(request))));
}, get);
}
void bind_external_resources(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
app.registerHandler(external_resources_path + "/descriptor", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_descriptor_json<Json, External_Resource_Row>())));
}, get);
app.registerHandler(external_resources_path + "/view", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(adminive::to_view_json<Json, External_Resource_Row>(adminive::describe_table_view<External_Resource_Row>()))));
}, get);
app.registerHandler(external_resources_path + "/amis", [](const drogon::HttpRequestPtr&, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(adminive::make_http_success<Json>(external_resource_amis_schema())));
}, get);
app.registerHandler(external_resources_path, [this](const drogon::HttpRequestPtr& request, std::function<void(const drogon::HttpResponsePtr&)>&& callback) {
callback(adminive::make_drogon_response(list_response<External_Resource_Row>(external_resources_path, external_resource_rows(global_), read_collection_query(request))));
}, get);
}
void bind_data_sources(drogon::HttpAppFramework& app) {
const auto get = adminive::make_drogon_constraints(drogon::Get, {});
const auto post = adminive::make_drogon_constraints(drogon::Post, {});
@@ -896,7 +1118,7 @@ private:
}, post);
}
Json manifest() const {
const auto view = adminive::composition_view("ecap_config", adminive::compose::frontend(adminive::compose::slot("mode_acs"), adminive::compose::slot("data_feed_settings"), adminive::compose::slot("data_sources"), adminive::compose::slot("data_feeds"), adminive::compose::slot("source_feed_relations"), adminive::compose::slot("mlat"), adminive::compose::slot("cesium_graphics"))).titled("ECAP 配置");
const auto view = adminive::composition_view("ecap_config", adminive::compose::frontend(adminive::compose::slot("mode_acs"), adminive::compose::slot("data_feed_settings"), adminive::compose::slot("data_sources"), adminive::compose::slot("data_feeds"), adminive::compose::slot("source_feed_relations"), adminive::compose::slot("mlat"), adminive::compose::slot("map_view"), adminive::compose::slot("cesium_graphics"), adminive::compose::slot("external_resources"), adminive::compose::slot("archive_operations"), adminive::compose::slot("cesium_models"), adminive::compose::slot("backend_config"), adminive::compose::slot("system_actions"))).titled("ECAP 配置");
const std::vector<adminive::Composition_Slot_Contract> contracts = {
{"mode_acs", "amis_schema", mode_acs_path + "/descriptor", mode_acs_path + "/view", mode_acs_path + "/data", mode_acs_path + "/amis"},
{"data_feed_settings", "amis_schema", data_feed_settings_path + "/descriptor", data_feed_settings_path + "/view", data_feed_settings_path + "/data", data_feed_settings_path + "/amis"},
@@ -904,7 +1126,13 @@ private:
{"data_feeds", "amis_schema", data_feeds_path + "/descriptor", data_feeds_path + "/view", data_feeds_path, data_feeds_path + "/amis"},
{"source_feed_relations", "amis_schema", relations_path + "/descriptor", relations_path + "/view", relations_path, relations_path + "/amis"},
{"mlat", "amis_schema", mlat_path + "/descriptor", mlat_path + "/view", mlat_path + "/data", mlat_path + "/amis"},
{"cesium_graphics", "amis_schema", cesium_graphics_path + "/descriptor", cesium_graphics_path + "/view", cesium_graphics_path + "/data", cesium_graphics_path + "/amis"}
{"map_view", "amis_schema", map_view_path + "/descriptor", map_view_path + "/view", map_view_path + "/data", map_view_path + "/amis"},
{"cesium_graphics", "amis_schema", cesium_graphics_path + "/descriptor", cesium_graphics_path + "/view", cesium_graphics_path + "/data", cesium_graphics_path + "/amis"},
{"external_resources", "amis_schema", external_resources_path + "/descriptor", external_resources_path + "/view", external_resources_path, external_resources_path + "/amis"},
{"archive_operations", "ecap_archive_operations", {}, {}, {}, {}},
{"cesium_models", "ecap_cesium_models", {}, {}, "/map/models", {}},
{"backend_config", "amis_schema", backend_config_path + "/descriptor", backend_config_path + "/view", backend_config_path, backend_config_path + "/amis"},
{"system_actions", "amis_schema", {}, {}, {}, {}}
};
const std::map<std::string, Json> schemas = {
{"mode_acs", mode_acs_resource_.amis_schema()},
@@ -913,15 +1141,24 @@ private:
{"data_feeds", feed_amis_schema()},
{"source_feed_relations", relation_amis_schema()},
{"mlat", mlat_resource_.amis_schema()},
{"cesium_graphics", cesium_graphics_resource_.amis_schema()}
{"map_view", map_view_resource_.amis_schema()},
{"cesium_graphics", cesium_graphics_resource_.amis_schema()},
{"external_resources", external_resource_amis_schema()},
{"archive_operations", archive_operations_schema()},
{"cesium_models", cesium_models_schema(global_)},
{"backend_config", backend_config_amis_schema()},
{"system_actions", system_actions_schema()}
};
return adminive::to_composition_manifest_json<Json>(view, contracts, schemas);
}
static inline const std::string mode_acs_path = "/api/adminive/config/mode_acs";
static inline const std::string data_feed_settings_path = "/api/adminive/config/data_feed_settings";
static inline const std::string map_view_path = "/api/adminive/config/map_view";
static inline const std::string data_sources_path = "/api/adminive/config/data_sources";
static inline const std::string data_feeds_path = "/api/adminive/config/data_feeds";
static inline const std::string relations_path = "/api/adminive/config/source_feed_relations";
static inline const std::string external_resources_path = "/api/adminive/config/external_resources";
static inline const std::string backend_config_path = "/api/adminive/config/backend_config";
static inline const std::string mlat_path = "/api/adminive/config/mlat";
static inline const std::string cesium_graphics_path = "/api/adminive/config/cesium_graphics";
static inline const std::string manifest_path = "/api/adminive/config/manifest";
@@ -929,6 +1166,7 @@ private:
std::mutex topology_mutex_;
adminive::Drogon_Resource<Mode_ACS_Config_Data, Json> mode_acs_resource_;
adminive::Drogon_Resource<Data_feed_Config_Data, Json> data_feed_settings_resource_;
adminive::Drogon_Resource<Map_View_Config, Json> map_view_resource_;
adminive::Drogon_Resource<MLAT_Config_Data, Json> mlat_resource_;
adminive::Drogon_Resource<Cesium_Graphics_Config_Data, Json> cesium_graphics_resource_;
};