From bc7153a060b7b2fc1463253cf91bcb4cdd54c102 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Sat, 3 Dec 2022 16:40:53 +0530 Subject: [PATCH] feat: add website from web UI closes: https://git.batsense.net/LibrePages/librepages/issues/4#issuecomment-752 --- src/pages/dash/sites/add.rs | 172 +++++++++++++++++++++++++++ src/pages/dash/sites/mod.rs | 32 +++++ src/pages/mod.rs | 1 + src/pages/routes.rs | 19 ++- templates/main.scss | 1 + templates/pages/dash/sites/add.html | 29 +++++ templates/pages/dash/sites/main.scss | 4 + 7 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 src/pages/dash/sites/add.rs create mode 100644 src/pages/dash/sites/mod.rs create mode 100644 templates/pages/dash/sites/add.html create mode 100644 templates/pages/dash/sites/main.scss diff --git a/src/pages/dash/sites/add.rs b/src/pages/dash/sites/add.rs new file mode 100644 index 0000000..1d3190a --- /dev/null +++ b/src/pages/dash/sites/add.rs @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +use std::cell::RefCell; + +use actix_identity::Identity; +use actix_web::http::header::ContentType; +use serde::{Deserialize, Serialize}; +use tera::Context; + +use super::get_auth_middleware; +use crate::ctx::api::v1::pages::AddSite; +use crate::pages::errors::*; +use crate::settings::Settings; +use crate::AppCtx; + +pub use super::*; + +pub const DASH_SITE_ADD: TemplateFile = + TemplateFile::new("dash_site_add", "pages/dash/sites/add.html"); + +pub struct Add { + ctx: RefCell, +} + +impl CtxError for Add { + fn with_error(&self, e: &ReadableError) -> String { + self.ctx.borrow_mut().insert(ERROR_KEY, e); + self.render() + } +} + +impl Add { + pub fn new(settings: &Settings) -> Self { + let ctx = RefCell::new(context(settings)); + Self { ctx } + } + + pub fn render(&self) -> String { + TEMPLATES + .render(DASH_SITE_ADD.name, &self.ctx.borrow()) + .unwrap() + } +} + +#[actix_web_codegen_const_routes::get(path = "PAGES.dash.site.add", wrap = "get_auth_middleware()")] +#[tracing::instrument(name = "Dashboard add site webpage", skip(ctx))] +pub async fn get_add_site(ctx: AppCtx) -> PageResult { + let add = Add::new(&ctx.settings).render(); + let html = ContentType::html(); + Ok(HttpResponse::Ok().content_type(html).body(add)) +} + +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +/// Data required to add site +pub struct TemplateAddSite { + pub repo_url: String, + pub branch: String, +} + +#[actix_web_codegen_const_routes::post( + path = "PAGES.dash.site.add", + wrap = "get_auth_middleware()" +)] +#[tracing::instrument(name = "Post Dashboard add site webpage", skip(ctx, id))] +pub async fn post_add_site( + ctx: AppCtx, + id: Identity, + payload: web::Form, +) -> PageResult { + let owner = id.identity().unwrap(); + let payload = payload.into_inner(); + let msg = AddSite { + branch: payload.branch, + repo_url: payload.repo_url, + owner, + }; + let _page = ctx + .add_site(msg) + .await + .map_err(|e| PageError::new(Add::new(&ctx.settings), e))?; + + // TODO: redirect to deployment view + + Ok(HttpResponse::Found() + .append_header((http::header::LOCATION, PAGES.dash.home)) + .finish()) +} + +pub fn services(cfg: &mut web::ServiceConfig) { + cfg.service(get_add_site); + cfg.service(post_add_site); +} + +#[cfg(test)] +mod tests { + use actix_web::http::StatusCode; + use actix_web::test; + + use crate::ctx::ArcCtx; + use crate::pages::dash::sites::add::TemplateAddSite; + use crate::tests; + use crate::*; + + use super::PAGES; + + #[actix_rt::test] + async fn postgres_dashboard_add_site_works() { + let (_, ctx) = tests::get_ctx().await; + dashboard_add_site_works(ctx.clone()).await; + } + + async fn dashboard_add_site_works(ctx: ArcCtx) { + const NAME: &str = "testdashaddsiteuser"; + const EMAIL: &str = "testdashaddsiteuser@foo.com"; + const PASSWORD: &str = "longpassword"; + + let _ = ctx.delete_user(NAME, PASSWORD).await; + let (_, signin_resp) = ctx.register_and_signin(NAME, EMAIL, PASSWORD).await; + let cookies = get_cookie!(signin_resp); + let app = get_app!(ctx).await; + + let resp = get_request!(&app, PAGES.dash.site.add, cookies.clone()); + assert_eq!(resp.status(), StatusCode::OK); + let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + assert!(res.contains("Add Site")); + + let payload = TemplateAddSite { + repo_url: tests::REPO_URL.into(), + branch: tests::BRANCH.into(), + }; + + let add_site = test::call_service( + &app, + post_request!(&payload, PAGES.dash.site.add, FORM) + .cookie(cookies.clone()) + .to_request(), + ) + .await; + assert_eq!(add_site.status(), StatusCode::FOUND); + let headers = add_site.headers(); + assert_eq!( + headers.get(actix_web::http::header::LOCATION).unwrap(), + &PAGES.dash.home + ); + + // let page = ctx.add_test_site(NAME.into()).await; + // + // let resp = get_request!(&app, PAGES.dash.home, cookies.clone()); + // assert_eq!(resp.status(), StatusCode::OK); + // let res = String::from_utf8(test::read_body(resp).await.to_vec()).unwrap(); + // println!("after adding site: {res}"); + // assert!(!res.contains("Nothing here")); + // assert!(res.contains(&page.domain)); + // assert!(res.contains(&page.repo)); + // + let _ = ctx.delete_user(NAME, PASSWORD).await; + } +} diff --git a/src/pages/dash/sites/mod.rs b/src/pages/dash/sites/mod.rs new file mode 100644 index 0000000..69c5191 --- /dev/null +++ b/src/pages/dash/sites/mod.rs @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 Aravinth Manivannan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +use actix_web::*; + +use super::get_auth_middleware; +pub use super::{context, Footer, TemplateFile, PAGES, PAYLOAD_KEY, TEMPLATES}; + +pub mod add; + +pub fn register_templates(t: &mut tera::Tera) { + add::DASH_SITE_ADD + .register(t) + .expect(add::DASH_SITE_ADD.name); +} + +pub fn services(cfg: &mut web::ServiceConfig) { + add::services(cfg); +} diff --git a/src/pages/mod.rs b/src/pages/mod.rs index b1bb3e7..bf9b571 100644 --- a/src/pages/mod.rs +++ b/src/pages/mod.rs @@ -166,6 +166,7 @@ mod tests { auth::register::REGISTER, errors::ERROR_TEMPLATE, super::dash::home::DASH_HOME, + super::dash::sites::add::DASH_SITE_ADD, ] .iter() { diff --git a/src/pages/routes.rs b/src/pages/routes.rs index 6c513a1..97d40fd 100644 --- a/src/pages/routes.rs +++ b/src/pages/routes.rs @@ -70,13 +70,30 @@ impl Auth { pub struct Dash { /// home route pub home: &'static str, + pub site: DashSite, } impl Dash { /// create new instance of Dash route pub const fn new() -> Dash { let home = "/dash"; - Dash { home } + let site = DashSite::new(); + Dash { home, site } + } +} + +#[derive(Serialize)] +/// Dashboard Site routes +pub struct DashSite { + /// home route + pub add: &'static str, +} + +impl DashSite { + /// create new instance of DashSite route + pub const fn new() -> DashSite { + let add = "/dash/site/add"; + DashSite { add } } } diff --git a/templates/main.scss b/templates/main.scss index cf3033c..8b913ee 100644 --- a/templates/main.scss +++ b/templates/main.scss @@ -2,6 +2,7 @@ @import "pages/auth/sass/main.scss"; @import "pages/auth/sass/form/main.scss"; @import "pages/dash/main.scss"; +@import "pages/dash/sites/main.scss"; @import "components/sass/footer/main.scss"; @import "components/nav/sass/main.scss"; diff --git a/templates/pages/dash/sites/add.html b/templates/pages/dash/sites/add.html new file mode 100644 index 0000000..097a1f6 --- /dev/null +++ b/templates/pages/dash/sites/add.html @@ -0,0 +1,29 @@ +{% extends 'base' %}{% block title %} Add Site{% endblock title %} {% block nav +%} {% include "auth_nav" %} {% endblock nav %} {% block main %} + +
+
+
+ + + + +
+ +
+
+
+
+ +{% endblock main %} diff --git a/templates/pages/dash/sites/main.scss b/templates/pages/dash/sites/main.scss new file mode 100644 index 0000000..e75d8c5 --- /dev/null +++ b/templates/pages/dash/sites/main.scss @@ -0,0 +1,4 @@ +.add-site__container { + max-width: 50%; + margin: auto; +}