Sfoglia il codice sorgente

Merge pull request #461 from smiclea/options-names

Display options names instead of IDs
Nashwan Azhari 6 anni fa
parent
commit
f1b29a5729

+ 22 - 11
src/components/organisms/MainDetails/MainDetails.jsx

@@ -30,6 +30,9 @@ import type { Instance } from '../../../types/Instance'
 import type { MainItem } from '../../../types/MainItem'
 import type { MainItem } from '../../../types/MainItem'
 import type { Endpoint } from '../../../types/Endpoint'
 import type { Endpoint } from '../../../types/Endpoint'
 import type { Network } from '../../../types/Network'
 import type { Network } from '../../../types/Network'
+import type { Field as FieldType } from '../../../types/Field'
+import fieldHelper from '../../../types/Field'
+
 import StyleProps from '../../styleUtils/StyleProps'
 import StyleProps from '../../styleUtils/StyleProps'
 import Palette from '../../styleUtils/Palette'
 import Palette from '../../styleUtils/Palette'
 import DateUtils from '../../../utils/DateUtils'
 import DateUtils from '../../../utils/DateUtils'
@@ -69,6 +72,11 @@ const Label = styled.div`
   color: ${Palette.grayscale[3]};
   color: ${Palette.grayscale[3]};
   font-weight: ${StyleProps.fontWeights.medium};
   font-weight: ${StyleProps.fontWeights.medium};
   text-transform: uppercase;
   text-transform: uppercase;
+  display: flex;
+  align-items: center;
+`
+const StatusIconStub = styled.div`
+  ${StyleProps.exactSize('16px')}
 `
 `
 const Value = styled.div`
 const Value = styled.div`
   display: ${props => props.flex ? 'flex' : props.block ? 'block' : 'inline-table'};
   display: ${props => props.flex ? 'flex' : props.block ? 'block' : 'inline-table'};
@@ -112,6 +120,8 @@ const PropertyValue = styled.div`
 
 
 type Props = {
 type Props = {
   item: ?MainItem,
   item: ?MainItem,
+  destinationSchema: FieldType[],
+  destinationSchemaLoading: boolean,
   instancesDetails: Instance[],
   instancesDetails: Instance[],
   instancesDetailsLoading: boolean,
   instancesDetailsLoading: boolean,
   endpoints: Endpoint[],
   endpoints: Endpoint[],
@@ -193,17 +203,11 @@ class MainDetails extends React.Component<Props> {
   }
   }
 
 
   renderPropertiesTable(propertyNames: string[]) {
   renderPropertiesTable(propertyNames: string[]) {
-    let getValue = (value: any) => {
-      if (value === true) {
-        return 'Yes'
-      }
-      if (value === false) {
-        return 'No'
-      }
+    let getValue = (name: string, value: any) => {
       if (value.join && value.length && value[0].destination && value[0].source) {
       if (value.join && value.length && value[0].destination && value[0].source) {
         return value.map(v => `${v.source}=${v.destination}`).join(', ')
         return value.map(v => `${v.source}=${v.destination}`).join(', ')
       }
       }
-      return value.toString()
+      return fieldHelper.getValueAlias(name, value, this.props.destinationSchema)
     }
     }
 
 
     let properties = []
     let properties = []
@@ -222,13 +226,17 @@ class MainDetails extends React.Component<Props> {
           if (p === 'disk_mappings') {
           if (p === 'disk_mappings') {
             return null
             return null
           }
           }
+          let fieldName = pn
+          if (fieldName === 'migr_image_map') {
+            fieldName = `${p}_os_image`
+          }
           return {
           return {
             label: `${label} - ${LabelDictionary.get(p)}`,
             label: `${label} - ${LabelDictionary.get(p)}`,
-            value: getValue(value[p]),
+            value: getValue(fieldName, value[p]),
           }
           }
         }))
         }))
       } else {
       } else {
-        properties.push({ label, value: getValue(value) })
+        properties.push({ label, value: getValue(pn, value) })
       }
       }
     })
     })
 
 
@@ -336,7 +344,10 @@ class MainDetails extends React.Component<Props> {
           {propertyNames.length > 0 ? (
           {propertyNames.length > 0 ? (
             <Row>
             <Row>
               <Field>
               <Field>
-                <Label>Properties</Label>
+                <Label>Properties{this.props.destinationSchemaLoading ? (
+                  <StatusIcon status="RUNNING" style={{ marginLeft: '8px' }} />
+                ) : <StatusIconStub />
+                }</Label>
                 <Value block>{this.renderPropertiesTable(propertyNames)}</Value>
                 <Value block>{this.renderPropertiesTable(propertyNames)}</Value>
               </Field>
               </Field>
             </Row>
             </Row>

+ 5 - 0
src/components/organisms/MigrationDetailsContent/MigrationDetailsContent.jsx

@@ -27,6 +27,7 @@ import StyleProps from '../../styleUtils/StyleProps'
 import type { Instance } from '../../../types/Instance'
 import type { Instance } from '../../../types/Instance'
 import type { MainItem } from '../../../types/MainItem'
 import type { MainItem } from '../../../types/MainItem'
 import type { Endpoint } from '../../../types/Endpoint'
 import type { Endpoint } from '../../../types/Endpoint'
+import type { Field } from '../../../types/Field'
 
 
 const Wrapper = styled.div`
 const Wrapper = styled.div`
   display: flex;
   display: flex;
@@ -57,6 +58,8 @@ type Props = {
   detailsLoading: boolean,
   detailsLoading: boolean,
   instancesDetails: Instance[],
   instancesDetails: Instance[],
   instancesDetailsLoading: boolean,
   instancesDetailsLoading: boolean,
+  destinationSchema: Field[],
+  destinationSchemaLoading: boolean,
   endpoints: Endpoint[],
   endpoints: Endpoint[],
   page: string,
   page: string,
   onDeleteMigrationClick: () => void,
   onDeleteMigrationClick: () => void,
@@ -85,6 +88,8 @@ class MigrationDetailsContent extends React.Component<Props> {
         item={this.props.item}
         item={this.props.item}
         instancesDetails={this.props.instancesDetails}
         instancesDetails={this.props.instancesDetails}
         instancesDetailsLoading={this.props.instancesDetailsLoading}
         instancesDetailsLoading={this.props.instancesDetailsLoading}
+        destinationSchema={this.props.destinationSchema}
+        destinationSchemaLoading={this.props.destinationSchemaLoading}
         endpoints={this.props.endpoints}
         endpoints={this.props.endpoints}
         bottomControls={this.renderBottomControls()}
         bottomControls={this.renderBottomControls()}
         loading={this.props.detailsLoading}
         loading={this.props.detailsLoading}

+ 5 - 0
src/components/organisms/ReplicaDetailsContent/ReplicaDetailsContent.jsx

@@ -29,6 +29,7 @@ import type { MainItem } from '../../../types/MainItem'
 import type { Endpoint } from '../../../types/Endpoint'
 import type { Endpoint } from '../../../types/Endpoint'
 import type { Execution } from '../../../types/Execution'
 import type { Execution } from '../../../types/Execution'
 import type { Network } from '../../../types/Network'
 import type { Network } from '../../../types/Network'
+import type { Field } from '../../../types/Field'
 import type { Schedule as ScheduleType } from '../../../types/Schedule'
 import type { Schedule as ScheduleType } from '../../../types/Schedule'
 import StyleProps from '../../styleUtils/StyleProps'
 import StyleProps from '../../styleUtils/StyleProps'
 
 
@@ -72,6 +73,8 @@ type TimezoneValue = 'utc' | 'local'
 type Props = {
 type Props = {
   item: ?MainItem,
   item: ?MainItem,
   endpoints: Endpoint[],
   endpoints: Endpoint[],
+  destinationSchema: Field[],
+  destinationSchemaLoading: boolean,
   networks: Network[],
   networks: Network[],
   instancesDetails: Instance[],
   instancesDetails: Instance[],
   instancesDetailsLoading: boolean,
   instancesDetailsLoading: boolean,
@@ -155,6 +158,8 @@ class ReplicaDetailsContent extends React.Component<Props, State> {
     return (
     return (
       <MainDetails
       <MainDetails
         item={this.props.item}
         item={this.props.item}
+        destinationSchema={this.props.destinationSchema}
+        destinationSchemaLoading={this.props.destinationSchemaLoading}
         instancesDetails={this.props.instancesDetails}
         instancesDetails={this.props.instancesDetails}
         instancesDetailsLoading={this.props.instancesDetailsLoading}
         instancesDetailsLoading={this.props.instancesDetailsLoading}
         loading={this.props.detailsLoading}
         loading={this.props.detailsLoading}

+ 2 - 0
src/components/organisms/WizardPageContent/WizardPageContent.jsx

@@ -429,6 +429,8 @@ class WizardPageContent extends React.Component<Props, State> {
             storageMap={this.props.storageMap}
             storageMap={this.props.storageMap}
             wizardType={this.props.type}
             wizardType={this.props.type}
             instancesDetails={this.props.instanceStore.instancesDetails}
             instancesDetails={this.props.instanceStore.instancesDetails}
+            sourceSchema={this.props.providerStore.sourceSchema}
+            destinationSchema={this.props.providerStore.destinationSchema}
           />
           />
         )
         )
         break
         break

+ 9 - 18
src/components/organisms/WizardSummary/WizardSummary.jsx

@@ -29,7 +29,9 @@ import type { Schedule } from '../../../types/Schedule'
 import type { WizardData } from '../../../types/WizardData'
 import type { WizardData } from '../../../types/WizardData'
 import type { StorageMap, StorageBackend } from '../../../types/Endpoint'
 import type { StorageMap, StorageBackend } from '../../../types/Endpoint'
 import type { Instance, Disk } from '../../../types/Instance'
 import type { Instance, Disk } from '../../../types/Instance'
+import type { Field } from '../../../types/Field'
 
 
+import fieldHelper from '../../../types/Field'
 import { getDisks } from '../WizardStorage'
 import { getDisks } from '../WizardStorage'
 
 
 import networkArrowImage from './images/network-arrow.svg'
 import networkArrowImage from './images/network-arrow.svg'
@@ -158,10 +160,12 @@ type Props = {
   schedules: Schedule[],
   schedules: Schedule[],
   storageMap: StorageMap[],
   storageMap: StorageMap[],
   instancesDetails: Instance[],
   instancesDetails: Instance[],
+  sourceSchema: Field[],
+  destinationSchema: Field[],
 }
 }
 @observer
 @observer
 class WizardSummary extends React.Component<Props> {
 class WizardSummary extends React.Component<Props> {
-  getDefaultOption(fieldName: string) {
+  getDefaultOption(fieldName: string): boolean {
     if (this.props.data.destOptions && this.props.data.destOptions[fieldName] === false) {
     if (this.props.data.destOptions && this.props.data.destOptions[fieldName] === false) {
       return false
       return false
     }
     }
@@ -237,19 +241,6 @@ class WizardSummary extends React.Component<Props> {
     )
     )
   }
   }
 
 
-  renderOptionValue(value: any) {
-    if (value === true) {
-      return 'Yes'
-    }
-    if (value === false) {
-      return 'No'
-    }
-    if (value.join) {
-      return value.join(', ')
-    }
-    return value
-  }
-
   renderSourceOptionsSection() {
   renderSourceOptionsSection() {
     let data = this.props.data
     let data = this.props.data
     let type = this.props.wizardType.charAt(0).toUpperCase() + this.props.wizardType.substr(1)
     let type = this.props.wizardType.charAt(0).toUpperCase() + this.props.wizardType.substr(1)
@@ -272,7 +263,7 @@ class WizardSummary extends React.Component<Props> {
                   {optionName.split('/').map(n => LabelDictionary.get(n)).join(' - ')}
                   {optionName.split('/').map(n => LabelDictionary.get(n)).join(' - ')}
                 </OptionLabel>
                 </OptionLabel>
                 <OptionValue>{
                 <OptionValue>{
-                  this.renderOptionValue(data.sourceOptions && data.sourceOptions[optionName])
+                  fieldHelper.getValueAlias(optionName, data.sourceOptions && data.sourceOptions[optionName], this.props.sourceSchema)
                 }</OptionValue>
                 }</OptionValue>
               </Option>
               </Option>
             )
             )
@@ -289,14 +280,14 @@ class WizardSummary extends React.Component<Props> {
     let executeNowOption = (
     let executeNowOption = (
       <Option>
       <Option>
         <OptionLabel>Execute now?</OptionLabel>
         <OptionLabel>Execute now?</OptionLabel>
-        <OptionValue>{this.renderOptionValue(this.getDefaultOption('execute_now'))}</OptionValue>
+        <OptionValue>{this.getDefaultOption('execute_now') ? 'Yes' : 'No'}</OptionValue>
       </Option>
       </Option>
     )
     )
 
 
     let separateVmOption = (
     let separateVmOption = (
       <Option>
       <Option>
         <OptionLabel>Separate {type}/VM?</OptionLabel>
         <OptionLabel>Separate {type}/VM?</OptionLabel>
-        <OptionValue>{this.renderOptionValue(this.getDefaultOption('separate_vm'))}</OptionValue>
+        <OptionValue>{this.getDefaultOption('separate_vm') ? 'Yes' : 'No'}</OptionValue>
       </Option>
       </Option>
     )
     )
 
 
@@ -321,7 +312,7 @@ class WizardSummary extends React.Component<Props> {
                   {optionName.split('/').map(n => LabelDictionary.get(n)).join(' - ')}
                   {optionName.split('/').map(n => LabelDictionary.get(n)).join(' - ')}
                 </OptionLabel>
                 </OptionLabel>
                 <OptionValue data-test-id={`wSummary-optionValue-${optionName}`}>{
                 <OptionValue data-test-id={`wSummary-optionValue-${optionName}`}>{
-                  this.renderOptionValue(data.destOptions && data.destOptions[optionName])
+                  fieldHelper.getValueAlias(optionName, data.destOptions && data.destOptions[optionName], this.props.destinationSchema)
                 }</OptionValue>
                 }</OptionValue>
               </Option>
               </Option>
             )
             )

+ 1 - 1
src/components/organisms/WizardSummary/test.jsx

@@ -21,7 +21,7 @@ import WizardSummary from '.'
 
 
 const wrap = props => new TW(shallow(
 const wrap = props => new TW(shallow(
   // $FlowIgnore
   // $FlowIgnore
-  <WizardSummary storageMap={[]} instancesDetails={[]} {...props} />
+  <WizardSummary storageMap={[]} instancesDetails={[]} sourceSchema={[]} destinationSchema={[]} {...props} />
 ), 'wSummary')
 ), 'wSummary')
 
 
 let schedules = [
 let schedules = [

+ 37 - 3
src/components/pages/MigrationDetailsPage/MigrationDetailsPage.jsx

@@ -33,6 +33,7 @@ import endpointStore from '../../../stores/EndpointStore'
 import notificationStore from '../../../stores/NotificationStore'
 import notificationStore from '../../../stores/NotificationStore'
 import networkStore from '../../../stores/NetworkStore'
 import networkStore from '../../../stores/NetworkStore'
 import instanceStore from '../../../stores/InstanceStore'
 import instanceStore from '../../../stores/InstanceStore'
+import providerStore from '../../../stores/ProviderStore'
 import configLoader from '../../../utils/Config'
 import configLoader from '../../../utils/Config'
 
 
 import migrationImage from './images/migration.svg'
 import migrationImage from './images/migration.svg'
@@ -66,8 +67,38 @@ class MigrationDetailsPage extends React.Component<Props, State> {
   componentWillMount() {
   componentWillMount() {
     document.title = 'Migration Details'
     document.title = 'Migration Details'
 
 
-    endpointStore.getEndpoints({ showLoading: true })
-    this.loadMigrationWithInstances(this.props.match.params.id, true)
+    let loadMigration = async () => {
+      await Promise.all([
+        endpointStore.getEndpoints({ showLoading: true }),
+        this.loadMigrationWithInstances(this.props.match.params.id, true),
+      ])
+      let details = migrationStore.migrationDetails
+      if (!details) {
+        return
+      }
+      let endpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
+      if (!endpoint) {
+        return
+      }
+      // This allows the values to be displayed with their allocated names instead of their IDs
+      await providerStore.loadOptionsSchema({
+        providerName: endpoint.type,
+        schemaType: details.type,
+        optionsType: 'destination',
+        useCache: true,
+        quietError: true,
+      })
+      await providerStore.getOptionsValues({
+        optionsType: 'destination',
+        endpointId: details.destination_endpoint_id,
+        providerName: endpoint.type,
+        envData: details.destination_environment,
+        useCache: true,
+        quietError: true,
+      })
+    }
+    loadMigration()
+
     this.pollData()
     this.pollData()
   }
   }
 
 
@@ -266,6 +297,10 @@ class MigrationDetailsPage extends React.Component<Props, State> {
             item={migrationStore.migrationDetails}
             item={migrationStore.migrationDetails}
             instancesDetails={instanceStore.instancesDetails}
             instancesDetails={instanceStore.instancesDetails}
             instancesDetailsLoading={instanceStore.loadingInstancesDetails}
             instancesDetailsLoading={instanceStore.loadingInstancesDetails}
+            destinationSchema={providerStore.destinationSchema}
+            destinationSchemaLoading={providerStore.destinationSchemaLoading
+              || providerStore.destinationOptionsPrimaryLoading
+              || providerStore.destinationOptionsSecondaryLoading}
             endpoints={endpointStore.endpoints}
             endpoints={endpointStore.endpoints}
             page={this.props.match.params.page || ''}
             page={this.props.match.params.page || ''}
             detailsLoading={endpointStore.loading || migrationStore.detailsLoading}
             detailsLoading={endpointStore.loading || migrationStore.detailsLoading}
@@ -302,7 +337,6 @@ class MigrationDetailsPage extends React.Component<Props, State> {
           </Modal>
           </Modal>
         ) : null}
         ) : null}
         {this.renderEditModal()}
         {this.renderEditModal()}
-
       </Wrapper>
       </Wrapper>
     )
     )
   }
   }

+ 36 - 2
src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.jsx

@@ -86,8 +86,38 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
   componentWillMount() {
   componentWillMount() {
     document.title = 'Replica Details'
     document.title = 'Replica Details'
 
 
-    this.loadReplicaWithInstances(this.props.match.params.id, true)
-    endpointStore.getEndpoints({ showLoading: true })
+    let loadReplica = async () => {
+      await Promise.all([
+        this.loadReplicaWithInstances(this.props.match.params.id, true),
+        endpointStore.getEndpoints({ showLoading: true }),
+      ])
+      let details = replicaStore.replicaDetails
+      if (!details) {
+        return
+      }
+      let endpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
+      if (!endpoint) {
+        return
+      }
+      // This allows the values to be displayed with their allocated names instead of their IDs
+      await providerStore.loadOptionsSchema({
+        providerName: endpoint.type,
+        schemaType: details.type,
+        optionsType: 'destination',
+        useCache: true,
+        quietError: true,
+      })
+      await providerStore.getOptionsValues({
+        optionsType: 'destination',
+        endpointId: details.destination_endpoint_id,
+        providerName: endpoint.type,
+        envData: details.destination_environment,
+        useCache: true,
+        quietError: true,
+      })
+    }
+    loadReplica()
+
     scheduleStore.getSchedules(this.props.match.params.id)
     scheduleStore.getSchedules(this.props.match.params.id)
     this.pollData(true)
     this.pollData(true)
   }
   }
@@ -422,6 +452,10 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
             scheduleStore={scheduleStore}
             scheduleStore={scheduleStore}
             networks={networkStore.networks}
             networks={networkStore.networks}
             detailsLoading={replicaStore.detailsLoading || endpointStore.loading}
             detailsLoading={replicaStore.detailsLoading || endpointStore.loading}
+            destinationSchema={providerStore.destinationSchema}
+            destinationSchemaLoading={providerStore.destinationSchemaLoading
+              || providerStore.destinationOptionsPrimaryLoading
+              || providerStore.destinationOptionsSecondaryLoading}
             executionsLoading={replicaStore.executionsLoading}
             executionsLoading={replicaStore.executionsLoading}
             page={this.props.match.params.page || ''}
             page={this.props.match.params.page || ''}
             onCancelExecutionClick={execution => { this.handleCancelExecution(execution) }}
             onCancelExecutionClick={execution => { this.handleCancelExecution(execution) }}

+ 4 - 2
src/sources/ProviderSource.js

@@ -34,7 +34,7 @@ class ProviderSource {
     return response.data.providers
     return response.data.providers
   }
   }
 
 
-  async loadOptionsSchema(providerName: string, schemaType: 'migration' | 'replica', optionsType: 'source' | 'destination', useCache?: ?boolean): Promise<Field[]> {
+  async loadOptionsSchema(providerName: string, schemaType: 'migration' | 'replica', optionsType: 'source' | 'destination', useCache?: ?boolean, quietError?: ?boolean): Promise<Field[]> {
     let schemaTypeInt = schemaType === 'migration' ?
     let schemaTypeInt = schemaType === 'migration' ?
       optionsType === 'source' ? providerTypes.SOURCE_MIGRATION : providerTypes.TARGET_MIGRATION :
       optionsType === 'source' ? providerTypes.SOURCE_MIGRATION : providerTypes.TARGET_MIGRATION :
       optionsType === 'source' ? providerTypes.SOURCE_REPLICA : providerTypes.TARGET_REPLICA
       optionsType === 'source' ? providerTypes.SOURCE_REPLICA : providerTypes.TARGET_REPLICA
@@ -42,13 +42,14 @@ class ProviderSource {
     let response = await Api.send({
     let response = await Api.send({
       url: `${servicesUrl.coriolis}/${Api.projectId}/providers/${providerName}/schemas/${schemaTypeInt}`,
       url: `${servicesUrl.coriolis}/${Api.projectId}/providers/${providerName}/schemas/${schemaTypeInt}`,
       cache: useCache,
       cache: useCache,
+      quietError,
     })
     })
     let schema = optionsType === 'source' ? response.data.schemas.source_environment_schema : response.data.schemas.destination_environment_schema
     let schema = optionsType === 'source' ? response.data.schemas.source_environment_schema : response.data.schemas.destination_environment_schema
     let fields = SchemaParser.optionsSchemaToFields(providerName, schema)
     let fields = SchemaParser.optionsSchemaToFields(providerName, schema)
     return fields
     return fields
   }
   }
 
 
-  async getOptionsValues(optionsType: 'source' | 'destination', endpointId: string, envData: ?{ [string]: mixed }, cache?: ?boolean): Promise<OptionValues[]> {
+  async getOptionsValues(optionsType: 'source' | 'destination', endpointId: string, envData: ?{ [string]: mixed }, cache?: ?boolean, quietError?: boolean): Promise<OptionValues[]> {
     let envString = ''
     let envString = ''
     if (envData) {
     if (envData) {
       envString = `?env=${btoa(JSON.stringify(envData))}`
       envString = `?env=${btoa(JSON.stringify(envData))}`
@@ -60,6 +61,7 @@ class ProviderSource {
       url: `${servicesUrl.coriolis}/${Api.projectId}/endpoints/${endpointId}/${callName}${envString}`,
       url: `${servicesUrl.coriolis}/${Api.projectId}/endpoints/${endpointId}/${callName}${envString}`,
       cache,
       cache,
       cancelId: endpointId,
       cancelId: endpointId,
+      quietError,
     })
     })
     return response.data[fieldName]
     return response.data[fieldName]
   }
   }

+ 6 - 4
src/stores/ProviderStore.js

@@ -152,8 +152,9 @@ class ProviderStore {
     schemaType: 'migration' | 'replica',
     schemaType: 'migration' | 'replica',
     optionsType: 'source' | 'destination',
     optionsType: 'source' | 'destination',
     useCache?: boolean,
     useCache?: boolean,
+    quietError?: boolean,
   }): Promise<void> {
   }): Promise<void> {
-    let { schemaType, providerName, optionsType, useCache } = options
+    let { schemaType, providerName, optionsType, useCache, quietError } = options
     if (optionsType === 'source') {
     if (optionsType === 'source') {
       this.lastSourceSchemaType = schemaType
       this.lastSourceSchemaType = schemaType
     } else {
     } else {
@@ -167,7 +168,7 @@ class ProviderStore {
     }
     }
 
 
     try {
     try {
-      let fields: Field[] = await ProviderSource.loadOptionsSchema(providerName, schemaType, optionsType, useCache)
+      let fields: Field[] = await ProviderSource.loadOptionsSchema(providerName, schemaType, optionsType, useCache, quietError)
       this.loadOptionsSchemaSuccess(fields, optionsType)
       this.loadOptionsSchemaSuccess(fields, optionsType)
     } catch (err) {
     } catch (err) {
       throw err
       throw err
@@ -198,8 +199,9 @@ class ProviderStore {
     providerName: string,
     providerName: string,
     envData?: { [string]: mixed },
     envData?: { [string]: mixed },
     useCache?: boolean,
     useCache?: boolean,
+    quietError?: boolean,
   }): Promise<OptionValues[]> {
   }): Promise<OptionValues[]> {
-    let { providerName, optionsType, endpointId, envData, useCache } = config
+    let { providerName, optionsType, endpointId, envData, useCache, quietError } = config
     let providerType = optionsType === 'source' ? providerTypes.SOURCE_OPTIONS : providerTypes.DESTINATION_OPTIONS
     let providerType = optionsType === 'source' ? providerTypes.SOURCE_OPTIONS : providerTypes.DESTINATION_OPTIONS
 
 
     await this.loadProviders()
     await this.loadProviders()
@@ -216,7 +218,7 @@ class ProviderStore {
     this.getOptionsValuesStart(optionsType, !envData)
     this.getOptionsValuesStart(optionsType, !envData)
 
 
     try {
     try {
-      let options = await ProviderSource.getOptionsValues(optionsType, endpointId, envData, useCache)
+      let options = await ProviderSource.getOptionsValues(optionsType, endpointId, envData, useCache, quietError)
       this.getOptionsValuesSuccess(optionsType, providerName, options)
       this.getOptionsValuesSuccess(optionsType, providerName, options)
       return options
       return options
     } catch (err) {
     } catch (err) {

+ 45 - 0
src/types/Field.js

@@ -36,3 +36,48 @@ export type Field = {
   title?: string,
   title?: string,
   description?: string,
   description?: string,
 }
 }
+
+const migrationImageOsTypes = ['windows', 'linux']
+
+class FieldHelper {
+  getValueAlias(name: string, value: any, fields: Field[]): string {
+    if (value === true) {
+      return 'Yes'
+    }
+    if (value === false) {
+      return 'No'
+    }
+    let field = fields.find(f => f.name === name)
+    let findInEnum = (v: any) => {
+      let valueName = v
+      if (field && field.enum) {
+        let enumObject = field.enum.find(e => e.id ? e.id === v : false)
+        if (enumObject && enumObject.name) {
+          valueName = enumObject.name
+        }
+      }
+      return valueName
+    }
+    if (value.join) {
+      return value.map(v => findInEnum(v)).join(', ')
+    }
+
+    let isImageMapField = migrationImageOsTypes.find(os => `${os}_os_image` === name)
+    if (isImageMapField) {
+      let migrImageField = fields.find(f => f.name === 'migr_image_map')
+      if (migrImageField && migrImageField.properties) {
+        let imageField = migrImageField.properties.find(p => p.name === name)
+        if (imageField && imageField.enum) {
+          let imageFieldValueObject = imageField.enum.find(e => e.id ? e.id === value : false)
+          if (imageFieldValueObject) {
+            return imageFieldValueObject.name
+          }
+        }
+      }
+    }
+    // $FlowIssue
+    return findInEnum(value)
+  }
+}
+
+export default new FieldHelper()

+ 1 - 1
src/types/MainItem.js

@@ -50,7 +50,7 @@ export type MainItem = {
   origin_endpoint_id: string,
   origin_endpoint_id: string,
   destination_endpoint_id: string,
   destination_endpoint_id: string,
   instances: string[],
   instances: string[],
-  type: string,
+  type: 'replica' | 'migration',
   info: { [string]: MainItemInfo },
   info: { [string]: MainItemInfo },
   destination_environment: { [string]: mixed },
   destination_environment: { [string]: mixed },
   source_environment: { [string]: mixed },
   source_environment: { [string]: mixed },

+ 1 - 1
src/utils/ApiCaller.js

@@ -34,7 +34,7 @@ type RequestOptions = {
   headers?: { [string]: string },
   headers?: { [string]: string },
   data?: any,
   data?: any,
   responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream',
   responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream',
-  quietError?: boolean,
+  quietError?: ?boolean,
   skipLog?: ?boolean,
   skipLog?: ?boolean,
   cache?: ?boolean,
   cache?: ?boolean,
   cacheFor?: ?number,
   cacheFor?: ?number,

+ 1 - 0
src/utils/Cacher.js

@@ -46,6 +46,7 @@ class Cacher {
       data,
       data,
       createdAt: new Date().toISOString(),
       createdAt: new Date().toISOString(),
     }
     }
+
     localStorage.setItem(STORE, JSON.stringify(storage))
     localStorage.setItem(STORE, JSON.stringify(storage))
   }
   }
 }
 }