1
0

add ability to assign process to factory

This commit is contained in:
Rokas Puzonas 2023-04-16 02:23:59 +03:00
parent e149726b83
commit 838830d2e6
13 changed files with 416 additions and 269 deletions

View File

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

View File

@ -2410,9 +2410,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.51" version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -2428,9 +2428,9 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]

View File

@ -1,7 +1,6 @@
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};
use sqlx::{Pool, MySql}; use sqlx::{Pool, MySql};
use tauri::State; use tauri::State;
use anyhow::Result; use anyhow::Result;
pub struct Database { pub struct Database {
@ -47,6 +46,30 @@ pub async fn delete_factory(id: Id, db: State<'_, Database>) -> Result<()> {
Ok(()) Ok(())
} }
#[tauri::command]
pub async fn list_factory_processess(id: Id, db: State<'_, Database>) -> Result<Vec<Id>> {
let mut tx = db.pool.begin().await?;
let processess = factory_repo::list_processess(&mut tx, id).await?;
tx.commit().await?;
Ok(processess)
}
#[tauri::command]
pub async fn add_factory_process(factory_id: Id, process_id: Id, db: State<'_, Database>) -> Result<()> {
let mut tx = db.pool.begin().await?;
factory_repo::add_process(&mut tx, factory_id, process_id).await?;
tx.commit().await?;
Ok(())
}
#[tauri::command]
pub async fn delete_factory_process(factory_id: Id, process_id: Id, db: State<'_, Database>) -> Result<()> {
let mut tx = db.pool.begin().await?;
factory_repo::delete_process(&mut tx, factory_id, process_id).await?;
tx.commit().await?;
Ok(())
}
// --------------------- Manager --------------------------- // --------------------- Manager ---------------------------
#[tauri::command] #[tauri::command]

View File

@ -1,6 +1,6 @@
use crate::models::{Id, FactoryData, Factory}; use crate::models::{Id, FactoryData, Factory};
use anyhow::Result; use anyhow::Result;
use sqlx::{Transaction, MySql}; use sqlx::{Transaction, MySql, Row};
type MySqlTransaction<'a> = Transaction<'a, MySql>; type MySqlTransaction<'a> = Transaction<'a, MySql>;
@ -15,8 +15,18 @@ pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
PRIMARY KEY(ID), PRIMARY KEY(ID),
UNIQUE(FK_MANAGER_ID), UNIQUE(FK_MANAGER_ID),
FOREIGN KEY(FK_MANAGER_ID) REFERENCES MANAGER (ID) ON DELETE CASCADE FOREIGN KEY(FK_MANAGER_ID) REFERENCES MANAGER (ID)
);"#).execute(tx).await?; );"#).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(()) Ok(())
} }
@ -38,8 +48,7 @@ pub async fn add(tx: &mut MySqlTransaction<'_>, manager_id: Id, factory: &Factor
} }
pub async fn list(tx: &mut MySqlTransaction<'_>) -> Result<Vec<Factory>> { pub async fn list(tx: &mut MySqlTransaction<'_>) -> Result<Vec<Factory>> {
let factories = sqlx::query_as::<_, Factory>( let factories = sqlx::query_as::<_, Factory>(r#"
r#"
SELECT SELECT
ID as id, ID as id,
NAME as name, NAME as name,
@ -57,6 +66,10 @@ pub async fn delete(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<()> {
.bind(id) .bind(id)
.execute(&mut *tx).await?; .execute(&mut *tx).await?;
sqlx::query("DELETE FROM `factory_supports_processes` WHERE FK_FACTORY_ID = ?")
.bind(id)
.execute(&mut *tx).await?;
sqlx::query("DELETE FROM `factory` WHERE ID = ?") sqlx::query("DELETE FROM `factory` WHERE ID = ?")
.bind(id) .bind(id)
.execute(&mut *tx).await?; .execute(&mut *tx).await?;
@ -65,8 +78,7 @@ pub async fn delete(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<()> {
} }
pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, factory: &FactoryData) -> Result<()> { pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, factory: &FactoryData) -> Result<()> {
sqlx::query( sqlx::query(r#"
r#"
UPDATE `factory` SET UPDATE `factory` SET
NAME = ?, NAME = ?,
LOCATION = ?, LOCATION = ?,
@ -80,4 +92,48 @@ pub async fn update(tx: &mut MySqlTransaction<'_>, id: Id, factory: &FactoryData
.execute(tx).await?; .execute(tx).await?;
Ok(()) Ok(())
}
pub async fn add_process(tx: &mut MySqlTransaction<'_>, factory_id: Id, process_id: Id) -> Result<()> {
sqlx::query(r#"
INSERT INTO `factory_supports_processes`
(`FK_FACTORY_ID`, `FK_PROCESS_ID`)
VALUES
(?, ?)
"#)
.bind(factory_id)
.bind(process_id)
.execute(&mut *tx).await?;
Ok(())
}
pub async fn list_processess(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<Vec<Id>> {
let processess = sqlx::query(r#"
SELECT
FK_PROCESS_ID
FROM `factory_supports_processes`
WHERE FK_FACTORY_ID = ?
"#)
.bind(id)
.fetch_all(tx).await?;
let processess = processess.into_iter()
.map(|r| r.get(0))
.collect();
Ok(processess)
}
pub async fn delete_process(tx: &mut MySqlTransaction<'_>, factory_id: Id, process_id: Id) -> Result<()> {
sqlx::query(r#"
DELETE FROM `factory_supports_processes`
WHERE
FK_FACTORY_ID = ? AND
FK_PROCESS_ID = ?
"#)
.bind(factory_id)
.bind(process_id)
.execute(&mut *tx).await?;
Ok(())
} }

View File

@ -11,16 +11,18 @@ use std::{env, process::exit};
use dotenv::dotenv; use dotenv::dotenv;
use models::{ManagerData, FactoryData, ProcessData}; use models::{ManagerData, FactoryData, ProcessData};
use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row}; use sqlx::{Pool, MySql, mysql::MySqlPoolOptions, Row, Transaction};
use api::*; use api::*;
use anyhow::Result; use anyhow::Result;
type MySqlTransaction<'a> = Transaction<'a, MySql>;
async fn setup_tables(pool: &Pool<MySql>) -> Result<()> { 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?;
process_repo::create_table(&mut tx).await?; process_repo::create_table(&mut tx).await?;
factory_repo::create_table(&mut tx).await?;
tx.commit().await?; tx.commit().await?;
Ok(()) Ok(())
} }
@ -37,13 +39,18 @@ async fn drop_all_tables(pool: &Pool<MySql>) -> Result<()> {
async fn set_foreign_key_checks(pool: &Pool<MySql>, enable: bool) -> Result<()> { async fn set_foreign_key_checks(pool: &Pool<MySql>, enable: bool) -> Result<()> {
let query = match enable { let query = match enable {
true => "SET GLOBAL FOREIGN_KEY_CHECKS=1", true => "SET FOREIGN_KEY_CHECKS=1",
false => "SET GLOBAL FOREIGN_KEY_CHECKS=0", false => "SET FOREIGN_KEY_CHECKS=0",
}; };
sqlx::query(query).execute(pool).await?; sqlx::query(query).execute(pool).await?;
Ok(()) Ok(())
} }
async fn add_test_process(tx: &mut MySqlTransaction<'_>, process: ProcessData) -> Result<()> {
process_repo::add(tx, &process).await?;
Ok(())
}
async fn add_test_data(pool: &Pool<MySql>) -> Result<()> { async fn add_test_data(pool: &Pool<MySql>) -> Result<()> {
let mut tx = pool.begin().await?; let mut tx = pool.begin().await?;
let manager = ManagerData { let manager = ManagerData {
@ -58,13 +65,23 @@ 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?;
add_test_process(&mut tx, ProcessData {
name: "Certifuge 9000".into(),
size: 10.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?;
tx.commit().await?; tx.commit().await?;
Ok(()) Ok(())
@ -103,6 +120,9 @@ async fn main() {
list_factories, list_factories,
delete_factory, delete_factory,
update_factory, update_factory,
list_factory_processess,
add_factory_process,
delete_factory_process,
list_managers, list_managers,
update_manager, update_manager,

View File

@ -15,16 +15,6 @@ pub async fn create_table(tx: &mut MySqlTransaction<'_>) -> Result<()> {
PRIMARY KEY(ID) PRIMARY KEY(ID)
);"#) );"#)
.execute(&mut *tx).await?; .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(()) Ok(())
} }
@ -63,6 +53,10 @@ pub async fn delete(tx: &mut MySqlTransaction<'_>, id: Id) -> Result<()> {
.bind(id) .bind(id)
.execute(&mut *tx).await?; .execute(&mut *tx).await?;
sqlx::query("DELETE FROM `factory_supports_processes` WHERE FK_PROCESS_ID = ?")
.bind(id)
.execute(&mut *tx).await?;
Ok(()) Ok(())
} }

View File

@ -3,7 +3,7 @@
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 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 { 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 Processess from "./routes/Processess.svelte"; import Processess from "./routes/Processess.svelte";
import { Building, Calibrate } from "carbon-icons-svelte"; import { Building, Calibrate } from "carbon-icons-svelte";
@ -12,6 +12,9 @@
$managers = await list_managers() $managers = await list_managers()
$factories = await list_factories() $factories = await list_factories()
$processess = await list_processess() $processess = await list_processess()
for (var factory of $factories) {
$factory_processess[factory.id] = await list_factory_processess(factory.id)
}
}) })
let isSideNavOpen = false; let isSideNavOpen = false;

View File

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { Form, TextInput, NumberInput } from "carbon-components-svelte"; import { Form, TextInput, NumberInput, DataTable } from "carbon-components-svelte";
import type { FactoryData } from "./api" import type { FactoryData } from "./api"
export let factory: FactoryData = { export let factory: FactoryData = {

View File

@ -61,30 +61,30 @@
{rows} {rows}
> >
<Toolbar> <Toolbar>
<ToolbarBatchActions <ToolbarBatchActions
bind:active={activeDelete} bind:active={activeDelete}
on:cancel={(e) => { on:cancel={(e) => {
e.preventDefault(); e.preventDefault();
activeDelete = false; activeDelete = false;
}} }}
>
<Button
icon={TrashCan}
disabled={selectedRowIds.length === 0}
on:click={deleteSelectedRows}
> >
Delete <Button
</Button> icon={TrashCan}
</ToolbarBatchActions> disabled={selectedRowIds.length === 0}
<ToolbarContent> on:click={deleteSelectedRows}
<ToolbarSearch >
persistent Delete
shouldFilterRows </Button>
bind:filteredRowIds </ToolbarBatchActions>
/> <ToolbarContent>
<Button on:click={showAddModal}>Create</Button> <ToolbarSearch
<Button on:click={() => activeDelete = true}>Delete</Button> persistent
</ToolbarContent> shouldFilterRows
bind:filteredRowIds
/>
<Button on:click={showAddModal}>Create</Button>
<Button on:click={() => activeDelete = true}>Delete</Button>
</ToolbarContent>
</Toolbar> </Toolbar>
<svelte:fragment slot="cell" let:row let:cell> <svelte:fragment slot="cell" let:row let:cell>
{#if cell.key === "update_btn"} {#if cell.key === "update_btn"}

View File

@ -0,0 +1,86 @@
<script lang="ts">
import { Button, Dropdown } from "carbon-components-svelte"
import { AddAlt, TrashCan } from "carbon-icons-svelte"
import { processess as allProcessess, type Id } from "./api"
export let processess: Id[] = []
let allProcessItems = []
let selectedAdd = undefined
function getAvailableProcessess() {
return allProcessItems
.filter(item => !processess.includes(item.id))
.map(item => item.id)
}
$: allProcessItems = $allProcessess.map(process => ({ id: process.id, text: process.name }))
$: {
let available = getAvailableProcessess()
if (!available.includes(selectedAdd) && available.length > 0) {
selectedAdd = available[0]
}
}
function addRow(newId) {
processess = [ ...processess, newId ]
selectedAdd = getAvailableProcessess()[0]
}
export function reset() {
selectedAdd = undefined
processess = []
}
export function prepare(newProcessess) {
processess = newProcessess
selectedAdd = getAvailableProcessess()[0]
}
</script>
<div>
<div class="flex flex-col gap-1rem">
{#each processess as id}
<div class="flex flex-row gap-1rem">
<Dropdown
class="flex-grow"
bind:selectedId={id}
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)
}}
/>
</div>
{/each}
<div class="flex flex-row gap-1rem">
{#if allProcessItems.length === processess.length}
<Dropdown
class="flex-grow"
selectedId={1}
items={[{ id: 1, text: "No process available" }]}
disabled={true}
/>
<Button icon={AddAlt} iconDescription="Add" disabled={true} />
{:else}
<Dropdown
class="flex-grow"
bind:selectedId={selectedAdd}
items={allProcessItems.filter(item => !processess.includes(item.id))}
/>
<Button
icon={AddAlt}
iconDescription="Add"
on:click={() => addRow(selectedAdd)}
/>
{/if}
</div>
</div>
</div>

View File

@ -1,14 +1,8 @@
import { invoke } from '@tauri-apps/api/tauri' import { invoke } from '@tauri-apps/api/tauri'
import { writable } from 'svelte/store' import { get, writable, type Writable } from 'svelte/store'
export type Id = number
export interface Manager {
id: number,
first_name: string,
surname: string,
phone_number?: string,
title: string,
email?: string
}
export interface ManagerData { export interface ManagerData {
first_name: string, first_name: string,
surname: string, surname: string,
@ -16,42 +10,63 @@ export interface ManagerData {
title: string, title: string,
email?: string email?: string
} }
export interface Manager extends ManagerData {
export interface Factory { id: Id
id: number,
name: string,
location: string,
floor_size: number,
manager_id: number
} }
export interface FactoryData { export interface FactoryData {
name: string, name: string,
location: string, location: string,
floor_size: number floor_size: number
} }
export interface Factory extends FactoryData {
export interface Process { id: Id,
id: number, manager_id: Id
name: string,
size: number
} }
export interface ProcessData { export interface ProcessData {
name: string, name: string,
size: number size: number
} }
export interface Process extends ProcessData {
id: Id
}
export let factories = writable<Factory[]>([]) export let factory_processess = writable<Record<Id, Id[]>>([])
export let managers = writable<Manager[]>([]) export let factories = writable<Factory[]>([])
export let processess = writable<Process[]>([]) export let managers = writable<Manager[]>([])
export let processess = writable<Process[]>([])
function add_object<T>(objects: Writable<T[]>, object: T) {
objects.update((objects) => {
objects.push(object)
return objects
})
}
function update_object<T>(objects: Writable<T[]>, index: number, updates: Partial<T>) {
if (index == -1) return
objects.update((objects) => {
const obj = objects[index]
for (var key in updates) {
obj[key] = updates[key]
}
return objects
})
}
function remove_object<T>(objects: Writable<T[]>, index: number) {
if (index == -1) return
objects.update((objects) => {
objects.splice(index, 1)
return objects
})
}
function remove_manager_by_id(id: number) { function remove_manager_by_id(id: number) {
managers.update(managers => { remove_object(managers, get(managers).findIndex(m => m.id == id))
var index = managers.findIndex(m => m.id == id)
if (index != -1) {
managers.splice(index, 1)
}
return managers
})
} }
export async function list_factories(): Promise<Factory[]> { export async function list_factories(): Promise<Factory[]> {
@ -66,82 +81,59 @@ export async function list_processess(): Promise<Process[]> {
return invoke("list_processess") return invoke("list_processess")
} }
export async function list_factory_processess(id: number): Promise<Id[]> {
return invoke("list_factory_processess", { id })
}
// 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
// TODO: handle error // TODO: handle error
let [factory_id, manager_id] = await invoke<[number, number]>("add_manager_factory", { factory, manager }) let [factory_id, manager_id] = await invoke<[number, number]>("add_manager_factory", { factory, manager })
factories.update((factories) => { add_object<Factory>(factories, {
factories.push({ id: factory_id,
id: factory_id, manager_id,
manager_id, ...factory
...factory
})
return factories
}) })
managers.update((managers) => { add_object<Manager>(managers, {
managers.push({ id: manager_id, ...manager }) id: manager_id,
return managers ...manager
}) })
return [factory_id, manager_id] return [factory_id, manager_id]
} }
export async function update_manager(id: number, manager: ManagerData): Promise<void> { export async function update_manager(id: number, manager: ManagerData): Promise<void> {
invoke("update_manager", { id, manager }) await invoke("update_manager", { id, manager })
managers.update((managers) => { const index = get(managers).findIndex(f => f.id == id)
var index = managers.findIndex(f => f.id == id) update_object(managers, index, manager)
if (index != -1) {
managers[index] = {
...managers[index],
...manager
}
}
return managers
})
} }
export async function update_factory(id: number, factory: FactoryData): Promise<void> { export async function update_factory(id: number, factory: FactoryData): Promise<void> {
invoke("update_factory", { id, factory }) await invoke("update_factory", { id, factory })
factories.update((factories) => { const index = get(factories).findIndex(f => f.id == id)
var index = factories.findIndex(f => f.id == id) update_object(factories, index, factory)
if (index != -1) {
factories[index] = {
...factories[index],
...factory
}
}
return factories
})
} }
export async function delete_factory(id: number): Promise<void> { export async function delete_factory(id: number): Promise<void> {
invoke("delete_factory", { id }) await invoke("delete_factory", { id })
factories.update((factories) => { const index = get(factories).findIndex(f => f.id == id)
var index = factories.findIndex(f => f.id == id) if (index != -1) {
if (index != -1) { var manager_id = factories[index]
remove_manager_by_id(factories[index].manager_id) remove_object(factories, index)
factories.splice(index, 1) remove_manager_by_id(manager_id)
} }
return factories
})
} }
export async function delete_process(id: number): Promise<void> { export async function delete_process(id: number): Promise<void> {
invoke("delete_process", { id }) await invoke("delete_process", { id })
processess.update((processess) => { const index = get(processess).findIndex(f => f.id == id)
var index = processess.findIndex(f => f.id == id) remove_object(processess, index)
if (index != -1) {
// TODO: Remove from associated factories
processess.splice(index, 1)
}
return processess
})
} }
export async function add_process(process: ProcessData): Promise<number> { export async function add_process(process: ProcessData): Promise<number> {
@ -149,28 +141,63 @@ export async function add_process(process: ProcessData): Promise<number> {
// TODO: handle error // TODO: handle error
let id = await invoke<number>("add_process", { process }) let id = await invoke<number>("add_process", { process })
processess.update((processess) => { add_object<Process>(processess, {
processess.push({ id,
id, ...process
...process
})
return processess
}) })
return id return id
} }
export async function update_process(id: number, process: ProcessData): Promise<void> { export async function update_process(id: number, process: ProcessData): Promise<void> {
invoke("update_process", { id, process }) await invoke("update_process", { id, process })
processess.update((processess) => { var index = get(processess).findIndex(f => f.id == id)
var index = processess.findIndex(f => f.id == id) update_object(processess, index, process)
if (index != -1) { }
processess[index] = {
...processess[index], export async function add_factory_processess(factory_id: Id, process_ids: Id[]): Promise<void> {
...process for (var processId of process_ids) {
} await invoke("add_factory_process", { factoryId: factory_id, processId })
}
factory_processess.update((factory_processess) => {
if (factory_processess[factory_id] == undefined) {
factory_processess[factory_id] = []
} }
return processess for (var process_id of process_ids) {
factory_processess[factory_id].push(process_id)
}
return factory_processess
})
}
export async function update_factory_processess(factory_id: Id, process_ids: Id[]): Promise<void> {
let current = get(factory_processess)[factory_id]
let added = process_ids.filter(id => !current.includes(id))
let removed = current.filter(id => !process_ids.includes(id))
for (var processId of added) {
await invoke("add_factory_process", { factoryId: factory_id, processId })
}
for (var processId of removed) {
await invoke("delete_factory_process", { factoryId: factory_id, processId })
}
factory_processess.update((factory_processess) => {
if (factory_processess[factory_id] == undefined) {
factory_processess[factory_id] = []
}
var processess = factory_processess[factory_id]
for (var process_id of added) {
processess.push(process_id)
}
for (var process_id of removed) {
processess.splice(processess.findIndex(id => id === process_id), 1)
}
return factory_processess
}) })
} }

View File

@ -1,18 +1,9 @@
<script lang="ts"> <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 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, managers } from "../lib/api" import { add_manager_factory, delete_factory, update_factory, update_manager, factories, managers, factory_processess, add_factory_processess, update_factory_processess } from "../lib/api"
import ProcessList from "../lib/ProcessList.svelte"
import MyDataTable from "../lib/MyDataTable.svelte"
var rows = [] var rows = []
@ -29,19 +20,13 @@
}) })
} }
let isModalShown = false let processess = []
let resetProcessList, prepareProcessess
let resetFactoryForm, validateFactoryForm, factoryData let resetFactoryForm, validateFactoryForm, factoryData
let resetManagerForm, validateManagerForm, managerData let resetManagerForm, validateManagerForm, managerData
let activeDelete = false let showUpdateModal = event => {
let selectedRowIds = [] let factory_id = event.detail
let filteredRowIds = []
let currentlyEditingId = undefined
let showUpdateModal = factory_id => {
console.log(factory_id)
currentlyEditingId = factory_id
let factory = $factories.find(factory => factory.id == factory_id) let factory = $factories.find(factory => factory.id == factory_id)
let manager = $managers.find(manager => manager.id == factory.manager_id) let manager = $managers.find(manager => manager.id == factory.manager_id)
@ -54,113 +39,58 @@
managerData.title = manager.title managerData.title = manager.title
managerData.email = manager.email managerData.email = manager.email
isModalShown = true if ($factory_processess[factory_id]) {
prepareProcessess([ ...$factory_processess[factory_id] ])
} else {
prepareProcessess([])
}
} }
let showCreateModal = () => { let showAddModal = () => {
currentlyEditingId = undefined
resetFactoryForm() resetFactoryForm()
resetManagerForm() resetManagerForm()
isModalShown = true resetProcessList()
} }
let closeModal = () => { let validateModal = () => {
isModalShown = false let isFactoryValid = validateFactoryForm()
} let isManagerValid = validateManagerForm()
return isFactoryValid && isManagerValid
let deleteSelectedRows = async () => {
for (var id of selectedRowIds) {
await delete_factory(id)
}
selectedRowIds = []
} }
</script> </script>
<DataTable <MyDataTable
zebra addModalTitle={"Create factory & manager"}
selectable={activeDelete} updateModalTitle={"Edit factory & manager"}
batchSelection={activeDelete} bind:rows
sortable on:showAddModal={showAddModal}
bind:selectedRowIds on:showUpdateModal={showUpdateModal}
on:validateModal={validateModal}
on:add={async () => {
let [factory_id, _] = await add_manager_factory(factoryData, managerData)
await add_factory_processess(factory_id, processess)
}}
on:update={async (event) => {
let factory_id = event.detail
let manager_id = $factories.find(factory => factory.id == factory_id).manager_id
await update_factory(factory_id, factoryData)
await update_manager(manager_id, managerData)
await update_factory_processess(factory_id, processess)
}}
on:delete={async (event) => {
let ids = event.detail
for (var id of ids) {
await delete_factory(id)
}
}}
headers={[ headers={[
{ key: "factory_name", value: "Factory" }, { key: "factory_name", value: "Factory" },
{ key: "factory_location", value: "Location" }, { key: "factory_location", value: "Location" },
{ key: "factory_floor_size", value: "Floor size" }, { key: "factory_floor_size", value: "Floor size" },
{ key: "manager_fullname", value: "Manager" }, { key: "manager_fullname", value: "Manager" }
{ key: "update_btn", empty: true, width: "5rem" },
]} ]}
{rows}
> >
<Toolbar> <div class="flex flex-row gap-1rem mb-1rem">
<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={showCreateModal}>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={currentlyEditingId != undefined ? "Edit factory & manager" : "Create factory & manager"}
primaryButtonText="Confirm"
secondaryButtonText="Cancel"
on:open
on:click:button--secondary={closeModal}
on:submit={async () => {
let isFactoryValid = validateFactoryForm()
let isManagerValid = validateManagerForm()
if (!(isFactoryValid && isManagerValid)) {
return false
}
if (currentlyEditingId != undefined) {
// TODO: Handle if factory is not found
let manager_id = $factories.find(factory => factory.id == currentlyEditingId).manager_id
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
}
closeModal()
return true
}}
>
<div class="flex flex-row gap-1rem">
<div class="flex-grow"> <div class="flex-grow">
<p>Factory</p> <p>Factory</p>
<FactoryForm <FactoryForm
@ -178,4 +108,13 @@
/> />
</div> </div>
</div> </div>
</Modal>
<div class="mt-1rem">
<p class="mb-0.5rem">Processess</p>
<ProcessList
bind:processess
bind:prepare={prepareProcessess}
bind:reset={resetProcessList}
/>
</div>
</MyDataTable>

View File

@ -35,7 +35,7 @@
}} }}
headers={[ headers={[
{ key: "name", value: "Name" }, { key: "name", value: "Name" },
{ key: "size", value: "Size" } { key: "size", value: "Size (m²)" }
]} ]}
> >
<ProcessForm <ProcessForm