Parcourir la source

Add source properties info to replica details page

Replica and migration details page now displays source properties
information.
Previously, only target properties information was displayed.
Sergiu Miclea il y a 6 ans
Parent
commit
56030ce1fa

+ 4 - 0
src/components/atoms/PasswordValue/PasswordValue.jsx

@@ -48,6 +48,7 @@ const Value = styled.span`
 
 type Props = {
   value: string,
+  onShow?: () => void,
 }
 type State = {
   show: boolean,
@@ -59,6 +60,9 @@ class PasswordValue extends React.Component<Props, State> {
   }
 
   handleShowClick() {
+    if (this.props.onShow) {
+      this.props.onShow()
+    }
     this.setState({ show: true })
   }
 

+ 1 - 1
src/components/molecules/MainDetailsTable/MainDetailsTable.jsx

@@ -394,7 +394,7 @@ class MainDetailsTable extends React.Component<Props, State> {
       <Wrapper>
         <Header>
           <HeaderLabel>Source</HeaderLabel>
-          <HeaderLabel>Destination</HeaderLabel>
+          <HeaderLabel>Target</HeaderLabel>
         </Header>
         {this.props.instancesDetails.map(instance => (
           <InstanceInfo key={instance.name}>

+ 43 - 15
src/components/organisms/MainDetails/MainDetails.jsx

@@ -117,13 +117,16 @@ const PropertyValue = styled.div`
   text-align: right;
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 50%;
+  max-width: calc(50% + 16px);
+  margin-right: -16px;
 `
 
 type Props = {
   item: ?MainItem,
   destinationSchema: FieldType[],
   destinationSchemaLoading: boolean,
+  sourceSchema: FieldType[],
+  sourceSchemaLoading: boolean,
   instancesDetails: Instance[],
   instancesDetailsLoading: boolean,
   endpoints: Endpoint[],
@@ -131,8 +134,15 @@ type Props = {
   bottomControls: React.Node,
   loading: boolean,
 }
+type State = {
+  showPassword: string[]
+}
 @observer
-class MainDetails extends React.Component<Props> {
+class MainDetails extends React.Component<Props, State> {
+  state = {
+    showPassword: [],
+  }
+
   getSourceEndpoint(): ?Endpoint {
     let endpoint = this.props.endpoints.find(e => this.props.item && e.id === this.props.item.origin_endpoint_id)
     return endpoint
@@ -204,14 +214,15 @@ class MainDetails extends React.Component<Props> {
     return endpointIsMissing
   }
 
-  renderPropertiesTable(propertyNames: string[]) {
-    let endpoint = this.getDestinationEndpoint()
+  renderPropertiesTable(propertyNames: string[], type: 'source' | 'destination') {
+    let endpoint = type === 'source' ? this.getSourceEndpoint() : this.getDestinationEndpoint()
 
     let getValue = (name: string, value: any) => {
       if (value.join && value.length && value[0].destination && value[0].source) {
         return value.map(v => `${v.source}=${v.destination}`).join(', ')
       }
-      return fieldHelper.getValueAlias(name, value, this.props.destinationSchema, endpoint && endpoint.type)
+      let schema = type === 'source' ? this.props.sourceSchema : this.props.destinationSchema
+      return fieldHelper.getValueAlias(name, value, schema, endpoint && endpoint.type)
     }
 
     let properties = []
@@ -219,10 +230,11 @@ class MainDetails extends React.Component<Props> {
     let migrationImageMapFieldName = plugin && plugin.migrationImageMapFieldName
     let dictionaryKey = ''
     if (endpoint) {
-      dictionaryKey = `${endpoint.type}-destination`
+      dictionaryKey = `${endpoint.type}-${type}`
     }
+    let environment = this.props.item && (type === 'source' ? this.props.item.source_environment : this.props.item.destination_environment)
     propertyNames.forEach(pn => {
-      let value = this.props.item ? this.props.item.destination_environment[pn] : ''
+      let value = environment ? environment[pn] : ''
       let label = LabelDictionary.get(pn, dictionaryKey)
 
       if (value && value.join) {
@@ -256,8 +268,12 @@ class MainDetails extends React.Component<Props> {
           <PropertyRow key={prop.label}>
             <PropertyName>{prop.label}</PropertyName>
             <PropertyValue>
-              {prop.label.toLowerCase().indexOf('password') > -1
-                ? <PasswordValue value={prop.value} /> : <CopyValue value={prop.value} />}
+              {prop.label.toLowerCase().indexOf('password') > -1 && !this.state.showPassword.find(f => f === `${prop.label}-${type}`)
+                ? (
+                  <PasswordValue
+                    value={prop.value}
+                    onShow={() => this.setState({ showPassword: [...this.state.showPassword, `${prop.label}-${type}`] })}
+                  />) : <CopyValue value={prop.value} />}
             </PropertyValue>
           </PropertyRow>
         ))}
@@ -273,14 +289,15 @@ class MainDetails extends React.Component<Props> {
     const destinationEndpoint = this.getDestinationEndpoint()
     const lastUpdated = this.renderLastExecutionTime()
 
-    const destEnv = this.props.item && this.props.item.destination_environment
-    const propertyNames = destEnv ?
-      Object.keys(destEnv).filter(k =>
+    const getPropertyNames = (type: 'source' | 'destination') => {
+      let env = this.props.item && (type === 'source' ? this.props.item.source_environment : this.props.item.destination_environment)
+      return env ? Object.keys(env).filter(k =>
         k !== 'network_map' && (
           k !== 'storage_mappings' ||
-          (destEnv[k] != null && typeof destEnv[k] === 'object' && Object.keys(destEnv[k]).length > 0)
+          (env[k] != null && typeof env[k] === 'object' && Object.keys(env[k]).length > 0)
         )
       ) : []
+    }
 
     return (
       <ColumnsLayout>
@@ -297,6 +314,17 @@ class MainDetails extends React.Component<Props> {
               data-test-id="mainDetails-sourceLogo"
             />
           </Row>
+          {getPropertyNames('source').length > 0 ? (
+            <Row>
+              <Field>
+                <Label>Properties{this.props.sourceSchemaLoading ? (
+                  <StatusIcon status="RUNNING" style={{ marginLeft: '8px' }} />
+                ) : <StatusIconStub />
+                }</Label>
+                <Value block>{this.renderPropertiesTable(getPropertyNames('source'), 'source')}</Value>
+              </Field>
+            </Row>
+          ) : null}
           <Row>
             <Field>
               <Label>Id</Label>
@@ -352,14 +380,14 @@ class MainDetails extends React.Component<Props> {
               data-test-id="mainDetails-targetLogo"
             />
           </Row>
-          {propertyNames.length > 0 ? (
+          {getPropertyNames('destination').length > 0 ? (
             <Row>
               <Field>
                 <Label>Properties{this.props.destinationSchemaLoading ? (
                   <StatusIcon status="RUNNING" style={{ marginLeft: '8px' }} />
                 ) : <StatusIconStub />
                 }</Label>
-                <Value block>{this.renderPropertiesTable(propertyNames)}</Value>
+                <Value block>{this.renderPropertiesTable(getPropertyNames('destination'), 'destination')}</Value>
               </Field>
             </Row>
           ) : null}

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

@@ -59,6 +59,8 @@ type Props = {
   detailsLoading: boolean,
   instancesDetails: Instance[],
   instancesDetailsLoading: boolean,
+  sourceSchema: Field[],
+  sourceSchemaLoading: boolean,
   destinationSchema: Field[],
   destinationSchemaLoading: boolean,
   endpoints: Endpoint[],
@@ -89,6 +91,8 @@ class MigrationDetailsContent extends React.Component<Props> {
         item={this.props.item}
         instancesDetails={this.props.instancesDetails}
         instancesDetailsLoading={this.props.instancesDetailsLoading}
+        sourceSchema={this.props.sourceSchema}
+        sourceSchemaLoading={this.props.sourceSchemaLoading}
         destinationSchema={this.props.destinationSchema}
         destinationSchemaLoading={this.props.destinationSchemaLoading}
         endpoints={this.props.endpoints}

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

@@ -74,6 +74,8 @@ type TimezoneValue = 'utc' | 'local'
 type Props = {
   item: ?MainItem,
   endpoints: Endpoint[],
+  sourceSchema: Field[],
+  sourceSchemaLoading: boolean,
   destinationSchema: Field[],
   destinationSchemaLoading: boolean,
   networks: Network[],
@@ -159,6 +161,8 @@ class ReplicaDetailsContent extends React.Component<Props, State> {
     return (
       <MainDetails
         item={this.props.item}
+        sourceSchema={this.props.sourceSchema}
+        sourceSchemaLoading={this.props.sourceSchemaLoading}
         destinationSchema={this.props.destinationSchema}
         destinationSchemaLoading={this.props.destinationSchemaLoading}
         instancesDetails={this.props.instancesDetails}

+ 35 - 24
src/components/pages/MigrationDetailsPage/MigrationDetailsPage.jsx

@@ -81,33 +81,40 @@ class MigrationDetailsPage extends React.Component<Props, State> {
       if (!details) {
         return
       }
-      let endpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
-      if (!endpoint) {
+      let sourceEndpoint = endpointStore.endpoints.find(e => e.id === details.origin_endpoint_id)
+      let destinationEndpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
+      if (!sourceEndpoint || !destinationEndpoint) {
         return
       }
-      // This allows the values to be displayed with their allocated names instead of their IDs
-      await providerStore.loadOptionsSchema({
-        providerName: endpoint.type,
-        optionsType: 'destination',
-        useCache: true,
-        quietError: true,
-      })
-      let getOptionsValuesConfig = {
-        optionsType: 'destination',
-        endpointId: details.destination_endpoint_id,
-        providerName: endpoint.type,
-        useCache: true,
-        quietError: true,
-        allowMultiple: true,
+      const loadOptions = async (optionsType: 'source' | 'destination') => {
+        let providerName = optionsType === 'source' ? sourceEndpoint.type : destinationEndpoint.type
+        // This allows the values to be displayed with their allocated names instead of their IDs
+        await providerStore.loadOptionsSchema({
+          providerName,
+          optionsType,
+          useCache: true,
+          quietError: true,
+        })
+        let getOptionsValuesConfig = {
+          optionsType,
+          endpointId: optionsType === 'source' ? details.origin_endpoint_id : details.destination_endpoint_id,
+          providerName,
+          useCache: true,
+          quietError: true,
+          allowMultiple: true,
+        }
+        // For some providers, the API doesn't return the required fields values
+        // if those required fields are sent in env data,
+        // so to retrieve those values a request without env data must be made
+        await providerStore.getOptionsValues(getOptionsValuesConfig)
+        await providerStore.getOptionsValues({
+          ...getOptionsValuesConfig,
+          envData: optionsType === 'source' ? details.source_environment : details.destination_environment,
+        })
       }
-      // For some providers, the API doesn't return the required fields values
-      // if those required fields are sent in env data,
-      // so to retrieve those values a request without env data must be made
-      await providerStore.getOptionsValues(getOptionsValuesConfig)
-      await providerStore.getOptionsValues({
-        ...getOptionsValuesConfig,
-        envData: details.destination_environment,
-      })
+
+      loadOptions('source')
+      loadOptions('destination')
     }
     loadMigration()
 
@@ -326,6 +333,10 @@ class MigrationDetailsPage extends React.Component<Props, State> {
             item={migrationStore.migrationDetails}
             instancesDetails={instanceStore.instancesDetails}
             instancesDetailsLoading={instanceStore.loadingInstancesDetails}
+            sourceSchema={providerStore.sourceSchema}
+            sourceSchemaLoading={providerStore.sourceSchemaLoading
+              || providerStore.sourceOptionsPrimaryLoading
+              || providerStore.sourceOptionsSecondaryLoading}
             destinationSchema={providerStore.destinationSchema}
             destinationSchemaLoading={providerStore.destinationSchemaLoading
               || providerStore.destinationOptionsPrimaryLoading

+ 35 - 24
src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.jsx

@@ -98,33 +98,40 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
       if (!details) {
         return
       }
-      let endpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
-      if (!endpoint) {
+      let sourceEndpoint = endpointStore.endpoints.find(e => e.id === details.origin_endpoint_id)
+      let destinationEndpoint = endpointStore.endpoints.find(e => e.id === details.destination_endpoint_id)
+      if (!sourceEndpoint || !destinationEndpoint) {
         return
       }
-      // This allows the values to be displayed with their allocated names instead of their IDs
-      await providerStore.loadOptionsSchema({
-        providerName: endpoint.type,
-        optionsType: 'destination',
-        useCache: true,
-        quietError: true,
-      })
-      let getOptionsValuesConfig = {
-        optionsType: 'destination',
-        endpointId: details.destination_endpoint_id,
-        providerName: endpoint.type,
-        useCache: true,
-        quietError: true,
-        allowMultiple: true,
+      const loadOptions = async (optionsType: 'source' | 'destination') => {
+        let providerName = optionsType === 'source' ? sourceEndpoint.type : destinationEndpoint.type
+        // This allows the values to be displayed with their allocated names instead of their IDs
+        await providerStore.loadOptionsSchema({
+          providerName,
+          optionsType,
+          useCache: true,
+          quietError: true,
+        })
+        let getOptionsValuesConfig = {
+          optionsType,
+          endpointId: optionsType === 'source' ? details.origin_endpoint_id : details.destination_endpoint_id,
+          providerName,
+          useCache: true,
+          quietError: true,
+          allowMultiple: true,
+        }
+        // For some providers, the API doesn't return the required fields values
+        // if those required fields are sent in env data,
+        // so to retrieve those values a request without env data must be made
+        await providerStore.getOptionsValues(getOptionsValuesConfig)
+        await providerStore.getOptionsValues({
+          ...getOptionsValuesConfig,
+          envData: optionsType === 'source' ? details.source_environment : details.destination_environment,
+        })
       }
-      // For some providers, the API doesn't return the required fields values
-      // if those required fields are sent in env data,
-      // so to retrieve those values a request without env data must be made
-      await providerStore.getOptionsValues(getOptionsValuesConfig)
-      await providerStore.getOptionsValues({
-        ...getOptionsValuesConfig,
-        envData: details.destination_environment,
-      })
+
+      loadOptions('source')
+      loadOptions('destination')
     }
     loadReplica()
 
@@ -495,6 +502,10 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
             scheduleStore={scheduleStore}
             networks={networkStore.networks}
             detailsLoading={replicaStore.detailsLoading || endpointStore.loading}
+            sourceSchema={providerStore.sourceSchema}
+            sourceSchemaLoading={providerStore.sourceSchemaLoading
+              || providerStore.sourceOptionsPrimaryLoading
+              || providerStore.sourceOptionsSecondaryLoading}
             destinationSchema={providerStore.destinationSchema}
             destinationSchemaLoading={providerStore.destinationSchemaLoading
               || providerStore.destinationOptionsPrimaryLoading

+ 3 - 0
src/types/Field.js

@@ -15,6 +15,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // @flow
 
 import { OptionsSchemaPlugin } from '../plugins/endpoint'
+import LabelDictionary from '../utils/LabelDictionary'
 
 export type Field = {
   name: string,
@@ -79,6 +80,8 @@ class FieldHelper {
         let enumObject = field.enum.find(e => e.id ? e.id === v : false)
         if (enumObject && enumObject.name) {
           valueName = enumObject.name
+        } else if (field && LabelDictionary.enumFields.find(f => field && f === field.name)) {
+          valueName = LabelDictionary.get(v)
         }
       }
       return valueName