Skip to content

Commit

Permalink
feat: ✨ added request parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
zaghaghi committed Mar 9, 2024
1 parent cd5d3e9 commit 6172403
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 35 deletions.
133 changes: 98 additions & 35 deletions src/panes/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock};

use color_eyre::eyre::Result;
use crossterm::event::{KeyEvent, MouseEvent};
use oas3::Schema;
use oas3::{spec::RequestBody, Schema};
use ratatui::{
prelude::*,
widgets::{block::*, *},
Expand All @@ -21,16 +21,24 @@ use crate::{
tui::{EventResponse, Frame},
};

pub struct RequestType {
location: String,
media_type: String,
schema: Schema,
title: String,
}

#[derive(Default)]
pub struct RequestPane {
focused: bool,
focused_border_style: Style,
state: Arc<RwLock<State>>,
request_schema: Option<Schema>,

request_schemas: Vec<RequestType>,
request_schemas_index: usize,
request_schemas_styles: Vec<Vec<(Style, String)>>,
request_schema_line_offset: usize,
request_schema_content_keys: Vec<String>,
request_schema_content_keys_index: usize,
request_schema_styles: Vec<Vec<(Style, String)>>,

highlighter_syntax_set: SyntaxSet,
highlighter_theme_set: ThemeSet,
}
Expand All @@ -41,11 +49,10 @@ impl RequestPane {
state,
focused,
focused_border_style,
request_schema: None,
request_schemas: Vec::default(),
request_schemas_index: 0,
request_schemas_styles: Vec::default(),
request_schema_line_offset: 0,
request_schema_content_keys: Vec::default(),
request_schema_content_keys_index: 0,
request_schema_styles: Vec::default(),
highlighter_syntax_set: SyntaxSet::load_defaults_newlines(),
highlighter_theme_set: ThemeSet::load_defaults(),
}
Expand All @@ -69,9 +76,26 @@ impl RequestPane {
}
}

fn location_color(&self, status: &str) -> Color {
if status.starts_with("header") {
return Color::LightCyan;
}
if status.starts_with("path") {
return Color::LightBlue;
}
if status.starts_with("query") {
return Color::LightMagenta;
}
if status.starts_with("body") {
return Color::LightYellow;
}
Color::default()
}

fn set_request_schema_styles(&mut self) -> Result<()> {
if let Some(request_schema) = &self.request_schema {
let yaml_schema = serde_yaml::to_string(&request_schema)?;
self.request_schemas_styles = Vec::default();
if let Some(request_type) = self.request_schemas.get(self.request_schemas_index) {
let yaml_schema = serde_yaml::to_string(&request_type.schema)?;
let mut highlighter =
HighlightLines::new(self.yaml_syntax(), &self.highlighter_theme_set.themes["Solarized (dark)"]);
for (line_num, line) in LinesWithEndings::from(yaml_schema.as_str()).enumerate() {
Expand All @@ -90,35 +114,69 @@ impl RequestPane {
})
.collect();
line_styles.insert(0, (Style::default().dim(), format!(" {:<3} ", line_num + 1)));
self.request_schema_styles.push(line_styles);
self.request_schemas_styles.push(line_styles);
}
}
Ok(())
}

fn init_request_schema(&mut self) -> Result<()> {
{
let state = self.state.read().unwrap();
self.request_schema_styles = vec![];
self.request_schemas_styles = vec![];
self.request_schema_line_offset = 0;
self.request_schema = None;
self.request_schema_content_keys = vec![];
let state = self.state.read().unwrap();
if let Some((_path, _method, operation)) = state.active_operation() {
if let Some(oor) = &operation.request_body {
let resolved_oor = oor.resolve(&state.openapi_spec)?;
self.request_schema_content_keys = resolved_oor.content.keys().map(|key| key.to_string()).collect();
self.request_schema = None;
if !self.request_schema_content_keys.is_empty() {
let content_key = self.request_schema_content_keys.get(self.request_schema_content_keys_index).unwrap();
self.request_schema =
resolved_oor.content.get(content_key).map_or(Ok(None), |v| v.schema(&state.openapi_spec).map(Some))?;
}
let mut request_schemas: Vec<RequestType> = vec![];
if let Some(request_body) = &operation.request_body {
request_schemas = request_body
.resolve(&state.openapi_spec)
.unwrap_or(RequestBody::default())
.content
.iter()
.filter_map(|(media_type, media)| {
media.schema(&state.openapi_spec).map_or(None, |schema| {
Some(RequestType {
location: String::from("body"),
media_type: media_type.to_string(),
title: schema.title.clone().unwrap_or("Body".to_string()),
schema,
})
})
})
.collect();
}
request_schemas.extend(
operation.parameters.iter().filter_map(|parameter| parameter.resolve(&state.openapi_spec).ok()).map(
|parameter| {
RequestType {
location: parameter.location,
media_type: parameter.param_type.unwrap_or_default(),
schema: parameter.schema.unwrap_or_default(),
title: parameter.name,
}
},
),
);
self.request_schemas = request_schemas;
}
}
self.set_request_schema_styles()?;
Ok(())
}

fn legend_line(&mut self) -> Line<'_> {
Line::from(vec![
Span::raw("[ "),
Span::styled("Body".to_string(), self.location_color("body")),
Span::raw(format!(" {} ", symbols::DOT)),
Span::styled("Path".to_string(), self.location_color("path")),
Span::raw(format!(" {} ", symbols::DOT)),
Span::styled("Query".to_string(), self.location_color("query")),
Span::raw(format!(" {} ", symbols::DOT)),
Span::styled("Header".to_string(), self.location_color("header")),
Span::raw(" ]"),
])
}
}
impl Pane for RequestPane {
fn init(&mut self) -> Result<()> {
Expand Down Expand Up @@ -148,18 +206,18 @@ impl Pane for RequestPane {
fn update(&mut self, action: Action) -> Result<Option<Action>> {
match action {
Action::Update => {
self.request_schema_content_keys_index = 0;
self.request_schemas_index = 0;
self.init_request_schema()?;
},
Action::Down => {
self.request_schema_line_offset =
self.request_schema_line_offset.saturating_add(1).min(self.request_schema_styles.len() - 1);
self.request_schema_line_offset.saturating_add(1).min(self.request_schemas_styles.len() - 1);
},
Action::Up => {
self.request_schema_line_offset = self.request_schema_line_offset.saturating_sub(1);
},
Action::Tab(index) if index < self.request_schema_content_keys.len().try_into()? => {
self.request_schema_content_keys_index = index.try_into()?;
Action::Tab(index) if index < self.request_schemas.len().try_into()? => {
self.request_schemas_index = index.try_into()?;
self.init_request_schema()?;
},
Action::Submit => {},
Expand All @@ -175,18 +233,22 @@ impl Pane for RequestPane {
let inner = area.inner(&inner_margin);

frame.render_widget(
Tabs::new(
self.request_schema_content_keys.iter().map(|item| Span::styled(format!("[{}]", item), Style::default()).dim()),
)
Tabs::new(self.request_schemas.iter().map(|item| {
let mut title = item.title.clone();
if !item.media_type.is_empty() {
title.push_str(format!(" [{}]", item.media_type).as_str());
}
Span::styled(title, Style::default().fg(self.location_color(item.location.as_str()))).dim()
}))
.highlight_style(Style::default().add_modifier(Modifier::BOLD | Modifier::UNDERLINED).not_dim())
.select(self.request_schema_content_keys_index),
.select(self.request_schemas_index),
inner,
);

let inner_margin: Margin = Margin { horizontal: 1, vertical: 1 };
let mut inner = inner.inner(&inner_margin);
inner.height = inner.height.saturating_add(1);
let lines = self.request_schema_styles.iter().map(|items| {
let lines = self.request_schemas_styles.iter().map(|items| {
return Line::from(
items
.iter()
Expand All @@ -209,7 +271,8 @@ impl Pane for RequestPane {
.title("Request")
.borders(Borders::ALL)
.border_style(self.border_style())
.border_type(self.border_type()),
.border_type(self.border_type())
.title_bottom(self.legend_line().right_aligned()),
area,
);

Expand Down
2 changes: 2 additions & 0 deletions src/panes/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ pub struct ResponsePane {
focused: bool,
focused_border_style: Style,
state: Arc<RwLock<State>>,

response_schemas: Vec<ResponseType>,
response_schemas_index: usize,
response_schemas_styles: Vec<Vec<(Style, String)>>,
response_schema_line_offset: usize,

highlighter_syntax_set: SyntaxSet,
highlighter_theme_set: ThemeSet,
}
Expand Down
Binary file modified static/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6172403

Please sign in to comment.