更新功能
This commit is contained in:
@@ -7,21 +7,46 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
namespace adminive {
|
||||
|
||||
inline Json make_config_tree(std::string name, std::string label, Json children = Json::array()) {
|
||||
return Json{{"name", std::move(name)}, {"label", std::move(label)}, {"children", std::move(children)}};
|
||||
inline std::string make_field_name(std::string_view prefix, std::string_view name) {
|
||||
if(prefix.empty()) {
|
||||
return std::string(name);
|
||||
}
|
||||
return std::string(prefix) + "." + std::string(name);
|
||||
}
|
||||
|
||||
inline Json make_amis_control(const Json& field, std::string_view permission) {
|
||||
Json control{{"name", field.at("name")}, {"label", field.at("label")}};
|
||||
inline Json make_amis_form_actions(std::string submit_label = "Apply") {
|
||||
return Json::array({Json{{"type", "reset"}, {"label", "Reset"}}, Json{{"type", "submit"}, {"label", std::move(submit_label)}, {"level", "primary"}}});
|
||||
}
|
||||
inline Json make_amis_control(const Json& field, std::string_view permission, std::string_view prefix = {}) {
|
||||
const std::string name = field.at("name").get<std::string>();
|
||||
const std::string full_name = make_field_name(prefix, name);
|
||||
const std::string value_type = field.at("value_type").get<std::string>();
|
||||
if(value_type == "object" && field.contains("children")) {
|
||||
Json body = Json::array();
|
||||
for(const auto& child : field.at("children")) {
|
||||
if(child.at("visible").get<bool>()) {
|
||||
body.push_back(make_amis_control(child, permission, full_name));
|
||||
}
|
||||
}
|
||||
Json control{{"type", "fieldset"}, {"title", field.at("label")}, {"body", std::move(body)}, {"collapsable", true}, {"collapsed", false}};
|
||||
if(field.contains("description")) {
|
||||
control["description"] = field.at("description");
|
||||
}
|
||||
if(field.contains("visible_on")) {
|
||||
control["visibleOn"] = field.at("visible_on");
|
||||
}
|
||||
return control;
|
||||
}
|
||||
Json control{{"name", full_name}, {"label", field.at("label")}};
|
||||
if(field.contains("description")) {
|
||||
control["description"] = field.at("description");
|
||||
}
|
||||
if(field.contains("visible_on")) {
|
||||
control["visibleOn"] = field.at("visible_on");
|
||||
}
|
||||
if(!field.at(permission).get<bool>()) {
|
||||
control["type"] = "static";
|
||||
return control;
|
||||
}
|
||||
const std::string value_type = field.at("value_type");
|
||||
if(field.contains("widget")) {
|
||||
control["type"] = field.at("widget");
|
||||
} else if(value_type == "boolean") {
|
||||
@@ -33,6 +58,13 @@ inline Json make_amis_control(const Json& field, std::string_view permission) {
|
||||
} else {
|
||||
control["type"] = "input-text";
|
||||
}
|
||||
if(control.at("type") == "input-date") {
|
||||
control["valueFormat"] = "YYYY-MM-DD";
|
||||
control["displayFormat"] = "YYYY-MM-DD";
|
||||
control["clearable"] = true;
|
||||
} else if(control.at("type") == "input-color") {
|
||||
control["clearable"] = true;
|
||||
}
|
||||
if(field.at("required").get<bool>()) {
|
||||
control["required"] = true;
|
||||
}
|
||||
@@ -64,8 +96,12 @@ inline Json make_amis_form_body(const Json& descriptor, std::string_view permiss
|
||||
}
|
||||
inline Json make_amis_column(const Json& field) {
|
||||
Json column{{"name", field.at("name")}, {"label", field.at("list_label")}};
|
||||
if(field.contains("order")) { column["order"] = field.at("order"); }
|
||||
if(field.contains("sortable")) { column["sortable"] = field.at("sortable"); }
|
||||
if(field.contains("order")) {
|
||||
column["order"] = field.at("order");
|
||||
}
|
||||
if(field.contains("sortable")) {
|
||||
column["sortable"] = field.at("sortable");
|
||||
}
|
||||
const std::string value_type = field.at("value_type");
|
||||
if(value_type == "boolean") {
|
||||
column["type"] = "status";
|
||||
@@ -107,9 +143,9 @@ inline Json make_amis_object_status_column(const Json& descriptor, std::string s
|
||||
return Json{{"type", "tpl"}, {"label", descriptor.at("label")}, {"tpl", R"(<span class="text-primary">View status ▾</span>)"}, {"popOver", pop_over}};
|
||||
}
|
||||
template <Described_Type T>
|
||||
Json to_amis_form_schema(const T& value, std::string submit_api = {}) {
|
||||
Json to_amis_form_schema(const T& value, std::string submit_api = {}, std::string submit_label = "Apply") {
|
||||
const Json descriptor = to_descriptor_json<T>();
|
||||
Json result{{"type", "form"}, {"title", descriptor.at("label")}, {"data", to_frontend_json(value)}, {"body", make_amis_form_body(descriptor, "editable")}};
|
||||
Json result{{"type", "form"}, {"title", descriptor.at("label")}, {"data", to_frontend_json(value)}, {"body", make_amis_form_body(descriptor, "editable")}, {"actions", make_amis_form_actions(std::move(submit_label))}, {"affixFooter", true}};
|
||||
if(!submit_api.empty()) {
|
||||
result["api"] = Json{{"method", "post"}, {"url", std::move(submit_api)}};
|
||||
}
|
||||
@@ -122,7 +158,7 @@ Json to_amis_crud_schema(std::string base_api, const Json* status_descriptor = n
|
||||
Json columns = Json::array({Json{{"name", "id"}, {"label", "Id"}}});
|
||||
std::vector<Json> list_fields;
|
||||
for(const auto& field : descriptor.at("fields")) {
|
||||
if(field.at("readable").get<bool>() && field.at("list_visible").get<bool>()) {
|
||||
if(field.at("readable").get<bool>() && field.at("list_visible").get<bool>() && field.at("value_type") != "object") {
|
||||
list_fields.push_back(field);
|
||||
}
|
||||
}
|
||||
@@ -135,8 +171,8 @@ Json to_amis_crud_schema(std::string base_api, const Json* status_descriptor = n
|
||||
if(status_descriptor) {
|
||||
columns.push_back(make_amis_object_status_column(*status_descriptor, base_api + "/${id}/status", status_interval));
|
||||
}
|
||||
const Json create_form{{"type", "form"}, {"api", Json{{"method", "post"}, {"url", base_api}}}, {"reload", crud_id}, {"body", make_amis_form_body(descriptor, "creatable")}};
|
||||
const Json edit_form{{"type", "form"}, {"api", Json{{"method", "put"}, {"url", base_api + "/${id}"}}}, {"reload", crud_id}, {"body", make_amis_form_body(descriptor, "editable")}};
|
||||
const Json create_form{{"type", "form"}, {"api", Json{{"method", "post"}, {"url", base_api}}}, {"reload", crud_id}, {"body", make_amis_form_body(descriptor, "creatable")}, {"actions", make_amis_form_actions("Create")}};
|
||||
const Json edit_form{{"type", "form"}, {"api", Json{{"method", "put"}, {"url", base_api + "/${id}"}}}, {"reload", crud_id}, {"body", make_amis_form_body(descriptor, "editable")}, {"actions", make_amis_form_actions("Confirm Changes")}};
|
||||
const Json create_button{{"type", "button"}, {"label", "Create"}, {"level", "primary"}, {"actionType", "dialog"}, {"dialog", Json{{"title", "Create " + descriptor.at("label").get<std::string>()}, {"body", create_form}}}};
|
||||
Json actions = Json::array();
|
||||
actions.push_back(Json{{"type", "button"}, {"label", "Edit"}, {"level", "link"}, {"actionType", "dialog"}, {"dialog", Json{{"title", "Edit " + descriptor.at("label").get<std::string>()}, {"body", edit_form}}}});
|
||||
|
||||
@@ -26,8 +26,8 @@ inline std::string make_label(std::string_view name) {
|
||||
std::string result;
|
||||
result.reserve(name.size());
|
||||
bool uppercase = true;
|
||||
for (const char value : name) {
|
||||
if (value == '_') {
|
||||
for(const char value : name) {
|
||||
if(value == '_') {
|
||||
result.push_back(' ');
|
||||
uppercase = true;
|
||||
continue;
|
||||
@@ -90,6 +90,11 @@ public:
|
||||
result.widget_ = std::move(value);
|
||||
return result;
|
||||
}
|
||||
Field_Descriptor visible_on(std::string value) const {
|
||||
auto result = *this;
|
||||
result.visible_on_ = std::move(value);
|
||||
return result;
|
||||
}
|
||||
Field_Descriptor list_label(std::string value) const {
|
||||
auto result = *this;
|
||||
result.list_label_ = std::move(value);
|
||||
@@ -120,6 +125,9 @@ public:
|
||||
const std::string& widget() const noexcept {
|
||||
return widget_;
|
||||
}
|
||||
const std::string& visible_on() const noexcept {
|
||||
return visible_on_;
|
||||
}
|
||||
bool is_editable() const noexcept {
|
||||
return editable_;
|
||||
}
|
||||
@@ -150,6 +158,7 @@ private:
|
||||
std::string list_label_;
|
||||
std::string description_;
|
||||
std::string widget_;
|
||||
std::string visible_on_;
|
||||
bool editable_{};
|
||||
bool creatable_{};
|
||||
bool readable_{true};
|
||||
|
||||
@@ -25,6 +25,10 @@ requires std::copy_constructible<T> && std::assignable_from<T&, T>
|
||||
class Http_Resource {
|
||||
public:
|
||||
Http_Resource(T& value, std::string path) : value_(value), path_(std::move(path)) {}
|
||||
Json amis_schema() const {
|
||||
std::scoped_lock lock(mutex_);
|
||||
return to_amis_form_schema(value_, path_ + "/data", "Confirm Changes");
|
||||
}
|
||||
void bind(httplib::Server& server) {
|
||||
server.Get(path_ + "/descriptor", [this](const httplib::Request&, httplib::Response& response) {
|
||||
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", to_descriptor_json<T>()}});
|
||||
@@ -34,8 +38,7 @@ public:
|
||||
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", to_frontend_json(value_)}});
|
||||
});
|
||||
server.Get(path_ + "/amis", [this](const httplib::Request&, httplib::Response& response) {
|
||||
std::scoped_lock lock(mutex_);
|
||||
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", to_amis_form_schema(value_, path_ + "/data")}});
|
||||
write_http_json(response, Json{{"status", 0}, {"msg", ""}, {"data", amis_schema()}});
|
||||
});
|
||||
server.Post(path_ + "/data", [this](const httplib::Request& request, httplib::Response& response) {
|
||||
try {
|
||||
@@ -56,7 +59,7 @@ public:
|
||||
private:
|
||||
T& value_;
|
||||
std::string path_;
|
||||
std::mutex mutex_;
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
template <Described_Type T>
|
||||
requires std::default_initializable<T> && std::copy_constructible<T> && std::assignable_from<T&, T>
|
||||
|
||||
@@ -36,6 +36,9 @@ Json to_json(const T& value);
|
||||
template <Described_Type T>
|
||||
Json to_frontend_json(const T& value);
|
||||
template <Described_Type T>
|
||||
requires std::default_initializable<T>
|
||||
Json to_descriptor_json();
|
||||
template <Described_Type T>
|
||||
requires std::default_initializable<T> && std::copy_constructible<T> && std::assignable_from<T&, T>
|
||||
Update_Result assign_json(T& target, const Json& value);
|
||||
template <class T>
|
||||
@@ -190,9 +193,15 @@ Json to_descriptor_json() {
|
||||
if (!item.description().empty()) {
|
||||
field_json["description"] = item.description();
|
||||
}
|
||||
if (!item.widget().empty()) {
|
||||
if(!item.widget().empty()) {
|
||||
field_json["widget"] = item.widget();
|
||||
}
|
||||
if(!item.visible_on().empty()) {
|
||||
field_json["visible_on"] = item.visible_on();
|
||||
}
|
||||
if constexpr(Described_Type<Member>) {
|
||||
field_json["children"] = to_descriptor_json<Member>().at("fields");
|
||||
}
|
||||
append_constraints<Member>(field_json);
|
||||
const auto options = enum_options<Member>();
|
||||
if (!options.empty()) {
|
||||
|
||||
Reference in New Issue
Block a user