@@ -537,6 +537,148 @@ export const priceEstimatorStore = reactive({
537537 const storageSum = this . calculateTotalStorageCost ( )
538538 console . log ( "SUMMARY" , storageSum )
539539 summary . allStorage = storageSum
540+ console . log ( "FINAL SUMMARY" , summary )
540541 return summary
541542 } ,
543+
544+ exportItems ( ) {
545+ const labsToExport = this . labs . map ( lab => ( {
546+ id : lab . id ,
547+ name : lab . title ,
548+ compute : lab . selectedCompute . map ( c => ( {
549+ id : c . id ,
550+ name : c . name ,
551+ flavor : c . flavor ,
552+ core_count : c . core_count ,
553+ ram : c . ram ,
554+ gpu : c . gpu ,
555+ type : c . type ,
556+ } ) ) ,
557+ storage : lab . selectedStorage . map ( s => ( {
558+ id : s . id ,
559+ name : s . name ,
560+ usage : s . usage ,
561+ type : s . type ,
562+ size : s . size ,
563+ } ) ) ,
564+ } ) )
565+
566+ const exportData = {
567+ version : "1.0" ,
568+ labs : labsToExport ,
569+ }
570+
571+ const jsonString = JSON . stringify ( exportData , null , 2 )
572+ const blob = new Blob ( [ jsonString ] , { type : "application/json" } )
573+ const url = URL . createObjectURL ( blob )
574+ const a = document . createElement ( "a" )
575+ a . href = url
576+ a . download = "hunt-cloud-estimate.json"
577+ document . body . appendChild ( a )
578+ a . click ( )
579+ document . body . removeChild ( a )
580+ URL . revokeObjectURL ( url )
581+ } ,
582+
583+ async importLabs ( file : File ) {
584+ return new Promise < void > ( ( resolve , reject ) => {
585+ const reader = new FileReader ( )
586+
587+ reader . onload = e => {
588+ try {
589+ const data = JSON . parse ( e . target ?. result as string )
590+
591+ // Validation
592+ if ( ! data . version ) throw new Error ( "Invalid JSON format: Missing version" )
593+ if ( ! Array . isArray ( data . labs ) ) throw new Error ( "Invalid JSON format: 'labs' must be an array" )
594+
595+ data . labs . forEach ( ( lab : any , labIndex : number ) => {
596+ if ( ! lab . name ) throw new Error ( `Invalid lab at index ${ labIndex } : Missing 'name'` )
597+
598+ if ( lab . compute ) {
599+ if ( ! Array . isArray ( lab . compute ) ) throw new Error ( `Invalid lab '${ lab . name } ': 'compute' must be an array` )
600+ lab . compute . forEach ( ( comp : any , compIndex : number ) => {
601+ const required = [ "name" , "flavor" , "core_count" , "ram" , "type" ]
602+ const missing = required . filter (
603+ field => comp [ field ] === undefined || comp [ field ] === null || comp [ field ] === "" ,
604+ )
605+ if ( missing . length > 0 ) {
606+ throw new Error (
607+ `Invalid compute item at index ${ compIndex } in lab '${ lab . name } ': Missing fields: ${ missing . join ( ", " ) } ` ,
608+ )
609+ }
610+ } )
611+ }
612+
613+ if ( lab . storage ) {
614+ if ( ! Array . isArray ( lab . storage ) ) throw new Error ( `Invalid lab '${ lab . name } ': 'storage' must be an array` )
615+ lab . storage . forEach ( ( store : any , storeIndex : number ) => {
616+ const required = [ "name" , "usage" , "type" , "size" ]
617+ const missing = required . filter (
618+ field => store [ field ] === undefined || store [ field ] === null || store [ field ] === "" ,
619+ )
620+ if ( missing . length > 0 ) {
621+ throw new Error (
622+ `Invalid storage item at index ${ storeIndex } in lab '${ lab . name } ': Missing fields: ${ missing . join ( ", " ) } ` ,
623+ )
624+ }
625+ } )
626+ }
627+ } )
628+
629+ this . isInitializingPriseEstimator = true
630+ this . clearAllLabs ( )
631+
632+ for ( const labData of data . labs ) {
633+ const newLabId = this . labs . length
634+
635+ this . labs . push ( {
636+ id : newLabId ,
637+ title : labData . name ,
638+ selectedCompute : [ ] ,
639+ selectedStorage : [ ] ,
640+ } )
641+
642+ if ( labData . compute ) {
643+ for ( const comp of labData . compute ) {
644+ this . addComputeToLab ( newLabId , {
645+ name : comp . name ,
646+ flavor : comp . flavor ,
647+ core_count : comp . core_count ,
648+ ram : comp . ram ,
649+ type : comp . type ,
650+ gpu : comp . gpu ,
651+ } )
652+ }
653+ }
654+
655+ if ( labData . storage ) {
656+ for ( const store of labData . storage ) {
657+ this . addStorageToLab ( newLabId , {
658+ name : store . name ,
659+ usage : store . usage ,
660+ type : store . type ,
661+ size : store . size ,
662+ } )
663+ }
664+ }
665+ }
666+
667+ this . updateTotalSummary ( )
668+ this . isInitializingPriseEstimator = false
669+ resolve ( )
670+ } catch ( err ) {
671+ this . isInitializingPriseEstimator = false
672+ reject ( err )
673+ }
674+ }
675+
676+ reader . onerror = ( ) => {
677+ this . isInitializingPriseEstimator = false
678+ reject ( new Error ( "Failed to read file" ) )
679+ }
680+
681+ reader . readAsText ( file )
682+ } )
683+ } ,
542684} )
0 commit comments