[SDC-29] Amdocs OnBoard 1707 initial commit.
[sdc.git] / openecomp-ui / src / nfvo-components / input / dualListbox / DualListboxView.jsx
1 /*!
2  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16 import React from 'react';
17 import SVGIcon from 'nfvo-components/icon/SVGIcon.jsx';
18 import Input from 'nfvo-components/input/validation/InputWrapper.jsx';
19
20 class DualListboxView extends React.Component {
21
22         static propTypes = {
23
24                 availableList: React.PropTypes.arrayOf(React.PropTypes.shape({
25                         id: React.PropTypes.string.isRequired,
26                         name: React.PropTypes.string.isRequired
27                 })),
28                 filterTitle: React.PropTypes.shape({
29                         left: React.PropTypes.string,
30                         right: React.PropTypes.string
31                 }),
32                 selectedValuesList: React.PropTypes.arrayOf(React.PropTypes.string),
33
34                 onChange: React.PropTypes.func.isRequired
35         };
36
37         static defaultProps = {
38                 selectedValuesList: [],
39                 availableList: [],
40                 filterTitle: {
41                         left: '',
42                         right: ''
43                 }
44         };
45
46         state = {
47                 availableListFilter: '',
48                 selectedValuesListFilter: '',
49                 selectedValues: []
50         };
51
52         render() {
53                 let {availableList, selectedValuesList, filterTitle, isReadOnlyMode} = this.props;
54                 let {availableListFilter, selectedValuesListFilter} = this.state;
55
56                 let unselectedList = availableList.filter(availableItem => !selectedValuesList.find(value => value === availableItem.id));
57                 let selectedList = availableList.filter(availableItem => selectedValuesList.find(value => value === availableItem.id));
58                 selectedList = selectedList.sort((a, b) => selectedValuesList.indexOf(a.id) - selectedValuesList.indexOf(b.id));
59                 return (
60                         <div className='dual-list-box'>
61                                 {this.renderListbox(filterTitle.left, unselectedList, {
62                                         value: availableListFilter,
63                                         ref: 'availableListFilter',
64                                         disabled: isReadOnlyMode,
65                                         onChange: (value) => this.setState({availableListFilter: value})
66                                 }, {ref: 'availableValues', disabled: isReadOnlyMode, testId: 'available',})}
67                                 {this.renderOperationsBar(isReadOnlyMode)}
68                                 {this.renderListbox(filterTitle.right, selectedList, {
69                                         value: selectedValuesListFilter,
70                                         ref: 'selectedValuesListFilter',
71                                         disabled: isReadOnlyMode,
72                                         onChange: (value) => this.setState({selectedValuesListFilter: value})
73                                 }, {ref: 'selectedValues', disabled: isReadOnlyMode, testId: 'selected'})}
74                         </div>
75                 );
76         }
77
78         renderListbox(filterTitle, list, filterProps, props) {
79                 let regExFilter = new RegExp(escape(filterProps.value), 'i');
80                 let matchedItems = list.filter(item => item.name.match(regExFilter));
81                 let unMatchedItems = list.filter(item => !item.name.match(regExFilter));
82                 return (
83                         <div className='dual-search-multi-select-section'>
84                                 <p>{filterTitle}</p>
85                                 <div className='dual-text-box-search search-wrapper'>
86                                         <Input data-test-id={`${props.testId}-search-input`}
87                                                    name='search-input-control' type='text'
88                                                    groupClassName='search-input-control'
89                                                    {...filterProps}/>
90                                         <SVGIcon name='search' className='search-icon'/>
91                                 </div>
92                                 <Input
93                                         multiple
94                                         onChange={(event) => this.onSelectItems(event.target.selectedOptions)}
95                                         groupClassName='dual-list-box-multi-select'
96                                         type='select'
97                                         name='dual-list-box-multi-select'
98                                         data-test-id={`${props.testId}-select-input`}
99                                         disabled={props.disabled}
100                                         ref={props.ref}>
101                                         {matchedItems.map(item => this.renderOption(item.id, item.name))}
102                                         {matchedItems.length && unMatchedItems.length && <option style={{pointerEvents: 'none'}}>--------------------</option>}
103                                         {unMatchedItems.map(item => this.renderOption(item.id, item.name))}
104                                 </Input>
105                         </div>
106                 );
107         }
108
109         onSelectItems(selectedOptions) {
110                 let selectedValues = Object.keys(selectedOptions).map((k) => selectedOptions[k].value);
111                 this.setState({selectedValues});
112         }
113
114         renderOption(value, name) {
115                 return (<option className='dual-list-box-multi-select-text' key={value} value={value}>{name}</option>);
116         }
117
118         renderOperationsBar(isReadOnlyMode) {
119                 return (
120                         <div className={`dual-list-options-bar${isReadOnlyMode ? ' disabled' : ''}`}>
121                                 {this.renderOperationBarButton(() => this.addToSelectedList(), 'angle-right')}
122                                 {this.renderOperationBarButton(() => this.removeFromSelectedList(), 'angle-left')}
123                                 {this.renderOperationBarButton(() => this.addAllToSelectedList(), 'angle-double-right')}
124                                 {this.renderOperationBarButton(() => this.removeAllFromSelectedList(), 'angle-double-left')}
125                         </div>
126                 );
127         }
128
129         renderOperationBarButton(onClick, iconName){
130                 return (<div className='dual-list-option' data-test-id={`operation-icon-${iconName}`} onClick={onClick}><SVGIcon name={iconName}/></div>);
131         }
132
133         addToSelectedList() {
134                 this.props.onChange(this.props.selectedValuesList.concat(this.state.selectedValues));
135                 this.setState({selectedValues: []});
136         }
137
138         removeFromSelectedList() {
139                 const selectedValues = this.state.selectedValues;
140                 this.props.onChange(this.props.selectedValuesList.filter(value => !selectedValues.find(selectedValue => selectedValue === value)));
141                 this.setState({selectedValues: []});
142         }
143
144         addAllToSelectedList() {
145                 this.props.onChange(this.props.availableList.map(item => item.id));
146         }
147
148         removeAllFromSelectedList() {
149                 this.props.onChange([]);
150         }
151 }
152
153 export default DualListboxView;