Skip to content

Commit

Permalink
feat: add ui for multiple subcomps
Browse files Browse the repository at this point in the history
  • Loading branch information
zabackary committed Nov 1, 2024
1 parent 3d8b2f1 commit 8444149
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 215 deletions.
1 change: 1 addition & 0 deletions src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod mapping;
pub mod network;
pub mod profile;
mod serializer;
pub mod sports;
pub mod stream;
8 changes: 1 addition & 7 deletions src/backend/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,12 +226,10 @@ pub struct Mapping {
impl Mapping {
pub fn map(
&self,
source_composition_name: &str,
source: &serde_json::Value,
exclude_incomplete_data: bool,
) -> Result<serde_json::Value, MapError> {
let source_map = source.as_object().ok_or(MapError::SourceNotMap)?;
let mut value = serde_json::Map::new();
// map could be underfilled if fields are disabled, but that's okay
let mut destination = serde_json::Map::with_capacity(self.items.len());
for item in &self.items {
Expand All @@ -251,11 +249,7 @@ impl Mapping {
Err(err) => return Err(err),
}
}
value.insert(
source_composition_name.to_string(),
serde_json::Value::Object(destination),
);
Ok(serde_json::Value::Object(value))
Ok(serde_json::Value::Object(destination))
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/backend/profile.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{de::Error, Deserialize, Serialize};
use serde_json::Value;

use super::{mapping::Mapping, sports::DynamicSportType};

Expand Down Expand Up @@ -90,7 +91,7 @@ impl Profile {
}

pub fn import(source: &str) -> Result<Self, serde_json::Error> {
let value = serde_json::Value::from(source);
let value = serde_json::from_str::<Value>(source)?;
let version = value
.as_object()
.ok_or(serde_json::Error::invalid_type(
Expand Down
25 changes: 25 additions & 0 deletions src/backend/serializer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use serde_json::{Map, Value};

use super::{mapping::MapError, profile::ProfileCompositionMapping};

// Same as in assets/root_composition_script.js
const APPLY_CHECKBOX_KEY: &str = "__APPLY_CHECKBOX";

pub fn serialize_mappings(
mappings: &Vec<ProfileCompositionMapping>,
source: &Value,
exclude_incomplete_data: bool,
) -> Result<Value, MapError> {
let mut map = Map::with_capacity(mappings.len());
for comp_mapping in mappings {
let mut mapped_obj = comp_mapping.mapping.map(&source, exclude_incomplete_data)?;
if let Some(ref key) = comp_mapping.enabled_checkbox_name {
mapped_obj
.as_object_mut()
.unwrap()
.insert(APPLY_CHECKBOX_KEY.to_owned(), Value::String(key.clone()));
}
map.insert(comp_mapping.subcomp_name.clone(), mapped_obj);
}
Ok(Value::Object(map))
}
12 changes: 4 additions & 8 deletions src/backend/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use tokio::{
};
use tokio_serial::SerialPortBuilderExt;

use crate::{mock::MockDataSource, APP_USER_AGENT};
use crate::{backend::serializer::serialize_mappings, mock::MockDataSource, APP_USER_AGENT};

use super::{network::put_to_server, profile::Profile};

Expand Down Expand Up @@ -152,9 +152,8 @@ impl ActiveStream {

let network_processing_join_handle = {
let serialized = serialized.clone();
let composition_name = profile.subcomp_name.clone();
let data_stream_url = profile.data_stream_url.clone();
let mapping = profile.mapping.clone();
let mappings = profile.mappings.clone();
let client = reqwest::Client::builder()
.user_agent(APP_USER_AGENT)
.http2_keep_alive_while_idle(true)
Expand All @@ -175,11 +174,8 @@ impl ActiveStream {
loop {
let serialized = { serialized.lock().await.take() };
if let Some(value) = serialized {
match mapping.map(
&composition_name,
&value,
profile.exclude_incomplete_data,
) {
match serialize_mappings(&mappings, &value, profile.exclude_incomplete_data)
{
Ok(serialized) => {
let stringified = serialized.to_string();
let stringified_bytes = stringified.as_bytes().len();
Expand Down
58 changes: 13 additions & 45 deletions src/frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod welcome;

use std::path::PathBuf;

use configure::{configure, ConfigureEvent};
use configure::{ConfigureMessage, ProfileConfigureExt};
use iced::border::Radius;
use iced::widget::{column, container, horizontal_space, row, scrollable, svg, text, text_input};
use iced::{Alignment, Element, Length, Subscription, Task};
Expand Down Expand Up @@ -72,14 +72,14 @@ pub enum Message {
ProfileNameChange(String),
UpdateStreamStats,
UpdateStreamStatsResponse(Vec<WorkerEvent>),
HandleConfigureEvent(ConfigureEvent),
CloseRequested,
Close,
SetUpTokenUpdated(String),
SetUpCopyScript,
SetUpOpenDataStreams,
SetUpOpenDashboard,

ProfileConfigureMessage(ConfigureMessage),
StreamRunningMessage(stream_running::StreamRunningMessage),
StreamStartMessage(stream_start::StreamStartMessage),
HeaderMessage(header::HeaderMessage),
Expand Down Expand Up @@ -333,44 +333,6 @@ impl DaktronicsSingularUiApp {
}
_ => Task::none(),
},
Message::HandleConfigureEvent(event) => {
self.profile_dirty = true;
match event {
ConfigureEvent::DataStreamUrlUpdated(new) => self.profile.data_stream_url = new,
ConfigureEvent::SubcompNameUpdated(new) => self.profile.subcomp_name = new,
ConfigureEvent::SportTypeUpdated(new) => {
self.sport_type_keys = new
.all_serialized_keys()
.expect("failed to get key list for sport");
self.profile.sport_type = Some(new)
}
ConfigureEvent::MultipleRequestsUpdated(new) => {
self.profile.multiple_requests = new
}
ConfigureEvent::ExcludeIncompleteDataUpdated(new) => {
self.profile.exclude_incomplete_data = new
}
ConfigureEvent::MappingItemAdded => {
self.profile.mapping.items.push(Default::default())
}
ConfigureEvent::MappingItemRemoved(i) => {
self.profile.mapping.items.remove(i);
}
ConfigureEvent::MappingItemEnabledUpdated(i, new) => {
self.profile.mapping.items[i].enabled = new
}
ConfigureEvent::MappingItemSourceFieldUpdated(i, new) => {
self.profile.mapping.items[i].source_field = new
}
ConfigureEvent::MappingItemTransformationUpdated(i, new) => {
self.profile.mapping.items[i].transformation = new
}
ConfigureEvent::MappingItemDestinationFieldUpdated(i, new) => {
self.profile.mapping.items[i].destination_field = new
}
};
Task::none()
}
Message::CloseRequested => {
let profile_dirty = self.profile_dirty;
let is_streaming = matches!(self.screen, Screen::StreamRunning(_, _));
Expand Down Expand Up @@ -427,6 +389,16 @@ impl DaktronicsSingularUiApp {
_ => Task::none(),
},

Message::ProfileConfigureMessage(message) => match self.profile.update(message) {
configure::Update::None => Task::none(),
configure::Update::RefreshSports(sport) => {
self.sport_type_keys = sport
.all_serialized_keys()
.expect("failed to get key list for sport");
self.profile.sport_type = Some(sport);
Task::none()
}
},
Message::HeaderMessage(message) => match self.header.update(message) {
// TODO: many of these messages can just be moved here.
header::Update::None => Task::none(),
Expand Down Expand Up @@ -570,11 +542,7 @@ impl DaktronicsSingularUiApp {
.map(Message::HeaderMessage)
},
match &self.screen {
Screen::Configure => configure(
&self.profile,
&self.sport_type_keys,
Message::HandleConfigureEvent,
)
Screen::Configure => self.profile.view(&self.sport_type_keys).map(Message::ProfileConfigureMessage)
.into(),
Screen::SetUp(public_token) => container(
scrollable(
Expand Down
Loading

0 comments on commit 8444149

Please sign in to comment.