working ratatui frontend
This commit is contained in:
4
src/adresar/handlers.rs
Normal file
4
src/adresar/handlers.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
// src/adresar/handlers.rs
|
||||
|
||||
pub mod create_adresar;
|
||||
pub use create_adresar::create_adresar;
|
||||
57
src/adresar/handlers/create_adresar.rs
Normal file
57
src/adresar/handlers/create_adresar.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
// src/adresar/handlers/create_adresar.rs
|
||||
use tonic::{Request, Response, Status};
|
||||
use sqlx::PgPool;
|
||||
use crate::adresar::models::Adresar;
|
||||
use crate::proto::multieko2::{AdresarRequest, AdresarResponse};
|
||||
|
||||
pub async fn create_adresar(
|
||||
db_pool: &PgPool,
|
||||
request: AdresarRequest,
|
||||
) -> Result<AdresarResponse, Status> {
|
||||
let adresar = sqlx::query_as!(
|
||||
Adresar,
|
||||
r#"
|
||||
INSERT INTO adresar (
|
||||
firma, kz, drc, ulica, psc, mesto, stat, banka, ucet, skladm, ico, kontakt, telefon, skladu, fax
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
||||
RETURNING id, firma, kz, drc, ulica, psc, mesto, stat, banka, ucet, skladm, ico, kontakt, telefon, skladu, fax
|
||||
"#,
|
||||
request.firma,
|
||||
request.kz,
|
||||
request.drc,
|
||||
request.ulica,
|
||||
request.psc,
|
||||
request.mesto,
|
||||
request.stat,
|
||||
request.banka,
|
||||
request.ucet,
|
||||
request.skladm,
|
||||
request.ico,
|
||||
request.kontakt,
|
||||
request.telefon,
|
||||
request.skladu,
|
||||
request.fax
|
||||
)
|
||||
.fetch_one(db_pool)
|
||||
.await
|
||||
.map_err(|e| Status::internal(e.to_string()))?;
|
||||
|
||||
Ok(AdresarResponse {
|
||||
id: adresar.id,
|
||||
firma: adresar.firma,
|
||||
kz: adresar.kz.unwrap_or_default(),
|
||||
drc: adresar.drc.unwrap_or_default(),
|
||||
ulica: adresar.ulica.unwrap_or_default(),
|
||||
psc: adresar.psc.unwrap_or_default(),
|
||||
mesto: adresar.mesto.unwrap_or_default(),
|
||||
stat: adresar.stat.unwrap_or_default(),
|
||||
banka: adresar.banka.unwrap_or_default(),
|
||||
ucet: adresar.ucet.unwrap_or_default(),
|
||||
skladm: adresar.skladm.unwrap_or_default(),
|
||||
ico: adresar.ico.unwrap_or_default(),
|
||||
kontakt: adresar.kontakt.unwrap_or_default(),
|
||||
telefon: adresar.telefon.unwrap_or_default(),
|
||||
skladu: adresar.skladu.unwrap_or_default(),
|
||||
fax: adresar.fax.unwrap_or_default(),
|
||||
})
|
||||
}
|
||||
4
src/adresar/mod.rs
Normal file
4
src/adresar/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
// src/adresar/mod.rs
|
||||
|
||||
pub mod models;
|
||||
pub mod handlers;
|
||||
22
src/adresar/models.rs
Normal file
22
src/adresar/models.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
// src/adresar/models.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Adresar {
|
||||
pub id: i64,
|
||||
pub firma: String,
|
||||
pub kz: Option<String>,
|
||||
pub drc: Option<String>,
|
||||
pub ulica: Option<String>,
|
||||
pub psc: Option<String>,
|
||||
pub mesto: Option<String>,
|
||||
pub stat: Option<String>,
|
||||
pub banka: Option<String>,
|
||||
pub ucet: Option<String>,
|
||||
pub skladm: Option<String>,
|
||||
pub ico: Option<String>,
|
||||
pub kontakt: Option<String>,
|
||||
pub telefon: Option<String>,
|
||||
pub skladu: Option<String>,
|
||||
pub fax: Option<String>,
|
||||
}
|
||||
@@ -1,18 +1,177 @@
|
||||
// src/client/mod.rs
|
||||
use tonic::transport::Channel;
|
||||
use crate::proto::multieko2::data_processor_client::DataProcessorClient;
|
||||
use crate::proto::multieko2::DataRequest;
|
||||
use ratatui::{
|
||||
backend::CrosstermBackend,
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
layout::{Layout, Constraint, Direction},
|
||||
Terminal,
|
||||
style::{Style, Color},
|
||||
Frame,
|
||||
};
|
||||
use crossterm::{
|
||||
event::{self, Event, KeyCode},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use std::io;
|
||||
use crate::proto::multieko2::{
|
||||
AdresarRequest,
|
||||
adresar_client::AdresarClient,
|
||||
};
|
||||
|
||||
pub async fn run_client() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut client = DataProcessorClient::connect("http://[::1]:50051").await?;
|
||||
// Setup terminal
|
||||
enable_raw_mode()?;
|
||||
let mut stdout = io::stdout();
|
||||
execute!(stdout, EnterAlternateScreen)?;
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
|
||||
let request = tonic::Request::new(DataRequest {
|
||||
data: "hello world".to_string(),
|
||||
let mut client = AdresarClient::connect("http://[::1]:50051").await?;
|
||||
|
||||
let mut firma = String::new();
|
||||
let mut kz = String::new();
|
||||
let mut drc = String::new();
|
||||
let mut ulica = String::new();
|
||||
let mut psc = String::new();
|
||||
let mut mesto = String::new();
|
||||
let mut stat = String::new();
|
||||
let mut banka = String::new();
|
||||
let mut ucet = String::new();
|
||||
let mut skladm = String::new();
|
||||
let mut ico = String::new();
|
||||
let mut kontakt = String::new();
|
||||
let mut telefon = String::new();
|
||||
let mut skladu = String::new();
|
||||
let mut fax = String::new();
|
||||
|
||||
let mut current_field = 0;
|
||||
let fields = vec!["Firma", "KZ", "DRC", "Ulica", "PSC", "Mesto", "Stat", "Banka", "Ucet", "Skladm", "ICO", "Kontakt", "Telefon", "Skladu", "Fax"];
|
||||
|
||||
loop {
|
||||
terminal.draw(|f| {
|
||||
ui(f, &fields, &mut current_field, &[
|
||||
&firma, &kz, &drc, &ulica, &psc, &mesto, &stat, &banka, &ucet, &skladm, &ico, &kontakt, &telefon, &skladu, &fax,
|
||||
]);
|
||||
})?;
|
||||
|
||||
if let Event::Key(key) = event::read()? {
|
||||
match key.code {
|
||||
KeyCode::Char(c) => {
|
||||
match current_field {
|
||||
0 => firma.push(c),
|
||||
1 => kz.push(c),
|
||||
2 => drc.push(c),
|
||||
3 => ulica.push(c),
|
||||
4 => psc.push(c),
|
||||
5 => mesto.push(c),
|
||||
6 => stat.push(c),
|
||||
7 => banka.push(c),
|
||||
8 => ucet.push(c),
|
||||
9 => skladm.push(c),
|
||||
10 => ico.push(c),
|
||||
11 => kontakt.push(c),
|
||||
12 => telefon.push(c),
|
||||
13 => skladu.push(c),
|
||||
14 => fax.push(c),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
KeyCode::Backspace => {
|
||||
match current_field {
|
||||
0 => firma.pop(),
|
||||
1 => kz.pop(),
|
||||
2 => drc.pop(),
|
||||
3 => ulica.pop(),
|
||||
4 => psc.pop(),
|
||||
5 => mesto.pop(),
|
||||
6 => stat.pop(),
|
||||
7 => banka.pop(),
|
||||
8 => ucet.pop(),
|
||||
9 => skladm.pop(),
|
||||
10 => ico.pop(),
|
||||
11 => kontakt.pop(),
|
||||
12 => telefon.pop(),
|
||||
13 => skladu.pop(),
|
||||
14 => fax.pop(),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
KeyCode::Down => {
|
||||
if current_field < fields.len() - 1 {
|
||||
current_field += 1;
|
||||
}
|
||||
}
|
||||
KeyCode::Up => {
|
||||
if current_field > 0 {
|
||||
current_field -= 1;
|
||||
}
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
if current_field == fields.len() - 1 {
|
||||
break;
|
||||
} else {
|
||||
current_field += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup terminal
|
||||
disable_raw_mode()?;
|
||||
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
|
||||
|
||||
let request = tonic::Request::new(AdresarRequest {
|
||||
firma,
|
||||
kz,
|
||||
drc,
|
||||
ulica,
|
||||
psc,
|
||||
mesto,
|
||||
stat,
|
||||
banka,
|
||||
ucet,
|
||||
skladm,
|
||||
ico,
|
||||
kontakt,
|
||||
telefon,
|
||||
skladu,
|
||||
fax,
|
||||
});
|
||||
|
||||
let response = client.process_data(request).await?;
|
||||
|
||||
println!("RESPONSE={:?}", response.into_inner().processed_data);
|
||||
let response = client.create_adresar(request).await?;
|
||||
println!("Adresar created: {:?}", response.into_inner());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ui(
|
||||
f: &mut Frame,
|
||||
fields: &[&str],
|
||||
current_field: &mut usize,
|
||||
inputs: &[&String],
|
||||
) {
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints::<&[Constraint]>(
|
||||
&fields
|
||||
.iter()
|
||||
.map(|_| Constraint::Length(3))
|
||||
.collect::<Vec<Constraint>>(),
|
||||
)
|
||||
.split(f.area());
|
||||
|
||||
for (i, field) in fields.iter().enumerate() {
|
||||
let input = inputs[i].clone();
|
||||
let paragraph = Paragraph::new(input)
|
||||
.block(Block::default().borders(Borders::ALL).title(*field))
|
||||
.style(if i == *current_field {
|
||||
Style::default().fg(Color::Yellow)
|
||||
} else {
|
||||
Style::default()
|
||||
});
|
||||
|
||||
f.render_widget(paragraph, chunks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@ pub mod db;
|
||||
pub mod client;
|
||||
pub mod server;
|
||||
pub mod proto;
|
||||
pub mod adresar;
|
||||
|
||||
@@ -1,49 +1,35 @@
|
||||
// src/server/mod.rs
|
||||
use tonic::{Request, Response, Status};
|
||||
use crate::db;
|
||||
use crate::adresar::handlers::create_adresar;
|
||||
use crate::proto::multieko2::{
|
||||
data_processor_server::{DataProcessor, DataProcessorServer},
|
||||
DataRequest, DataResponse
|
||||
AdresarRequest, AdresarResponse,
|
||||
adresar_server::{Adresar, AdresarServer},
|
||||
};
|
||||
|
||||
pub struct DataProcessorService {
|
||||
pub struct AdresarService {
|
||||
db_pool: sqlx::PgPool,
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl DataProcessor for DataProcessorService {
|
||||
async fn process_data(
|
||||
impl Adresar for AdresarService {
|
||||
async fn create_adresar(
|
||||
&self,
|
||||
request: Request<DataRequest>,
|
||||
) -> Result<Response<DataResponse>, Status> {
|
||||
let data = request.into_inner().data;
|
||||
|
||||
// Store data in database
|
||||
let stored_data = sqlx::query!(
|
||||
"INSERT INTO processed_data (content) VALUES ($1) RETURNING id",
|
||||
data
|
||||
)
|
||||
.fetch_one(&self.db_pool)
|
||||
.await
|
||||
.map_err(|e| Status::internal(e.to_string()))?;
|
||||
|
||||
// Simple processing: convert to uppercase
|
||||
let processed_data = data.to_uppercase();
|
||||
|
||||
Ok(Response::new(DataResponse {
|
||||
processed_data: format!("Processed data with ID: {}", stored_data.id)
|
||||
}))
|
||||
request: Request<AdresarRequest>,
|
||||
) -> Result<Response<AdresarResponse>, Status> {
|
||||
let response = create_adresar(&self.db_pool, request.into_inner()).await?;
|
||||
Ok(Response::new(response))
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run_server(db_pool: sqlx::PgPool) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let addr = "[::1]:50051".parse()?;
|
||||
let service = DataProcessorService { db_pool };
|
||||
let adresar_service = AdresarService { db_pool: db_pool.clone() };
|
||||
|
||||
println!("Server listening on {}", addr);
|
||||
|
||||
tonic::transport::Server::builder()
|
||||
.add_service(DataProcessorServer::new(service))
|
||||
.add_service(AdresarServer::new(adresar_service))
|
||||
.serve(addr)
|
||||
.await?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user