Fixed several features
This commit is contained in:
parent
c06ddc9498
commit
45b34f5fc8
|
|
@ -1,20 +0,0 @@
|
||||||
[default]
|
|
||||||
template_dir = "templates"
|
|
||||||
secret_key = "${ROCKET_SECRET_KEY}"
|
|
||||||
address = "0.0.0.0"
|
|
||||||
port = 8001
|
|
||||||
ident = "Randerath Inventur"
|
|
||||||
|
|
||||||
[default.tls]
|
|
||||||
certs="private/cert.pem"
|
|
||||||
key="private/key.pem"
|
|
||||||
|
|
||||||
#[default.databases.inventur]
|
|
||||||
#url = "${ROCKET_DATABASE_URL}"
|
|
||||||
|
|
||||||
[default.oauth.oauth]
|
|
||||||
auth_uri = "https://ldap.randerath.eu/realms/master/protocol/openid-connect/auth"
|
|
||||||
token_uri = "https://ldap.randerath.eu/realms/master/protocol/openid-connect/token"
|
|
||||||
client_id = "randy_inventur"
|
|
||||||
client_secret = "${ROCKET_CLIENT_SECRET}"
|
|
||||||
redirect_uri = "https://inventur.rander.at/auth"
|
|
||||||
|
|
@ -17,5 +17,5 @@ fn main() {
|
||||||
.expect("Usage: add_column <tblid> <name> <uid>.");
|
.expect("Usage: add_column <tblid> <name> <uid>.");
|
||||||
|
|
||||||
let conn = &mut establish_connection();
|
let conn = &mut establish_connection();
|
||||||
println!("{}", add_column(conn, table_id, name, uid).expect("Error"));
|
println!("{}", add_column(conn, table_id, name, crate::FIELDTYPE::TEXT, uid).expect("Error"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,5 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
println!("{}", create_table(conn, name.to_string(), fields, uid).unwrap());
|
println!("{}", create_table(conn, name.to_string(), fields.clone(), vec![crate::FIELDTYPE::TEXT; fields.len()], uid).unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ pub fn create_jrcell_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i3
|
||||||
create_jrcell(conn, ntrid, clmid, &value)
|
create_jrcell(conn, ntrid, clmid, &value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_jrcell_value_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, new_value: String) -> Result<usize, diesel::result::Error> {
|
pub fn change_jrcell_value_relative(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, idintbl: i32, new_value: &String) -> Result<usize, diesel::result::Error> {
|
||||||
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
|
let ntrid = jrentries::get_jrentry_id(conn, tblid, rowpos);
|
||||||
if ntrid.is_err() {
|
if ntrid.is_err() {
|
||||||
return Err(ntrid.err().unwrap());
|
return Err(ntrid.err().unwrap());
|
||||||
|
|
@ -78,7 +78,7 @@ pub fn create_jrcell(conn: &mut MysqlConnection, entryid: i32, columnid: i32, va
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn change_jrcell_value(conn: &mut MysqlConnection, entryid: i32, columnid: i32, new_value: String) -> Result<usize, diesel::result::Error> {
|
pub fn change_jrcell_value(conn: &mut MysqlConnection, entryid: i32, columnid: i32, new_value: &String) -> Result<usize, diesel::result::Error> {
|
||||||
diesel::update(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
|
diesel::update(jrcells.filter(jrentry_id.eq(entryid)).filter(jrcolumn_id.eq(columnid)))
|
||||||
.set(cell_value.eq(new_value))
|
.set(cell_value.eq(new_value))
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
|
|
@ -96,3 +96,10 @@ pub fn get_entry_cells(conn: &mut MysqlConnection, entryid: i32) -> Result<Vec<J
|
||||||
.select(Jrcell::as_select())
|
.select(Jrcell::as_select())
|
||||||
.load(conn)
|
.load(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_entry_cell_ids(conn: &mut MysqlConnection, entryid: i32) -> Result<Vec<i32>, diesel::result::Error> {
|
||||||
|
jrcells
|
||||||
|
.filter(jrentry_id.eq(entryid))
|
||||||
|
.select(id)
|
||||||
|
.load(conn)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ use models::{ Jrcolumn, NewJrcolumn };
|
||||||
use schema::jrcolumns::dsl::{ jrcolumns, id, name, jrtable_id, id_in_table };
|
use schema::jrcolumns::dsl::{ jrcolumns, id, name, jrtable_id, id_in_table };
|
||||||
|
|
||||||
|
|
||||||
pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String) -> Result<usize, diesel::result::Error> {
|
pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String, clmtype: crate::FIELDTYPE) -> Result<usize, diesel::result::Error> {
|
||||||
use schema::jrentries::dsl::{ jrentries, jrtable_id };
|
use schema::jrentries::dsl::{ jrentries, jrtable_id };
|
||||||
use models::{ Jrentry, NewJrcell };
|
use models::{ Jrentry, NewJrcell };
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String)
|
||||||
return ncols;
|
return ncols;
|
||||||
}
|
}
|
||||||
let ncols = ncols.unwrap() as i32;
|
let ncols = ncols.unwrap() as i32;
|
||||||
let jrcolumn = NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols + 1 };
|
let jrcolumn = NewJrcolumn { name: clmnname.clone(), jrtable_id: tblid, column_type: clmtype as i32, id_in_table: (ncols + 1) as i32 };
|
||||||
let res = diesel::insert_into(crate::schema::jrcolumns::table)
|
let res = diesel::insert_into(crate::schema::jrcolumns::table)
|
||||||
.values(&jrcolumn)
|
.values(&jrcolumn)
|
||||||
.execute(conn);
|
.execute(conn);
|
||||||
|
|
@ -48,16 +48,11 @@ pub fn create_jrcolumn(conn: &mut MysqlConnection, tblid: i32, clmnname: String)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_jrcolumns_empty_tbl(conn: &mut MysqlConnection, tblid: i32, names: Vec<String>) -> Result<usize, diesel::result::Error> {
|
pub fn create_jrcolumns_empty_tbl(conn: &mut MysqlConnection, tblid: i32, names: Vec<String>, types: Vec<crate::FIELDTYPE>) -> Result<usize, diesel::result::Error> {
|
||||||
let mut cols : Vec<NewJrcolumn> = Vec::new();
|
let mut cols : Vec<NewJrcolumn> = Vec::new();
|
||||||
let ncols = jrtables::get_ncols(conn, tblid);
|
|
||||||
if ncols.is_err() {
|
for i in 0..names.len() {
|
||||||
return ncols;
|
cols.push(NewJrcolumn { name: names[i].clone(), column_type: types[i] as i32, jrtable_id: tblid, id_in_table: (i+1) as i32});
|
||||||
}
|
|
||||||
let mut ncols = ncols.unwrap() as i32;
|
|
||||||
for clmnname in names {
|
|
||||||
ncols += 1;
|
|
||||||
cols.push(NewJrcolumn { name: clmnname, jrtable_id: tblid, id_in_table: ncols});
|
|
||||||
}
|
}
|
||||||
let cols = cols;
|
let cols = cols;
|
||||||
|
|
||||||
|
|
@ -169,8 +164,8 @@ pub fn move_column(conn: &mut MysqlConnection, clmnid: i32, new_id_in_table: i32
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_column_relative(conn: &mut MysqlConnection, tblid: i32, idinclm: i32) -> Result<usize, diesel::result::Error> {
|
pub fn delete_column_relative(conn: &mut MysqlConnection, tblid: i32, idintbl: i32) -> Result<usize, diesel::result::Error> {
|
||||||
let clmid = get_clmid_relative(conn, tblid, idinclm);
|
let clmid = get_clmid_relative(conn, tblid, idintbl);
|
||||||
if clmid.is_err() {
|
if clmid.is_err() {
|
||||||
return Err(clmid.err().unwrap());
|
return Err(clmid.err().unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ pub fn delete_jrentry_relative(conn: &mut MysqlConnection, tblid: i32, rowpos:
|
||||||
return Err(entryid.err().unwrap());
|
return Err(entryid.err().unwrap());
|
||||||
}
|
}
|
||||||
delete_jrentry(conn, entryid.unwrap())
|
delete_jrentry(conn, entryid.unwrap())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_jrentry(conn: &mut MysqlConnection, entryid: i32) -> Result<usize, diesel::result::Error> {
|
pub fn delete_jrentry(conn: &mut MysqlConnection, entryid: i32) -> Result<usize, diesel::result::Error> {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::jrcolumns;
|
||||||
use models::{ Jrtable, NewJrtable };
|
use models::{ Jrtable, NewJrtable };
|
||||||
use schema::jrtables::dsl::{ jrtables, id, name, owner_id };
|
use schema::jrtables::dsl::{ jrtables, id, name, owner_id };
|
||||||
|
|
||||||
pub fn create_jrtable(conn: &mut MysqlConnection, tblname: &String, field_names: Vec<String>, uid: i32) -> Result<i32, diesel::result::Error> {
|
pub fn create_jrtable(conn: &mut MysqlConnection, tblname: &String, field_names: Vec<String>, field_types: Vec<crate::FIELDTYPE>, uid: i32) -> Result<i32, diesel::result::Error> {
|
||||||
let jrtable = NewJrtable { name: tblname.to_string(), owner_id: uid };
|
let jrtable = NewJrtable { name: tblname.to_string(), owner_id: uid };
|
||||||
|
|
||||||
let tbl = diesel::insert_into(crate::schema::jrtables::table)
|
let tbl = diesel::insert_into(crate::schema::jrtables::table)
|
||||||
|
|
@ -24,7 +24,7 @@ pub fn create_jrtable(conn: &mut MysqlConnection, tblname: &String, field_names:
|
||||||
return Err(tblid.err().unwrap());
|
return Err(tblid.err().unwrap());
|
||||||
}
|
}
|
||||||
let tblid = tblid.unwrap();
|
let tblid = tblid.unwrap();
|
||||||
let cols = jrcolumns::create_jrcolumns_empty_tbl(conn, tblid, field_names);
|
let cols = jrcolumns::create_jrcolumns_empty_tbl(conn, tblid, field_names, field_types);
|
||||||
if cols.is_err() {
|
if cols.is_err() {
|
||||||
return Err(cols.err().unwrap());
|
return Err(cols.err().unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![recursion_limit = "512"]
|
||||||
//! Database API using the table style system provided by this crate
|
//! Database API using the table style system provided by this crate
|
||||||
mod models;
|
mod models;
|
||||||
mod schema;
|
mod schema;
|
||||||
|
|
@ -17,6 +18,8 @@ use diesel::deserialize::FromSql;
|
||||||
use diesel::deserialize;
|
use diesel::deserialize;
|
||||||
use diesel::backend::Backend;
|
use diesel::backend::Backend;
|
||||||
use diesel::sql_types::Integer;
|
use diesel::sql_types::Integer;
|
||||||
|
use diesel::expression::Expression;
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, diesel::FromSqlRow)]
|
#[derive(PartialEq, Clone, Copy, diesel::FromSqlRow)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
|
|
@ -25,6 +28,10 @@ pub enum FIELDTYPE {
|
||||||
NUMBER = 1,
|
NUMBER = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Expression for FIELDTYPE {
|
||||||
|
type SqlType = Integer;
|
||||||
|
}
|
||||||
|
|
||||||
impl<DB> FromSql<Integer, DB> for FIELDTYPE
|
impl<DB> FromSql<Integer, DB> for FIELDTYPE
|
||||||
where DB: Backend, i32: FromSql<Integer,DB> {
|
where DB: Backend, i32: FromSql<Integer,DB> {
|
||||||
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
|
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
|
||||||
|
|
@ -36,6 +43,15 @@ where DB: Backend, i32: FromSql<Integer,DB> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<isize> for FIELDTYPE {
|
||||||
|
fn from(value: isize) -> Self {
|
||||||
|
match value {
|
||||||
|
1 => FIELDTYPE::NUMBER,
|
||||||
|
x => FIELDTYPE::TEXT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// represents and summarised all relevant data of a table.
|
/// represents and summarised all relevant data of a table.
|
||||||
/// Standard return type if whole tables should be returned
|
/// Standard return type if whole tables should be returned
|
||||||
pub struct Tbl {
|
pub struct Tbl {
|
||||||
|
|
@ -169,7 +185,7 @@ pub fn search_table(tbl: Tbl, search_fields: Vec<i32>, search_value: String) ->
|
||||||
let mut field_sets = HashSet::new();
|
let mut field_sets = HashSet::new();
|
||||||
for field in search_fields {
|
for field in search_fields {
|
||||||
for row in &rows {
|
for row in &rows {
|
||||||
if row.cells[field as usize].contains(&search_value) {
|
if row.cells[field as usize].to_lowercase().contains(&search_value) {
|
||||||
field_sets.insert(row.clone());
|
field_sets.insert(row.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -241,11 +257,11 @@ pub fn delete_table(conn: &mut MysqlConnection, tblid: i32, uid: i32) -> Option<
|
||||||
/// Returns the id of the newly created table if the action seems to have been successful and the requesting user is the
|
/// Returns the id of the newly created table if the action seems to have been successful and the requesting user is the
|
||||||
/// table's owner.
|
/// table's owner.
|
||||||
/// None otherwise.
|
/// None otherwise.
|
||||||
pub fn create_table(conn: &mut MysqlConnection, name: String, field_names: Vec<String>, uid: i32) -> Option<i32> {
|
pub fn create_table(conn: &mut MysqlConnection, name: String, field_names: Vec<String>, field_types: Vec<crate::FIELDTYPE>, uid: i32) -> Option<i32> {
|
||||||
if jrtables::get_tbl_by_name_uid(conn, &name, uid).is_ok() {
|
if jrtables::get_tbl_by_name_uid(conn, &name, uid).is_ok() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if jrtables::create_jrtable(conn, &name, field_names, uid).is_err() {
|
if jrtables::create_jrtable(conn, &name, field_names, field_types, uid).is_err() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let tblid = jrtables::get_tbl_by_name_uid(conn, &name, uid);
|
let tblid = jrtables::get_tbl_by_name_uid(conn, &name, uid);
|
||||||
|
|
@ -327,8 +343,21 @@ pub fn move_row(conn: &mut MysqlConnection, tblid: i32, rowpos: i32, newpos: i32
|
||||||
Some(true)
|
Some(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn edit_row(conn: &mut MysqlConnection, tblid: i32, cells: Vec<String>, row_pos: i32, uid: i32) -> Option<bool> {
|
||||||
|
let owner = jrtables::get_owner_id(conn, tblid);
|
||||||
|
if owner.is_err() || owner.unwrap() != uid {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
for (i, cell) in cells.iter().enumerate() {
|
||||||
|
if jrcells::change_jrcell_value_relative(conn, tblid, row_pos, (i+1) as i32, cell).is_err() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(true)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn edit_cell(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, column_pos: i32, new_value: String, uid: i32) -> Option<bool> {
|
|
||||||
|
pub fn edit_cell(conn: &mut MysqlConnection, tblid: i32, row_pos: i32, column_pos: i32, new_value: &String, uid: i32) -> Option<bool> {
|
||||||
let owner = jrtables::get_owner_id(conn, tblid);
|
let owner = jrtables::get_owner_id(conn, tblid);
|
||||||
if owner.is_err() ||
|
if owner.is_err() ||
|
||||||
owner.unwrap() != uid ||
|
owner.unwrap() != uid ||
|
||||||
|
|
@ -350,11 +379,11 @@ pub fn move_column(conn: &mut MysqlConnection, tblid:i32, column_pos: i32, new_c
|
||||||
Some(true)
|
Some(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_column(conn: &mut MysqlConnection, tblid: i32, name: String, uid: i32) -> Option<i32> {
|
pub fn add_column(conn: &mut MysqlConnection, tblid: i32, name: String, clmtype: FIELDTYPE, uid: i32) -> Option<i32> {
|
||||||
let owner = jrtables::get_owner_id(conn, tblid);
|
let owner = jrtables::get_owner_id(conn, tblid);
|
||||||
if owner.is_err() ||
|
if owner.is_err() ||
|
||||||
owner.unwrap() != uid ||
|
owner.unwrap() != uid ||
|
||||||
jrcolumns::create_jrcolumn(conn, tblid, name).is_err()
|
jrcolumns::create_jrcolumn(conn, tblid, name, clmtype).is_err()
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ pub struct Jrcolumn {
|
||||||
pub struct NewJrcolumn {
|
pub struct NewJrcolumn {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub jrtable_id: i32,
|
pub jrtable_id: i32,
|
||||||
|
pub column_type: i32,
|
||||||
pub id_in_table: i32,
|
pub id_in_table: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,9 @@ async fn rocket() -> _ {
|
||||||
.attach(Db::fairing())
|
.attach(Db::fairing())
|
||||||
.attach(OAuth2::<auth::RanderathIdentity>::fairing("oauth"))
|
.attach(OAuth2::<auth::RanderathIdentity>::fairing("oauth"))
|
||||||
.mount("/", routes![auth::oauth_login, auth::oauth_callback, home, login_home])
|
.mount("/", routes![auth::oauth_login, auth::oauth_callback, home, login_home])
|
||||||
.mount("/table", routes![table::table, table::table_sec, table::edit_tname, table::create, table::import_table])
|
.mount("/table", routes![table::table, table::table_sec, table::edit_tname, table::create, table::import_table, table::delete_table])
|
||||||
.mount("/entry", routes![table::new_entry])
|
.mount("/row", routes![table::new_entry, table::edit_entry, table::delete_entry])
|
||||||
|
.mount("/column", routes![table::delete_column])
|
||||||
.register("/", catchers![auth::redirect_to_login])
|
.register("/", catchers![auth::redirect_to_login])
|
||||||
.mount("/static", FileServer::from(relative!("static")))
|
.mount("/static", FileServer::from(relative!("static")))
|
||||||
|
|
||||||
|
|
|
||||||
83
src/table.rs
83
src/table.rs
|
|
@ -9,8 +9,13 @@ use rocket::response::Redirect;
|
||||||
use inventur_db;
|
use inventur_db;
|
||||||
use rocket::serde::{Serialize, Deserialize, json::Json};
|
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||||
use rocket::http::{Status, Cookie, CookieJar, SameSite};
|
use rocket::http::{Status, Cookie, CookieJar, SameSite};
|
||||||
|
use inventur_db::FIELDTYPE;
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
struct DeleteColumn {
|
||||||
|
tblid: i32,
|
||||||
|
id_in_table: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct NewEntry {
|
struct NewEntry {
|
||||||
|
|
@ -18,6 +23,19 @@ struct NewEntry {
|
||||||
cells: Vec<String>,
|
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)]
|
#[derive(FromForm)]
|
||||||
struct EditTname {
|
struct EditTname {
|
||||||
tblid: i32,
|
tblid: i32,
|
||||||
|
|
@ -27,7 +45,8 @@ struct EditTname {
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct NewTable {
|
struct NewTable {
|
||||||
name: String,
|
name: String,
|
||||||
fields: Vec<String>,
|
field_names: Vec<String>,
|
||||||
|
field_types: Vec<isize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
@ -38,6 +57,11 @@ struct ImportTable {
|
||||||
rows: Vec<Vec<String>>,
|
rows: Vec<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(FromForm)]
|
||||||
|
struct DeleteTable {
|
||||||
|
tblid: i32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
struct JRows {
|
struct JRows {
|
||||||
|
|
@ -109,7 +133,8 @@ pub async fn table(conn: Db, tid: i32, sort_dir: Option<u8>, sort_field: Option<
|
||||||
let table = inventur_db::sort_table(table, sortfield, sortdir);
|
let table = inventur_db::sort_table(table, sortfield, sortdir);
|
||||||
|
|
||||||
let tname = table.name;
|
let tname = table.name;
|
||||||
let columns = table.column_names;
|
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 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;
|
let (tids, tnames) = get_tids(&conn, uid).await;
|
||||||
|
|
||||||
|
|
@ -124,13 +149,24 @@ pub async fn table(conn: Db, tid: i32, sort_dir: Option<u8>, sort_field: Option<
|
||||||
tblname: tname,
|
tblname: tname,
|
||||||
tids: tids,
|
tids: tids,
|
||||||
tnames: tnames,
|
tnames: tnames,
|
||||||
columns: columns,
|
column_names: column_names,
|
||||||
|
column_types: column_types,
|
||||||
rows: rows,
|
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>")]
|
#[post("/new", data="<data>")]
|
||||||
pub async fn new_entry(conn: Db, data: Form<NewEntry>, user: AuthUser) -> Result<Redirect, Status> {
|
pub async fn new_entry(conn: Db, data: Form<NewEntry>, user: AuthUser) -> Result<Redirect, Status> {
|
||||||
let uid = user.uid;
|
let uid = user.uid;
|
||||||
|
|
@ -142,6 +178,40 @@ pub async fn new_entry(conn: Db, data: Form<NewEntry>, user: AuthUser) -> Result
|
||||||
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
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>")]
|
#[post("/name/edit", data="<data>")]
|
||||||
pub async fn edit_tname(conn: Db, data: Form<EditTname>, user: AuthUser) -> Result<Redirect, Status> {
|
pub async fn edit_tname(conn: Db, data: Form<EditTname>, user: AuthUser) -> Result<Redirect, Status> {
|
||||||
let uid = user.uid;
|
let uid = user.uid;
|
||||||
|
|
@ -155,7 +225,7 @@ pub async fn edit_tname(conn: Db, data: Form<EditTname>, user: AuthUser) -> Resu
|
||||||
#[post("/create", data="<data>")]
|
#[post("/create", data="<data>")]
|
||||||
pub async fn create(conn: Db, data: Form<NewTable>, user: AuthUser) -> Result<Redirect, Status> {
|
pub async fn create(conn: Db, data: Form<NewTable>, user: AuthUser) -> Result<Redirect, Status> {
|
||||||
let uid = user.uid;
|
let uid = user.uid;
|
||||||
let tblid = conn.run(move |c| inventur_db::create_table(c, data.name.clone(), data.fields.clone(), uid)).await;
|
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() {
|
if tblid.is_none() {
|
||||||
return Err(Status::Forbidden);
|
return Err(Status::Forbidden);
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +237,7 @@ pub async fn import_table(conn: Db, data: Json<ImportTable>, user: AuthUser) ->
|
||||||
let uid = user.uid;
|
let uid = user.uid;
|
||||||
let columns = data.columns.clone();
|
let columns = data.columns.clone();
|
||||||
let rows = data.rows.clone();
|
let rows = data.rows.clone();
|
||||||
let tblid = conn.run(move |c| inventur_db::create_table(c, data.name.clone(), columns, uid)).await;
|
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() {
|
if tblid.is_none() {
|
||||||
return Err(Status::UnprocessableEntity);
|
return Err(Status::UnprocessableEntity);
|
||||||
}
|
}
|
||||||
|
|
@ -177,4 +247,3 @@ pub async fn import_table(conn: Db, data: Json<ImportTable>, user: AuthUser) ->
|
||||||
}
|
}
|
||||||
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
Ok(Redirect::to(uri!("/table", table_sec(tblid))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,193 +1,239 @@
|
||||||
{# vim: set filetype=html :#}
|
{# vim: set filetype=html :#}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<!--
|
<!--
|
||||||
This file is part of Inventory.
|
This file is part of Inventory.
|
||||||
|
|
||||||
Inventory is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
Inventory is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with Inventory. If not, see <https://www.gnu.org/licenses/>.
|
You should have received a copy of the GNU General Public License along with Inventory. If not, see <https://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
<html>
|
<html>
|
||||||
<head lang="en">
|
<head lang="en">
|
||||||
<meta name="author" content="Johannes Randerath" />
|
<meta name="author" content="Johannes Randerath" />
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script src="https://unpkg.com/papaparse@latest/papaparse.min.js"></script>
|
<script src="https://unpkg.com/papaparse@latest/papaparse.min.js"></script>
|
||||||
<title>Inventory - {% block pagename %}{% endblock pagename %}</title>
|
<title>Inventory - {% block pagename %}{% endblock pagename %}</title>
|
||||||
<script>
|
<script>
|
||||||
function create_table() {
|
let todelete = "";
|
||||||
document.getElementById('create_table').submit().clear();
|
function create_table() {
|
||||||
document.getElementById('dynamic_columns').innerHTML = "";
|
document.getElementById('create_table').submit().reset();
|
||||||
ncol = 1;
|
document.getElementById('dynamic_columns').innerHTML = "";
|
||||||
|
ncol = 1;
|
||||||
|
}
|
||||||
|
function set_modal_target(modal_target) {
|
||||||
|
document.getElementById('modal_caller').innerHTML = modal_target;
|
||||||
|
}
|
||||||
|
function start_ajax(path, listener) {
|
||||||
|
let req = new XMLHttpRequest();
|
||||||
|
req.open('GET', path, true);
|
||||||
|
req.send();
|
||||||
|
req.onReadyStateChange = function() {
|
||||||
|
if (req.readyState == XMLHttpRequest.DONE) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
function import_table() {
|
||||||
|
console.log("1");
|
||||||
|
Papa.parse(document.getElementById('import_file').files[0], {
|
||||||
|
complete: function process(result) {
|
||||||
|
console.log("2");
|
||||||
|
let csv = result.data;
|
||||||
|
let req = new XMLHttpRequest();
|
||||||
|
req.open("POST", "/table/import", true);
|
||||||
|
req.responseType = 'blob';
|
||||||
|
req.setRequestHeader('Content-Type', 'application/json');
|
||||||
|
let cols = csv[0];
|
||||||
|
let rows = csv.slice(1);
|
||||||
|
if (rows[rows.length - 1].length != cols.length) {
|
||||||
|
rows = rows.slice(0, rows.length-1);
|
||||||
}
|
}
|
||||||
function set_modal_target(modal_target) {
|
req.send(JSON.stringify({
|
||||||
document.getElementById('modal_caller').innerHTML = modal_target;
|
name: document.getElementById('import_name').value,
|
||||||
}
|
columns: cols,
|
||||||
function start_ajax(path, listener) {
|
rows: rows,
|
||||||
let req = new XMLHttpRequest();
|
}));
|
||||||
req.open('GET', path, true);
|
req.onload = function(resp) {
|
||||||
req.send();
|
if (this.readyState == 4) {
|
||||||
req.onReadyStateChange = function() {
|
window.location.href = req.responseURL;
|
||||||
if (req.readyState == XMLHttpRequest.DONE) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
function import_table() {
|
}
|
||||||
console.log("1");
|
});
|
||||||
Papa.parse(document.getElementById('import_file').files[0], {
|
};
|
||||||
complete: function process(result) {
|
function add_column() {
|
||||||
console.log("2");
|
ncol += 1;
|
||||||
let csv = result.data;
|
document.getElementById('dynamic_columns').innerHTML += `
|
||||||
let req = new XMLHttpRequest();
|
<div class='row mt-3' id='columns'>
|
||||||
req.open("POST", "/table/import", true);
|
<div class='col-auto align-bottom'>
|
||||||
req.responseType = 'blob';
|
<div class='form-text me-1' id='field_index'>
|
||||||
req.setRequestHeader('Content-Type', 'application/json');
|
<strong>${ncol}</strong>
|
||||||
let cols = csv[0];
|
</div>
|
||||||
let rows = csv.slice(1);
|
</div>
|
||||||
if (rows[rows.length - 1].length != cols.length) {
|
<div class='col-auto'>
|
||||||
rows = rows.slice(0, rows.length-1);
|
<input type='text' class='form-control' name='field_names' id='field_name' aria-describedby='field_name_label'>
|
||||||
}
|
</div>
|
||||||
req.send(JSON.stringify({
|
<div class='col-auto'>
|
||||||
name: document.getElementById('import_name').value,
|
<select class='form-select' aria-label='data type' name='field_types'>
|
||||||
columns: cols,
|
<option value='0' selected>Text</option>
|
||||||
rows: rows,
|
<option value='1'>Number</option>
|
||||||
}));
|
</select>
|
||||||
req.onload = function(resp) {
|
</div>
|
||||||
if (this.readyState == 4) {
|
</div>`;
|
||||||
window.location.href = req.responseURL;
|
};
|
||||||
}
|
function confirm_delete(form) {
|
||||||
};
|
document.getElementById(`form_edit_${form}`).reset();
|
||||||
}
|
$('#confirm_delete_modal').modal('show');
|
||||||
});
|
document.getElementById('confirm_delete_modal_entity').innerHTML = form;
|
||||||
}
|
document.getElementById('confirm_delete_modal_button').onclick = function () {
|
||||||
</script>
|
document.getElementById(`form_delete_${form}`).submit();
|
||||||
{% block script %}{% endblock script %}
|
}
|
||||||
</head>
|
}
|
||||||
|
</script>
|
||||||
|
{% block script %}{% endblock script %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class='navbar navbar-expand-lg bg-body bg-body-tertiary'>
|
||||||
|
<div class='container-fluid'>
|
||||||
|
<a class='navbar-brand' href='/'>Inventory</a>
|
||||||
|
<button class='navbar-toggler' type='button' data-bs-toggle='collapse' data-bs-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
|
||||||
|
<span class='navbar-toggler-icon'></span>
|
||||||
|
</button>
|
||||||
|
<div class='collapse navbar-collapse' id='navbarSupportedContent'>
|
||||||
|
<ul class='navbar-nav me-auto mb-2 mb-lg-0'>
|
||||||
|
<li class='nav-item dropdown'>
|
||||||
|
<a class='nav-link dropdown-toggle' role='button' data-bs-toggle='dropdown' aria-expanded='false'>
|
||||||
|
Choose Table
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
{% for tid in tids %}
|
||||||
|
<li class="dropdown-option"><a class="nav-link" href="/table/{{ tid }}">{{ tnames[loop.index0] }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" role="button" data-bs-toggle="modal" data-bs-target="#new_table">
|
||||||
|
<i class="bi bi-plus-lg"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" role="button" data-bs-toggle="modal" data-bs-target="#import_table">
|
||||||
|
<i class="bi bi-folder2-open"></i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<nav class='navbar navbar-expand-lg bg-body bg-body-tertiary'>
|
{% block body %}{% endblock body %}
|
||||||
<div class='container-fluid'>
|
|
||||||
<a class='navbar-brand' href='/'>Inventory</a>
|
|
||||||
<button class='navbar-toggler' type='button' data-bs-toggle='collapse' data-bs-target='#navbarSupportedContent' aria-controls='navbarSupportedContent' aria-expanded='false' aria-label='Toggle navigation'>
|
|
||||||
<span class='navbar-toggler-icon'></span>
|
|
||||||
</button>
|
|
||||||
<div class='collapse navbar-collapse' id='navbarSupportedContent'>
|
|
||||||
<ul class='navbar-nav me-auto mb-2 mb-lg-0'>
|
|
||||||
<li class='nav-item dropdown'>
|
|
||||||
<a class='nav-link dropdown-toggle' role='button' data-bs-toggle='dropdown' aria-expanded='false'>
|
|
||||||
Choose Table
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
{% for tid in tids %}
|
|
||||||
<li class="dropdown-option"><a class="nav-link" href="/table/{{ tid }}">{{ tnames[loop.index0] }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" role="button" data-bs-toggle="modal" data-bs-target="#new_table">
|
|
||||||
<i class="bi bi-plus-lg"></i>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" role="button" data-bs-toggle="modal" data-bs-target="#import_table">
|
|
||||||
<i class="bi bi-folder2-open"></i>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{% block body %}{% endblock body %}
|
<!-- Modals -->
|
||||||
|
<!-- Create new table -->
|
||||||
<!-- Modals -->
|
<div class="modal fade" id="new_table" tabindex="-1" aria-hidden="true">
|
||||||
<!-- Create new table -->
|
<div class="modal-dialog">
|
||||||
<div class="modal fade" id="new_table" tabindex="-1" aria-hidden="true">
|
<div class="modal-content">
|
||||||
<div class="modal-dialog">
|
<div class="modal-header">
|
||||||
<div class="modal-content">
|
<h1 class="modal-title fs-5">New table</h1>
|
||||||
<div class="modal-header">
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
<h1 class="modal-title fs-5">New table</h1>
|
</div>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<div class="modal-body">
|
||||||
</div>
|
<form id="create_table" method="post" action="/table/create">
|
||||||
<div class="modal-body">
|
<div class="mb-3">
|
||||||
<form id="create_table" method="post" action="/table/create">
|
<label for="new_table_name" class="form-label">Name</label>
|
||||||
<div class="mb-3">
|
<input type="text" class="form-control" name="name" aria-describedby="new_table_name_label">
|
||||||
<label for="new_table_name" class="form-label">Name</label>
|
<div id="new_table_name_label" class="form-text">Name of the new table</div>
|
||||||
<input type="text" class="form-control" name="name" aria-describedby="new_table_name_label">
|
</div>
|
||||||
<div id="new_table_name_label" class="form-text">Name of the new table</div>
|
<div class="mb-3">
|
||||||
</div>
|
<div class="row" id="columns">
|
||||||
<div class="mb-3">
|
<div class="col-auto align-bottom me-1">
|
||||||
<div class="row" id="columns">
|
<label for="field_index" class="form-label">#</label>
|
||||||
<div class="col-auto align-bottom me-1">
|
<div class="form-text" id="field_index"><strong>1</strong></div>
|
||||||
<label for="field_index" class="form-label">#</label>
|
</div>
|
||||||
<div class="form-text" id="field_index"><strong>1</strong></div>
|
<div class="col-auto">
|
||||||
</div>
|
<label for="fields" class="form-label">Column name</label>
|
||||||
<div class="col-auto">
|
<input type="text" class="form-control" id="field_name" aria-describedby="field_name_label" name="field_names">
|
||||||
<label for="fields" class="form-label">Column name</label>
|
</div>
|
||||||
<input type="text" class="form-control" id="field_name" aria-describedby="field_name_label" name="fields">
|
<div class="col-auto">
|
||||||
</div>
|
<label for="field_type" class="form-label">Data type</label>
|
||||||
<div class="col-auto">
|
<select class="form-select" aria-label="data type" name="field_types">
|
||||||
<label for="field_name" class="form-label">Data type</label>
|
<option value="0" selected>Text</option>
|
||||||
<select class="form-select" aria-label="data type">
|
<option value="1">Number</option>
|
||||||
<option value="text" selected>Text</option>
|
</select>
|
||||||
<option value="number">Number</option>
|
</div>
|
||||||
<option value="date">Date</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="dynamic_columns">
|
|
||||||
<!-- Columns added using plus button -->
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="row justify-content-center mb-3 mt-3">
|
|
||||||
<div class="col-auto">
|
|
||||||
<button class="btn btn-primary" type="button" onclick="add_column()"><i class="bi bi-plus-lg"></i></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
|
||||||
<button class="btn btn-primary" type="button" onclick="create_table()">Create</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="dynamic_columns">
|
||||||
|
<!-- Columns added using plus button -->
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="row justify-content-center mb-3 mt-3">
|
||||||
|
<div class="col-auto">
|
||||||
|
<button class="btn btn-primary" type="button" onclick="add_column()"><i class="bi bi-plus-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
||||||
|
<button class="btn btn-primary" type="button" onclick="create_table()">Create</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Import new table -->
|
<!-- Import new table -->
|
||||||
<div class="modal fade" id="import_table" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="import_table" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Import new table</h1>
|
<h1 class="modal-title fs-5">Import new table</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form action="/table/import" method="post" id="form_import_table">
|
<form action="/table/import" method="post" id="form_import_table">
|
||||||
<label for="import_name" class="form-label">Name</label>
|
<label for="import_name" class="form-label">Name</label>
|
||||||
<input type="text" class="form-control" id="import_name" name="name">
|
<input type="text" class="form-control" id="import_name" name="name">
|
||||||
<label for="import_file" class="form-label">File</label>
|
<label for="import_file" class="form-label">File</label>
|
||||||
<input id="import_columns" name="columns" hidden>
|
<input id="import_columns" name="columns" hidden>
|
||||||
<input id="import_rows" name="rows" hidden>
|
<input id="import_rows" name="rows" hidden>
|
||||||
</form>
|
</form>
|
||||||
<input type="file" class="form-control" id="import_file" name="name" accept="text/csv">
|
<input type="file" class="form-control" id="import_file" name="name" accept="text/csv">
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
||||||
<button class="btn btn-primary" type="button" onclick="import_table();">Import</button>
|
<button class="btn btn-primary" type="button" onclick="import_table();">Import</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Confirm delete -->
|
||||||
|
<div class="modal fade" id="confirm_delete_modal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5">Confirm deletion</h1>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<h5>Are you sure you want to delete this <span id="confirm_delete_modal_entity"></span>?</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button"><i class="bi bi-x"></i></button>
|
||||||
|
<button class="btn btn-danger" type="button" data-bs-dismiss="modal" id="confirm_delete_modal_button"><i class="bi bi-trash3-fill"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% block more_modals %}{% endblock more_modals %}
|
{% block more_modals %}{% endblock more_modals %}
|
||||||
|
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -2,232 +2,303 @@
|
||||||
|
|
||||||
{% extends "base" %}
|
{% extends "base" %}
|
||||||
{% block pagename %}Table{% endblock pagename %}
|
{% block pagename %}Table{% endblock pagename %}
|
||||||
{% block script %}
|
|
||||||
<script type="text/javascript">
|
{% block script %}
|
||||||
let ncol = 1;
|
<script type="text/javascript">
|
||||||
let edit_mode = false;
|
let ncol = 1;
|
||||||
document.addEventListener("DOMContentLoaded", (event) => {
|
let edit_mode = false;
|
||||||
for (let row of document.getElementById("content_table").getElementsByTagName('tbody')[0].rows) {
|
let column_names = [{% for col in column_names %} '{{ col }}', {% endfor %}];
|
||||||
let createClickHandler = function(r) {
|
let column_types = [{% for col in column_types %} {{ col }}, {% endfor %}];
|
||||||
return function() {
|
|
||||||
$('#edit_item').modal('show');
|
document.addEventListener("DOMContentLoaded", (event) => {
|
||||||
};
|
let rows = document.getElementById("content_table").getElementsByTagName('tbody')[0].rows;
|
||||||
};
|
for (let i = 0; i < rows.length; i++)
|
||||||
row.onclick = createClickHandler(row);
|
{
|
||||||
}
|
let row = rows[i];
|
||||||
});
|
let createClickHandler = function(r)
|
||||||
function add_column() {
|
{
|
||||||
ncol += 1;
|
return function()
|
||||||
document.getElementById('dynamic_columns').innerHTML += `
|
{
|
||||||
<div class='row mt-3' id='columns'>
|
$('#edit_entry_modal').modal('show');
|
||||||
<div class='col-auto align-bottom'>
|
document.getElementById('modal_caller').innerHTML = i+1;
|
||||||
<div class='form-text me-1' id='field_index'>
|
document.getElementById('form_edit_entry_rowpos').value = i+1;
|
||||||
<strong>${ncol}</strong>
|
document.getElementById('form_delete_entry_rowpos').value = i+1;
|
||||||
</div>
|
let cells = row.cells;
|
||||||
</div>
|
for (let j = 1; j < cells.length; j++) {
|
||||||
<div class='col-auto'>
|
document.getElementById(`form_edit_entry_${j}`).value = cells[j].innerHTML;
|
||||||
<input type='text' class='form-control' name='fields' id='field_name' aria-describedby='field_name_label'>
|
|
||||||
</div>
|
|
||||||
<div class='col-auto'>
|
|
||||||
<select class='form-select' aria-label='data type'>
|
|
||||||
<option value='text' selected>Text</option>
|
|
||||||
<option value='number'>Number</option>
|
|
||||||
<option value='date'>Date</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
function toggle_edit_tname() {
|
|
||||||
let span = document.getElementById('tname');
|
|
||||||
if (!edit_mode) {
|
|
||||||
span.innerHTML = `
|
|
||||||
<div class='row'>
|
|
||||||
<div class='col-auto ml-1 p-2'>
|
|
||||||
<form id='form_edit_tname' action='/table/name/edit' method='post'>
|
|
||||||
<input name='tblid' value='{{ tblid }}' hidden />
|
|
||||||
<input type='text' class='form-control' id='tname_edit' name='new_name' value='{{ tblname }}' />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div class='col-auto mt-0 pt-0 pr-1'>
|
|
||||||
<button class='btn btn-success' type='button' onclick='toggle_edit_tname()'>
|
|
||||||
<i class='bi bi-check'></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
edit_mode = true;
|
|
||||||
} else {
|
|
||||||
document.getElementById('form_edit_tname').submit().clear();
|
|
||||||
span.innerHTML = '{{ tblname }}';
|
|
||||||
edit_mode = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function add_entry() {
|
|
||||||
document.getElementById('form_add_entry').submit().clear();
|
|
||||||
}
|
}
|
||||||
</script>
|
};
|
||||||
{% endblock script %}
|
};
|
||||||
{% block body %}
|
row.onclick = createClickHandler(row);
|
||||||
<div class="row justify-content-between">
|
}
|
||||||
<div class="col-auto">
|
});
|
||||||
<h1><div class='input-group'><span id="tname">{{ tblname }}</span><button class="btn" type="button" onclick="toggle_edit_tname();"><i class="bi bi-pencil"></i></button></div></h1>
|
|
||||||
</div>
|
function toggle_edit_tname() {
|
||||||
<div class="col-auto">
|
let span = document.getElementById('tname');
|
||||||
<div class="btn-toolbar mt-2" role="toolbar">
|
if (!edit_mode) {
|
||||||
<div class="btn-group me-2">
|
span.innerHTML = `
|
||||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#new_item"><i class="bi bi-plus-lg"></i></button>
|
<div class='row'>
|
||||||
</div>
|
<div class='col-auto ml-1 p-2'>
|
||||||
<form method="get" action="/table/{{ tblid }}">
|
<form id='form_edit_table' action='/table/name/edit' method='post'>
|
||||||
<div class="input-group">
|
<input name='tblid' value='{{ tblid }}' hidden />
|
||||||
<div class="input-group-text dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
<input type='text' class='form-control' id='tname_edit' name='new_name' value='{{ tblname }}' />
|
||||||
<i class="bi bi-table"></i>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<input id="input_search_value" name="search_value" type="text" placeholder="Search" value="{{ search_value }}" class="form-control">
|
<div class='col-auto mt-0 pt-0 pr-1'>
|
||||||
<button class="btn btn-outline-primary" type="submit"><i class="bi bi-search"></i></button>
|
<div class="btn-group" role="group">
|
||||||
<ul class="dropdown-menu">
|
<button class="btn btn-secondary" onclick="toggle_edit_tname();" type="button"><i class="bi bi-x"></i></button>
|
||||||
<select name="search_fields" class="form-select" multiple>
|
<button class='btn btn-success' type='button' onclick='edit_tname()'>
|
||||||
<li><option disabled class="dropdown-header">Search in</option></li>
|
<i class='bi bi-check'></i>
|
||||||
{% for column in columns %}
|
</button>
|
||||||
<li><option class="dropdown-option" value="{{ loop.index - 1 }}" {% if (loop.index - 1) in search_fields %}selected{% endif %}>{{ column }}</option></li>
|
</div>
|
||||||
{% endfor %}
|
<button class='btn btn-danger' type="button" onclick='confirm_delete("table");'><i class="bi bi-trash3-fill"></i></button>
|
||||||
</select>
|
</div>
|
||||||
</ul>
|
<form id="form_delete_table" action="/table/delete" method="post">
|
||||||
</div>
|
<input value="{{ tblid}}" name="tblid" hidden />
|
||||||
</div>
|
</form>`;
|
||||||
</div>
|
edit_mode = true;
|
||||||
</div>
|
document.getElementById('pencil_button_edit_tname').hidden = true;
|
||||||
<br>
|
} else {
|
||||||
<table id="content_table" class="table table-striped table-hover table-responsive table-bordered mt-2">
|
document.getElementById('pencil_button_edit_tname').hidden = false;
|
||||||
<thead>
|
span.innerHTML = '{{ tblname }}';
|
||||||
<tr>
|
edit_mode = false;
|
||||||
<th style="width:7%">
|
}
|
||||||
<div class="row justify-content-between">
|
}
|
||||||
<div class="col-auto">
|
function edit_tname() {
|
||||||
#
|
document.getElementById('form_edit_tname').submit();
|
||||||
</div>
|
toggle_edit_tname();
|
||||||
<div class="col-auto">
|
}
|
||||||
<div class="btn-toolbar">
|
function edit_column(clmn_index) {
|
||||||
<button class="btn p-0 me-2 mdl" type="button" data-bs-toggle="modal" data-bs-target="#filter"><i class="bi bi-filter"></i></button>
|
document.getElementById('form_edit_column_name').value = column_names[clmn_index];
|
||||||
<form method="GET" action="/table/{{ tblid }}">
|
document.getElementById('form_edit_column_type').value = column_types[clmn_index];
|
||||||
<input value="0" name="sort_field" hidden />
|
document.getElementById('modal_caller').innerHTML = column_names[clmn_index];
|
||||||
<input value="{% if sort_field == 0 %}{{ (sort_dir + 1) % 2}}{% else %}0{% endif %}" name="sort_dir" hidden />
|
document.getElementById('form_delete_column_idintbl').value = clmn_index + 1;
|
||||||
{% if sort_field == 0 and sort_dir == 0 %}
|
}
|
||||||
{% set dir='up' %}
|
</script>
|
||||||
{% else %}
|
{% endblock script %}
|
||||||
{% set dir='down' %}
|
{% block body %}
|
||||||
{% endif %}
|
<div class="row justify-content-between">
|
||||||
<button class="btn p-0" type="submit"><i class="bi bi-sort-{{ dir }}"></i></button>
|
<div class="col-auto">
|
||||||
</form>
|
<h1><div class='input-group'><span id="tname">{{ tblname }}</span><button class="btn" type="button" onclick="toggle_edit_tname();" id="pencil_button_edit_tname"><i class="bi bi-pencil"></i></button></div></h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-auto">
|
||||||
</div>
|
<div class="btn-toolbar mt-2" role="toolbar">
|
||||||
</th>
|
<div class="btn-group me-2">
|
||||||
{% for column in columns %}
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#new_item"><i class="bi bi-plus-lg"></i></button>
|
||||||
<th>
|
</div>
|
||||||
<div class="row justify-content-between">
|
<form method="get" action="/table/{{ tblid }}">
|
||||||
<div class="col-auto">
|
<div class="input-group">
|
||||||
{{ column }}
|
<div class="input-group-text dropdown-toggle" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
</div>
|
<i class="bi bi-table"></i>
|
||||||
<div class="col-auto">
|
</div>
|
||||||
<div class="btn-toolbar">
|
<input id="input_search_value" name="search_value" type="text" placeholder="Search" value="{{ search_value }}" class="form-control">
|
||||||
<button class="btn p-0 me-2" type="button" data-bs-toggle="modal" data-bs-target="#filter" onclick="set_modal_target('{{ column }}');"><i class="bi bi-filter"></i></button>
|
<button class="btn btn-outline-primary" type="submit"><i class="bi bi-search"></i></button>
|
||||||
<form method="GET" action="/table/{{ tblid }}">
|
<ul class="dropdown-menu">
|
||||||
<input value="{{ loop.index }}" name="sort_field" hidden />
|
<select name="search_fields" class="form-select" multiple>
|
||||||
<input value="{% if sort_field == loop.index %}{{ (sort_dir + 1) % 2}}{% else %}0{% endif %}" name="sort_dir" hidden />
|
<li><option disabled class="dropdown-header">Search in</option></li>
|
||||||
{% if sort_field == loop.index and sort_dir == 0 %}
|
{% for column in column_names %}
|
||||||
{% set dir='up' %}
|
<li><option class="dropdown-option" value="{{ loop.index - 1 }}" {% if (loop.index - 1) in search_fields %}selected{% endif %}>{{ column }}</option></li>
|
||||||
{% else %}
|
{% endfor %}
|
||||||
{% set dir='down'%}
|
</select>
|
||||||
{% endif %}
|
</ul>
|
||||||
<button class="btn p-0" type="submit"><i class="bi bi-sort-{{ dir }}"></i></button>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<br>
|
||||||
</th>
|
<table id="content_table" class="table table-striped table-hover table-responsive table-bordered mt-2">
|
||||||
{% endfor %}
|
<thead>
|
||||||
</tr>
|
<tr>
|
||||||
</thead>
|
<th style="width:7%">
|
||||||
<tbody>
|
<div class="row justify-content-between">
|
||||||
{% for row in rows %}
|
<div class="col-auto">
|
||||||
<tr>
|
#
|
||||||
{% for column in row %}
|
</div>
|
||||||
<td>{{ column }}</td>
|
<div class="col-auto">
|
||||||
{% endfor %}
|
<div class="btn-toolbar">
|
||||||
</tr>
|
<form method="GET" action="/table/{{ tblid }}">
|
||||||
{% endfor %}
|
<input value="0" name="sort_field" hidden />
|
||||||
</tbody>
|
<input value="{% if sort_field == 0 %}{{ (sort_dir + 1) % 2}}{% else %}0{% endif %}" name="sort_dir" hidden />
|
||||||
</table>
|
{% if sort_field == 0 and sort_dir == 0 %}
|
||||||
|
{% set dir='up' %}
|
||||||
|
{% else %}
|
||||||
|
{% set dir='down' %}
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn p-0" type="submit"><i class="bi bi-sort-{{ dir }}"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
{% for column in column_names %}
|
||||||
|
<th>
|
||||||
|
<div class="row justify-content-between">
|
||||||
|
<div class="col-auto">
|
||||||
|
{{ column }}
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<div class="btn-toolbar">
|
||||||
|
<button class="btn p-0 me-2" type="button" data-bs-toggle="modal" data-bs-target="#edit_column_modal" onclick="edit_column({{ loop.index0 }});"><i class="bi bi-pencil"></i></button>
|
||||||
|
<form method="GET" action="/table/{{ tblid }}">
|
||||||
|
<input value="{{ loop.index }}" name="sort_field" hidden />
|
||||||
|
<input value="{% if sort_field == loop.index %}{{ (sort_dir + 1) % 2}}{% else %}0{% endif %}" name="sort_dir" hidden />
|
||||||
|
{% if sort_field == loop.index and sort_dir == 0 %}
|
||||||
|
{% set dir='up' %}
|
||||||
|
{% else %}
|
||||||
|
{% set dir='down'%}
|
||||||
|
{% endif %}
|
||||||
|
<button class="btn p-0" type="submit"><i class="bi bi-sort-{{ dir }}"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for row in rows %}
|
||||||
|
<tr>
|
||||||
|
{% for column in row %}
|
||||||
|
<td>{{ column }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block more_modals %}
|
{% block more_modals %}
|
||||||
<!-- Add new item -->
|
<!-- Add new item -->
|
||||||
<div class="modal fade" id="new_item" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="new_item" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Add entry</h1>
|
<h1 class="modal-title fs-5">Add entry</h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<h5>Cell values:</h5>
|
<h5>Cell values:</h5>
|
||||||
<br>
|
<br>
|
||||||
<form id="form_add_entry" action="/entry/new" method="post">
|
<form id="form_add_entry" action="/row/new" method="post">
|
||||||
<input name="tblid" value="{{ tblid }}" hidden />
|
<input name="tblid" value="{{ tblid }}" hidden />
|
||||||
{% for column in columns %}
|
{% for column in column_names %}
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<label for="entry_value_{{ column }}" class="form-label" >{{ column }}:</label>
|
<label for="entry_value_{{ column }}" class="form-label" >{{ column }}:</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<input type="text" class="form-control" name="cells" id="entry_value_{{column}}" />
|
<input type="text" class="form-control" name="cells" id="entry_value_{{column}}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
<div class="container row justify-content-between">
|
||||||
<button class="btn btn-primary" type="button" onclick="add_entry()">Add</button>
|
<div class="col-auto">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-auto">
|
||||||
</div>
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button" onclick="document.getElementById('form_add_entry').reset();"><i class="bi bi-x"></i></button>
|
||||||
</div>
|
<button class="btn btn-primary" type="button" onclick="document.getElementById('form_add_entry').submit().reset();"><i class="bi bi-check-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Edit item -->
|
<!-- Edit entry -->
|
||||||
<div class="modal fade" id="edit_item" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="edit_entry_modal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Edit entry</h1>
|
<h1 class="modal-title fs-5"><div class="row"><div class="col-auto">Row <span id="modal_caller"></span></div><div class="col-auto"><i class="bi bi-pencil-fill"></i></div></div></h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
</div>
|
<form action="/row/edit" method="post" id="form_edit_entry">
|
||||||
<div class="modal-footer">
|
<input name="tblid" value="{{ tblid }}" hidden>
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
<input name="row_pos" id="form_edit_entry_rowpos" hidden>
|
||||||
<button class="btn btn-primary" type="button">Save</button>
|
{% for column in column_names %}
|
||||||
</div>
|
<div class="mb-3">
|
||||||
</div>
|
<div class="row">
|
||||||
</div>
|
<div class="col-auto">
|
||||||
</div>
|
<label for="form_edit_entry_{{ loop.index }}" class="form-label">{{ column }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<input type="text" class="form-control" name="cells" id="form_edit_entry_{{ loop.index }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="container row justify-content-between">
|
||||||
|
<div class="col-auto">
|
||||||
|
<form action="/row/delete" method="post" id="form_delete_entry">
|
||||||
|
<input name="tblid" value="{{ tblid }}" hidden>
|
||||||
|
<input id="form_delete_entry_rowpos" name="row_pos" hidden>
|
||||||
|
<button class="btn btn-danger" data-bs-dismiss="modal" type="button" onclick="confirm_delete('entry');"><i class="bi bi-trash3-fill"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button" onclick="document.getElementById('form_edit_entry').reset();"><i class="bi bi-x"></i></button>
|
||||||
|
<button class="btn btn-primary" type="button" onclick="document.getElementById('form_edit_entry').submit().reset();"><i class="bi bi-check-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Filter column -->
|
<!-- Edit column -->
|
||||||
<div class="modal fade" id="filter" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="edit_column_modal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5">Edit filter on <span id="modal_caller"></span></h1>
|
<h1 class="modal-title fs-5"><div class="row"><div class="col-auto"><span id="modal_caller"></span></div><div class="col-auto"><i class="bi bi-pencil-fill"></i></div></div></h1>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
</div>
|
<form action="/column/edit" method="post" id="form_edit_column">
|
||||||
<div class="modal-footer">
|
<input name="tblid" value="{{ tblid }}" hidden>
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button">Close</button>
|
<div class="mb-3">
|
||||||
<button class="btn btn-primary" type="button">Filter</button>
|
<div class="row">
|
||||||
</div>
|
<div class="col-auto">
|
||||||
</div>
|
<label for="form_edit_column_name" class="form-label">Name:</label>
|
||||||
</div>
|
<input type="text" class="form-control" name="name" id="form_edit_column_name" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<label for="form_edit_column_type" class="form-label">Type</label>
|
||||||
|
<select class="form-select" name="column_type" id="form_edit_column_type">
|
||||||
|
<option value="0">Text</option>
|
||||||
|
<option value="1">Number</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<div class="container row justify-content-between">
|
||||||
|
<div class="col-auto">
|
||||||
|
<form action="/column/delete" method="post" id="form_delete_column">
|
||||||
|
<input name="id_in_table" id="form_delete_column_idintbl" hidden>
|
||||||
|
<input name="tblid" value="{{ tblid }}" hidden>
|
||||||
|
<button class="btn btn-danger" data-bs-dismiss="modal" type="button" onclick="confirm_delete('column');"><i class="bi bi-trash3-fill"></i></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button class="btn btn-secondary" data-bs-dismiss="modal" type="button" onclick="document.getElementById('form_edit_column').reset();"><i class="bi bi-x"></i></button>
|
||||||
|
<button class="btn btn-primary" type="button" onclick="document.getElementById('form_edit_column').submit().reset();"><i class="bi bi-check-lg"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock more_modals %}
|
{% endblock more_modals %}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user