update api to comply with REST
add delete build endpoint parse some info to new build view
This commit is contained in:
		@@ -1,19 +1,7 @@
 | 
				
			|||||||
use crate::api::list::build_output;
 | 
					use crate::api::build::*;
 | 
				
			||||||
use crate::api::list::okapi_add_operation_for_get_build_;
 | 
					use crate::api::list::*;
 | 
				
			||||||
use crate::api::list::okapi_add_operation_for_stats_;
 | 
					use crate::api::package::*;
 | 
				
			||||||
use crate::api::list::search;
 | 
					use crate::api::version::*;
 | 
				
			||||||
use crate::api::list::{get_build, okapi_add_operation_for_list_builds_};
 | 
					 | 
				
			||||||
use crate::api::list::{list_builds, okapi_add_operation_for_search_};
 | 
					 | 
				
			||||||
use crate::api::list::{okapi_add_operation_for_build_output_, stats};
 | 
					 | 
				
			||||||
use crate::api::package::okapi_add_operation_for_package_add_endpoint_;
 | 
					 | 
				
			||||||
use crate::api::package::okapi_add_operation_for_package_del_;
 | 
					 | 
				
			||||||
use crate::api::package::okapi_add_operation_for_package_list_;
 | 
					 | 
				
			||||||
use crate::api::package::okapi_add_operation_for_package_update_endpoint_;
 | 
					 | 
				
			||||||
use crate::api::package::package_add_endpoint;
 | 
					 | 
				
			||||||
use crate::api::package::{get_package, package_del, package_list};
 | 
					 | 
				
			||||||
use crate::api::package::{okapi_add_operation_for_get_package_, package_update_endpoint};
 | 
					 | 
				
			||||||
use crate::api::remove::okapi_add_operation_for_version_del_;
 | 
					 | 
				
			||||||
use crate::api::remove::version_del;
 | 
					 | 
				
			||||||
use rocket::Route;
 | 
					use rocket::Route;
 | 
				
			||||||
use rocket_okapi::openapi_get_routes;
 | 
					use rocket_okapi::openapi_get_routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,6 +13,7 @@ pub fn build_api() -> Vec<Route> {
 | 
				
			|||||||
        package_del,
 | 
					        package_del,
 | 
				
			||||||
        version_del,
 | 
					        version_del,
 | 
				
			||||||
        build_output,
 | 
					        build_output,
 | 
				
			||||||
 | 
					        delete_build,
 | 
				
			||||||
        list_builds,
 | 
					        list_builds,
 | 
				
			||||||
        stats,
 | 
					        stats,
 | 
				
			||||||
        get_build,
 | 
					        get_build,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										169
									
								
								backend/src/api/build.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								backend/src/api/build.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					use crate::db::migration::{JoinType, Order};
 | 
				
			||||||
 | 
					use crate::db::prelude::Builds;
 | 
				
			||||||
 | 
					use crate::db::{builds, packages, versions};
 | 
				
			||||||
 | 
					use rocket::response::status::NotFound;
 | 
				
			||||||
 | 
					use rocket::serde::json::Json;
 | 
				
			||||||
 | 
					use rocket::serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					use rocket::{delete, get, State};
 | 
				
			||||||
 | 
					use rocket_okapi::okapi::schemars;
 | 
				
			||||||
 | 
					use rocket_okapi::{openapi, JsonSchema};
 | 
				
			||||||
 | 
					use sea_orm::ColumnTrait;
 | 
				
			||||||
 | 
					use sea_orm::QueryFilter;
 | 
				
			||||||
 | 
					use sea_orm::{
 | 
				
			||||||
 | 
					    DatabaseConnection, EntityTrait, FromQueryResult, ModelTrait, QueryOrder, QuerySelect,
 | 
				
			||||||
 | 
					    RelationTrait,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
				
			||||||
 | 
					#[serde(crate = "rocket::serde")]
 | 
				
			||||||
 | 
					pub struct ListPackageModel {
 | 
				
			||||||
 | 
					    id: i32,
 | 
				
			||||||
 | 
					    name: String,
 | 
				
			||||||
 | 
					    status: i32,
 | 
				
			||||||
 | 
					    outofdate: bool,
 | 
				
			||||||
 | 
					    latest_version: Option<String>,
 | 
				
			||||||
 | 
					    latest_version_id: Option<i32>,
 | 
				
			||||||
 | 
					    latest_aur_version: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[openapi(tag = "build")]
 | 
				
			||||||
 | 
					#[get("/build/<buildid>/output?<startline>")]
 | 
				
			||||||
 | 
					pub async fn build_output(
 | 
				
			||||||
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
 | 
					    buildid: i32,
 | 
				
			||||||
 | 
					    startline: Option<i32>,
 | 
				
			||||||
 | 
					) -> Result<String, NotFound<String>> {
 | 
				
			||||||
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let build = Builds::find_by_id(buildid)
 | 
				
			||||||
 | 
					        .one(db)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .map_err(|e| NotFound(e.to_string()))?
 | 
				
			||||||
 | 
					        .ok_or(NotFound("couldn't find id".to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return match build.ouput {
 | 
				
			||||||
 | 
					        None => Err(NotFound("No Output".to_string())),
 | 
				
			||||||
 | 
					        Some(v) => match startline {
 | 
				
			||||||
 | 
					            None => Ok(v),
 | 
				
			||||||
 | 
					            Some(startline) => {
 | 
				
			||||||
 | 
					                let output: Vec<String> = v.split("\n").map(|x| x.to_string()).collect();
 | 
				
			||||||
 | 
					                let len = output.len();
 | 
				
			||||||
 | 
					                let len_missing = len as i32 - startline;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let output = output
 | 
				
			||||||
 | 
					                    .iter()
 | 
				
			||||||
 | 
					                    .rev()
 | 
				
			||||||
 | 
					                    .take(if len_missing > 0 {
 | 
				
			||||||
 | 
					                        len_missing as usize
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        0
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .rev()
 | 
				
			||||||
 | 
					                    .map(|x1| x1.clone())
 | 
				
			||||||
 | 
					                    .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let output = output.join("\n");
 | 
				
			||||||
 | 
					                Ok(output)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
				
			||||||
 | 
					#[serde(crate = "rocket::serde")]
 | 
				
			||||||
 | 
					pub struct ListBuildsModel {
 | 
				
			||||||
 | 
					    id: i32,
 | 
				
			||||||
 | 
					    pkg_id: i32,
 | 
				
			||||||
 | 
					    pkg_name: String,
 | 
				
			||||||
 | 
					    version: String,
 | 
				
			||||||
 | 
					    status: i32,
 | 
				
			||||||
 | 
					    start_time: Option<u32>,
 | 
				
			||||||
 | 
					    end_time: Option<u32>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[openapi(tag = "build")]
 | 
				
			||||||
 | 
					#[get("/builds?<pkgid>&<limit>")]
 | 
				
			||||||
 | 
					pub async fn list_builds(
 | 
				
			||||||
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
 | 
					    pkgid: Option<i32>,
 | 
				
			||||||
 | 
					    limit: Option<u64>,
 | 
				
			||||||
 | 
					) -> Result<Json<Vec<ListBuildsModel>>, NotFound<String>> {
 | 
				
			||||||
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let basequery = Builds::find()
 | 
				
			||||||
 | 
					        .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def())
 | 
				
			||||||
 | 
					        .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def())
 | 
				
			||||||
 | 
					        .select_only()
 | 
				
			||||||
 | 
					        .column_as(builds::Column::Id, "id")
 | 
				
			||||||
 | 
					        .column(builds::Column::Status)
 | 
				
			||||||
 | 
					        .column_as(packages::Column::Name, "pkg_name")
 | 
				
			||||||
 | 
					        .column_as(packages::Column::Id, "pkg_id")
 | 
				
			||||||
 | 
					        .column(versions::Column::Version)
 | 
				
			||||||
 | 
					        .column(builds::Column::EndTime)
 | 
				
			||||||
 | 
					        .column(builds::Column::StartTime)
 | 
				
			||||||
 | 
					        .order_by(builds::Column::StartTime, Order::Desc)
 | 
				
			||||||
 | 
					        .limit(limit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let build = match pkgid {
 | 
				
			||||||
 | 
					        None => basequery.into_model::<ListBuildsModel>().all(db),
 | 
				
			||||||
 | 
					        Some(pkgid) => basequery
 | 
				
			||||||
 | 
					            .filter(builds::Column::PkgId.eq(pkgid))
 | 
				
			||||||
 | 
					            .into_model::<ListBuildsModel>()
 | 
				
			||||||
 | 
					            .all(db),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .await
 | 
				
			||||||
 | 
					    .map_err(|e| NotFound(e.to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(Json(build))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[openapi(tag = "build")]
 | 
				
			||||||
 | 
					#[get("/build/<buildid>")]
 | 
				
			||||||
 | 
					pub async fn get_build(
 | 
				
			||||||
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
 | 
					    buildid: i32,
 | 
				
			||||||
 | 
					) -> Result<Json<ListBuildsModel>, NotFound<String>> {
 | 
				
			||||||
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let result = Builds::find()
 | 
				
			||||||
 | 
					        .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def())
 | 
				
			||||||
 | 
					        .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def())
 | 
				
			||||||
 | 
					        .filter(builds::Column::Id.eq(buildid))
 | 
				
			||||||
 | 
					        .select_only()
 | 
				
			||||||
 | 
					        .column_as(builds::Column::Id, "id")
 | 
				
			||||||
 | 
					        .column(builds::Column::Status)
 | 
				
			||||||
 | 
					        .column_as(packages::Column::Name, "pkg_name")
 | 
				
			||||||
 | 
					        .column_as(packages::Column::Id, "pkg_id")
 | 
				
			||||||
 | 
					        .column(versions::Column::Version)
 | 
				
			||||||
 | 
					        .column(builds::Column::EndTime)
 | 
				
			||||||
 | 
					        .column(builds::Column::StartTime)
 | 
				
			||||||
 | 
					        .into_model::<ListBuildsModel>()
 | 
				
			||||||
 | 
					        .one(db)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .map_err(|e| NotFound(e.to_string()))?
 | 
				
			||||||
 | 
					        .ok_or(NotFound("no item with id found".to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(Json(result))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[openapi(tag = "build")]
 | 
				
			||||||
 | 
					#[delete("/build/<buildid>")]
 | 
				
			||||||
 | 
					pub async fn delete_build(
 | 
				
			||||||
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
 | 
					    buildid: i32,
 | 
				
			||||||
 | 
					) -> Result<(), NotFound<String>> {
 | 
				
			||||||
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let build = Builds::find_by_id(buildid)
 | 
				
			||||||
 | 
					        .one(db)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .map_err(|e| NotFound(e.to_string()))?
 | 
				
			||||||
 | 
					        .ok_or(NotFound("Id not found".to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build
 | 
				
			||||||
 | 
					        .delete(db)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .map_err(|e| NotFound(e.to_string()))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,7 +1,6 @@
 | 
				
			|||||||
use crate::aur::aur::query_aur;
 | 
					use crate::aur::aur::query_aur;
 | 
				
			||||||
use crate::db::migration::JoinType;
 | 
					 | 
				
			||||||
use crate::db::prelude::{Builds, Packages};
 | 
					use crate::db::prelude::{Builds, Packages};
 | 
				
			||||||
use crate::db::{builds, packages, versions};
 | 
					use crate::db::{builds};
 | 
				
			||||||
use crate::utils::dir_size::dir_size;
 | 
					use crate::utils::dir_size::dir_size;
 | 
				
			||||||
use rocket::response::status::NotFound;
 | 
					use rocket::response::status::NotFound;
 | 
				
			||||||
use rocket::serde::json::Json;
 | 
					use rocket::serde::json::Json;
 | 
				
			||||||
@@ -10,8 +9,8 @@ use rocket::{get, State};
 | 
				
			|||||||
use rocket_okapi::okapi::schemars;
 | 
					use rocket_okapi::okapi::schemars;
 | 
				
			||||||
use rocket_okapi::{openapi, JsonSchema};
 | 
					use rocket_okapi::{openapi, JsonSchema};
 | 
				
			||||||
use sea_orm::{ColumnTrait, QueryFilter};
 | 
					use sea_orm::{ColumnTrait, QueryFilter};
 | 
				
			||||||
use sea_orm::{DatabaseConnection, EntityTrait, FromQueryResult, QuerySelect, RelationTrait};
 | 
					use sea_orm::{DatabaseConnection, EntityTrait, FromQueryResult};
 | 
				
			||||||
use sea_orm::{Order, PaginatorTrait, QueryOrder};
 | 
					use sea_orm::{PaginatorTrait};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, JsonSchema)]
 | 
					#[derive(Serialize, JsonSchema)]
 | 
				
			||||||
#[serde(crate = "rocket::serde")]
 | 
					#[serde(crate = "rocket::serde")]
 | 
				
			||||||
@@ -20,7 +19,7 @@ pub struct ApiPackage {
 | 
				
			|||||||
    version: String,
 | 
					    version: String,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					#[openapi(tag = "aur")]
 | 
				
			||||||
#[get("/search?<query>")]
 | 
					#[get("/search?<query>")]
 | 
				
			||||||
pub async fn search(query: &str) -> Result<Json<Vec<ApiPackage>>, String> {
 | 
					pub async fn search(query: &str) -> Result<Json<Vec<ApiPackage>>, String> {
 | 
				
			||||||
    return match query_aur(query).await {
 | 
					    return match query_aur(query).await {
 | 
				
			||||||
@@ -38,135 +37,6 @@ pub async fn search(query: &str) -> Result<Json<Vec<ApiPackage>>, String> {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
					 | 
				
			||||||
#[serde(crate = "rocket::serde")]
 | 
					 | 
				
			||||||
pub struct ListPackageModel {
 | 
					 | 
				
			||||||
    id: i32,
 | 
					 | 
				
			||||||
    name: String,
 | 
					 | 
				
			||||||
    status: i32,
 | 
					 | 
				
			||||||
    outofdate: bool,
 | 
					 | 
				
			||||||
    latest_version: Option<String>,
 | 
					 | 
				
			||||||
    latest_version_id: Option<i32>,
 | 
					 | 
				
			||||||
    latest_aur_version: String,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					 | 
				
			||||||
#[get("/builds/output?<buildid>&<startline>")]
 | 
					 | 
				
			||||||
pub async fn build_output(
 | 
					 | 
				
			||||||
    db: &State<DatabaseConnection>,
 | 
					 | 
				
			||||||
    buildid: i32,
 | 
					 | 
				
			||||||
    startline: Option<i32>,
 | 
					 | 
				
			||||||
) -> Result<String, NotFound<String>> {
 | 
					 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let build = Builds::find_by_id(buildid)
 | 
					 | 
				
			||||||
        .one(db)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
        .map_err(|e| NotFound(e.to_string()))?
 | 
					 | 
				
			||||||
        .ok_or(NotFound("couldn't find id".to_string()))?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return match build.ouput {
 | 
					 | 
				
			||||||
        None => Err(NotFound("No Output".to_string())),
 | 
					 | 
				
			||||||
        Some(v) => match startline {
 | 
					 | 
				
			||||||
            None => Ok(v),
 | 
					 | 
				
			||||||
            Some(startline) => {
 | 
					 | 
				
			||||||
                let output: Vec<String> = v.split("\n").map(|x| x.to_string()).collect();
 | 
					 | 
				
			||||||
                let len = output.len();
 | 
					 | 
				
			||||||
                let len_missing = len as i32 - startline;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let output = output
 | 
					 | 
				
			||||||
                    .iter()
 | 
					 | 
				
			||||||
                    .rev()
 | 
					 | 
				
			||||||
                    .take(if len_missing > 0 {
 | 
					 | 
				
			||||||
                        len_missing as usize
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        0
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                    .rev()
 | 
					 | 
				
			||||||
                    .map(|x1| x1.clone())
 | 
					 | 
				
			||||||
                    .collect::<Vec<_>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let output = output.join("\n");
 | 
					 | 
				
			||||||
                Ok(output)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
					 | 
				
			||||||
#[serde(crate = "rocket::serde")]
 | 
					 | 
				
			||||||
pub struct ListBuildsModel {
 | 
					 | 
				
			||||||
    id: i32,
 | 
					 | 
				
			||||||
    pkg_name: String,
 | 
					 | 
				
			||||||
    version: String,
 | 
					 | 
				
			||||||
    status: i32,
 | 
					 | 
				
			||||||
    start_time: Option<u32>,
 | 
					 | 
				
			||||||
    end_time: Option<u32>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					 | 
				
			||||||
#[get("/builds?<pkgid>&<limit>")]
 | 
					 | 
				
			||||||
pub async fn list_builds(
 | 
					 | 
				
			||||||
    db: &State<DatabaseConnection>,
 | 
					 | 
				
			||||||
    pkgid: Option<i32>,
 | 
					 | 
				
			||||||
    limit: Option<u64>,
 | 
					 | 
				
			||||||
) -> Result<Json<Vec<ListBuildsModel>>, NotFound<String>> {
 | 
					 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let basequery = Builds::find()
 | 
					 | 
				
			||||||
        .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def())
 | 
					 | 
				
			||||||
        .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def())
 | 
					 | 
				
			||||||
        .select_only()
 | 
					 | 
				
			||||||
        .column_as(builds::Column::Id, "id")
 | 
					 | 
				
			||||||
        .column(builds::Column::Status)
 | 
					 | 
				
			||||||
        .column_as(packages::Column::Name, "pkg_name")
 | 
					 | 
				
			||||||
        .column(versions::Column::Version)
 | 
					 | 
				
			||||||
        .column(builds::Column::EndTime)
 | 
					 | 
				
			||||||
        .column(builds::Column::StartTime)
 | 
					 | 
				
			||||||
        .order_by(builds::Column::StartTime, Order::Desc)
 | 
					 | 
				
			||||||
        .limit(limit);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let build = match pkgid {
 | 
					 | 
				
			||||||
        None => basequery.into_model::<ListBuildsModel>().all(db),
 | 
					 | 
				
			||||||
        Some(pkgid) => basequery
 | 
					 | 
				
			||||||
            .filter(builds::Column::PkgId.eq(pkgid))
 | 
					 | 
				
			||||||
            .into_model::<ListBuildsModel>()
 | 
					 | 
				
			||||||
            .all(db),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .await
 | 
					 | 
				
			||||||
    .map_err(|e| NotFound(e.to_string()))?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Ok(Json(build))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					 | 
				
			||||||
#[get("/builds/<buildid>")]
 | 
					 | 
				
			||||||
pub async fn get_build(
 | 
					 | 
				
			||||||
    db: &State<DatabaseConnection>,
 | 
					 | 
				
			||||||
    buildid: i32,
 | 
					 | 
				
			||||||
) -> Result<Json<ListBuildsModel>, NotFound<String>> {
 | 
					 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let result = Builds::find()
 | 
					 | 
				
			||||||
        .join_rev(JoinType::InnerJoin, packages::Relation::Builds.def())
 | 
					 | 
				
			||||||
        .join_rev(JoinType::InnerJoin, versions::Relation::Builds.def())
 | 
					 | 
				
			||||||
        .filter(builds::Column::Id.eq(buildid))
 | 
					 | 
				
			||||||
        .select_only()
 | 
					 | 
				
			||||||
        .column_as(builds::Column::Id, "id")
 | 
					 | 
				
			||||||
        .column(builds::Column::Status)
 | 
					 | 
				
			||||||
        .column_as(packages::Column::Name, "pkg_name")
 | 
					 | 
				
			||||||
        .column(versions::Column::Version)
 | 
					 | 
				
			||||||
        .column(builds::Column::EndTime)
 | 
					 | 
				
			||||||
        .column(builds::Column::StartTime)
 | 
					 | 
				
			||||||
        .into_model::<ListBuildsModel>()
 | 
					 | 
				
			||||||
        .one(db)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
        .map_err(|e| NotFound(e.to_string()))?
 | 
					 | 
				
			||||||
        .ok_or(NotFound("no item with id found".to_string()))?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Ok(Json(result))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
					#[derive(FromQueryResult, Deserialize, JsonSchema, Serialize)]
 | 
				
			||||||
#[serde(crate = "rocket::serde")]
 | 
					#[serde(crate = "rocket::serde")]
 | 
				
			||||||
pub struct ListStats {
 | 
					pub struct ListStats {
 | 
				
			||||||
@@ -179,15 +49,15 @@ pub struct ListStats {
 | 
				
			|||||||
    total_packages: u32,
 | 
					    total_packages: u32,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					#[openapi(tag = "stats")]
 | 
				
			||||||
#[get("/stats")]
 | 
					#[get("/stats")]
 | 
				
			||||||
pub async fn stats(db: &State<DatabaseConnection>) -> Result<Json<ListStats>, NotFound<String>> {
 | 
					pub async fn stats(db: &State<DatabaseConnection>) -> Result<Json<ListStats>, NotFound<String>> {
 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return match get_stats(db).await {
 | 
					    get_stats(db)
 | 
				
			||||||
        Ok(v) => Ok(Json(v)),
 | 
					        .await
 | 
				
			||||||
        Err(e) => Err(NotFound(e.to_string())),
 | 
					        .map_err(|e| NotFound(e.to_string()))
 | 
				
			||||||
    };
 | 
					        .map(Json)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn get_stats(db: &DatabaseConnection) -> anyhow::Result<ListStats> {
 | 
					async fn get_stats(db: &DatabaseConnection) -> anyhow::Result<ListStats> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
pub mod backend;
 | 
					pub mod backend;
 | 
				
			||||||
 | 
					mod build;
 | 
				
			||||||
#[cfg(feature = "static")]
 | 
					#[cfg(feature = "static")]
 | 
				
			||||||
pub mod embed;
 | 
					pub mod embed;
 | 
				
			||||||
mod list;
 | 
					mod list;
 | 
				
			||||||
mod package;
 | 
					mod package;
 | 
				
			||||||
mod remove;
 | 
					mod version;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
use crate::api::list::ListPackageModel;
 | 
					use crate::api::build::ListPackageModel;
 | 
				
			||||||
use crate::builder::types::Action;
 | 
					use crate::builder::types::Action;
 | 
				
			||||||
use crate::db::migration::{JoinType, Order};
 | 
					use crate::db::migration::{JoinType, Order};
 | 
				
			||||||
use crate::db::prelude::Packages;
 | 
					use crate::db::prelude::Packages;
 | 
				
			||||||
@@ -9,7 +9,7 @@ use crate::package::update::package_update;
 | 
				
			|||||||
use rocket::response::status::{BadRequest, NotFound};
 | 
					use rocket::response::status::{BadRequest, NotFound};
 | 
				
			||||||
use rocket::serde::json::Json;
 | 
					use rocket::serde::json::Json;
 | 
				
			||||||
use rocket::serde::Deserialize;
 | 
					use rocket::serde::Deserialize;
 | 
				
			||||||
use rocket::{get, post, State};
 | 
					use rocket::{delete, get, post, State};
 | 
				
			||||||
use rocket_okapi::okapi::schemars;
 | 
					use rocket_okapi::okapi::schemars;
 | 
				
			||||||
use rocket_okapi::{openapi, JsonSchema};
 | 
					use rocket_okapi::{openapi, JsonSchema};
 | 
				
			||||||
use sea_orm::DatabaseConnection;
 | 
					use sea_orm::DatabaseConnection;
 | 
				
			||||||
@@ -23,7 +23,7 @@ pub struct AddBody {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "Packages")]
 | 
					#[openapi(tag = "Packages")]
 | 
				
			||||||
#[post("/packages/add", data = "<input>")]
 | 
					#[post("/package", data = "<input>")]
 | 
				
			||||||
pub async fn package_add_endpoint(
 | 
					pub async fn package_add_endpoint(
 | 
				
			||||||
    db: &State<DatabaseConnection>,
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
    input: Json<AddBody>,
 | 
					    input: Json<AddBody>,
 | 
				
			||||||
@@ -41,20 +41,21 @@ pub struct UpdateBody {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "Packages")]
 | 
					#[openapi(tag = "Packages")]
 | 
				
			||||||
#[post("/packages/<id>/update", data = "<input>")]
 | 
					#[post("/package/<id>/update", data = "<input>")]
 | 
				
			||||||
pub async fn package_update_endpoint(
 | 
					pub async fn package_update_endpoint(
 | 
				
			||||||
    db: &State<DatabaseConnection>,
 | 
					    db: &State<DatabaseConnection>,
 | 
				
			||||||
    id: i32,
 | 
					    id: i32,
 | 
				
			||||||
    input: Json<UpdateBody>,
 | 
					    input: Json<UpdateBody>,
 | 
				
			||||||
    tx: &State<Sender<Action>>,
 | 
					    tx: &State<Sender<Action>>,
 | 
				
			||||||
) -> Result<(), BadRequest<String>> {
 | 
					) -> Result<Json<i32>, BadRequest<String>> {
 | 
				
			||||||
    package_update(db, id, input.force, tx)
 | 
					    package_update(db, id, input.force, tx)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
 | 
					        .map(|e| Json(e))
 | 
				
			||||||
        .map_err(|e| BadRequest(Some(e.to_string())))
 | 
					        .map_err(|e| BadRequest(Some(e.to_string())))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "Packages")]
 | 
					#[openapi(tag = "Packages")]
 | 
				
			||||||
#[post("/package/delete/<id>")]
 | 
					#[delete("/package/<id>")]
 | 
				
			||||||
pub async fn package_del(db: &State<DatabaseConnection>, id: i32) -> Result<(), String> {
 | 
					pub async fn package_del(db: &State<DatabaseConnection>, id: i32) -> Result<(), String> {
 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
use crate::repo::repo::remove_version;
 | 
					use crate::repo::repo::remove_version;
 | 
				
			||||||
use rocket::{post, State};
 | 
					use rocket::{delete, State};
 | 
				
			||||||
use rocket_okapi::openapi;
 | 
					use rocket_okapi::openapi;
 | 
				
			||||||
use sea_orm::DatabaseConnection;
 | 
					use sea_orm::DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[openapi(tag = "test")]
 | 
					#[openapi(tag = "version")]
 | 
				
			||||||
#[post("/versions/delete/<id>")]
 | 
					#[delete("/version/<id>/delete")]
 | 
				
			||||||
pub async fn version_del(db: &State<DatabaseConnection>, id: i32) -> Result<(), String> {
 | 
					pub async fn version_del(db: &State<DatabaseConnection>, id: i32) -> Result<(), String> {
 | 
				
			||||||
    let db = db as &DatabaseConnection;
 | 
					    let db = db as &DatabaseConnection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -19,12 +19,13 @@ pub async fn init(db: DatabaseConnection, tx: Sender<Action>) {
 | 
				
			|||||||
        if let Ok(_result) = tx.subscribe().recv().await {
 | 
					        if let Ok(_result) = tx.subscribe().recv().await {
 | 
				
			||||||
            match _result {
 | 
					            match _result {
 | 
				
			||||||
                // add a package to parallel build
 | 
					                // add a package to parallel build
 | 
				
			||||||
                Action::Build(name, version, url, version_model) => {
 | 
					                Action::Build(name, version, url, version_model, build_model) => {
 | 
				
			||||||
                    let _ = queue_package(
 | 
					                    let _ = queue_package(
 | 
				
			||||||
                        name,
 | 
					                        name,
 | 
				
			||||||
                        version,
 | 
					                        version,
 | 
				
			||||||
                        url,
 | 
					                        url,
 | 
				
			||||||
                        version_model,
 | 
					                        version_model,
 | 
				
			||||||
 | 
					                        build_model,
 | 
				
			||||||
                        db.clone(),
 | 
					                        db.clone(),
 | 
				
			||||||
                        semaphore.clone(),
 | 
					                        semaphore.clone(),
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
@@ -40,25 +41,10 @@ async fn queue_package(
 | 
				
			|||||||
    version: String,
 | 
					    version: String,
 | 
				
			||||||
    url: String,
 | 
					    url: String,
 | 
				
			||||||
    version_model: versions::ActiveModel,
 | 
					    version_model: versions::ActiveModel,
 | 
				
			||||||
 | 
					    mut build_model: builds::ActiveModel,
 | 
				
			||||||
    db: DatabaseConnection,
 | 
					    db: DatabaseConnection,
 | 
				
			||||||
    semaphore: Arc<Semaphore>,
 | 
					    semaphore: Arc<Semaphore>,
 | 
				
			||||||
) -> anyhow::Result<()> {
 | 
					) -> anyhow::Result<()> {
 | 
				
			||||||
    // set build status to pending
 | 
					 | 
				
			||||||
    let build = builds::ActiveModel {
 | 
					 | 
				
			||||||
        pkg_id: version_model.package_id.clone(),
 | 
					 | 
				
			||||||
        version_id: version_model.id.clone(),
 | 
					 | 
				
			||||||
        ouput: Set(None),
 | 
					 | 
				
			||||||
        status: Set(Some(3)),
 | 
					 | 
				
			||||||
        start_time: Set(Some(
 | 
					 | 
				
			||||||
            SystemTime::now()
 | 
					 | 
				
			||||||
                .duration_since(UNIX_EPOCH)
 | 
					 | 
				
			||||||
                .unwrap()
 | 
					 | 
				
			||||||
                .as_secs() as u32,
 | 
					 | 
				
			||||||
        )),
 | 
					 | 
				
			||||||
        ..Default::default()
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
    let mut new_build = build.save(&db).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let permits = Arc::clone(&semaphore);
 | 
					    let permits = Arc::clone(&semaphore);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // spawn new thread for each pkg build
 | 
					    // spawn new thread for each pkg build
 | 
				
			||||||
@@ -67,10 +53,10 @@ async fn queue_package(
 | 
				
			|||||||
        let _permit = permits.acquire().await.unwrap();
 | 
					        let _permit = permits.acquire().await.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // set build status to building
 | 
					        // set build status to building
 | 
				
			||||||
        new_build.status = Set(Some(0));
 | 
					        build_model.status = Set(Some(0));
 | 
				
			||||||
        new_build = new_build.save(&db).await.unwrap();
 | 
					        build_model = build_model.save(&db).await.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let _ = build_package(new_build, db, version_model, version, name, url).await;
 | 
					        let _ = build_package(build_model, db, version_model, version, name, url).await;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,12 @@
 | 
				
			|||||||
use crate::db::versions;
 | 
					use crate::db::{builds, versions};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub enum Action {
 | 
					pub enum Action {
 | 
				
			||||||
    Build(String, String, String, versions::ActiveModel),
 | 
					    Build(
 | 
				
			||||||
 | 
					        String,
 | 
				
			||||||
 | 
					        String,
 | 
				
			||||||
 | 
					        String,
 | 
				
			||||||
 | 
					        versions::ActiveModel,
 | 
				
			||||||
 | 
					        builds::ActiveModel,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
use crate::aur::aur::get_info_by_name;
 | 
					use crate::aur::aur::get_info_by_name;
 | 
				
			||||||
use crate::builder::types::Action;
 | 
					use crate::builder::types::Action;
 | 
				
			||||||
use crate::db::prelude::Packages;
 | 
					use crate::db::prelude::Packages;
 | 
				
			||||||
use crate::db::{packages, versions};
 | 
					use crate::db::{builds, packages, versions};
 | 
				
			||||||
use anyhow::anyhow;
 | 
					use anyhow::anyhow;
 | 
				
			||||||
use sea_orm::ColumnTrait;
 | 
					use sea_orm::ColumnTrait;
 | 
				
			||||||
use sea_orm::QueryFilter;
 | 
					use sea_orm::QueryFilter;
 | 
				
			||||||
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set, TransactionTrait};
 | 
					use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set, TransactionTrait};
 | 
				
			||||||
 | 
					use std::time::{SystemTime, UNIX_EPOCH};
 | 
				
			||||||
use tokio::sync::broadcast::Sender;
 | 
					use tokio::sync::broadcast::Sender;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn package_add(
 | 
					pub async fn package_add(
 | 
				
			||||||
@@ -49,11 +50,28 @@ pub async fn package_add(
 | 
				
			|||||||
    new_package.latest_version_id = Set(Some(new_version.id.clone().unwrap()));
 | 
					    new_package.latest_version_id = Set(Some(new_version.id.clone().unwrap()));
 | 
				
			||||||
    new_package.save(&txn).await?;
 | 
					    new_package.save(&txn).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set build status to pending
 | 
				
			||||||
 | 
					    let build = builds::ActiveModel {
 | 
				
			||||||
 | 
					        pkg_id: new_version.package_id.clone(),
 | 
				
			||||||
 | 
					        version_id: new_version.id.clone(),
 | 
				
			||||||
 | 
					        ouput: Set(None),
 | 
				
			||||||
 | 
					        status: Set(Some(3)),
 | 
				
			||||||
 | 
					        start_time: Set(Some(
 | 
				
			||||||
 | 
					            SystemTime::now()
 | 
				
			||||||
 | 
					                .duration_since(UNIX_EPOCH)
 | 
				
			||||||
 | 
					                .unwrap()
 | 
				
			||||||
 | 
					                .as_secs() as u32,
 | 
				
			||||||
 | 
					        )),
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let new_build = build.save(&txn).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let _ = tx.send(Action::Build(
 | 
					    let _ = tx.send(Action::Build(
 | 
				
			||||||
        pkg.name,
 | 
					        pkg.name,
 | 
				
			||||||
        pkg.version,
 | 
					        pkg.version,
 | 
				
			||||||
        pkg.url_path.unwrap(),
 | 
					        pkg.url_path.unwrap(),
 | 
				
			||||||
        new_version,
 | 
					        new_version,
 | 
				
			||||||
 | 
					        new_build,
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    txn.commit().await?;
 | 
					    txn.commit().await?;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
use crate::aur::aur::get_info_by_name;
 | 
					use crate::aur::aur::get_info_by_name;
 | 
				
			||||||
use crate::builder::types::Action;
 | 
					use crate::builder::types::Action;
 | 
				
			||||||
use crate::db::prelude::{Packages, Versions};
 | 
					use crate::db::prelude::{Packages, Versions};
 | 
				
			||||||
use crate::db::{packages, versions};
 | 
					use crate::db::{builds, packages, versions};
 | 
				
			||||||
use anyhow::anyhow;
 | 
					use anyhow::anyhow;
 | 
				
			||||||
use sea_orm::ColumnTrait;
 | 
					use sea_orm::ColumnTrait;
 | 
				
			||||||
use sea_orm::QueryFilter;
 | 
					use sea_orm::QueryFilter;
 | 
				
			||||||
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set, TransactionTrait};
 | 
					use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set, TransactionTrait};
 | 
				
			||||||
 | 
					use std::time::{SystemTime, UNIX_EPOCH};
 | 
				
			||||||
use tokio::sync::broadcast::Sender;
 | 
					use tokio::sync::broadcast::Sender;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub async fn package_update(
 | 
					pub async fn package_update(
 | 
				
			||||||
@@ -13,7 +14,7 @@ pub async fn package_update(
 | 
				
			|||||||
    pkg_id: i32,
 | 
					    pkg_id: i32,
 | 
				
			||||||
    force: bool,
 | 
					    force: bool,
 | 
				
			||||||
    tx: &Sender<Action>,
 | 
					    tx: &Sender<Action>,
 | 
				
			||||||
) -> anyhow::Result<()> {
 | 
					) -> anyhow::Result<i32> {
 | 
				
			||||||
    let txn = db.begin().await?;
 | 
					    let txn = db.begin().await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut pkg_model: packages::ActiveModel = Packages::find_by_id(pkg_id)
 | 
					    let mut pkg_model: packages::ActiveModel = Packages::find_by_id(pkg_id)
 | 
				
			||||||
@@ -54,16 +55,34 @@ pub async fn package_update(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pkg_model.status = Set(3);
 | 
					    pkg_model.status = Set(3);
 | 
				
			||||||
    pkg_model.latest_version_id = Set(Some(version_model.id.clone().unwrap()));
 | 
					    pkg_model.latest_version_id = Set(Some(version_model.id.clone().unwrap()));
 | 
				
			||||||
    pkg_model.save(&txn).await.expect("todo error message");
 | 
					    pkg_model.save(&txn).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set build status to pending
 | 
				
			||||||
 | 
					    let build = builds::ActiveModel {
 | 
				
			||||||
 | 
					        pkg_id: version_model.package_id.clone(),
 | 
				
			||||||
 | 
					        version_id: version_model.id.clone(),
 | 
				
			||||||
 | 
					        ouput: Set(None),
 | 
				
			||||||
 | 
					        status: Set(Some(3)),
 | 
				
			||||||
 | 
					        start_time: Set(Some(
 | 
				
			||||||
 | 
					            SystemTime::now()
 | 
				
			||||||
 | 
					                .duration_since(UNIX_EPOCH)
 | 
				
			||||||
 | 
					                .unwrap()
 | 
				
			||||||
 | 
					                .as_secs() as u32,
 | 
				
			||||||
 | 
					        )),
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let new_build = build.save(&txn).await?;
 | 
				
			||||||
 | 
					    let build_id = new_build.id.clone().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let _ = tx.send(Action::Build(
 | 
					    let _ = tx.send(Action::Build(
 | 
				
			||||||
        pkg.name,
 | 
					        pkg.name,
 | 
				
			||||||
        pkg.version,
 | 
					        pkg.version,
 | 
				
			||||||
        pkg.url_path.unwrap(),
 | 
					        pkg.url_path.unwrap(),
 | 
				
			||||||
        version_model,
 | 
					        version_model,
 | 
				
			||||||
 | 
					        new_build,
 | 
				
			||||||
    ));
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    txn.commit().await?;
 | 
					    txn.commit().await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(build_id)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ApiClient {
 | 
					class ApiClient {
 | 
				
			||||||
  static const String _apiBase =
 | 
					  static const String _apiBase =
 | 
				
			||||||
      kDebugMode ? "https://aurcache.heili.eu/api" : "api";
 | 
					      kDebugMode ? "http://localhost:8081/api" : "api";
 | 
				
			||||||
  final Dio _dio = Dio(BaseOptions(baseUrl: _apiBase));
 | 
					  final Dio _dio = Dio(BaseOptions(baseUrl: _apiBase));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  String? token;
 | 
					  String? token;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,14 +21,19 @@ extension BuildsAPI on ApiClient {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<Build> getBuild(int id) async {
 | 
					  Future<Build> getBuild(int id) async {
 | 
				
			||||||
    final resp = await getRawClient().get("/builds/${id}");
 | 
					    final resp = await getRawClient().get("/build/${id}");
 | 
				
			||||||
    return Build.fromJson(resp.data);
 | 
					    return Build.fromJson(resp.data);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<bool> deleteBuild(int id) async {
 | 
				
			||||||
 | 
					    final resp = await getRawClient().delete("/build/${id}");
 | 
				
			||||||
 | 
					    return resp.statusCode == 400;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<String> getOutput({int? line, required int buildID}) async {
 | 
					  Future<String> getOutput({int? line, required int buildID}) async {
 | 
				
			||||||
    String uri = "/builds/output?buildid=$buildID";
 | 
					    String uri = "/build/$buildID/output";
 | 
				
			||||||
    if (line != null) {
 | 
					    if (line != null) {
 | 
				
			||||||
      uri += "&startline=$line";
 | 
					      uri += "?startline=$line";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    final resp = await getRawClient().get(uri);
 | 
					    final resp = await getRawClient().get(uri);
 | 
				
			||||||
    return resp.data.toString();
 | 
					    return resp.data.toString();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,19 +20,20 @@ extension PackagesAPI on ApiClient {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> addPackage({required String name}) async {
 | 
					  Future<void> addPackage({required String name}) async {
 | 
				
			||||||
    final resp =
 | 
					    final resp = await getRawClient().post("/package", data: {'name': name});
 | 
				
			||||||
        await getRawClient().post("/packages/add", data: {'name': name});
 | 
					 | 
				
			||||||
    print(resp.data);
 | 
					    print(resp.data);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<void> updatePackage({bool force = false, required int id}) async {
 | 
					  Future<int> updatePackage({bool force = false, required int id}) async {
 | 
				
			||||||
    final resp = await getRawClient()
 | 
					    final resp = await getRawClient()
 | 
				
			||||||
        .post("/packages/$id/update", data: {'force': force});
 | 
					        .post("/package/$id/update", data: {'force': force});
 | 
				
			||||||
    print(resp.data);
 | 
					    print(resp.data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return resp.data as int;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Future<bool> deletePackage(int id) async {
 | 
					  Future<bool> deletePackage(int id) async {
 | 
				
			||||||
    final resp = await getRawClient().post("/package/delete/$id");
 | 
					    final resp = await getRawClient().delete("/package/$id");
 | 
				
			||||||
    return resp.statusCode == 200;
 | 
					    return resp.statusCode == 200;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,14 @@
 | 
				
			|||||||
class Build {
 | 
					class Build {
 | 
				
			||||||
  final int id;
 | 
					  final int id;
 | 
				
			||||||
  final String pkg_name;
 | 
					  final String pkg_name;
 | 
				
			||||||
 | 
					  final int pkg_id;
 | 
				
			||||||
  final String version;
 | 
					  final String version;
 | 
				
			||||||
  final int status;
 | 
					  final int status;
 | 
				
			||||||
  final int? start_time, end_time;
 | 
					  final int? start_time, end_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Build(
 | 
					  Build(
 | 
				
			||||||
      {required this.id,
 | 
					      {required this.id,
 | 
				
			||||||
 | 
					      required this.pkg_id,
 | 
				
			||||||
      required this.pkg_name,
 | 
					      required this.pkg_name,
 | 
				
			||||||
      required this.version,
 | 
					      required this.version,
 | 
				
			||||||
      required this.start_time,
 | 
					      required this.start_time,
 | 
				
			||||||
@@ -16,6 +18,7 @@ class Build {
 | 
				
			|||||||
  factory Build.fromJson(Map<String, dynamic> json) {
 | 
					  factory Build.fromJson(Map<String, dynamic> json) {
 | 
				
			||||||
    return Build(
 | 
					    return Build(
 | 
				
			||||||
      id: json["id"] as int,
 | 
					      id: json["id"] as int,
 | 
				
			||||||
 | 
					      pkg_id: json["pkg_id"] as int,
 | 
				
			||||||
      status: json["status"] as int,
 | 
					      status: json["status"] as int,
 | 
				
			||||||
      start_time: json["start_time"] as int?,
 | 
					      start_time: json["start_time"] as int?,
 | 
				
			||||||
      end_time: json["end_time"] as int?,
 | 
					      end_time: json["end_time"] as int?,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import 'package:aurcache/api/builds.dart';
 | 
				
			||||||
 | 
					import 'package:aurcache/api/packages.dart';
 | 
				
			||||||
import 'package:aurcache/components/build_output.dart';
 | 
					import 'package:aurcache/components/build_output.dart';
 | 
				
			||||||
import 'package:aurcache/models/build.dart';
 | 
					import 'package:aurcache/models/build.dart';
 | 
				
			||||||
import 'package:aurcache/components/api/APIBuilder.dart';
 | 
					import 'package:aurcache/components/api/APIBuilder.dart';
 | 
				
			||||||
@@ -7,6 +9,7 @@ import 'package:flutter/material.dart';
 | 
				
			|||||||
import 'package:go_router/go_router.dart';
 | 
					import 'package:go_router/go_router.dart';
 | 
				
			||||||
import 'package:provider/provider.dart';
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import '../api/API.dart';
 | 
				
			||||||
import '../components/confirm_popup.dart';
 | 
					import '../components/confirm_popup.dart';
 | 
				
			||||||
import '../components/dashboard/chart_card.dart';
 | 
					import '../components/dashboard/chart_card.dart';
 | 
				
			||||||
import '../components/dashboard/your_packages.dart';
 | 
					import '../components/dashboard/your_packages.dart';
 | 
				
			||||||
@@ -57,7 +60,7 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
                        ],
 | 
					                        ],
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    _buildSideBar(),
 | 
					                    _buildSideBar(buildData),
 | 
				
			||||||
                  ],
 | 
					                  ],
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
              });
 | 
					              });
 | 
				
			||||||
@@ -159,7 +162,7 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Widget _buildSideBar() {
 | 
					  Widget _buildSideBar(Build buildData) {
 | 
				
			||||||
    return SizedBox(
 | 
					    return SizedBox(
 | 
				
			||||||
      width: 300,
 | 
					      width: 300,
 | 
				
			||||||
      child: Container(
 | 
					      child: Container(
 | 
				
			||||||
@@ -190,8 +193,9 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
                    final confirmResult = await showConfirmationDialog(
 | 
					                    final confirmResult = await showConfirmationDialog(
 | 
				
			||||||
                        context,
 | 
					                        context,
 | 
				
			||||||
                        "Delete Build",
 | 
					                        "Delete Build",
 | 
				
			||||||
                        "Are you sure to delete this Package?", () async {
 | 
					                        "Are you sure to delete this Package?", () {
 | 
				
			||||||
                      // todo delete build
 | 
					                      API.deleteBuild(widget.buildID);
 | 
				
			||||||
 | 
					                      context.pop();
 | 
				
			||||||
                    }, null);
 | 
					                    }, null);
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  child: const Text(
 | 
					                  child: const Text(
 | 
				
			||||||
@@ -204,7 +208,9 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
                ),
 | 
					                ),
 | 
				
			||||||
                ElevatedButton(
 | 
					                ElevatedButton(
 | 
				
			||||||
                  onPressed: () async {
 | 
					                  onPressed: () async {
 | 
				
			||||||
                    // todo api call and page redirect
 | 
					                    final buildid =
 | 
				
			||||||
 | 
					                        await API.updatePackage(id: buildData.pkg_id);
 | 
				
			||||||
 | 
					                    context.pushReplacement("/build/$buildid");
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  child: const Text(
 | 
					                  child: const Text(
 | 
				
			||||||
                    "Retry",
 | 
					                    "Retry",
 | 
				
			||||||
@@ -220,21 +226,21 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
            const SizedBox(
 | 
					            const SizedBox(
 | 
				
			||||||
              height: 5,
 | 
					              height: 5,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            Text(
 | 
					            const Text(
 | 
				
			||||||
              "Build Information:",
 | 
					              "Build Information:",
 | 
				
			||||||
              style: TextStyle(fontSize: 18),
 | 
					              style: TextStyle(fontSize: 18),
 | 
				
			||||||
              textAlign: TextAlign.start,
 | 
					              textAlign: TextAlign.start,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            SizedBox(
 | 
					            const SizedBox(
 | 
				
			||||||
              height: 20,
 | 
					              height: 20,
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            SideCard(
 | 
					            SideCard(
 | 
				
			||||||
              title: "Build Number",
 | 
					              title: "Build Number",
 | 
				
			||||||
              textRight: "7",
 | 
					              textRight: buildData.id.toString(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            SideCard(
 | 
					            SideCard(
 | 
				
			||||||
              title: "Finished",
 | 
					              title: "Finished",
 | 
				
			||||||
              textRight: "7",
 | 
					              textRight: buildData.end_time.toString(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            SideCard(
 | 
					            SideCard(
 | 
				
			||||||
              title: "Queued",
 | 
					              title: "Queued",
 | 
				
			||||||
@@ -242,7 +248,13 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
            SideCard(
 | 
					            SideCard(
 | 
				
			||||||
              title: "Duration",
 | 
					              title: "Duration",
 | 
				
			||||||
              textRight: "7",
 | 
					              textRight: (buildData.end_time != null
 | 
				
			||||||
 | 
					                      ? DateTime.fromMillisecondsSinceEpoch(
 | 
				
			||||||
 | 
					                          buildData.end_time! * 1000)
 | 
				
			||||||
 | 
					                      : DateTime.now())
 | 
				
			||||||
 | 
					                  .difference(DateTime.fromMillisecondsSinceEpoch(
 | 
				
			||||||
 | 
					                      buildData.start_time! * 1000))
 | 
				
			||||||
 | 
					                  .readableDuration(),
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,3 +18,21 @@ extension TimeFormatter on DateTime {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension DurationFormatter on Duration {
 | 
				
			||||||
 | 
					  String readableDuration() {
 | 
				
			||||||
 | 
					    if (inSeconds < 60) {
 | 
				
			||||||
 | 
					      return '$inSeconds second${inSeconds != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    } else if (inMinutes < 60) {
 | 
				
			||||||
 | 
					      return '$inMinutes minute${inMinutes != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    } else if (inHours < 24) {
 | 
				
			||||||
 | 
					      return '$inHours hour${inHours != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    } else if (inDays < 30) {
 | 
				
			||||||
 | 
					      return '$inDays day${inDays != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    } else if ((inDays / 30) < 12) {
 | 
				
			||||||
 | 
					      return '${inDays ~/ 30} month${(inDays ~/ 30) != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return '${inDays ~/ 365} year${(inDays ~/ 365) != 1 ? 's' : ''}';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user