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",
|
"directories",
|
||||||
"hyperlog-core",
|
"hyperlog-core",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -13,3 +13,4 @@ tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
|||||||
clap = { version = "4", features = ["derive", "env"] }
|
clap = { version = "4", features = ["derive", "env"] }
|
||||||
dotenv = { version = "0.15" }
|
dotenv = { version = "0.15" }
|
||||||
axum = { version = "0.7" }
|
axum = { version = "0.7" }
|
||||||
|
serde_json = "1.0.116"
|
||||||
|
@ -10,6 +10,7 @@ anyhow.workspace = true
|
|||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
ratatui = "0.26.2"
|
ratatui = "0.26.2"
|
||||||
crossterm = { version = "0.27.0", features = ["event-stream"] }
|
crossterm = { version = "0.27.0", features = ["event-stream"] }
|
||||||
|
@ -10,9 +10,11 @@ use crossterm::{
|
|||||||
execute,
|
execute,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
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 ratatui::{backend::CrosstermBackend, prelude::*, widgets::*, Frame, Terminal};
|
||||||
|
|
||||||
|
use crate::state::SharedState;
|
||||||
|
|
||||||
struct TerminalInstance {
|
struct TerminalInstance {
|
||||||
terminal: Terminal<CrosstermBackend<Stdout>>,
|
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");
|
tracing::debug!("starting hyperlog tui");
|
||||||
|
|
||||||
logging::initialize_panic_handler()?;
|
logging::initialize_panic_handler()?;
|
||||||
logging::initialize_logging()?;
|
logging::initialize_logging()?;
|
||||||
|
|
||||||
|
let state = SharedState::from(state);
|
||||||
|
|
||||||
let mut terminal = TerminalInstance::new()?;
|
let mut terminal = TerminalInstance::new()?;
|
||||||
run(&mut terminal, state).context("app loop failed")?;
|
run(&mut terminal, state).context("app loop failed")?;
|
||||||
|
|
||||||
Ok(())
|
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 {
|
loop {
|
||||||
terminal.draw(|f| crate::render_app(f, &state))?;
|
terminal.draw(|f| crate::render_app(f, &mut app))?;
|
||||||
if should_quit()? {
|
if should_quit()? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -69,7 +134,7 @@ fn run(terminal: &mut Terminal<CrosstermBackend<Stdout>>, state: &State) -> Resu
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_app(frame: &mut Frame, state: &State) {
|
fn render_app(frame: &mut Frame, state: &mut App) {
|
||||||
let chunks =
|
let chunks =
|
||||||
Layout::vertical(vec![Constraint::Length(2), Constraint::Min(0)]).split(frame.size());
|
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,
|
top: 2,
|
||||||
bottom: 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> {
|
fn should_quit() -> Result<bool> {
|
||||||
|
@ -14,6 +14,7 @@ tracing-subscriber.workspace = true
|
|||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
dotenv.workspace = true
|
dotenv.workspace = true
|
||||||
axum.workspace = true
|
axum.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
sqlx = { version = "0.7.3", features = [
|
sqlx = { version = "0.7.3", features = [
|
||||||
@ -25,7 +26,6 @@ sqlx = { version = "0.7.3", features = [
|
|||||||
] }
|
] }
|
||||||
uuid = { version = "1.7.0", features = ["v4"] }
|
uuid = { version = "1.7.0", features = ["v4"] }
|
||||||
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
|
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
|
||||||
serde_json = "1.0.116"
|
|
||||||
bus = "2.4.1"
|
bus = "2.4.1"
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ pub async fn execute() -> anyhow::Result<()> {
|
|||||||
println!("cleared lock file");
|
println!("cleared lock file");
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
hyperlog_tui::execute(&state).await?;
|
hyperlog_tui::execute(state).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user