Compare commits
4 Commits
838830d2e6
...
10162217e3
Author | SHA1 | Date | |
---|---|---|---|
10162217e3 | |||
38a201baef | |||
9c8db5e7c8 | |||
1b4a7f3612 |
@ -15,7 +15,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^2.0.0",
|
||||
"@tauri-apps/cli": "^1.2.2",
|
||||
"@tauri-apps/cli": "^1.3.1",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"@types/node": "^18.7.10",
|
||||
"@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:
|
||||
'@sveltejs/vite-plugin-svelte': ^2.0.0
|
||||
'@tauri-apps/api': ^1.2.0
|
||||
'@tauri-apps/cli': ^1.2.2
|
||||
'@tauri-apps/cli': ^1.3.1
|
||||
'@tsconfig/svelte': ^3.0.0
|
||||
'@types/node': ^18.7.10
|
||||
'@unocss/transformer-directives': ^0.50.4
|
||||
@ -23,7 +23,7 @@ dependencies:
|
||||
|
||||
devDependencies:
|
||||
'@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
|
||||
'@types/node': 18.15.0
|
||||
'@unocss/transformer-directives': 0.50.4
|
||||
@ -370,8 +370,8 @@ packages:
|
||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||
dev: false
|
||||
|
||||
/@tauri-apps/cli-darwin-arm64/1.2.3:
|
||||
resolution: {integrity: sha512-phJN3fN8FtZZwqXg08bcxfq1+X1JSDglLvRxOxB7VWPq+O5SuB8uLyssjJsu+PIhyZZnIhTGdjhzLSFhSXfLsw==}
|
||||
/@tauri-apps/cli-darwin-arm64/1.3.1:
|
||||
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
@ -379,8 +379,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-darwin-x64/1.2.3:
|
||||
resolution: {integrity: sha512-jFZ/y6z8z6v4yliIbXKBXA7BJgtZVMsITmEXSuD6s5+eCOpDhQxbRkr6CA+FFfr+/r96rWSDSgDenDQuSvPAKw==}
|
||||
/@tauri-apps/cli-darwin-x64/1.3.1:
|
||||
resolution: {integrity: sha512-fKcAUPVFO3jfDKXCSDGY0MhZFF/wDtx3rgFnogWYu4knk38o9RaqRkvMvqJhLYPuWaEM5h6/z1dRrr9KKCbrVg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
@ -388,8 +388,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-linux-arm-gnueabihf/1.2.3:
|
||||
resolution: {integrity: sha512-C7h5vqAwXzY0kRGSU00Fj8PudiDWFCiQqqUNI1N+fhCILrzWZB9TPBwdx33ZfXKt/U4+emdIoo/N34v3TiAOmQ==}
|
||||
/@tauri-apps/cli-linux-arm-gnueabihf/1.3.1:
|
||||
resolution: {integrity: sha512-+4H0dv8ltJHYu/Ma1h9ixUPUWka9EjaYa8nJfiMsdCI4LJLNE6cPveE7RmhZ59v9GW1XB108/k083JUC/OtGvA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
@ -397,8 +397,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-linux-arm64-gnu/1.2.3:
|
||||
resolution: {integrity: sha512-buf1c8sdkuUzVDkGPQpyUdAIIdn5r0UgXU6+H5fGPq/Xzt5K69JzXaeo6fHsZEZghbV0hOK+taKV4J0m30UUMQ==}
|
||||
/@tauri-apps/cli-linux-arm64-gnu/1.3.1:
|
||||
resolution: {integrity: sha512-Pj3odVO1JAxLjYmoXKxcrpj/tPxcA8UP8N06finhNtBtBaxAjrjjxKjO4968KB0BUH7AASIss9EL4Tr0FGnDuw==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
@ -406,8 +406,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-linux-arm64-musl/1.2.3:
|
||||
resolution: {integrity: sha512-x88wPS9W5xAyk392vc4uNHcKBBvCp0wf4H9JFMF9OBwB7vfd59LbQCFcPSu8f0BI7bPrOsyHqspWHuFL8ojQEA==}
|
||||
/@tauri-apps/cli-linux-arm64-musl/1.3.1:
|
||||
resolution: {integrity: sha512-tA0JdDLPFaj42UDIVcF2t8V0tSha40rppcmAR/MfQpTCxih6399iMjwihz9kZE1n4b5O4KTq9GliYo50a8zYlQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
@ -415,8 +415,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-linux-x64-gnu/1.2.3:
|
||||
resolution: {integrity: sha512-ZMz1jxEVe0B4/7NJnlPHmwmSIuwiD6ViXKs8F+OWWz2Y4jn5TGxWKFg7DLx5OwQTRvEIZxxT7lXHi5CuTNAxKg==}
|
||||
/@tauri-apps/cli-linux-x64-gnu/1.3.1:
|
||||
resolution: {integrity: sha512-FDU+Mnvk6NLkqQimcNojdKpMN4Y3W51+SQl+NqG9AFCWprCcSg62yRb84751ujZuf2MGT8HQOfmd0i77F4Q3tQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
@ -424,8 +424,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-linux-x64-musl/1.2.3:
|
||||
resolution: {integrity: sha512-B/az59EjJhdbZDzawEVox0LQu2ZHCZlk8rJf85AMIktIUoAZPFbwyiUv7/zjzA/sY6Nb58OSJgaPL2/IBy7E0A==}
|
||||
/@tauri-apps/cli-linux-x64-musl/1.3.1:
|
||||
resolution: {integrity: sha512-MpO3akXFmK8lZYEbyQRDfhdxz1JkTBhonVuz5rRqxwA7gnGWHa1aF1+/2zsy7ahjB2tQ9x8DDFDMdVE20o9HrA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
@ -433,8 +433,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-win32-ia32-msvc/1.2.3:
|
||||
resolution: {integrity: sha512-ypdO1OdC5ugNJAKO2m3sb1nsd+0TSvMS9Tr5qN/ZSMvtSduaNwrcZ3D7G/iOIanrqu/Nl8t3LYlgPZGBKlw7Ng==}
|
||||
/@tauri-apps/cli-win32-ia32-msvc/1.3.1:
|
||||
resolution: {integrity: sha512-9Boeo3K5sOrSBAZBuYyGkpV2RfnGQz3ZhGJt4hE6P+HxRd62lS6+qDKAiw1GmkZ0l1drc2INWrNeT50gwOKwIQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
@ -442,8 +442,8 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli-win32-x64-msvc/1.2.3:
|
||||
resolution: {integrity: sha512-CsbHQ+XhnV/2csOBBDVfH16cdK00gNyNYUW68isedmqcn8j+s0e9cQ1xXIqi+Hue3awp8g3ImYN5KPepf3UExw==}
|
||||
/@tauri-apps/cli-win32-x64-msvc/1.3.1:
|
||||
resolution: {integrity: sha512-wMrTo91hUu5CdpbElrOmcZEoJR4aooTG+fbtcc87SMyPGQy1Ux62b+ZdwLvL1sVTxnIm//7v6QLRIWGiUjCPwA==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
@ -451,20 +451,20 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@tauri-apps/cli/1.2.3:
|
||||
resolution: {integrity: sha512-erxtXuPhMEGJPBtnhPILD4AjuT81GZsraqpFvXAmEJZ2p8P6t7MVBifCL8LznRknznM3jn90D3M8RNBP3wcXTw==}
|
||||
/@tauri-apps/cli/1.3.1:
|
||||
resolution: {integrity: sha512-o4I0JujdITsVRm3/0spfJX7FcKYrYV1DXJqzlWIn6IY25/RltjU6qbC1TPgVww3RsRX63jyVUTcWpj5wwFl+EQ==}
|
||||
engines: {node: '>= 10'}
|
||||
hasBin: true
|
||||
optionalDependencies:
|
||||
'@tauri-apps/cli-darwin-arm64': 1.2.3
|
||||
'@tauri-apps/cli-darwin-x64': 1.2.3
|
||||
'@tauri-apps/cli-linux-arm-gnueabihf': 1.2.3
|
||||
'@tauri-apps/cli-linux-arm64-gnu': 1.2.3
|
||||
'@tauri-apps/cli-linux-arm64-musl': 1.2.3
|
||||
'@tauri-apps/cli-linux-x64-gnu': 1.2.3
|
||||
'@tauri-apps/cli-linux-x64-musl': 1.2.3
|
||||
'@tauri-apps/cli-win32-ia32-msvc': 1.2.3
|
||||
'@tauri-apps/cli-win32-x64-msvc': 1.2.3
|
||||
'@tauri-apps/cli-darwin-arm64': 1.3.1
|
||||
'@tauri-apps/cli-darwin-x64': 1.3.1
|
||||
'@tauri-apps/cli-linux-arm-gnueabihf': 1.3.1
|
||||
'@tauri-apps/cli-linux-arm64-gnu': 1.3.1
|
||||
'@tauri-apps/cli-linux-arm64-musl': 1.3.1
|
||||
'@tauri-apps/cli-linux-x64-gnu': 1.3.1
|
||||
'@tauri-apps/cli-linux-x64-musl': 1.3.1
|
||||
'@tauri-apps/cli-win32-ia32-msvc': 1.3.1
|
||||
'@tauri-apps/cli-win32-x64-msvc': 1.3.1
|
||||
dev: true
|
||||
|
||||
/@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 tauri::State;
|
||||
use anyhow::Result;
|
||||
@ -12,7 +12,7 @@ pub async fn add_manager_factory(
|
||||
factory: FactoryData,
|
||||
manager: ManagerData,
|
||||
db: State<'_, Database>
|
||||
) -> Result<(Id, Id)> {
|
||||
) -> 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?;
|
||||
@ -119,9 +119,35 @@ pub async fn update_process(id: Id, process: ProcessData, db: State<'_, Database
|
||||
pub async fn add_process(
|
||||
process: ProcessData,
|
||||
db: State<'_, Database>
|
||||
) -> Result<Id> {
|
||||
) -> Result<Id> {
|
||||
let mut tx = db.pool.begin().await?;
|
||||
let id = process_repo::add(&mut tx, &process).await?;
|
||||
tx.commit().await?;
|
||||
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 manager_repo;
|
||||
mod process_repo;
|
||||
mod report_gen;
|
||||
mod api;
|
||||
|
||||
use std::{env, process::exit};
|
||||
use dotenv::dotenv;
|
||||
|
||||
use models::{ManagerData, FactoryData, ProcessData};
|
||||
use models::{ManagerData, FactoryData, ProcessData, Id};
|
||||
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row, Transaction};
|
||||
|
||||
use api::*;
|
||||
@ -46,9 +47,13 @@ async fn set_foreign_key_checks(pool: &Pool<MySql>, enable: bool) -> Result<()>
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn add_test_process(tx: &mut MySqlTransaction<'_>, process: ProcessData) -> Result<()> {
|
||||
process_repo::add(tx, &process).await?;
|
||||
Ok(())
|
||||
async fn add_test_processess(tx: &mut MySqlTransaction<'_>, processess: &[ProcessData]) -> Result<Vec<Id>> {
|
||||
let mut ids = vec![];
|
||||
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<()> {
|
||||
@ -62,26 +67,20 @@ async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
|
||||
};
|
||||
let factory = FactoryData {
|
||||
name: "Big factory".into(),
|
||||
location: "idk".into(),
|
||||
location: "Kaunas, fabriko gatve 1".into(),
|
||||
floor_size: 10.0,
|
||||
};
|
||||
let id = manager_repo::add(&mut tx, &manager).await?;
|
||||
factory_repo::add(&mut tx, id, &factory).await?;
|
||||
let manager_id = manager_repo::add(&mut tx, &manager).await?;
|
||||
let factory_id = factory_repo::add(&mut tx, manager_id, &factory).await?;
|
||||
|
||||
add_test_process(&mut tx, ProcessData {
|
||||
name: "Certifuge 9000".into(),
|
||||
size: 10.0
|
||||
}).await?;
|
||||
let process_ids = add_test_processess(&mut tx, &[
|
||||
ProcessData { name: "Certifuge 9000".into(), size: 10.0 },
|
||||
ProcessData { name: "Certifuge 9001".into(), size: 20.0 },
|
||||
ProcessData { name: "Certifuge 9002".into(), size: 30.0 }
|
||||
]).await?;
|
||||
|
||||
add_test_process(&mut tx, ProcessData {
|
||||
name: "Certifuge 9001".into(),
|
||||
size: 20.0
|
||||
}).await?;
|
||||
|
||||
add_test_process(&mut tx, ProcessData {
|
||||
name: "Certifuge 9002".into(),
|
||||
size: 30.0
|
||||
}).await?;
|
||||
factory_repo::add_process(&mut tx, factory_id, process_ids[0]).await?;
|
||||
factory_repo::add_process(&mut tx, factory_id, process_ids[1]).await?;
|
||||
|
||||
tx.commit().await?;
|
||||
Ok(())
|
||||
@ -130,7 +129,10 @@ async fn main() {
|
||||
list_processess,
|
||||
update_process,
|
||||
delete_process,
|
||||
add_process
|
||||
add_process,
|
||||
|
||||
get_factories_by_used_space,
|
||||
get_processess_of_factory
|
||||
])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
|
@ -45,7 +45,7 @@ pub struct Process {
|
||||
pub size: f32
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize, Serialize, FromRow)]
|
||||
pub struct ProcessData {
|
||||
pub name: String,
|
||||
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">
|
||||
import Router, {location} from "svelte-spa-router"
|
||||
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 { 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 { Building, Calibrate } from "carbon-icons-svelte";
|
||||
import Report from "./routes/Report.svelte";
|
||||
|
||||
onMount(async () => {
|
||||
$managers = await list_managers()
|
||||
@ -23,6 +25,12 @@
|
||||
<Header href="/#/" company="ICE" platformName="Production" bind:isSideNavOpen />
|
||||
<SideNav bind:isOpen={isSideNavOpen} rail>
|
||||
<SideNavItems>
|
||||
<SideNavLink
|
||||
icon={ReportData}
|
||||
text="Report"
|
||||
href="/#/report"
|
||||
isSelected={$location == "/report"}
|
||||
/>
|
||||
<SideNavLink
|
||||
icon={Building}
|
||||
text="Factories & Managers"
|
||||
@ -42,6 +50,7 @@
|
||||
<Router routes={{
|
||||
"/": Home,
|
||||
"/factories-managers": FactoriesManagers,
|
||||
"/processess": Processess
|
||||
"/processess": Processess,
|
||||
"/report": Report
|
||||
}} />
|
||||
</Content>
|
||||
|
@ -1,6 +1,5 @@
|
||||
|
||||
<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"
|
||||
|
||||
export let factory: FactoryData = {
|
||||
|
@ -28,12 +28,42 @@
|
||||
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
|
||||
export const validate = () => {
|
||||
validateFirstName()
|
||||
validateSurname()
|
||||
validateTitle()
|
||||
return !showFirstNameInvalid && !showSurnameInvalid && !showTitleInvalid
|
||||
validateEmail()
|
||||
validatePhoneNumber()
|
||||
return !showFirstNameInvalid && !showSurnameInvalid && !showTitleInvalid && !showEmailInvalid && !showPhoneNumberInvalid
|
||||
};
|
||||
|
||||
export const reset = () => {
|
||||
@ -45,6 +75,8 @@
|
||||
showFirstNameInvalid = false
|
||||
showSurnameInvalid = false
|
||||
showTitleInvalid = false
|
||||
showEmailInvalid = false
|
||||
showPhoneNumberInvalid = false
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -76,10 +108,16 @@
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.phone_number}
|
||||
bind:invalid={showPhoneNumberInvalid}
|
||||
on:input={validatePhoneNumber}
|
||||
invalidText={"Phone number can only contain '+', ' ', '(', ')' and numbers"}
|
||||
labelText="Phone number"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.email}
|
||||
bind:invalid={showEmailInvalid}
|
||||
on:input={validateEmail}
|
||||
invalidText={"Email must contain '@'"}
|
||||
labelText="Email"
|
||||
/>
|
||||
</Form>
|
||||
|
@ -102,6 +102,7 @@
|
||||
</DataTable>
|
||||
|
||||
<Modal
|
||||
preventCloseOnClickOutside
|
||||
bind:open={isModalShown}
|
||||
modalHeading={currentlyUpdatingId != undefined ? updateModalTitle : addModalTitle}
|
||||
primaryButtonText="Confirm"
|
||||
|
@ -37,6 +37,19 @@
|
||||
processess = newProcessess
|
||||
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>
|
||||
|
||||
<div>
|
||||
@ -46,15 +59,14 @@
|
||||
<Dropdown
|
||||
class="flex-grow"
|
||||
bind:selectedId={id}
|
||||
on:select={onRowSelect}
|
||||
items={allProcessItems.filter(item => item.id == id || !processess.includes(item.id))}
|
||||
/>
|
||||
<Button
|
||||
icon={TrashCan}
|
||||
iconDescription="Delete"
|
||||
kind="danger-tertiary"
|
||||
on:click={() => {
|
||||
processess = processess.filter(row => row != id)
|
||||
}}
|
||||
on:click={() => removeRow(id)}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -30,6 +30,14 @@ export interface ProcessData {
|
||||
}
|
||||
export interface Process extends ProcessData {
|
||||
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[]>>([])
|
||||
@ -201,3 +209,12 @@ export async function update_factory_processess(factory_id: Id, process_ids: Id[
|
||||
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()
|
||||
}
|
||||
|
||||
let validateModal = () => {
|
||||
let validateModal = (event) => {
|
||||
let isFactoryValid = validateFactoryForm()
|
||||
let isManagerValid = validateManagerForm()
|
||||
return isFactoryValid && isManagerValid
|
||||
let valid = isFactoryValid && isManagerValid
|
||||
if (!valid) {
|
||||
event.preventDefault()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -91,7 +94,7 @@
|
||||
]}
|
||||
>
|
||||
<div class="flex flex-row gap-1rem mb-1rem">
|
||||
<div class="flex-grow">
|
||||
<div class="flex-grow w-50">
|
||||
<p>Factory</p>
|
||||
<FactoryForm
|
||||
bind:factory={factoryData}
|
||||
@ -99,7 +102,7 @@
|
||||
bind:reset={resetFactoryForm}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-grow-2">
|
||||
<div class="flex-grow w-50">
|
||||
<p>Manager</p>
|
||||
<ManagerForm
|
||||
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