shared/screens/select_org_bucket_measurements/
mod.rsuse crux_core::Command;
use crux_http::http::Url;
use crux_http::Response;
use log::{error, trace, Level};
use serde::{Deserialize, Serialize};
use crate::{ Effect, Event};
use crate::internal_error_strings::{N050_USED};
use crate::screens::initial::InitialScreenData;
use crate::screens::select_org_bucket_measurements::flux_get_buckets_existing_measurements::flux_get_buckets_existing_measurements;
use crate::screens::select_org_bucket_measurements::flux_get_buckets_existing_measurements_response::flux_get_buckets_existing_measurements_response;
use crate::screens::select_org_bucket_measurements::influx_get_orgs::influx_get_orgs;
use crate::screens::select_org_bucket_measurements::influx_get_orgs_response::{influx_get_orgs_response, Org, OrgsResult};
use crate::screens::select_org_bucket_measurements::set_bucket::set_bucket;
use crate::screens::select_org_bucket_measurements::set_measurement::set_measurement;
use crate::screens::select_org_bucket_measurements::set_org::set_org;
use crate::screens_common::influx::flux_call;
use crate::model::{Model, Screens, UserMessages};
use crate::model_ui::screens_common::remote_multi_choice::multi_choice::UiStringIndex;
use crate::screens::input_fields_and_tags::{LoadingResource, RemoteResource};
use crate::screens::input_fields_and_tags::RemoteResource::{Loaded};
use crate::screens::select_org_bucket_measurements::back_button_clicked::back_button_clicked;
use crate::screens::select_org_bucket_measurements::confirm_input_change_on_measurements::confirm_input_change_on_measurements;
use crate::screens::select_org_bucket_measurements::influx_get_buckets::influx_get_buckets;
use crate::screens::select_org_bucket_measurements::influx_get_buckets_response::influx_get_buckets_response;
use crate::screens::select_org_bucket_measurements::move_to_next_screen::move_to_next_screen;
use crate::screens::select_org_bucket_measurements::user_set_measurement::user_set_measurement;
use crate::screens_common::model::multi_choice::MultiChoice;
use crate::screens_common::model::user_input_or_multi_choice::UserInputOrMultiChoice;
use crate::screens_common::requests::BucketsResult;
mod back_button_clicked;
mod confirm_input_change_on_measurements;
mod flux_get_buckets_existing_measurements;
mod flux_get_buckets_existing_measurements_response;
mod influx_get_buckets;
mod influx_get_buckets_response;
pub mod influx_get_orgs;
pub mod influx_get_orgs_response;
mod move_to_next_screen;
pub mod set_bucket;
mod set_measurement;
mod set_org;
mod user_set_measurement;
#[derive(Clone, Debug)]
pub struct SelectOrgBucketMeasurementScreenData {
pub api_token: String,
pub base_url: Url,
pub orgs: RemoteResource<MultiChoice<Org>>,
pub buckets: RemoteResource<MultiChoice<String>>,
pub measurements: UserInputOrMultiChoice,
}
pub(crate) fn validate_measurement_string(value: &str) -> Result<(), String> {
if value.trim().contains(' ') {
return Err("Cannot contain spaces".to_owned());
}
Ok(())
}
impl TryFrom<&mut InitialScreenData> for SelectOrgBucketMeasurementScreenData {
type Error = ();
fn try_from(value: &mut InitialScreenData) -> Result<Self, Self::Error> {
trace!("validate base_url");
let Ok(base_url) = Url::parse(value.base_url.as_ref().ok_or(())?) else {
return Err(());
};
trace!("validate api_token");
let Some(api_token) = &value.api_token else {
return Err(());
};
Ok(SelectOrgBucketMeasurementScreenData {
api_token: api_token.to_string(),
base_url,
orgs: Default::default(),
buckets: Default::default(),
measurements: UserInputOrMultiChoice {
options: RemoteResource::NotLoaded(LoadingResource {
retry_count: 0,
failure_reasons: vec![],
current_state: Default::default(),
}),
selected: None,
notify_user_of_mode_switch: None,
user_validating_function: validate_measurement_string,
},
})
}
}
impl SelectOrgBucketMeasurementScreenData {
pub fn flux_call<F>(
&self,
flux_query: String,
user_messages: &mut UserMessages,
event_to_send: F,
) -> Command<Effect, Event>
where
F: FnOnce(crux_http::Result<Response<String>>) -> Event + Send + 'static,
{
let Loaded(multi_orgs) = &self.orgs else {
error!("orgs value was not loaded, unable to make flux call");
user_messages.error_report_to_developer(N050_USED);
return crux_core::render::render();
};
let Some(org) = multi_orgs.selected_as_option() else {
error!("No org selected");
user_messages.add_message(
"No org selected. Please select an org before getting buckets/measurements",
Level::Error,
);
return crux_core::render::render();
};
flux_call(
user_messages,
&org,
&self.base_url,
&self.api_token,
flux_query,
event_to_send,
)
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum ScEvSelectOrgBucketMeasurement {
BackButtonClicked,
FluxGetBucketsExistingMeasurements,
#[serde(skip)]
FluxGetBucketsExistingMeasurementsResponse(crux_http::Result<Response<String>>),
InfluxGetOrgs,
#[serde(skip)]
InfluxGetOrgsResponse(crux_http::Result<Response<OrgsResult>>),
InfluxGetBuckets,
#[serde(skip)]
InfluxGetBucketsResponse(crux_http::Result<Response<BucketsResult>>),
SetBucket(UiStringIndex),
SelectMeasurement(UiStringIndex),
UserSetMeasurement(String),
ConfirmInputChangeOnMeasurements(ConfirmUndo, DontShowDialogAgain),
SetOrg(UiStringIndex),
MoveToNextScreen,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum ConfirmUndo {
Undo,
Confirm,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum DontShowDialogAgain {
KeepShowing,
SavePreference,
}
pub fn select_org_bucket_measurement_screen_events(
initial_screen_event: ScEvSelectOrgBucketMeasurement,
model: &mut Model,
) -> Command<Effect, Event> {
trace!("select org,bucket,measurement screen event: Validating model");
let Screens::SelectOrgBucketMeasurementScreen(ref mut screen_model) = model.screen else {
error!("Screen was in an unexpected state {:?}", model.screen);
model
.user_messages
.add_message("Unrecoverable internal error state", Level::Error);
return crux_core::render::render();
};
trace!("Running select org,bucket,measurement event");
match initial_screen_event {
ScEvSelectOrgBucketMeasurement::FluxGetBucketsExistingMeasurements => {
flux_get_buckets_existing_measurements(
screen_model,
&mut model.user_messages,
&model.example_data,
)
}
ScEvSelectOrgBucketMeasurement::FluxGetBucketsExistingMeasurementsResponse(response) => {
flux_get_buckets_existing_measurements_response(screen_model, response)
}
ScEvSelectOrgBucketMeasurement::InfluxGetOrgs => {
influx_get_orgs(screen_model, &model.example_data)
}
ScEvSelectOrgBucketMeasurement::InfluxGetOrgsResponse(response) => {
influx_get_orgs_response(screen_model, response, &mut model.user_messages)
}
ScEvSelectOrgBucketMeasurement::SetBucket(bucket) => set_bucket(
screen_model,
&mut model.user_messages,
bucket,
&model.example_data,
),
ScEvSelectOrgBucketMeasurement::SelectMeasurement(measurement) => {
set_measurement(screen_model, &mut model.user_messages, measurement)
}
ScEvSelectOrgBucketMeasurement::SetOrg(org) => {
set_org(&mut screen_model.orgs, &mut model.user_messages, org)
}
ScEvSelectOrgBucketMeasurement::UserSetMeasurement(value) => {
user_set_measurement(&mut screen_model.measurements, value)
}
ScEvSelectOrgBucketMeasurement::ConfirmInputChangeOnMeasurements(confirm_undo, dialog) => {
confirm_input_change_on_measurements(
screen_model,
&mut model.user_messages,
confirm_undo,
dialog,
)
}
ScEvSelectOrgBucketMeasurement::MoveToNextScreen => move_to_next_screen(
&mut model.screen,
&mut model.user_messages,
&model.example_data,
),
ScEvSelectOrgBucketMeasurement::BackButtonClicked => back_button_clicked(model),
ScEvSelectOrgBucketMeasurement::InfluxGetBuckets => {
influx_get_buckets(screen_model, &model.example_data, &mut model.user_messages)
}
ScEvSelectOrgBucketMeasurement::InfluxGetBucketsResponse(data) => {
influx_get_buckets_response(screen_model, &mut model.user_messages, data)
}
}
}
#[cfg(test)]
impl Default for SelectOrgBucketMeasurementScreenData {
fn default() -> Self {
SelectOrgBucketMeasurementScreenData {
api_token: "".to_string(),
base_url: Url::parse("http://notaurl.com").unwrap(),
orgs: Default::default(),
buckets: Default::default(),
measurements: UserInputOrMultiChoice {
options: RemoteResource::default(),
selected: None,
notify_user_of_mode_switch: None,
user_validating_function: validate_measurement_string,
},
}
}
}