diff --git a/nixin_farm/assets/views/base.html b/nixin_farm/assets/views/base.html new file mode 100644 index 0000000..d0d8c43 --- /dev/null +++ b/nixin_farm/assets/views/base.html @@ -0,0 +1,26 @@ + + + + + + {% block title %}{% endblock title %} + + + + {% block head %} + + {% endblock head %} + + + +
+ {% block content %} + {% endblock content %} +
+ + {% block js %} + + {% endblock js %} + + + \ No newline at end of file diff --git a/nixin_farm/assets/views/server/create.html b/nixin_farm/assets/views/server/create.html new file mode 100644 index 0000000..9dc318c --- /dev/null +++ b/nixin_farm/assets/views/server/create.html @@ -0,0 +1,54 @@ +{% extends "base.html" %} + +{% block title %} +Create server +{% endblock title %} + +{% block content %} +
+
+

Create new server

+
+
+ +
+ +
+
+ +
+ +
+
+
+ +
+
+
+{% endblock content %} + +{% block js %} + +{% endblock js %} \ No newline at end of file diff --git a/nixin_farm/assets/views/server/edit.html b/nixin_farm/assets/views/server/edit.html new file mode 100644 index 0000000..b2b8c7f --- /dev/null +++ b/nixin_farm/assets/views/server/edit.html @@ -0,0 +1,73 @@ +{% extends "base.html" %} + +{% block title %} +Edit server: {{ item.id }} +{% endblock title %} + +{% block content %} +

Edit server: {{ item.id }}

+
+
+
+
+ +
+ +
+
+ +
+ +
+
+
+ + +
+
+ +
+
+Back to server +
+{% endblock content %} + +{% block js %} + +{% endblock js %} \ No newline at end of file diff --git a/nixin_farm/assets/views/server/list.html b/nixin_farm/assets/views/server/list.html new file mode 100644 index 0000000..5e732dd --- /dev/null +++ b/nixin_farm/assets/views/server/list.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block title %} +List of server +{% endblock title %} + +{% block content %} +

server

+
+ {% for item in items %} +
+
+ +
+
+ +
+ Edit + View +
+ {% endfor %} + +
+
+ New server +
+{% endblock content %} diff --git a/nixin_farm/assets/views/server/show.html b/nixin_farm/assets/views/server/show.html new file mode 100644 index 0000000..aff640a --- /dev/null +++ b/nixin_farm/assets/views/server/show.html @@ -0,0 +1,19 @@ +{% extends "base.html" %} + +{% block title %} +View server: {{ item.id }} +{% endblock title %} + +{% block content %} +

View server: {{ item.id }}

+
+
+ +
+
+ +
+
+Back to servers +
+{% endblock content %} diff --git a/nixin_farm/migration/src/lib.rs b/nixin_farm/migration/src/lib.rs index 3352f5c..48f563c 100644 --- a/nixin_farm/migration/src/lib.rs +++ b/nixin_farm/migration/src/lib.rs @@ -5,6 +5,7 @@ pub use sea_orm_migration::prelude::*; mod m20220101_000001_users; mod m20231103_114510_notes; +mod m20241016_180911_servers; pub struct Migrator; #[async_trait::async_trait] @@ -13,6 +14,7 @@ impl MigratorTrait for Migrator { vec![ Box::new(m20220101_000001_users::Migration), Box::new(m20231103_114510_notes::Migration), + Box::new(m20241016_180911_servers::Migration), ] } -} +} \ No newline at end of file diff --git a/nixin_farm/migration/src/m20241016_180911_servers.rs b/nixin_farm/migration/src/m20241016_180911_servers.rs new file mode 100644 index 0000000..30a9518 --- /dev/null +++ b/nixin_farm/migration/src/m20241016_180911_servers.rs @@ -0,0 +1,37 @@ +use loco_rs::schema::table_auto_tz; +use sea_orm_migration::{prelude::*, schema::*}; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + table_auto_tz(Servers::Table) + .col(pk_auto(Servers::Id)) + .col(string_null(Servers::Name)) + .col(string_null(Servers::Domain)) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table(Table::drop().table(Servers::Table).to_owned()) + .await + } +} + +#[derive(DeriveIden)] +enum Servers { + Table, + Id, + Name, + Domain, + +} + + diff --git a/nixin_farm/src/app.rs b/nixin_farm/src/app.rs index 62d3c94..1c9a468 100644 --- a/nixin_farm/src/app.rs +++ b/nixin_farm/src/app.rs @@ -50,6 +50,7 @@ impl Hooks for App { fn routes(_ctx: &AppContext) -> AppRoutes { AppRoutes::with_default_routes() + .add_route(controllers::server::routes()) .add_route(controllers::notes::routes()) .add_route(controllers::auth::routes()) .add_route(controllers::user::routes()) @@ -75,4 +76,4 @@ impl Hooks for App { db::seed::(db, &base.join("notes.yaml").display().to_string()).await?; Ok(()) } -} +} \ No newline at end of file diff --git a/nixin_farm/src/controllers/mod.rs b/nixin_farm/src/controllers/mod.rs index 0a3d0b5..baf6605 100644 --- a/nixin_farm/src/controllers/mod.rs +++ b/nixin_farm/src/controllers/mod.rs @@ -1,3 +1,5 @@ pub mod auth; pub mod notes; pub mod user; + +pub mod server; \ No newline at end of file diff --git a/nixin_farm/src/controllers/server.rs b/nixin_farm/src/controllers/server.rs new file mode 100644 index 0000000..1de9dda --- /dev/null +++ b/nixin_farm/src/controllers/server.rs @@ -0,0 +1,115 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::unnecessary_struct_initialization)] +#![allow(clippy::unused_async)] +use loco_rs::prelude::*; +use serde::{Deserialize, Serialize}; +use sea_orm::{sea_query::Order, QueryOrder}; +use axum::debug_handler; + +use crate::{ + models::_entities::servers::{ActiveModel, Column, Entity, Model}, + views, +}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Params { + pub name: Option, + pub domain: Option, + } + +impl Params { + fn update(&self, item: &mut ActiveModel) { + item.name = Set(self.name.clone()); + item.domain = Set(self.domain.clone()); + } +} + +async fn load_item(ctx: &AppContext, id: i32) -> Result { + let item = Entity::find_by_id(id).one(&ctx.db).await?; + item.ok_or_else(|| Error::NotFound) +} + +#[debug_handler] +pub async fn list( + ViewEngine(v): ViewEngine, + State(ctx): State, +) -> Result { + let item = Entity::find() + .order_by(Column::Id, Order::Desc) + .all(&ctx.db) + .await?; + views::server::list(&v, &item) +} + +#[debug_handler] +pub async fn new( + ViewEngine(v): ViewEngine, + State(_ctx): State, +) -> Result { + views::server::create(&v) +} + +#[debug_handler] +pub async fn update( + Path(id): Path, + State(ctx): State, + Json(params): Json, +) -> Result { + let item = load_item(&ctx, id).await?; + let mut item = item.into_active_model(); + params.update(&mut item); + let item = item.update(&ctx.db).await?; + format::json(item) +} + +#[debug_handler] +pub async fn edit( + Path(id): Path, + ViewEngine(v): ViewEngine, + State(ctx): State, +) -> Result { + let item = load_item(&ctx, id).await?; + views::server::edit(&v, &item) +} + +#[debug_handler] +pub async fn show( + Path(id): Path, + ViewEngine(v): ViewEngine, + State(ctx): State, +) -> Result { + let item = load_item(&ctx, id).await?; + views::server::show(&v, &item) +} + +#[debug_handler] +pub async fn add( + ViewEngine(v): ViewEngine, + State(ctx): State, + Json(params): Json, +) -> Result { + let mut item = ActiveModel { + ..Default::default() + }; + params.update(&mut item); + let item = item.insert(&ctx.db).await?; + views::server::show(&v, &item) +} + +#[debug_handler] +pub async fn remove(Path(id): Path, State(ctx): State) -> Result { + load_item(&ctx, id).await?.delete(&ctx.db).await?; + format::empty() +} + +pub fn routes() -> Routes { + Routes::new() + .prefix("servers/") + .add("/", get(list)) + .add("/", post(add)) + .add("new", get(new)) + .add(":id", get(show)) + .add(":id/edit", get(edit)) + .add(":id", post(update)) + .add(":id", delete(remove)) +} diff --git a/nixin_farm/src/models/_entities/mod.rs b/nixin_farm/src/models/_entities/mod.rs index c04afbb..fa23d39 100644 --- a/nixin_farm/src/models/_entities/mod.rs +++ b/nixin_farm/src/models/_entities/mod.rs @@ -1,6 +1,7 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.0 pub mod prelude; pub mod notes; +pub mod servers; pub mod users; diff --git a/nixin_farm/src/models/_entities/notes.rs b/nixin_farm/src/models/_entities/notes.rs index a803353..0bf2b7c 100644 --- a/nixin_farm/src/models/_entities/notes.rs +++ b/nixin_farm/src/models/_entities/notes.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.0 use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; diff --git a/nixin_farm/src/models/_entities/prelude.rs b/nixin_farm/src/models/_entities/prelude.rs index 4d11019..2a9300a 100644 --- a/nixin_farm/src/models/_entities/prelude.rs +++ b/nixin_farm/src/models/_entities/prelude.rs @@ -1,4 +1,5 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.0 pub use super::notes::Entity as Notes; +pub use super::servers::Entity as Servers; pub use super::users::Entity as Users; diff --git a/nixin_farm/src/models/_entities/servers.rs b/nixin_farm/src/models/_entities/servers.rs new file mode 100644 index 0000000..7f1f434 --- /dev/null +++ b/nixin_farm/src/models/_entities/servers.rs @@ -0,0 +1,18 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.0 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "servers")] +pub struct Model { + pub created_at: DateTimeWithTimeZone, + pub updated_at: DateTimeWithTimeZone, + #[sea_orm(primary_key)] + pub id: i32, + pub name: Option, + pub domain: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} diff --git a/nixin_farm/src/models/_entities/users.rs b/nixin_farm/src/models/_entities/users.rs index 120b1a1..d5441bb 100644 --- a/nixin_farm/src/models/_entities/users.rs +++ b/nixin_farm/src/models/_entities/users.rs @@ -1,4 +1,4 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.0 use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; diff --git a/nixin_farm/src/models/mod.rs b/nixin_farm/src/models/mod.rs index 917969b..2622fcb 100644 --- a/nixin_farm/src/models/mod.rs +++ b/nixin_farm/src/models/mod.rs @@ -1,3 +1,4 @@ pub mod _entities; pub mod notes; pub mod users; +pub mod servers; diff --git a/nixin_farm/src/models/servers.rs b/nixin_farm/src/models/servers.rs new file mode 100644 index 0000000..cb875b7 --- /dev/null +++ b/nixin_farm/src/models/servers.rs @@ -0,0 +1,7 @@ +use sea_orm::entity::prelude::*; +use super::_entities::servers::{ActiveModel, Entity}; +pub type Servers = Entity; + +impl ActiveModelBehavior for ActiveModel { + // extend activemodel below (keep comment for generators) +} diff --git a/nixin_farm/src/views/mod.rs b/nixin_farm/src/views/mod.rs index f9bae3d..b8613a9 100644 --- a/nixin_farm/src/views/mod.rs +++ b/nixin_farm/src/views/mod.rs @@ -1,2 +1,4 @@ pub mod auth; pub mod user; + +pub mod server; \ No newline at end of file diff --git a/nixin_farm/src/views/server.rs b/nixin_farm/src/views/server.rs new file mode 100644 index 0000000..01e4ce3 --- /dev/null +++ b/nixin_farm/src/views/server.rs @@ -0,0 +1,39 @@ +use loco_rs::prelude::*; + +use crate::models::_entities::servers; + +/// Render a list view of servers. +/// +/// # Errors +/// +/// When there is an issue with rendering the view. +pub fn list(v: &impl ViewRenderer, items: &Vec) -> Result { + format::render().view(v, "server/list.html", data!({"items": items})) +} + +/// Render a single server view. +/// +/// # Errors +/// +/// When there is an issue with rendering the view. +pub fn show(v: &impl ViewRenderer, item: &servers::Model) -> Result { + format::render().view(v, "server/show.html", data!({"item": item})) +} + +/// Render a server create form. +/// +/// # Errors +/// +/// When there is an issue with rendering the view. +pub fn create(v: &impl ViewRenderer) -> Result { + format::render().view(v, "server/create.html", data!({})) +} + +/// Render a server edit form. +/// +/// # Errors +/// +/// When there is an issue with rendering the view. +pub fn edit(v: &impl ViewRenderer, item: &servers::Model) -> Result { + format::render().view(v, "server/edit.html", data!({"item": item})) +} diff --git a/nixin_farm/tests/models/mod.rs b/nixin_farm/tests/models/mod.rs index 5975988..22e060c 100644 --- a/nixin_farm/tests/models/mod.rs +++ b/nixin_farm/tests/models/mod.rs @@ -1 +1,3 @@ mod users; + +mod servers; \ No newline at end of file diff --git a/nixin_farm/tests/models/servers.rs b/nixin_farm/tests/models/servers.rs new file mode 100644 index 0000000..4ff12ef --- /dev/null +++ b/nixin_farm/tests/models/servers.rs @@ -0,0 +1,31 @@ +use nixin_farm::app::App; +use loco_rs::testing; +use serial_test::serial; + +macro_rules! configure_insta { + ($($expr:expr),*) => { + let mut settings = insta::Settings::clone_current(); + settings.set_prepend_module_to_snapshot(false); + let _guard = settings.bind_to_scope(); + }; +} + +#[tokio::test] +#[serial] +async fn test_model() { + configure_insta!(); + + let boot = testing::boot_test::().await.unwrap(); + testing::seed::(&boot.app_context.db).await.unwrap(); + + // query your model, e.g.: + // + // let item = models::posts::Model::find_by_pid( + // &boot.app_context.db, + // "11111111-1111-1111-1111-111111111111", + // ) + // .await; + + // snapshot the result: + // assert_debug_snapshot!(item); +}