All checks were successful
Frontend CI / build (push) Successful in 1m8s
### Description This PR introduces full CRUD (Create, Read, Update) functionality for post labels, implemented by following the existing Clean Architecture. #### Backend * **New API Endpoints for Label Management:** * `POST /label`: Create a new label (**authentication required**). * `PUT /label/{id}`: Update a label by its ID (**authentication required**). * `GET /label`: Get all labels. * **Architectural Implementation:** * **Delivery Layer**: Added `CreateLabelRequestDto`, `UpdateLabelRequestDto`, and updated `PostController` with methods to handle label-related operations. * **Application Layer**: Created corresponding use cases (`CreateLabelUseCase`, `UpdateLabelUseCase`, `GetAllLabelsUseCase`) to handle business logic. * **Gateway/Framework Layer**: Implemented `LabelRepository` and `LabelDbService` to manage database interactions, including creating, updating, and querying labels. * **Route Adjustment:** * The route for fetching all post info has been changed from `GET /post/all` to `GET /post` to be more RESTful. #### Frontend * **API Call Update:** * To match the backend route change, the API path for fetching all posts is updated from `/post/all` to `/post`. ### Package Changes _No response_ ### Screenshots _No response_ ### Reference Resolves #105 ### Checklist - [x] A milestone is set - [x] The related issuse has been linked to this branch Reviewed-on: #107 Co-authored-by: SquidSpirit <squid@squidspirit.com> Co-committed-by: SquidSpirit <squid@squidspirit.com>
140 lines
4.1 KiB
Rust
140 lines
4.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use async_trait::async_trait;
|
|
|
|
use crate::{
|
|
adapter::delivery::{
|
|
create_label_request_dto::CreateLabelRequestDto, post_info_query_dto::PostQueryDto,
|
|
update_label_request_dto::UpdateLabelRequestDto,
|
|
},
|
|
application::{
|
|
error::post_error::PostError,
|
|
use_case::{
|
|
create_label_use_case::CreateLabelUseCase,
|
|
get_all_labels_use_case::GetAllLabelsUseCase,
|
|
get_all_post_info_use_case::GetAllPostInfoUseCase,
|
|
get_full_post_use_case::GetFullPostUseCase, update_label_use_case::UpdateLabelUseCase,
|
|
},
|
|
},
|
|
};
|
|
|
|
use super::{
|
|
label_response_dto::LabelResponseDto, post_info_response_dto::PostInfoResponseDto,
|
|
post_response_dto::PostResponseDto,
|
|
};
|
|
|
|
#[async_trait]
|
|
pub trait PostController: Send + Sync {
|
|
async fn get_all_post_info(
|
|
&self,
|
|
query: PostQueryDto,
|
|
) -> Result<Vec<PostInfoResponseDto>, PostError>;
|
|
|
|
async fn get_post_by_id(&self, id: i32) -> Result<PostResponseDto, PostError>;
|
|
|
|
async fn create_label(
|
|
&self,
|
|
label: CreateLabelRequestDto,
|
|
) -> Result<LabelResponseDto, PostError>;
|
|
|
|
async fn update_label(
|
|
&self,
|
|
id: i32,
|
|
label: UpdateLabelRequestDto,
|
|
) -> Result<LabelResponseDto, PostError>;
|
|
|
|
async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, PostError>;
|
|
}
|
|
|
|
pub struct PostControllerImpl {
|
|
get_all_post_info_use_case: Arc<dyn GetAllPostInfoUseCase>,
|
|
get_full_post_use_case: Arc<dyn GetFullPostUseCase>,
|
|
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
|
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
|
|
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
|
|
}
|
|
|
|
impl PostControllerImpl {
|
|
pub fn new(
|
|
get_all_post_info_use_case: Arc<dyn GetAllPostInfoUseCase>,
|
|
get_full_post_use_case: Arc<dyn GetFullPostUseCase>,
|
|
create_label_use_case: Arc<dyn CreateLabelUseCase>,
|
|
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
|
|
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
|
|
) -> Self {
|
|
Self {
|
|
get_all_post_info_use_case,
|
|
get_full_post_use_case,
|
|
create_label_use_case,
|
|
update_label_use_case,
|
|
get_all_labels_use_case,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl PostController for PostControllerImpl {
|
|
async fn get_all_post_info(
|
|
&self,
|
|
query: PostQueryDto,
|
|
) -> Result<Vec<PostInfoResponseDto>, PostError> {
|
|
let result = self
|
|
.get_all_post_info_use_case
|
|
.execute(query.is_published_only.unwrap_or(true))
|
|
.await;
|
|
|
|
result.map(|post_info_list| {
|
|
let post_info_response_dto_list: Vec<PostInfoResponseDto> = post_info_list
|
|
.into_iter()
|
|
.map(|post_info| PostInfoResponseDto::from(post_info))
|
|
.collect();
|
|
|
|
post_info_response_dto_list
|
|
})
|
|
}
|
|
|
|
async fn get_post_by_id(&self, id: i32) -> Result<PostResponseDto, PostError> {
|
|
let result = self.get_full_post_use_case.execute(id).await;
|
|
|
|
result.map(PostResponseDto::from)
|
|
}
|
|
|
|
async fn create_label(
|
|
&self,
|
|
label: CreateLabelRequestDto,
|
|
) -> Result<LabelResponseDto, PostError> {
|
|
let mut label_entity = label.into_entity();
|
|
let id = self
|
|
.create_label_use_case
|
|
.execute(label_entity.clone())
|
|
.await?;
|
|
|
|
label_entity.id = id;
|
|
Ok(LabelResponseDto::from(label_entity))
|
|
}
|
|
|
|
async fn update_label(
|
|
&self,
|
|
id: i32,
|
|
label: UpdateLabelRequestDto,
|
|
) -> Result<LabelResponseDto, PostError> {
|
|
let label_entity = label.into_entity(id);
|
|
self.update_label_use_case
|
|
.execute(label_entity.clone())
|
|
.await?;
|
|
|
|
Ok(LabelResponseDto::from(label_entity))
|
|
}
|
|
|
|
async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, PostError> {
|
|
let result = self.get_all_labels_use_case.execute().await;
|
|
|
|
result.map(|labels| {
|
|
labels
|
|
.into_iter()
|
|
.map(|label| LabelResponseDto::from(label))
|
|
.collect()
|
|
})
|
|
}
|
|
}
|