فهرست منبع

Improve layout of instances list

When there are multiple instances in a replica / migration, show each
instance in a separate line, instead of listing them comma-separated for
a much better reading experience.

The layout is also kept when copying to clipboard.

The same layout is also applied to the list of migrations / replicas
where an endpoint is used (in the endpoint details page).
Sergiu Miclea 7 سال پیش
والد
کامیت
e8d9e32b3b

+ 2 - 1
.eslintrc

@@ -79,6 +79,7 @@
     "arrow-parens": 0,
     "react/prefer-stateless-function": 0,
     "react/no-array-index-key": 0,
+    "react/no-danger": 0,
     "no-param-reassign": 0,
     "no-shadow": 0,
     "arrow-body-style": 0,
@@ -142,4 +143,4 @@
   "plugins": [
     "flowtype"
   ]
-}
+}

+ 20 - 9
src/components/atoms/CopyMultilineValue/CopyMultilineValue.jsx

@@ -22,28 +22,34 @@ import CopyButton from '../CopyButton'
 import DomUtils from '../../../utils/DomUtils'
 import notificationStore from '../../../stores/NotificationStore'
 
+const CopyButtonStyled = styled(CopyButton)`
+  background-position-y: 4px;
+  margin-left: 4px;
+`
 const Wrapper = styled.div`
   cursor: pointer;
 
-  &:hover > span {
+  &:hover ${CopyButtonStyled} {
     opacity: 1;
   }
-  > span {
-    background-position-y: 4px;
-    margin-left: 4px;
-  }
 `
 
 type Props = {
   'data-test-id'?: string,
   value: string,
   onCopy?: (value: string) => void,
+  useDangerousHtml?: boolean,
 }
 @observer
 class CopyMultineValue extends React.Component<Props> {
   handleCopy() {
-    let succesful = DomUtils.copyTextToClipboard(this.props.value)
-    if (this.props.onCopy) this.props.onCopy(this.props.value)
+    let value = this.props.value
+    if (this.props.useDangerousHtml) {
+      value = value.replace(/<br\s*\/>/g, '\n').replace(/<.*?>/g, '')
+    }
+
+    let succesful = DomUtils.copyTextToClipboard(value)
+    if (this.props.onCopy) this.props.onCopy(value)
 
     if (succesful) {
       notificationStore.alert('The message has been copied to clipboard.')
@@ -51,13 +57,18 @@ class CopyMultineValue extends React.Component<Props> {
   }
 
   render() {
+    let text = this.props.value
+    if (this.props.useDangerousHtml) {
+      text = <span dangerouslySetInnerHTML={{ __html: text }} />
+    }
+
     return (
       <Wrapper
         onClick={() => { this.handleCopy() }}
         data-test-id={(this.props && this.props['data-test-id']) || 'copyMultilineValue'}
       >
-        {this.props.value}
-        <CopyButton />
+        {text}
+        <CopyButtonStyled />
       </Wrapper>
     )
   }

+ 1 - 1
src/components/atoms/CopyMultilineValue/test.jsx

@@ -24,7 +24,7 @@ const wrap = props => shallow(<CopyMultilineValue value="" {...props} />)
 describe('CopyMultilineValue Component', () => {
   it('renders `value`', () => {
     const wrapper = wrap({ value: 'the_value' })
-    expect(wrapper.dive().text()).toBe('the_value<CopyButton />')
+    expect(wrapper.dive().text()).toBe('the_value<Styled(CopyButton) />')
   })
 
   it('copies `value` to clipboard', () => {

+ 5 - 5
src/components/organisms/EndpointDetailsContent/EndpointDetailsContent.jsx

@@ -41,12 +41,12 @@ const Info = styled.div`
   display: flex;
   flex-wrap: wrap;
   margin-top: 32px;
-  margin-left: -32px;  
+  margin-left: -32px;
 `
 const Field = styled.div`
   ${StyleProps.exactWidth('calc(50% - 32px)')}
   margin-bottom: 32px;
-  margin-left: 32px;  
+  margin-left: 32px;
 `
 const Label = styled.div`
   font-size: 10px;
@@ -172,15 +172,15 @@ class EndpointDetailsContent extends React.Component<Props> {
   }
 
   renderUsage(items: MainItem[]) {
-    return items.map((item, i) => (
+    return items.map(item => (
       <span>
         <Link
           key={item.id}
           href={`#/${item.type}/${item.id}`}
         >
-          {item.instances.join(', ')}
+          {item.instances[0]}
         </Link>
-        {i < items.length - 1 ? ', ' : ''}
+        <br />
       </span>
     ))
   }

+ 2 - 2
src/components/organisms/MainDetails/MainDetails.jsx

@@ -160,7 +160,7 @@ class MainDetails extends React.Component<Props> {
       }
     })
 
-    return vms.length === 0 ? 'Failed to read network configuration for the original instance' : vms.join(', ')
+    return vms.length === 0 ? '-' : vms.map(vm => <div data-test-id={`vm-${vm}`} style={{ marginBottom: '8px' }}>{vm}<br /></div>)
   }
 
   getNetworks() {
@@ -376,7 +376,7 @@ class MainDetails extends React.Component<Props> {
             <Row>
               <Field>
                 <Label>Instances</Label>
-                <CopyMultilineValue value={this.props.item.instances.join(', ')} />
+                <CopyMultilineValue value={this.props.item.instances.join('<br />')} useDangerousHtml />
               </Field>
             </Row>
           ) : null}

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

@@ -79,7 +79,7 @@ describe('MainDetails Component', () => {
     expect(tableItems.length).toBe(1)
     expect(tableItems[0].length).toBe(4)
     expect(tableItems[0][0]).toBe('network_1')
-    expect(tableItems[0][1][0]).toBe('instance_1')
+    expect(new TW(shallow(tableItems[0][1][0])).find('vm-', true).text()).toBe('instance_1')
     expect(tableItems[0][2]).toBe('Mapping 1')
     expect(tableItems[0][3]).toBe('Existing network')
     expect(wrapper.find('loading').length).toBe(0)

+ 15 - 14
src/components/organisms/WizardSummary/test.jsx

@@ -24,6 +24,19 @@ const wrap = props => new TW(shallow(
   <WizardSummary {...props} />
 ), 'wSummary')
 
+let schedules = [
+  {
+    id: 's-1',
+    schedule: {
+      month: 2,
+      dom: 14,
+      dow: 3,
+      minute: 0,
+      hour: 17,
+    },
+  },
+]
+
 let data = {
   options: {
     description: 'A description',
@@ -46,18 +59,6 @@ let data = {
     type: 'azure',
     name: 'target name',
   },
-  schedules: [
-    {
-      id: 's-1',
-      schedule: {
-        month: 2,
-        dom: 14,
-        dow: 3,
-        minute: 0,
-        hour: 17,
-      },
-    },
-  ],
 }
 
 describe('WizardSummary Component', () => {
@@ -90,8 +91,8 @@ describe('WizardSummary Component', () => {
   })
 
   it('renders schedule section', () => {
-    let wrapper = wrap({ data, wizardType: 'replica' })
-    expect(wrapper.findText(`scheduleItem-${data.schedules[0].id}`))
+    let wrapper = wrap({ data, schedules, wizardType: 'replica' })
+    expect(wrapper.findText(`scheduleItem-${schedules[0].id}`))
       .toBe('Every February, every 14th, every Wednesday, at 17:00')
   })
 })