Add a RON API to search recipes by title + a bit of refactoring
This commit is contained in:
parent
a3f61e3711
commit
084f7ef445
26 changed files with 499 additions and 333 deletions
|
|
@ -4,7 +4,7 @@ use axum::{
|
|||
extract::{Extension, Query, State},
|
||||
response::{Html, IntoResponse},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use common::web_api;
|
||||
|
||||
use crate::{
|
||||
app::{Context, Result},
|
||||
|
|
@ -12,15 +12,10 @@ use crate::{
|
|||
html_templates::*,
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CurrentRecipeId {
|
||||
current_recipe_id: Option<i64>,
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn recipes_list_fragments(
|
||||
State(connection): State<db::Connection>,
|
||||
current_recipe: Query<CurrentRecipeId>,
|
||||
params: Query<web_api::RecipesListFragmentsParams>,
|
||||
Extension(context): Extension<Context>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
Ok(Html(
|
||||
|
|
@ -29,7 +24,7 @@ pub async fn recipes_list_fragments(
|
|||
connection,
|
||||
&context.user,
|
||||
context.tr.current_lang_code(),
|
||||
current_recipe.current_recipe_id,
|
||||
params.current_recipe_id,
|
||||
)
|
||||
.await?,
|
||||
context,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use axum::{
|
|||
middleware::Next,
|
||||
response::{Html, IntoResponse, Response},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde::{self, Deserialize};
|
||||
|
||||
use crate::{
|
||||
app::{AppState, Context, Result},
|
||||
|
|
@ -109,7 +109,7 @@ pub async fn dev_panel(
|
|||
///// LOGS /////
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LogFile {
|
||||
pub struct LogsParams {
|
||||
#[serde(default)]
|
||||
pub log_file: String,
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ pub async fn logs(
|
|||
State(connection): State<db::Connection>,
|
||||
State(log): State<Log>,
|
||||
Extension(context): Extension<Context>,
|
||||
log_file: Query<LogFile>,
|
||||
Query(params): Query<LogsParams>,
|
||||
) -> Result<Response> {
|
||||
if context.user.is_some() && context.user.as_ref().unwrap().is_admin {
|
||||
Ok(Html(
|
||||
|
|
@ -133,11 +133,11 @@ pub async fn logs(
|
|||
.await?,
|
||||
context,
|
||||
current_log_file: match (
|
||||
log_file.log_file.is_empty(),
|
||||
params.log_file.is_empty(),
|
||||
log.file_names().unwrap_or_default(),
|
||||
) {
|
||||
(true, file_names) if !file_names.is_empty() => file_names[0].clone(),
|
||||
_ => log_file.log_file.clone(),
|
||||
_ => params.log_file.clone(),
|
||||
},
|
||||
log,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,10 @@ use super::rights::*;
|
|||
pub async fn get_scheduled_recipes(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
date_range: Query<common::ron_api::DateRange>,
|
||||
date_range: Query<common::web_api::DateRange>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
if let Some(user) = context.user {
|
||||
Ok(ron_response_ok(common::ron_api::ScheduledRecipes {
|
||||
Ok(ron_response_ok(common::web_api::ScheduledRecipes {
|
||||
recipes: connection
|
||||
.get_scheduled_recipes(user.id, date_range.start_date, date_range.end_date)
|
||||
.await?,
|
||||
|
|
@ -36,7 +36,7 @@ pub async fn get_scheduled_recipes(
|
|||
}
|
||||
}
|
||||
|
||||
impl From<data::db::recipe::AddScheduledRecipeResult> for common::ron_api::ScheduleRecipeResult {
|
||||
impl From<data::db::recipe::AddScheduledRecipeResult> for common::web_api::ScheduleRecipeResult {
|
||||
fn from(db_res: data::db::recipe::AddScheduledRecipeResult) -> Self {
|
||||
match db_res {
|
||||
db::recipe::AddScheduledRecipeResult::Ok => Self::Ok,
|
||||
|
|
@ -51,7 +51,7 @@ impl From<data::db::recipe::AddScheduledRecipeResult> for common::ron_api::Sched
|
|||
pub async fn add_scheduled_recipe(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
ExtractRon(ron): ExtractRon<common::ron_api::ScheduleRecipe>,
|
||||
ExtractRon(ron): ExtractRon<common::web_api::ScheduleRecipe>,
|
||||
) -> Result<Response> {
|
||||
check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?;
|
||||
if let Some(user) = context.user {
|
||||
|
|
@ -65,7 +65,7 @@ pub async fn add_scheduled_recipe(
|
|||
)
|
||||
.await
|
||||
.map(|res| {
|
||||
ron_response_ok(common::ron_api::ScheduleRecipeResult::from(res)).into_response()
|
||||
ron_response_ok(common::web_api::ScheduleRecipeResult::from(res)).into_response()
|
||||
})
|
||||
.map_err(ErrorResponse::from)
|
||||
} else {
|
||||
|
|
@ -77,7 +77,7 @@ pub async fn add_scheduled_recipe(
|
|||
pub async fn rm_scheduled_recipe(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
ExtractRon(ron): ExtractRon<common::ron_api::RemoveScheduledRecipe>,
|
||||
ExtractRon(ron): ExtractRon<common::web_api::RemoveScheduledRecipe>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?;
|
||||
if let Some(user) = context.user {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use crate::{
|
|||
};
|
||||
|
||||
pub mod calendar;
|
||||
mod model_converter;
|
||||
pub mod recipe;
|
||||
mod rights;
|
||||
pub mod shopping_list;
|
||||
|
|
|
|||
50
backend/src/services/ron/model_converter.rs
Normal file
50
backend/src/services/ron/model_converter.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use common::web_api;
|
||||
|
||||
use crate::data::model;
|
||||
|
||||
impl From<model::Group> for web_api::Group {
|
||||
fn from(group: model::Group) -> Self {
|
||||
Self {
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
comment: group.comment,
|
||||
steps: group.steps.into_iter().map(web_api::Step::from).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<model::Step> for web_api::Step {
|
||||
fn from(step: model::Step) -> Self {
|
||||
Self {
|
||||
id: step.id,
|
||||
action: step.action,
|
||||
ingredients: step
|
||||
.ingredients
|
||||
.into_iter()
|
||||
.map(web_api::Ingredient::from)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<model::Ingredient> for web_api::Ingredient {
|
||||
fn from(ingredient: model::Ingredient) -> Self {
|
||||
Self {
|
||||
id: ingredient.id,
|
||||
name: ingredient.name,
|
||||
comment: ingredient.comment,
|
||||
quantity_value: ingredient.quantity_value,
|
||||
quantity_unit: ingredient.quantity_unit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<model::RecipeSearchResult> for web_api::RecipeSearchResult {
|
||||
fn from(result: model::RecipeSearchResult) -> Self {
|
||||
Self {
|
||||
recipe_id: result.id,
|
||||
title: result.title,
|
||||
title_highlighted: result.title_highlighted,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,24 +5,39 @@ use axum::{
|
|||
response::{IntoResponse, Result},
|
||||
};
|
||||
use axum_extra::extract::Query;
|
||||
use common::ron_api;
|
||||
use common::web_api;
|
||||
use serde::Deserialize;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{
|
||||
app::Context, data::db, data::model, ron_extractor::ExtractRon, ron_utils::ron_response_ok,
|
||||
};
|
||||
use crate::{app::Context, data::db, ron_extractor::ExtractRon, ron_utils::ron_response_ok};
|
||||
|
||||
use super::rights::*;
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn search_by_title(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
Query(params): Query<web_api::SearchByTitleParams>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
Ok(ron_response_ok(
|
||||
connection
|
||||
.search_recipes(context.tr.current_lang_code(), ¶ms.search_term)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(web_api::RecipeSearchResult::from)
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Ask recipe titles associated with each given id. The returned titles are in the same order
|
||||
/// as the given ids.
|
||||
#[debug_handler]
|
||||
pub async fn get_titles(
|
||||
State(connection): State<db::Connection>,
|
||||
recipe_ids: Query<Vec<i64>>,
|
||||
Query(params): Query<web_api::GetTitlesParams>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
Ok(ron_response_ok(
|
||||
connection.get_recipe_titles(&recipe_ids).await?,
|
||||
connection.get_recipe_titles(¶ms.ids).await?,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
@ -88,16 +103,23 @@ pub async fn get_tags(
|
|||
))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct GetAllTagsParams {
|
||||
nb_max_tags: Option<u32>,
|
||||
lang: Option<String>,
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn get_all_tags(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
nb_max_tags: Query<Option<u32>>,
|
||||
lang: Query<Option<String>>,
|
||||
Query(params): Query<GetAllTagsParams>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
let lang = lang.0.unwrap_or(context.tr.current_lang_code().to_string());
|
||||
let lang = params
|
||||
.lang
|
||||
.unwrap_or(context.tr.current_lang_code().to_string());
|
||||
Ok(ron_response_ok(
|
||||
connection.get_all_tags(&lang, nb_max_tags.0).await?,
|
||||
connection.get_all_tags(&lang, params.nb_max_tags).await?,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +152,7 @@ pub async fn set_difficulty(
|
|||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
Path(recipe_id): Path<i64>,
|
||||
ExtractRon(difficulty): ExtractRon<ron_api::Difficulty>,
|
||||
ExtractRon(difficulty): ExtractRon<web_api::Difficulty>,
|
||||
) -> Result<StatusCode> {
|
||||
check_user_rights_recipe(&connection, &context.user, recipe_id).await?;
|
||||
connection
|
||||
|
|
@ -184,43 +206,6 @@ pub async fn rm(
|
|||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
impl From<model::Group> for ron_api::Group {
|
||||
fn from(group: model::Group) -> Self {
|
||||
Self {
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
comment: group.comment,
|
||||
steps: group.steps.into_iter().map(ron_api::Step::from).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<model::Step> for ron_api::Step {
|
||||
fn from(step: model::Step) -> Self {
|
||||
Self {
|
||||
id: step.id,
|
||||
action: step.action,
|
||||
ingredients: step
|
||||
.ingredients
|
||||
.into_iter()
|
||||
.map(ron_api::Ingredient::from)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<model::Ingredient> for ron_api::Ingredient {
|
||||
fn from(ingredient: model::Ingredient) -> Self {
|
||||
Self {
|
||||
id: ingredient.id,
|
||||
name: ingredient.name,
|
||||
comment: ingredient.comment,
|
||||
quantity_value: ingredient.quantity_value,
|
||||
quantity_unit: ingredient.quantity_unit,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[debug_handler]
|
||||
pub async fn get_groups(
|
||||
State(connection): State<db::Connection>,
|
||||
|
|
@ -232,7 +217,7 @@ pub async fn get_groups(
|
|||
.get_groups(recipe_id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(ron_api::Group::from)
|
||||
.map(web_api::Group::from)
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use axum::{
|
|||
http::StatusCode,
|
||||
response::{ErrorResponse, IntoResponse, Result},
|
||||
};
|
||||
use common::ron_api;
|
||||
use common::web_api;
|
||||
|
||||
use crate::{
|
||||
app::Context,
|
||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
|
||||
use super::rights::*;
|
||||
|
||||
impl From<model::ShoppingListItem> for common::ron_api::ShoppingListItem {
|
||||
impl From<model::ShoppingListItem> for common::web_api::ShoppingListItem {
|
||||
fn from(item: model::ShoppingListItem) -> Self {
|
||||
Self {
|
||||
id: item.id,
|
||||
|
|
@ -43,7 +43,7 @@ pub async fn get(
|
|||
.get_shopping_list(user.id)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(common::ron_api::ShoppingListItem::from)
|
||||
.map(common::web_api::ShoppingListItem::from)
|
||||
.collect::<Vec<_>>(),
|
||||
))
|
||||
} else {
|
||||
|
|
@ -58,7 +58,7 @@ pub async fn get(
|
|||
pub async fn set_entry_checked(
|
||||
State(connection): State<db::Connection>,
|
||||
Extension(context): Extension<Context>,
|
||||
ExtractRon(ron): ExtractRon<ron_api::KeyValue<bool>>,
|
||||
ExtractRon(ron): ExtractRon<web_api::KeyValue<bool>>,
|
||||
) -> Result<impl IntoResponse> {
|
||||
check_user_rights_shopping_list_entry(&connection, &context.user, ron.id).await?;
|
||||
Ok(ron_response_ok(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue