vault backup: 2024-05-15 19:12:54
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
## App zum prepen
|
||||
|
||||
App zum prep Inventar Management mit mhd. Soll und ist bestand
|
||||
Übersicht nach empfohlenen Produkten
|
||||
Hochrechnung für Empfohlene menge anhand Personen im Haushalt
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
- Hauptkategorien unter denen einzelne Etiketten erstellt werden können.
|
||||
- Zwei Label Arten:
|
||||
- Grid
|
||||
- Custom
|
||||
- Grid:
|
||||
- Einfacher Editor für Grid Eigenschaften
|
||||
- Custom:
|
||||
- Aufwendiger Editor
|
||||
- Textfelder
|
||||
- Farbe
|
||||
- Schriftgröße
|
||||
- Schriftart
|
||||
- Bilder
|
||||
- EAN Code
|
||||
- Label Content in DB speichern
|
||||
- Text für Textfelder
|
||||
- EAN Nummer für Barcode
|
||||
- Daten der einzelnen Labels in Datenbank
|
||||
- Bilder als Datei auf Server speichern
|
||||
- Benutzer vor Druck nach MHD und Chargennummer fragen
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
- [ ] Grid Layout:
|
||||
- [ ] Anhand der maximalen Zeilen Anzahl Textfelder erstellen
|
||||
- [ ] In Einstellungen festlegen wie das Textfeld heißt
|
||||
- [ ] Beispiel Text für Eingabe hinterlegen
|
||||
- [ ] Schriftarten von PC laden?
|
||||
- [ ]
|
||||
@@ -0,0 +1,10 @@
|
||||
- [ ] Editor für Custom Labels
|
||||
- [ ] Optionales anzeigen einzelner Elemente in Abhängigkeit von Benutzer definierte Werte
|
||||
- [ ] Editor für Content für Labels
|
||||
- [ ] Kleines 'Inventar System'
|
||||
- z.B. wie viel von Zweckform Blätter noch da sind
|
||||
- [ ] Benachrichtigung per Mail und in Weboberfläche wenn Inventar unter bestimmten Wert fällt.
|
||||
- [ ] Druck Historie
|
||||
- [ ] Benutzer & Benutzer Verwaltung
|
||||
- [ ] Bei Grid Label merken was die letzte Position war und automatisch als neue Start Position setzten.
|
||||
- [ ]
|
||||
@@ -0,0 +1,4 @@
|
||||
Kombi 125 Stk. - 1 für Temperatur
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
|
||||
- [ ] Beim einbuchen von Lieferungen (einzel/alle) nach Charge fragen und Server übergeben und dort verarbeiten und anwenden
|
||||
- [ ] In Variante anzeigen wo diese verwendet wird
|
||||
- [ ] In Variante Etiketten Ansicht und Daten
|
||||
- [ ] Delete Funktionalität bei Varianten und Artikel überprüfen
|
||||
- [ ] Lieferschein Nummer als Charge
|
||||
- [ ] Rundungsfehler
|
||||
- Schauen ob JS sowas wie Mathe.abs für vergleiche bei Produktion und Chargen hat
|
||||
- [ ] Vue & Nuxt 3
|
||||
- [x] Trim für Textfelder ✅ 2024-01-18
|
||||
- [x] Graph für Preis Historie ✅ 2024-04-15
|
||||
- [ ] Verwendung in nicht nur Produktnamen sondern auch Varianten Namen anzeigen
|
||||
- [ ] Chargen Rückverfolgung überarbeiten
|
||||
- [ ] Rückmeldung von Server ob Aktion erfolgreich war
|
||||
- [ ] Lieferung alle Zutaten einbuchen -> Code anschauen dauert so lange?
|
||||
- [ ] Bei Produktion Chargen auswahl prüfen ob Zutaten die öfters vorkommen richtig berechnet sind und ob auswahl menge stimmt.
|
||||
- [ ] Felder für Produktionsbeleg und weitere Felder für Datenbank??? Schon gemacht?
|
||||
- Produziert am: -> Normale Charge (ABC) intern verwenden und link MHD für extern
|
||||
- [ ] Bei Produktion Chargen Auswahl bei leeren Feldern Wert auf 0 setzten und übermitteln oder auf Eingabe bestehen?
|
||||
- [ ] Extra Feld für Produziert und Bestand -> Option zum späteren dazu / abbuchen der Menge
|
||||
- [ ] Rezepte Vordruck auch nach Kipper aufteilen
|
||||
- [ ] Artikelnummer der Lieferanten hinterlegen
|
||||
- [ ] Bestelllisten nach Artikel sortieren
|
||||
- [x] Verfügbarkeit in Varianten Ansicht prüfen ⏫ ✅ 2023-11-30
|
||||
- [ ] Update Varianten Preis wenn Zutaten hinzugefügt/entfernt wurden
|
||||
- [ ] Base EK prüfen was zu tun ist wenn kein Preis hinterlegt ist. NaN!
|
||||
- [x] Benachrichtungen in Cookies speichern ✅ 2023-12-27
|
||||
- [ ] Angeblichen UI Fehler beim hinzufügen von Zutaten prüfen
|
||||
- [ ] Lade Indikatoren & Buttons deaktivieren beim hinzufügen von Produkten zur Lieferung
|
||||
- [x] Complete für Steper beim Zutaten hinzufügen setzen ✅ 2024-03-02
|
||||
- [ ] PDF für Zettel für Boxen erstellen
|
||||
- [ ] Ganze Calls im Store überarbeiten:
|
||||
- [ ] https://www.youtube.com/watch?v=njsGVmcWviY
|
||||
- [ ] Beim erstellen einer Lieferung / hinzufügen von Produkten / einbuchen der Lieferung fragen ob alles neu geliefert wird oder ob aktueller bestand berücksichtig werden soll
|
||||
- [ ] Bei Verwendet in die einzelne Varianten anzeigen und nicht nur Artikel
|
||||
- [ ] Artikel/Liefer/Chargen Suche direkt öffnen wenn keine ausgewählt ist
|
||||
- [ ]
|
||||
|
||||
---
|
||||
|
||||
- [x] Verwendet in Funktionalität ✅ 2024-04-17
|
||||
- [ ] Preise bei "Mischprodukt" eingeben und berechneter Preis als Hint anzeigen
|
||||
- [x] Chargen Rückverfolgungs Ansicht ✅ 2024-04-18
|
||||
- [ ] Extra Feld für Bezeichnung für Etikett
|
||||
- [ ] Einmal im Hauptartikel
|
||||
- [ ] Einmal in Variante
|
||||
- [ ] Je nach dem was vorhanden ist verwenden
|
||||
- Variante Etiketten bez.-> Hauptartikel Etiketten bez. -> Zusammensetzung von Hauptartikel + Varianten Standard Bezeichnung
|
||||
- [ ] Fehlende Funktionen für Nuxt 3 port:
|
||||
- [ ] Verwendete gesamtmenge einer Variante in Zeitraum von X bis Y anzeigen ggf. über Admin Ansicht
|
||||
- [ ] Varianten Ersetzten Option über Admin Ansicht
|
||||
- [ ] Preise aktualisieren
|
||||
- [ ] Chargen Ansicht linke Seite wird nicht richtig aktualisiert
|
||||
- [ ]
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
- [ ] Benutzer System
|
||||
- [ ] Produkt spezifischer Verlust?
|
||||
- [ ] Lieferanten Feld für Produkte -> Extra Datenstruckur
|
||||
- [ ] Bei neuer Bestellung vorhandenen Bestand berücksichtigen
|
||||
- [ ] Bestellung:
|
||||
- [ ] Vorhandenen Bestand berücksichtigen
|
||||
- [ ] Teillieferungen für bestimmte Produkte
|
||||
- [ ] Produkte anzahl veränderbar / löschbar machen
|
||||
- [ ] Wannen Zetel PDF erstellen
|
||||
- [ ]
|
||||
@@ -0,0 +1,278 @@
|
||||
|
||||
use actix_web::web::Data;
|
||||
use chrono::{Datelike, DateTime, Timelike, Utc};
|
||||
use futures::executor::block_on;
|
||||
use sqlx::{Arguments, Pool, Row, Sqlite};
|
||||
use sqlx::sqlite::{SqliteArguments, SqliteRow};
|
||||
|
||||
use common::models::delivery::Delivery;
|
||||
use common::models::delivery_for::DeliveryFor;
|
||||
use common::models::delivery_item::DeliveryItem;
|
||||
use crate::impls::delivery_items_entry::DeliveryItemEntry;
|
||||
|
||||
use crate::traits::database::{Database, DatabaseSub};
|
||||
use crate::traits::query::Query;
|
||||
use crate::traits::standard::Standard;
|
||||
|
||||
impl Standard for Delivery {
|
||||
fn table_name() -> String {
|
||||
"delivery".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl Query<Delivery> for Delivery {
|
||||
fn from_sqlite_row(row: SqliteRow, pool: &Data<Pool<Sqlite>>) -> Delivery {
|
||||
let delivery_for: Vec<DeliveryFor> = DeliveryFor::get_by_parent_id(row.get(0), pool);
|
||||
let delivery_items: Vec<DeliveryItem> = DeliveryItem::get_by_parent_id(row.get(0), pool);
|
||||
|
||||
Delivery {
|
||||
id: row.get(0),
|
||||
description: row.get(3),
|
||||
creation_date: row.get(1),
|
||||
received_all_date: row.get(2),
|
||||
delivery_for,
|
||||
delivery_items
|
||||
}
|
||||
}
|
||||
|
||||
fn from_sqlite_row_small(row: SqliteRow, _pool: &Data<Pool<Sqlite>>) -> Delivery {
|
||||
Delivery {
|
||||
id: row.get(0),
|
||||
description: row.get(3),
|
||||
creation_date: row.get(1),
|
||||
received_all_date: row.get(2),
|
||||
delivery_for: vec![],
|
||||
delivery_items: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Database<Delivery> for Delivery {
|
||||
fn insert(&self, pool: &Data<Pool<Sqlite>>) -> i64 {
|
||||
let statement = format!(
|
||||
"INSERT INTO {} (creation_date, description) VALUES ($1, $2)",
|
||||
Delivery::table_name(),
|
||||
);
|
||||
|
||||
let mut date_time: DateTime<Utc> = Utc::now();
|
||||
date_time = date_time.with_day(21).unwrap();
|
||||
date_time = date_time.with_month(09).unwrap();
|
||||
//date_time = date_time.with_hour(10).unwrap();
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(date_time);
|
||||
args.add(&self.description);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
|
||||
temp.unwrap().last_insert_rowid()
|
||||
}
|
||||
|
||||
fn update(&self, pool: &Data<Pool<Sqlite>>) {
|
||||
let statement = format!(
|
||||
"UPDATE {} SET description = $2, received_all_date = $3 WHERE id = $1",
|
||||
Delivery::table_name(),
|
||||
);
|
||||
|
||||
let mut delivered = true;
|
||||
|
||||
for delivery_item in &self.delivery_items {
|
||||
if delivery_item.total_amount_needed > delivery_item.received_amount {
|
||||
delivered = false;
|
||||
}
|
||||
}
|
||||
|
||||
let mut date_time: DateTime<Utc> = Utc::now();
|
||||
date_time = date_time.with_day(21).unwrap();
|
||||
date_time = date_time.with_month(09).unwrap();
|
||||
//date_time = date_time.with_hour(10).unwrap();
|
||||
|
||||
let date_time: Option<DateTime<Utc>> = match delivered {
|
||||
true => {Some(date_time)}
|
||||
false => {None}
|
||||
};
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(&self.id);
|
||||
args.add(&self.description);
|
||||
args.add(date_time);
|
||||
|
||||
println!("Updating Delivery");
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
fn delete(&self, pool: &Data<Pool<Sqlite>>) {
|
||||
let received_amounts: f64 = self.delivery_items.iter().map(|x| x.received_amount).sum();
|
||||
|
||||
if received_amounts == 0.0 {
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
|
||||
// Delete delivery for
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
format!("DELETE FROM {} WHERE delivery_id = {}",
|
||||
DeliveryFor::table_name(),
|
||||
self.id
|
||||
).as_str()
|
||||
).execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
|
||||
// Delete delivery item entry
|
||||
for delivery_item in &self.delivery_items {
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
format!("DELETE FROM {} WHERE delivery_item_id = {}",
|
||||
DeliveryItemEntry::table_name(),
|
||||
delivery_item.id
|
||||
).as_str()
|
||||
).execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
// Delete delivery item
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
format!("DELETE FROM {} WHERE delivery_id = {}",
|
||||
DeliveryItem::table_name(),
|
||||
self.id
|
||||
).as_str()
|
||||
).execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
|
||||
// Delete delivery
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
format!("DELETE FROM {} WHERE id = {}",
|
||||
Delivery::table_name(),
|
||||
self.id
|
||||
).as_str()
|
||||
).execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
} else {
|
||||
println!("Can not delete delivery, already something delivered.");
|
||||
}
|
||||
}
|
||||
|
||||
fn get_all(pool: &Data<Pool<Sqlite>>) -> Vec<Delivery> {
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(format!("SELECT * FROM {}", Delivery::table_name()).as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut deliveries: Vec<Delivery> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
deliveries.push(
|
||||
Delivery::from_sqlite_row_small(record, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading all deliveries:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
deliveries
|
||||
}
|
||||
|
||||
fn get_by_id(id: i64, pool: &Data<Pool<Sqlite>>) -> Vec<Delivery> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE id = $1",
|
||||
Delivery::table_name(),
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(id);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut deliveries: Vec<Delivery> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
deliveries.push(
|
||||
Delivery::from_sqlite_row(record, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading deliveries with id: {}:", id);
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
deliveries
|
||||
}
|
||||
|
||||
fn get_by_search(search_term: String, pool: &Data<Pool<Sqlite>>) -> Vec<Delivery> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE creation_date like \"%{}%\"",
|
||||
Delivery::table_name(),
|
||||
search_term,
|
||||
);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(
|
||||
statement.as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut deliveries: Vec<Delivery> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
deliveries.push(
|
||||
Delivery::from_sqlite_row_small(record, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading deliveries with search term: {}:", search_term);
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
deliveries
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
use actix_web::web::Data;
|
||||
use chrono::{Datelike, DateTime, Utc};
|
||||
use futures::executor::block_on;
|
||||
use sqlx::{Arguments, Pool, Row, Sqlite};
|
||||
use sqlx::sqlite::{SqliteArguments, SqliteRow};
|
||||
|
||||
use common::models::entry::Entry;
|
||||
use common::models::production::Production;
|
||||
|
||||
use crate::traits::database::{Database, DatabaseSub};
|
||||
use crate::traits::query::QuerySub;
|
||||
use crate::traits::standard::{Standard, StandardSub};
|
||||
|
||||
impl Standard for Entry {
|
||||
fn table_name() -> String {
|
||||
"entry".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl StandardSub for Entry {
|
||||
fn parent_table() -> String {
|
||||
"variant".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl QuerySub<Entry> for Entry {
|
||||
fn from_sqlite_row(row: SqliteRow, _parent_id: i64, pool: &Data<Pool<Sqlite>>) -> Entry {
|
||||
let production: Option<Production> = match Production::get_by_id(row.get(7), pool).first() {
|
||||
Some(prod) => {
|
||||
Some(prod.clone())
|
||||
}
|
||||
None => {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
Entry {
|
||||
id: row.get(0),
|
||||
charge: row.get(1),
|
||||
amount_created: row.get(2),
|
||||
amount_left: row.get(3),
|
||||
date: row.get(4),
|
||||
variant_id: row.get(5),
|
||||
origin: row.get(6),
|
||||
production,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_sqlite_row_small(row: SqliteRow, _parent_id: i64, pool: &Data<Pool<Sqlite>>) -> Entry {
|
||||
Entry {
|
||||
id: row.get(0),
|
||||
charge: row.get(1),
|
||||
amount_created: row.get(2),
|
||||
amount_left: row.get(3),
|
||||
date: row.get(4),
|
||||
variant_id: row.get(5),
|
||||
origin: row.get(6),
|
||||
production: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseSub<Entry> for Entry {
|
||||
|
||||
}
|
||||
|
||||
impl Database<Entry> for Entry {
|
||||
fn insert(&self, pool: &Data<Pool<Sqlite>>) -> i64 {
|
||||
let production_id = match &self.production {
|
||||
Some(production) => {
|
||||
Some(production.insert(pool))
|
||||
}
|
||||
None => {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let statement = format!(
|
||||
"INSERT INTO {} (charge, amount_created, amount_left, date, variant, origin_id, production_id) VALUES ($1, $2, $2, $3, $4, $5, $6)",
|
||||
Entry::table_name(),
|
||||
);
|
||||
|
||||
let charge = self.charge.as_str();
|
||||
|
||||
let charge = if charge.eq("000_TO_GENERATE") {
|
||||
let new_charge = next_charge(pool);
|
||||
insert_charge(new_charge.clone(), pool);
|
||||
|
||||
new_charge
|
||||
} else {
|
||||
self.charge.clone()
|
||||
};
|
||||
|
||||
let mut date_time: DateTime<Utc> = Utc::now();
|
||||
date_time = date_time.with_day(21).unwrap();
|
||||
date_time = date_time.with_month(09).unwrap();
|
||||
//date_time = date_time.with_hour(10).unwrap();
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(charge);
|
||||
args.add(&self.amount_created);
|
||||
args.add(date_time);
|
||||
args.add(&self.variant_id);
|
||||
args.add(&self.origin);
|
||||
args.add(production_id);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Entry result:\n {:#?}", temp);
|
||||
temp.unwrap().last_insert_rowid()
|
||||
}
|
||||
|
||||
fn update(&self, pool: &Data<Pool<Sqlite>>) {
|
||||
let statement = format!(
|
||||
"UPDATE {} SET amount_left = $2 WHERE id = $1",
|
||||
Entry::table_name(),
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(&self.id);
|
||||
args.add(&self.amount_left);
|
||||
|
||||
println!("Updating");
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
fn delete(&self, pool: &Data<Pool<Sqlite>>) {
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
format!("DELETE FROM {} WHERE id = {}",
|
||||
Entry::table_name(),
|
||||
self.id
|
||||
).as_str()
|
||||
).execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
fn get_all(pool: &Data<Pool<Sqlite>>) -> Vec<Entry> {
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(format!("SELECT * FROM {}", Entry::table_name()).as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
|
||||
let mut entry: Vec<Entry> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
entry.push(
|
||||
// TODO: Parent_id
|
||||
Entry::from_sqlite_row_small(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading all entry entries:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
entry
|
||||
}
|
||||
|
||||
fn get_by_id(id: i64, pool: &Data<Pool<Sqlite>>) -> Vec<Entry> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE id = $1",
|
||||
Entry::table_name(),
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(id);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
|
||||
let mut entry: Vec<Entry> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
entry.push(
|
||||
// TODO: Parent_id
|
||||
Entry::from_sqlite_row(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading all entry entries:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
entry
|
||||
}
|
||||
|
||||
fn get_by_search(search_term: String, pool: &Data<Pool<Sqlite>>) -> Vec<Entry> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE variant = {}",
|
||||
Entry::table_name(),
|
||||
search_term,
|
||||
);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(
|
||||
statement.as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
|
||||
let mut entry: Vec<Entry> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
entry.push(
|
||||
// TODO: Parent_id
|
||||
Entry::from_sqlite_row(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading all entry entries:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
entry
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_entry_by_variant_and_date(variant_id: i64, date_start: String, date_end: String, pool: &Data<Pool<Sqlite>>) -> Vec<Entry> {
|
||||
let statement = format!(
|
||||
"SELECT entry.*
|
||||
FROM entry WHERE entry.variant = $1 AND entry.date > date($2) AND entry.date < date($3)",
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(variant_id);
|
||||
args.add(date_start);
|
||||
args.add(date_end);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut entries: Vec<Entry> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
entries.push(
|
||||
// TODO: Parent_id
|
||||
Entry::from_sqlite_row_small(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading entries by variant and dates:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
entries
|
||||
}
|
||||
|
||||
pub fn get_entry_with_used_via_production(production_id: i64, pool: &Data<Pool<Sqlite>>) -> Option<Entry> {
|
||||
let statement = format!(
|
||||
"SELECT entry.*
|
||||
FROM entry WHERE entry.production_id = $1",
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(production_id);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.fetch_one(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let entry: Option<Entry>;
|
||||
|
||||
match res {
|
||||
Ok(record) => {
|
||||
entry = Some(Entry::from_sqlite_row_small(record, -1, pool));
|
||||
}
|
||||
Err(err) => {
|
||||
entry = None;
|
||||
println!("Error while loading parent entry by used:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
entry
|
||||
}
|
||||
|
||||
const CHARGE_TABLE: &str = "used_charge";
|
||||
|
||||
fn insert_charge(charge: String, pool: &Data<Pool<Sqlite>>) {
|
||||
let statement = format!(
|
||||
"INSERT INTO {} (charge) VALUES ($1)",
|
||||
CHARGE_TABLE,
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(charge);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
println!("Charge result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
fn next_charge(pool: &Data<Pool<Sqlite>>) -> String {
|
||||
let statement = format!(
|
||||
"SELECT charge FROM {}",
|
||||
CHARGE_TABLE,
|
||||
);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query(
|
||||
statement.as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
match temp {
|
||||
Ok(charges) => {
|
||||
if charges.last().is_some() {
|
||||
increment_charge(charges.last().unwrap().get(0))
|
||||
} else {
|
||||
"A".to_string()
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
"A".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increment_charge(charge: String) -> String {
|
||||
let mut charge: Vec<char> = charge.chars().collect();
|
||||
|
||||
charge.reverse();
|
||||
let mut over = false;
|
||||
|
||||
for ch in charge.iter_mut() {
|
||||
if *ch == 'Z' {
|
||||
over = true;
|
||||
*ch = 'A';
|
||||
} else if over {
|
||||
*ch = std::char::from_u32(*ch as u32 + 1).unwrap_or(*ch);
|
||||
over = false;
|
||||
} else {
|
||||
*ch = std::char::from_u32(*ch as u32 + 1).unwrap_or(*ch);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
charge.reverse();
|
||||
|
||||
if over {
|
||||
charge.push('A');
|
||||
}
|
||||
|
||||
charge.iter().collect()
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
use actix_web::web::Data;
|
||||
use chrono::{Datelike, DateTime, Timelike, Utc};
|
||||
use futures::executor::block_on;
|
||||
use sqlx::{Arguments, Pool, Row, Sqlite};
|
||||
use sqlx::sqlite::{SqliteArguments, SqliteRow};
|
||||
|
||||
|
||||
use common::models::production::Production;
|
||||
use common::models::used::Used;
|
||||
|
||||
use crate::traits::database::{Database, DatabaseSub};
|
||||
use crate::traits::query::QuerySub;
|
||||
use crate::traits::standard::{Standard, StandardSub};
|
||||
|
||||
impl Standard for Production {
|
||||
fn table_name() -> String {
|
||||
"production".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl StandardSub for Production {
|
||||
fn parent_table() -> String {
|
||||
"produced_entry_id".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl QuerySub<Production> for Production {
|
||||
fn from_sqlite_row(row: SqliteRow, _parent_id: i64, pool: &Data<Pool<Sqlite>>) -> Production {
|
||||
let production_id: i64 = row.get(0);
|
||||
|
||||
let uses = Used::get_by_parent_id(production_id, pool);
|
||||
|
||||
Production {
|
||||
id: production_id,
|
||||
date_created: row.get(1),
|
||||
date_produced: row.get(2),
|
||||
mhd: row.get(3),
|
||||
uses
|
||||
}
|
||||
}
|
||||
|
||||
fn from_sqlite_row_small(row: SqliteRow, _parent_id: i64, _pool: &Data<Pool<Sqlite>>) -> Production {
|
||||
Production {
|
||||
id: row.get(0),
|
||||
date_created: row.get(1),
|
||||
date_produced: row.get(2),
|
||||
mhd: row.get(3),
|
||||
uses: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseSub<Production> for Production {
|
||||
|
||||
}
|
||||
|
||||
impl Database<Production> for Production {
|
||||
fn insert(&self, pool: &Data<Pool<Sqlite>>) -> i64 {
|
||||
// TODO: First check if there is enough from ingredient to produce
|
||||
|
||||
let statement = format!(
|
||||
"INSERT INTO {} (date_created) VALUES ($1)",
|
||||
Production::table_name(),
|
||||
);
|
||||
|
||||
let mut date_time: DateTime<Utc> = Utc::now();
|
||||
date_time = date_time.with_day(21).unwrap();
|
||||
date_time = date_time.with_month(09).unwrap();
|
||||
//date_time = date_time.with_hour(10).unwrap();
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(date_time);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Produced result:\n {:#?}", temp);
|
||||
|
||||
// TODO: Check if problematic with more users when more productions are created in a very very short timespan.
|
||||
let production_id = temp.unwrap().last_insert_rowid();
|
||||
|
||||
for entry in &self.uses {
|
||||
let mut entry = entry.clone();
|
||||
|
||||
entry.production_id = Some(production_id);
|
||||
entry.order_pos_id = None;
|
||||
|
||||
entry.insert(pool);
|
||||
}
|
||||
|
||||
production_id
|
||||
}
|
||||
|
||||
fn update(&self, pool: &Data<Pool<Sqlite>>) {
|
||||
let production = Production::get_by_id(self.id, pool).first().unwrap().clone();
|
||||
|
||||
let mut date_produced: Option<DateTime<chrono::Utc>> = self.date_produced;
|
||||
let mut mhd: Option<DateTime<chrono::Utc>> = self.mhd;
|
||||
|
||||
if production.date_produced.is_some() {
|
||||
date_produced = production.date_produced;
|
||||
}
|
||||
|
||||
if production.mhd.is_some() {
|
||||
mhd = production.mhd;
|
||||
}
|
||||
|
||||
let statement = format!(
|
||||
"UPDATE {} SET date_produced = $2, mhd = $3 WHERE id = $1",
|
||||
Production::table_name(),
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(&self.id);
|
||||
args.add(date_produced);
|
||||
args.add(mhd);
|
||||
|
||||
println!("Production");
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let temp = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.execute(&mut *conn)
|
||||
);
|
||||
|
||||
println!("Result:\n {:#?}", temp);
|
||||
}
|
||||
|
||||
fn delete(&self, _pool: &Data<Pool<Sqlite>>) {
|
||||
println!("Not allowed to delete!")
|
||||
}
|
||||
|
||||
fn get_all(pool: &Data<Pool<Sqlite>>) -> Vec<Production> {
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(format!("SELECT * FROM {}", Production::table_name()).as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut productions: Vec<Production> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
productions.push(
|
||||
// TODO: Load parent_id
|
||||
//Production::from_sqlite_row(record, -1, pool) Production::from_sqlite_row_small(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading all production entries:");
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
productions
|
||||
}
|
||||
|
||||
fn get_by_id(id: i64, pool: &Data<Pool<Sqlite>>) -> Vec<Production> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE id = $1",
|
||||
Production::table_name(),
|
||||
);
|
||||
|
||||
let mut args = SqliteArguments::default();
|
||||
args.add(id);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query_with(
|
||||
statement.as_str(),
|
||||
args)
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut productions: Vec<Production> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
productions.push(
|
||||
// TODO: Load parent_id
|
||||
Production::from_sqlite_row(record, -1, pool)
|
||||
//Production::from_sqlite_row_small(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading production with id: {}:", id);
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
productions
|
||||
}
|
||||
|
||||
fn get_by_search(search_term: String, pool: &Data<Pool<Sqlite>>) -> Vec<Production> {
|
||||
let statement = format!(
|
||||
"SELECT * FROM {} WHERE description like \"%{}%\"",
|
||||
Production::table_name(),
|
||||
search_term,
|
||||
);
|
||||
|
||||
let mut conn = block_on(pool.acquire()).unwrap();
|
||||
let res = block_on(
|
||||
sqlx::query(
|
||||
statement.as_str())
|
||||
.fetch_all(&mut *conn)
|
||||
);
|
||||
conn.detach();
|
||||
|
||||
let mut productions: Vec<Production> = Vec::new();
|
||||
|
||||
match res {
|
||||
Ok(records) => {
|
||||
for record in records {
|
||||
productions.push(
|
||||
// TODO: Load parent_id
|
||||
//Production::from_sqlite_row(record, -1, pool) Production::from_sqlite_row_small(record, -1, pool)
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error while loading variants with search term: {}:", search_term);
|
||||
println!("{:#?}", err);
|
||||
}
|
||||
}
|
||||
|
||||
productions
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
ppm Werte:
|
||||
- Standard: 300 - 450ppm
|
||||
|
||||
ppm Ampel:
|
||||
- Grün: ppm<=550
|
||||
- Gelb: ppm >= 551 && ppm <= 799
|
||||
- Rot: ppm >= 800
|
||||
|
||||
|
||||
|
||||
http://www.learningaboutelectronics.com/Articles/MQ-7-carbon-monoxide-sensor-circuit-with-arduino.php
|
||||
@@ -0,0 +1,9 @@
|
||||
- [x] Add dashboard ✅ 2023-10-18
|
||||
- [x] Save selected rooms to browser ✅ 2023-10-18
|
||||
- [x] Get current temp ✅ 2023-10-18
|
||||
- [ ] Get avg temp over set time eg. 1 hour
|
||||
- [ ] Let user pick time window to display data.
|
||||
- [ ] Don't prerender room
|
||||
- /rooms/...
|
||||
- [ ]
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
````.ino
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#include <ESP8266HTTPClient.h>
|
||||
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
#include <WiFiClient.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
|
||||
|
||||
const int rows = 3;
|
||||
|
||||
const char* wlans[rows][2] = { { "Privat W-LAN", "99842DA5D0" }, { "Rose", "Lodner2023" }, { "Privat W-LAN", "99842DA5D0" } };
|
||||
|
||||
const char* serverAddress = "https://api.temperature-station.lodner.dev/measurement";
|
||||
|
||||
|
||||
|
||||
WiFiClientSecure client;
|
||||
|
||||
HTTPClient https;
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(9600);
|
||||
|
||||
|
||||
|
||||
Serial.println("Start connecting to wlan.");
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
|
||||
WiFi.begin(wlans[i][0], wlans[i][1]);
|
||||
|
||||
Serial.print("Connecting to: ");
|
||||
|
||||
Serial.println(wlans[i][0]);
|
||||
|
||||
|
||||
|
||||
int trys = 0;
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED && trys < 30) {
|
||||
|
||||
Serial.print("Err connecting to: ");
|
||||
|
||||
Serial.print(wlans[i][0]);
|
||||
|
||||
Serial.print(" Versuch: ");
|
||||
|
||||
Serial.println(trys + 1);
|
||||
|
||||
trys++;
|
||||
|
||||
delay(1000);
|
||||
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
|
||||
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
|
||||
Serial.print("Connected to WiFi network with IP Address: ");
|
||||
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
|
||||
Serial.print("Connected to WiFi network with IP Address: ");
|
||||
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
} else {
|
||||
|
||||
// TODO: LED = 1 when not connected?
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void loop() {
|
||||
|
||||
// put your main code here, to run repeatedly:
|
||||
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
./sqldiff.exe db1.db db2.db
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
- Trainer sollen ihre Trainingszeiten (Tag und Uhrzeit (von bis)) eintragen können
|
||||
- Verwalter soll eine Übersicht haben welche Zeiten ein Trainer in gewünschten Zeitraum gearbeitet hat.
|
||||
- Eine Art Stundenplan wann welche Trainings sind? Wenn Trainer nach 1 Stunde nach Trainingsende keine Zeiten eingetragen hat benachrichtigen?
|
||||
- Verwalter am Ende vom Monat informieren das er die Lohnabrechnungen machen soll.
|
||||
## Benötigt:
|
||||
- [ ] Benutzer und Rechte System
|
||||
- [ ] E-Mail für Benachrichtigungen
|
||||
- [ ]
|
||||
|
||||
|
||||
## Anforderungen von Sebastian:
|
||||
>Wichtig für den Anfang ist es, dass die Übungsleiter sich mit einem eigenen Account einloggen können und Trainingseinheiten erfassen können. Dabei sollen sie eingeben können:
|
||||
>
|
||||
>- Datum - Beginn (Uhrzeit), Ende (Uhrzeit), Trainingsart (Dropdown) Jeder neue Eintrag bei den Trainingseinheiten sollte automatisch den Status „offen“ erhalten.
|
||||
>
|
||||
>Als Admin sollte ich dann für den Anfang mal alle eingegebenen Einheiten sehen, diese nach Kriterien filtern können (Übungsleiter, Trainingsart, Abrechnungsstatus (offen, genehmigt, abgerechnet), Datumsbereich) und im Anschluss daran als csv exportieren können.
|
||||
>
|
||||
>Das wäre für den Anfang schon mal mega.
|
||||
>Danke und Grüße
|
||||
|
||||
\- Sebi
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
|
||||
excalidraw-plugin: parsed
|
||||
tags: [excalidraw]
|
||||
|
||||
---
|
||||
==⚠ Switch to EXCALIDRAW VIEW in the MORE OPTIONS menu of this document. ⚠==
|
||||
|
||||
|
||||
# Text Elements
|
||||
|
||||
# Embedded files
|
||||
1f0cf67c0973016d54192859aa1266807796ddce: [[Pasted Image 20230817235524_186.png]]
|
||||
|
||||
%%
|
||||
# Drawing
|
||||
```json
|
||||
{
|
||||
"type": "excalidraw",
|
||||
"version": 2,
|
||||
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/1.9.14",
|
||||
"elements": [
|
||||
{
|
||||
"type": "image",
|
||||
"version": 81,
|
||||
"versionNonce": 1691747051,
|
||||
"isDeleted": false,
|
||||
"id": "ntYf1pYJeJzf9wdHztFPz",
|
||||
"fillStyle": "hachure",
|
||||
"strokeWidth": 1,
|
||||
"strokeStyle": "solid",
|
||||
"roughness": 1,
|
||||
"opacity": 100,
|
||||
"angle": 0,
|
||||
"x": -423.4633027522936,
|
||||
"y": -240.10546875,
|
||||
"strokeColor": "transparent",
|
||||
"backgroundColor": "transparent",
|
||||
"width": 871.9266055045872,
|
||||
"height": 396,
|
||||
"seed": 1445298917,
|
||||
"groupIds": [],
|
||||
"frameId": null,
|
||||
"roundness": null,
|
||||
"boundElements": [],
|
||||
"updated": 1692309315315,
|
||||
"link": null,
|
||||
"locked": false,
|
||||
"status": "pending",
|
||||
"fileId": "1f0cf67c0973016d54192859aa1266807796ddce",
|
||||
"scale": [
|
||||
1,
|
||||
1
|
||||
]
|
||||
}
|
||||
],
|
||||
"appState": {
|
||||
"theme": "light",
|
||||
"viewBackgroundColor": "#ffffff",
|
||||
"currentItemStrokeColor": "#1e1e1e",
|
||||
"currentItemBackgroundColor": "transparent",
|
||||
"currentItemFillStyle": "hachure",
|
||||
"currentItemStrokeWidth": 1,
|
||||
"currentItemStrokeStyle": "solid",
|
||||
"currentItemRoughness": 1,
|
||||
"currentItemOpacity": 100,
|
||||
"currentItemFontFamily": 1,
|
||||
"currentItemFontSize": 20,
|
||||
"currentItemTextAlign": "left",
|
||||
"currentItemStartArrowhead": null,
|
||||
"currentItemEndArrowhead": "arrow",
|
||||
"scrollX": 452.0454545454545,
|
||||
"scrollY": 402.9186789772727,
|
||||
"zoom": {
|
||||
"value": 1.1
|
||||
},
|
||||
"currentItemRoundness": "round",
|
||||
"gridSize": null,
|
||||
"currentStrokeOptions": null,
|
||||
"previousGridSize": null,
|
||||
"frameRendering": {
|
||||
"enabled": true,
|
||||
"clip": true,
|
||||
"name": true,
|
||||
"outline": true
|
||||
}
|
||||
},
|
||||
"files": {}
|
||||
}
|
||||
```
|
||||
%%
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 170 KiB |
Reference in New Issue
Block a user