feat: redesign cli ux progress
This commit is contained in:
parent
ab60ee641f
commit
c63b2917da
21 changed files with 994 additions and 99 deletions
|
|
@ -4,7 +4,13 @@ use aim_core::domain::update::UpdateExecutionStatus;
|
|||
use crate::DispatchResult;
|
||||
|
||||
pub fn render_update_summary(total: usize, selected: usize, failed: usize) -> String {
|
||||
format!("updates found: {total}, selected: {selected}, failed: {failed}",)
|
||||
[
|
||||
crate::ui::theme::heading("Update Review"),
|
||||
format!("apps with updates: {total}"),
|
||||
format!("selected: {selected}"),
|
||||
format!("failed: {failed}"),
|
||||
]
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
pub fn render_dispatch_result(result: &DispatchResult) -> String {
|
||||
|
|
@ -13,9 +19,7 @@ pub fn render_dispatch_result(result: &DispatchResult) -> String {
|
|||
DispatchResult::List(rows) => render_list(rows),
|
||||
DispatchResult::PendingAdd(plan) => render_pending_add(plan),
|
||||
DispatchResult::Removed(removed) => render_removed_app(removed),
|
||||
DispatchResult::UpdatePlan(plan) => {
|
||||
render_update_summary(plan.items.len(), plan.items.len(), 0)
|
||||
}
|
||||
DispatchResult::UpdatePlan(plan) => render_update_plan(plan),
|
||||
DispatchResult::Updated(result) => render_updated_apps(result),
|
||||
DispatchResult::Noop => String::new(),
|
||||
}
|
||||
|
|
@ -31,46 +35,68 @@ fn render_added_app(added: &aim_core::app::add::InstalledApp) -> String {
|
|||
.warnings
|
||||
.iter()
|
||||
.chain(added.install_outcome.warnings.iter())
|
||||
.map(|warning| format!("warning: {warning}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
.map(|warning| format!("Warning: {warning}"))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let summary = format!(
|
||||
"installing as {scope}\ninstalled app: {} ({})\nsource: {} {}\nselected artifact: {} [{}]",
|
||||
added.record.display_name,
|
||||
added.record.stable_id,
|
||||
added.source.kind.as_str(),
|
||||
added.source.locator,
|
||||
added.selected_artifact.url,
|
||||
added.selected_artifact.selection_reason,
|
||||
);
|
||||
let mut lines = vec![
|
||||
crate::ui::theme::heading("Installation Summary"),
|
||||
format!(
|
||||
"{} {} ({})",
|
||||
crate::ui::theme::label("Application"),
|
||||
added.record.display_name,
|
||||
added.record.stable_id,
|
||||
),
|
||||
format!("{} {scope}", crate::ui::theme::label("Install scope")),
|
||||
format!(
|
||||
"{} {} {}",
|
||||
crate::ui::theme::label("Source"),
|
||||
added.source.kind.as_str(),
|
||||
added.source.locator,
|
||||
),
|
||||
format!(
|
||||
"{} {} [{}]",
|
||||
crate::ui::theme::label("Selected artifact"),
|
||||
added.selected_artifact.url,
|
||||
added.selected_artifact.selection_reason,
|
||||
),
|
||||
];
|
||||
|
||||
if warning_lines.is_empty() {
|
||||
summary
|
||||
} else {
|
||||
format!("{summary}\n{warning_lines}")
|
||||
}
|
||||
lines.extend(warning_lines);
|
||||
lines.join("\n")
|
||||
}
|
||||
|
||||
fn render_pending_add(plan: &AddPlan) -> String {
|
||||
let prompts = crate::ui::prompt::render_interactions(&plan.interactions);
|
||||
format!(
|
||||
"resolved source: {} {}\nselected artifact: {} [{}]\n{prompts}",
|
||||
plan.resolution.source.kind.as_str(),
|
||||
plan.resolution.source.locator,
|
||||
plan.selected_artifact.url,
|
||||
plan.selected_artifact.selection_reason,
|
||||
)
|
||||
[
|
||||
crate::ui::theme::heading("Installation Review"),
|
||||
format!(
|
||||
"{} {} {}",
|
||||
crate::ui::theme::label("Resolved source"),
|
||||
plan.resolution.source.kind.as_str(),
|
||||
plan.resolution.source.locator,
|
||||
),
|
||||
format!(
|
||||
"{} {} [{}]",
|
||||
crate::ui::theme::label("Selected artifact"),
|
||||
plan.selected_artifact.url,
|
||||
plan.selected_artifact.selection_reason,
|
||||
),
|
||||
prompts,
|
||||
]
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
fn render_list(rows: &[aim_core::app::list::ListRow]) -> String {
|
||||
if rows.is_empty() {
|
||||
return "installed apps: none".to_owned();
|
||||
return crate::ui::theme::muted("No installed apps yet");
|
||||
}
|
||||
|
||||
let mut output = String::from("installed apps:\n");
|
||||
let mut output = format!("{}\n", crate::ui::theme::heading("Installed Apps"));
|
||||
for row in rows {
|
||||
output.push_str(&format!("- {} ({})\n", row.display_name, row.stable_id));
|
||||
output.push_str(&format!(
|
||||
"{}\n",
|
||||
crate::ui::theme::bullet(&format!("{} ({})", row.display_name, row.stable_id))
|
||||
));
|
||||
}
|
||||
output.trim_end().to_owned()
|
||||
}
|
||||
|
|
@ -79,36 +105,38 @@ fn render_removed_app(removed: &aim_core::app::remove::RemovalResult) -> String
|
|||
let warning_lines = removed
|
||||
.warnings
|
||||
.iter()
|
||||
.map(|warning| format!("warning: {warning}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let summary = format!("removed: {}", removed.removed.display_name);
|
||||
|
||||
if warning_lines.is_empty() {
|
||||
summary
|
||||
} else {
|
||||
format!("{summary}\n{warning_lines}")
|
||||
}
|
||||
.map(|warning| format!("Warning: {warning}"))
|
||||
.collect::<Vec<_>>();
|
||||
let mut lines = vec![
|
||||
crate::ui::theme::heading("Removal Summary"),
|
||||
format!(
|
||||
"{} {}",
|
||||
crate::ui::theme::label("Removed app"),
|
||||
removed.removed.display_name,
|
||||
),
|
||||
];
|
||||
lines.extend(warning_lines);
|
||||
lines.join("\n")
|
||||
}
|
||||
|
||||
fn render_updated_apps(result: &aim_core::domain::update::UpdateExecutionResult) -> String {
|
||||
let mut lines = vec![format!(
|
||||
"updated apps: {}, failed: {}",
|
||||
result.updated_count(),
|
||||
result.failed_count()
|
||||
)];
|
||||
let mut lines = vec![
|
||||
crate::ui::theme::heading("Update Summary"),
|
||||
format!("updated apps: {}", result.updated_count()),
|
||||
format!("failed updates: {}", result.failed_count()),
|
||||
];
|
||||
|
||||
for item in &result.items {
|
||||
match &item.status {
|
||||
UpdateExecutionStatus::Updated => lines.push(format!(
|
||||
"updated: {} ({}) {} -> {}",
|
||||
"Updated: {} ({}) {} -> {}",
|
||||
item.display_name,
|
||||
item.stable_id,
|
||||
item.from_version.as_deref().unwrap_or("unknown"),
|
||||
item.to_version.as_deref().unwrap_or("unknown")
|
||||
)),
|
||||
UpdateExecutionStatus::Failed { reason } => lines.push(format!(
|
||||
"failed: {} ({}) {}",
|
||||
"Failed: {} ({}) {}",
|
||||
item.display_name, item.stable_id, reason
|
||||
)),
|
||||
}
|
||||
|
|
@ -116,3 +144,16 @@ fn render_updated_apps(result: &aim_core::domain::update::UpdateExecutionResult)
|
|||
|
||||
lines.join("\n")
|
||||
}
|
||||
|
||||
fn render_update_plan(plan: &aim_core::domain::update::UpdatePlan) -> String {
|
||||
let mut lines = vec![render_update_summary(plan.items.len(), plan.items.len(), 0)];
|
||||
|
||||
for item in &plan.items {
|
||||
lines.push(format!(
|
||||
"{} ({}) via {}",
|
||||
item.display_name, item.stable_id, item.selected_channel.locator
|
||||
));
|
||||
}
|
||||
|
||||
lines.join("\n")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue