new project init
3
src-tauri/.gitignore
vendored
@@ -1,4 +1,7 @@
|
||||
# Generated by Cargo
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
||||
|
1692
src-tauri/Cargo.lock
generated
@@ -1,26 +1,28 @@
|
||||
[package]
|
||||
name = "app"
|
||||
name = "inventory"
|
||||
version = "0.1.0"
|
||||
description = "A Tauri App"
|
||||
authors = ["you"]
|
||||
license = ""
|
||||
repository = ""
|
||||
edition = "2021"
|
||||
rust-version = "1.77.2"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "app_lib"
|
||||
# The `_lib` suffix may seem redundant but it is necessary
|
||||
# to make the lib name unique and wouldn't conflict with the bin name.
|
||||
# This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
|
||||
name = "inventory_lib"
|
||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.2", features = [] }
|
||||
tauri-build = { version = "2", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0"
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-opener = "2"
|
||||
serde_json = "1"
|
||||
rusqlite = "0.26.0"
|
||||
anyhow = "1.0"
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4"
|
||||
tauri = { version = "2.1.0", features = [] }
|
||||
tauri-plugin-log = "2.0.0-rc"
|
||||
mysql = "25.0.1"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
@@ -1,4 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build();
|
||||
tauri_build::build()
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,10 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "enables the default permissions",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default"
|
||||
"core:default",
|
||||
"opener:default"
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 974 B |
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 903 B |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 14 KiB |
@@ -1,16 +1,135 @@
|
||||
use lazy_static::lazy_static;
|
||||
use rusqlite::{params, Connection};
|
||||
use std::sync::Mutex;
|
||||
use chrono::{NaiveDateTime, DateTime, Utc};
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref DB: Mutex<Option<Connection>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct InventoryItem {
|
||||
id: Option<i32>,
|
||||
name: String,
|
||||
quantity: i32,
|
||||
price: f64,
|
||||
category: String,
|
||||
#[serde(with = "chrono::serde::ts_seconds_option")]
|
||||
last_updated: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust Yimmers!", name)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn db_init() -> Result<(), String> {
|
||||
let conn = Connection::open("inventory.db").expect("Failed to open database");
|
||||
|
||||
conn.execute(
|
||||
"CREATE TABLE IF NOT EXISTS inventory (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
quantity INTEGER NOT NULL,
|
||||
price REAL NOT NULL,
|
||||
category TEXT NOT NULL,
|
||||
last_updated DATETIME NOT NULL
|
||||
)",
|
||||
[],
|
||||
)
|
||||
.expect("Failed to create table");
|
||||
|
||||
*DB.lock().unwrap() = Some(conn);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn add_item(name: String, quantity: i32, price: f64, category: String) -> Result<(), String> {
|
||||
let conn = DB.lock().unwrap();
|
||||
let conn = conn.as_ref().ok_or("Database not initialized")?;
|
||||
|
||||
let now = Utc::now();
|
||||
let now_str = now.format("%Y-%m-%d %H:%M:%S").to_string();
|
||||
|
||||
conn.execute(
|
||||
"INSERT INTO inventory (name, quantity, price, category, last_updated)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5)",
|
||||
params![name, quantity, price, category, now_str],
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_items() -> Result<Vec<InventoryItem>, String> {
|
||||
let conn = DB.lock().unwrap();
|
||||
let conn = conn.as_ref().ok_or("Database not initialized")?;
|
||||
|
||||
let mut stmt = conn
|
||||
.prepare("SELECT id, name, quantity, price, category, last_updated FROM inventory")
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let items = stmt
|
||||
.query_map([], |row| {
|
||||
let datetime_str: String = row.get(5)?;
|
||||
let naive_dt = NaiveDateTime::parse_from_str(&datetime_str, "%Y-%m-%d %H:%M:%S")
|
||||
.map_err(|_| rusqlite::Error::InvalidColumnType(5, String::from("DateTime"), rusqlite::types::Type::Text))?;
|
||||
let last_updated = Some(DateTime::from_naive_utc_and_offset(naive_dt, Utc));
|
||||
|
||||
Ok(InventoryItem {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
quantity: row.get(2)?,
|
||||
price: row.get(3)?,
|
||||
category: row.get(4)?,
|
||||
last_updated,
|
||||
})
|
||||
})
|
||||
.map_err(|e| e.to_string())?
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(items)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_inventory() -> Result<Vec<InventoryItem>, String> {
|
||||
let conn = DB.lock().unwrap();
|
||||
let conn = conn.as_ref().ok_or("Database not initialized")?;
|
||||
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT id, name, quantity, price, category, last_updated FROM inventory"
|
||||
).map_err(|e| e.to_string())?;
|
||||
|
||||
let items = stmt.query_map([], |row| {
|
||||
let datetime_str: String = row.get(5)?;
|
||||
let naive_dt = NaiveDateTime::parse_from_str(&datetime_str, "%Y-%m-%d %H:%M:%S")
|
||||
.map_err(|_| rusqlite::Error::InvalidColumnType(5, String::from("DateTime"), rusqlite::types::Type::Text))?;
|
||||
let last_updated = Some(DateTime::from_naive_utc_and_offset(naive_dt, Utc));
|
||||
|
||||
Ok(InventoryItem {
|
||||
id: row.get(0)?,
|
||||
name: row.get(1)?,
|
||||
quantity: row.get(2)?,
|
||||
price: row.get(3)?,
|
||||
category: row.get(4)?,
|
||||
last_updated,
|
||||
})
|
||||
}).map_err(|e| e.to_string())?;
|
||||
|
||||
items.collect::<Result<Vec<_>, _>>()
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
.level(log::LevelFilter::Info)
|
||||
.build(),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
.invoke_handler(tauri::generate_handler![greet, db_init, add_item, get_inventory, get_items])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
@@ -1,44 +1,6 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
use mysql::*;
|
||||
use mysql::prelude::*;
|
||||
use tauri::generate_handler;
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.invoke_handler(generate_handler![get_data, insert_data])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
inventory_lib::run()
|
||||
}
|
||||
|
||||
fn my_sql_connect() -> Result<PooledConn> {
|
||||
let url: &str = "mysql://rust:rust@localhost:43158/Inventory";
|
||||
let pool = Pool::new(url)?;
|
||||
let conn = pool.get_conn()?;
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_data() -> Result<Vec<String>, String> {
|
||||
let mut conn = my_sql_connect().map_err(|e| e.to_string())?;
|
||||
let result: Vec<String> = conn
|
||||
.query("SELECT name FROM users")
|
||||
.map_err(|e| e.to_string())?;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn insert_data(name: String) -> Result<(), String> {
|
||||
println!("Inserting data: {}", name); // Debug print
|
||||
let mut conn = my_sql_connect().map_err(|e| {
|
||||
eprintln!("Connection error: {}", e); // Print connection error
|
||||
e.to_string()
|
||||
})?;
|
||||
conn.exec_drop("INSERT INTO users (name) VALUES (:name)", params! {"name" => name})
|
||||
.map_err(|e| {
|
||||
eprintln!("Insert error: {}", e); // Print insert error
|
||||
e.to_string()
|
||||
})?;
|
||||
println!("Data inserted successfully"); // Debug print
|
||||
Ok(())
|
||||
}
|
@@ -1,22 +1,20 @@
|
||||
{
|
||||
"$schema": "https://schema.tauri.app/config/2.0.0-rc",
|
||||
"productName": "AE2",
|
||||
"$schema": "https://schema.tauri.app/config/2",
|
||||
"productName": "inventory",
|
||||
"version": "0.1.0",
|
||||
"identifier": "com.tauri.dev",
|
||||
"identifier": "com.inventory.app",
|
||||
"build": {
|
||||
"beforeDevCommand": "cd frontend && deno task dev",
|
||||
"devUrl": "http://localhost:3000"
|
||||
},
|
||||
"beforeDevCommand": "deno task dev",
|
||||
"devUrl": "http://localhost:1420",
|
||||
"beforeBuildCommand": "deno task build",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
|
||||
"windows": [
|
||||
{
|
||||
"title": "Inventory",
|
||||
"width": 800,
|
||||
"height": 600,
|
||||
"resizable": true,
|
||||
"fullscreen": false
|
||||
|
||||
"title": "inventory",
|
||||
"width": 1600,
|
||||
"height": 1200
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|