aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java9
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java9
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java14
-rw-r--r--server/sonar-web/src/main/js/apps/code/actions/index.js5
-rw-r--r--server/sonar-web/src/main/js/apps/code/components/Search.js12
-rw-r--r--server/sonar-web/src/main/js/apps/code/styles/code.css11
7 files changed, 66 insertions, 7 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
index 09a7efdb496..292b77400e7 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/TreeAction.java
@@ -73,6 +73,7 @@ import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_STR
public class TreeAction implements ComponentsWsAction {
private static final int MAX_SIZE = 500;
+ private static final int QUERY_MINIMUM_LENGTH = 3;
private static final String ALL_STRATEGY = "all";
private static final String CHILDREN_STRATEGY = "children";
private static final String LEAVES_STRATEGY = "leaves";
@@ -125,10 +126,11 @@ public class TreeAction implements ComponentsWsAction {
.setExampleValue(NAME_SORT + ", " + PATH_SORT);
action.createParam(Param.TEXT_QUERY)
- .setDescription("Limit search to: <ul>" +
+ .setDescription(format("Limit search to: <ul>" +
"<li>component names that contain the supplied string</li>" +
"<li>component keys that are exactly the same as the supplied string</li>" +
- "</ul>")
+ "</ul>" +
+ "Must have at least %d characters", QUERY_MINIMUM_LENGTH))
.setExampleValue("FILE_NAM");
createQualifiersParameter(action, newQualifierParameterContext(userSession, i18n, resourceTypes));
@@ -292,6 +294,9 @@ public class TreeAction implements ComponentsWsAction {
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
checkRequest(treeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
+ String searchQuery = treeWsRequest.getQuery();
+ checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
+ "The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
return treeWsRequest;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
index 7f903223247..f7850a85908 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/ComponentTreeAction.java
@@ -75,6 +75,7 @@ import static org.sonarqube.ws.client.measure.MeasuresWsParameters.PARAM_STRATEG
*/
public class ComponentTreeAction implements MeasuresWsAction {
private static final int MAX_SIZE = 500;
+ private static final int QUERY_MINIMUM_LENGTH = 3;
static final String ALL_STRATEGY = "all";
static final String CHILDREN_STRATEGY = "children";
static final String LEAVES_STRATEGY = "leaves";
@@ -120,10 +121,11 @@ public class ComponentTreeAction implements MeasuresWsAction {
.setExampleValue(NAME_SORT + ", " + PATH_SORT);
action.createParam(Param.TEXT_QUERY)
- .setDescription("Limit search to: <ul>" +
+ .setDescription(format("Limit search to: <ul>" +
"<li>component names that contain the supplied string</li>" +
"<li>component keys that are exactly the same as the supplied string</li>" +
- "</ul>")
+ "</ul>" +
+ "Must have at least %d characters.", QUERY_MINIMUM_LENGTH))
.setExampleValue("FILE_NAM");
action.createParam(PARAM_BASE_COMPONENT_ID)
@@ -243,6 +245,9 @@ public class ComponentTreeAction implements MeasuresWsAction {
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
.setQuery(request.param(Param.TEXT_QUERY));
checkRequest(componentTreeWsRequest.getPageSize() <= MAX_SIZE, "The '%s' parameter must be less than %d", Param.PAGE_SIZE, MAX_SIZE);
+ String searchQuery = componentTreeWsRequest.getQuery();
+ checkRequest(searchQuery == null || searchQuery.length() >= QUERY_MINIMUM_LENGTH,
+ "The '%s' parameter must have at least %d characters", Param.TEXT_QUERY, QUERY_MINIMUM_LENGTH);
String metricSortValue = componentTreeWsRequest.getMetricSort();
checkRequest(!componentTreeWsRequest.getMetricKeys().isEmpty(), "The '%s' parameter must contain at least one metric key", PARAM_METRIC_KEYS);
checkRequest(metricSortValue == null ^ componentTreeWsRequest.getSort().contains(METRIC_SORT),
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java
index 015d4e35673..85c78b149af 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/TreeActionTest.java
@@ -306,6 +306,19 @@ public class TreeActionTest {
}
@Test
+ public void fail_when_search_query_has_less_than_3_characters() {
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("The 'q' parameter must have at least 3 characters");
+ componentDb.insertComponent(newProjectDto("project-uuid"));
+ db.commit();
+
+ ws.newRequest()
+ .setParam(PARAM_BASE_COMPONENT_ID, "project-uuid")
+ .setParam(Param.TEXT_QUERY, "fi")
+ .execute();
+ }
+
+ @Test
public void fail_when_sort_is_unknown() {
expectedException.expect(IllegalArgumentException.class);
componentDb.insertComponent(newProjectDto("project-uuid"));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
index 7ed74774d4b..4461b351508 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/ComponentTreeActionTest.java
@@ -317,6 +317,20 @@ public class ComponentTreeActionTest {
}
@Test
+ public void fail_when_search_query_have_less_than_3_characters() {
+ componentDb.insertProjectAndSnapshot(newProjectDto("project-uuid"));
+ insertNclocMetric();
+ insertNewViolationsMetric();
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage("The 'q' parameter must have at least 3 characters");
+
+ call(ws.newRequest()
+ .setParam(PARAM_BASE_COMPONENT_ID, "project-uuid")
+ .setParam(PARAM_METRIC_KEYS, "ncloc, new_violations")
+ .setParam(Param.TEXT_QUERY, "fi"));
+ }
+
+ @Test
public void fail_when_insufficient_privileges() {
userSession.anonymous().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
componentDb.insertProjectAndSnapshot(newProjectDto("project-uuid"));
diff --git a/server/sonar-web/src/main/js/apps/code/actions/index.js b/server/sonar-web/src/main/js/apps/code/actions/index.js
index a89e78786f5..6bca96a7b02 100644
--- a/server/sonar-web/src/main/js/apps/code/actions/index.js
+++ b/server/sonar-web/src/main/js/apps/code/actions/index.js
@@ -222,7 +222,10 @@ debouncedSearch = _.debounce(debouncedSearch, 250);
export function search (query, baseComponent) {
return dispatch => {
dispatch(updateQueryAction(query));
- debouncedSearch(query, baseComponent, dispatch);
+
+ if (query.length > 2 || !query.length) {
+ debouncedSearch(query, baseComponent, dispatch);
+ }
};
}
diff --git a/server/sonar-web/src/main/js/apps/code/components/Search.js b/server/sonar-web/src/main/js/apps/code/components/Search.js
index 60522b0f759..97cba288b03 100644
--- a/server/sonar-web/src/main/js/apps/code/components/Search.js
+++ b/server/sonar-web/src/main/js/apps/code/components/Search.js
@@ -19,8 +19,10 @@
*/
import React, { Component } from 'react';
import { connect } from 'react-redux';
+import classNames from 'classnames';
import { search, selectCurrent, selectNext, selectPrev } from '../actions';
+import { translateWithParameters } from '../../../helpers/l10n';
class Search extends Component {
@@ -44,7 +46,7 @@ class Search extends Component {
dispatch(selectNext());
break;
default:
- // do nothing
+ // do nothing
}
}
@@ -57,6 +59,9 @@ class Search extends Component {
render () {
const { query } = this.props;
+ const inputClassName = classNames('search-box-input', {
+ 'touched': query.length > 0 && query.length < 3
+ });
return (
<form
@@ -70,12 +75,15 @@ class Search extends Component {
onKeyDown={this.handleKeyDown.bind(this)}
onChange={this.handleSearch.bind(this)}
value={query}
- className="search-box-input"
+ className={inputClassName}
type="search"
name="q"
placeholder="Search"
maxLength="100"
autoComplete="off"/>
+ <div className="note">
+ {translateWithParameters('select2.tooShort', 3)}
+ </div>
</form>
);
}
diff --git a/server/sonar-web/src/main/js/apps/code/styles/code.css b/server/sonar-web/src/main/js/apps/code/styles/code.css
index 3577f7f341e..f5ffda5a8e0 100644
--- a/server/sonar-web/src/main/js/apps/code/styles/code.css
+++ b/server/sonar-web/src/main/js/apps/code/styles/code.css
@@ -49,3 +49,14 @@
float: left;
padding-right: 10px;
}
+
+.code-search-box .note {
+ margin-top: 4px;
+ margin-left: 25px;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+.code-search-box input.touched ~ .note {
+ opacity: 1;
+}