2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
8 * ============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
26 import React, {Component} from 'react';
27 import {Button} from 'react-bootstrap';
28 import AutoSuggest from 'react-autosuggest';
29 import Highlighter from 'react-highlight-words';
30 import debounce from 'lodash.debounce';
31 import {ButtonGroup} from 'react-bootstrap';
32 import {Link} from 'react-router-dom';
34 import {changeUrlAddress} from 'utils/Routes.js';
41 SEARCH_PLACEHOLDER_TEXT
42 } from './AutoCompleteSearchBarConstants.js';
44 export default class AutoCompleteSearchBar extends Component {
46 value: React.PropTypes.string,
47 suggestions: React.PropTypes.array,
48 cachedSuggestions: React.PropTypes.array,
49 suggestionName: React.PropTypes.string
52 componentWillMount() {
53 this.debouncedLoadSuggestions =
54 debounce(this.props.onSuggestionsFetchRequested, SEARCH_DEBOUNCE_TIME);
57 onSuggestionsFetchRequested = ({value}) => {
58 this.debouncedLoadSuggestions({value});
61 isValidSearch(value) {
62 return (value && value !== NO_MATCHES_FOUND);
65 isValidSuggestionObject(suggestionObj) {
66 return (suggestionObj &&
67 Object.keys(suggestionObj).length > 0 &&
68 this.isValidSearch(suggestionObj.text));
71 getSelectedSuggestionObj(value, cachedSuggestions) {
72 let matchesSuggestion = {};
74 if (this.isValidSearch(value)) {
75 for (let suggestionIndex in cachedSuggestions) {
76 if (cachedSuggestions[suggestionIndex].text === value) {
77 matchesSuggestion = cachedSuggestions[suggestionIndex];
83 return matchesSuggestion;
87 cachedSuggestion, invalidSearchCallback, dispatchAnalytics, value) {
88 if (this.isValidSuggestionObject(cachedSuggestion)) {
89 changeUrlAddress(cachedSuggestion, this.props.history);
90 //Call analytics if defined
91 if (dispatchAnalytics) {
95 invalidSearchCallback(value);
102 suggestionName, cachedSuggestions,
103 onInputChange, onInvalidSearch,
104 onClearSuggestionsTextFieldRequested,
105 onSuggestionsClearRequested,
109 placeholder: SEARCH_PLACEHOLDER_TEXT,
111 onChange: onInputChange
114 let clearButtonClass = (value.length > 0)
115 ? 'auto-complete-clear-button'
116 : 'auto-complete-clear-button hidden';
118 <div className='auto-complete-search'>
120 suggestions={suggestions}
121 getSuggestionValue={suggestion => suggestion[suggestionName]}
122 onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
123 onSuggestionsClearRequested={onSuggestionsClearRequested}
124 onSuggestionSelected={(event, {suggestion}) => {
125 this.newSearchSelected(suggestion, onInvalidSearch, dispatchAnalytics, value);
126 this.props.onClearSuggestionsTextFieldRequested();
128 renderSuggestion={this.renderSuggestion}
129 inputProps={inputProps}
130 focusFirstSuggestion={false}
131 renderSuggestionsContainer={this.renderSuggestionsContainer}/>
132 <ButtonGroup className='auto-complete-search-button-group'>
133 <Button type='submit' className={clearButtonClass}
134 onClick={onClearSuggestionsTextFieldRequested}>
135 <i className={ICON_CLASS_CLEAR} aria-hidden='true'/>
138 <Button type='submit' className='auto-complete-search-button' onClick={() => {
139 this.newSearchSelected(this.getSelectedSuggestionObj(value, cachedSuggestions),
140 onInvalidSearch, dispatchAnalytics, value);
141 this.props.onSuggestionsClearRequested();
143 <i className={ICON_CLASS_SEARCH} aria-hidden='true'/>
150 renderSuggestion(suggestion, {query}) {
151 let toHighLightArray = query.split(' ');
152 let suggestionTextArray = suggestion.text.split(' ');
155 if (suggestion.text !== NO_MATCHES_FOUND) {
156 // render the suggestion as a clickable link
158 <div className='suggestionFlexContainer'>
159 <span key={'sugSpan1'}
160 className='suggestionColumnTwo'>
161 <Link style={{textDecoration: 'none'}}
162 to={'/' + suggestion.route + '/' + suggestion.hashId}
164 {suggestionTextArray.map(
167 <span key={arrayIndex + 'sugSpan3'}>
168 <Highlighter key={arrayIndex + 'high'}
169 highlightClassName='highlight'
170 searchWords={toHighLightArray}
171 textToHighlight={suggestionTextArray[arrayIndex]}/>
172 { ++arrayIndex ? ' ' : ' '}
180 // render the suggestion as plain text
182 <div className='suggestionFlexContainer'>
183 <span key={'sugSpan1'}
184 className='suggestionColumnTwo'>
185 {suggestionTextArray.map(
188 <span key={arrayIndex + 'sugSpan3'}>
189 <Highlighter key={arrayIndex + 'high'}
190 highlightClassName='highlight'
191 searchWords={toHighLightArray}
192 textToHighlight={suggestionTextArray[arrayIndex]}/>
193 { ++arrayIndex ? ' ' : ' '}
203 renderSuggestionsContainer({children, ...rest}) {
204 if (children !== null && children.props.items.length < 5) {
205 rest.className = 'react-autosuggest__suggestions-containerCopy';