Преглед изворни кода

Use the "notes" field as transfer item title

Instead of instance ID, the "notes" field is used, if available, to
display the replica / migration list item title.

The "notes" field is prepopulated when creating a replica / migration
with the selected instance(s) names.

The "notes" field can also be edited after the transfer item has been
created.
Sergiu Miclea пре 5 година
родитељ
комит
143a2c2a02

+ 8 - 7
src/components/molecules/MainListItem/MainListItem.tsx

@@ -178,20 +178,22 @@ class MainListItem extends React.Component<Props> {
       </EndpointsImages>
     )
     const status = this.getStatus()
-    const { instances } = this.props.item
-    let title = instances[0]
-    if (instances.length > 1) {
-      title += ` (+${instances.length - 1} more)`
+    const { instances, notes } = this.props.item
+    let title = notes
+    if (!notes) {
+      title = instances[0]
+      if (instances.length > 1) {
+        title += ` (+${instances.length - 1} more)`
+      }
     }
 
     return (
       <Wrapper>
         <CheckboxStyled
-          data-test-id="mainListItem-checkbox"
           checked={this.props.selected}
           onChange={this.props.onSelectedChange}
         />
-        <Content onClick={this.props.onClick} data-test-id="mainListItem-content">
+        <Content onClick={this.props.onClick}>
           <Image image={this.props.image} />
           <Title>
             <TitleLabel>{title}</TitleLabel>
@@ -200,7 +202,6 @@ class MainListItem extends React.Component<Props> {
                 <StatusPill
                   status={status}
                   style={{ marginRight: '8px' }}
-                  data-test-id={`mainListItem-statusPill-${status}`}
                 />
               ) : null}
               {this.props.showScheduleIcon ? (

+ 8 - 0
src/components/organisms/EditReplica/EditReplica.tsx

@@ -239,6 +239,14 @@ class EditReplica extends React.Component<Props, State> {
       return currentData[fieldName]
     }
 
+    if (fieldName === 'title') {
+      let title = this.props.instancesDetails?.[0]?.name
+      if (this.props.instancesDetails && this.props.instancesDetails.length > 1) {
+        title += ` (+${this.props.instancesDetails.length - 1} more)`
+      }
+      return title
+    }
+
     if (fieldName === 'minion_pool_id') {
       return type === 'source' ? this.props.replica.origin_minion_pool_id : this.props.replica.destination_minion_pool_id
     }

+ 0 - 11
src/components/organisms/MainDetails/MainDetails.tsx

@@ -22,7 +22,6 @@ import CopyValue from '../../atoms/CopyValue'
 import StatusIcon from '../../atoms/StatusIcon'
 import StatusImage from '../../atoms/StatusImage'
 import MainDetailsTable from '../../molecules/MainDetailsTable'
-import CopyMultilineValue from '../../atoms/CopyMultilineValue'
 import PasswordValue from '../../atoms/PasswordValue'
 
 import type { Instance } from '../../../@types/Instance'
@@ -316,16 +315,6 @@ class MainDetails extends React.Component<Props, State> {
               {this.props.item && this.props.item.created_at ? this.renderValue(DateUtils.getLocalTime(this.props.item.created_at).format('YYYY-MM-DD HH:mm:ss'), 'created') : <Value>-</Value>}
             </Field>
           </Row>
-          {this.props.item && this.props.item.notes
-            ? (
-              <Row>
-                <Field>
-                  <Label>Description</Label>
-                  <CopyMultilineValue value={this.props.item.notes} data-test-id="mainDetails-description" />
-                </Field>
-              </Row>
-            )
-            : null}
           {lastUpdated ? (
             <Row>
               <Field>

+ 3 - 2
src/components/organisms/WizardOptions/WizardOptions.tsx

@@ -222,8 +222,9 @@ class WizardOptions extends React.Component<Props> {
       fieldsSchema.push({ name: 'skip_os_morphing', type: 'boolean', default: false })
     }
 
-    if (this.props.wizardType === 'migration' || this.props.wizardType === 'replica') {
-      fieldsSchema.push({ name: 'description', type: 'string' })
+    if (this.props.wizardType === 'migration' || this.props.wizardType === 'replica'
+      || this.props.wizardType === 'migration-destination-options-edit' || this.props.wizardType === 'replica-destination-options-edit') {
+      fieldsSchema.push({ name: 'title', type: 'string' })
     }
 
     if (this.props.wizardType === 'replica') {

+ 1 - 1
src/components/organisms/WizardPageContent/WizardPageContent.tsx

@@ -452,7 +452,7 @@ class WizardPageContent extends React.Component<Props, State> {
               .filter(m => m.platform === 'destination' && m.endpoint_id === this.props.wizardData.target?.id)}
             optionsLoading={this.props.providerStore.destinationOptionsSecondaryLoading}
             optionsLoadingSkipFields={[
-              ...getOptionsLoadingSkipFields('destination'), 'description', 'execute_now',
+              ...getOptionsLoadingSkipFields('destination'), 'title', 'execute_now',
               'execute_now_options', ...migrationFields.map(f => f.name)]}
             selectedInstances={this.props.wizardData.selectedInstances}
             showSeparatePerVm={

+ 9 - 8
src/components/pages/MigrationDetailsPage/MigrationDetailsPage.tsx

@@ -342,19 +342,20 @@ class MigrationDetailsPage extends React.Component<Props, State> {
         action: () => { this.handleDeleteMigrationClick() },
       },
     ]
-    let title = null
+
     const migration = migrationStore.migrationDetails
-    if (migration) {
-      const { instances } = migration
-      if (instances) {
-        title = instances[0]
-        if (instances.length > 1) {
-          title += ` (+${instances.length - 1} more)`
+    let title = migration?.notes
+    if (!title) {
+      if (migration?.instances) {
+        title = migration.instances[0]
+        if (migration.instances.length > 1) {
+          title += ` (+${migration.instances.length - 1} more)`
         }
       } else {
-        title = migration.name
+        title = migration?.name
       }
     }
+
     return (
       <Wrapper>
         <DetailsTemplate

+ 8 - 8
src/components/pages/ReplicaDetailsPage/ReplicaDetailsPage.tsx

@@ -551,18 +551,18 @@ class ReplicaDetailsPage extends React.Component<Props, State> {
       },
     ]
     const replica = this.replica
-    let title = null
-    if (replica) {
-      const { instances } = replica
-      if (instances) {
-        title = instances[0]
-        if (instances.length > 1) {
-          title += ` (+${instances.length - 1} more)`
+    let title = replica?.notes
+    if (!title) {
+      if (replica?.instances) {
+        title = replica.instances[0]
+        if (replica.instances.length > 1) {
+          title += ` (+${replica.instances.length - 1} more)`
         }
       } else {
-        title = replica.name
+        title = replica?.name
       }
     }
+
     return (
       <Wrapper>
         <DetailsTemplate

+ 20 - 0
src/components/pages/WizardPage/WizardPage.tsx

@@ -74,6 +74,8 @@ class WizardPage extends React.Component<Props, State> {
 
   contentRef!: WizardPageContent
 
+  title: string | undefined
+
   UNSAFE_componentWillMount() {
     this.initializeState(this.props.match)
     this.handleResize()
@@ -127,6 +129,16 @@ class WizardPage extends React.Component<Props, State> {
       .filter(p => p.id !== 'storage' || hasStorageMapping())
   }
 
+  setTransferItemTitle() {
+    const selectedInstance = wizardStore.data?.selectedInstances?.[0]
+    let title = selectedInstance?.name || selectedInstance?.instance_name || selectedInstance?.id
+    if (wizardStore.data?.selectedInstances && wizardStore.data.selectedInstances.length > 1) {
+      title += ` (+${wizardStore.data.selectedInstances.length - 1} more)`
+    }
+    this.title = title
+    wizardStore.updateData({ destOptions: { title } })
+  }
+
   @autobind
   handleResize() {
     instanceStore.updateInstancesPerPage(this.instancesPerPage)
@@ -311,6 +323,7 @@ class WizardPage extends React.Component<Props, State> {
     wizardStore.clearStorageMap()
     wizardStore.toggleInstanceSelection(instance)
     wizardStore.updateUrlState()
+    this.setTransferItemTitle()
   }
 
   handleInstancePageClick(page: number) {
@@ -400,6 +413,7 @@ class WizardPage extends React.Component<Props, State> {
 
   initializeState(match: any) {
     wizardStore.getUrlState()
+    this.setTransferItemTitle()
     const type = match && match.params && match.params.type
     if (type === 'migration' || type === 'replica') {
       this.setState({ type })
@@ -492,6 +506,12 @@ class WizardPage extends React.Component<Props, State> {
         loadOptions(target, 'destination')
         break
       }
+      case 'dest-options': {
+        if (!wizardStore.data?.destOptions?.title) {
+          wizardStore.updateData({ destOptions: { title: this.title } })
+        }
+        break
+      }
       case 'networks':
         this.loadNetworks(true)
         break

+ 1 - 1
src/plugins/endpoint/default/OptionsSchemaPlugin.ts

@@ -81,7 +81,7 @@ export const defaultGetDestinationEnv = (
   oldOptions?: { [prop: string]: any } | null,
 ): any => {
   const env: any = {}
-  const specialOptions = ['execute_now', 'execute_now_options', 'separate_vm', 'skip_os_morphing', 'description', 'minion_pool_id']
+  const specialOptions = ['execute_now', 'execute_now_options', 'separate_vm', 'skip_os_morphing', 'title', 'minion_pool_id']
     .concat(migrationFields.map(f => f.name))
     .concat(executionOptions.map(o => o.name))
     .concat(migrationImageOsTypes)

+ 1 - 1
src/sources/MigrationSource.ts

@@ -154,7 +154,7 @@ class MigrationSource {
       replication_count: (opts.updatedDestEnv
         && opts.updatedDestEnv.replication_count) || opts.replicationCount || 2,
       instances: opts.instanceNames,
-      notes: getValue('description') || '',
+      notes: getValue('title') || getValue('notes') || '',
     }
 
     const skipOsMorphingValue = getValue('skip_os_morphing')

+ 4 - 0
src/sources/ReplicaSource.ts

@@ -228,6 +228,10 @@ class ReplicaSource {
     const parser = OptionsSchemaPlugin.for(destinationEndpoint.type)
     const payload: any = { replica: {} }
 
+    if (updateData.destination.title) {
+      payload.replica.notes = updateData.destination.title
+    }
+
     if (updateData.network.length > 0) {
       payload.replica.network_map = parser.getNetworkMap(updateData.network)
     }

+ 1 - 1
src/sources/WizardSource.ts

@@ -44,7 +44,7 @@ class WizardSource {
       network_map: destParser.getNetworkMap(data.networks),
       instances: data.selectedInstances ? data.selectedInstances.map(i => i.instance_name || i.id) : 'null',
       storage_mappings: destParser.getStorageMap(defaultStorage, storageMap),
-      notes: data.destOptions ? data.destOptions.description || '' : '',
+      notes: data.destOptions?.title || '',
     }
 
     if (data.destOptions && data.destOptions.skip_os_morphing != null) {