11use anyhow:: Result ;
22
33use super :: state:: {
4- detail_state :: DetailState , events_state :: EventsState , modal_state :: ModalState ,
5- search_state:: SearchState , view_state:: ViewState ,
4+ claim_builder_state :: ClaimBuilderState , detail_state :: DetailState , events_state :: EventsState ,
5+ modal_state :: ModalState , search_state:: SearchState , view_state:: ViewState ,
66} ;
77use super :: utils:: NavItem ;
88use crate :: current_region_handler;
@@ -35,6 +35,8 @@ pub enum PendingAction {
3535 LoadJobLogs ( String ) ,
3636 ReapplyDeployment ( usize ) ,
3737 DestroyDeployment ( usize ) ,
38+ SaveClaimToFile ,
39+ RunClaimFromBuilder ,
3840}
3941
4042#[ derive( Debug , Clone ) ]
@@ -100,6 +102,7 @@ pub struct App {
100102 pub events_state : EventsState ,
101103 pub modal_state : ModalState ,
102104 pub search_state : SearchState ,
105+ pub claim_builder_state : ClaimBuilderState ,
103106
104107 // ==================== LEGACY FIELDS (TRANSITIONING) ====================
105108 // These are kept for backward compatibility during migration.
@@ -167,6 +170,7 @@ impl App {
167170 let events_state = EventsState :: new ( ) ;
168171 let modal_state = ModalState :: new ( ) ;
169172 let search_state = SearchState :: new ( ) ;
173+ let claim_builder_state = ClaimBuilderState :: new ( ) ;
170174
171175 Self {
172176 // Core app state
@@ -189,6 +193,7 @@ impl App {
189193 events_state,
190194 modal_state,
191195 search_state,
196+ claim_builder_state,
192197
193198 // Legacy fields - initialized from defaults for backward compatibility
194199 // View state
@@ -585,6 +590,12 @@ impl App {
585590 self . selected_index = index;
586591 self . destroy_deployment ( ) . await ?;
587592 }
593+ PendingAction :: SaveClaimToFile => {
594+ self . save_claim_to_file ( ) . await ?;
595+ }
596+ PendingAction :: RunClaimFromBuilder => {
597+ self . run_claim_from_builder ( ) . await ?;
598+ }
588599 }
589600
590601 Ok ( ( ) )
@@ -640,6 +651,12 @@ impl App {
640651 PendingAction :: DestroyDeployment ( _) => {
641652 self . set_loading ( "Destroying deployment..." ) ;
642653 }
654+ PendingAction :: SaveClaimToFile => {
655+ self . set_loading ( "Saving claim to file..." ) ;
656+ }
657+ PendingAction :: RunClaimFromBuilder => {
658+ self . set_loading ( "Running claim..." ) ;
659+ }
643660 }
644661 }
645662
@@ -2032,6 +2049,129 @@ impl App {
20322049 }
20332050 self . close_confirmation ( ) ;
20342051 }
2052+
2053+ /// Save the claim builder's generated YAML to a file
2054+ pub async fn save_claim_to_file ( & mut self ) -> Result < ( ) > {
2055+ use std:: fs;
2056+ use std:: path:: PathBuf ;
2057+
2058+ // Validate the form first
2059+ if let Err ( err) = self . claim_builder_state . validate ( ) {
2060+ self . detail_state
2061+ . show_error ( & format ! ( "Validation failed: {}" , err) ) ;
2062+ self . clear_loading ( ) ;
2063+ return Ok ( ( ) ) ;
2064+ }
2065+
2066+ // Generate the YAML
2067+ self . claim_builder_state . generate_yaml ( ) ;
2068+
2069+ // Create a filename based on deployment name
2070+ let deployment_name = if self . claim_builder_state . deployment_name . is_empty ( ) {
2071+ "deployment" . to_string ( )
2072+ } else {
2073+ self . claim_builder_state . deployment_name . clone ( )
2074+ } ;
2075+
2076+ let filename = format ! ( "{}.yaml" , deployment_name) ;
2077+ let mut filepath = PathBuf :: from ( "./" ) ;
2078+ filepath. push ( & filename) ;
2079+
2080+ // Write to file
2081+ match fs:: write ( & filepath, & self . claim_builder_state . generated_yaml ) {
2082+ Ok ( _) => {
2083+ self . detail_state
2084+ . show_message ( format ! ( "Claim saved to: {}" , filepath. display( ) ) ) ;
2085+ // Close the claim builder after successful save
2086+ self . claim_builder_state . close ( ) ;
2087+ }
2088+ Err ( e) => {
2089+ self . detail_state
2090+ . show_error ( & format ! ( "Failed to save claim: {}" , e) ) ;
2091+ }
2092+ }
2093+
2094+ self . clear_loading ( ) ;
2095+ Ok ( ( ) )
2096+ }
2097+
2098+ pub async fn run_claim_from_builder ( & mut self ) -> Result < ( ) > {
2099+ use crate :: utils:: get_environment;
2100+ use env_common:: logic:: run_claim;
2101+ use env_defs:: ExtraData ;
2102+
2103+ // Validate the form first
2104+ if let Err ( err) = self . claim_builder_state . validate ( ) {
2105+ self . detail_state
2106+ . show_error ( & format ! ( "Validation failed: {}" , err) ) ;
2107+ self . clear_loading ( ) ;
2108+ return Ok ( ( ) ) ;
2109+ }
2110+
2111+ // Generate the YAML
2112+ self . claim_builder_state . generate_yaml ( ) ;
2113+
2114+ // Parse the claim YAML
2115+ let yaml: serde_yaml:: Value =
2116+ match serde_yaml:: from_str ( & self . claim_builder_state . generated_yaml ) {
2117+ Ok ( y) => y,
2118+ Err ( e) => {
2119+ self . detail_state
2120+ . show_error ( & format ! ( "Failed to parse YAML: {}" , e) ) ;
2121+ self . clear_loading ( ) ;
2122+ return Ok ( ( ) ) ;
2123+ }
2124+ } ;
2125+
2126+ // Use the same environment handling as the CLI
2127+ let environment = get_environment ( "default" ) ;
2128+
2129+ let reference_fallback = match hostname:: get ( ) {
2130+ Ok ( hostname) => hostname. to_string_lossy ( ) . to_string ( ) ,
2131+ Err ( e) => {
2132+ self . detail_state
2133+ . show_error ( & format ! ( "Failed to get hostname: {}" , e) ) ;
2134+ self . clear_loading ( ) ;
2135+ return Ok ( ( ) ) ;
2136+ }
2137+ } ;
2138+
2139+ // Run the claim using current_region_handler (same as reapply_deployment)
2140+ let handler = current_region_handler ( ) . await ;
2141+ match run_claim (
2142+ & handler,
2143+ & yaml,
2144+ & environment,
2145+ "apply" ,
2146+ vec ! [ ] ,
2147+ ExtraData :: None ,
2148+ & reference_fallback,
2149+ )
2150+ . await
2151+ {
2152+ Ok ( ( job_id, deployment_id, _) ) => {
2153+ let message = format ! (
2154+ "✅ Claim applied successfully!\n \n Job ID: {}\n Deployment ID: {}\n Environment: {}" ,
2155+ job_id, deployment_id, environment
2156+ ) ;
2157+
2158+ self . detail_state . show_message ( message. clone ( ) ) ;
2159+
2160+ // Close the claim builder after successful run
2161+ self . claim_builder_state . close ( ) ;
2162+
2163+ // Reload deployments list
2164+ self . schedule_action ( PendingAction :: LoadDeployments ) ;
2165+ }
2166+ Err ( e) => {
2167+ let message = format ! ( "❌ Failed to run claim:\n \n {}" , e) ;
2168+ self . detail_state . show_message ( message) ;
2169+ }
2170+ }
2171+
2172+ self . clear_loading ( ) ;
2173+ Ok ( ( ) )
2174+ }
20352175}
20362176
20372177// Implement VersionItem trait for Module to work with VersionsModal widget
0 commit comments