Коммит номер какой-то. Сделано что-то

master
Алексей Алексей 2026-06-07 15:07:07 +10:00
parent f6bb3306ee
commit 0b457af6f7
6 changed files with 173 additions and 84 deletions

View File

@ -1,4 +1,4 @@
use std::{collections::HashMap, ops::Deref, str::FromStr, sync::Arc}; use std::{collections::HashMap, default::Default, ops::Deref, str::FromStr, sync::Arc};
use crate::{ use crate::{
database::DBOperator, database::DBOperator,
@ -8,7 +8,7 @@ use crate::{
ModalWinState, Position, Worker, ModalWinState, Position, Worker,
}, },
tab::*, tab::*,
worker_tab::*, worker_tab::{self, *},
}; };
use egui::{TextBuffer, Vec2, mutex::RwLock}; use egui::{TextBuffer, Vec2, mutex::RwLock};
use egui_dock::{DockArea, Style, TabViewer}; use egui_dock::{DockArea, Style, TabViewer};
@ -22,11 +22,12 @@ pub struct App<'a> {
pub main_viewer: MainTabViewer, pub main_viewer: MainTabViewer,
pub db_oper: DBOperator, pub db_oper: DBOperator,
pub rt: tokio::runtime::Runtime, pub rt: tokio::runtime::Runtime,
pub is_admin: bool,
} }
impl Default for App<'_> { impl Default for App<'_> {
fn default() -> Self { fn default() -> Self {
let tree = egui_dock::DockState::new(vec![ let mut tree = egui_dock::DockState::new(vec![
Tab { Tab {
tab_type: TabTypes::Equipment, tab_type: TabTypes::Equipment,
title: "Оборудование".to_owned(), title: "Оборудование".to_owned(),
@ -69,6 +70,7 @@ impl Default for App<'_> {
}, },
db_oper: rt.block_on(DBOperator::new()), db_oper: rt.block_on(DBOperator::new()),
rt, rt,
is_admin: false,
} }
} }
} }
@ -104,28 +106,31 @@ impl eframe::App for App<'_> {
|| ui.input(|i| i.key_pressed(egui::Key::Enter)) || ui.input(|i| i.key_pressed(egui::Key::Enter))
{ {
let uname = self.login_modal_state.data.get("login").unwrap().clone(); let uname = self.login_modal_state.data.get("login").unwrap().clone();
self.login_modal_state.fail = false;
let mut hashed_pass = Sha256::new();
hashed_pass.update(self.login_modal_state.data.get("password").unwrap());
let pass_hash = hex::encode(hashed_pass.finalize());
if self.rt.block_on(async { if self.rt.block_on(async {
self.db_oper.check_username(uname.clone()).await.unwrap() self.db_oper
.check_password(uname.clone(), pass_hash)
.await
.unwrap()
}) { }) {
self.login_modal_state.fail = false; self.login_modal_state.fail = false;
let mut hashed_pass = Sha256::new(); self.login_modal_state.status = crate::models::LoginStatus::Finished;
hashed_pass self.login_modal_state.is_open = false;
.update(self.login_modal_state.data.get("password").unwrap());
let pass_hash = hex::encode(hashed_pass.finalize());
if self.rt.block_on(async { if self.rt.block_on(async {
self.db_oper.check_password(uname, pass_hash).await.unwrap() self.db_oper.check_admin(uname.clone()).await.unwrap()
}) { }) {
self.login_modal_state.fail = false; self.main_viewer.is_admin = true
self.login_modal_state.status =
crate::models::LoginStatus::Finished;
self.login_modal_state.is_open = false;
} else { } else {
self.login_modal_state.fail = true; self.main_viewer.is_admin = false;
self.login_modal_state.fail_message = "Неверный пароль".to_string();
} }
} else { } else {
self.login_modal_state.fail = true; self.login_modal_state.fail = true;
self.login_modal_state.fail_message = "Неверный логин".to_string(); self.login_modal_state.fail_message =
"Неверные логин или пароль".to_string();
} }
} }
}); });
@ -158,6 +163,7 @@ struct MainTabViewer {
equipment_modal_state: ModalWinState, equipment_modal_state: ModalWinState,
is_dark_theme: bool, is_dark_theme: bool,
interface_scale_ratio: f32, interface_scale_ratio: f32,
is_admin: bool,
} }
impl Default for MainTabViewer { impl Default for MainTabViewer {
fn default() -> Self { fn default() -> Self {
@ -211,29 +217,40 @@ impl Default for MainTabViewer {
]), ]),
status: ModalStatus::Add, status: ModalStatus::Add,
}, },
is_admin: false,
} }
} }
} }
impl MainTabViewer { impl MainTabViewer {
fn new(is_admin: bool) -> Self {
Self {
is_admin,
worker_tabs: WorkerTabViewer::new(is_admin),
material_tabs: MaterialTabViewer::new(is_admin),
..Default::default()
}
}
fn show_equipment(&mut self, ui: &mut egui::Ui) { fn show_equipment(&mut self, ui: &mut egui::Ui) {
ui.horizontal(|ui| { if self.is_admin {
if ui.button("Добавить").clicked() { ui.horizontal(|ui| {
self.equipment_modal_state.is_open = true; if ui.button("Добавить").clicked() {
self.equipment_modal_state.status = ModalStatus::Add; self.equipment_modal_state.is_open = true;
self.equipment_modal_state self.equipment_modal_state.status = ModalStatus::Add;
.data self.equipment_modal_state
.insert("id".into(), "0".into()); .data
self.equipment_modal_state .insert("id".into(), "0".into());
.data self.equipment_modal_state
.insert("name".into(), "".into()); .data
self.equipment_modal_state .insert("name".into(), "".into());
.data self.equipment_modal_state
.insert("inv_numver".into(), "".into()); .data
self.equipment_modal_state .insert("inv_numver".into(), "".into());
.data self.equipment_modal_state
.insert("worker_id".into(), "0".into()); .data
} .insert("worker_id".into(), "0".into());
}); }
});
}
let mut table = TableBuilder::new(ui) let mut table = TableBuilder::new(ui)
.striped(true) .striped(true)
.resizable(false) .resizable(false)
@ -275,21 +292,23 @@ impl MainTabViewer {
ui.label(eq.maintenance_date.date_naive().to_string()); ui.label(eq.maintenance_date.date_naive().to_string());
}); });
row.col(|ui| { row.col(|ui| {
if ui.button("Удалить").clicked() { if self.is_admin {
self.equipment_modal_state.is_open = true; if ui.button("Удалить").clicked() {
self.equipment_modal_state.status = ModalStatus::Remove; self.equipment_modal_state.is_open = true;
self.equipment_modal_state self.equipment_modal_state.status = ModalStatus::Remove;
.data self.equipment_modal_state
.insert("id".into(), eq.id.to_string()); .data
self.equipment_modal_state .insert("id".into(), eq.id.to_string());
.data self.equipment_modal_state
.insert("name".into(), eq.name.clone()); .data
self.equipment_modal_state .insert("name".into(), eq.name.clone());
.data self.equipment_modal_state
.insert("inv_numver".into(), eq.inv_number.clone()); .data
self.equipment_modal_state .insert("inv_numver".into(), eq.inv_number.clone());
.data self.equipment_modal_state
.insert("worker_id".into(), eq.worker.id.to_string()); .data
.insert("worker_id".into(), eq.worker.id.to_string());
}
} }
}); });
if row.response().double_clicked() { if row.response().double_clicked() {

View File

@ -1,3 +1,4 @@
use sqlx::Row;
use sqlx::mysql::MySqlPool; use sqlx::mysql::MySqlPool;
use sqlx::mysql::MySqlPoolOptions; use sqlx::mysql::MySqlPoolOptions;
@ -283,22 +284,6 @@ impl DBOperator {
Err(_) => Ok(false), Err(_) => Ok(false),
} }
} }
pub async fn check_username(&self, username: String) -> Result<bool, sqlx::Error> {
let ans = sqlx::query("SELECT * FROM Brewery.profile WHERE login=?")
.bind(username)
.fetch_all(&self.pool)
.await;
match ans {
Ok(n) => {
if n.len() > 0 {
return Ok(true);
} else {
return Ok(false);
}
}
Err(_) => Ok(false),
}
}
pub async fn check_password( pub async fn check_password(
&self, &self,
username: String, username: String,
@ -320,6 +305,30 @@ impl DBOperator {
Err(_) => Ok(false), Err(_) => Ok(false),
} }
} }
pub async fn check_admin(&self, username: String) -> Result<bool, sqlx::Error> {
let ans: bool = sqlx::query_scalar(
r#"SELECT
position.is_admin,
profile.worker_id,
worker.id,
profile.login,
position.id
FROM
Brewery.profile
JOIN
Brewery.worker
JOIN
Brewery.position
ON profile.worker_id = worker.id
AND profile.login=?
AND worker.position_id =position.id"#,
)
.bind(username)
.fetch_one(&self.pool)
.await
.unwrap();
Ok(ans)
}
} }
pub async fn estabilish_connection() -> Result<(), sqlx::Error> { pub async fn estabilish_connection() -> Result<(), sqlx::Error> {

View File

@ -1,9 +1,13 @@
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, default::Default, sync::Arc};
use egui::mutex::RwLock; use egui::mutex::RwLock;
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
use crate::{database::DBOperator, models::{Material, MaterialCategory, MaterialRow, ModalStatus, ModalWinState}, tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes}}; use crate::{
database::DBOperator,
models::{Material, MaterialCategory, MaterialRow, ModalStatus, ModalWinState},
tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes},
};
pub struct MaterialTabViewer { pub struct MaterialTabViewer {
db_oper: DBOperator, db_oper: DBOperator,
@ -14,8 +18,15 @@ pub struct MaterialTabViewer {
mat_cats: Arc<RwLock<Vec<MaterialCategory>>>, mat_cats: Arc<RwLock<Vec<MaterialCategory>>>,
mats: Arc<RwLock<Vec<Material>>>, mats: Arc<RwLock<Vec<Material>>>,
is_admin: bool,
} }
impl MaterialTabViewer { impl MaterialTabViewer {
pub fn new(is_admin: bool) -> Self {
Self {
is_admin,
..Default::default()
}
}
fn update_material_category(&mut self) { fn update_material_category(&mut self) {
self.mat_cats = Arc::new(RwLock::new( self.mat_cats = Arc::new(RwLock::new(
self.rt self.rt
@ -576,6 +587,7 @@ impl Default for MaterialTabViewer {
}, },
mat_cats, mat_cats,
mats, mats,
is_admin: false,
} }
} }
} }

View File

@ -112,6 +112,12 @@ pub struct Product<'a> {
price_per_unit: rust_decimal::Decimal, price_per_unit: rust_decimal::Decimal,
} }
#[derive(Default)] #[derive(Default)]
pub struct User{
login: String,
is_admin: bool,
worker: Worker,
}
#[derive(Default)]
pub struct ModalWinState { pub struct ModalWinState {
pub is_open: bool, pub is_open: bool,
pub can_finish: bool, pub can_finish: bool,

View File

@ -1,8 +1,17 @@
use crate::tab::{Tab, TabTypes}; use crate::tab::{Tab, TabTypes};
use std::default::Default;
struct RecipeTabViewer {} struct RecipeTabViewer {
is_admin: bool,
}
impl RecipeTabViewer { impl RecipeTabViewer {
fn new(is_admin: bool) -> Self {
Self {
is_admin,
..Default::default()
}
}
fn show_recipe_list(&mut self, ui: &mut egui::Ui) {} fn show_recipe_list(&mut self, ui: &mut egui::Ui) {}
fn show_recipe_detail(&mut self, ui: &mut egui::Ui) {} fn show_recipe_detail(&mut self, ui: &mut egui::Ui) {}
} }
@ -27,3 +36,9 @@ impl egui_dock::TabViewer for RecipeTabViewer {
} }
} }
} }
impl Default for RecipeTabViewer {
fn default() -> Self {
Self { is_admin: false }
}
}

View File

@ -1,16 +1,17 @@
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::{Arc};
use bigdecimal::BigDecimal; use bigdecimal::BigDecimal;
use egui::mutex::RwLock; use egui::mutex::RwLock;
use egui_extras::{Column, TableBuilder}; use egui_extras::{Column, TableBuilder};
use std::collections::HashMap;
use std::default::Default;
use std::str::FromStr;
use std::sync::Arc;
use crate::models::{ModalStatus, ModalWinState, Position, Worker};
use crate::database::*; use crate::database::*;
use crate::models::{ModalStatus, ModalWinState, Position, Worker};
use crate::tab::*; use crate::tab::*;
pub struct WorkerTabViewer { pub struct WorkerTabViewer {
db_oper: DBOperator, db_oper: DBOperator,
workers: Arc<RwLock<Option<Vec<Worker>>>>, workers: Arc<RwLock<Vec<Worker>>>,
positions: Arc<RwLock<Vec<Position>>>, positions: Arc<RwLock<Vec<Position>>>,
show_worker_add_modal: bool, show_worker_add_modal: bool,
show_worker_edit_modal: bool, show_worker_edit_modal: bool,
@ -33,15 +34,23 @@ pub struct WorkerTabViewer {
rt: tokio::runtime::Runtime, rt: tokio::runtime::Runtime,
show_position_delete_modal: bool, show_position_delete_modal: bool,
delete_position: Position, delete_position: Position,
process_worker_state: ModalWinState,
process_position_state: ModalWinState, process_position_state: ModalWinState,
is_admin: bool,
} }
impl WorkerTabViewer { impl WorkerTabViewer {
pub fn new(is_admin: bool) -> Self {
Self {
is_admin,
..Default::default()
}
}
fn update_workers(&mut self) { fn update_workers(&mut self) {
self.workers = Arc::new(RwLock::new(Option::Some( self.workers = Arc::new(RwLock::new(
self.rt self.rt
.block_on(async { self.db_oper.get_workers().await.unwrap() }), .block_on(async { self.db_oper.get_workers().await.unwrap() }),
))); ));
} }
fn update_positions(&mut self) { fn update_positions(&mut self) {
self.positions = Arc::new(RwLock::new( self.positions = Arc::new(RwLock::new(
@ -98,7 +107,7 @@ impl WorkerTabViewer {
.selected_text(format!("{}", self.add_worker_position.name)) .selected_text(format!("{}", self.add_worker_position.name))
.show_ui(ui, |ui| { .show_ui(ui, |ui| {
self.rt.block_on(async { self.rt.block_on(async {
for pos in self.db_oper.get_position().await.unwrap().iter() { for pos in self.positions.read().clone().iter() {
ui.selectable_value( ui.selectable_value(
&mut self.add_worker_position, &mut self.add_worker_position,
pos.clone(), pos.clone(),
@ -278,7 +287,7 @@ impl WorkerTabViewer {
.body(|mut body| { .body(|mut body| {
body.ui_mut().style_mut().interaction.selectable_labels = false; body.ui_mut().style_mut().interaction.selectable_labels = false;
for wk in self.workers.read().clone().unwrap().iter() { for wk in self.workers.read().clone().iter() {
body.row(25.0, |mut row| { body.row(25.0, |mut row| {
row.col(|ui| { row.col(|ui| {
ui.label(&wk.full_name); ui.label(&wk.full_name);
@ -420,7 +429,6 @@ impl WorkerTabViewer {
.workers .workers
.read() .read()
.clone() .clone()
.unwrap()
.iter() .iter()
.find(|wrkr| wrkr.position.id == self.delete_position.id) .find(|wrkr| wrkr.position.id == self.delete_position.id)
.iter() .iter()
@ -493,9 +501,7 @@ impl egui_dock::TabViewer for WorkerTabViewer {
} }
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) { fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
match &tab.tab_type { match &tab.tab_type {
TabTypes::WorkerList => { TabTypes::WorkerList => self.show_worker(ui),
self.show_worker(ui)
},
TabTypes::WorkerPosition => self.show_position(ui), TabTypes::WorkerPosition => self.show_position(ui),
_ => { _ => {
ui.label("Nope"); ui.label("Nope");
@ -519,6 +525,9 @@ impl Default for WorkerTabViewer {
let positions = Arc::new(RwLock::new( let positions = Arc::new(RwLock::new(
rt.block_on(async { db_oper.get_position().await.unwrap() }), rt.block_on(async { db_oper.get_position().await.unwrap() }),
)); ));
let workers = Arc::new(RwLock::new(
rt.block_on(async { db_oper.get_workers().await.unwrap() }),
));
let mut pos_map: HashMap<String, String> = HashMap::new(); let mut pos_map: HashMap<String, String> = HashMap::new();
pos_map.extend(|| -> Vec<(String, String)> { pos_map.extend(|| -> Vec<(String, String)> {
let pos = positions.read()[0].clone(); let pos = positions.read()[0].clone();
@ -528,6 +537,20 @@ impl Default for WorkerTabViewer {
("wage".to_string(), pos.wage.to_string()), ("wage".to_string(), pos.wage.to_string()),
] ]
}()); }());
let mut worker_map: HashMap<String, String> = HashMap::new();
worker_map.extend(|| -> Vec<(String, String)> {
let worker = workers.read()[0].clone();
vec![
("id".to_string(), worker.id.to_string()),
("full_name".to_string(), worker.full_name),
("position_id".to_string(), worker.position.id.to_string()),
(
"hire_date".to_string(),
worker.hire_date.date_naive().format("%d-%m-%Y").to_string(),
),
("is_fired".to_string(), worker.is_fired.to_string()),
]
}());
Self { Self {
process_position_state: ModalWinState { process_position_state: ModalWinState {
is_open: false, is_open: false,
@ -535,9 +558,13 @@ impl Default for WorkerTabViewer {
data: pos_map, data: pos_map,
status: ModalStatus::Add, status: ModalStatus::Add,
}, },
workers: Arc::new(RwLock::new(Option::Some( process_worker_state: ModalWinState {
rt.block_on(async { db_oper.get_workers().await.unwrap() }), is_open: false,
))), can_finish: false,
data: worker_map,
status: ModalStatus::Add,
},
workers,
positions: positions, positions: positions,
show_worker_add_modal: false, show_worker_add_modal: false,
show_worker_edit_modal: false, show_worker_edit_modal: false,
@ -561,6 +588,7 @@ impl Default for WorkerTabViewer {
db_oper, db_oper,
rt, rt,
is_admin: false,
} }
} }
} }