Add process add/list/delete/update
This commit is contained in:
parent
77684d6347
commit
e149726b83
@ -1,2 +1 @@
|
|||||||
RUST_BACKTRACE=1
|
|
||||||
DATABASE_URL="mysql://root@localhost/ice_cream"
|
DATABASE_URL="mysql://root@localhost/ice_cream"
|
1
lab2/.vscode/settings.json
vendored
1
lab2/.vscode/settings.json
vendored
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
|
".\\src-tauri\\Cargo.toml",
|
||||||
".\\src-tauri\\Cargo.toml"
|
".\\src-tauri\\Cargo.toml"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{models::{Manager, Factory, ManagerData, FactoryData, Id}, manager_repo, factory_repo};
|
use crate::{models::{Manager, Factory, ManagerData, FactoryData, Id, Process, ProcessData}, manager_repo, factory_repo, process_repo};
|
||||||
use sqlx::{Pool, MySql};
|
use sqlx::{Pool, MySql};
|
||||||
use tauri::State;
|
use tauri::State;
|
||||||
|
|
||||||
@ -21,12 +21,14 @@ pub async fn add_manager_factory(
|
|||||||
Ok((factory_id, manager_id))
|
Ok((factory_id, manager_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------- Factory ---------------------------
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn delete_factory(id: Id, db: State<'_, Database>) -> Result<()> {
|
pub async fn list_factories(db: State<'_, Database>) -> Result<Vec<Factory>> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
factory_repo::delete(&mut tx, id).await?;
|
let factories = factory_repo::list(&mut tx).await?;
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(())
|
Ok(factories)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
@ -38,13 +40,15 @@ pub async fn update_factory(id: Id, factory: FactoryData, db: State<'_, Database
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn update_manager(id: Id, manager: ManagerData, db: State<'_, Database>) -> Result<()> {
|
pub async fn delete_factory(id: Id, db: State<'_, Database>) -> Result<()> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
manager_repo::update(&mut tx, id, &manager).await?;
|
factory_repo::delete(&mut tx, id).await?;
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------- Manager ---------------------------
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn list_managers(db: State<'_, Database>) -> Result<Vec<Manager>> {
|
pub async fn list_managers(db: State<'_, Database>) -> Result<Vec<Manager>> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
@ -54,10 +58,47 @@ pub async fn list_managers(db: State<'_, Database>) -> Result<Vec<Manager>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn list_factories(db: State<'_, Database>) -> Result<Vec<Factory>> {
|
pub async fn update_manager(id: Id, manager: ManagerData, db: State<'_, Database>) -> Result<()> {
|
||||||
let mut tx = db.pool.begin().await?;
|
let mut tx = db.pool.begin().await?;
|
||||||
let factories = factory_repo::list(&mut tx).await?;
|
manager_repo::update(&mut tx, id, &manager).await?;
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(factories)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------- Process ---------------------------
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn list_processess(db: State<'_, Database>) -> Result<Vec<Process>> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
let processess = process_repo::list(&mut tx).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(processess)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn delete_process(id: Id, db: State<'_, Database>) -> Result<()> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
process_repo::delete(&mut tx, id).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn update_process(id: Id, process: ProcessData, db: State<'_, Database>) -> Result<()> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
process_repo::update(&mut tx, id, &process).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn add_process(
|
||||||
|
process: ProcessData,
|
||||||
|
db: State<'_, Database>
|
||||||
|
) -> Result<Id> {
|
||||||
|
let mut tx = db.pool.begin().await?;
|
||||||
|
let id = process_repo::add(&mut tx, &process).await?;
|
||||||
|
tx.commit().await?;
|
||||||
|
Ok(id)
|
||||||
|
}
|
@ -7,7 +7,7 @@ type MySqlTransaction<'a> = Transaction<'a, MySql>;
|
|||||||
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
|
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
|
||||||
sqlx::query(r#"
|
sqlx::query(r#"
|
||||||
CREATE TABLE IF NOT EXISTS `factory` (
|
CREATE TABLE IF NOT EXISTS `factory` (
|
||||||
ID bigint unsigned NOT NULL,
|
ID bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
NAME varchar(255) NOT NULL,
|
NAME varchar(255) NOT NULL,
|
||||||
LOCATION varchar(255) NOT NULL,
|
LOCATION varchar(255) NOT NULL,
|
||||||
FLOOR_SIZE float NOT NULL,
|
FLOOR_SIZE float NOT NULL,
|
||||||
|
@ -4,12 +4,13 @@
|
|||||||
mod models;
|
mod models;
|
||||||
mod factory_repo;
|
mod factory_repo;
|
||||||
mod manager_repo;
|
mod manager_repo;
|
||||||
|
mod process_repo;
|
||||||
mod api;
|
mod api;
|
||||||
|
|
||||||
use std::{env, process::exit};
|
use std::{env, process::exit};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
|
||||||
use models::{ManagerData, FactoryData};
|
use models::{ManagerData, FactoryData, ProcessData};
|
||||||
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row};
|
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row};
|
||||||
|
|
||||||
use api::*;
|
use api::*;
|
||||||
@ -19,6 +20,7 @@ async fn setup_tables(pool: &Pool<MySql>) -> Result<()> {
|
|||||||
let mut tx = pool.begin().await?;
|
let mut tx = pool.begin().await?;
|
||||||
manager_repo::create_table(&mut tx).await?;
|
manager_repo::create_table(&mut tx).await?;
|
||||||
factory_repo::create_table(&mut tx).await?;
|
factory_repo::create_table(&mut tx).await?;
|
||||||
|
process_repo::create_table(&mut tx).await?;
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -33,8 +35,12 @@ async fn drop_all_tables(pool: &Pool<MySql>) -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn enable_foreign_key_checks(pool: &Pool<MySql>) -> Result<()> {
|
async fn set_foreign_key_checks(pool: &Pool<MySql>, enable: bool) -> Result<()> {
|
||||||
sqlx::query("SET GLOBAL FOREIGN_KEY_CHECKS=1").execute(pool).await?;
|
let query = match enable {
|
||||||
|
true => "SET GLOBAL FOREIGN_KEY_CHECKS=1",
|
||||||
|
false => "SET GLOBAL FOREIGN_KEY_CHECKS=0",
|
||||||
|
};
|
||||||
|
sqlx::query(query).execute(pool).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +58,13 @@ async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
|
|||||||
location: "idk".into(),
|
location: "idk".into(),
|
||||||
floor_size: 10.0,
|
floor_size: 10.0,
|
||||||
};
|
};
|
||||||
|
let process = ProcessData {
|
||||||
|
name: "Certifuge 9000".into(),
|
||||||
|
size: 10.0
|
||||||
|
};
|
||||||
let id = manager_repo::add(&mut tx, &manager).await?;
|
let id = manager_repo::add(&mut tx, &manager).await?;
|
||||||
factory_repo::add(&mut tx, id, &factory).await?;
|
factory_repo::add(&mut tx, id, &factory).await?;
|
||||||
|
process_repo::add(&mut tx, &process).await?;
|
||||||
|
|
||||||
tx.commit().await?;
|
tx.commit().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -77,8 +88,9 @@ async fn main() {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
enable_foreign_key_checks(&pool).await.expect("Enable foreign key checks");
|
set_foreign_key_checks(&pool, false).await.expect("Disable foreign key checks");
|
||||||
drop_all_tables(&pool).await.unwrap(); // For testing purposes
|
drop_all_tables(&pool).await.unwrap(); // For testing purposes
|
||||||
|
set_foreign_key_checks(&pool, true).await.expect("Enable foreign key checks");
|
||||||
setup_tables(&pool).await.expect("Setup tables");
|
setup_tables(&pool).await.expect("Setup tables");
|
||||||
|
|
||||||
add_test_data(&pool).await.expect("Add test data");
|
add_test_data(&pool).await.expect("Add test data");
|
||||||
@ -86,12 +98,19 @@ async fn main() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.manage(Database { pool })
|
.manage(Database { pool })
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
list_factories,
|
|
||||||
list_managers,
|
|
||||||
add_manager_factory,
|
add_manager_factory,
|
||||||
|
|
||||||
|
list_factories,
|
||||||
delete_factory,
|
delete_factory,
|
||||||
update_factory,
|
update_factory,
|
||||||
update_manager
|
|
||||||
|
list_managers,
|
||||||
|
update_manager,
|
||||||
|
|
||||||
|
list_processess,
|
||||||
|
update_process,
|
||||||
|
delete_process,
|
||||||
|
add_process
|
||||||
])
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -9,12 +9,13 @@ type MySqlTransaction<'a> = Transaction<'a, MySql>;
|
|||||||
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
|
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
|
||||||
sqlx::query(r#"
|
sqlx::query(r#"
|
||||||
CREATE TABLE IF NOT EXISTS `manager` (
|
CREATE TABLE IF NOT EXISTS `manager` (
|
||||||
ID bigint unsigned NOT NULL,
|
ID bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
FIRST_NAME varchar(255) NOT NULL,
|
FIRST_NAME varchar(255) NOT NULL,
|
||||||
SURNAME varchar(255) NOT NULL,
|
SURNAME varchar(255) NOT NULL,
|
||||||
PHONE_NUMBER varchar(255) NULL,
|
PHONE_NUMBER varchar(255) NULL,
|
||||||
TITLE varchar(255) NOT NULL,
|
TITLE varchar(255) NOT NULL,
|
||||||
EMAIL varchar(255) NULL,
|
EMAIL varchar(255) NULL,
|
||||||
|
|
||||||
PRIMARY KEY(ID)
|
PRIMARY KEY(ID)
|
||||||
);"#)
|
);"#)
|
||||||
.execute(tx).await?;
|
.execute(tx).await?;
|
||||||
|
@ -36,4 +36,17 @@ pub struct FactoryData {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub location: String,
|
pub location: String,
|
||||||
pub floor_size: f32
|
pub floor_size: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, FromRow)]
|
||||||
|
pub struct Process {
|
||||||
|
pub id: Id,
|
||||||
|
pub name: String,
|
||||||
|
pub size: f32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct ProcessData {
|
||||||
|
pub name: String,
|
||||||
|
pub size: f32
|
||||||
}
|
}
|
83
lab2/src-tauri/src/process_repo.rs
Normal file
83
lab2/src-tauri/src/process_repo.rs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use sqlx::{Transaction, MySql};
|
||||||
|
|
||||||
|
use crate::models::{ProcessData, Id, Process};
|
||||||
|
|
||||||
|
type MySqlTransaction<'a> = Transaction<'a, MySql>;
|
||||||
|
|
||||||
|
pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
|
||||||
|
sqlx::query(r#"
|
||||||
|
CREATE TABLE IF NOT EXISTS `process` (
|
||||||
|
ID bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
NAME varchar(255) NOT NULL,
|
||||||
|
SIZE float NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY(ID)
|
||||||
|
);"#)
|
||||||
|
.execute(&mut *tx).await?;
|
||||||
|
sqlx::query(r#"
|
||||||
|
CREATE TABLE `factory_supports_processes` (
|
||||||
|
FK_PROCESS_ID bigint unsigned NOT NULL,
|
||||||
|
FK_FACTORY_ID bigint unsigned NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY(FK_PROCESS_ID, FK_FACTORY_ID),
|
||||||
|
FOREIGN KEY(FK_PROCESS_ID) REFERENCES PROCESS (ID),
|
||||||
|
FOREIGN KEY(FK_FACTORY_ID) REFERENCES FACTORY (ID)
|
||||||
|
);"#)
|
||||||
|
.execute(&mut *tx).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add(tx: &mut MySqlTransaction<'_>, process: &ProcessData) -> Result<Id>
|
||||||
|
{
|
||||||
|
let id = sqlx::query(r#"
|
||||||
|
INSERT INTO `process`
|
||||||
|
(`NAME`, `SIZE`)
|
||||||
|
VALUES
|
||||||
|
(?, ?)
|
||||||
|
"#)
|
||||||
|
.bind(&process.name)
|
||||||
|
.bind(process.size)
|
||||||
|
.execute(&mut *tx).await?
|
||||||
|
.last_insert_id();
|
||||||
|
|
||||||
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list(tx: &mut MySqlTransaction<'_>) -> Result<Vec<Process>> {
|
||||||
|
let factories = sqlx::query_as::<_, Process>(
|
||||||
|
r#"
|
||||||
|
SELECT
|
||||||
|
ID as id,
|
||||||
|
NAME as name,
|
||||||
|
SIZE as size
|
||||||
|
FROM `process`
|
||||||
|
"#).fetch_all(tx).await?;
|
||||||
|
|
||||||
|
Ok(factories)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<()> {
|
||||||
|
sqlx::query("DELETE FROM `process` WHERE ID = ?")
|
||||||
|
.bind(id)
|
||||||
|
.execute(&mut *tx).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, process: &ProcessData) -> Result<()> {
|
||||||
|
sqlx::query(
|
||||||
|
r#"
|
||||||
|
UPDATE `process` SET
|
||||||
|
NAME = ?,
|
||||||
|
SIZE = ?
|
||||||
|
WHERE ID = ?
|
||||||
|
"#)
|
||||||
|
.bind(&process.name)
|
||||||
|
.bind(process.size)
|
||||||
|
.bind(id)
|
||||||
|
.execute(tx).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,10 +1,18 @@
|
|||||||
<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 User from "carbon-icons-svelte/lib/User.svelte";
|
|
||||||
|
|
||||||
import Home from './routes/Home.svelte'
|
import Home from './routes/Home.svelte'
|
||||||
import FactoriesManagers from './routes/Factories-Managers.svelte'
|
import FactoriesManagers from './routes/Factories-Managers.svelte'
|
||||||
|
import { factories, list_factories, list_managers, list_processess, managers, processess } from "./lib/api";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import Processess from "./routes/Processess.svelte";
|
||||||
|
import { Building, Calibrate } from "carbon-icons-svelte";
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
$managers = await list_managers()
|
||||||
|
$factories = await list_factories()
|
||||||
|
$processess = await list_processess()
|
||||||
|
})
|
||||||
|
|
||||||
let isSideNavOpen = false;
|
let isSideNavOpen = false;
|
||||||
</script>
|
</script>
|
||||||
@ -13,11 +21,17 @@
|
|||||||
<SideNav bind:isOpen={isSideNavOpen} rail>
|
<SideNav bind:isOpen={isSideNavOpen} rail>
|
||||||
<SideNavItems>
|
<SideNavItems>
|
||||||
<SideNavLink
|
<SideNavLink
|
||||||
icon={User}
|
icon={Building}
|
||||||
text="Factories & Managers"
|
text="Factories & Managers"
|
||||||
href="/#/factories-managers"
|
href="/#/factories-managers"
|
||||||
isSelected={$location == "/factories-managers"}
|
isSelected={$location == "/factories-managers"}
|
||||||
/>
|
/>
|
||||||
|
<SideNavLink
|
||||||
|
icon={Calibrate}
|
||||||
|
text="Processess"
|
||||||
|
href="/#/processess"
|
||||||
|
isSelected={$location == "/processess"}
|
||||||
|
/>
|
||||||
</SideNavItems>
|
</SideNavItems>
|
||||||
</SideNav>
|
</SideNav>
|
||||||
|
|
||||||
@ -25,5 +39,6 @@
|
|||||||
<Router routes={{
|
<Router routes={{
|
||||||
"/": Home,
|
"/": Home,
|
||||||
"/factories-managers": FactoriesManagers,
|
"/factories-managers": FactoriesManagers,
|
||||||
|
"/processess": Processess
|
||||||
}} />
|
}} />
|
||||||
</Content>
|
</Content>
|
||||||
|
129
lab2/src/lib/MyDataTable.svelte
Normal file
129
lab2/src/lib/MyDataTable.svelte
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {
|
||||||
|
DataTable,
|
||||||
|
Toolbar,
|
||||||
|
ToolbarContent,
|
||||||
|
ToolbarBatchActions,
|
||||||
|
Button,
|
||||||
|
ToolbarSearch,
|
||||||
|
Modal,
|
||||||
|
} from "carbon-components-svelte"
|
||||||
|
import TrashCan from "carbon-icons-svelte/lib/TrashCan.svelte"
|
||||||
|
import Edit from "carbon-icons-svelte/lib/Edit.svelte"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
|
import type { DataTableHeader } from "carbon-components-svelte/types/DataTable/DataTable.svelte";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
export let addModalTitle = "Create"
|
||||||
|
export let updateModalTitle = "Edit"
|
||||||
|
export let rows = []
|
||||||
|
export let headers: DataTableHeader[] = []
|
||||||
|
|
||||||
|
let isModalShown = false
|
||||||
|
let activeDelete = false
|
||||||
|
let selectedRowIds = []
|
||||||
|
let filteredRowIds = []
|
||||||
|
|
||||||
|
let currentlyUpdatingId = undefined
|
||||||
|
export let showUpdateModal = id => {
|
||||||
|
currentlyUpdatingId = id
|
||||||
|
dispatch("showUpdateModal", id)
|
||||||
|
isModalShown = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let showAddModal = () => {
|
||||||
|
currentlyUpdatingId = undefined
|
||||||
|
dispatch("showAddModal")
|
||||||
|
isModalShown = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let closeModal = () => {
|
||||||
|
isModalShown = false
|
||||||
|
}
|
||||||
|
|
||||||
|
let deleteSelectedRows = async () => {
|
||||||
|
dispatch("delete", selectedRowIds)
|
||||||
|
selectedRowIds = []
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DataTable
|
||||||
|
zebra
|
||||||
|
selectable={activeDelete}
|
||||||
|
batchSelection={activeDelete}
|
||||||
|
sortable
|
||||||
|
bind:selectedRowIds
|
||||||
|
headers={[
|
||||||
|
...headers,
|
||||||
|
{ key: "update_btn", empty: true, width: "5rem" }
|
||||||
|
]}
|
||||||
|
{rows}
|
||||||
|
>
|
||||||
|
<Toolbar>
|
||||||
|
<ToolbarBatchActions
|
||||||
|
bind:active={activeDelete}
|
||||||
|
on:cancel={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
activeDelete = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
icon={TrashCan}
|
||||||
|
disabled={selectedRowIds.length === 0}
|
||||||
|
on:click={deleteSelectedRows}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</ToolbarBatchActions>
|
||||||
|
<ToolbarContent>
|
||||||
|
<ToolbarSearch
|
||||||
|
persistent
|
||||||
|
shouldFilterRows
|
||||||
|
bind:filteredRowIds
|
||||||
|
/>
|
||||||
|
<Button on:click={showAddModal}>Create</Button>
|
||||||
|
<Button on:click={() => activeDelete = true}>Delete</Button>
|
||||||
|
</ToolbarContent>
|
||||||
|
</Toolbar>
|
||||||
|
<svelte:fragment slot="cell" let:row let:cell>
|
||||||
|
{#if cell.key === "update_btn"}
|
||||||
|
<Button
|
||||||
|
kind="ghost"
|
||||||
|
size="field"
|
||||||
|
iconDescription={"Edit"}
|
||||||
|
icon={Edit}
|
||||||
|
on:click={() => showUpdateModal(row.id)}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
{cell.value}
|
||||||
|
{/if}
|
||||||
|
</svelte:fragment>
|
||||||
|
</DataTable>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
bind:open={isModalShown}
|
||||||
|
modalHeading={currentlyUpdatingId != undefined ? updateModalTitle : addModalTitle}
|
||||||
|
primaryButtonText="Confirm"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
on:open
|
||||||
|
on:click:button--secondary={closeModal}
|
||||||
|
on:submit={async () => {
|
||||||
|
let valid = dispatch("validateModal", undefined, { cancelable: true })
|
||||||
|
if (!valid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add erro handling
|
||||||
|
if (currentlyUpdatingId != undefined) {
|
||||||
|
dispatch("update", currentlyUpdatingId)
|
||||||
|
} else {
|
||||||
|
dispatch("add")
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal()
|
||||||
|
return true
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
</Modal>
|
47
lab2/src/lib/ProcessForm.svelte
Normal file
47
lab2/src/lib/ProcessForm.svelte
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Form, TextInput, NumberInput } from "carbon-components-svelte";
|
||||||
|
import type { ProcessData } from "./api"
|
||||||
|
|
||||||
|
export let process: ProcessData = {
|
||||||
|
name: "",
|
||||||
|
size: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name validation
|
||||||
|
let showNameInvalid = false;
|
||||||
|
function validateName() {
|
||||||
|
showNameInvalid = process.name === ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exports
|
||||||
|
export const validate = () => {
|
||||||
|
validateName()
|
||||||
|
return !showNameInvalid && process.size >= 1
|
||||||
|
};
|
||||||
|
|
||||||
|
export const reset = () => {
|
||||||
|
process.name = ""
|
||||||
|
process.size = 1
|
||||||
|
showNameInvalid = false
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Form class="flex flex-col gap-1rem" title="Process">
|
||||||
|
<TextInput
|
||||||
|
bind:value={process.name}
|
||||||
|
invalidText={"Name can't be empty"}
|
||||||
|
bind:invalid={showNameInvalid}
|
||||||
|
on:input={validateName}
|
||||||
|
required
|
||||||
|
labelText="Name"
|
||||||
|
/>
|
||||||
|
<NumberInput
|
||||||
|
bind:value={process.size}
|
||||||
|
required
|
||||||
|
hideSteppers
|
||||||
|
min={1}
|
||||||
|
invalidText="Size must be at least 1m²"
|
||||||
|
label="Size (m²)"
|
||||||
|
/>
|
||||||
|
</Form>
|
@ -30,8 +30,19 @@ export interface FactoryData {
|
|||||||
floor_size: number
|
floor_size: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export let factories = writable<Factory[]>([])
|
export interface Process {
|
||||||
export let managers = writable<Manager[]>([])
|
id: number,
|
||||||
|
name: string,
|
||||||
|
size: number
|
||||||
|
}
|
||||||
|
export interface ProcessData {
|
||||||
|
name: string,
|
||||||
|
size: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export let factories = writable<Factory[]>([])
|
||||||
|
export let managers = writable<Manager[]>([])
|
||||||
|
export let processess = writable<Process[]>([])
|
||||||
|
|
||||||
function remove_manager_by_id(id: number) {
|
function remove_manager_by_id(id: number) {
|
||||||
managers.update(managers => {
|
managers.update(managers => {
|
||||||
@ -51,6 +62,10 @@ export async function list_managers(): Promise<Manager[]> {
|
|||||||
return invoke("list_managers")
|
return invoke("list_managers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function list_processess(): Promise<Process[]> {
|
||||||
|
return invoke("list_processess")
|
||||||
|
}
|
||||||
|
|
||||||
// Result -> Promise<[factory_id, manager_id]>
|
// Result -> Promise<[factory_id, manager_id]>
|
||||||
export async function add_manager_factory(factory: FactoryData, manager: ManagerData): Promise<[number, number]> {
|
export async function add_manager_factory(factory: FactoryData, manager: ManagerData): Promise<[number, number]> {
|
||||||
// TODO: For now always assume success
|
// TODO: For now always assume success
|
||||||
@ -114,4 +129,48 @@ export async function delete_factory(id: number): Promise<void> {
|
|||||||
}
|
}
|
||||||
return factories
|
return factories
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function delete_process(id: number): Promise<void> {
|
||||||
|
invoke("delete_process", { id })
|
||||||
|
|
||||||
|
processess.update((processess) => {
|
||||||
|
var index = processess.findIndex(f => f.id == id)
|
||||||
|
if (index != -1) {
|
||||||
|
// TODO: Remove from associated factories
|
||||||
|
processess.splice(index, 1)
|
||||||
|
}
|
||||||
|
return processess
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function add_process(process: ProcessData): Promise<number> {
|
||||||
|
// TODO: For now always assume success
|
||||||
|
// TODO: handle error
|
||||||
|
let id = await invoke<number>("add_process", { process })
|
||||||
|
|
||||||
|
processess.update((processess) => {
|
||||||
|
processess.push({
|
||||||
|
id,
|
||||||
|
...process
|
||||||
|
})
|
||||||
|
return processess
|
||||||
|
})
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function update_process(id: number, process: ProcessData): Promise<void> {
|
||||||
|
invoke("update_process", { id, process })
|
||||||
|
|
||||||
|
processess.update((processess) => {
|
||||||
|
var index = processess.findIndex(f => f.id == id)
|
||||||
|
if (index != -1) {
|
||||||
|
processess[index] = {
|
||||||
|
...processess[index],
|
||||||
|
...process
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processess
|
||||||
|
})
|
||||||
}
|
}
|
@ -6,26 +6,17 @@
|
|||||||
ToolbarBatchActions,
|
ToolbarBatchActions,
|
||||||
Button,
|
Button,
|
||||||
ToolbarSearch,
|
ToolbarSearch,
|
||||||
Pagination,
|
|
||||||
Modal,
|
Modal,
|
||||||
} from "carbon-components-svelte"
|
} from "carbon-components-svelte"
|
||||||
import TrashCan from "carbon-icons-svelte/lib/TrashCan.svelte"
|
import TrashCan from "carbon-icons-svelte/lib/TrashCan.svelte"
|
||||||
import Edit from "carbon-icons-svelte/lib/Edit.svelte"
|
import Edit from "carbon-icons-svelte/lib/Edit.svelte"
|
||||||
import ManagerForm from "../lib/ManagerForm.svelte"
|
import ManagerForm from "../lib/ManagerForm.svelte"
|
||||||
import FactoryForm from "../lib/FactoryForm.svelte"
|
import FactoryForm from "../lib/FactoryForm.svelte"
|
||||||
import { add_manager_factory, delete_factory, update_factory, update_manager, factories, list_factories, list_managers, managers } from "../lib/api"
|
import { add_manager_factory, delete_factory, update_factory, update_manager, factories, managers } from "../lib/api"
|
||||||
import { onMount } from 'svelte'
|
|
||||||
|
|
||||||
var rows = []
|
var rows = []
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
$managers = await list_managers()
|
|
||||||
$factories = await list_factories()
|
|
||||||
console.log($managers)
|
|
||||||
})
|
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
console.log($factories)
|
|
||||||
rows = $factories.map(factory => {
|
rows = $factories.map(factory => {
|
||||||
let manager = $managers.find(m => m.id == factory.manager_id)
|
let manager = $managers.find(m => m.id == factory.manager_id)
|
||||||
return {
|
return {
|
||||||
|
46
lab2/src/routes/Processess.svelte
Normal file
46
lab2/src/routes/Processess.svelte
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { add_process, delete_process, processess, update_process } from "../lib/api";
|
||||||
|
import MyDataTable from "../lib/MyDataTable.svelte";
|
||||||
|
import ProcessForm from "../lib/ProcessForm.svelte";
|
||||||
|
|
||||||
|
let resetProcessForm, validateProcessForm, processData
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<MyDataTable
|
||||||
|
addModalTitle={"Create process"}
|
||||||
|
updateModalTitle={"Edit process"}
|
||||||
|
rows={$processess}
|
||||||
|
on:delete={async (event) => {
|
||||||
|
let ids = event.detail
|
||||||
|
for (var id of ids) {
|
||||||
|
await delete_process(id)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:showAddModal={resetProcessForm}
|
||||||
|
on:showUpdateModal={(event) => {
|
||||||
|
let id = event.detail
|
||||||
|
let process = $processess.find(process => process.id == id)
|
||||||
|
processData.name = process.name
|
||||||
|
processData.size = process.size
|
||||||
|
}}
|
||||||
|
on:validateModal={(event) => {
|
||||||
|
if (!validateProcessForm()) event.preventDefault()
|
||||||
|
}}
|
||||||
|
on:add={async () => {
|
||||||
|
await add_process(processData)
|
||||||
|
}}
|
||||||
|
on:update={async (event) => {
|
||||||
|
let id = event.detail
|
||||||
|
await update_process(id, processData)
|
||||||
|
}}
|
||||||
|
headers={[
|
||||||
|
{ key: "name", value: "Name" },
|
||||||
|
{ key: "size", value: "Size" }
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<ProcessForm
|
||||||
|
bind:process={processData}
|
||||||
|
bind:validate={validateProcessForm}
|
||||||
|
bind:reset={resetProcessForm}
|
||||||
|
/>
|
||||||
|
</MyDataTable>
|
Loading…
Reference in New Issue
Block a user