use std::{ops::Deref, sync::Arc}; use axum::{ Router, extract::{Path, Query, State}, http::StatusCode, response::{Html, Result}, routing::get, }; use wallsocket_core::{Database, Id, LoadEntryErr, logs::ServiceCallLogs}; use serde::Serialize; use minijinja::context; use crate::{AppState, helpers::Pagination}; #[cfg(feature = "input")] mod input; pub fn router + Send + Sync + 'static>() -> Router>> { let router = Router::new() .route("/", get(info_route)) .route("/logs/{sink}", get(page_preview::)) .route("/logs/{sink}/{id}", get(log_data::)); #[cfg(feature = "input")] let router = router.merge(input::router()); router } async fn info_route + Send + Sync + 'static>( State(state): State>>, ) -> Html { Html( state .templates .get_template("index") .unwrap() .render(context! {}) .unwrap(), ) } #[derive(Debug, Clone, Serialize)] struct LogPreview { id: String, input: String, } impl From<(Id, ServiceCallLogs)> for LogPreview { fn from((id, logs): (Id, ServiceCallLogs)) -> Self { Self { id: format!("{id}"), input: logs.called_with().to_string(), } } } async fn page_preview + Send + Sync + 'static>( Path(sink): Path, Query(page): Query, State(state): State>>, ) -> Result> { let results = state .config .log_retriever .get_in_id_range( &sink, None, match &page.after { Some(x) => Some( Id::from_string(x) .map_err(|e| (StatusCode::BAD_REQUEST, format!("error parsing id: {e}")))?, ), None => None, }, ) .map_err(|e| { ( StatusCode::BAD_REQUEST, format!("error retrieving logs: {e}"), ) })? .take(page.limit) .map(|r| r.map(Into::into)) .collect::, LoadEntryErr>>() .map_err(|e| { ( StatusCode::BAD_REQUEST, format!("error retrieving logs: {e}"), ) })?; Ok(Html( state .templates .get_template("log_previews") .unwrap() .render(context! { sink, results }) .unwrap(), )) } async fn log_data + Send + Sync + 'static>( Path((sink, id)): Path<(String, String)>, State(state): State>>, ) -> Result> { let logs: ServiceCallLogs = state .config .log_retriever .get( &sink, Id::from_string(&id).map_err(|_| (StatusCode::NOT_FOUND, "error parsing id"))?, ) .ok_or_else(|| (StatusCode::NOT_FOUND, "couldnt find log entry".to_string()))?; Ok(Html( state .templates .get_template("log_data") .unwrap() .render(context! { sink, id, logs }) .unwrap(), )) }