准备改adminive
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "Gallery_Protocol.h"
|
||||
#include "Gallery_Properties_Adminive.h"
|
||||
#include "Gallery_Renderables_Adminive.h"
|
||||
#include "Gallery_Session_Control_Adminive.h"
|
||||
|
||||
#include "adminive/adminive.hpp"
|
||||
#include "adminive/adapters/nlohmann_json.hpp"
|
||||
@@ -88,10 +89,7 @@ std::vector<Action_Definition> actions(std::string_view case_id,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
std::vector<Action_Definition> result{
|
||||
action("reset", "恢复本图默认值", "Gallery_Scene::rebuild", "会话"),
|
||||
action("rebuild_renderable", "移除并重建控件", "Plot_Core::remove_renderable / Builder::build", "会话"),
|
||||
action("toggle_view", "切换 View 生命周期", "Plot_Core::activate_view / deactivate_view", "会话"),
|
||||
action("axis_set_start", "写入坐标范围起点", "Axis::set<&Axis_Properties::coordinates>", "Axis"),
|
||||
action("axis_set_length", "写入坐标范围跨度", "Axis::set<&Axis_Properties::coordinates>", "Axis"),
|
||||
action("axis_probe", "读取坐标映射与刻度", "coord_to_pixel / pixel_to_coord / tick_step / sub_tick_count / tick_label", "Axis")
|
||||
};
|
||||
if (frame_mode == Gallery_Frame_Mode::Manual) {
|
||||
@@ -178,67 +176,6 @@ const Case_Model* find_case(std::string_view id) {
|
||||
Json parse_request(std::string_view message) {
|
||||
return Json::parse(message.begin(), message.end());
|
||||
}
|
||||
template <class Properties>
|
||||
Gallery_Property_Model make_property_model(Gallery_Frame_Mode frame_mode) {
|
||||
if(frame_mode == Gallery_Frame_Mode::Low_Latency) {
|
||||
using T = Gallery_Low_Latency_Case_Properties<Properties>;
|
||||
return Gallery_Property_Model{std::in_place_type<T>};
|
||||
}
|
||||
return Gallery_Property_Model{std::in_place_type<Properties>};
|
||||
}
|
||||
Gallery_Property_Model make_property_model(std::string_view case_id, Gallery_Frame_Mode frame_mode) {
|
||||
if(case_id == "spectrum")
|
||||
return make_property_model<Gallery_Spectrum_Properties>(frame_mode);
|
||||
if(case_id == "afterglow")
|
||||
return make_property_model<Gallery_Afterglow_Properties>(frame_mode);
|
||||
if(case_id == "sweep_spectrum")
|
||||
return make_property_model<Gallery_Sweep_Spectrum_Properties>(frame_mode);
|
||||
if(case_id == "waterfall")
|
||||
return make_property_model<Gallery_Waterfall_Properties>(frame_mode);
|
||||
if(case_id == "frequency_trace")
|
||||
return make_property_model<Gallery_Frequency_Trace_Properties>(frame_mode);
|
||||
if(case_id == "selection_overlay")
|
||||
return make_property_model<Gallery_Selection_Overlay_Properties>(frame_mode);
|
||||
if(case_id == "constellation")
|
||||
return make_property_model<Gallery_Constellation_Properties>(frame_mode);
|
||||
return make_property_model<Gallery_Axis_Lab_Properties>(frame_mode);
|
||||
}
|
||||
Gallery_Value gallery_value(const Json& value) {
|
||||
if(value.is_boolean())
|
||||
return value.get<bool>();
|
||||
if(value.is_number())
|
||||
return value.get<double>();
|
||||
return value.get<std::string>();
|
||||
}
|
||||
template <class T>
|
||||
std::optional<Gallery_Value> property_value(const T& value, std::string_view id) {
|
||||
std::optional<Gallery_Value> result;
|
||||
const auto descriptor = adminive::describe<T>();
|
||||
std::apply([&](const auto&... field) {
|
||||
([&] {
|
||||
if(!result && field.name() == id)
|
||||
result = gallery_value(adminive::encode_json_value<Json>(field.get(value)));
|
||||
}(), ...);
|
||||
}, descriptor.fields());
|
||||
return result;
|
||||
}
|
||||
template <class T>
|
||||
std::size_t property_count(const T&) {
|
||||
return std::tuple_size_v<adminive::Descriptor_Fields<T>>;
|
||||
}
|
||||
template <class T>
|
||||
Json property_resource(const T& value) {
|
||||
return {
|
||||
{"descriptor", adminive::to_descriptor_json<Json, T>()},
|
||||
{"view", adminive::to_view_json<Json, T>(adminive::describe_edit_view<T>().titled("控件属性").submit("应用"))},
|
||||
{"data", adminive::to_frontend_json<Json>(value)}
|
||||
};
|
||||
}
|
||||
template <class T>
|
||||
adminive::Update_Result apply_property_patch(T& value, const Json& patch) {
|
||||
return adminive::apply_frontend_patch<Json>(value, patch);
|
||||
}
|
||||
|
||||
adminive::Table_View action_view();
|
||||
|
||||
} // namespace renderive::web::gallery_detail
|
||||
@@ -525,27 +462,6 @@ Json frame_mode_contract(Gallery_Frame_Mode mode) {
|
||||
|
||||
} // namespace
|
||||
|
||||
Gallery_Value gallery_property_value(const Gallery_State& state, std::string_view id) {
|
||||
const auto result = std::visit([id](const auto& properties) {
|
||||
return gallery_detail::property_value(properties, id);
|
||||
}, state.properties);
|
||||
if(!result)
|
||||
throw std::out_of_range("gallery property does not exist: " + std::string(id));
|
||||
return *result;
|
||||
}
|
||||
|
||||
bool gallery_has_property(const Gallery_State& state, std::string_view id) {
|
||||
return std::visit([id](const auto& properties) {
|
||||
return gallery_detail::property_value(properties, id).has_value();
|
||||
}, state.properties);
|
||||
}
|
||||
|
||||
std::size_t gallery_property_count(const Gallery_State& state) {
|
||||
return std::visit([](const auto& properties) {
|
||||
return gallery_detail::property_count(properties);
|
||||
}, state.properties);
|
||||
}
|
||||
|
||||
std::string Gallery_Protocol::catalog_json() {
|
||||
Json result = protocol_base();
|
||||
result["type"] = "catalog";
|
||||
@@ -600,27 +516,23 @@ bool Gallery_Protocol::is_case(std::string_view case_id) {
|
||||
return gallery_detail::find_case(case_id) != nullptr;
|
||||
}
|
||||
|
||||
Gallery_State Gallery_Protocol::default_state(std::string_view case_id,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
return {gallery_detail::make_property_model(case_id, frame_mode)};
|
||||
}
|
||||
|
||||
Gallery_State Gallery_Protocol::default_state(std::string_view case_id) {
|
||||
return default_state(case_id, Gallery_Frame_Mode::Low_Latency);
|
||||
}
|
||||
|
||||
std::string Gallery_Protocol::case_json(std::string_view case_id,
|
||||
const Gallery_State& state,
|
||||
std::string_view telemetry_json,
|
||||
std::string_view notice,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
std::string Gallery_Protocol::case_json_from_controls(
|
||||
std::string_view case_id,
|
||||
std::string_view controls_json,
|
||||
std::string_view telemetry_json,
|
||||
std::string_view notice,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
Json result = protocol_base();
|
||||
result["type"] = "case_state";
|
||||
result["case"] = case_contract(case_id);
|
||||
result["frame_mode"] = frame_mode_contract(frame_mode);
|
||||
result["controls"] = std::visit([](const auto& properties) {
|
||||
return gallery_detail::property_resource(properties);
|
||||
}, state.properties);
|
||||
try {
|
||||
result["controls"] = {
|
||||
{"resources", Json::parse(controls_json.begin(), controls_json.end())}
|
||||
};
|
||||
} catch (const std::exception&) {
|
||||
result["controls"] = {{"resources", Json::array()}};
|
||||
}
|
||||
result["actions"] = {
|
||||
{"descriptor", adminive::to_descriptor_json<Json, gallery_detail::Action_Model>()},
|
||||
{"view", adminive::to_view_json<Json, gallery_detail::Action_Model>(
|
||||
@@ -640,14 +552,6 @@ std::string Gallery_Protocol::case_json(std::string_view case_id,
|
||||
return result.dump();
|
||||
}
|
||||
|
||||
std::string Gallery_Protocol::case_json(std::string_view case_id,
|
||||
const Gallery_State& state,
|
||||
std::string_view telemetry_json,
|
||||
std::string_view notice) {
|
||||
return case_json(case_id, state, telemetry_json, notice,
|
||||
Gallery_Frame_Mode::Low_Latency);
|
||||
}
|
||||
|
||||
std::string Gallery_Protocol::error_json(std::string_view message,
|
||||
std::string_view field) {
|
||||
Json result = protocol_base();
|
||||
@@ -674,40 +578,6 @@ std::string Gallery_Protocol::observer_json(std::string_view case_id,
|
||||
return result.dump();
|
||||
}
|
||||
|
||||
Gallery_Patch_Result Gallery_Protocol::apply_patch(std::string_view case_id,
|
||||
const Gallery_State& current,
|
||||
std::string_view message,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
try {
|
||||
const Json request = gallery_detail::parse_request(message);
|
||||
if (!request.is_object() || request.value("category", "") != "event" ||
|
||||
request.value("type", "") != "gallery_patch" ||
|
||||
!request.contains("patch") || !request.at("patch").is_object()) {
|
||||
return {std::nullopt, error_json("gallery_patch 格式无效")};
|
||||
}
|
||||
Gallery_State candidate = current;
|
||||
const auto update = std::visit([&request](auto& properties) {
|
||||
return gallery_detail::apply_property_patch(properties, request.at("patch"));
|
||||
}, candidate.properties);
|
||||
if(!update.success) {
|
||||
Json response = protocol_base();
|
||||
response["type"] = "error";
|
||||
response["message"] = update.message;
|
||||
response["field_errors"] = update.field_errors;
|
||||
return {std::nullopt, response.dump()};
|
||||
}
|
||||
return {std::move(candidate), {}};
|
||||
} catch (const std::exception& error) {
|
||||
return {std::nullopt, error_json(error.what())};
|
||||
}
|
||||
}
|
||||
|
||||
Gallery_Patch_Result Gallery_Protocol::apply_patch(std::string_view case_id,
|
||||
const Gallery_State& current,
|
||||
std::string_view message) {
|
||||
return apply_patch(case_id, current, message, Gallery_Frame_Mode::Low_Latency);
|
||||
}
|
||||
|
||||
std::optional<Gallery_Open_Request> Gallery_Protocol::open_request(std::string_view message) {
|
||||
try {
|
||||
const Json request = gallery_detail::parse_request(message);
|
||||
@@ -756,9 +626,68 @@ std::optional<Gallery_Action_Request> Gallery_Protocol::action_request(
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Gallery_Control_Patch_Request> Gallery_Protocol::control_patch_request(
|
||||
std::string_view message) {
|
||||
try {
|
||||
const Json request = gallery_detail::parse_request(message);
|
||||
if (!request.is_object() || request.value("category", "") != "event" ||
|
||||
request.value("type", "") != "gallery_patch" ||
|
||||
!request.contains("target") || !request.at("target").is_string() ||
|
||||
!request.contains("patch") || !request.at("patch").is_object())
|
||||
return std::nullopt;
|
||||
return Gallery_Control_Patch_Request{
|
||||
request.at("target").get<std::string>(), request.at("patch").dump()};
|
||||
} catch (const std::exception&) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t Gallery_Protocol::control_count(std::string_view case_id,
|
||||
Gallery_Frame_Mode frame_mode) {
|
||||
return gallery_property_count(default_state(case_id, frame_mode));
|
||||
const auto count = [](const auto& self, const Json& fields) -> std::size_t {
|
||||
std::size_t result{};
|
||||
for (const auto& field : fields) {
|
||||
if (field.value("editable", false) && !field.contains("children"))
|
||||
++result;
|
||||
if (field.contains("children"))
|
||||
result += self(self, field.at("children"));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto type_count = [&count]<class T>() {
|
||||
return count(count, adminive::to_descriptor_json<Json, T>().at("fields"));
|
||||
};
|
||||
std::size_t result = type_count.template operator()<Gallery_Session_Control>();
|
||||
if (case_id == "axis_lab")
|
||||
return result + type_count.template operator()<Gallery_Frequency_Axis>() +
|
||||
type_count.template operator()<Gallery_Time_Axis>();
|
||||
if (case_id == "spectrum" || case_id == "selection_overlay") {
|
||||
result += type_count.template operator()<Gallery_Frequency_Axis>() +
|
||||
type_count.template operator()<Gallery_Axis>() +
|
||||
type_count.template operator()<Gallery_Spectrum>();
|
||||
if (case_id == "selection_overlay")
|
||||
result += type_count.template operator()<Gallery_Selection_Rectangle_Overlay>();
|
||||
return result;
|
||||
}
|
||||
if (case_id == "waterfall")
|
||||
return result + type_count.template operator()<Gallery_Frequency_Axis>() +
|
||||
type_count.template operator()<Gallery_Time_Axis>() +
|
||||
type_count.template operator()<Gallery_Waterfall>();
|
||||
if (case_id == "afterglow")
|
||||
return result + type_count.template operator()<Gallery_Frequency_Axis>() +
|
||||
type_count.template operator()<Gallery_Axis>() +
|
||||
type_count.template operator()<Gallery_Afterglow>();
|
||||
if (case_id == "sweep_spectrum")
|
||||
return result + 2 * type_count.template operator()<Gallery_Axis>() +
|
||||
type_count.template operator()<Gallery_Sweep_Spectrum>();
|
||||
if (case_id == "frequency_trace")
|
||||
return result + type_count.template operator()<Gallery_Time_Axis>() +
|
||||
type_count.template operator()<Gallery_Axis>() +
|
||||
type_count.template operator()<Gallery_Frequency_Trace>();
|
||||
if (case_id == "constellation")
|
||||
return result + 2 * type_count.template operator()<Gallery_Axis>() +
|
||||
type_count.template operator()<Gallery_Constellation_Diagram>();
|
||||
return result;
|
||||
}
|
||||
|
||||
std::size_t Gallery_Protocol::control_count(std::string_view case_id) {
|
||||
|
||||
Reference in New Issue
Block a user