Data view

This commit is contained in:
2024-11-10 07:04:24 +01:00
parent 5d267af600
commit 99dddb9a0e
14 changed files with 201 additions and 10 deletions

View File

@@ -74,6 +74,8 @@ impl Hooks for App {
tasks.register(tasks::create_job::CreateJobData);
tasks.register(tasks::create_skill::CreateSkillData);
tasks.register(tasks::add_data_file::AddDataFile);
tasks.register(tasks::delete_data::DeleteData);
tasks.register(tasks::clear_data::ClearData);
}
async fn truncate(db: &DatabaseConnection) -> Result<()> {

View File

@@ -54,6 +54,19 @@ pub async fn render_project_detail_from_name(
views::website::project_detail_from_name(v, &ctx, name).await
}
pub async fn render_data(
auth: auth::JWT,
ViewEngine(v): ViewEngine<TeraView>,
State(ctx): State<AppContext>,
) -> Result<impl IntoResponse> {
match users::Model::find_by_pid(&ctx.db, &auth.claims.pid).await {
Ok(_) => {}
Err(_) => return unauthorized("Unauthorized"),
}
views::data::list(v, &ctx).await
}
pub fn routes() -> Routes {
Routes::new()
.add("/", get(render_index))
@@ -62,5 +75,6 @@ pub fn routes() -> Routes {
.add("/projects", get(render_projects))
.add("/projects/:id", get(render_project_detail))
.add("/projects/project/:name", get(render_project_detail_from_name))
.add("/data", get(render_data))
.add("/about", get(render_about))
}

View File

@@ -30,6 +30,18 @@ pub struct ProjectDto {
pub thumbnails: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateProject {
pub name: String,
pub short_description: String,
pub description: Option<String>,
pub category: Category,
pub github_url: Option<String>,
pub download_url: Option<String>,
pub visit_url: Option<String>,
pub technologies: Vec<String>,
}
pub fn get_category_from_string(category: &str) -> Category {
match category {
"Web" => Category::Web,
@@ -44,4 +56,14 @@ pub fn get_category_from_string(category: &str) -> Category {
"api" => Category::Api,
_ => Category::Desktop,
}
}
pub fn get_string_from_category(category: &Category) -> String {
match category {
Category::Web => "Web".to_string(),
Category::Mobile => "Mobile".to_string(),
Category::Desktop => "Desktop".to_string(),
Category::Game => "Game".to_string(),
Category::Api => "Api".to_string(),
}
}

View File

@@ -15,6 +15,11 @@ use std::fs::{self};
use axum_range::KnownSize;
use axum_range::Ranged;
pub async fn get_all_data(ctx: &AppContext) -> ModelResult<Vec<Model>> {
let data = Entity::find().all(&ctx.db).await?;
Ok(data)
}
pub async fn get_data_by_file_name(file_name: &str, ctx: &AppContext) -> ModelResult<Model> {
let data = Entity::find()
.filter(data::Column::FileName.eq(file_name))
@@ -183,3 +188,41 @@ pub async fn add(
}
Ok(item)
}
pub async fn clear_all_data(ctx: &AppContext) -> ModelResult<()> {
let data = get_all_data(&ctx).await?;
for item in data {
let path = PathBuf::from(&item.file_url);
tracing::info!("Deleting file: {:?}", path);
match ctx.storage.as_ref().delete(&path).await {
Ok(_) => {}
Err(_) => return Err(ModelError::Any("Failed to delete file from storage".into())),
}
item.delete(&ctx.db).await?;
}
Ok(())
}
pub async fn delete_data_by_file_name(file_name: &str, ctx: &AppContext) -> ModelResult<()> {
let data = get_data_by_file_name(&file_name, &ctx).await?;
let path = PathBuf::from(&data.file_url);
match ctx.storage.as_ref().delete(&path).await {
Ok(_) => {}
Err(_) => return Err(ModelError::Any("Failed to delete file from storage".into())),
}
data.delete(&ctx.db).await?;
Ok(())
}
pub async fn delete_multiple_data_by_file_names(
file_names: Vec<String>,
ctx: &AppContext,
) -> ModelResult<()> {
for file_name in file_names {
delete_data_by_file_name(&file_name, &ctx).await?;
}
Ok(())
}

View File

@@ -4,9 +4,9 @@ use crate::{
models::{
_entities::{
project_thumbnails,
projects::{self, Entity, Model},
projects::{self, ActiveModel, Entity, Model},
},
projects::{get_category_from_string, ProjectDto},
projects::{get_category_from_string, get_string_from_category, Category, CreateProject, ProjectDto},
},
shared::get_technologies_from_string::get_technologies_from_string,
};
@@ -139,3 +139,25 @@ pub async fn get_project_dto_by_name(ctx: &AppContext, name: &str) -> Result<Pro
Ok(project_dto)
}
pub async fn add_project(
ctx: &AppContext,
data: CreateProject,
) -> ModelResult<Model> {
let mut item = ActiveModel {
..Default::default()
};
item.name = Set(data.name);
item.short_description = Set(data.short_description);
item.description = Set(data.description);
item.category = Set(get_string_from_category(&data.category));
item.github_url = Set(data.github_url);
item.download_url = Set(data.download_url);
item.visit_url = Set(data.visit_url);
item.technology = Set(data.technologies.join(","));
let item = item.insert(&ctx.db).await?;
Ok(item)
}

View File

@@ -5,3 +5,7 @@ pub fn get_technologies_from_string(technologies: &str) -> Vec<String> {
.filter(|s| !s.trim().is_empty())
.collect()
}
pub fn convert_technologies_to_string(technologies: Vec<String>) -> String {
technologies.join(", ")
}

23
src/tasks/clear_data.rs Normal file
View File

@@ -0,0 +1,23 @@
use loco_rs::prelude::*;
use crate::services;
pub struct ClearData;
#[async_trait]
impl Task for ClearData {
fn task(&self) -> TaskInfo {
TaskInfo {
name: "clear_data".to_string(),
detail: "Task for clearing all data".to_string(),
}
}
async fn run(&self, app_context: &AppContext, _vars: &task::Vars) -> Result<()> {
services::data::clear_all_data(&app_context).await?;
tracing::info!("All data cleared successfully");
Ok(())
}
}

24
src/tasks/delete_data.rs Normal file
View File

@@ -0,0 +1,24 @@
use loco_rs::prelude::*;
use crate::services;
pub struct DeleteData;
#[async_trait]
impl Task for DeleteData {
fn task(&self) -> TaskInfo {
TaskInfo {
name: "delete_data".to_string(),
detail: "Task for deleting all data".to_string(),
}
}
async fn run(&self, app_context: &AppContext, vars: &task::Vars) -> Result<()> {
let file_name = vars.cli_arg("name")?;
services::data::delete_data_by_file_name(&file_name, &app_context).await?;
tracing::info!("Data file {} deleted successfully", file_name);
Ok(())
}
}

View File

@@ -3,3 +3,5 @@ pub mod create_job;
pub mod create_skill;
pub mod create_user;
pub mod seed;
pub mod clear_data;
pub mod delete_data;

View File

@@ -1,5 +1,12 @@
use loco_rs::prelude::*;
use crate::services;
pub async fn upload(v: impl ViewRenderer) -> Result<impl IntoResponse> {
format::render().view(&v, "website/data-upload.html", data!({}))
}
pub async fn list(v: impl ViewRenderer, ctx: &AppContext) -> Result<impl IntoResponse> {
let data = services::data::get_all_data(&ctx).await?;
format::render().view(&v, "website/data.html", data!({ "data": data }))
}