From 01d828625d48cec4ab3b53913a522a7ad498fbe5 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 01:38:50 +0800 Subject: [PATCH 01/16] feat(core): change database UUID version from v4 to v7 --- elebox-core/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elebox-core/Cargo.toml b/elebox-core/Cargo.toml index b6f8dbd..e194961 100644 --- a/elebox-core/Cargo.toml +++ b/elebox-core/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" jammdb = "0.11.0" serde = { version = "1.0", features = ["derive"] } rmp-serde = "1.1.2" -uuid = { version = "1.5.0", features = ["v4", "fast-rng", "macro-diagnostics"] } +uuid = { version = "1.5.0", features = ["v7", "fast-rng", "macro-diagnostics"] } csv = "1.3.0" [profile.release] From 7b7da055484ca2c09fc08647634c443af411386a Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 07:41:41 +0800 Subject: [PATCH 02/16] fix(core): check item name already exists when update --- elebox-core/src/category.rs | 16 ++++++++-------- elebox-core/src/manufacturer.rs | 14 +++++++------- elebox-core/src/package.rs | 14 +++++++------- elebox-core/src/part.rs | 14 +++++++------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/elebox-core/src/category.rs b/elebox-core/src/category.rs index 8b02b8b..ae78e9b 100644 --- a/elebox-core/src/category.rs +++ b/elebox-core/src/category.rs @@ -106,6 +106,14 @@ impl<'a> CategoryManager<'a> { } fn to_db_category(&self, category: &Category) -> Result { + // Part category name is unique + if self.db.get_category_id(&category.name).is_some() { + return Err(EleboxError::AlreadyExists( + "Category".to_string(), + category.name.clone(), + )); + } + // Get the ID of parent category let p_id = match &category.parent { Some(p_name) => match self.db.get_category_id(&p_name) { @@ -132,14 +140,6 @@ impl<'a> CategoryManager<'a> { } pub fn add(&self, category: &Category) -> Result<(), EleboxError> { - // Part category name is unique - if self.db.get_category_id(&category.name).is_some() { - return Err(EleboxError::AlreadyExists( - "Category".to_string(), - category.name.clone(), - )); - } - // Normalize let mut cat = Category { name: category.name.clone(), diff --git a/elebox-core/src/manufacturer.rs b/elebox-core/src/manufacturer.rs index 289e75a..49d5bb8 100644 --- a/elebox-core/src/manufacturer.rs +++ b/elebox-core/src/manufacturer.rs @@ -38,6 +38,13 @@ impl<'a> ManufacturerManager<'a> { } fn to_db_mfr(&self, mfr: &Manufacturer) -> Result { + if self.db.get_mfr_id(&mfr.name).is_some() { + return Err(EleboxError::AlreadyExists( + "Mfr".to_string(), + mfr.name.clone(), + )); + } + let db_mfr = DbManufacturer { name: mfr.name.to_string(), alias: match &mfr.alias { @@ -53,13 +60,6 @@ impl<'a> ManufacturerManager<'a> { } pub fn add(&self, mfr: &Manufacturer) -> Result<(), EleboxError> { - if self.db.get_mfr_id(&mfr.name).is_some() { - return Err(EleboxError::AlreadyExists( - "Mfr".to_string(), - mfr.name.clone(), - )); - } - let db_mfr = self.to_db_mfr(mfr)?; self.db.add_mfr(&db_mfr); Ok(()) diff --git a/elebox-core/src/package.rs b/elebox-core/src/package.rs index 7a60696..cfd254a 100644 --- a/elebox-core/src/package.rs +++ b/elebox-core/src/package.rs @@ -46,6 +46,13 @@ impl<'a> PackageManager<'a> { } fn to_db_package(&self, package: &Package) -> Result { + if self.db.get_package_id(&package.name).is_some() { + return Err(EleboxError::AlreadyExists( + "Package".to_string(), + package.name.clone(), + )); + } + let db_pkg = DbPackage { name: package.name.to_string(), pkg_type: match package.pkg_type { @@ -62,13 +69,6 @@ impl<'a> PackageManager<'a> { } pub fn add(&self, package: &Package) -> Result<(), EleboxError> { - if self.db.get_package_id(&package.name).is_some() { - return Err(EleboxError::AlreadyExists( - "Package".to_string(), - package.name.clone(), - )); - } - let db_pkg = self.to_db_package(package)?; self.db.add_package(&db_pkg); Ok(()) diff --git a/elebox-core/src/part.rs b/elebox-core/src/part.rs index 6d2ca78..6a28344 100644 --- a/elebox-core/src/part.rs +++ b/elebox-core/src/part.rs @@ -64,6 +64,13 @@ impl<'a> PartManager<'a> { } fn to_db_part(&self, part: &Part) -> Result { + if self.db.get_part_id(&part.name).is_some() { + return Err(EleboxError::AlreadyExists( + "Part".to_string(), + part.name.clone(), + )); + } + let category_id = match self.db.get_category_id(&part.category) { Some(id) => id.to_string(), None => { @@ -151,13 +158,6 @@ impl<'a> PartManager<'a> { } pub fn add(&self, part: &Part) -> Result<(), EleboxError> { - if self.db.get_part_id(&part.name).is_some() { - return Err(EleboxError::AlreadyExists( - "Part".to_string(), - part.name.clone(), - )); - } - let db_part = self.to_db_part(part)?; self.db.add_part(&db_part); Ok(()) From 9acb8b4516ef96f6668eb7da11d1a78ccf514ed6 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 07:42:44 +0800 Subject: [PATCH 03/16] feat(tauri): add error massage snackbar for part --- elebox-tauri/src/db_cmd_part.ts | 28 +++++++++++++++++++--------- elebox-tauri/src/views/Part.vue | 29 ++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/elebox-tauri/src/db_cmd_part.ts b/elebox-tauri/src/db_cmd_part.ts index 8474ccd..a38903f 100644 --- a/elebox-tauri/src/db_cmd_part.ts +++ b/elebox-tauri/src/db_cmd_part.ts @@ -6,7 +6,7 @@ export namespace DbPart { export async function get(name: string) { return invoke("get_part", { name }).catch((err) => - console.error(`Get part, ${err}`) + console.warn(`Get part, ${err}`) ); } @@ -15,26 +15,36 @@ export namespace DbPart { } export async function add(item: PartInterface) { - await invoke("add_part", { item }) - .then((msg) => console.log(`Add part, ${msg}`)) - .catch((err) => console.error(`Add part, ${err}`)); + try { + const msg = await invoke("add_part", { item }); + console.log(`Add part, ${msg}`); + return msg; + } catch (err) { + console.warn(`Add part, ${err}`); + throw err; + } } export async function update(ori_name: string, new_item: PartInterface) { - await invoke("update_part", { ori_name, new_item }) - .then((msg) => console.log(`Update part, ${msg}`)) - .catch((err) => console.error(`Update part, ${err}`)); + try { + const msg = await invoke("update_part", { ori_name, new_item }); + console.log(`Update part, ${msg}`); + return msg; + } catch (err) { + console.warn(`Update part, ${err}`); + throw err; + } } export async function remove(name: string) { await invoke("del_part", { name }) .then((msg) => console.log(`Delete part, ${msg}`)) - .catch((err) => console.error(`Delete part, ${err}`)); + .catch((err) => console.warn(`Delete part, ${err}`)); } export async function modifyQty(name: string, increment: number) { await invoke("increment_part", { name, increment }) .then((msg) => console.log(`Modify qty part, ${msg}`)) - .catch((err) => console.error(`Modify qty part, ${err}`)); + .catch((err) => console.warn(`Modify qty part, ${err}`)); } } diff --git a/elebox-tauri/src/views/Part.vue b/elebox-tauri/src/views/Part.vue index b4dfcb7..a088297 100644 --- a/elebox-tauri/src/views/Part.vue +++ b/elebox-tauri/src/views/Part.vue @@ -9,6 +9,9 @@ import { CustomField, PkgType, Supplier } from "../interface"; import PartCustomField from "../components/PartCustomField.vue"; import PartSupplier from "../components/PartSupplier.vue"; +const snackbar = ref(false); +const snackbar_msg = ref(""); + const router = useRouter(); const origin_name = ref(""); const part = ref({ @@ -21,7 +24,6 @@ const part = ref({ }); const qty_input = ref(undefined); -// const alert = ref(false); const new_custom_field = ref({ name: "", @@ -66,8 +68,12 @@ async function newPart() { part.value.custom_fields = custom_fields; part.value.suppliers = suppliers; - await DbPart.add(part.value); - router.replace("/"); // Back to home + await DbPart.add(part.value) + .then(() => router.replace("/")) // Back to home + .catch((err) => { + snackbar.value = true; + snackbar_msg.value = err; + }); } async function updatePart() { @@ -94,8 +100,12 @@ async function updatePart() { part.value.custom_fields = custom_fields; part.value.suppliers = suppliers; - await DbPart.update(origin_name.value, part.value); - router.replace("/"); // Back to home + await DbPart.update(origin_name.value, part.value) + .then(() => router.replace("/")) // Back to home + .catch((err) => { + snackbar.value = true; + snackbar_msg.value = err; + }); } async function getCategories() { @@ -382,5 +392,14 @@ onMounted(() => { + + + {{ snackbar_msg }} + + From 8226b6bb58ed13160f69fb0c20e5ffed94097444 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 08:52:54 +0800 Subject: [PATCH 04/16] feat(tauri): add item duplicate rule --- elebox-tauri/src/components/CategoryField.vue | 30 +++++++++++++-- .../src/components/ManufacturerField.vue | 38 +++++++++++++++++-- elebox-tauri/src/components/PackageField.vue | 38 +++++++++++++++++-- elebox-tauri/src/db_cmd_category.ts | 26 +++++++++---- elebox-tauri/src/db_cmd_manufacturer.ts | 22 ++++++++--- elebox-tauri/src/db_cmd_package.ts | 22 ++++++++--- elebox-tauri/src/views/Part.vue | 18 +++++++-- 7 files changed, 162 insertions(+), 32 deletions(-) diff --git a/elebox-tauri/src/components/CategoryField.vue b/elebox-tauri/src/components/CategoryField.vue index 36fe31e..a8b4a2e 100644 --- a/elebox-tauri/src/components/CategoryField.vue +++ b/elebox-tauri/src/components/CategoryField.vue @@ -6,14 +6,30 @@ const props = defineProps<{ origin_name?: string }>(); const category = ref({ name: "", parent: "", alias: "" }); let categories = reactive([]); +const snackbar = ref(false); +const snackbar_msg = ref(""); +const rules = ref({ + required: (v: any) => !!v || "Required", + duplicate: (v: any) => + !categories.some((cat) => cat.name === v) || "Already exists", +}); + async function add() { if (category.value === undefined) { console.warn("undefined"); return; } - await Db.add(category.value); - await list(); + await Db.add(category.value) + .then(() => { + snackbar.value = true; + snackbar_msg.value = "Success"; + list(); + }) + .catch((e) => { + snackbar.value = true; + snackbar_msg.value = e; + }); } async function update() { @@ -61,7 +77,7 @@ onMounted(() => { variant="outlined" v-model="category.name" placeholder="MCU" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required, rules.duplicate]" required > @@ -92,4 +108,12 @@ onMounted(() => { + + {{ snackbar_msg }} + + diff --git a/elebox-tauri/src/components/ManufacturerField.vue b/elebox-tauri/src/components/ManufacturerField.vue index b809513..a88753e 100644 --- a/elebox-tauri/src/components/ManufacturerField.vue +++ b/elebox-tauri/src/components/ManufacturerField.vue @@ -1,9 +1,18 @@ @@ -43,7 +67,7 @@ onMounted(() => { variant="outlined" v-model="mfr.name" placeholder="Texas Instruments" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required, rules.duplicate]" required > @@ -74,4 +98,12 @@ onMounted(() => { + + {{ snackbar_msg }} + + diff --git a/elebox-tauri/src/components/PackageField.vue b/elebox-tauri/src/components/PackageField.vue index bb63d2e..459007f 100644 --- a/elebox-tauri/src/components/PackageField.vue +++ b/elebox-tauri/src/components/PackageField.vue @@ -1,11 +1,20 @@ @@ -78,7 +102,7 @@ onMounted(() => { variant="outlined" v-model.trim="pkg.name" placeholder="SOT-23" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required, rules.duplicate]" required > @@ -101,4 +125,12 @@ onMounted(() => { + + {{ snackbar_msg }} + + diff --git a/elebox-tauri/src/db_cmd_category.ts b/elebox-tauri/src/db_cmd_category.ts index fc6b4f5..cb247fe 100644 --- a/elebox-tauri/src/db_cmd_category.ts +++ b/elebox-tauri/src/db_cmd_category.ts @@ -10,7 +10,7 @@ export namespace DbCategory { export async function get(name: string) { return invoke("get_category", { name }).catch((err) => - console.error(`Get part, ${err}`) + console.warn(`Get part, ${err}`) ); } @@ -19,21 +19,31 @@ export namespace DbCategory { } export async function add(item: CategoryInterface) { - await invoke("add_category", { item }) - .then((msg) => console.log(`Add category, ${msg}`)) - .catch((err) => console.error(`Add category, ${err}`)); + try { + const msg = await invoke("add_category", { item }); + console.log(`Add category, ${msg}`); + return msg; + } catch (err) { + console.warn(`Add category, ${err}`); + throw err; + } } export async function update(ori_name: string, new_item: CategoryInterface) { - await invoke("update_category", { ori_name, new_item }) - .then((msg) => console.log(`Update category, ${msg}`)) - .catch((err) => console.error(`Update category, ${err}`)); + try { + const msg = await invoke("update_category", { ori_name, new_item }); + console.log(`Update category, ${msg}`); + return msg; + } catch (err) { + console.warn(`Update category, ${err}`); + throw err; + } } export async function remove(name: string) { await invoke("del_category", { name }) .then((msg) => console.log(`Delete category, ${msg}`)) - .catch((err) => console.error(`Delete category, ${err}`)); + .catch((err) => console.warn(`Delete category, ${err}`)); } export async function getTree(): Promise { diff --git a/elebox-tauri/src/db_cmd_manufacturer.ts b/elebox-tauri/src/db_cmd_manufacturer.ts index 5fc065b..5233d51 100644 --- a/elebox-tauri/src/db_cmd_manufacturer.ts +++ b/elebox-tauri/src/db_cmd_manufacturer.ts @@ -15,18 +15,28 @@ export namespace DbManufacturer { } export async function add(item: ManufacturerInterface) { - await invoke("add_mfr", { item }) - .then((msg) => console.log(`Add manufacturer, ${msg}`)) - .catch((err) => console.error(`Add manufacturer, ${err}`)); + try { + const msg = await invoke("add_mfr", { item }); + console.log(`Add manufacturer, ${msg}`); + return msg; + } catch (err) { + console.warn(`Add manufacturer, ${err}`); + throw err; + } } export async function update( ori_name: string, new_item: ManufacturerInterface ) { - await invoke("update_mfr", { ori_name, new_item }) - .then((msg) => console.log(`Update manufacturer, ${msg}`)) - .catch((err) => console.error(`Update manufacturer, ${err}`)); + try { + const msg = await invoke("update_mfr", { ori_name, new_item }); + console.log(`Update manufacturer, ${msg}`); + return msg; + } catch (err) { + console.warn(`Update manufacturer, ${err}`); + throw err; + } } export async function remove(name: string) { diff --git a/elebox-tauri/src/db_cmd_package.ts b/elebox-tauri/src/db_cmd_package.ts index 106a977..7d371f7 100644 --- a/elebox-tauri/src/db_cmd_package.ts +++ b/elebox-tauri/src/db_cmd_package.ts @@ -15,15 +15,25 @@ export namespace DbPackage { } export async function add(item: PackageInterface) { - await invoke("add_package", { item }) - .then((msg) => console.log(`Add package, ${msg}`)) - .catch((err) => console.error(`Add package, ${err}`)); + try { + const msg = await invoke("add_package", { item }); + console.log(`Add package, ${msg}`); + return msg; + } catch (err) { + console.warn(`Add package, ${err}`); + throw err; + } } export async function update(ori_name: string, new_item: PackageInterface) { - await invoke("update_package", { ori_name, new_item }) - .then((msg) => console.log(`Update package, ${msg}`)) - .catch((err) => console.error(`Update package, ${err}`)); + try { + const msg = await invoke("update_package", { ori_name, new_item }); + console.log(`Update package, ${msg}`); + return msg; + } catch (err) { + console.warn(`Update package, ${err}`); + throw err; + } } export async function remove(name: string) { diff --git a/elebox-tauri/src/views/Part.vue b/elebox-tauri/src/views/Part.vue index a088297..ea1c107 100644 --- a/elebox-tauri/src/views/Part.vue +++ b/elebox-tauri/src/views/Part.vue @@ -11,6 +11,11 @@ import PartSupplier from "../components/PartSupplier.vue"; const snackbar = ref(false); const snackbar_msg = ref(""); +const rules = ref({ + required: (v: any) => !!v || "Required", + duplicate: (v: any) => + !parts.some((part) => part.name === v) || "Already exists", +}); const router = useRouter(); const origin_name = ref(""); @@ -38,6 +43,7 @@ const new_supplier = ref({ note: "", }); +let parts = reactive([]); let categories = reactive([]); let packages = reactive([]); let mfrs = reactive([]); @@ -108,6 +114,11 @@ async function updatePart() { }); } +async function getParts() { + const data = await DbPart.list(); + Object.assign(parts, data); +} + async function getCategories() { const data = await DbCategory.list(); Object.assign(categories, data); @@ -181,6 +192,7 @@ onMounted(() => { getPart(origin_name.value); } + getParts(); getCategories(); getMfrs(); getPackages(); @@ -221,7 +233,7 @@ onMounted(() => { variant="outlined" v-model="part.name" placeholder="RP2040" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required, rules.duplicate]" required > @@ -231,7 +243,7 @@ onMounted(() => { variant="outlined" v-model="part.category" :items="Object.values(categories).map((cat) => cat.name)" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required]" > @@ -240,7 +252,7 @@ onMounted(() => { variant="outlined" v-model.number="qty_input" placeholder="15" - :rules="[(v: any) => !!v || 'Required']" + :rules="[rules.required]" required type="number" min="0" From 6c200102c7760b0c0fab98696359e61b52949295 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 11:43:01 +0800 Subject: [PATCH 05/16] feat(tauri): update supplier rules --- elebox-tauri/src/components/PartSupplier.vue | 81 ++++++++++++-------- elebox-tauri/src/input_rules.ts | 11 +++ elebox-tauri/src/views/Part.vue | 14 +--- 3 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 elebox-tauri/src/input_rules.ts diff --git a/elebox-tauri/src/components/PartSupplier.vue b/elebox-tauri/src/components/PartSupplier.vue index cad6f4c..1f2a0da 100644 --- a/elebox-tauri/src/components/PartSupplier.vue +++ b/elebox-tauri/src/components/PartSupplier.vue @@ -1,20 +1,38 @@ + + diff --git a/elebox-tauri/src/views/Home.vue b/elebox-tauri/src/views/Home.vue index d91daad..9e264e0 100644 --- a/elebox-tauri/src/views/Home.vue +++ b/elebox-tauri/src/views/Home.vue @@ -1,91 +1,16 @@ diff --git a/elebox-tauri/src/views/PartDetail.vue b/elebox-tauri/src/views/PartDetail.vue index 6cfeaba..561a35c 100644 --- a/elebox-tauri/src/views/PartDetail.vue +++ b/elebox-tauri/src/views/PartDetail.vue @@ -3,6 +3,7 @@ import { onMounted, ref } from "vue"; import { useRoute, useRouter } from "vue-router"; import { DbPart } from "../db_cmd_part"; import ItemEditButton from "../components/ItemEditButton.vue"; +import ItemDeleteButton from "../components/ItemDeleteButton.vue"; const router = useRouter(); const route = useRoute(); @@ -44,46 +45,7 @@ onMounted(() => { - - - - - + From 6ba001a9ca3457347c06f8c3d15fa0910c56f8e2 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 14:08:18 +0800 Subject: [PATCH 12/16] feat(tauri): add parent category be itself check --- elebox-tauri/src/components/CategoryField.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/elebox-tauri/src/components/CategoryField.vue b/elebox-tauri/src/components/CategoryField.vue index a8b4a2e..696ae18 100644 --- a/elebox-tauri/src/components/CategoryField.vue +++ b/elebox-tauri/src/components/CategoryField.vue @@ -51,6 +51,14 @@ async function list() { data.splice(0, 0, { name: "" }); // Root Object.assign(categories, data); + // The parent category cannot be itself + if (props.origin_name) { + const index = categories.findIndex((s) => s.name === props.origin_name); + if (index !== -1) { + categories.splice(index, 1); + } + } + console.debug(`get categories: ${categories.length}`); } From 19f6646cbb93c9c27f9f6a560009febd53c07471 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 16:05:08 +0800 Subject: [PATCH 13/16] feat(core): change export/import CSV to YAML --- elebox-cli/src/category_cmd.rs | 2 +- elebox-cli/src/main.rs | 4 ++-- elebox-cli/src/part_cmd.rs | 4 ++-- elebox-core/Cargo.toml | 1 + elebox-core/src/category.rs | 24 +++++++++++++------ elebox-core/src/lib.rs | 37 +++++++++++++++-------------- elebox-core/src/manufacturer.rs | 10 ++++---- elebox-core/src/package.rs | 10 ++++---- elebox-core/src/part.rs | 15 +++++++----- elebox-core/src/yaml.rs | 24 +++++++++++++++++++ elebox-tauri/src-tauri/src/main.rs | 4 ++-- elebox-tauri/src/views/Settings.vue | 4 ++-- 12 files changed, 89 insertions(+), 50 deletions(-) create mode 100644 elebox-core/src/yaml.rs diff --git a/elebox-cli/src/category_cmd.rs b/elebox-cli/src/category_cmd.rs index b006d02..e75ee49 100644 --- a/elebox-cli/src/category_cmd.rs +++ b/elebox-cli/src/category_cmd.rs @@ -76,7 +76,7 @@ pub fn category_cmd(db: &dyn elebox_core::Database, cmd: &CategoryCommand) { // }; } Some(CategorySubCommand::Export(args)) => { - let _ = manager.export_csv(&args.path); + let _ = manager.export(&args.path); } None => { println!("List part category"); diff --git a/elebox-cli/src/main.rs b/elebox-cli/src/main.rs index 073e391..3127e68 100644 --- a/elebox-cli/src/main.rs +++ b/elebox-cli/src/main.rs @@ -53,9 +53,9 @@ fn main() { EntityType::Init => db.init(), EntityType::Part(cmd) => part_cmd(&db, cmd), EntityType::Category(cmd) => category_cmd(&db, cmd), - EntityType::Export(args) => elebox_core::export_csv(&db, &args.path), + EntityType::Export(args) => elebox_core::export(&db, &args.path), EntityType::Import(args) => { - let _ = elebox_core::import_csv(&args.path); + let _ = elebox_core::import(&args.path); } }; } diff --git a/elebox-cli/src/part_cmd.rs b/elebox-cli/src/part_cmd.rs index 5dc137d..b8d2d0b 100644 --- a/elebox-cli/src/part_cmd.rs +++ b/elebox-cli/src/part_cmd.rs @@ -116,10 +116,10 @@ pub fn part_cmd(db: &dyn elebox_core::Database, cmd: &PartCommand) { } } PartSubCommand::Export(args) => { - let _ = manager.export_csv(&args.path); + let _ = manager.export(&args.path); } PartSubCommand::Import(args) => { - let _ = manager.import_csv(&args.path); + let _ = manager.import(&args.path); } }, None => { diff --git a/elebox-core/Cargo.toml b/elebox-core/Cargo.toml index e194961..b0c96a8 100644 --- a/elebox-core/Cargo.toml +++ b/elebox-core/Cargo.toml @@ -13,6 +13,7 @@ serde = { version = "1.0", features = ["derive"] } rmp-serde = "1.1.2" uuid = { version = "1.5.0", features = ["v7", "fast-rng", "macro-diagnostics"] } csv = "1.3.0" +serde_yaml = "0.9.34" [profile.release] lto = true diff --git a/elebox-core/src/category.rs b/elebox-core/src/category.rs index e34ed26..751c810 100644 --- a/elebox-core/src/category.rs +++ b/elebox-core/src/category.rs @@ -1,4 +1,4 @@ -use crate::{csv::*, db::*, errors::EleboxError}; +use crate::{csv::*, db::*, errors::EleboxError, yaml::*}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, fmt::Debug}; @@ -165,26 +165,36 @@ impl<'a> CategoryManager<'a> { Ok(()) } - pub fn export_csv(&self, filename: &str) -> Result<(), ()> { + pub fn export(&self, filename: &str) -> Result<(), ()> { let cats = self.list(); - let res = write_csv(filename, cats, None); + let res = write_yaml(filename, cats); return res; } - pub fn import_csv(&self, filename: &str) -> Result<(), ()> { - let res_parts = read_csv(filename, None); + pub fn import(&self, filename: &str) -> Result<(), ()> { + let res_parts = read_yaml(filename); if res_parts.is_err() { return Err(()); } let cats: Vec = res_parts.unwrap(); - for cat in cats { - let _ = self.add(&cat); + for cat in &cats { + self.add_recursion(cat, &cats); } Ok(()) } + fn add_recursion(&self, category: &Category, cats: &[Category]) -> Result<(), EleboxError> { + if let Some(parent_name) = &category.parent { + if let Some(parent_cat) = cats.iter().find(|c| c.name == *parent_name) { + self.add_recursion(parent_cat, cats); + } + } + + self.add(category) + } + fn to_node(&self, name: String, map: &HashMap>) -> TreeNode { let mut children = vec![]; diff --git a/elebox-core/src/lib.rs b/elebox-core/src/lib.rs index 54c2bf3..8d0dd8a 100644 --- a/elebox-core/src/lib.rs +++ b/elebox-core/src/lib.rs @@ -6,6 +6,7 @@ mod errors; mod manufacturer; mod package; mod part; +mod yaml; pub use category::*; pub use db::CustomField; @@ -19,45 +20,45 @@ pub use part::*; pub use default_db::create_default_db; -pub fn export_csv(db: &dyn Database, path: &str) { - let filename_part = format!("{}{}", path, "elebox_export_parts.tsv"); - let _ = PartManager::new(db).export_csv(&filename_part); +pub fn export(db: &dyn Database, path: &str) { + let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); + let _ = PartManager::new(db).export(&filename_part); - let filename_cat = format!("{}{}", path, "elebox_export_categories.tsv"); - let _ = CategoryManager::new(db).export_csv(&filename_cat); + let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); + let _ = CategoryManager::new(db).export(&filename_cat); - let filename_pkg = format!("{}{}", path, "elebox_export_packages.tsv"); - let _ = PackageManager::new(db).export_csv(&filename_pkg); + let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); + let _ = PackageManager::new(db).export(&filename_pkg); - let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.tsv"); - let _ = ManufacturerManager::new(db).export_csv(&filename_mfr); + let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); + let _ = ManufacturerManager::new(db).export(&filename_mfr); } -pub fn import_csv(path: &str) -> Result<(), String> { +pub fn import(path: &str) -> Result<(), String> { let db_path = format!("{}{}", path, "import_elebox.db"); let db = JammDatabase::new(&db_path); db.init(); - let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.tsv"); - let res = ManufacturerManager::new(&db).import_csv(&filename_mfr); + let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); + let res = ManufacturerManager::new(&db).import(&filename_mfr); if res.is_err() { return Err("Part".to_string()); } - let filename_pkg = format!("{}{}", path, "elebox_export_packages.tsv"); - let res = PackageManager::new(&db).import_csv(&filename_pkg); + let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); + let res = PackageManager::new(&db).import(&filename_pkg); if res.is_err() { return Err("Part".to_string()); } - let filename_cat = format!("{}{}", path, "elebox_export_categories.tsv"); - let res = CategoryManager::new(&db).import_csv(&filename_cat); + let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); + let res = CategoryManager::new(&db).import(&filename_cat); if res.is_err() { return Err("Part".to_string()); } - let filename_part = format!("{}{}", path, "elebox_export_parts.tsv"); - let res = PartManager::new(&db).import_csv(&filename_part); + let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); + let res = PartManager::new(&db).import(&filename_part); if res.is_err() { return Err("Part".to_string()); } diff --git a/elebox-core/src/manufacturer.rs b/elebox-core/src/manufacturer.rs index 1cad512..8b69eb2 100644 --- a/elebox-core/src/manufacturer.rs +++ b/elebox-core/src/manufacturer.rs @@ -1,4 +1,4 @@ -use crate::{csv::*, db::*, errors::EleboxError}; +use crate::{csv::*, db::*, errors::EleboxError, yaml::*}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -115,14 +115,14 @@ impl<'a> ManufacturerManager<'a> { .collect() } - pub fn export_csv(&self, filename: &str) -> Result<(), ()> { + pub fn export(&self, filename: &str) -> Result<(), ()> { let mfrs = self.list(); - let res = write_csv(filename, mfrs, None); + let res = write_yaml(filename, mfrs); return res; } - pub fn import_csv(&self, filename: &str) -> Result<(), ()> { - let res_parts = read_csv(filename, None); + pub fn import(&self, filename: &str) -> Result<(), ()> { + let res_parts = read_yaml(filename); if res_parts.is_err() { return Err(()); } diff --git a/elebox-core/src/package.rs b/elebox-core/src/package.rs index 100ec15..387787f 100644 --- a/elebox-core/src/package.rs +++ b/elebox-core/src/package.rs @@ -1,4 +1,4 @@ -use crate::{csv::*, db::*, errors::EleboxError}; +use crate::{csv::*, db::*, errors::EleboxError, yaml::*}; use serde::{Deserialize, Serialize}; use std::fmt::Debug; @@ -131,14 +131,14 @@ impl<'a> PackageManager<'a> { .collect() } - pub fn export_csv(&self, filename: &str) -> Result<(), ()> { + pub fn export(&self, filename: &str) -> Result<(), ()> { let pkgs = self.list(); - let res = write_csv(filename, pkgs, None); + let res = write_yaml(filename, pkgs); return res; } - pub fn import_csv(&self, filename: &str) -> Result<(), ()> { - let res_parts = read_csv(filename, None); + pub fn import(&self, filename: &str) -> Result<(), ()> { + let res_parts = read_yaml(filename); if res_parts.is_err() { return Err(()); } diff --git a/elebox-core/src/part.rs b/elebox-core/src/part.rs index 6384dc7..ffa092a 100644 --- a/elebox-core/src/part.rs +++ b/elebox-core/src/part.rs @@ -1,4 +1,4 @@ -use crate::{csv::*, db::*, errors::EleboxError}; +use crate::{csv::*, db::*, errors::EleboxError, yaml::*}; use serde::{Deserialize, Serialize}; use std::fmt::{format, Debug}; @@ -231,21 +231,24 @@ impl<'a> PartManager<'a> { .collect() } - pub fn export_csv(&self, filename: &str) -> Result<(), ()> { + pub fn export(&self, filename: &str) -> Result<(), ()> { let parts = self.list(); - let res = write_csv(filename, parts, None); + let res = write_yaml(filename, parts); return res; } - pub fn import_csv(&self, filename: &str) -> Result<(), ()> { - let res_parts = read_csv(filename, None); + pub fn import(&self, filename: &str) -> Result<(), ()> { + let res_parts = read_yaml(filename); + if res_parts.is_err() { return Err(()); } let parts: Vec = res_parts.unwrap(); for part in parts { - let _ = self.add(&part); + if let Err(e) = self.add(&part) { + panic!("{}", e.to_string()) + } } Ok(()) diff --git a/elebox-core/src/yaml.rs b/elebox-core/src/yaml.rs new file mode 100644 index 0000000..834005f --- /dev/null +++ b/elebox-core/src/yaml.rs @@ -0,0 +1,24 @@ +use std::fs::{self, File}; + +use csv::{ReaderBuilder, WriterBuilder}; +use serde::{Deserialize, Serialize}; + +use serde_yaml; + +pub fn write_yaml(filename: &str, items: Vec) -> Result<(), ()> +where + T: Serialize, +{ + let contents = serde_yaml::to_string(&items).unwrap(); + fs::write(filename, contents); + Ok(()) +} + +pub fn read_yaml(filename: &str) -> Result, ()> +where + T: for<'a> Deserialize<'a>, +{ + let content = fs::read_to_string(filename).unwrap(); + let items: Vec = serde_yaml::from_str(&content).unwrap(); + Ok(items) +} diff --git a/elebox-tauri/src-tauri/src/main.rs b/elebox-tauri/src-tauri/src/main.rs index c73a414..94eaec9 100644 --- a/elebox-tauri/src-tauri/src/main.rs +++ b/elebox-tauri/src-tauri/src/main.rs @@ -232,12 +232,12 @@ fn set_db_path(path: tauri::State, new_path: &str) { fn export_csv(path: tauri::State, csv_path: &str) { let p = GET!(path); let db = elebox_core::JammDatabase::new(&p); - elebox_core::export_csv(&db, csv_path); + elebox_core::export(&db, csv_path); } #[tauri::command(rename_all = "snake_case")] fn import_csv(csv_path: &str) -> Result<(), String> { - elebox_core::import_csv(csv_path) + elebox_core::import(csv_path) } fn main() { diff --git a/elebox-tauri/src/views/Settings.vue b/elebox-tauri/src/views/Settings.vue index 15c491a..1500ea1 100644 --- a/elebox-tauri/src/views/Settings.vue +++ b/elebox-tauri/src/views/Settings.vue @@ -6,12 +6,12 @@ import DbPath from "../components/DbPath.vue"; const csv_path = ref(""); async function export_csv() { - await invoke("export_csv", { csvPath: csv_path.value }); + await invoke("export_csv", { csv_path: csv_path.value }); console.debug(`Export path: ${csv_path.value}`); } async function import_csv() { - await invoke("import_csv", { csvPath: csv_path.value }); + await invoke("import_csv", { csv_path: csv_path.value }); console.debug(`Import path: ${csv_path.value}`); } From 1a49104fb5c313e9191e218c58d6dba79ae392ca Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 16:39:29 +0800 Subject: [PATCH 14/16] refactor(core): move export and import methods --- elebox-core/src/backup.rs | 50 +++++++++++++++++++++++++++++++++++++++ elebox-core/src/lib.rs | 49 +++----------------------------------- 2 files changed, 53 insertions(+), 46 deletions(-) create mode 100644 elebox-core/src/backup.rs diff --git a/elebox-core/src/backup.rs b/elebox-core/src/backup.rs new file mode 100644 index 0000000..b1379db --- /dev/null +++ b/elebox-core/src/backup.rs @@ -0,0 +1,50 @@ +use crate::{ + CategoryManager, Database, JammDatabase, ManufacturerManager, PackageManager, PartManager, +}; +use std::path::PathBuf; + +pub fn export(db: &dyn Database, path: &str) { + let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); + let _ = PartManager::new(db).export(&filename_part); + + let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); + let _ = CategoryManager::new(db).export(&filename_cat); + + let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); + let _ = PackageManager::new(db).export(&filename_pkg); + + let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); + let _ = ManufacturerManager::new(db).export(&filename_mfr); +} + +pub fn import(path: &str) -> Result<(), String> { + let db_path = format!("{}{}", path, "import_elebox.db"); + let db = JammDatabase::new(&db_path); + db.init(); + + let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); + let res = ManufacturerManager::new(&db).import(&filename_mfr); + if res.is_err() { + return Err("Part".to_string()); + } + + let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); + let res = PackageManager::new(&db).import(&filename_pkg); + if res.is_err() { + return Err("Part".to_string()); + } + + let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); + let res = CategoryManager::new(&db).import(&filename_cat); + if res.is_err() { + return Err("Part".to_string()); + } + + let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); + let res = PartManager::new(&db).import(&filename_part); + if res.is_err() { + return Err("Part".to_string()); + } + + Ok(()) +} diff --git a/elebox-core/src/lib.rs b/elebox-core/src/lib.rs index 8d0dd8a..864c048 100644 --- a/elebox-core/src/lib.rs +++ b/elebox-core/src/lib.rs @@ -1,3 +1,4 @@ +mod backup; mod category; mod csv; mod db; @@ -18,50 +19,6 @@ pub use manufacturer::*; pub use package::*; pub use part::*; +pub use backup::export; +pub use backup::import; pub use default_db::create_default_db; - -pub fn export(db: &dyn Database, path: &str) { - let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); - let _ = PartManager::new(db).export(&filename_part); - - let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); - let _ = CategoryManager::new(db).export(&filename_cat); - - let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); - let _ = PackageManager::new(db).export(&filename_pkg); - - let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); - let _ = ManufacturerManager::new(db).export(&filename_mfr); -} - -pub fn import(path: &str) -> Result<(), String> { - let db_path = format!("{}{}", path, "import_elebox.db"); - let db = JammDatabase::new(&db_path); - db.init(); - - let filename_mfr = format!("{}{}", path, "elebox_export_mfrs.yaml"); - let res = ManufacturerManager::new(&db).import(&filename_mfr); - if res.is_err() { - return Err("Part".to_string()); - } - - let filename_pkg = format!("{}{}", path, "elebox_export_packages.yaml"); - let res = PackageManager::new(&db).import(&filename_pkg); - if res.is_err() { - return Err("Part".to_string()); - } - - let filename_cat = format!("{}{}", path, "elebox_export_categories.yaml"); - let res = CategoryManager::new(&db).import(&filename_cat); - if res.is_err() { - return Err("Part".to_string()); - } - - let filename_part = format!("{}{}", path, "elebox_export_parts.yaml"); - let res = PartManager::new(&db).import(&filename_part); - if res.is_err() { - return Err("Part".to_string()); - } - - Ok(()) -} From 203f28261f145aca3af030d747e3e0c762827be1 Mon Sep 17 00:00:00 2001 From: ziteh Date: Sat, 20 Jul 2024 16:44:13 +0800 Subject: [PATCH 15/16] refactor(tauri): remove unused code --- elebox-tauri/src/components/NewDatabase.vue | 10 ++++------ elebox-tauri/src/views/Home.vue | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/elebox-tauri/src/components/NewDatabase.vue b/elebox-tauri/src/components/NewDatabase.vue index 1344327..edfbc06 100644 --- a/elebox-tauri/src/components/NewDatabase.vue +++ b/elebox-tauri/src/components/NewDatabase.vue @@ -1,7 +1,6 @@