diff --git a/docma-config.json b/docma-config.json
index 474ed400d8..9085a54d7e 100644
--- a/docma-config.json
+++ b/docma-config.json
@@ -199,6 +199,7 @@
"web/client/plugins/GlobeViewSwitcher.jsx",
"web/client/plugins/GoFull.jsx",
"web/client/plugins/Map.jsx",
+ "web/client/plugins/MapSearch.jsx",
"web/client/plugins/Measure.jsx",
"web/client/plugins/MeasurePanel.jsx",
"web/client/plugins/MeasureResults.jsx",
diff --git a/web/client/components/mapcontrols/search/SearchBar.jsx b/web/client/components/mapcontrols/search/SearchBar.jsx
index d410aa7437..f39a5e43ec 100644
--- a/web/client/components/mapcontrols/search/SearchBar.jsx
+++ b/web/client/components/mapcontrols/search/SearchBar.jsx
@@ -1,20 +1,21 @@
-const PropTypes = require('prop-types');
/*
* Copyright 2015, GeoSolutions Sas.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
- */
+*/
-var React = require('react');
-var {FormControl, FormGroup, Glyphicon, Tooltip} = require('react-bootstrap');
+const PropTypes = require('prop-types');
+const React = require('react');
+const {FormControl, FormGroup, Glyphicon, Tooltip} = require('react-bootstrap');
const OverlayTrigger = require('../../misc/OverlayTrigger');
-var LocaleUtils = require('../../../utils/LocaleUtils');
-var Spinner = require('react-spinkit');
+const LocaleUtils = require('../../../utils/LocaleUtils');
+const Spinner = require('react-spinkit');
+const assign = require('object-assign');
-var delay = (
+const delay = (
function() {
var timer = 0;
return function(callback, ms) {
@@ -36,6 +37,8 @@ require('./searchbar.css');
* @prop {function} onCancelSelectedItem triggered when the user deletes the selected item (by hitting backspace) when text is empty
* @prop {string} placeholder string to use as placeholder when text is empty
* @prop {string} placeholderMsgId msgId for the placeholder. Used if placeholder is not defined
+ * @prop {string} removeIcon glyphicon used for reset button, default 1-close
+ * @prop {string} searchIcon glyphicon used for search button, default search
* @prop {number} delay milliseconds after trigger onSearch if typeAhead is true
* @prop {boolean} hideOnBlur if true, it triggers onPurgeResults on blur
* @prop {boolean} typeAhead if true, onSearch is triggered when users change the search text, after `delay` milliseconds
@@ -43,6 +46,7 @@ require('./searchbar.css');
* @prop {searchText} the text to display in the component
* @prop {object[]} selectedItems the items selected. Must have `text` property to display
* @prop {boolean} autoFocusOnSelect if true, the component gets focus when items are added, or deleted but some item is still selected. Useful for continue writing after selecting an item (with nested services for instance)
+ * @prop {boolean} splitTools if false, the search and reset can appear both at the same time, otherwise the search appear only with empty text, the reset if a text is entered
* @prop {boolean} loading if true, shows the loading tool
* @prop {object} error if not null, an error icon will be display
* @prop {object} style css style to apply to the component
@@ -64,8 +68,11 @@ class SearchBar extends React.Component {
blurResetDelay: PropTypes.number,
typeAhead: PropTypes.bool,
searchText: PropTypes.string,
+ removeIcon: PropTypes.string,
+ searchIcon: PropTypes.string,
selectedItems: PropTypes.array,
autoFocusOnSelect: PropTypes.bool,
+ splitTools: PropTypes.bool,
loading: PropTypes.bool,
error: PropTypes.object,
style: PropTypes.object,
@@ -84,9 +91,12 @@ class SearchBar extends React.Component {
onCancelSelectedItem: () => {},
selectedItems: [],
placeholderMsgId: "search.placeholder",
+ removeIcon: "1-close",
+ searchIcon: "search",
delay: 1000,
blurResetDelay: 300,
autoFocusOnSelect: true,
+ splitTools: true,
hideOnBlur: true,
typeAhead: true,
searchText: ""
@@ -138,6 +148,17 @@ class SearchBar extends React.Component {
}
};
+ getSpinnerStyle = () => {
+ const nonSplittedStyle = {
+ right: "19px",
+ top: "7px"
+ };
+ const splittedStyle = {
+ right: "16px",
+ top: "12px"
+ };
+ return assign({}, {position: "absolute"}, this.props.splitTools ? {...splittedStyle} : {...nonSplittedStyle} );
+ }
renderAddonBefore = () => {
return this.props.selectedItems && this.props.selectedItems.map((item, index) =>
{item.text}
@@ -145,15 +166,12 @@ class SearchBar extends React.Component {
};
renderAddonAfter = () => {
- const remove = ;
- var showRemove = this.props.searchText !== "" || this.props.selectedItems && this.props.selectedItems.length > 0;
- let addonAfter = showRemove ? [remove] : [];
+ const remove = ;
+ const search = ;
+ const showRemove = this.props.searchText !== "" || this.props.selectedItems && this.props.selectedItems.length > 0;
+ let addonAfter = showRemove ? (this.props.splitTools ? [remove] : [remove, search]) : [search];
if (this.props.loading) {
- addonAfter = [, addonAfter];
+ addonAfter = [, addonAfter];
}
if (this.props.error) {
let tooltip = {this.props.error && this.props.error.message || null};
diff --git a/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx b/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx
index 767ae5109a..27583119cb 100644
--- a/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx
+++ b/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx
@@ -197,4 +197,39 @@ describe("test the SearchBar", () => {
done();
}, 10);
});
+
+ it('test search and reset buttons both present, splitTools=false', () => {
+ const tb = ReactDOM.render(, document.getElementById("container"));
+ let reset = TestUtils.findRenderedDOMComponentWithClass(tb, "searchclear");
+ let search = TestUtils.findRenderedDOMComponentWithClass(tb, "magnifying-glass");
+ expect(reset).toExist();
+ expect(search).toExist();
+ });
+ it('test only search present, splitTools=false', () => {
+ const tb = ReactDOM.render(, document.getElementById("container"));
+ let reset = TestUtils.scryRenderedDOMComponentsWithClass(tb, "searchclear");
+ expect(reset.length).toBe(0);
+
+ let search = TestUtils.findRenderedDOMComponentWithClass(tb, "magnifying-glass");
+ expect(search).toExist();
+ });
+
+
+ it('test only search present, splitTools=true', () => {
+ const tb = ReactDOM.render(, document.getElementById("container"));
+ let reset = TestUtils.scryRenderedDOMComponentsWithClass(tb, "searchclear");
+ expect(reset.length).toBe(0);
+
+ let search = TestUtils.findRenderedDOMComponentWithClass(tb, "magnifying-glass");
+ expect(search).toExist();
+ });
+
+ it('test only reset present, splitTools=true', () => {
+ const tb = ReactDOM.render(, document.getElementById("container"));
+ let reset = TestUtils.findRenderedDOMComponentWithClass(tb, "searchclear");
+ expect(reset).toExist();
+
+ let search = TestUtils.scryRenderedDOMComponentsWithClass(tb, "magnifying-glass");
+ expect(search.length).toBe(0);
+ });
});
diff --git a/web/client/examples/3dviewer/containers/Viewer.jsx b/web/client/examples/3dviewer/containers/Viewer.jsx
index 5460735277..befd2ff970 100644
--- a/web/client/examples/3dviewer/containers/Viewer.jsx
+++ b/web/client/examples/3dviewer/containers/Viewer.jsx
@@ -111,7 +111,7 @@ class Viewer extends React.Component {
}}>
-
+
({
className: "maps-search",
hideOnBlur: false,
@@ -26,10 +37,11 @@ const SearchBar = connect((state) => ({
return loadMaps(ConfigUtils.getDefaults().geoStoreUrl, searchText, options);
},
onSearchReset: loadMaps.bind(null, ConfigUtils.getDefaults().geoStoreUrl, ConfigUtils.getDefaults().initialMapFilter || "*")
-}, (stateProps, dispatchProps) => {
+}, (stateProps, dispatchProps, ownProps) => {
return {
...stateProps,
+ ...ownProps,
onSearch: (text) => {
let limit = stateProps.limit;
dispatchProps.onSearch(text, {start: 0, limit});
diff --git a/web/client/themes/default/less/map-search-bar.less b/web/client/themes/default/less/map-search-bar.less
index 556eecc4bc..84cf7a99e3 100644
--- a/web/client/themes/default/less/map-search-bar.less
+++ b/web/client/themes/default/less/map-search-bar.less
@@ -17,10 +17,16 @@ div.MapSearchBar .input-group-addon {
font-size: @icon-size;
}
+.MapSearchBar .input-group-addon .magnifying-glass:hover,
+.MapSearchBar .input-group-addon .searchclear:hover {
+ opacity: 0.75
+}
+
+.MapSearchBar .input-group-addon .magnifying-glass,
.MapSearchBar .input-group-addon .searchclear,
.MapSearchBar .input-group-addon .searcherror {
- font-size: @icon-size-md;
margin-right: 4px;
+ cursor: pointer
}
.MapSearchBar .input-group-addon .searcherror {