250 lines
7.5 KiB
Rust
250 lines
7.5 KiB
Rust
use crate::auth;
|
|
|
|
use auth::AuthUser;
|
|
use crate::Db;
|
|
|
|
use rocket_dyn_templates::{Template, context};
|
|
use rocket::form::Form;
|
|
use rocket::response::Redirect;
|
|
use inventur_db;
|
|
use rocket::serde::{Serialize, Deserialize, json::Json};
|
|
use rocket::http::{Status, Cookie, CookieJar, SameSite};
|
|
use inventur_db::FIELDTYPE;
|
|
|
|
#[derive(FromForm)]
|
|
struct DeleteColumn {
|
|
tblid: i32,
|
|
id_in_table: i32,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct NewEntry {
|
|
tblid: i32,
|
|
cells: Vec<String>,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct EditEntry {
|
|
tblid: i32,
|
|
cells: Vec<String>,
|
|
row_pos: i32,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct DeleteEntry {
|
|
tblid: i32,
|
|
row_pos: i32,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct EditTname {
|
|
tblid: i32,
|
|
new_name: String,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct NewTable {
|
|
name: String,
|
|
field_names: Vec<String>,
|
|
field_types: Vec<isize>,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
struct ImportTable {
|
|
name: String,
|
|
columns: Vec<String>,
|
|
rows: Vec<Vec<String>>,
|
|
}
|
|
|
|
#[derive(FromForm)]
|
|
struct DeleteTable {
|
|
tblid: i32,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(crate = "rocket::serde")]
|
|
struct JRows {
|
|
rows: Vec<Vec<String>>,
|
|
}
|
|
|
|
pub async fn get_tids(conn: &Db, uid: i32) -> (Vec<i32>, Vec<String>) {
|
|
let mut tids = conn.run(move |c| inventur_db::get_user_tblids(c, uid)).await;
|
|
let tnames;
|
|
if tids.is_none() {
|
|
tids = Some(Vec::new());
|
|
tnames = Some(Vec::new());
|
|
}else {
|
|
let tids = tids.clone().unwrap();
|
|
tnames = conn.run(move |c| inventur_db::get_tblnames(c, tids)).await;
|
|
}
|
|
(tids.unwrap(), tnames.unwrap())
|
|
}
|
|
|
|
#[get("/<tid>", rank=2)]
|
|
pub async fn table_sec(conn: Db, tid: i32, user: AuthUser) -> Redirect {
|
|
let nus : Option<usize> = None;
|
|
let nu8 : Option<u8> = None;
|
|
let nvi32 : Option<Vec<i32>> = None;
|
|
let ns : Option<String> = None;
|
|
Redirect::to(uri!("/table", table(tid, nu8, nus, nvi32, ns)))
|
|
}
|
|
|
|
#[get("/<tid>?<sort_dir>&<sort_field>&<search_fields>&<search_value>")]
|
|
pub async fn table(conn: Db, tid: i32, sort_dir: Option<u8>, sort_field: Option<usize>, search_fields: Option<Vec<i32>>, search_value: Option<String>, user: AuthUser) -> Option<Template> {
|
|
let uid = user.uid;
|
|
let table = conn.run(move |c| inventur_db::get_table(c, tid, uid)).await;
|
|
if table.is_none() {
|
|
return None;
|
|
}
|
|
let mut table = table.unwrap();
|
|
let searchvalue;
|
|
let searchfields;
|
|
if search_value.is_some() && !search_value.clone().unwrap().eq_ignore_ascii_case("") && search_fields.is_some() {
|
|
searchvalue = search_value.unwrap();
|
|
searchfields = search_fields.unwrap();
|
|
table = inventur_db::search_table(table, searchfields.clone(), searchvalue.clone());
|
|
}else {
|
|
if search_value.is_none() {
|
|
searchvalue = String::new();
|
|
} else {
|
|
searchvalue = search_value.unwrap();
|
|
}
|
|
if search_fields.is_none() {
|
|
searchfields = (0i32..(table.column_names.len() as i32)).collect();
|
|
|
|
} else {
|
|
searchfields = search_fields.unwrap();
|
|
}
|
|
}
|
|
|
|
let sortdir;
|
|
if sort_dir.is_none() || sort_dir.unwrap() > 1 {
|
|
sortdir = 0;
|
|
}else {
|
|
sortdir = sort_dir.unwrap();
|
|
}
|
|
let sortfield;
|
|
if sort_field.is_none() {
|
|
sortfield = 0;
|
|
}else {
|
|
sortfield = sort_field.unwrap();
|
|
}
|
|
let table = inventur_db::sort_table(table, sortfield, sortdir);
|
|
|
|
let tname = table.name;
|
|
let column_names = table.column_names;
|
|
let column_types = table.column_types.iter().map(|x: &inventur_db::FIELDTYPE| *x as i32).collect::<Vec<i32>>();
|
|
let rows : Vec<Vec<String>>= table.rows.iter().map(|v| {let mut r = v.cells.clone(); r.insert(0, v.row_pos.to_string()); r}).collect();
|
|
let (tids, tnames) = get_tids(&conn, uid).await;
|
|
|
|
Some(
|
|
Template::render("table",
|
|
context!{
|
|
search_value: searchvalue,
|
|
search_fields: searchfields,
|
|
sort_field: sortfield,
|
|
sort_dir: sortdir,
|
|
tblid: tid,
|
|
tblname: tname,
|
|
tids: tids,
|
|
tnames: tnames,
|
|
column_names: column_names,
|
|
column_types: column_types,
|
|
rows: rows,
|
|
}
|
|
)
|
|
)
|
|
}
|
|
|
|
#[post("/delete", data="<data>")]
|
|
pub async fn delete_table(conn: Db, data: Form<DeleteTable>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let tblid = data.tblid;
|
|
if conn.run(move |c| inventur_db::delete_table(c, tblid, uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/")))
|
|
}
|
|
|
|
#[post("/new", data="<data>")]
|
|
pub async fn new_entry(conn: Db, data: Form<NewEntry>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let cells = data.cells.clone();
|
|
let tblid = data.tblid;
|
|
if conn.run(move |c| inventur_db::add_row(c, data.tblid, cells, uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|
|
|
|
#[post("/edit", data="<data>")]
|
|
pub async fn edit_entry(conn: Db, data: Form<EditEntry>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let cells = data.cells.clone();
|
|
let tblid = data.tblid;
|
|
let row_pos = data.row_pos;
|
|
if conn.run(move |c| inventur_db::edit_row(c, tblid, cells, row_pos, uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|
|
|
|
#[post("/delete", data="<data>")]
|
|
pub async fn delete_entry(conn: Db, data: Form<DeleteEntry>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let tblid = data.tblid;
|
|
let row_pos = data.row_pos;
|
|
if conn.run(move |c| inventur_db::delete_row(c, tblid, row_pos, uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|
|
|
|
#[post("/delete", data="<data>")]
|
|
pub async fn delete_column(conn: Db, data: Form<DeleteColumn>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let tblid = data.tblid;
|
|
let idintbl = data.id_in_table;
|
|
if conn.run(move |c| inventur_db::delete_column(c, tblid, idintbl, uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|
|
|
|
#[post("/name/edit", data="<data>")]
|
|
pub async fn edit_tname(conn: Db, data: Form<EditTname>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let tblid = data.tblid;
|
|
if conn.run(move |c| inventur_db::rename_table(c, data.tblid, data.new_name.clone(), uid)).await.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|
|
|
|
#[post("/create", data="<data>")]
|
|
pub async fn create(conn: Db, data: Form<NewTable>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let tblid = conn.run(move |c| inventur_db::create_table(c, data.name.clone(), data.field_names.clone(), data.field_types.iter().map(|x: &isize| FIELDTYPE::from(*x)).collect::<Vec<FIELDTYPE>>(), uid)).await;
|
|
if tblid.is_none() {
|
|
return Err(Status::Forbidden);
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid.unwrap()))))
|
|
}
|
|
|
|
#[post("/import", data="<data>")]
|
|
pub async fn import_table(conn: Db, data: Json<ImportTable>, user: AuthUser) -> Result<Redirect, Status> {
|
|
let uid = user.uid;
|
|
let columns = data.columns.clone();
|
|
let rows = data.rows.clone();
|
|
let tblid = conn.run(move |c| inventur_db::create_table(c, data.name.clone(), columns.clone(), vec![FIELDTYPE::TEXT; columns.len()], uid)).await;
|
|
if tblid.is_none() {
|
|
return Err(Status::UnprocessableEntity);
|
|
}
|
|
let tblid = tblid.unwrap();
|
|
for row in rows {
|
|
conn.run(move |c| inventur_db::add_row(c, tblid, row, uid)).await;
|
|
}
|
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
|
}
|