Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: dozer ui and dozer ui update #2376

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions dozer-cli/src/cli/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,23 @@ pub enum Commands {
Security(Security),
#[command(about = "Deploy cloud applications")]
Cloud(Cloud),
#[command(about = "Run UI server")]
UI(UI),
}

#[derive(Debug, Args)]
pub struct UI {
#[command(subcommand)]
pub command: Option<UICommands>,
}

#[derive(Debug, Subcommand)]
pub enum UICommands {
#[command(
about = "Updates the latest UI code",
long_about = "Updates the latest UI code"
)]
Update,
}

#[derive(Debug, Args)]
Expand Down Expand Up @@ -121,11 +138,6 @@ pub enum RunCommands {
long_about = "Run lambda functions. Lambda functions are JavaScript or Python functions that are called when a new operation is output."
)]
Lambda,
#[command(
about = "Open web interface",
long_about = "Open web interface. Web interface is used to interact with dozer"
)]
AppUI,
}

#[derive(Debug, Args)]
Expand Down
36 changes: 27 additions & 9 deletions dozer-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use clap::Parser;
use dozer_api::shutdown;
use dozer_cli::cli::cloud::CloudCommands;
use dozer_cli::cli::types::{Cli, Commands, ConnectorCommand, RunCommands, SecurityCommands};
use dozer_cli::cli::types::{
Cli, Commands, ConnectorCommand, RunCommands, SecurityCommands, UICommands,
};
use dozer_cli::cli::{generate_config_repl, init_config};
use dozer_cli::cli::{init_dozer, list_sources};
use dozer_cli::cloud::{cloud_app_context::CloudAppContext, CloudClient, DozerGrpcCloudClient};
use dozer_cli::errors::{CliError, CloudError, OrchestrationError};
use dozer_cli::ui;
use dozer_cli::ui::app::AppUIError;
use dozer_cli::{set_ctrl_handler, set_panic_hook, ui::live};
use dozer_tracing::LabelsAndProgress;
use dozer_types::models::config::Config;
use dozer_types::models::telemetry::{TelemetryConfig, TelemetryMetricsConfig};
use dozer_types::tracing::{error, error_span, info};
use futures::stream::{AbortHandle, Abortable};
use futures::TryFutureExt;
use std::convert::identity;
use std::process;
use std::sync::Arc;
Expand Down Expand Up @@ -40,6 +44,7 @@ fn run() -> Result<(), OrchestrationError> {
set_panic_hook();

let config_res = init_configuration(&cli, runtime.clone());

// Now we have access to telemetry configuration. Telemetry must be initialized in tokio runtime.
let app_id = config_res
.as_ref()
Expand All @@ -61,6 +66,24 @@ fn run() -> Result<(), OrchestrationError> {

let _telemetry = runtime.block_on(async { Telemetry::new(app_id, &telemetry_config) });

// running UI does not require config to be loaded
if let Commands::UI(run) = &cli.cmd {
if let Some(UICommands::Update) = run.command {
runtime.block_on(
ui::downloader::fetch_latest_dozer_app_ui_code()
.map_err(AppUIError::DownloaderError),
)?;
info!("Run `dozer ui` to see the changes.");
} else {
runtime.block_on(ui::app::start_app_ui_server(
&runtime,
shutdown_receiver,
false,
))?;
}
return Ok(());
}

// Run Cloud
if let Commands::Cloud(cloud) = &cli.cmd {
return run_cloud(cloud, runtime, &cli);
Expand All @@ -85,14 +108,6 @@ fn run() -> Result<(), OrchestrationError> {
Some(RunCommands::Lambda) => {
dozer.runtime.block_on(dozer.run_lambda(shutdown_receiver))
}
Some(RunCommands::AppUI) => {
dozer.runtime.block_on(ui::app::start_app_ui_server(
&dozer.runtime,
shutdown_receiver,
false,
))?;
Ok(())
}
None => dozer
.runtime
.block_on(dozer.run_all(shutdown_receiver, run.locked)),
Expand Down Expand Up @@ -134,6 +149,9 @@ fn run() -> Result<(), OrchestrationError> {
.and_then(identity)
}),
Commands::Clean => dozer.clean(),
Commands::UI(_) => {
panic!("This should not happen as it is handled earlier");
}
Commands::Cloud(_) => {
panic!("This should not happen as it is handled earlier");
}
Expand Down
14 changes: 11 additions & 3 deletions dozer-cli/src/ui/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,24 @@ pub async fn start_app_ui_server(
let state = Arc::new(AppUIState::new());
state.set_sender(sender.clone()).await;
// Ignore if build fails
let _ = state.build(runtime.clone()).await;
let res = state.build(runtime.clone()).await;
if let Err(e) = res {
info!("Failed to build state : {}", e);
}
let state2: Arc<AppUIState> = state.clone();
if !disable_ui {
downloader::fetch_latest_dozer_app_ui_code().await?;
info!("Check if latest app ui code is available");
let already_exist = downloader::validate_if_dozer_app_ui_code_exists();
if !already_exist {
info!("There's no ui code folder, fetching latest app ui code");
downloader::fetch_latest_dozer_app_ui_code().await?;
}
let react_app_server: dozer_api::actix_web::dev::Server =
downloader::start_react_app(APP_UI_WEB_PORT, LOCAL_APP_UI_DIR)
.map_err(AppUIError::CannotStartUiServer)?;
tokio::spawn(react_app_server);
let browser_url: String = format!("http://localhost:{}", APP_UI_WEB_PORT);
info!("Starting ui on : {}", browser_url);
if webbrowser::open(&browser_url).is_err() {
info!("Failed to open browser. ");
}
Expand All @@ -54,6 +63,5 @@ pub async fn start_app_ui_server(
res.unwrap();
});
watcher::watch(runtime, state.clone(), shutdown).await?;

Ok(())
}
2 changes: 1 addition & 1 deletion dozer-cli/src/ui/app/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ impl AppUIState {
let mut lock = self.dozer.write().await;

let cli = Cli::parse();

let (config, _) = init_config(
cli.config_paths.clone(),
cli.config_token.clone(),
cli.config_overrides.clone(),
cli.ignore_pipe,
)
.await?;

let dozer = init_dozer(runtime, config, Default::default())?;

let contract = create_contract(dozer.clone()).await;
Expand Down
12 changes: 10 additions & 2 deletions dozer-cli/src/ui/downloader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ async fn fetch_dozer_ui(url: &str, folder_name: &str) -> Result<(), DownloaderEr
let prev_zip_file_name = existing_key.as_str();
if key_changed {
info!("Downloading latest file: {}", zip_file_name);

let base_url = &format!("{}/", url);
let zip_url = &(base_url.to_owned() + zip_file_name);
if !prev_zip_file_name.is_empty() {
delete_file_if_present(prev_zip_file_name, folder_name)?;
}
get_zip_from_url(zip_url, folder_name, zip_file_name).await?;
} else {
info!("Current file is up to date");
}

Ok(())
}
pub const LOCAL_APP_UI_DIR: &str = "local-app-ui";
Expand All @@ -67,6 +67,14 @@ pub async fn fetch_latest_dozer_app_ui_code() -> Result<(), DownloaderError> {
.await
}

pub fn validate_if_dozer_app_ui_code_exists() -> bool {
let directory_path = get_directory_path();
let file_path = Path::new(&directory_path)
.join(LOCAL_APP_UI_DIR)
.join("contents");
file_path.exists()
}

pub const LIVE_APP_UI_DIR: &str = "live-app-ui";
pub async fn fetch_latest_dozer_explorer_code() -> Result<(), DownloaderError> {
fetch_dozer_ui(
Expand Down
2 changes: 1 addition & 1 deletion dozer-cli/src/ui/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod app;
mod downloader;
pub mod downloader;
pub mod live;
Loading