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

Improve duplicated items in the dropdown component

For each duplicated item in a dropdown list, display its ID value bellow
its label, this makes it much more easier to understand what's actually
selected. No changes should be seen if there're no duplicated items.

For a quick test of this feature, create an endpoint with the same name
as an existing one, go to Wizard's source or target selection page and
open the dropdown containing the duplicated endpoint names.
Sergiu Miclea 8 лет назад
Родитель
Сommit
dcde890bc6

+ 11 - 7
private/storybook/Decorator.jsx

@@ -15,7 +15,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // @flow
 // @flow
 
 
 import * as React from 'react'
 import * as React from 'react'
-import styled from 'styled-components'
+import styled, { injectGlobal } from 'styled-components'
 import Palette from '../../src/components/styleUtils/Palette'
 import Palette from '../../src/components/styleUtils/Palette'
 import StyleProps from '../../src/components/styleUtils/StyleProps'
 import StyleProps from '../../src/components/styleUtils/StyleProps'
 
 
@@ -23,12 +23,16 @@ const Wrapper = styled.div`
   display: inline-block;
   display: inline-block;
   background: ${Palette.grayscale[7]};
   background: ${Palette.grayscale[7]};
   padding: 32px;
   padding: 32px;
-  color: ${Palette.black};
-  font-family: Rubik;
-  font-size: 14px;
-  font-weight: ${StyleProps.fontWeights.regular};
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
+`
+injectGlobal`
+  body {
+    color: ${Palette.black};
+    font-family: Rubik;
+    font-size: 14px;
+    font-weight: ${StyleProps.fontWeights.regular};
+    -webkit-font-smoothing: antialiased;
+    -moz-osx-font-smoothing: grayscale;
+  }
 `
 `
 
 
 type Props = {
 type Props = {

+ 38 - 4
src/components/molecules/Dropdown/index.jsx

@@ -87,11 +87,21 @@ const ListItem = styled.div`
     color: white;
     color: white;
   }
   }
 `
 `
+const DuplicatedLabel = styled.div`
+  display: flex;
+  font-size: 11px;
+  span {
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    overflow: hidden;
+  }
+`
 
 
 type Props = {
 type Props = {
   selectedItem: any,
   selectedItem: any,
   items: any[],
   items: any[],
   labelField: string,
   labelField: string,
+  valueField: string,
   className: string,
   className: string,
   onChange: (item: any) => void,
   onChange: (item: any) => void,
   noItemsMessage: string,
   noItemsMessage: string,
@@ -153,6 +163,16 @@ class Dropdown extends React.Component<Props, State> {
     return (item[labelField] !== null && item[labelField] !== undefined && item[labelField].toString()) || item.toString()
     return (item[labelField] !== null && item[labelField] !== undefined && item[labelField].toString()) || item.toString()
   }
   }
 
 
+  getValue(item: any) {
+    let valueField = this.props.valueField || 'value'
+
+    if (item === null || item === undefined) {
+      return null
+    }
+
+    return (item[valueField] !== null && item[valueField] !== undefined && item[valueField].toString()) || this.getLabel(item)
+  }
+
   handlePageClick() {
   handlePageClick() {
     if (!this.itemMouseDown) {
     if (!this.itemMouseDown) {
       this.setState({ showDropdownList: false })
       this.setState({ showDropdownList: false })
@@ -220,23 +240,37 @@ class Dropdown extends React.Component<Props, State> {
     }
     }
 
 
     const body: any = document.body
     const body: any = document.body
-    let selectedLabel = this.getLabel(this.props.selectedItem)
+    let selectedValue = this.getValue(this.props.selectedItem)
+    let duplicatedLabels = []
+    this.props.items.forEach((item, i) => {
+      let label = this.getLabel(item)
+      for (let j = i + 1; j < this.props.items.length; j += 1) {
+        if (label === this.getLabel(this.props.items[j]) && !duplicatedLabels.find(item2 => this.getLabel(item2) === label)) {
+          duplicatedLabels.push(label)
+        }
+      }
+    })
+
     let list = ReactDOM.createPortal((
     let list = ReactDOM.createPortal((
       <List {...this.props} innerRef={ref => { this.listRef = ref }}>
       <List {...this.props} innerRef={ref => { this.listRef = ref }}>
         <Tip innerRef={ref => { this.tipRef = ref }} primary={this.state.firstItemHover} />
         <Tip innerRef={ref => { this.tipRef = ref }} primary={this.state.firstItemHover} />
         <ListItems>
         <ListItems>
           {this.props.items.map((item, i) => {
           {this.props.items.map((item, i) => {
             let label = this.getLabel(item)
             let label = this.getLabel(item)
+            let value = this.getValue(item)
+            let duplicatedLabel = duplicatedLabels.find(l => l === label)
             let listItem = (
             let listItem = (
               <ListItem
               <ListItem
-                key={label}
+                key={value}
                 onMouseDown={() => { this.itemMouseDown = true }}
                 onMouseDown={() => { this.itemMouseDown = true }}
                 onMouseUp={() => { this.itemMouseDown = false }}
                 onMouseUp={() => { this.itemMouseDown = false }}
                 onMouseEnter={() => { this.handleItemMouseEnter(i) }}
                 onMouseEnter={() => { this.handleItemMouseEnter(i) }}
                 onMouseLeave={() => { this.handleItemMouseLeave(i) }}
                 onMouseLeave={() => { this.handleItemMouseLeave(i) }}
                 onClick={() => { this.handleItemClick(item) }}
                 onClick={() => { this.handleItemClick(item) }}
-                selected={label === selectedLabel}
-              >{label}
+                selected={value === selectedValue}
+              >
+                {label}
+                {duplicatedLabel ? <DuplicatedLabel> (<span>{value || ''}</span>)</DuplicatedLabel> : ''}
               </ListItem>
               </ListItem>
             )
             )
 
 

+ 1 - 0
src/components/molecules/Dropdown/story.jsx

@@ -20,6 +20,7 @@ const items = [
   { label: 'Item 1', value: 'item-1' },
   { label: 'Item 1', value: 'item-1' },
   { label: 'Item 2', value: 'item-2' },
   { label: 'Item 2', value: 'item-2' },
   { label: 'Item 3', value: 'item-3' },
   { label: 'Item 3', value: 'item-3' },
+  { label: 'Item 3', value: 'item-3-duplicated' },
 ]
 ]
 
 
 class Wrapper extends React.Component {
 class Wrapper extends React.Component {

+ 1 - 1
src/components/molecules/WizardOptionsField/index.jsx

@@ -120,7 +120,7 @@ class WizardOptionsField extends React.Component<Props> {
       <Dropdown
       <Dropdown
         width={320}
         width={320}
         noSelectionMessage="Choose a value"
         noSelectionMessage="Choose a value"
-        selectedItem={selectedItem ? selectedItem.label : null}
+        selectedItem={selectedItem}
         items={items}
         items={items}
         onChange={item => this.props.onChange(item.value)}
         onChange={item => this.props.onChange(item.value)}
       />
       />

+ 1 - 0
src/components/organisms/WizardEndpointList/index.jsx

@@ -96,6 +96,7 @@ class WizardEndpointList extends React.Component<Props> {
         <Dropdown
         <Dropdown
           primary={Boolean(selectedItem)}
           primary={Boolean(selectedItem)}
           items={items}
           items={items}
+          valueField="id"
           labelField="name"
           labelField="name"
           noSelectionMessage="Select"
           noSelectionMessage="Select"
           centered
           centered

+ 3 - 5
src/components/organisms/WizardNetworks/index.jsx

@@ -173,10 +173,7 @@ class WizardNetworks extends React.Component<Props> {
             }
             }
             return false
             return false
           }).map(i => i.instance_name)
           }).map(i => i.instance_name)
-          let selectedNetworkName = this.props.selectedNetworks && this.props.selectedNetworks.find(n => n.sourceNic.network_name === nic.network_name)
-          if (selectedNetworkName) {
-            selectedNetworkName = selectedNetworkName.targetNetwork.name
-          }
+          let selectedNetwork = this.props.selectedNetworks && this.props.selectedNetworks.find(n => n.sourceNic.network_name === nic.network_name)
           return (
           return (
             <Nic key={nic.id}>
             <Nic key={nic.id}>
               <NetworkImage />
               <NetworkImage />
@@ -190,9 +187,10 @@ class WizardNetworks extends React.Component<Props> {
                 centered
                 centered
                 noSelectionMessage="Select ..."
                 noSelectionMessage="Select ..."
                 noItemsMessage="No networks found"
                 noItemsMessage="No networks found"
-                selectedItem={selectedNetworkName}
+                selectedItem={selectedNetwork ? selectedNetwork.targetNetwork : null}
                 items={this.props.networks}
                 items={this.props.networks}
                 labelField="name"
                 labelField="name"
+                valueField="id"
                 onChange={(item: Network) => { this.props.onChange(nic, item) }}
                 onChange={(item: Network) => { this.props.onChange(nic, item) }}
               />
               />
             </Nic>
             </Nic>