feat: show basic json screen
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
1885a200c4
commit
d7e21a256d
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -920,6 +920,7 @@ dependencies = [
|
||||
"directories",
|
||||
"hyperlog-core",
|
||||
"ratatui",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
|
@ -13,3 +13,4 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||
clap = { version = "4", features = ["derive", "env"] }
|
||||
dotenv = { version = "0.15" }
|
||||
axum = { version = "0.7" }
|
||||
serde_json = "1.0.116"
|
||||
|
@ -10,6 +10,7 @@ anyhow.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
ratatui = "0.26.2"
|
||||
crossterm = { version = "0.27.0", features = ["event-stream"] }
|
||||
|
@ -10,9 +10,11 @@ use crossterm::{
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use hyperlog_core::state::State;
|
||||
use hyperlog_core::{log::GraphItem, state::State};
|
||||
use ratatui::{backend::CrosstermBackend, prelude::*, widgets::*, Frame, Terminal};
|
||||
|
||||
use crate::state::SharedState;
|
||||
|
||||
struct TerminalInstance {
|
||||
terminal: Terminal<CrosstermBackend<Stdout>>,
|
||||
}
|
||||
@ -47,21 +49,84 @@ impl Drop for TerminalInstance {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn execute(state: &State) -> Result<()> {
|
||||
mod state {
|
||||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use hyperlog_core::state::State;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SharedState {
|
||||
state: Arc<State>,
|
||||
}
|
||||
|
||||
impl Deref for SharedState {
|
||||
type Target = State;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.state
|
||||
}
|
||||
}
|
||||
|
||||
impl From<State> for SharedState {
|
||||
fn from(value: State) -> Self {
|
||||
Self {
|
||||
state: Arc::new(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn execute(state: State) -> Result<()> {
|
||||
tracing::debug!("starting hyperlog tui");
|
||||
|
||||
logging::initialize_panic_handler()?;
|
||||
logging::initialize_logging()?;
|
||||
|
||||
let state = SharedState::from(state);
|
||||
|
||||
let mut terminal = TerminalInstance::new()?;
|
||||
run(&mut terminal, state).context("app loop failed")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: &State) -> Result<()> {
|
||||
pub struct App<'a> {
|
||||
state: SharedState,
|
||||
|
||||
graph_explorer: GraphExplorer<'a>,
|
||||
}
|
||||
|
||||
impl<'a> App<'a> {
|
||||
pub fn new(state: SharedState, graph_explorer: GraphExplorer<'a>) -> Self {
|
||||
Self {
|
||||
state,
|
||||
graph_explorer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Widget for &mut App<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
StatefulWidget::render(
|
||||
GraphExplorer::new(self.state.clone()),
|
||||
area,
|
||||
buf,
|
||||
&mut self.graph_explorer.inner,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: SharedState) -> Result<()> {
|
||||
let mut graph_explorer = GraphExplorer::new(state.clone());
|
||||
graph_explorer.update_graph()?;
|
||||
|
||||
let mut app = App::new(state.clone(), graph_explorer);
|
||||
|
||||
loop {
|
||||
terminal.draw(|f| crate::render_app(f, &state))?;
|
||||
terminal.draw(|f| crate::render_app(f, &mut app))?;
|
||||
if should_quit()? {
|
||||
break;
|
||||
}
|
||||
@ -69,7 +134,7 @@ fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: &State) -> Resu
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_app(frame: &mut Frame, state: &State) {
|
||||
fn render_app(frame: &mut Frame, state: &mut App) {
|
||||
let chunks =
|
||||
Layout::vertical(vec![Constraint::Length(2), Constraint::Min(0)]).split(frame.size());
|
||||
|
||||
@ -104,10 +169,74 @@ fn render_app(frame: &mut Frame, state: &State) {
|
||||
top: 2,
|
||||
bottom: 2,
|
||||
});
|
||||
//frame.render_widget(background.block(bg_block), chunks[1]);
|
||||
|
||||
if let Some(graph) = state.querier.get("something", Vec::<String>::new()) {}
|
||||
frame.render_widget(state, chunks[1])
|
||||
}
|
||||
|
||||
frame.render_widget(background.block(bg_block), chunks[1]);
|
||||
struct GraphExplorer<'a> {
|
||||
state: SharedState,
|
||||
|
||||
inner: GraphExplorerState<'a>,
|
||||
}
|
||||
|
||||
struct GraphExplorerState<'a> {
|
||||
current_path: Option<&'a str>,
|
||||
|
||||
graph: Option<GraphItem>,
|
||||
}
|
||||
|
||||
impl GraphExplorer<'_> {
|
||||
pub fn new(state: SharedState) -> Self {
|
||||
Self {
|
||||
state,
|
||||
inner: GraphExplorerState::<'_> {
|
||||
current_path: None,
|
||||
graph: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_graph(&mut self) -> Result<&mut Self> {
|
||||
let graph = self
|
||||
.state
|
||||
.querier
|
||||
.get(
|
||||
"something",
|
||||
self.inner
|
||||
.current_path
|
||||
.map(|p| p.split('.').collect::<Vec<_>>())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.ok_or(anyhow::anyhow!("graph should've had an item"))?;
|
||||
|
||||
self.inner.graph = Some(graph);
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> StatefulWidget for GraphExplorer<'a> {
|
||||
type State = GraphExplorerState<'a>;
|
||||
|
||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||
let Rect { height, .. } = area;
|
||||
let height = height as usize;
|
||||
|
||||
if let Some(graph) = &state.graph {
|
||||
if let Ok(graph) = serde_json::to_string_pretty(graph) {
|
||||
let lines = graph
|
||||
.split('\n')
|
||||
.take(height)
|
||||
.map(Line::raw)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let para = Paragraph::new(lines);
|
||||
|
||||
para.render(area, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn should_quit() -> Result<bool> {
|
||||
|
@ -14,6 +14,7 @@ tracing-subscriber.workspace = true
|
||||
clap.workspace = true
|
||||
dotenv.workspace = true
|
||||
axum.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
sqlx = { version = "0.7.3", features = [
|
||||
@ -25,7 +26,6 @@ sqlx = { version = "0.7.3", features = [
|
||||
] }
|
||||
uuid = { version = "1.7.0", features = ["v4"] }
|
||||
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
|
||||
serde_json = "1.0.116"
|
||||
bus = "2.4.1"
|
||||
dirs = "5.0.1"
|
||||
|
||||
|
@ -111,7 +111,7 @@ pub async fn execute() -> anyhow::Result<()> {
|
||||
println!("cleared lock file");
|
||||
}
|
||||
None => {
|
||||
hyperlog_tui::execute(&state).await?;
|
||||
hyperlog_tui::execute(state).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user