Compare commits
4 Commits
838830d2e6
...
10162217e3
Author | SHA1 | Date | |
---|---|---|---|
10162217e3 | |||
38a201baef | |||
9c8db5e7c8 | |||
1b4a7f3612 |
@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.0.0",
|
"@sveltejs/vite-plugin-svelte": "^2.0.0",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.3.1",
|
||||||
"@tsconfig/svelte": "^3.0.0",
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
"@unocss/transformer-directives": "^0.50.4",
|
"@unocss/transformer-directives": "^0.50.4",
|
||||||
|
62
lab2/pnpm-lock.yaml
generated
62
lab2/pnpm-lock.yaml
generated
@ -3,7 +3,7 @@ lockfileVersion: 5.4
|
|||||||
specifiers:
|
specifiers:
|
||||||
'@sveltejs/vite-plugin-svelte': ^2.0.0
|
'@sveltejs/vite-plugin-svelte': ^2.0.0
|
||||||
'@tauri-apps/api': ^1.2.0
|
'@tauri-apps/api': ^1.2.0
|
||||||
'@tauri-apps/cli': ^1.2.2
|
'@tauri-apps/cli': ^1.3.1
|
||||||
'@tsconfig/svelte': ^3.0.0
|
'@tsconfig/svelte': ^3.0.0
|
||||||
'@types/node': ^18.7.10
|
'@types/node': ^18.7.10
|
||||||
'@unocss/transformer-directives': ^0.50.4
|
'@unocss/transformer-directives': ^0.50.4
|
||||||
@ -23,7 +23,7 @@ dependencies:
|
|||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@sveltejs/vite-plugin-svelte': 2.0.3_svelte@3.56.0+vite@4.1.4
|
'@sveltejs/vite-plugin-svelte': 2.0.3_svelte@3.56.0+vite@4.1.4
|
||||||
'@tauri-apps/cli': 1.2.3
|
'@tauri-apps/cli': 1.3.1
|
||||||
'@tsconfig/svelte': 3.0.0
|
'@tsconfig/svelte': 3.0.0
|
||||||
'@types/node': 18.15.0
|
'@types/node': 18.15.0
|
||||||
'@unocss/transformer-directives': 0.50.4
|
'@unocss/transformer-directives': 0.50.4
|
||||||
@ -370,8 +370,8 @@ packages:
|
|||||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tauri-apps/cli-darwin-arm64/1.2.3:
|
/@tauri-apps/cli-darwin-arm64/1.3.1:
|
||||||
resolution: {integrity: sha512-phJN3fN8FtZZwqXg08bcxfq1+X1JSDglLvRxOxB7VWPq+O5SuB8uLyssjJsu+PIhyZZnIhTGdjhzLSFhSXfLsw==}
|
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@ -379,8 +379,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-darwin-x64/1.2.3:
|
/@tauri-apps/cli-darwin-x64/1.3.1:
|
||||||
resolution: {integrity: sha512-jFZ/y6z8z6v4yliIbXKBXA7BJgtZVMsITmEXSuD6s5+eCOpDhQxbRkr6CA+FFfr+/r96rWSDSgDenDQuSvPAKw==}
|
resolution: {integrity: sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
@ -388,8 +388,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm-gnueabihf/1.2.3:
|
/@tauri-apps/cli-linux-arm-gnueabihf/1.3.1:
|
||||||
resolution: {integrity: sha512-C7h5vqAwXzY0kRGSU00Fj8PudiDWFCiQqqUNI1N+fhCILrzWZB9TPBwdx33ZfXKt/U4+emdIoo/N34v3TiAOmQ==}
|
resolution: {integrity: sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm]
|
cpu: [arm]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@ -397,8 +397,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm64-gnu/1.2.3:
|
/@tauri-apps/cli-linux-arm64-gnu/1.3.1:
|
||||||
resolution: {integrity: sha512-buf1c8sdkuUzVDkGPQpyUdAIIdn5r0UgXU6+H5fGPq/Xzt5K69JzXaeo6fHsZEZghbV0hOK+taKV4J0m30UUMQ==}
|
resolution: {integrity: sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@ -406,8 +406,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-arm64-musl/1.2.3:
|
/@tauri-apps/cli-linux-arm64-musl/1.3.1:
|
||||||
resolution: {integrity: sha512-x88wPS9W5xAyk392vc4uNHcKBBvCp0wf4H9JFMF9OBwB7vfd59LbQCFcPSu8f0BI7bPrOsyHqspWHuFL8ojQEA==}
|
resolution: {integrity: sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@ -415,8 +415,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-x64-gnu/1.2.3:
|
/@tauri-apps/cli-linux-x64-gnu/1.3.1:
|
||||||
resolution: {integrity: sha512-ZMz1jxEVe0B4/7NJnlPHmwmSIuwiD6ViXKs8F+OWWz2Y4jn5TGxWKFg7DLx5OwQTRvEIZxxT7lXHi5CuTNAxKg==}
|
resolution: {integrity: sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@ -424,8 +424,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-linux-x64-musl/1.2.3:
|
/@tauri-apps/cli-linux-x64-musl/1.3.1:
|
||||||
resolution: {integrity: sha512-B/az59EjJhdbZDzawEVox0LQu2ZHCZlk8rJf85AMIktIUoAZPFbwyiUv7/zjzA/sY6Nb58OSJgaPL2/IBy7E0A==}
|
resolution: {integrity: sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
@ -433,8 +433,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-win32-ia32-msvc/1.2.3:
|
/@tauri-apps/cli-win32-ia32-msvc/1.3.1:
|
||||||
resolution: {integrity: sha512-ypdO1OdC5ugNJAKO2m3sb1nsd+0TSvMS9Tr5qN/ZSMvtSduaNwrcZ3D7G/iOIanrqu/Nl8t3LYlgPZGBKlw7Ng==}
|
resolution: {integrity: sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [ia32]
|
cpu: [ia32]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@ -442,8 +442,8 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli-win32-x64-msvc/1.2.3:
|
/@tauri-apps/cli-win32-x64-msvc/1.3.1:
|
||||||
resolution: {integrity: sha512-CsbHQ+XhnV/2csOBBDVfH16cdK00gNyNYUW68isedmqcn8j+s0e9cQ1xXIqi+Hue3awp8g3ImYN5KPepf3UExw==}
|
resolution: {integrity: sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@ -451,20 +451,20 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@tauri-apps/cli/1.2.3:
|
/@tauri-apps/cli/1.3.1:
|
||||||
resolution: {integrity: sha512-erxtXuPhMEGJPBtnhPILD4AjuT81GZsraqpFvXAmEJZ2p8P6t7MVBifCL8LznRknznM3jn90D3M8RNBP3wcXTw==}
|
resolution: {integrity: sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@tauri-apps/cli-darwin-arm64': 1.2.3
|
'@tauri-apps/cli-darwin-arm64': 1.3.1
|
||||||
'@tauri-apps/cli-darwin-x64': 1.2.3
|
'@tauri-apps/cli-darwin-x64': 1.3.1
|
||||||
'@tauri-apps/cli-linux-arm-gnueabihf': 1.2.3
|
'@tauri-apps/cli-linux-arm-gnueabihf': 1.3.1
|
||||||
'@tauri-apps/cli-linux-arm64-gnu': 1.2.3
|
'@tauri-apps/cli-linux-arm64-gnu': 1.3.1
|
||||||
'@tauri-apps/cli-linux-arm64-musl': 1.2.3
|
'@tauri-apps/cli-linux-arm64-musl': 1.3.1
|
||||||
'@tauri-apps/cli-linux-x64-gnu': 1.2.3
|
'@tauri-apps/cli-linux-x64-gnu': 1.3.1
|
||||||
'@tauri-apps/cli-linux-x64-musl': 1.2.3
|
'@tauri-apps/cli-linux-x64-musl': 1.3.1
|
||||||
'@tauri-apps/cli-win32-ia32-msvc': 1.2.3
|
'@tauri-apps/cli-win32-ia32-msvc': 1.3.1
|
||||||
'@tauri-apps/cli-win32-x64-msvc': 1.2.3
|
'@tauri-apps/cli-win32-x64-msvc': 1.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@tsconfig/svelte/3.0.0:
|
/@tsconfig/svelte/3.0.0:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{models::{Manager, Factory, ManagerData, FactoryData, Id, Process, ProcessData}, manager_repo, factory_repo, process_repo};
|
use crate::{models::{Manager, Factory, ManagerData, FactoryData, Id, Process, ProcessData}, manager_repo, factory_repo, process_repo, report_gen::{self, FactoryUsedSpace}};
|
||||||
use sqlx::{Pool, MySql};
|
use sqlx::{Pool, MySql};
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
@ -9,10 +9,10 @@ pub struct Database {
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn add_manager_factory(
|
pub async fn add_manager_factory(
|
||||||
factory: FactoryData,
|
factory: FactoryData,
|
||||||
manager: ManagerData,
|
manager: ManagerData,
|
||||||
db: State<'_, Database>
|
db: State<'_, Database>
|
||||||
) -> Result<(Id, Id)> {
|
) -> Result<(Id, Id)> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
let manager_id = manager_repo::add(&mut tx, &manager).await?;
|
let manager_id = manager_repo::add(&mut tx, &manager).await?;
|
||||||
let factory_id = factory_repo::add(&mut tx, manager_id, &factory).await?;
|
let factory_id = factory_repo::add(&mut tx, manager_id, &factory).await?;
|
||||||
@ -117,11 +117,37 @@ pub async fn update_process(id: Id, process: ProcessData, db: State<'_, Database
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn add_process(
|
pub async fn add_process(
|
||||||
process: ProcessData,
|
process: ProcessData,
|
||||||
db: State<'_, Database>
|
db: State<'_, Database>
|
||||||
) -> Result<Id> {
|
) -> Result<Id> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
let id = process_repo::add(&mut tx, &process).await?;
|
let id = process_repo::add(&mut tx, &process).await?;
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(id)
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------- Report generation ---------------------------
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_factories_by_used_space(
|
||||||
|
from: f32,
|
||||||
|
to: f32,
|
||||||
|
location: String,
|
||||||
|
db: State<'_, Database>
|
||||||
|
) -> Result<Vec<FactoryUsedSpace>> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
let results = report_gen::get_factories_by_used_space(&mut tx, from, to, &location).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn get_processess_of_factory(
|
||||||
|
factory: Id,
|
||||||
|
db: State<'_, Database>
|
||||||
|
) -> Result<Vec<ProcessData>> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
let results = report_gen::get_processess_of_factory(&mut tx, factory).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(results)
|
||||||
}
|
}
|
@ -5,12 +5,13 @@ mod models;
|
|||||||
mod factory_repo;
|
mod factory_repo;
|
||||||
mod manager_repo;
|
mod manager_repo;
|
||||||
mod process_repo;
|
mod process_repo;
|
||||||
|
mod report_gen;
|
||||||
mod api;
|
mod api;
|
||||||
|
|
||||||
use std::{env, process::exit};
|
use std::{env, process::exit};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
|
||||||
use models::{ManagerData, FactoryData, ProcessData};
|
use models::{ManagerData, FactoryData, ProcessData, Id};
|
||||||
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row, Transaction};
|
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row, Transaction};
|
||||||
|
|
||||||
use api::*;
|
use api::*;
|
||||||
@ -46,9 +47,13 @@ async fn set_foreign_key_checks(pool: &Pool<MySql>, enable: bool) -> Result<()>
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_test_process(tx: &mut MySqlTransaction<'_>, process: ProcessData) -> Result<()> {
|
async fn add_test_processess(tx: &mut MySqlTransaction<'_>, processess: &[ProcessData]) -> Result<Vec<Id>> {
|
||||||
process_repo::add(tx, &process).await?;
|
let mut ids = vec![];
|
||||||
Ok(())
|
for process in processess {
|
||||||
|
let id = process_repo::add(tx, &process).await?;
|
||||||
|
ids.push(id);
|
||||||
|
}
|
||||||
|
Ok(ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
|
async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
|
||||||
@ -62,26 +67,20 @@ async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
|
|||||||
};
|
};
|
||||||
let factory = FactoryData {
|
let factory = FactoryData {
|
||||||
name: "Big factory".into(),
|
name: "Big factory".into(),
|
||||||
location: "idk".into(),
|
location: "Kaunas, fabriko gatve 1".into(),
|
||||||
floor_size: 10.0,
|
floor_size: 10.0,
|
||||||
};
|
};
|
||||||
let id = manager_repo::add(&mut tx, &manager).await?;
|
let manager_id = manager_repo::add(&mut tx, &manager).await?;
|
||||||
factory_repo::add(&mut tx, id, &factory).await?;
|
let factory_id = factory_repo::add(&mut tx, manager_id, &factory).await?;
|
||||||
|
|
||||||
add_test_process(&mut tx, ProcessData {
|
let process_ids = add_test_processess(&mut tx, &[
|
||||||
name: "Certifuge 9000".into(),
|
ProcessData { name: "Certifuge 9000".into(), size: 10.0 },
|
||||||
size: 10.0
|
ProcessData { name: "Certifuge 9001".into(), size: 20.0 },
|
||||||
}).await?;
|
ProcessData { name: "Certifuge 9002".into(), size: 30.0 }
|
||||||
|
]).await?;
|
||||||
|
|
||||||
add_test_process(&mut tx, ProcessData {
|
factory_repo::add_process(&mut tx, factory_id, process_ids[0]).await?;
|
||||||
name: "Certifuge 9001".into(),
|
factory_repo::add_process(&mut tx, factory_id, process_ids[1]).await?;
|
||||||
size: 20.0
|
|
||||||
}).await?;
|
|
||||||
|
|
||||||
add_test_process(&mut tx, ProcessData {
|
|
||||||
name: "Certifuge 9002".into(),
|
|
||||||
size: 30.0
|
|
||||||
}).await?;
|
|
||||||
|
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -130,7 +129,10 @@ async fn main() {
|
|||||||
list_processess,
|
list_processess,
|
||||||
update_process,
|
update_process,
|
||||||
delete_process,
|
delete_process,
|
||||||
add_process
|
add_process,
|
||||||
|
|
||||||
|
get_factories_by_used_space,
|
||||||
|
get_processess_of_factory
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -45,7 +45,7 @@ pub struct Process {
|
|||||||
pub size: f32
|
pub size: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize, Serialize, FromRow)]
|
||||||
pub struct ProcessData {
|
pub struct ProcessData {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub size: f32
|
pub size: f32
|
||||||
|
61
lab2/src-tauri/src/report_gen.rs
Normal file
61
lab2/src-tauri/src/report_gen.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use serde::Serialize;
|
||||||
|
use sqlx::{Transaction, MySql, FromRow};
|
||||||
|
|
||||||
|
use crate::models::{Id, ProcessData};
|
||||||
|
|
||||||
|
type MySqlTransaction<'a> = Transaction<'a, MySql>;
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, FromRow)]
|
||||||
|
pub struct FactoryUsedSpace {
|
||||||
|
manager_name: String,
|
||||||
|
factory_id: Id,
|
||||||
|
used_size: f32,
|
||||||
|
used_percent: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_factories_by_used_space(tx: &mut MySqlTransaction<'_>, from: f32, to: f32, location: &str) -> Result<Vec<FactoryUsedSpace>> {
|
||||||
|
let results = sqlx::query_as::<_, FactoryUsedSpace>(r#"
|
||||||
|
SELECT
|
||||||
|
CONCAT(manager.FIRST_NAME, " ", manager.SURNAME) as manager_name,
|
||||||
|
factory.ID as factory_id,
|
||||||
|
SUM(process.SIZE) as used_size,
|
||||||
|
ROUND(CAST(SUM(process.SIZE) as FLOAT) / CAST(factory.FLOOR_SIZE as FLOAT) * 100, 2) as used_percent
|
||||||
|
FROM
|
||||||
|
factory
|
||||||
|
LEFT JOIN factory_supports_processes
|
||||||
|
ON factory_supports_processes.FK_FACTORY_ID = factory.ID
|
||||||
|
LEFT JOIN process
|
||||||
|
ON process.ID = factory_supports_processes.FK_PROCESS_ID
|
||||||
|
LEFT JOIN manager
|
||||||
|
ON manager.ID = factory.FK_MANAGER_ID
|
||||||
|
WHERE LOCATE(?, factory.LOCATION)>0
|
||||||
|
GROUP BY factory.ID
|
||||||
|
HAVING ? <= used_percent AND used_percent <= ?
|
||||||
|
"#)
|
||||||
|
.bind(location)
|
||||||
|
.bind(from)
|
||||||
|
.bind(to)
|
||||||
|
.fetch_all(tx).await?;
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_processess_of_factory(tx: &mut MySqlTransaction<'_>, factory_id: Id) -> Result<Vec<ProcessData>> {
|
||||||
|
let results = sqlx::query_as::<_, ProcessData>("
|
||||||
|
SELECT
|
||||||
|
process.NAME as name,
|
||||||
|
process.SIZE as size
|
||||||
|
FROM
|
||||||
|
factory
|
||||||
|
LEFT JOIN factory_supports_processes
|
||||||
|
ON factory_supports_processes.FK_FACTORY_ID = factory.ID
|
||||||
|
LEFT JOIN process
|
||||||
|
ON process.ID = factory_supports_processes.FK_PROCESS_ID
|
||||||
|
WHERE factory.ID = 1
|
||||||
|
")
|
||||||
|
.bind(factory_id)
|
||||||
|
.fetch_all(tx).await?;
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
|
}
|
@ -1,12 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Router, {location} from "svelte-spa-router"
|
import Router, {location} from "svelte-spa-router"
|
||||||
import { Header, Content, SideNav, SideNavItems, SideNavLink } from "carbon-components-svelte";
|
import { Header, Content, SideNav, SideNavItems, SideNavLink } from "carbon-components-svelte";
|
||||||
import Home from './routes/Home.svelte'
|
|
||||||
import FactoriesManagers from './routes/Factories-Managers.svelte'
|
|
||||||
import { factories, factory_processess, list_factories, list_factory_processess, list_managers, list_processess, managers, processess } from "./lib/api";
|
import { factories, factory_processess, list_factories, list_factory_processess, list_managers, list_processess, managers, processess } from "./lib/api";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import { Building, Calibrate, ReportData } from "carbon-icons-svelte";
|
||||||
|
|
||||||
|
import Home from './routes/Home.svelte'
|
||||||
|
import FactoriesManagers from './routes/Factories-Managers.svelte'
|
||||||
import Processess from "./routes/Processess.svelte";
|
import Processess from "./routes/Processess.svelte";
|
||||||
import { Building, Calibrate } from "carbon-icons-svelte";
|
import Report from "./routes/Report.svelte";
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
$managers = await list_managers()
|
$managers = await list_managers()
|
||||||
@ -23,6 +25,12 @@
|
|||||||
<Header href="/#/" company="ICE" platformName="Production" bind:isSideNavOpen />
|
<Header href="/#/" company="ICE" platformName="Production" bind:isSideNavOpen />
|
||||||
<SideNav bind:isOpen={isSideNavOpen} rail>
|
<SideNav bind:isOpen={isSideNavOpen} rail>
|
||||||
<SideNavItems>
|
<SideNavItems>
|
||||||
|
<SideNavLink
|
||||||
|
icon={ReportData}
|
||||||
|
text="Report"
|
||||||
|
href="/#/report"
|
||||||
|
isSelected={$location == "/report"}
|
||||||
|
/>
|
||||||
<SideNavLink
|
<SideNavLink
|
||||||
icon={Building}
|
icon={Building}
|
||||||
text="Factories & Managers"
|
text="Factories & Managers"
|
||||||
@ -42,6 +50,7 @@
|
|||||||
<Router routes={{
|
<Router routes={{
|
||||||
"/": Home,
|
"/": Home,
|
||||||
"/factories-managers": FactoriesManagers,
|
"/factories-managers": FactoriesManagers,
|
||||||
"/processess": Processess
|
"/processess": Processess,
|
||||||
|
"/report": Report
|
||||||
}} />
|
}} />
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Form, TextInput, NumberInput, DataTable } from "carbon-components-svelte";
|
import { Form, TextInput, NumberInput } from "carbon-components-svelte";
|
||||||
import type { FactoryData } from "./api"
|
import type { FactoryData } from "./api"
|
||||||
|
|
||||||
export let factory: FactoryData = {
|
export let factory: FactoryData = {
|
||||||
|
@ -28,12 +28,42 @@
|
|||||||
showTitleInvalid = manager.title === ""
|
showTitleInvalid = manager.title === ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Phone number validation
|
||||||
|
let showPhoneNumberInvalid = false
|
||||||
|
function validatePhoneNumber() {
|
||||||
|
showPhoneNumberInvalid = false
|
||||||
|
if (manager.phone_number === "") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let allowedSymbols = " +()1234567890"
|
||||||
|
for (var symbol of manager.phone_number) {
|
||||||
|
if (allowedSymbols.indexOf(symbol) == -1) {
|
||||||
|
showPhoneNumberInvalid = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Email validation
|
||||||
|
let showEmailInvalid = false
|
||||||
|
function validateEmail() {
|
||||||
|
if (manager.email === "") {
|
||||||
|
showEmailInvalid = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
showEmailInvalid = !manager.email.includes("@")
|
||||||
|
}
|
||||||
|
|
||||||
// Exports
|
// Exports
|
||||||
export const validate = () => {
|
export const validate = () => {
|
||||||
validateFirstName()
|
validateFirstName()
|
||||||
validateSurname()
|
validateSurname()
|
||||||
validateTitle()
|
validateTitle()
|
||||||
return !showFirstNameInvalid && !showSurnameInvalid && !showTitleInvalid
|
validateEmail()
|
||||||
|
validatePhoneNumber()
|
||||||
|
return !showFirstNameInvalid && !showSurnameInvalid && !showTitleInvalid && !showEmailInvalid && !showPhoneNumberInvalid
|
||||||
};
|
};
|
||||||
|
|
||||||
export const reset = () => {
|
export const reset = () => {
|
||||||
@ -45,6 +75,8 @@
|
|||||||
showFirstNameInvalid = false
|
showFirstNameInvalid = false
|
||||||
showSurnameInvalid = false
|
showSurnameInvalid = false
|
||||||
showTitleInvalid = false
|
showTitleInvalid = false
|
||||||
|
showEmailInvalid = false
|
||||||
|
showPhoneNumberInvalid = false
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -76,10 +108,16 @@
|
|||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
bind:value={manager.phone_number}
|
bind:value={manager.phone_number}
|
||||||
|
bind:invalid={showPhoneNumberInvalid}
|
||||||
|
on:input={validatePhoneNumber}
|
||||||
|
invalidText={"Phone number can only contain '+', ' ', '(', ')' and numbers"}
|
||||||
labelText="Phone number"
|
labelText="Phone number"
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
bind:value={manager.email}
|
bind:value={manager.email}
|
||||||
|
bind:invalid={showEmailInvalid}
|
||||||
|
on:input={validateEmail}
|
||||||
|
invalidText={"Email must contain '@'"}
|
||||||
labelText="Email"
|
labelText="Email"
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -102,6 +102,7 @@
|
|||||||
</DataTable>
|
</DataTable>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
|
preventCloseOnClickOutside
|
||||||
bind:open={isModalShown}
|
bind:open={isModalShown}
|
||||||
modalHeading={currentlyUpdatingId != undefined ? updateModalTitle : addModalTitle}
|
modalHeading={currentlyUpdatingId != undefined ? updateModalTitle : addModalTitle}
|
||||||
primaryButtonText="Confirm"
|
primaryButtonText="Confirm"
|
||||||
|
@ -37,6 +37,19 @@
|
|||||||
processess = newProcessess
|
processess = newProcessess
|
||||||
selectedAdd = getAvailableProcessess()[0]
|
selectedAdd = getAvailableProcessess()[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeRow(id) {
|
||||||
|
processess = processess.filter(row => row != id)
|
||||||
|
if (selectedAdd == undefined) {
|
||||||
|
selectedAdd = getAvailableProcessess()[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRowSelect(event) {
|
||||||
|
if (event.detail.selectedId == selectedAdd) {
|
||||||
|
selectedAdd = getAvailableProcessess()[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -46,15 +59,14 @@
|
|||||||
<Dropdown
|
<Dropdown
|
||||||
class="flex-grow"
|
class="flex-grow"
|
||||||
bind:selectedId={id}
|
bind:selectedId={id}
|
||||||
|
on:select={onRowSelect}
|
||||||
items={allProcessItems.filter(item => item.id == id || !processess.includes(item.id))}
|
items={allProcessItems.filter(item => item.id == id || !processess.includes(item.id))}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
icon={TrashCan}
|
icon={TrashCan}
|
||||||
iconDescription="Delete"
|
iconDescription="Delete"
|
||||||
kind="danger-tertiary"
|
kind="danger-tertiary"
|
||||||
on:click={() => {
|
on:click={() => removeRow(id)}
|
||||||
processess = processess.filter(row => row != id)
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -30,6 +30,14 @@ export interface ProcessData {
|
|||||||
}
|
}
|
||||||
export interface Process extends ProcessData {
|
export interface Process extends ProcessData {
|
||||||
id: Id
|
id: Id
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FactoryUsedSpace {
|
||||||
|
manager_name: string
|
||||||
|
factory_id: Id,
|
||||||
|
used_size: number,
|
||||||
|
used_percent: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export let factory_processess = writable<Record<Id, Id[]>>([])
|
export let factory_processess = writable<Record<Id, Id[]>>([])
|
||||||
@ -200,4 +208,13 @@ export async function update_factory_processess(factory_id: Id, process_ids: Id[
|
|||||||
}
|
}
|
||||||
return factory_processess
|
return factory_processess
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function get_factories_by_used_space(from: number, to: number, location: string): Promise<FactoryUsedSpace[]> {
|
||||||
|
return await invoke("get_factories_by_used_space", { from, to, location })
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get_processess_of_factory(factory: Id): Promise<ProcessData[]> {
|
||||||
|
return await invoke("get_processess_of_factory", { factory })
|
||||||
}
|
}
|
@ -52,10 +52,13 @@
|
|||||||
resetProcessList()
|
resetProcessList()
|
||||||
}
|
}
|
||||||
|
|
||||||
let validateModal = () => {
|
let validateModal = (event) => {
|
||||||
let isFactoryValid = validateFactoryForm()
|
let isFactoryValid = validateFactoryForm()
|
||||||
let isManagerValid = validateManagerForm()
|
let isManagerValid = validateManagerForm()
|
||||||
return isFactoryValid && isManagerValid
|
let valid = isFactoryValid && isManagerValid
|
||||||
|
if (!valid) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -91,7 +94,7 @@
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<div class="flex flex-row gap-1rem mb-1rem">
|
<div class="flex flex-row gap-1rem mb-1rem">
|
||||||
<div class="flex-grow">
|
<div class="flex-grow w-50">
|
||||||
<p>Factory</p>
|
<p>Factory</p>
|
||||||
<FactoryForm
|
<FactoryForm
|
||||||
bind:factory={factoryData}
|
bind:factory={factoryData}
|
||||||
@ -99,7 +102,7 @@
|
|||||||
bind:reset={resetFactoryForm}
|
bind:reset={resetFactoryForm}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow-2">
|
<div class="flex-grow w-50">
|
||||||
<p>Manager</p>
|
<p>Manager</p>
|
||||||
<ManagerForm
|
<ManagerForm
|
||||||
bind:manager={managerData}
|
bind:manager={managerData}
|
||||||
|
91
lab2/src/routes/Report.svelte
Normal file
91
lab2/src/routes/Report.svelte
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Button, DataTable, NumberInput, TextInput } from "carbon-components-svelte";
|
||||||
|
import { factories, processess, get_factories_by_used_space, get_processess_of_factory, type ProcessData } from "../lib/api";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
let from_bound = 50.00
|
||||||
|
let to_bound = 100.00
|
||||||
|
let location = "Kaunas"
|
||||||
|
|
||||||
|
let rows = writable([])
|
||||||
|
|
||||||
|
async function requestReport() {
|
||||||
|
let newRows = []
|
||||||
|
|
||||||
|
const results = await get_factories_by_used_space(from_bound, to_bound, location)
|
||||||
|
for (var result of results) {
|
||||||
|
var factory = $factories.find(factory => factory.id == result.factory_id)
|
||||||
|
if (factory === undefined) continue
|
||||||
|
const processess = await get_processess_of_factory(result.factory_id) as (ProcessData & { id: string })[]
|
||||||
|
for (const process of processess) {
|
||||||
|
process.id = process.name
|
||||||
|
}
|
||||||
|
|
||||||
|
newRows.push({
|
||||||
|
id: result.factory_id,
|
||||||
|
manager_name: result.manager_name,
|
||||||
|
factory_name: factory.name,
|
||||||
|
factory_size: factory.floor_size,
|
||||||
|
used_percent: `${result.used_percent}%`,
|
||||||
|
used_size: result.used_size,
|
||||||
|
processess
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$rows = newRows
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-row gap-1rem mb-1rem">
|
||||||
|
<NumberInput
|
||||||
|
bind:value={from_bound}
|
||||||
|
required
|
||||||
|
hideSteppers
|
||||||
|
min={0}
|
||||||
|
invalidText="Can't be negative"
|
||||||
|
label="Lower used size bound (%)"
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
bind:value={to_bound}
|
||||||
|
required
|
||||||
|
hideSteppers
|
||||||
|
min={0}
|
||||||
|
invalidText="Can't be negative"
|
||||||
|
label="Upper used size bound (%)"
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
bind:value={location}
|
||||||
|
required
|
||||||
|
invalidText="Location can't be empty"
|
||||||
|
labelText="Location"
|
||||||
|
/>
|
||||||
|
<div class="pt">
|
||||||
|
<Button on:click={requestReport}>
|
||||||
|
Go
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
expandable
|
||||||
|
zebra
|
||||||
|
rows={$rows}
|
||||||
|
headers={[
|
||||||
|
{ key: "manager_name", value: "Manager" },
|
||||||
|
{ key: "factory_name", value: "Factory name" },
|
||||||
|
{ key: "factory_size", value: "Factory size"},
|
||||||
|
{ key: "used_size", value: "Used size" },
|
||||||
|
{ key: "used_percent", value: "Used percent" }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<svelte:fragment slot="expanded-row" let:row>
|
||||||
|
<DataTable
|
||||||
|
size="compact"
|
||||||
|
rows={row.processess}
|
||||||
|
headers={[
|
||||||
|
{ key: "name", value: "Process Name" },
|
||||||
|
{ key: "size", value: "Process Size" }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
</DataTable>
|
||||||
|
</svelte:fragment>
|
||||||
|
</DataTable>
|
Loading…
Reference in New Issue
Block a user