1
0

add updating and remove of factories/managers

This commit is contained in:
Rokas Puzonas 2023-04-14 19:15:28 +03:00
parent e3dd339ffe
commit 4f50aee949
12 changed files with 460 additions and 205 deletions

View File

@ -1 +1,2 @@
DATABASE_URL="sqlite:../database.sqlite"
RUST_BACKTRACE=1
DATABASE_URL="mysql://root@localhost/ice_cream"

5
lab2/.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"rust-analyzer.linkedProjects": [
".\\src-tauri\\Cargo.toml"
]
}

View File

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -43,6 +52,15 @@ dependencies = [
"alloc-no-stdlib",
]
[[package]]
name = "anyhow"
version = "1.0.58"
source = "git+https://github.com/Seeker14491/anyhow-tauri.git#b77b49a539d0bc6294359f2abb99bf0097434da7"
dependencies = [
"backtrace",
"serde",
]
[[package]]
name = "anyhow"
version = "1.0.70"
@ -237,6 +255,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.13.1"
@ -871,18 +904,6 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "flume"
version = "0.10.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
dependencies = [
"futures-core",
"futures-sink",
"pin-project",
"spin 0.9.5",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1148,6 +1169,12 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
[[package]]
name = "gio"
version = "0.15.12"
@ -1204,7 +1231,7 @@ version = "0.15.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64"
dependencies = [
"anyhow",
"anyhow 1.0.70",
"heck 0.4.1",
"proc-macro-crate",
"proc-macro-error",
@ -1312,7 +1339,7 @@ version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9"
dependencies = [
"anyhow",
"anyhow 1.0.70",
"proc-macro-crate",
"proc-macro-error",
"proc-macro2",
@ -1406,7 +1433,7 @@ checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
name = "ice-production"
version = "0.0.0"
dependencies = [
"anyhow",
"anyhow 1.0.58",
"async-std",
"dotenv",
"serde",
@ -1622,7 +1649,7 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
dependencies = [
"spin 0.5.2",
"spin",
]
[[package]]
@ -1637,17 +1664,6 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]]
name = "libsqlite3-sys"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "line-wrap"
version = "0.1.1"
@ -1979,6 +1995,15 @@ dependencies = [
"objc",
]
[[package]]
name = "object"
version = "0.30.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.17.1"
@ -2249,26 +2274,6 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
@ -2583,6 +2588,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rustc-demangle"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
[[package]]
name = "rustc_version"
version = "0.4.0"
@ -2917,15 +2928,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "spin"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
dependencies = [
"lock_api",
]
[[package]]
name = "spki"
version = "0.5.4"
@ -2949,9 +2951,9 @@ dependencies = [
[[package]]
name = "sqlx"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428"
checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188"
dependencies = [
"sqlx-core",
"sqlx-macros",
@ -2959,9 +2961,9 @@ dependencies = [
[[package]]
name = "sqlx-core"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105"
checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029"
dependencies = [
"ahash",
"atoi",
@ -2974,10 +2976,8 @@ dependencies = [
"dotenvy",
"either",
"event-listener",
"flume",
"futures-channel",
"futures-core",
"futures-executor",
"futures-intrusive",
"futures-util",
"generic-array",
@ -2986,7 +2986,6 @@ dependencies = [
"indexmap",
"itoa 1.0.6",
"libc",
"libsqlite3-sys",
"log",
"memchr",
"num-bigint",
@ -3007,9 +3006,9 @@ dependencies = [
[[package]]
name = "sqlx-macros"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9"
checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9"
dependencies = [
"dotenvy",
"either",
@ -3026,9 +3025,9 @@ dependencies = [
[[package]]
name = "sqlx-rt"
version = "0.6.2"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396"
checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024"
dependencies = [
"async-native-tls",
"async-std",
@ -3198,7 +3197,7 @@ version = "1.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449"
dependencies = [
"anyhow",
"anyhow 1.0.70",
"cocoa",
"dirs-next",
"embed_plist",
@ -3245,7 +3244,7 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8807c85d656b2b93927c19fe5a5f1f1f348f96c2de8b90763b3c2d561511f9b4"
dependencies = [
"anyhow",
"anyhow 1.0.70",
"cargo_toml",
"heck 0.4.1",
"json-patch",

View File

@ -15,11 +15,11 @@ tauri-build = { version = "1.2", features = [] }
[dependencies]
tauri = { version = "1.2", features = ["shell-open"] }
serde = { version = "1.0", features = ["derive"] }
sqlx = { version = "0.6.2", features = ["runtime-async-std-native-tls", "mysql", "sqlite", "macros"] }
sqlx = { version = "0.6.3", features = ["runtime-async-std-native-tls", "mysql"] }
async-std = {version = "1.12.0", features = ["attributes"] }
serde_json = "1.0"
dotenv = "0.15.0"
anyhow = "1.0.70"
anyhow = { git = "https://github.com/Seeker14491/anyhow-tauri.git", features = ["backtrace"] }
[features]
# this feature is used for production builds or when `devPath` points to the filesystem

63
lab2/src-tauri/src/api.rs Normal file
View File

@ -0,0 +1,63 @@
use crate::{models::{Manager, Factory, ManagerData, FactoryData, Id}, manager_repo, factory_repo};
use sqlx::{Pool, MySql};
use tauri::State;
use anyhow::Result;
pub struct Database {
pub pool: Pool<MySql>
}
#[tauri::command]
pub async fn add_manager_factory(
factory: FactoryData,
manager: ManagerData,
db: State<'_, Database>
) -> Result<(Id, Id)> {
let mut tx = db.pool.begin().await?;
let manager_id = manager_repo::add(&mut tx, &manager).await?;
let factory_id = factory_repo::add(&mut tx, manager_id, &factory).await?;
tx.commit().await?;
Ok((factory_id, manager_id))
}
#[tauri::command]
pub async fn delete_factory(id: Id, db: State<'_, Database>) -> Result<()> {
let mut tx = db.pool.begin().await?;
factory_repo::delete(&mut tx, id).await?;
tx.commit().await?;
Ok(())
}
#[tauri::command]
pub async fn update_factory(id: Id, factory: FactoryData, db: State<'_, Database>) -> Result<()> {
let mut tx = db.pool.begin().await?;
factory_repo::update(&mut tx, id, &factory).await?;
tx.commit().await?;
Ok(())
}
#[tauri::command]
pub async fn update_manager(id: Id, manager: ManagerData, db: State<'_, Database>) -> Result<()> {
let mut tx = db.pool.begin().await?;
manager_repo::update(&mut tx, id, &manager).await?;
tx.commit().await?;
Ok(())
}
#[tauri::command]
pub async fn list_managers(db: State<'_, Database>) -> Result<Vec<Manager>> {
let mut tx = db.pool.begin().await?;
let managers = manager_repo::list(&mut tx).await?;
tx.commit().await?;
Ok(managers)
}
#[tauri::command]
pub async fn list_factories(db: State<'_, Database>) -> Result<Vec<Factory>> {
let mut tx = db.pool.begin().await?;
let factories = factory_repo::list(&mut tx).await?;
tx.commit().await?;
Ok(factories)
}

View File

@ -0,0 +1,83 @@
use crate::models::{Id, FactoryData, Factory};
use anyhow::Result;
use sqlx::{Transaction, MySql};
type MySqlTransaction<'a> = Transaction<'a, MySql>;
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
sqlx::query(r#"
CREATE TABLE IF NOT EXISTS `factory` (
ID bigint unsigned NOT NULL,
NAME varchar(255) NOT NULL,
LOCATION varchar(255) NOT NULL,
FLOOR_SIZE float NOT NULL,
FK_MANAGER_ID bigint unsigned NOT NULL,
PRIMARY KEY(ID),
UNIQUE(FK_MANAGER_ID),
FOREIGN KEY(FK_MANAGER_ID) REFERENCES MANAGER (ID) ON DELETE CASCADE
);"#).execute(tx).await?;
Ok(())
}
pub async fn add(tx: &mut MySqlTransaction<'_>, manager_id: Id, factory: &FactoryData) -> Result<Id> {
let id = sqlx::query(r#"
INSERT INTO `factory`
(`NAME`, `LOCATION`, `FLOOR_SIZE`, `FK_MANAGER_ID`)
VALUES
(?, ?, ?, ?)
"#)
.bind(&factory.name)
.bind(&factory.location)
.bind(factory.floor_size)
.bind(manager_id)
.execute(&mut *tx).await?
.last_insert_id();
Ok(id)
}
pub async fn list(tx: &mut MySqlTransaction<'_>) -> Result<Vec<Factory>> {
let factories = sqlx::query_as::<_, Factory>(
r#"
SELECT
ID as id,
NAME as name,
LOCATION as location,
FLOOR_SIZE as floor_size,
FK_MANAGER_ID as manager_id
FROM `factory`
"#).fetch_all(tx).await?;
Ok(factories)
}
pub async fn delete(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<()> {
sqlx::query("DELETE FROM `manager` WHERE ID = (SELECT FK_MANAGER_ID FROM `factory` WHERE ID = ?)")
.bind(id)
.execute(&mut *tx).await?;
sqlx::query("DELETE FROM `factory` WHERE ID = ?")
.bind(id)
.execute(&mut *tx).await?;
Ok(())
}
pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, factory: &FactoryData) -> Result<()> {
sqlx::query(
r#"
UPDATE `factory` SET
NAME = ?,
LOCATION = ?,
FLOOR_SIZE = ?
WHERE ID = ?
"#)
.bind(&factory.name)
.bind(&factory.location)
.bind(factory.floor_size)
.bind(id)
.execute(tx).await?;
Ok(())
}

View File

@ -1,135 +1,62 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod models;
mod factory_repo;
mod manager_repo;
mod api;
use std::{env, process::exit};
use dotenv::dotenv;
use serde::{Serialize, Deserialize};
use sqlx::{SqlitePool, sqlite::SqlitePoolOptions, Pool, Sqlite, Row};
use tauri::State;
use models::{ManagerData, FactoryData};
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row};
// TODO: use transaction to revert changes, if failed to insert rows
use api::*;
use anyhow::Result;
type Id = i64;
#[derive(Serialize)]
struct Manager {
id: Id,
first_name: String,
surname: String,
phone_number: Option<String>,
title: String,
email: Option<String>
async fn setup_tables(pool: &Pool<MySql>) -> Result<()> {
let mut tx = pool.begin().await?;
manager_repo::create_table(&mut tx).await?;
factory_repo::create_table(&mut tx).await?;
tx.commit().await?;
Ok(())
}
#[derive(Deserialize)]
struct ManagerData {
first_name: String,
surname: String,
phone_number: Option<String>,
title: String,
email: Option<String>
async fn drop_all_tables(pool: &Pool<MySql>) -> Result<()> {
let tables = sqlx::query("SHOW TABLES").fetch_all(pool).await?;
let names: Vec<_> = tables.into_iter().map(|row| row.get::<String, usize>(0)).collect();
sqlx::query(&format!("DROP TABLE {}", names.join(", ")))
.execute(pool)
.await?;
Ok(())
}
#[derive(Serialize)]
struct Factory {
id: Id,
name: String,
location: String,
floor_size: f64,
manager_id: Id
}
#[derive(Deserialize)]
struct FactoryData {
name: String,
location: String,
floor_size: f64
async fn enable_foreign_key_checks(pool: &Pool<MySql>) -> Result<()> {
sqlx::query("SET GLOBAL FOREIGN_KEY_CHECKS=1").execute(pool).await?;
Ok(())
}
struct Database {
pool: Pool<Sqlite>
}
async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
let mut tx = pool.begin().await?;
let manager = ManagerData {
first_name: "Rokas".into(),
surname: "Puzonas".into(),
phone_number: Some("+123456789".into()),
title: "Big man".into(),
email: Some("bigman@pp.com".into())
};
let factory = FactoryData {
name: "Big factory".into(),
location: "idk".into(),
floor_size: 10.0,
};
let id = manager_repo::add(&mut tx, &manager).await?;
factory_repo::add(&mut tx, id, &factory).await?;
struct EntryID {
id: Id
}
async fn add_manager(db: &Database, manager: &ManagerData) -> anyhow::Result<Id> {
let entry = sqlx::query_as!(
EntryID,
r#"
INSERT INTO manager
(`FIRST_NAME`, `SURNAME`, `PHONE_NUMBER`, `TITLE`, `EMAIL`)
VALUES
(?, ?, ?, ?, ?)
RETURNING ID as id
"#,
manager.first_name,
manager.surname,
manager.phone_number,
manager.title,
manager.email
).fetch_one(&db.pool).await?;
Ok(entry.id)
}
async fn add_factory(db: &Database, manager_id: Id, factory: &FactoryData) -> anyhow::Result<Id> {
let entry = sqlx::query_as!(
EntryID,
r#"
INSERT INTO factory
(`NAME`, `LOCATION`, `FLOOR_SIZE`, `FK_MANAGER_ID`)
VALUES
(?, ?, ?, ?)
RETURNING ID as id
"#,
factory.name,
factory.location,
factory.floor_size,
manager_id
).fetch_one(&db.pool).await?;
Ok(entry.id)
}
async fn list_factories_db(db: &Database) -> anyhow::Result<Vec<Factory>> {
let factories = sqlx::query_as!(
Factory,
r#"
SELECT ID as id, NAME as name, LOCATION as location, FLOOR_SIZE as floor_size, FK_MANAGER_ID as manager_id FROM factory
"#,
).fetch_all(&db.pool).await?;
Ok(factories)
}
async fn list_managers_db(db: &Database) -> anyhow::Result<Vec<Manager>> {
let managers = sqlx::query_as!(
Manager,
r#"
SELECT ID as id, FIRST_NAME as first_name, SURNAME as surname, TITLE as title, EMAIL as email, PHONE_NUMBER as phone_number FROM manager
"#,
).fetch_all(&db.pool).await?;
Ok(managers)
}
#[tauri::command]
async fn add_manager_factory(
factory: FactoryData,
manager: ManagerData,
db: State<'_, Database>
) -> Result<(Id, Id), ()> {
let manager_id = add_manager(&db, &manager).await.unwrap();
let factory_id = add_factory(&db, manager_id, &factory).await.unwrap();
Ok((factory_id, manager_id))
}
#[tauri::command]
async fn list_managers(db: State<'_, Database>) -> Result<Vec<Manager>, ()> {
Ok(list_managers_db(&db).await.unwrap()) // TODO: handle .unwrap()
}
#[tauri::command]
async fn list_factories(db: State<'_, Database>) -> Result<Vec<Factory>, ()> {
Ok(list_factories_db(&db).await.unwrap()) // TODO: handle .unwrap()
tx.commit().await?;
Ok(())
}
#[async_std::main]
@ -144,18 +71,27 @@ async fn main() {
Ok(url) => url,
};
let pool = SqlitePoolOptions::new()
let pool = MySqlPoolOptions::new()
.max_connections(10)
.connect(&database_url)
.await
.unwrap();
enable_foreign_key_checks(&pool).await.expect("Enable foreign key checks");
drop_all_tables(&pool).await.unwrap(); // For testing purposes
setup_tables(&pool).await.expect("Setup tables");
add_test_data(&pool).await.expect("Add test data");
tauri::Builder::default()
.manage(Database { pool })
.invoke_handler(tauri::generate_handler![
list_factories,
list_managers,
add_manager_factory
add_manager_factory,
delete_factory,
update_factory,
update_manager
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

View File

@ -0,0 +1,79 @@
use anyhow::Result;
use sqlx::{Transaction, MySql};
use crate::models::{ManagerData, Id, Manager};
type MySqlTransaction<'a> = Transaction<'a, MySql>;
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
sqlx::query(r#"
CREATE TABLE IF NOT EXISTS `manager` (
ID bigint unsigned NOT NULL,
FIRST_NAME varchar(255) NOT NULL,
SURNAME varchar(255) NOT NULL,
PHONE_NUMBER varchar(255) NULL,
TITLE varchar(255) NOT NULL,
EMAIL varchar(255) NULL,
PRIMARY KEY(ID)
);"#)
.execute(tx).await?;
Ok(())
}
pub async fn add(tx: &mut MySqlTransaction<'_>, manager: &ManagerData) -> Result<Id>
{
let id = sqlx::query(r#"
INSERT INTO `manager`
(`FIRST_NAME`, `SURNAME`, `PHONE_NUMBER`, `TITLE`, `EMAIL`)
VALUES
(?, ?, ?, ?, ?)
"#)
.bind(&manager.first_name)
.bind(&manager.surname)
.bind(&manager.phone_number)
.bind(&manager.title)
.bind(&manager.email)
.execute(&mut *tx).await?
.last_insert_id();
Ok(id)
}
pub async fn list(tx: &mut MySqlTransaction<'_>) -> Result<Vec<Manager>> {
let managers = sqlx::query_as::<_, Manager>(
r#"
SELECT
ID as id,
FIRST_NAME as first_name,
SURNAME as surname,
TITLE as title,
EMAIL as email,
PHONE_NUMBER as phone_number
FROM `manager`
"#).fetch_all(tx).await?;
Ok(managers)
}
pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, manager: &ManagerData) -> Result<()> {
sqlx::query(
r#"
UPDATE `manager` SET
FIRST_NAME = ?,
SURNAME = ?,
TITLE = ?,
EMAIL = ?,
PHONE_NUMBER = ?
WHERE ID = ?
"#)
.bind(&manager.first_name)
.bind(&manager.surname)
.bind(&manager.title)
.bind(&manager.email)
.bind(&manager.phone_number)
.bind(id)
.execute(tx).await?;
Ok(())
}

View File

@ -0,0 +1,39 @@
use serde::{Serialize, Deserialize};
use sqlx::FromRow;
pub type Id = u64;
#[derive(Debug, Serialize, FromRow)]
pub struct Manager {
pub id: Id,
pub first_name: String,
pub surname: String,
pub phone_number: Option<String>,
pub title: String,
pub email: Option<String>
}
#[derive(Debug, Deserialize)]
pub struct ManagerData {
pub first_name: String,
pub surname: String,
pub phone_number: Option<String>,
pub title: String,
pub email: Option<String>
}
#[derive(Debug, Serialize, FromRow)]
pub struct Factory {
pub id: Id,
pub name: String,
pub location: String,
pub floor_size: f32,
pub manager_id: Id
}
#[derive(Debug, Deserialize)]
pub struct FactoryData {
pub name: String,
pub location: String,
pub floor_size: f32
}

View File

@ -9,7 +9,7 @@
let isSideNavOpen = false;
</script>
<Header href="/#/" company="ICE" platformName="Production" />
<Header href="/#/" company="ICE" platformName="Production" bind:isSideNavOpen />
<SideNav bind:isOpen={isSideNavOpen} rail>
<SideNavItems>
<SideNavLink

View File

@ -33,6 +33,16 @@ export interface FactoryData {
export let factories = writable<Factory[]>([])
export let managers = writable<Manager[]>([])
function remove_manager_by_id(id: number) {
managers.update(managers => {
var index = managers.findIndex(m => m.id == id)
if (index != -1) {
managers.splice(index, 1)
}
return managers
})
}
export async function list_factories(): Promise<Factory[]> {
return invoke("list_factories")
}
@ -63,10 +73,45 @@ export async function add_manager_factory(factory: FactoryData, manager: Manager
return [factory_id, manager_id]
}
export async function edit_manager(id: number, manager: ManagerData): Promise<void> {
// TODO: invoke("edit_manager")
export async function update_manager(id: number, manager: ManagerData): Promise<void> {
invoke("update_manager", { id, manager })
managers.update((managers) => {
var index = managers.findIndex(f => f.id == id)
if (index != -1) {
managers[index] = {
...managers[index],
...manager
}
}
return managers
})
}
export async function edit_factory(id: number, factory: FactoryData): Promise<void> {
// TODO: invoke("edit_factory")
export async function update_factory(id: number, factory: FactoryData): Promise<void> {
invoke("update_factory", { id, factory })
factories.update((factories) => {
var index = factories.findIndex(f => f.id == id)
if (index != -1) {
factories[index] = {
...factories[index],
...factory
}
}
return factories
})
}
export async function delete_factory(id: number): Promise<void> {
invoke("delete_factory", { id })
factories.update((factories) => {
var index = factories.findIndex(f => f.id == id)
if (index != -1) {
remove_manager_by_id(factories[index].manager_id)
factories.splice(index, 1)
}
return factories
})
}

View File

@ -13,7 +13,7 @@
import Edit from "carbon-icons-svelte/lib/Edit.svelte"
import ManagerForm from "../lib/ManagerForm.svelte"
import FactoryForm from "../lib/FactoryForm.svelte"
import { add_manager_factory, edit_factory, edit_manager, factories, list_factories, list_managers, managers } from "../lib/api"
import { add_manager_factory, delete_factory, update_factory, update_manager, factories, list_factories, list_managers, managers } from "../lib/api"
import { onMount } from 'svelte'
var rows = []
@ -48,6 +48,7 @@
let currentlyEditingId = undefined
let showUpdateModal = factory_id => {
console.log(factory_id)
currentlyEditingId = factory_id
let factory = $factories.find(factory => factory.id == factory_id)
@ -75,6 +76,13 @@
let closeModal = () => {
isModalShown = false
}
let deleteSelectedRows = async () => {
for (var id of selectedRowIds) {
await delete_factory(id)
}
selectedRowIds = []
}
</script>
<DataTable
@ -103,10 +111,7 @@
<Button
icon={TrashCan}
disabled={selectedRowIds.length === 0}
on:click={() => {
rows = rows.filter((row) => !selectedRowIds.includes(row.id));
selectedRowIds = [];
}}
on:click={deleteSelectedRows}
>
Delete
</Button>
@ -138,7 +143,7 @@
<Modal
bind:open={isModalShown}
modalHeading={currentlyEditingId ? "Edit factory & manager" : "Create factory & manager"}
modalHeading={currentlyEditingId != undefined ? "Edit factory & manager" : "Create factory & manager"}
primaryButtonText="Confirm"
secondaryButtonText="Cancel"
on:open
@ -150,12 +155,12 @@
return false
}
if (currentlyEditingId) {
if (currentlyEditingId != undefined) {
// TODO: Handle if factory is not found
let manager_id = $factories.find(factory => factory.id == currentlyEditingId).manager_id
await edit_factory(currentlyEditingId, factoryData) // TODO: handle if failed
await edit_manager(manager_id, managerData) // TODO: handle if failed
await update_factory(currentlyEditingId, factoryData) // TODO: handle if failed
await update_manager(manager_id, managerData) // TODO: handle if failed
} else {
await add_manager_factory(factoryData, managerData) // TODO: handle error
}