Skip to content

Commit b745e76

Browse files
committed
[FEATURE] TUI updated:
- Data base listing implemented. - Data base selector implemented.
1 parent 1635e9e commit b745e76

File tree

8 files changed

+160
-52
lines changed

8 files changed

+160
-52
lines changed
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
use super::terminal_cursor::TerminalCursor;
1+
use async_trait::async_trait;
22

3-
pub trait IManager: Clone {
4-
fn manage(&self, option: String) -> TerminalCursor<Self> where Self: Sized;
3+
use super::{terminal_cursor::TerminalCursor, terminal_option::TerminalOption};
4+
5+
#[async_trait]
6+
pub trait IManager: Clone + Send + Sync {
7+
async fn manage(&self, option: TerminalOption<Self>) -> TerminalCursor<Self> where Self: Sized;
58
}
Lines changed: 104 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
1+
use async_trait::async_trait;
2+
13
use crate::{infrastructure::repository::i_db_repository::IDBRepository, service::service::Service};
24

3-
use super::{i_manager::IManager, terminal_cursor::TerminalCursor, terminal_manager::TerminalManager, terminal_option::TerminalOption};
5+
use super::{i_manager::IManager, terminal_cursor::TerminalCursor, terminal_manager::{self, TerminalManager}, terminal_option::TerminalOption};
46

7+
const HOME: &'static str = "HOME";
58
const STATUS: &'static str = "STATUS";
69
const SHOW_DATABASES: &'static str = "SHOW_DATABASES";
10+
const SELECT_DATABASE_PANEL: &'static str = "SELECT_DATABASE_PANEL";
11+
const SELECT_DATABASE: &'static str = "SELECT_DATABASE";
12+
const DESELECT_DATABASE: &'static str = "DESELECT_DATABASE";
13+
714

815
#[derive(Clone)]
916
pub struct TerminalDatabase<T: IDBRepository> {
1017
service: Service<T>,
18+
data_base: Option<String>,
19+
collection: Option<String>
1120
}
1221

22+
#[async_trait]
1323
impl <T: IDBRepository> IManager for TerminalDatabase<T> {
1424

15-
fn manage(&self, option: String) -> TerminalCursor<Self> where Self: Sized {
16-
match option.as_str() {
17-
STATUS => self.clone().status(),
18-
SHOW_DATABASES => self.clone().show_databases(),
25+
async fn manage(&self, option: TerminalOption<Self>) -> TerminalCursor<Self> where Self: Sized {
26+
match option.option().as_str() {
27+
HOME => self.clone().home(&self.default_header()),
28+
STATUS => self.clone().status().await,
29+
SHOW_DATABASES => self.clone().show_databases().await,
30+
SELECT_DATABASE_PANEL => self.clone().select_database_panel().await,
31+
SELECT_DATABASE => self.clone().select_database(option),
32+
DESELECT_DATABASE => self.clone().deselect_database(),
1933
_ => todo!(),
2034
}
2135
}
@@ -25,30 +39,105 @@ impl <T: IDBRepository> IManager for TerminalDatabase<T> {
2539
impl <T: IDBRepository> TerminalDatabase<T> {
2640

2741
pub fn new(service: Service<T>) -> TerminalDatabase<T> {
28-
TerminalDatabase { service: service }
42+
TerminalDatabase {
43+
service: service,
44+
data_base: None,
45+
collection: None
46+
}
2947
}
3048

31-
pub fn launch(&mut self) -> &Self {
32-
let cursor = self.base_cursor();
33-
let _ = TerminalManager::new(cursor).launch();
49+
pub async fn launch(&mut self) -> &Self {
50+
let header = self.default_header();
51+
let cursor = self.home(&header);
52+
let _ = TerminalManager::new(cursor).launch().await;
3453
return self;
3554
}
3655

37-
fn base_cursor(&self) -> TerminalCursor<Self> {
38-
let mut cursor: TerminalCursor<Self> = TerminalCursor::new("Select any option: ");
39-
cursor.push(TerminalOption::from(String::from("Status"), STATUS, self.clone()));
56+
pub fn default_header(&self) -> String {
57+
return self.info_headers("Select any option: ");
58+
}
59+
60+
pub fn info_headers(&self, header: &str) -> String {
61+
let mut aux = String::from(header);
62+
if self.data_base.is_some() {
63+
aux = format!("{}\n\n * Selected data base '{}'.", aux, self.data_base.as_ref().unwrap());
64+
}
65+
return aux;
66+
}
67+
68+
fn home(&self, header: &str) -> TerminalCursor<Self> {
69+
let mut cursor: TerminalCursor<Self> = TerminalCursor::new(header);
4070
cursor.push(TerminalOption::from(String::from("Show databases"), SHOW_DATABASES, self.clone()));
71+
cursor.push(TerminalOption::from(String::from("Select database"), SELECT_DATABASE_PANEL, self.clone()));
72+
if self.data_base.is_some() {
73+
cursor.push(TerminalOption::from(String::from("Deselect database"), DESELECT_DATABASE, self.clone()));
74+
}
4175
cursor
4276
}
4377

44-
fn status(self) -> TerminalCursor<Self> {
78+
async fn status(self) -> TerminalCursor<Self> {
4579
let cursor = TerminalCursor::new("//TODO:");
4680
cursor
4781
}
4882

49-
fn show_databases(self) -> TerminalCursor<Self> {
50-
let cursor = TerminalCursor::new("//TODO:");
83+
async fn show_databases(&self) -> TerminalCursor<Self> {
84+
let result = self.service.list_data_bases().await;
85+
86+
let mut header = self.info_headers("The repository contains the following data bases: \n");
87+
if let Err(err) = &result {
88+
header = err.to_string();
89+
}
90+
91+
let mut vector = Vec::<String>::new();
92+
if result.is_ok() {
93+
vector = result.ok().unwrap();
94+
}
95+
96+
for element in vector {
97+
header = format!("{} \n - {}{}{}", header, terminal_manager::ANSI_BOLD, element, terminal_manager::ANSI_COLOR_RESET)
98+
}
99+
100+
self.home(&header)
101+
}
102+
103+
async fn select_database_panel(&self) -> TerminalCursor<Self> {
104+
let result = self.service.list_data_bases().await;
105+
106+
let mut header = self.info_headers("Select one of the following data bases:");
107+
if let Err(err) = &result {
108+
header = err.to_string();
109+
}
110+
111+
let mut vector = Vec::<String>::new();
112+
if result.is_ok() {
113+
vector = result.ok().unwrap();
114+
}
115+
116+
let mut cursor: TerminalCursor<Self> = TerminalCursor::new(&header);
117+
118+
for element in vector {
119+
let args = Vec::from(vec![element.clone()]);
120+
cursor.push(TerminalOption::from_args(element, SELECT_DATABASE, args, self.clone()));
121+
}
122+
123+
cursor.push(TerminalOption::from(String::from("[None]"), DESELECT_DATABASE, self.clone()));
124+
51125
cursor
52126
}
53127

128+
fn select_database(&mut self, option: TerminalOption<Self>) -> TerminalCursor<Self> {
129+
let args = option.args();
130+
if args.len() > 0 {
131+
let data_base = args.get(0).unwrap().to_string();
132+
self.data_base = Some(data_base);
133+
}
134+
135+
self.home(&self.default_header())
136+
}
137+
138+
fn deselect_database(&mut self) -> TerminalCursor<Self> {
139+
self.data_base = None;
140+
self.home(&self.default_header())
141+
}
142+
54143
}

src/infrastructure/manager/terminal/terminal_manager.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use crossterm::event::{read, Event, KeyCode, KeyEventKind};
44

55
use super::{i_manager::IManager, terminal_cursor::TerminalCursor};
66

7-
const ANSI_COLOR_RESET: &'static str = "\x1b[0m";
8-
const ANSI_BACKGROUND_WHITE: &'static str = "\x1b[47m";
7+
pub(crate) const ANSI_COLOR_RESET: &'static str = "\x1b[0m";
8+
pub(crate) const ANSI_BACKGROUND_WHITE: &'static str = "\x1b[47m";
9+
pub(crate) const ANSI_BOLD: &'static str = "\x1b[1m";
910

1011
#[derive(Clone)]
1112
pub struct TerminalManager<T: IManager> {
@@ -18,7 +19,7 @@ impl <T: IManager> TerminalManager<T> {
1819
return TerminalManager {cursor};
1920
}
2021

21-
pub fn launch(&mut self) -> io::Result<()> {
22+
pub async fn launch(&mut self) -> io::Result<()> {
2223

2324
self.hide_cursor();
2425

@@ -38,9 +39,10 @@ impl <T: IManager> TerminalManager<T> {
3839
KeyCode::Up => {self.cursor.decrease();},
3940
KeyCode::Down => {self.cursor.increase();},
4041
KeyCode::Enter => {
41-
println!("Enter");
42+
43+
println!("\n Please stand by...");
4244

43-
let update = self.manage();
45+
let update = self.manage().await;
4446
if update.is_none() {
4547
println!("Something goes wrong!");
4648
break;
@@ -93,11 +95,11 @@ impl <T: IManager> TerminalManager<T> {
9395

9496
}
9597

96-
fn manage(&mut self) -> Option<TerminalCursor<T>> {
98+
async fn manage(&mut self) -> Option<TerminalCursor<T>> {
9799
let o_option = self.cursor.option();
98100
if o_option.is_some() {
99101
let option = o_option.unwrap();
100-
return Some(option.execute());
102+
return Some(option.execute().await);
101103
}
102104
None
103105
}

src/infrastructure/manager/terminal/terminal_option.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@ pub struct TerminalOption<T: IManager> {
55
option: String,
66
focus: bool,
77
title: String,
8+
args: Vec<String>,
89
manager: T,
910
}
1011

1112
impl <T: IManager> TerminalOption<T> {
1213

1314
pub fn from(title: String, option: &str, manager: T) -> TerminalOption<T> {
15+
TerminalOption::from_args(title, option, Vec::new(), manager)
16+
}
17+
18+
pub fn from_args(title: String, option: &str, args: Vec<String>, manager: T) -> TerminalOption<T> {
1419
TerminalOption {
1520
option: String::from(option),
1621
focus: false,
1722
title: title,
23+
args: args,
1824
manager: manager
1925
}
2026
}
@@ -23,10 +29,18 @@ impl <T: IManager> TerminalOption<T> {
2329
return self.focus;
2430
}
2531

32+
pub fn option(&self) -> String {
33+
return self.option.clone();
34+
}
35+
2636
pub fn title(&self) -> String {
2737
return self.title.clone();
2838
}
2939

40+
pub fn args(&self) -> Vec<String> {
41+
return self.args.clone();
42+
}
43+
3044
pub fn focused(&mut self) -> &Self {
3145
self.focus = true;
3246
return self;
@@ -37,8 +51,8 @@ impl <T: IManager> TerminalOption<T> {
3751
return self;
3852
}
3953

40-
pub fn execute(&mut self) -> TerminalCursor<T> {
41-
return self.manager.manage(self.option.clone());
54+
pub async fn execute(&mut self) -> TerminalCursor<T> {
55+
return self.manager.manage(self.clone()).await;
4256
}
4357

4458
}

src/infrastructure/repository/i_db_repository.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ use async_trait::async_trait;
33
use crate::{commons::exception::connect_exception::ConnectException, domain::filter::data_base_query::DataBaseQuery};
44

55
#[async_trait]
6-
pub trait IDBRepository: Clone {
6+
pub trait IDBRepository: Clone + Send + Sync {
77
//TODO: Replace bytes vector returns with specific entities.
8-
async fn status(self) -> Result<(), ConnectException>;
9-
async fn list_data_bases(self) -> Result<Vec<String>, ConnectException>;
10-
async fn list_collections(self, query: DataBaseQuery) -> Result<Vec<String>, ConnectException>;
11-
fn info(self) -> Vec<u8>;
12-
async fn find(self, query: DataBaseQuery) -> Result<Vec<u8>, ConnectException>;
13-
fn find_all(self, query: DataBaseQuery) -> Vec<String>;
14-
fn insert(self, query: DataBaseQuery, value: String) -> Vec<u8>;
15-
fn update(self, query: DataBaseQuery, value: String) -> Vec<u8>;
16-
fn delete(self, query: DataBaseQuery) -> Vec<u8>;
8+
async fn status(&self) -> Result<(), ConnectException>;
9+
async fn list_data_bases(&self) -> Result<Vec<String>, ConnectException>;
10+
async fn list_collections(&self, query: DataBaseQuery) -> Result<Vec<String>, ConnectException>;
11+
fn info(&self) -> Vec<u8>;
12+
async fn find(&self, query: DataBaseQuery) -> Result<Vec<u8>, ConnectException>;
13+
fn find_all(&self, query: DataBaseQuery) -> Vec<String>;
14+
fn insert(&self, query: DataBaseQuery, value: String) -> Vec<u8>;
15+
fn update(&self, query: DataBaseQuery, value: String) -> Vec<u8>;
16+
fn delete(&self, query: DataBaseQuery) -> Vec<u8>;
1717
}

src/infrastructure/repository/mongo_db_repository.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ impl MongoDbRepository {
3838
Ok(client)
3939
}
4040

41-
fn data_base(self, query: &DataBaseQuery) -> Database {
41+
fn data_base(&self, query: &DataBaseQuery) -> Database {
4242
let data_base = query.data_base();
4343
return self.client.database(&data_base);
4444
}
4545

46-
fn collection(self, query: &DataBaseQuery) -> Collection<Document> {
46+
fn collection(&self, query: &DataBaseQuery) -> Collection<Document> {
4747
let collection = query.collection();
4848
return self.data_base(query).collection(&collection);
4949
}
@@ -53,7 +53,7 @@ impl MongoDbRepository {
5353
#[async_trait]
5454
impl IDBRepository for MongoDbRepository {
5555

56-
async fn status(self) -> Result<(), ConnectException> {
56+
async fn status(&self) -> Result<(), ConnectException> {
5757
let result = self.client.list_database_names(None, None).await;
5858
if result.is_err() {
5959
let exception = ConnectException::new(result.err().unwrap().to_string());
@@ -62,11 +62,11 @@ impl IDBRepository for MongoDbRepository {
6262
return Ok(());
6363
}
6464

65-
fn info(self) -> Vec<u8> {
65+
fn info(&self) -> Vec<u8> {
6666
todo!()
6767
}
6868

69-
async fn list_data_bases(self) -> Result<Vec<String>, ConnectException> {
69+
async fn list_data_bases(&self) -> Result<Vec<String>, ConnectException> {
7070
let result = self.client.list_database_names(None, None).await;
7171
if result.is_err() {
7272
let exception = ConnectException::new(result.err().unwrap().to_string());
@@ -75,7 +75,7 @@ impl IDBRepository for MongoDbRepository {
7575
return Ok(result.ok().unwrap());
7676
}
7777

78-
async fn list_collections(self, query: DataBaseQuery) -> Result<Vec<String>, ConnectException> {
78+
async fn list_collections(&self, query: DataBaseQuery) -> Result<Vec<String>, ConnectException> {
7979
let result = self.data_base(&query).list_collection_names(None).await;
8080
if result.is_err() {
8181
let exception = ConnectException::new(result.err().unwrap().to_string());
@@ -84,7 +84,7 @@ impl IDBRepository for MongoDbRepository {
8484
return Ok(result.ok().unwrap());
8585
}
8686

87-
async fn find(self, query: DataBaseQuery) -> Result<Vec<u8>, ConnectException> {
87+
async fn find(&self, query: DataBaseQuery) -> Result<Vec<u8>, ConnectException> {
8888
let collection = self.collection(&query);
8989

9090
let mut filter = FilterElement::new();
@@ -104,19 +104,19 @@ impl IDBRepository for MongoDbRepository {
104104
todo!()
105105
}
106106

107-
fn find_all(self, query: DataBaseQuery) -> Vec<String> {
107+
fn find_all(&self, query: DataBaseQuery) -> Vec<String> {
108108
todo!()
109109
}
110110

111-
fn insert(self, query: DataBaseQuery, value: String) -> Vec<u8> {
111+
fn insert(&self, query: DataBaseQuery, value: String) -> Vec<u8> {
112112
todo!()
113113
}
114114

115-
fn update(self, query: DataBaseQuery, value: String) -> Vec<u8> {
115+
fn update(&self, query: DataBaseQuery, value: String) -> Vec<u8> {
116116
todo!()
117117
}
118118

119-
fn delete(self, query: DataBaseQuery) -> Vec<u8> {
119+
fn delete(&self, query: DataBaseQuery) -> Vec<u8> {
120120
todo!()
121121
}
122122

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async fn main() {
4343
let service = Service::from(repository);
4444
let mut terminal = TerminalDatabase::new(service);
4545

46-
terminal.launch();
46+
terminal.launch().await;
4747

4848
println!("rust-db-manager!");
4949
}

0 commit comments

Comments
 (0)