use crate::request::{ContentType, Method, Request};
use crate::PLUGIN_TOOLS;
use crate::{ApiResponse, Tools};
use br_fields::Field;
use json::{array, object, JsonValue};
use std::any::type_name;
use std::collections::HashMap;
pub trait Action {
fn _name(&self) -> String {
type_name::<Self>()
.rsplit("::")
.next()
.unwrap()
.to_lowercase()
}
fn api(&self) -> String {
let t = type_name::<Self>().split("::").collect::<Vec<&str>>();
let plugin = t[2].to_lowercase();
let module = t[3].to_lowercase();
let action = t[4].to_lowercase();
format!("{plugin}.{module}.{action}")
}
fn token(&self) -> bool {
true
}
fn version(&self) -> &'static str {
"v1"
}
fn author(&self) -> &'static str {
""
}
fn sort(&self) -> usize {
99
}
fn title(&self) -> &'static str;
fn description(&self) -> &'static str {
""
}
fn tags(&self) -> &'static [&'static str] {
&[]
}
fn icon(&self) -> &'static str {
""
}
fn public(&self) -> bool {
true
}
fn auth(&mut self) -> bool {
true
}
fn interface_type(&mut self) -> InterfaceType {
InterfaceType::API
}
fn method(&mut self) -> Method {
Method::Post
}
fn content_type(&mut self) -> ContentType {
ContentType::Json
}
fn params(&mut self) -> JsonValue {
object! {}
}
fn success(&mut self) -> ApiResponse {
let mut data = object! {};
data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 0)
.example(0.into())
.swagger();
data["message"] = br_fields::str::Str::new(true, "message", "成功消息", 256, "")
.example("成功".into())
.swagger();
data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", true)
.example(true.into())
.swagger();
ApiResponse::success(data, "请求成功")
}
fn error(&mut self) -> ApiResponse {
let mut data = object! {};
data["code"] = br_fields::int::Int::new(true, "code", "编号", 10, 1000)
.example(1000.into())
.swagger();
data["message"] = br_fields::str::Str::new(true, "message", "错误消息", 256, "")
.example("失败".into())
.swagger();
data["data"] = br_fields::text::Json::new(true, "data", "返回数据", object! {}).swagger();
data["success"] = br_fields::int::Switch::new(true, "success", "成功状态", false)
.example(false.into())
.swagger();
ApiResponse::error(data, "请求失败")
}
fn run(&mut self, mut request: Request) -> Result<ApiResponse, ApiResponse> {
if self.method().str().to_lowercase() != request.method.str().to_lowercase() {
return Err(ApiResponse::fail(
-1,
format!(
"Request type error: Actual [{}] Expected [{}]",
request.method.str(),
self.method().str()
)
.as_str(),
));
}
self.check(&mut request.body)?;
let res = self.index(request.clone());
match res.success {
true => Ok(res),
false => Err(res),
}
}
fn check(&mut self, request: &mut JsonValue) -> Result<(), ApiResponse> {
let params = self.params();
let req = request.clone();
for (name, _) in req.entries() {
if !params.has_key(name) {
request.remove(name);
}
}
for (name, field) in params.entries() {
let require = field["require"].as_bool().unwrap_or(false);
if request.has_key(name) {
match field["mode"].as_str().unwrap() {
"int" => {
if !request[name].is_number() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
name, field["mode"]
)
.as_str(),
));
}
}
"string" => {
if !request[name].is_string() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
name, field["mode"]
)
.as_str(),
));
}
if require && request[name].is_empty() {
return Err(ApiResponse::fail(
-1,
format!("请求参数数据类型错误: 参数 [{}] 不能为空", name).as_str(),
));
}
}
"switch" => {
if !request[name].is_boolean() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
name, field["mode"]
)
.as_str(),
));
}
}
"select" => {
if !request[name].is_array() && !request[name].is_string() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数数据类型错误: 参数 [{}] 数据类型应为[{}]",
name, field["mode"]
)
.as_str(),
));
}
let option = field["option"]
.members()
.map(|m| m.as_str().unwrap_or(""))
.collect::<Vec<&str>>()
.join(",");
if request[name].is_string()
&& !field["option"].contains(request[name].as_str().unwrap_or(""))
{
return Err(ApiResponse::fail(
-1,
format!(
"请求参数选项错误: 参数 [{}] 数据类型应为[{}]之内",
name, option
)
.as_str(),
));
}
if request[name].is_array() {
let res1 = request[name]
.members()
.map(|m| m.as_str().unwrap_or(""))
.collect::<Vec<&str>>();
let diff = res1
.iter()
.filter(|&item| {
!field["option"]
.members()
.map(|m| m.as_str().unwrap_or(""))
.collect::<Vec<&str>>()
.contains(item)
})
.collect::<Vec<&&str>>();
if !diff.is_empty() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数选项错误: 参数 [{}] 数据 {:?} 应为[{:?}]范围之内",
name, diff, option
)
.as_str(),
));
}
}
}
"radio" => {
if !request[name].is_string() {
return Err(ApiResponse::fail(
-1,
format!(
"请求参数数据类型错误: 参数 [{}] 数据类型应为[{}] 实际为[{}]",
name, field["mode"], request[name]
)
.as_str(),
));
}
let option = field["option"]
.members()
.map(|m| m.as_str().unwrap_or(""))
.collect::<Vec<&str>>()
.join(",");
if request[name].is_string()
&& !field["option"].contains(request[name].as_str().unwrap_or(""))
{
return Err(ApiResponse::fail(
-1,
format!(
"请求参数选项错误: 参数 [{}] 数据 [{}] 应为 [{}] 之一",
name, request[name], option
)
.as_str(),
));
}
}
_ => {
}
}
} else {
if require {
return Err(ApiResponse::fail(
-1,
format!("请求参数错误: 参数[{}]必填", name).as_str(),
));
}
request[name] = field["def"].clone();
}
}
Ok(())
}
fn index(&mut self, request: Request) -> ApiResponse;
fn params_table_select(&mut self, mut params: JsonValue) -> JsonValue {
params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1)
.example(1.into())
.field();
params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10)
.example(10.into())
.field();
params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
.example("".into())
.field();
params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
.example(array![])
.field();
params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
.example(array![])
.field();
params
}
#[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
fn table_select(
&mut self,
request: JsonValue,
table_name: &str,
mut fields: Vec<&str>,
) -> JsonValue {
let page = request["page"].as_i32().unwrap_or(1);
let limit = request["limit"].as_i32().unwrap_or(10);
let search = request["search"].as_str().unwrap_or("");
let where_or = request["where_or"].clone();
let where_and = request["where_and"].clone();
let mut tools = self.tools();
let db = tools.db.table(table_name);
if !search.is_empty() {
db.where_and(&fields.join("|"), "like", format!("%{}%", search).into());
}
for (key, value) in where_or.entries() {
if value.is_empty() {
continue;
}
if value.is_array() {
db.where_or(key, "between", value.clone());
db.where_or(key, "in", value.clone());
} else if value.is_boolean() {
db.where_or(key, "=", value.clone());
} else {
db.where_or(key, "like", format!("%{}%", value).into());
}
}
for value in where_and.members() {
db.where_and(
value[0].as_str().unwrap(),
value[1].as_str().unwrap(),
value[2].clone(),
);
}
let total = (db.clone().count().as_f64().unwrap() / limit as f64).ceil() as i64;
let mut db_list = db.clone();
fields.push("id");
db_list.field(&fields.join(","));
let mut data = db_list.page(page, limit).select();
let mut list = array![];
for item in data.members_mut() {
let value = item["id"].clone();
item.remove("id");
let label = item
.entries()
.map(|(_, v)| v.as_str().unwrap())
.collect::<Vec<&str>>();
list.push(object! {
value: value,
label: label.join(" | ").clone(),
})
.unwrap();
}
object! {
total:total,
data:list,
}
}
fn params_table_menu(&mut self, mut params: JsonValue) -> JsonValue {
params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
.example("".into())
.field();
params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
.example(array![])
.field();
params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
.example(array![])
.field();
params
}
#[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
fn table_menu(
&mut self,
request: JsonValue,
table_name: &str,
label_field: &str,
fields: JsonValue,
hidd_field: Vec<&str>,
show_field: Vec<&str>,
search_fields: Vec<&str>,
_filter_fields: Vec<&str>,
) -> JsonValue {
let search = request["search"].as_str().unwrap_or("");
let order = request["order"].clone();
let where_or = request["where_or"].clone();
let where_and = request["where_and"].clone();
let mut columns = array![];
let mut search_name = vec![];
let mut search_field = vec![];
let mut filter_columns = vec![];
let mut table_fields = object! {};
let mut table_field_json = vec![];
let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
alls_field.retain(|x| !hidd_field.contains(x));
if !show_field.is_empty() {
alls_field.retain(|x| show_field.contains(x) || *x == "id");
}
for item in alls_field.iter() {
let row = fields[item.clone()].clone();
let field = row["field"].to_string();
let title = row["title"].to_string();
let mode = row["mode"].to_string();
if search_fields.contains(&field.as_str()) {
search_name.push(title);
search_field.push(field.clone());
}
filter_columns.push(self.filter_column(row.clone()));
columns.push(self.table_column(row.clone())).unwrap();
let mut table_field_info = object! {};
match mode.as_str() {
"table" => table_field_info = row.clone(),
"array" => table_field_json.push(field.clone()),
_ => {}
}
if !table_field_info.is_empty() {
table_fields[field.as_str()] = table_field_info;
}
}
let mut tools = self.tools();
let db = tools.db.table(table_name);
if !search.is_empty() {
db.where_and(
&search_field.join("|"),
"like",
format!("%{}%", search).into(),
);
}
for (key, value) in where_or.entries() {
if value.is_empty() {
continue;
}
if value.is_array() {
db.where_or(key, "in", value.clone());
} else if value.is_boolean() {
db.where_or(key, "=", value.clone());
} else {
db.where_or(key, "like", format!("%{}%", value).into());
}
}
for value in where_and.members() {
db.where_and(
value[0].as_str().unwrap(),
value[1].as_str().unwrap(),
value[2].clone(),
);
}
let mut db_list = db.clone();
for item in order.members() {
db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
}
let t = alls_field.join(",");
db_list.field(t.as_str());
if !table_field_json.is_empty() {
db_list.json(&table_field_json.join(","));
}
let mut data = db_list.select();
let mut table_datas = object! {};
let mut ids = HashMap::new();
for item in data.members_mut() {
for (field, _) in table_fields.entries() {
if table_datas[field].is_empty() {
table_datas[field] = array![];
}
let _ = table_datas[field].push(item[field].clone());
}
}
for (field, info) in table_fields.entries_mut() {
let _ = info["fields"].push("id");
let fields_k = info["fields"]
.members()
.map(|x| x.as_str().unwrap())
.collect::<Vec<&str>>();
let table_name = info["table"].clone();
let mut data_list = self
.tools()
.db
.table(table_name.as_str().unwrap())
.where_and("id", "in", table_datas[field].clone())
.field(&fields_k.join(","))
.select();
for item in data_list.members_mut() {
let id = item["id"].as_str().unwrap_or("").to_string();
item.remove("id");
let label = item
.entries()
.map(|(_, v)| v.as_str().unwrap())
.collect::<Vec<&str>>();
ids.insert(
id.clone(),
object! {
value: id.clone(),
label:label.join(" | ").clone(),
},
);
}
}
for item in data.members_mut() {
for (field, _) in table_fields.entries() {
if item[field].is_empty() {
continue;
}
item[field] = ids[item[field].as_str().unwrap()].clone();
}
}
object! {
data:data,
columns:columns,
search_name:search_name.join("/"),
filter_columns:filter_columns,
label_field:label_field,
btn_all:array![],
btn_api:array![]
}
}
fn params_table_tree(&mut self, mut params: JsonValue) -> JsonValue {
params["pid"] = br_fields::str::Str::new(false, "pid", "上级ID", 50, "")
.example("".into())
.field();
params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
.example("".into())
.field();
params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
.example(array![])
.field();
params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
.example(array![])
.field();
params
}
#[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
fn table_tree(
&mut self,
request: JsonValue,
table_name: &str,
pid_field: &str,
label_field: &str,
fields: JsonValue,
hidd_field: Vec<&str>,
show_field: Vec<&str>,
search_fields: Vec<&str>,
_filter_fields: Vec<&str>,
) -> JsonValue {
let search = request["search"].as_str().unwrap_or("");
let pid = request["pid"].clone();
let order = request["order"].clone();
let where_or = request["where_or"].clone();
let where_and = request["where_and"].clone();
let mut columns = array![];
let mut search_name = vec![];
let mut search_field = vec![];
let mut filter_columns = vec![];
let mut table_field_json = vec![];
let mut table_fields = object! {};
let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
alls_field.retain(|x| !hidd_field.contains(x));
if !show_field.is_empty() {
alls_field.retain(|x| show_field.contains(x) || *x == "id");
}
for item in alls_field.iter() {
let row = fields[item.clone()].clone();
let field = row["field"].to_string();
let title = row["title"].to_string();
let mode = row["mode"].to_string();
if search_fields.contains(&field.as_str()) {
search_name.push(title);
search_field.push(field.clone());
}
filter_columns.push(self.filter_column(row.clone()));
columns.push(self.table_column(row.clone())).unwrap();
let mut table_field_info = object! {};
match mode.as_str() {
"table" => table_field_info = row.clone(),
"array" => table_field_json.push(field.clone()),
_ => {}
}
if !table_field_info.is_empty() {
table_fields[field.as_str()] = table_field_info;
}
}
let mut tools = self.tools();
let db = tools.db.table(table_name);
db.where_and(pid_field, "=", pid);
if !search.is_empty() {
db.where_and(
&search_field.join("|"),
"like",
format!("%{}%", search).into(),
);
}
for (key, value) in where_or.entries() {
if value.is_empty() {
continue;
}
if value.is_array() {
db.where_or(key, "in", value.clone());
} else if value.is_boolean() {
db.where_or(key, "=", value.clone());
} else {
db.where_or(key, "like", format!("%{}%", value).into());
}
}
for value in where_and.members() {
db.where_and(
value[0].as_str().unwrap(),
value[1].as_str().unwrap(),
value[2].clone(),
);
}
let mut db_list = db.clone();
for item in order.members() {
db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
}
let t = alls_field.join(",");
db_list.field(t.as_str());
if !table_field_json.is_empty() {
db_list.json(&table_field_json.join(","));
}
let mut data = db_list.select();
let mut table_datas = object! {};
let mut ids = HashMap::new();
for item in data.members_mut() {
for (field, _) in table_fields.entries() {
if table_datas[field].is_empty() {
table_datas[field] = array![];
}
let _ = table_datas[field].push(item[field].clone());
}
}
for (field, info) in table_fields.entries_mut() {
let _ = info["fields"].push("id");
let fields_k = info["fields"]
.members()
.map(|x| x.as_str().unwrap())
.collect::<Vec<&str>>();
let table_name = info["table"].clone();
let mut data_list = self
.tools()
.db
.table(table_name.as_str().unwrap())
.where_and("id", "in", table_datas[field].clone())
.field(&fields_k.join(","))
.select();
for item in data_list.members_mut() {
let id = item["id"].as_str().unwrap_or("").to_string();
item.remove("id");
let label = item
.entries()
.map(|(_, v)| v.as_str().unwrap())
.collect::<Vec<&str>>();
ids.insert(
id.clone(),
object! {
value: id.clone(),
label:label.join(" | ").clone(),
},
);
}
}
let mut list = array![];
for item in data.members_mut() {
for (field, _) in table_fields.entries() {
if item[field].is_empty() {
continue;
}
item[field] = ids[item[field].as_str().unwrap()].clone();
}
let _ = list.push(object! {
id:item["id"].as_str().unwrap(),
label:item[label_field].as_str().unwrap(),
data:item.clone(),
});
}
object! {
data:list,
columns:columns,
search_name:search_name.join("/"),
filter_columns:filter_columns,
pid_field:pid_field,
btn_all:array![],
btn_api:array![]
}
}
fn params_table_list(&mut self, mut params: JsonValue) -> JsonValue {
params["page"] = br_fields::int::Int::new(false, "page", "页数", 10, 1)
.example(1.into())
.field();
params["limit"] = br_fields::int::Int::new(false, "limit", "行数", 10, 10)
.example(10.into())
.field();
params["search"] = br_fields::str::Str::new(false, "search", "搜索", 200, "")
.example("".into())
.field();
params["order"] = br_fields::text::Array::new(false, "order", "排序", array![])
.example(array![array!["id", false]])
.field();
params["where_or"] = br_fields::text::Array::new(false, "where_or", "查询条件", array![])
.example(array![])
.field();
params["where_and"] = br_fields::text::Array::new(false, "where_and", "查询条件", array![])
.example(array![])
.field();
params
}
#[cfg(any(feature = "sqlite", feature = "mssql", feature = "mysql"))]
fn table_list(
&mut self,
request: JsonValue,
table_name: &str,
fields: JsonValue,
hidd_field: Vec<&str>,
show_field: Vec<&str>,
search_fields: Vec<&str>,
filter_fields: Vec<&str>,
) -> JsonValue {
let page = request["page"].as_i32().unwrap_or(1);
let limit = request["limit"].as_i32().unwrap_or(10);
let search = request["search"].as_str().unwrap_or("");
let order = request["order"].clone();
let where_or = request["where_or"].clone();
let where_and = request["where_and"].clone();
let mut columns = array![];
let mut search_name = vec![];
let mut search_field = vec![];
let mut filter_columns = vec![];
let mut table_fields = object! {};
let mut alls_field = fields.entries().map(|(x, _)| x).collect::<Vec<&str>>();
alls_field.retain(|x| !hidd_field.contains(x));
if !show_field.is_empty() {
alls_field.retain(|x| show_field.contains(x) || *x == "id");
}
for item in alls_field.iter() {
let key = item.clone();
let field = fields[key]["field"].as_str().unwrap();
let title = fields[key]["title"].as_str().unwrap();
let mode = fields[key]["mode"].as_str().unwrap();
if search_fields.contains(&field) {
search_name.push(title);
search_field.push(field);
}
if filter_fields.contains(&field) {
filter_columns.push(self.filter_column(fields[key].clone()));
}
columns
.push(self.table_column(fields[key].clone()))
.unwrap();
let table_field_info = if mode == "table" {
fields[key].clone()
} else {
JsonValue::Null
};
if !table_field_info.is_empty() {
table_fields[field] = table_field_info;
}
}
let mut tools = self.tools();
let db = tools.db.table(table_name);
if !search.is_empty() {
db.where_and(
&search_field.join("|"),
"like",
format!("%{}%", search).into(),
);
}
for (key, value) in where_or.entries() {
if value.is_empty() {
continue;
}
if value.is_array() {
db.where_or(key, "in", value.clone());
} else if value.is_boolean() {
db.where_or(key, "=", value.clone());
} else {
db.where_or(key, "like", format!("%{}%", value).into());
}
}
for value in where_and.members() {
db.where_and(
value[0].as_str().unwrap(),
value[1].as_str().unwrap(),
value[2].clone(),
);
}
let total = db.clone().count().as_f64().unwrap();
let mut db_list = db.clone();
for item in order.members() {
db_list.order(item[0].as_str().unwrap(), item[1].as_bool().unwrap());
}
let t = alls_field.join(",");
db_list.field(t.as_str());
let mut data = db_list.page(page, limit).select();
let mut table_datas = object! {};
let mut ids = HashMap::new();
for item in data.members_mut() {
if table_fields.is_empty() {
continue;
}
for (field, _) in table_fields.entries() {
if table_datas[field].is_empty() {
table_datas[field] = array![];
}
let _ = table_datas[field].push(item[field].clone());
}
}
for (field, info) in table_fields.entries_mut() {
let _ = info["fields"].push("id");
let fields_k = info["fields"]
.members()
.map(|x| x.as_str().unwrap())
.collect::<Vec<&str>>();
let table_name = info["table"].clone();
let mut data_list = self
.tools()
.db
.table(table_name.as_str().unwrap())
.where_and("id", "in", table_datas[field].clone())
.field(&fields_k.join(","))
.select();
for item in data_list.members_mut() {
let id = item["id"].as_str().unwrap_or("").to_string();
item.remove("id");
let label = item
.entries()
.map(|(_, v)| v.as_str().unwrap())
.collect::<Vec<&str>>();
ids.insert(
id.clone(),
object! {
value: id.clone(),
label:label.join(" | ").clone(),
},
);
}
}
for item in data.members_mut() {
if table_fields.is_empty() {
continue;
}
for (field, _) in table_fields.entries() {
if item[field].is_empty() {
continue;
}
let key = item[field].as_str().unwrap_or("");
if key.is_empty() {
continue;
}
if ids.get(key).is_none(){
continue;
}
item[field] = ids.get(key).unwrap().clone();
}
}
object! {
total:total,
data:data,
columns:columns,
search_name:search_name.join("/"),
filter_columns:filter_columns,
btn_all:array![],
btn_api:array![],
btn_ids:array![]
}
}
fn table_column(&mut self, field: JsonValue) -> JsonValue {
object! {
name:field["field"].clone(),
label:field["title"].clone(),
align:"center",
field:field["field"].clone(),
sortable:true,
mode:field["mode"].clone(),
}
}
fn filter_column(&mut self, field: JsonValue) -> JsonValue {
object! {
name:field["field"].clone(),
label:field["title"].clone(),
mode:field["mode"].clone(),
option:field["option"].clone(),
api:field["api"].clone(),
}
}
fn tools(&mut self) -> Tools {
let tools = PLUGIN_TOOLS.lock().unwrap();
let tools = tools.get("tools").unwrap().clone();
tools
}
fn btn_info(
&mut self,
btn_type: BtnType,
btn_color: BtnColor,
title: &str,
desc: &str,
url: &str,
cnd: Vec<JsonValue>,
) -> JsonValue {
object! {
api:self.api().clone(),
title:if title.is_empty() {self.title()}else{title},
desc:if desc.is_empty() {self.description()}else{desc},
btn_type:btn_type.str(),
color:btn_color.str(),
icon:self.icon(),
cnd:cnd,
url:url,
path:self.api().replace(".","/"),
fields:self.params()
}
}
fn btn(&mut self) -> Btn {
let mut btn = Btn::new(self.api().as_str());
btn.fields(self.params().clone());
btn.icon(self.icon());
btn.desc(self.description());
btn.title(self.title());
btn.btn_type(BtnType::Api);
btn.btn_color(BtnColor::Primary);
btn.path(self.api().clone().replace(".", "/").as_str());
btn
}
}
#[derive(Debug, Clone)]
pub struct Btn {
api: String,
title: String,
desc: String,
btn_type: BtnType,
color: BtnColor,
icon: String,
cnd: Vec<JsonValue>,
url: String,
path: String,
fields: JsonValue,
}
impl Btn {
pub fn new(api: &str) -> Self {
Self {
api: api.to_string(),
title: "".to_string(),
desc: "".to_string(),
btn_type: BtnType::Api,
color: BtnColor::Primary,
icon: "".to_string(),
cnd: vec![],
url: "".to_string(),
path: "".to_string(),
fields: object! {},
}
}
pub fn path(&mut self, path: &str) -> &mut Self {
self.path = path.to_string();
self
}
pub fn cnd(&mut self, cnd: Vec<JsonValue>) -> &mut Self {
self.cnd = cnd;
self
}
pub fn btn_type(&mut self, btn_type: BtnType) -> &mut Self {
self.btn_type = btn_type;
self
}
pub fn btn_color(&mut self, btn_color: BtnColor) -> &mut Self {
self.color = btn_color;
self
}
pub fn fields(&mut self, fields: JsonValue) -> &mut Self {
self.fields = fields;
self
}
pub fn url(&mut self, url: &str) -> &mut Self {
self.url = url.to_string();
self
}
pub fn title(&mut self, title: &str) -> &mut Self {
self.title = title.to_string();
self
}
pub fn desc(&mut self, desc: &str) -> &mut Self {
self.desc = desc.to_string();
self
}
pub fn icon(&mut self, icon: &str) -> &mut Self {
self.icon = icon.to_string();
self
}
pub fn json(&mut self) -> JsonValue {
object! {
api:self.api.clone(),
title:self.title.clone(),
desc:self.desc.clone(),
btn_type:self.btn_type.clone().str(),
color:self.color.clone().str(),
icon:self.icon.clone(),
cnd:self.cnd.clone(),
url:self.url.clone(),
path:self.path.clone(),
fields:self.fields.clone()
}
}
}
#[derive(Debug, Clone)]
pub enum InterfaceType {
API,
BTN,
MENU,
}
impl InterfaceType {
pub fn str(self) -> &'static str {
match self {
InterfaceType::API => "api",
InterfaceType::BTN => "btn",
InterfaceType::MENU => "menu",
}
}
pub fn types() -> Vec<&'static str> {
vec!["api", "btn", "menu"]
}
}
#[derive(Debug, Clone)]
pub enum BtnType {
Form,
FormDownload,
FormCustom,
Url,
Api,
Download,
Path,
DialogCustom,
}
impl BtnType {
fn str(self) -> &'static str {
match self {
BtnType::Form => "form",
BtnType::FormDownload => "form_download",
BtnType::FormCustom => "form_custom",
BtnType::Api => "api",
BtnType::Download => "download",
BtnType::Url => "url",
BtnType::Path => "path",
BtnType::DialogCustom => "dialog_custom",
}
}
}
#[derive(Debug, Clone)]
pub enum BtnColor {
Primary,
Red,
Blue,
Yellow,
Green,
}
impl BtnColor {
fn str(self) -> &'static str {
match self {
BtnColor::Primary => "primary",
BtnColor::Red => "negative",
BtnColor::Blue => "info",
BtnColor::Yellow => "warning",
BtnColor::Green => "positive",
}
}
}