From 756c31bad7486fbab9b054ab9255db0735a5311c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Berthaud-M=C3=BCller?= Date: Fri, 29 Apr 2022 18:04:12 +0200 Subject: [PATCH] wip frontend --- public/scripts/api.js | 4 +-- public/scripts/records.js | 27 ++++++++++++----- public/styles/main.css | 45 +++++++++++++++++++++-------- src/cli/server.rs | 1 + src/routes/ui/auth.rs | 4 +-- src/routes/ui/zones.rs | 48 ++++++++++++++++++++++++++----- templates/bases/app.html | 34 ++++++++++++++++++++++ templates/{ => bases}/base.html | 0 templates/macros.html | 11 +++++++ templates/{ => pages}/login.html | 2 +- templates/pages/zone/records.html | 45 +++++++++++++++++++++++++++++ templates/pages/zones.html | 3 ++ templates/zone/records.html | 18 ------------ 13 files changed, 193 insertions(+), 49 deletions(-) create mode 100644 templates/bases/app.html rename templates/{ => bases}/base.html (100%) create mode 100644 templates/macros.html rename templates/{ => pages}/login.html (92%) create mode 100644 templates/pages/zone/records.html create mode 100644 templates/pages/zones.html delete mode 100644 templates/zone/records.html diff --git a/public/scripts/api.js b/public/scripts/api.js index f142d02..6074991 100644 --- a/public/scripts/api.js +++ b/public/scripts/api.js @@ -9,12 +9,12 @@ function apiGet(url) { throw new Error('Not ok'); } return res.json(); - }) + }); } function getRecords(zone) { - return apiGet(`zones/${zone}/records`) + return apiGet(`zones/${zone}/records`); } export { diff --git a/public/scripts/records.js b/public/scripts/records.js index 8b36373..91da855 100644 --- a/public/scripts/records.js +++ b/public/scripts/records.js @@ -11,7 +11,7 @@ const rdataInputProperties = { MasterServerName: {label: 'serveur primaire', type: 'text'}, Expire: {label: 'expiration', type: 'number'}, Target: {label: 'cible', type: 'text'}, -} +}; const Editable = createContext(false); @@ -33,10 +33,10 @@ function RDataInput({ name, value = '', index = 0 }) { } else { return html`
- ${label}: - ${value} +
${label}:
+
${value}
- ` + `; } } } @@ -56,7 +56,20 @@ function Record({name, ttl, type, rdata, index = 0}) { ${name} ${type} ${ttl} - <${RData} rdata=${rdata} index=${index}/> + + <${Editable.Consumer}> + ${ + (editable) => { + if (editable) { + return html`<${RData} rdata=${rdata} index=${index}/>` + } else { + return html`
<${RData} rdata=${rdata} index=${index}/>
` + } + } + } + + + `; } @@ -70,13 +83,13 @@ function RecordList({ zone }) { useEffect(() => { getRecords(zone) .then((res) => setRecords(res)); - }, []) + }, []); return html` <${Editable.Provider} value=${editable}> - +
diff --git a/public/styles/main.css b/public/styles/main.css index 54e9aa5..b64b972 100644 --- a/public/styles/main.css +++ b/public/styles/main.css @@ -1,33 +1,43 @@ body { color: #2e2033; -} -.record-list { - border-collapse: collapse; + display: flex; + height: 100%; + width: 100%; + margin: 0; } -.record-list .rdata { +main { + flex-grow: 1; +} + +zone-content table { + border-collapse: collapse; + width: 100%; +} + +zone-content .rdata { display: flex; flex-wrap: wrap; } -.record-list th, .record-list td { +zone-content th, .zone-content td { font-weight: normal; text-align: left; vertical-align: top; padding: 0.25rem; } -.record-list thead { +zone-content thead { background: #ccb9ff; color: #39004d; } -.record-list tbody tr:nth-child(even) td { +zone-content tbody tr:nth-child(even) td { background: #ccb9ff3d; } -.record-list tbody tr .rdata span.label, -.record-list tbody tr .rdata label { +zone-content tbody tr .rdata dt, +zone-content tbody tr .rdata label { display: inline-block; padding: 0.1em 0.5em; background: #cecece; @@ -35,7 +45,18 @@ body { border-radius: 0.5em; margin-right: 0.1rem; } - -.record-list tbody tr .rdata > div { - margin: 0.1rem 0.5rem 0.1rem 0; +zone-content tbody tr .rdata dd { + margin: 0; } +zone-content tbody tr .rdata dl { + display: flex; + flex-wrap: wrap; + margin: 0; +} + +zone-content tbody tr .rdata div { + margin: 0.1rem 0.5rem 0.1rem 0; + display: flex; + align-items: baseline; +} + diff --git a/src/cli/server.rs b/src/cli/server.rs index 749b357..8d55109 100644 --- a/src/cli/server.rs +++ b/src/cli/server.rs @@ -102,6 +102,7 @@ impl NomiloCommand for RunServerCommand { .mount("/", routes![ ui::get_login_page, ui::post_login_page, + ui::get_zones_page, ui::get_zone_records_page, ]) .mount("/", static_files) diff --git a/src/routes/ui/auth.rs b/src/routes/ui/auth.rs index c73b138..21e7149 100644 --- a/src/routes/ui/auth.rs +++ b/src/routes/ui/auth.rs @@ -18,7 +18,7 @@ pub struct LoginPage { #[get("/login")] pub async fn get_login_page() -> Template<'static, LoginPage> { - Template::new("login.html", LoginPage { error: None }) + Template::new("pages/login.html", LoginPage { error: None }) } #[post("/login", data = "")] @@ -38,7 +38,7 @@ pub async fn post_login_page( match res { Ok(_) => Ok(Redirect::to(uri!("/zones"))), Err(models::UserError::BadCreds) => Err(Either::Left(Template::new( - "login.html", + "pages/login.html", LoginPage { error: Some("Identifants incorrects".to_string()) } diff --git a/src/routes/ui/zones.rs b/src/routes/ui/zones.rs index 9b24241..ff61bcf 100644 --- a/src/routes/ui/zones.rs +++ b/src/routes/ui/zones.rs @@ -1,5 +1,7 @@ +use serde_json::{Value, json}; use serde::Serialize; use rocket::http::{Status}; +use rocket::http::uri::Origin; use crate::template::Template; use crate::models; @@ -11,20 +13,52 @@ pub struct RecordsPage { zone: String } + +// TODO: Check if origin changes if application mounted on different path #[get("/zone//records")] -pub async fn get_zone_records_page(user_info: models::UserInfo, zone: models::AbsoluteName, conn: DbConn) -> Result, Status> { +pub async fn get_zone_records_page(user_info: models::UserInfo, zone: models::AbsoluteName, conn: DbConn, origin: &Origin<'_>) -> Result, Status> { let zone_name = zone.to_utf8(); - conn.run(move |c| { + let zones = conn.run(move |c| { if user_info.is_admin() { - models::Zone::get_by_name(c, &zone_name) + models::Zone::get_by_name(c, &zone_name)?; + models::Zone::get_all(c) } else { - user_info.get_zone(c, &zone_name) + user_info.get_zone(c, &zone_name)?; + user_info.get_zones(c) + } }).await.map_err(|e| models::ErrorResponse::from(e).status)?; - Ok(Template::new("zone/records.html", RecordsPage { - zone: zone.to_utf8(), - })) + Ok(Template::new( + "pages/zone/records.html", + json!({ + "current_zone": zone.to_utf8(), + "zones": zones, + "nav_page": origin.clone().into_normalized().path().as_str(), + "nav_sections": vec!["zones", zone.to_utf8().as_str()], + }) + )) +} + +#[get("/zones")] +pub async fn get_zones_page(user_info: models::UserInfo, conn: DbConn, origin: &Origin<'_>) -> Result, Status> { + let zones = conn.run(move |c| { + if user_info.is_admin() { + models::Zone::get_all(c) + } else { + user_info.get_zones(c) + } + }).await.map_err(|e| models::ErrorResponse::from(e).status)?; + + + Ok(Template::new( + "pages/zones.html", + json!({ + "zones": zones, + "nav_page": origin.clone().into_normalized().path().as_str(), + "nav_sections": vec!["zones"], + }) + )) } diff --git a/templates/bases/app.html b/templates/bases/app.html new file mode 100644 index 0000000..6a69255 --- /dev/null +++ b/templates/bases/app.html @@ -0,0 +1,34 @@ +{% extends "bases/base.html" %} +{% import "macros.html" as macros %} + +{% block content %} + +
+ {% block main %}{% endblock main %} +
+{% endblock content %} diff --git a/templates/base.html b/templates/bases/base.html similarity index 100% rename from templates/base.html rename to templates/bases/base.html diff --git a/templates/macros.html b/templates/macros.html new file mode 100644 index 0000000..8a8e3a5 --- /dev/null +++ b/templates/macros.html @@ -0,0 +1,11 @@ +{% macro nav_link(content, href, current_page, section=False, current_sections=False, props='') %} +{{ content }} +{% endmacro nav_link %} diff --git a/templates/login.html b/templates/pages/login.html similarity index 92% rename from templates/login.html rename to templates/pages/login.html index f6f65f8..9b8299a 100644 --- a/templates/login.html +++ b/templates/pages/login.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "bases/base.html" %} {% block title %}Login ⋅ {% endblock title %} diff --git a/templates/pages/zone/records.html b/templates/pages/zone/records.html new file mode 100644 index 0000000..be0f2e2 --- /dev/null +++ b/templates/pages/zone/records.html @@ -0,0 +1,45 @@ +{% extends "bases/app.html" %} +{% import "macros.html" as macros %} + +{% block title %}{{ current_zone }} ⋅ Records ⋅ {% endblock title %} + +{% block main %} +

Gestion la zone {{ current_zone }}

+ +
+

Enregistrements

+ + +
+ +{% endblock main %} + +{% block scripts %} + +{% endblock scripts %} diff --git a/templates/pages/zones.html b/templates/pages/zones.html new file mode 100644 index 0000000..016a96f --- /dev/null +++ b/templates/pages/zones.html @@ -0,0 +1,3 @@ +{% extends "bases/app.html" %} + +{% block title %}Zones ⋅ {% endblock title %} diff --git a/templates/zone/records.html b/templates/zone/records.html deleted file mode 100644 index f9f1c21..0000000 --- a/templates/zone/records.html +++ /dev/null @@ -1,18 +0,0 @@ -{% extends "base.html" %} - -{% block title %}{{ zone }} ⋅ Records ⋅ {% endblock title %} - -{% block content %} -
-{% endblock content %} - -{% block scripts %} - -{% endblock scripts %}
Nom