Просмотр исходного кода

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 6 лет назад
Родитель
Сommit
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