use query component

pull/12/head
Takayuki Maeda 3 years ago
parent bfaaeb91d0
commit 105ceee313

@ -9,11 +9,8 @@ pub struct TreeItemInfo {
}
impl TreeItemInfo {
pub const fn new(indent: u8) -> Self {
Self {
indent,
visible: true,
}
pub const fn new(indent: u8, visible: bool) -> Self {
Self { indent, visible }
}
pub const fn is_visible(&self) -> bool {
@ -83,7 +80,7 @@ impl DatabaseTreeItem {
let indent = u8::try_from((3_usize).saturating_sub(2))?;
Ok(Self {
info: TreeItemInfo::new(indent),
info: TreeItemInfo::new(indent, false),
kind: DatabaseTreeItemKind::Table {
database: database.name.clone(),
table: table.clone(),
@ -93,10 +90,10 @@ impl DatabaseTreeItem {
pub fn new_database(database: &Database, collapsed: bool) -> Result<Self> {
Ok(Self {
info: TreeItemInfo::new(0),
info: TreeItemInfo::new(0, true),
kind: DatabaseTreeItemKind::Database {
name: database.name.to_string(),
collapsed,
collapsed: true,
},
})
}

@ -1,5 +1,5 @@
use crate::{
components::{DatabasesComponent, QueryComponent, TableComponent},
components::{ConnectionsComponent, DatabasesComponent, QueryComponent, TableComponent},
user_config::{Connection, UserConfig},
};
use sqlx::mysql::MySqlPool;
@ -54,6 +54,7 @@ pub struct App {
pub user_config: Option<UserConfig>,
pub selected_connection: ListState,
pub databases: DatabasesComponent,
pub connections: ConnectionsComponent,
pub pool: Option<MySqlPool>,
pub error: Option<String>,
}
@ -69,6 +70,7 @@ impl Default for App {
user_config: None,
selected_connection: ListState::default(),
databases: DatabasesComponent::new(),
connections: ConnectionsComponent::default(),
pool: None,
error: None,
}
@ -76,6 +78,15 @@ impl Default for App {
}
impl App {
pub fn new(user_config: UserConfig) -> App {
App {
user_config: Some(user_config.clone()),
connections: ConnectionsComponent::new(user_config.conn),
focus_block: FocusBlock::ConnectionList,
..App::default()
}
}
pub fn next_connection(&mut self) {
if let Some(config) = &self.user_config {
let i = match self.selected_connection.selected() {

@ -0,0 +1,123 @@
use super::{Component, DrawableComponent};
use crate::event::Key;
use crate::user_config::Connection;
use anyhow::Result;
use tui::{
backend::Backend,
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Style},
text::{Span, Spans},
widgets::{Block, Borders, Clear, List, ListItem, ListState},
Frame,
};
pub struct ConnectionsComponent {
pub connections: Vec<Connection>,
pub state: ListState,
}
impl Default for ConnectionsComponent {
fn default() -> Self {
Self {
connections: Vec::new(),
state: ListState::default(),
}
}
}
impl ConnectionsComponent {
pub fn new(connections: Vec<Connection>) -> Self {
Self {
connections,
..Self::default()
}
}
pub fn next_connection(&mut self) {
let i = match self.state.selected() {
Some(i) => {
if i >= self.connections.len() - 1 {
0
} else {
i + 1
}
}
None => 0,
};
self.state.select(Some(i));
}
pub fn previous_connection(&mut self) {
let i = match self.state.selected() {
Some(i) => {
if i == 0 {
self.connections.len() - 1
} else {
i - 1
}
}
None => 0,
};
self.state.select(Some(i));
}
}
impl DrawableComponent for ConnectionsComponent {
fn draw<B: Backend>(&mut self, f: &mut Frame<B>, _area: Rect, focused: bool) -> Result<()> {
let percent_x = 60;
let percent_y = 50;
let conns = &self.connections;
let connections: Vec<ListItem> = conns
.iter()
.map(|i| {
ListItem::new(vec![Spans::from(Span::raw(i.database_url()))])
.style(Style::default())
})
.collect();
let tasks = List::new(connections)
.block(Block::default().borders(Borders::ALL).title("Connections"))
.highlight_style(Style::default().bg(Color::Blue))
.style(if focused {
Style::default()
} else {
Style::default().fg(Color::DarkGray)
});
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints(
[
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
]
.as_ref(),
)
.split(f.size());
let area = Layout::default()
.direction(Direction::Horizontal)
.constraints(
[
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
]
.as_ref(),
)
.split(popup_layout[1])[1];
f.render_widget(Clear, area);
f.render_stateful_widget(tasks, area, &mut self.state);
return Ok(());
}
}
impl Component for ConnectionsComponent {
fn event(&mut self, key: Key) -> Result<()> {
match key {
Key::Char('j') => self.next_connection(),
Key::Char('k') => self.previous_connection(),
_ => (),
}
Ok(())
}
}

@ -1,10 +1,12 @@
pub mod command;
pub mod connections;
pub mod databases;
pub mod query;
pub mod table;
pub mod utils;
pub use command::{CommandInfo, CommandText};
pub use connections::ConnectionsComponent;
pub use databases::DatabasesComponent;
pub use query::QueryComponent;
pub use table::TableComponent;

@ -34,7 +34,7 @@ impl TableComponent {
pub fn next(&mut self, lines: usize) {
let i = match self.state.selected() {
Some(i) => {
if i >= self.rows.len() - lines {
if i + lines >= self.rows.len() {
Some(self.rows.len() - 1)
} else {
Some(i + lines)
@ -50,15 +50,23 @@ impl TableComponent {
self.rows = rows;
self.column_index = 0;
self.state.select(None);
self.state.select(Some(0));
if !self.rows.is_empty() {
self.state.select(Some(0));
}
}
pub fn scroll_top(&mut self) {
if self.rows.is_empty() {
return;
}
self.state.select(None);
self.state.select(Some(0));
}
pub fn scroll_bottom(&mut self) {
if self.rows.is_empty() {
return;
}
self.state.select(Some(self.rows.len() - 1));
}

@ -9,7 +9,7 @@ mod utils;
#[macro_use]
mod log;
use crate::app::{App, FocusBlock};
use crate::app::App;
use crate::event::{Event, Key};
use crate::handlers::handle_app;
use crossterm::{
@ -35,11 +35,7 @@ async fn main() -> anyhow::Result<()> {
let mut terminal = Terminal::new(backend)?;
let events = event::Events::new(250);
let mut app = App {
user_config,
focus_block: FocusBlock::ConnectionList,
..App::default()
};
let mut app = App::new(user_config.unwrap());
terminal.clear()?;

@ -2,12 +2,12 @@ use serde::Deserialize;
use std::fs::File;
use std::io::{BufReader, Read};
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Clone)]
pub struct UserConfig {
pub conn: Vec<Connection>,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Clone)]
pub struct Connection {
pub name: Option<String>,
pub user: String,

Loading…
Cancel
Save