From 7208269be13d0ee27fd696fcae31330e2a78b969 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 19 Sep 2024 23:33:17 +0200 Subject: Add content to settings page --- src/config.rs | 63 +++++++++++++++++++++++++++++++++++++-- src/ui.rs | 79 ++++++++++++++++--------------------------------- templates/head.html | 2 +- templates/settings.html | 76 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 156 insertions(+), 64 deletions(-) diff --git a/src/config.rs b/src/config.rs index 3e0571d..54f94dd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -2,16 +2,75 @@ use std::fs; use anyhow::Context; use serde::{Deserialize, Serialize}; +type Protection = u8; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Service { + pub sid: u32, + pub ecc: u8, + pub label: String, + pub shortlabel: String, + pub input_port: u16, + pub bitrate: u32, + pub protection: Protection, +} + +impl Service { + pub fn sid_hex(&self) -> String { + format!("{:04X}", self.sid) + } + + pub fn ecc_hex(&self) -> String { + format!("{:02X}", self.ecc) + } +} #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Config { - pub name: String, + pub instance_name: String, + pub tist: bool, + pub tist_offset: i32, + // TODO tai_clock_bulletins + pub ensemble_id: u16, + pub ensemble_ecc: u8, + pub ensemble_label: String, + pub ensemble_shortlabel: String, + pub output_edi_port: u16, + pub services: Vec, +} + +impl Config { + pub fn ensemble_id_hex(&self) -> String { + format!("{:04X}", self.ensemble_id) + } + + pub fn ensemble_ecc_hex(&self) -> String { + format!("{:02X}", self.ensemble_ecc) + } } impl Default for Config { fn default() -> Self { Config { - name: "CHANGEME".to_owned(), + instance_name: "CHANGEME".to_owned(), + tist: true, + tist_offset: 0, + ensemble_id: 0x4FFF, + ensemble_ecc: 0xE1, + ensemble_label: "OpenDigitalRadio".to_owned(), + ensemble_shortlabel: "ODR".to_owned(), + output_edi_port: 8951, + services: vec![ + Service { + sid: 0x4DAA, + ecc: 0xE1, + label: "nothing".to_owned(), + shortlabel: "no".to_owned(), + input_port: 9001, + bitrate: 128, + protection: 2 + } + ], } } } diff --git a/src/ui.rs b/src/ui.rs index 529dfa6..914d289 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -22,7 +22,8 @@ use crate::SharedState; pub async fn serve(port: u16, shared_state: SharedState) { let app = Router::new() .route("/", get(dashboard)) - .route("/settings", get(show_settings).post(post_settings)) + .route("/settings", get(show_settings)) + .route("/api/settings", post(post_settings)) .nest_service("/static", ServeDir::new("static")) /* For an example for timeouts and tracing, have a look at the git history */ .with_state(shared_state); @@ -45,7 +46,7 @@ impl ActivePage { fn styles(&self) -> Vec<&'static str> { match self { ActivePage::Dashboard => vec![], - ActivePage::Settings => vec![], + ActivePage::Settings => vec!["settings.js", "main.js"], ActivePage::None => vec![], } } @@ -99,60 +100,32 @@ struct SettingsAppliedTemplate<'a> { error_reason: String, } -#[derive(Deserialize, Debug)] -struct FormConfig { - name: String, -} - -impl TryFrom for config::Config { - type Error = anyhow::Error; - - fn try_from(value: FormConfig) -> Result { - Ok(config::Config { - name: value.name, - }) - } -} - async fn post_settings( State(state): State, - Form(input): Form) -> (StatusCode, SettingsAppliedTemplate<'static>) { - match config::Config::try_from(input) { - Ok(c) => { - match c.store() { - Ok(()) => { - state.lock().unwrap().conf.clone_from(&c); - - (StatusCode::OK, SettingsAppliedTemplate { - title: "Settings", - conf: c, - page: ActivePage::None, - ok: true, - error_message: "", - error_reason: "".to_owned(), - }) - } - Err(e) => { - (StatusCode::INTERNAL_SERVER_ERROR, SettingsAppliedTemplate { - title: "Settings", - conf : c, - page: ActivePage::None, - ok: false, - error_message: "Failed to store config", - error_reason: e.to_string(), - }) - }, - } - }, + Json(conf): Json) -> (StatusCode, SettingsAppliedTemplate<'static>) { + + match conf.store() { + Ok(()) => { + state.lock().unwrap().conf.clone_from(&conf); + + (StatusCode::OK, SettingsAppliedTemplate { + title: "Settings", + conf, + page: ActivePage::None, + ok: true, + error_message: "", + error_reason: "".to_owned(), + }) + } Err(e) => { - (StatusCode::BAD_REQUEST, SettingsAppliedTemplate { - title: "Settings", - conf: state.lock().unwrap().conf.clone(), - page: ActivePage::None, - ok: false, - error_message: "Error interpreting POST data", - error_reason: e.to_string(), - }) + (StatusCode::INTERNAL_SERVER_ERROR, SettingsAppliedTemplate { + title: "Settings", + conf, + page: ActivePage::None, + ok: false, + error_message: "Failed to store config", + error_reason: e.to_string(), + }) }, } } diff --git a/templates/head.html b/templates/head.html index 47b314f..7a2e5bb 100644 --- a/templates/head.html +++ b/templates/head.html @@ -16,7 +16,7 @@
diff --git a/templates/settings.html b/templates/settings.html index 8a7d56e..dfe71cf 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -1,15 +1,75 @@ {% include "head.html" %}

ODR-DabMux Settings

-
-
-
- General -
-
-
-
+

General

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + +
+
+ + +
+
+
+ +
+ {% for srv in conf.services %} +

+ + + + + + + + +

+ {% endfor %} +
+ +
+
+ +
{% include "foot.html" %} {# vi:set et sw=2 ts=2: #} -- cgit v1.2.3