diff options
author | Jenkins CI <ci@sonarsource.com> | 2015-12-09 17:31:06 +0100 |
---|---|---|
committer | Jenkins CI <ci@sonarsource.com> | 2015-12-09 17:31:06 +0100 |
commit | 0102d8108a6b40e3876ace01f1df0afbdeb37ddc (patch) | |
tree | 65eff5d83243d57292d1614b37f00ff975914543 | |
parent | 1342b253edd4d79be057ceb8905b0919525d140f (diff) | |
parent | a749013e0af281ac0eb19f35fe9f282f3bc80121 (diff) | |
download | sonarqube-0102d8108a6b40e3876ace01f1df0afbdeb37ddc.tar.gz sonarqube-0102d8108a6b40e3876ace01f1df0afbdeb37ddc.zip |
Automatic merge from branch-5.3
* origin/branch-5.3:
hide number of failing tasks on then project level page
SONAR-6887 Improve message when missing revision or date on blame
SONAR-6900 Add IT to simulate a build breaker strategy
increase contract of leak period background
improve display of leak period caption
add tooltips for ncloc distribution chart
love ie11
improve scales of the bubble chart on the overview page
fix tooltips on the overview treemap
filter out empty components on the overview treemap
normalize overview pages urls and titles
improve code quality
69 files changed, 465 insertions, 245 deletions
diff --git a/it/it-tests/src/test/java/it/Category1Suite.java b/it/it-tests/src/test/java/it/Category1Suite.java index 97489650fcc..2bcf718ffa9 100644 --- a/it/it-tests/src/test/java/it/Category1Suite.java +++ b/it/it-tests/src/test/java/it/Category1Suite.java @@ -52,6 +52,7 @@ import it.measureHistory.HistoryUiTest; import it.measureHistory.SincePreviousVersionHistoryTest; import it.measureHistory.SinceXDaysHistoryTest; import it.measureHistory.TimeMachineTest; +import it.projectAdministration.BackgroundTasksTest; import it.projectAdministration.BulkDeletionTest; import it.projectAdministration.ProjectAdministrationTest; import it.projectOverview.ProjectOverviewTest; @@ -76,6 +77,7 @@ import static util.ItUtils.xooPlugin; // project administration BulkDeletionTest.class, ProjectAdministrationTest.class, + BackgroundTasksTest.class, // project pages ProjectOverviewTest.class, // settings diff --git a/it/it-tests/src/test/java/it/projectAdministration/BackgroundTasksTest.java b/it/it-tests/src/test/java/it/projectAdministration/BackgroundTasksTest.java new file mode 100644 index 00000000000..93b92400d90 --- /dev/null +++ b/it/it-tests/src/test/java/it/projectAdministration/BackgroundTasksTest.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package it.projectAdministration; + +import com.sonar.orchestrator.Orchestrator; +import com.sonar.orchestrator.build.SonarRunner; +import com.sonar.orchestrator.selenium.Selenese; +import it.Category1Suite; +import org.junit.ClassRule; +import org.junit.Test; +import util.selenium.SeleneseTest; + +import static util.ItUtils.projectDir; + +public class BackgroundTasksTest { + + @ClassRule + public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; + + @Test + public void should_not_display_failing_and_search_and_filter_elements_on_project_level_page() throws Exception { + executeBuild("test-project", "Test Project"); + executeBuild("test-project-2", "Another Test Project"); + + Selenese selenese = Selenese.builder().setHtmlTestsInClasspath("should_not_display_failing_and_search_and_filter_elements_on_project_level_page", + "/projectAdministration/BackgroundTasksTest/should_not_display_failing_and_search_and_filter_elements_on_project_level_page.html" + ).build(); + new SeleneseTest(selenese).runOn(orchestrator); + } + + private void executeBuild(String projectKey, String projectName) { + orchestrator.executeBuild( + SonarRunner.create(projectDir("shared/xoo-sample")) + .setProjectKey(projectKey) + .setProjectName(projectName) + ); + } +} diff --git a/it/it-tests/src/test/java/it/qualityGate/QualityGateTest.java b/it/it-tests/src/test/java/it/qualityGate/QualityGateTest.java index 39006cc4c09..21f68c4cba9 100644 --- a/it/it-tests/src/test/java/it/qualityGate/QualityGateTest.java +++ b/it/it-tests/src/test/java/it/qualityGate/QualityGateTest.java @@ -8,7 +8,14 @@ package it.qualityGate; import com.sonar.orchestrator.Orchestrator; import com.sonar.orchestrator.build.SonarRunner; import it.Category1Suite; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.Properties; +import org.apache.commons.io.FileUtils; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Test; import org.sonar.wsclient.project.NewProject; @@ -18,23 +25,37 @@ import org.sonar.wsclient.qualitygate.QualityGateClient; import org.sonar.wsclient.services.Measure; import org.sonar.wsclient.services.Resource; import org.sonar.wsclient.services.ResourceQuery; +import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.WsCe; +import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse; +import org.sonarqube.ws.client.GetRequest; +import org.sonarqube.ws.client.WsClient; +import org.sonarqube.ws.client.WsResponse; +import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest; import static org.assertj.core.api.Assertions.assertThat; +import static util.ItUtils.newAdminWsClient; import static util.ItUtils.projectDir; public class QualityGateTest { private static final String PROJECT_KEY = "sample"; - private long provisionnedProjectId = -1L; + private long provisionedProjectId = -1L; @ClassRule public static Orchestrator orchestrator = Category1Suite.ORCHESTRATOR; + static WsClient wsClient; + + @BeforeClass + public static void startOrchestrator() { + wsClient = newAdminWsClient(orchestrator); + } @Before public void cleanUp() { orchestrator.resetData(); - provisionnedProjectId = Long.parseLong(orchestrator.getServer().adminWsClient().projectClient().create(NewProject.create().key(PROJECT_KEY).name("Sample")).id()); + provisionedProjectId = Long.parseLong(orchestrator.getServer().adminWsClient().projectClient().create(NewProject.create().key(PROJECT_KEY).name("Sample")).id()); } @Test @@ -121,7 +142,7 @@ public class QualityGateTest { qgClient().createCondition(NewCondition.create(error.id()).metricKey("ncloc").operator("GT").errorThreshold("10")); qgClient().setDefault(alert.id()); - qgClient().selectProject(error.id(), provisionnedProjectId); + qgClient().selectProject(error.id(), provisionedProjectId); try { SonarRunner build = SonarRunner.create(projectDir("qualitygate/xoo-sample")); @@ -159,6 +180,54 @@ public class QualityGateTest { } } + @Test + public void ad_hoc_build_break_strategy() throws IOException { + QualityGate simple = qgClient().create("SimpleWithLowThresholdForBuildBreakStrategy"); + qgClient().setDefault(simple.id()); + qgClient().createCondition(NewCondition.create(simple.id()).metricKey("ncloc").operator("GT").errorThreshold("7")); + + try { + File projectDir = projectDir("qualitygate/xoo-sample"); + SonarRunner build = SonarRunner.create(projectDir); + orchestrator.executeBuild(build); + + String taskId = getTaskIdInLocalReport(projectDir); + String analysisId = getAnalysisId(taskId); + + ProjectStatusWsResponse projectStatusWsResponse = wsClient.qualityGates().projectStatus(new ProjectStatusWsRequest().setAnalysisId(analysisId)); + ProjectStatusWsResponse.ProjectStatus projectStatus = projectStatusWsResponse.getProjectStatus(); + assertThat(projectStatus.getStatus()).isEqualTo(ProjectStatusWsResponse.Status.ERROR); + assertThat(projectStatus.getConditionsCount()).isEqualTo(1); + ProjectStatusWsResponse.Condition condition = projectStatus.getConditionsList().get(0); + assertThat(condition.getMetricKey()).isEqualTo("ncloc"); + assertThat(condition.getErrorThreshold()).isEqualTo("7"); + } finally { + qgClient().unsetDefault(); + qgClient().destroy(simple.id()); + } + } + + private String getAnalysisId(String taskId) throws IOException { + WsResponse activity = wsClient + .wsConnector() + .call(new GetRequest("api/ce/task") + .setParam("id", taskId) + .setMediaType(MediaTypes.PROTOBUF)); + WsCe.TaskResponse activityWsResponse = WsCe.TaskResponse.parseFrom(activity.contentStream()); + return activityWsResponse.getTask().getAnalysisId(); + } + + private String getTaskIdInLocalReport(File projectDirectory) throws IOException { + File metadata = new File(projectDirectory, ".sonar/report-task.txt"); + assertThat(metadata).exists().isFile(); + // verify properties + Properties props = new Properties(); + props.load(new StringReader(FileUtils.readFileToString(metadata, StandardCharsets.UTF_8))); + assertThat(props.getProperty("ceTaskId")).isNotEmpty(); + + return props.getProperty("ceTaskId"); + } + private Measure fetchGateStatus() { return fetchResourceWithGateStatus().getMeasure("alert_status"); } diff --git a/it/it-tests/src/test/resources/projectAdministration/BackgroundTasksTest/should_not_display_failing_and_search_and_filter_elements_on_project_level_page.html b/it/it-tests/src/test/resources/projectAdministration/BackgroundTasksTest/should_not_display_failing_and_search_and_filter_elements_on_project_level_page.html new file mode 100644 index 00000000000..06f59df2058 --- /dev/null +++ b/it/it-tests/src/test/resources/projectAdministration/BackgroundTasksTest/should_not_display_failing_and_search_and_filter_elements_on_project_level_page.html @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> +<head profile="http://selenium-ide.openqa.org/profiles/test-case"> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <link rel="selenium.base" href="http://localhost:49506"/> + <title>should_not_display_failing_and_search_and_filter_elements_on_project_level_page</title> +</head> +<body> +<table cellpadding="1" cellspacing="1" border="1"> + <thead> + <tr> + <td rowspan="1" colspan="3">should_not_display_failing_and_search_and_filter_elements_on_project_level_page</td> + </tr> + </thead> + <tbody> + <tr> + <td>open</td> + <td>/sonar/sessions/logout</td> + <td></td> +</tr> +<tr> + <td>open</td> + <td>/sonar/sessions/login</td> + <td></td> +</tr> +<tr> + <td>type</td> + <td>login</td> + <td>admin</td> +</tr> +<tr> + <td>type</td> + <td>password</td> + <td>admin</td> +</tr> +<tr> + <td>clickAndWait</td> + <td>commit</td> + <td></td> +</tr> +<tr> + <td>open</td> + <td>/sonar/project/background_tasks?id=test-project</td> + <td></td> +</tr> +<tr> + <td>waitForElementPresent</td> + <td>css=.background-tasks .badge</td> + <td></td> +</tr> +<tr> + <td>assertNotText</td> + <td>css=.background-tasks</td> + <td>*Another Test Project*</td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>css=.search-box</td> + <td></td> +</tr> +<tr> + <td>assertNotText</td> + <td>css=#content</td> + <td>*still failing*</td> +</tr> +<tr> + <td>assertElementNotPresent</td> + <td>css=.icon-filter</td> + <td></td> +</tr> +</tbody> +</table> +</body> +</html> diff --git a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_it_coverage_on_project_overview.html b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_it_coverage_on_project_overview.html index db38e860191..f5788966cbd 100644 --- a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_it_coverage_on_project_overview.html +++ b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_it_coverage_on_project_overview.html @@ -26,7 +26,7 @@ </tr> <tr> <td>open</td> - <td>/sonar/overview/tests?id=project-for-overview-it-coverage</td> + <td>/sonar/overview/coverage?id=project-for-overview-it-coverage</td> <td></td> </tr> <tr> diff --git a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_overall_coverage_on_project_overview.html b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_overall_coverage_on_project_overview.html index 9d5fd67fee2..96b6bba216f 100644 --- a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_overall_coverage_on_project_overview.html +++ b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_overall_coverage_on_project_overview.html @@ -26,7 +26,7 @@ </tr> <tr> <td>open</td> - <td>/sonar/overview/tests?id=project-for-overview-overall-coverage</td> + <td>/sonar/overview/coverage?id=project-for-overview-overall-coverage</td> <td></td> </tr> <tr> diff --git a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_ut_coverage_on_project_overview.html b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_ut_coverage_on_project_overview.html index fd88d0fc0aa..1dd3c9ccd27 100644 --- a/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_ut_coverage_on_project_overview.html +++ b/it/it-tests/src/test/resources/projectOverview/ProjectOverviewTest/test_ut_coverage_on_project_overview.html @@ -26,7 +26,7 @@ </tr> <tr> <td>open</td> - <td>/sonar/overview/tests?id=project-for-overview-ut-coverage</td> + <td>/sonar/overview/coverage?id=project-for-overview-ut-coverage</td> <td></td> </tr> <tr> diff --git a/server/sonar-web/.eslintrc b/server/sonar-web/.eslintrc index 19e2098c50f..77cfb1f6edd 100644 --- a/server/sonar-web/.eslintrc +++ b/server/sonar-web/.eslintrc @@ -14,21 +14,17 @@ }, "globals": { - "define": true, - "require": true, - "numeral": true, "key": true, "d3": true, - "baseUrl": true, - "t": true, - "tp": true + "baseUrl": true }, "parser": "babel-eslint", "plugins": [ "react", - "mocha" + "mocha", + "import" ], "rules": { @@ -74,6 +70,12 @@ "react/prop-types": 0, "react/react-in-jsx-scope": 2, "react/self-closing-comp": 2, - "react/sort-comp": 1 + "react/sort-comp": 1, + + "import/no-unresolved": 2, + "import/named": 2, + "import/export": 2, + "import/no-duplicates": 2, + "import/imports-first": 2 } } diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json index 38d0e420486..04d8169b95a 100644 --- a/server/sonar-web/package.json +++ b/server/sonar-web/package.json @@ -19,6 +19,7 @@ "d3": "3.5.6", "del": "2.0.2", "eslint": "^1.10.3", + "eslint-plugin-import": "^0.11.0", "eslint-plugin-mocha": "^1.1.0", "eslint-plugin-react": "^3.11.3", "event-stream": "3.3.1", diff --git a/server/sonar-web/src/main/js/apps/account/change-password-view.js b/server/sonar-web/src/main/js/apps/account/change-password-view.js index 6bd5d992b21..4df1c081161 100644 --- a/server/sonar-web/src/main/js/apps/account/change-password-view.js +++ b/server/sonar-web/src/main/js/apps/account/change-password-view.js @@ -10,7 +10,7 @@ export default ModalForm.extend({ if (this.checkPasswords()) { this.sendRequest(); } else { - this.showErrors([{ msg: t('user.password_doesnt_match_confirmation') }]); + this.showErrors([{ msg: window.t('user.password_doesnt_match_confirmation') }]); } }, diff --git a/server/sonar-web/src/main/js/apps/background-tasks/main.js b/server/sonar-web/src/main/js/apps/background-tasks/main.js index 02fa64391e1..521d3e36556 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/main.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/main.js @@ -171,8 +171,7 @@ export default React.createClass({ statusFilter: STATUSES.FAILED, currentsFilter: CURRENTS.ONLY_CURRENTS, activityPage: 1 - }, - this.requestActivity); + }, this.requestActivity); }, onTaskCanceled(task) { @@ -192,23 +191,31 @@ export default React.createClass({ <div className="page"> <Header/> - <Stats {...this.state} cancelPending={this.cancelPending} showFailures={this.showFailures}/> + <Stats + {...this.props} + {...this.state} + cancelPending={this.cancelPending} + showFailures={this.showFailures}/> - <Search {...this.props} {...this.state} + <Search + {...this.props} + {...this.state} refresh={this.requestData} onStatusChange={this.onStatusChange} onCurrentsChange={this.onCurrentsChange} onDateChange={this.onDateChange} onSearch={this.onSearch}/> - <Tasks {...this.props} + <Tasks + {...this.props} tasks={[].concat(this.state.queue, this.state.activity)} onTaskCanceled={this.onTaskCanceled} onFilter={this.handleFilter}/> - <ListFooter count={this.state.queue.length + this.state.activity.length} - total={this.state.queue.length + this.state.activityTotal} - loadMore={this.loadMore}/> + <ListFooter + count={this.state.queue.length + this.state.activity.length} + total={this.state.queue.length + this.state.activityTotal} + loadMore={this.loadMore}/> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/stats.js b/server/sonar-web/src/main/js/apps/background-tasks/stats.js index 308d7e4d8a8..2383f8d76fa 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/stats.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/stats.js @@ -61,6 +61,11 @@ export default React.createClass({ if (this.props.failuresCount == null) { return null; } + + if (this.props.options.component) { + return null; + } + if (this.props.failuresCount > 0) { return ( <span> diff --git a/server/sonar-web/src/main/js/apps/coding-rules/app.js b/server/sonar-web/src/main/js/apps/coding-rules/app.js index 61089511594..feb040c3562 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/app.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/app.js @@ -63,7 +63,7 @@ var App = new Marionette.Application(), App.manualRepository = function () { return { key: 'manual', - name: t('coding_rules.manual_rule'), + name: window.t('coding_rules.manual_rule'), language: 'none' }; }; diff --git a/server/sonar-web/src/main/js/apps/coding-rules/bulk-change-modal-view.js b/server/sonar-web/src/main/js/apps/coding-rules/bulk-change-modal-view.js index d816c21c219..453aa8fd107 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/bulk-change-modal-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/bulk-change-modal-view.js @@ -15,14 +15,14 @@ export default ModalFormView.extend({ showSuccessMessage: function (profile, succeeded) { var profileBase = _.findWhere(this.options.app.qualityProfiles, { key: profile }), profileName = profileBase != null ? profileBase.name : profile, - message = tp('coding_rules.bulk_change.success', profileName, profileBase.language, succeeded); + message = window.tp('coding_rules.bulk_change.success', profileName, profileBase.language, succeeded); this.ui.messagesContainer.append('<div class="alert alert-success">' + message + '</div>'); }, showWarnMessage: function (profile, succeeded, failed) { var profileBase = _.findWhere(this.options.app.qualityProfiles, { key: profile }), profileName = profileBase != null ? profileBase.name : profile, - message = tp('coding_rules.bulk_change.warning', profileName, profileBase.language, succeeded, failed); + message = window.tp('coding_rules.bulk_change.warning', profileName, profileBase.language, succeeded, failed); this.ui.messagesContainer.append('<div class="alert alert-warning">' + message + '</div>'); }, diff --git a/server/sonar-web/src/main/js/apps/coding-rules/facets/active-severity-facet.js b/server/sonar-web/src/main/js/apps/coding-rules/facets/active-severity-facet.js index 2062e292b99..2ab853c763a 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/facets/active-severity-facet.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/facets/active-severity-facet.js @@ -26,7 +26,7 @@ export default BaseFacet.extend({ forbid: function () { BaseFacet.prototype.forbid.apply(this, arguments); - this.$el.prop('title', t('coding_rules.filters.active_severity.inactive')); + this.$el.prop('title', window.t('coding_rules.filters.active_severity.inactive')); }, allow: function () { diff --git a/server/sonar-web/src/main/js/apps/coding-rules/facets/custom-values-facet.js b/server/sonar-web/src/main/js/apps/coding-rules/facets/custom-values-facet.js index 9b2e01ef70a..bf3739cf70c 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/facets/custom-values-facet.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/facets/custom-values-facet.js @@ -22,17 +22,17 @@ export default BaseFacet.extend({ prepareSearch: function () { this.$('.js-custom-value').select2({ - placeholder: t('search_verb'), + placeholder: window.t('search_verb'), minimumInputLength: 1, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 1); + return window.tp('select2.tooShort', 1); }, width: '100%', ajax: this.prepareAjaxSearch() diff --git a/server/sonar-web/src/main/js/apps/coding-rules/facets/inheritance-facet.js b/server/sonar-web/src/main/js/apps/coding-rules/facets/inheritance-facet.js index d72f47e4584..490498a13cb 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/facets/inheritance-facet.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/facets/inheritance-facet.js @@ -30,7 +30,7 @@ export default BaseFacet.extend({ forbid: function () { BaseFacet.prototype.forbid.apply(this, arguments); - this.$el.prop('title', t('coding_rules.filters.inheritance.inactive')); + this.$el.prop('title', window.t('coding_rules.filters.inheritance.inactive')); }, allow: function () { @@ -42,7 +42,7 @@ export default BaseFacet.extend({ var values = ['NONE', 'INHERITED', 'OVERRIDES']; return values.map(function (key) { return { - label: t('coding_rules.filters.inheritance', key.toLowerCase()), + label: window.t('coding_rules.filters.inheritance', key.toLowerCase()), val: key }; }); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/facets/status-facet.js b/server/sonar-web/src/main/js/apps/coding-rules/facets/status-facet.js index 23b0e41e089..fa453552567 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/facets/status-facet.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/facets/status-facet.js @@ -7,7 +7,7 @@ export default BaseFacet.extend({ getValues: function () { var values = this.model.getValues(); var x = values.map(function (value) { - return _.extend(value, { label: t('rules.status', value.val.toLowerCase()) }); + return _.extend(value, { label: window.t('rules.status', value.val.toLowerCase()) }); }); return x; }, diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule-details-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule-details-view.js index f8dee5b02cd..87ae705c660 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule-details-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule-details-view.js @@ -130,8 +130,8 @@ export default Marionette.LayoutView.extend({ var that = this, ruleType = this.model.has('templateKey') ? 'custom' : 'manual'; confirmDialog({ - title: t('delete'), - html: tp('coding_rules.delete.' + ruleType + '.confirm', this.model.get('name')), + title: window.t('delete'), + html: window.tp('coding_rules.delete.' + ruleType + '.confirm', this.model.get('name')), yesHandler: function () { var url = baseUrl + '/api/rules/delete', options = { key: that.model.id }; diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-creation-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-creation-view.js index ff0da3c7803..b4712e1c15e 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-creation-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-creation-view.js @@ -153,7 +153,7 @@ export default ModalFormView.extend({ }).fail(function (jqXHR) { if (jqXHR.status === 409) { that.existingRule = jqXHR.responseJSON.rule; - that.showErrors([], [{ msg: t('coding_rules.reactivate.help') }]); + that.showErrors([], [{ msg: window.t('coding_rules.reactivate.help') }]); that.ui.customRuleCreationCreate.addClass('hidden'); that.ui.customRuleCreationReactivate.removeClass('hidden'); } else { @@ -175,7 +175,7 @@ export default ModalFormView.extend({ var statuses = ['READY', 'BETA', 'DEPRECATED'].map(function (status) { return { id: status, - text: t('rules.status', status.toLowerCase()) + text: window.t('rules.status', status.toLowerCase()) }; }); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-view.js index 6e7002ba587..791334b4a0f 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule/custom-rule-view.js @@ -19,8 +19,8 @@ export default Marionette.ItemView.extend({ deleteRule: function () { var that = this; confirmDialog({ - title: t('delete'), - html: t('are_you_sure'), + title: window.t('delete'), + html: window.t('are_you_sure'), yesHandler: function () { var url = baseUrl + '/api/rules/delete', options = { key: that.model.id }; diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule/manual-rule-creation-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule/manual-rule-creation-view.js index cb0869490d0..dab19f1fb13 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule/manual-rule-creation-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule/manual-rule-creation-view.js @@ -99,7 +99,7 @@ export default ModalFormView.extend({ }).fail(function (jqXHR) { if (jqXHR.status === 409) { that.existingRule = jqXHR.responseJSON.rule; - that.showErrors([], [{ msg: t('coding_rules.reactivate.help') }]); + that.showErrors([], [{ msg: window.t('coding_rules.reactivate.help') }]); that.ui.manualRuleCreationCreate.addClass('hidden'); that.ui.manualRuleCreationReactivate.removeClass('hidden'); } else { diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-description-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-description-view.js index c1a2bc458e5..9b88e3267ce 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-description-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-description-view.js @@ -64,7 +64,7 @@ export default Marionette.ItemView.extend({ removeExtendedDescription: function () { var that = this; confirmDialog({ - html: t('coding_rules.remove_extended_description.confirm'), + html: window.t('coding_rules.remove_extended_description.confirm'), yesHandler: function () { that.ui.extendDescriptionText.val(''); that.submitExtendDescription(); diff --git a/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-profile-view.js b/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-profile-view.js index 1c74fc9dd63..6139044cbf6 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-profile-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/rule/rule-profile-view.js @@ -50,8 +50,8 @@ export default Marionette.ItemView.extend({ var that = this, ruleKey = this.options.rule.get('key'); confirmDialog({ - title: t('coding_rules.revert_to_parent_definition'), - html: tp('coding_rules.revert_to_parent_definition.confirm', this.getParent().name), + title: window.t('coding_rules.revert_to_parent_definition'), + html: window.tp('coding_rules.revert_to_parent_definition.confirm', this.getParent().name), yesHandler: function () { return $.ajax({ type: 'POST', @@ -72,8 +72,8 @@ export default Marionette.ItemView.extend({ var that = this, ruleKey = this.options.rule.get('key'); confirmDialog({ - title: t('coding_rules.deactivate'), - html: tp('coding_rules.deactivate.confirm'), + title: window.t('coding_rules.deactivate'), + html: window.tp('coding_rules.deactivate.confirm'), yesHandler: function () { return $.ajax({ type: 'POST', @@ -137,5 +137,3 @@ export default Marionette.ItemView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-empty-view.js b/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-empty-view.js index 6563efc2e3a..5045ff3891d 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-empty-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-empty-view.js @@ -4,8 +4,6 @@ export default Marionette.ItemView.extend({ className: 'search-navigator-no-results', template: function () { - return t('coding_rules.no_results'); + return window.t('coding_rules.no_results'); } }); - - diff --git a/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-item-view.js b/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-item-view.js index 5897372020b..05e54964103 100644 --- a/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-item-view.js +++ b/server/sonar-web/src/main/js/apps/coding-rules/workspace-list-item-view.js @@ -62,8 +62,8 @@ export default WorkspaceListItemView.extend(RuleFilterMixin).extend({ ruleKey = this.model.get('key'), activation = this.model.get('activation'); confirmDialog({ - title: t('coding_rules.deactivate'), - html: tp('coding_rules.deactivate.confirm'), + title: window.t('coding_rules.deactivate'), + html: window.tp('coding_rules.deactivate.confirm'), yesHandler: function () { return $.ajax({ type: 'POST', diff --git a/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js index 6567912ab1e..ec9d1a2966e 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/author-facet.js @@ -11,13 +11,13 @@ export default CustomValuesFacet.extend({ minimumInputLength: 2, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 2); + return window.tp('select2.tooShort', 2); }, width: '100%', ajax: { @@ -38,5 +38,3 @@ export default CustomValuesFacet.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js index bf86b4970fb..e9bb08d5853 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/custom-values-facet.js @@ -26,13 +26,13 @@ export default BaseFacet.extend({ minimumInputLength: 2, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 2); + return window.tp('select2.tooShort', 2); }, width: '100%', ajax: this.prepareAjaxSearch() @@ -65,5 +65,3 @@ export default BaseFacet.extend({ return this.options.app.state.updateFilter(obj); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js index c3d6f274420..e1d48fd5ac2 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/language-facet.js @@ -12,13 +12,13 @@ export default CustomValuesFacet.extend({ minimumInputLength: 2, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 2); + return window.tp('select2.tooShort', 2); }, width: '100%', ajax: { @@ -62,5 +62,3 @@ export default CustomValuesFacet.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js index 5c8eef0fd0e..b4657f808df 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/project-facet.js @@ -28,13 +28,13 @@ export default CustomValuesFacet.extend({ minimumInputLength: 2, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 2); + return window.tp('select2.tooShort', 2); }, width: '100%', ajax: { @@ -78,5 +78,3 @@ export default CustomValuesFacet.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js index 8d50f462c0e..d049890807b 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/rule-facet.js @@ -13,13 +13,13 @@ export default CustomValuesFacet.extend({ minimumInputLength: 2, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, formatInputTooShort: function () { - return tp('select2.tooShort', 2); + return window.tp('select2.tooShort', 2); }, width: '100%', ajax: { @@ -74,5 +74,3 @@ export default CustomValuesFacet.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js index 291bcf6f393..52b0a49c5bb 100644 --- a/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js +++ b/server/sonar-web/src/main/js/apps/issues/facets/tag-facet.js @@ -13,10 +13,10 @@ export default CustomValuesFacet.extend({ minimumInputLength: 0, allowClear: false, formatNoMatches: function () { - return t('select2.noMatches'); + return window.t('select2.noMatches'); }, formatSearching: function () { - return t('select2.searching'); + return window.t('select2.searching'); }, width: '100%', ajax: { @@ -50,5 +50,3 @@ export default CustomValuesFacet.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js b/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js index b40c68d0ab6..391dbbfd461 100644 --- a/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js +++ b/server/sonar-web/src/main/js/apps/issues/workspace-list-empty-view.js @@ -4,8 +4,6 @@ export default Marionette.ItemView.extend({ className: 'search-navigator-no-results', template: function () { - return t('issue_filter.no_issues'); + return window.t('issue_filter.no_issues'); } }); - - diff --git a/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js b/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js index 25db1cddea3..6400d512f54 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js +++ b/server/sonar-web/src/main/js/apps/overview/components/domain-timeline.js @@ -177,7 +177,7 @@ export const DomainTimeline = React.createClass({ <Select value={this.state.currentMetric} options={optionsWithDomains} clearable={false} - className="input-large" + style={{ width: 170 }} onChange={this.handleMetricChange}/> </span>; }, @@ -216,7 +216,7 @@ export const DomainTimeline = React.createClass({ <Select value={this.state.comparisonMetric} options={optionsWithDomains} placeholder="Compare with..." - className="input-large" + style={{ width: 170 }} onChange={this.handleComparisonMetricChange}/> </span>; }, diff --git a/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js b/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js index 033a791ead4..03253cbcf5a 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js +++ b/server/sonar-web/src/main/js/apps/overview/components/domain-treemap.js @@ -95,20 +95,21 @@ export class DomainTreemap extends React.Component { return this.renderLoading(); } - // TODO filter out zero sized components - let items = this.state.components.map(component => { - let colorMeasure = this.props.colorMetric ? component.measures[this.props.colorMetric] : null; - return { - key: component.key, - name: component.name, - qualifier: component.qualifier, - size: component.measures[this.props.sizeMetric], - color: colorMeasure != null ? this.props.scale(colorMeasure) : '#777', - tooltip: this.getTooltip(component), - label: component.name, - link: getComponentUrl(component.key) - }; - }); + let items = this.state.components + .filter(component => component.measures[this.props.sizeMetric]) + .map(component => { + let colorMeasure = this.props.colorMetric ? component.measures[this.props.colorMetric] : null; + return { + key: component.key, + name: component.name, + qualifier: component.qualifier, + size: component.measures[this.props.sizeMetric], + color: colorMeasure != null ? this.props.scale(colorMeasure) : '#777', + tooltip: this.getTooltip(component), + label: component.name, + link: getComponentUrl(component.key) + }; + }); const canBeClicked = node => node.qualifier !== 'FIL' && node.qualifier !== 'UTS'; diff --git a/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js b/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js index 764457ad403..0a24b77c65d 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js +++ b/server/sonar-web/src/main/js/apps/overview/components/ncloc-distribution.js @@ -65,7 +65,12 @@ export const NclocDistribution = React.createClass({ data = _.sortBy(data, d => -d.x); - let yTicks = data.map(d => collapsePath(d.value, 20)); + let yTicks = data.map(d => { + return { + label: collapsePath(d.value, 20), + tooltip: d.value + }; + }); let yValues = data.map(d => formatMeasure(d.x, 'SHORT_INT')); diff --git a/server/sonar-web/src/main/js/apps/overview/components/timeline-chart.js b/server/sonar-web/src/main/js/apps/overview/components/timeline-chart.js index e82f5a3c457..83b0f711b6b 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/timeline-chart.js +++ b/server/sonar-web/src/main/js/apps/overview/components/timeline-chart.js @@ -111,7 +111,7 @@ export const Timeline = React.createClass({ y: _.last(yScale.range()), width: xScale.range()[1] - xScale(this.props.leakPeriodDate), height: _.first(yScale.range()) - _.last(yScale.range()), - fill: '#fffae7' + fill: '#fbf3d5' }; return <rect {...opts}/>; }, diff --git a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js index 4ee8ce45476..d87d3dc5e70 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/debt-domain.js @@ -27,7 +27,7 @@ const KNOWN_METRICS = ['violations', 'sqale_index', 'sqale_rating', 'sqale_debt_ 'critical_violations', 'major_violations', 'minor_violations', 'info_violations', 'confirmed_issues']; -export const IssuesMain = React.createClass({ +export const DebtMain = React.createClass({ mixins: [TooltipsMixin], getInitialState() { diff --git a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js index 2223139a760..861e82ad2b5 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/duplications-domain.js @@ -8,13 +8,12 @@ import { DomainTreemap } from '../components/domain-treemap'; import { DomainBubbleChart } from '../components/domain-bubble-chart'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { TooltipsMixin } from '../../../components/mixins/tooltips-mixin'; -import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; +import { filterMetrics, filterMetricsForDomains, getMetricName } from '../helpers/metrics'; import { DomainLeakTitle } from '../main/components'; import { CHART_COLORS_RANGE_PERCENT } from '../../../helpers/constants'; import { formatMeasure, formatMeasureVariation } from '../../../helpers/measures'; import { DonutChart } from '../../../components/charts/donut-chart'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; -import { getMetricName } from '../helpers/metrics'; export const DuplicationsMain = React.createClass({ diff --git a/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js b/server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js index 05a23ae3d51..3c1563bde01 100644 --- a/server/sonar-web/src/main/js/apps/overview/domains/size-domain.js +++ b/server/sonar-web/src/main/js/apps/overview/domains/structure-domain.js @@ -12,7 +12,7 @@ import { filterMetrics, filterMetricsForDomains } from '../helpers/metrics'; import { DomainLeakTitle } from '../main/components'; -export const SizeMain = React.createClass({ +export const StructureMain = React.createClass({ mixins: [TooltipsMixin], getInitialState() { @@ -149,7 +149,7 @@ export const SizeMain = React.createClass({ return <div className="overview-detailed-page"> <div className="overview-card"> <div className="overview-card-header"> - <div className="overview-title">{window.t('overview.domain.size')}</div> + <div className="overview-title">{window.t('overview.domain.structure')}</div> {this.renderLegend()} </div> diff --git a/server/sonar-web/src/main/js/apps/overview/main/coverage.js b/server/sonar-web/src/main/js/apps/overview/main/coverage.js index 07aaff0c383..7755cb28df7 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/coverage.js +++ b/server/sonar-web/src/main/js/apps/overview/main/coverage.js @@ -85,9 +85,11 @@ export const GeneralCoverage = React.createClass({ ]; return <Domain> - <DomainHeader component={this.props.component} title={window.t('overview.domain.coverage')} linkTo="/tests"/> + <DomainHeader component={this.props.component} + title={window.t('overview.domain.coverage')} + linkTo="/coverage"/> - <DomainPanel domain="coverage"> + <DomainPanel> <DomainNutshell> <MeasuresList> diff --git a/server/sonar-web/src/main/js/apps/overview/main/issues.js b/server/sonar-web/src/main/js/apps/overview/main/debt.js index 86a145596e2..490eadc22c8 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/issues.js +++ b/server/sonar-web/src/main/js/apps/overview/main/debt.js @@ -18,7 +18,7 @@ import { getMetricName } from '../helpers/metrics'; import { formatMeasure } from '../../../helpers/measures'; -export const GeneralIssues = React.createClass({ +export const GeneralDebt = React.createClass({ propTypes: { leakPeriodLabel: React.PropTypes.string, leakPeriodDate: React.PropTypes.object @@ -56,9 +56,11 @@ export const GeneralIssues = React.createClass({ render () { return <Domain> - <DomainHeader component={this.props.component} title={window.t('overview.domain.debt')} linkTo="/issues"/> + <DomainHeader component={this.props.component} + title={window.t('overview.domain.debt')} + linkTo="/debt"/> - <DomainPanel domain="issues"> + <DomainPanel> <DomainNutshell> <MeasuresList> diff --git a/server/sonar-web/src/main/js/apps/overview/main/duplications.js b/server/sonar-web/src/main/js/apps/overview/main/duplications.js index 64cafcf8932..6240df80417 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/duplications.js +++ b/server/sonar-web/src/main/js/apps/overview/main/duplications.js @@ -57,10 +57,11 @@ export const GeneralDuplications = React.createClass({ ]; return <Domain> - <DomainHeader component={this.props.component} title={window.t('overview.domain.duplications')} + <DomainHeader component={this.props.component} + title={window.t('overview.domain.duplications')} linkTo="/duplications"/> - <DomainPanel domain="duplications"> + <DomainPanel> <DomainNutshell> <MeasuresList> diff --git a/server/sonar-web/src/main/js/apps/overview/main/main.js b/server/sonar-web/src/main/js/apps/overview/main/main.js index 39e17057257..81eabb769f4 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/main.js +++ b/server/sonar-web/src/main/js/apps/overview/main/main.js @@ -2,10 +2,10 @@ import _ from 'underscore'; import moment from 'moment'; import React from 'react'; -import { GeneralIssues } from './issues'; +import { GeneralDebt } from './debt'; import { GeneralCoverage } from './coverage'; import { GeneralDuplications } from './duplications'; -import { GeneralSize } from './size'; +import { GeneralStructure } from './structure'; import { CoverageSelectionMixin } from '../components/coverage-selection-mixin'; import { getPeriodLabel, getPeriodDate } from './../helpers/periods'; import { getMeasuresAndVariations } from '../../../api/measures'; @@ -146,11 +146,11 @@ export default React.createClass({ let props = _.extend({}, this.props, this.state); return <div className="overview-domains-list"> - <GeneralIssues {...props} history={this.state.history['sqale_index']}/> + <GeneralDebt {...props} history={this.state.history['sqale_index']}/> <GeneralCoverage {...props} coverageMetricPrefix={this.state.coverageMetricPrefix} history={this.state.history[coverageMetric]}/> <GeneralDuplications {...props} history={this.state.history['duplicated_lines_density']}/> - <GeneralSize {...props} history={this.state.history['ncloc']}/> + <GeneralStructure {...props} history={this.state.history['ncloc']}/> </div>; } }); diff --git a/server/sonar-web/src/main/js/apps/overview/main/size.js b/server/sonar-web/src/main/js/apps/overview/main/structure.js index d1138a87f13..a823614a498 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/size.js +++ b/server/sonar-web/src/main/js/apps/overview/main/structure.js @@ -15,7 +15,7 @@ import { formatMeasure, formatMeasureVariation } from '../../../helpers/measures import { LanguageDistribution } from '../components/language-distribution'; -export const GeneralSize = React.createClass({ +export const GeneralStructure = React.createClass({ propTypes: { leakPeriodLabel: React.PropTypes.string, leakPeriodDate: React.PropTypes.object @@ -51,9 +51,11 @@ export const GeneralSize = React.createClass({ render () { return <Domain> - <DomainHeader component={this.props.component} title={window.t('overview.domain.size')} linkTo="/size"/> + <DomainHeader component={this.props.component} + title={window.t('overview.domain.structure')} + linkTo="/structure"/> - <DomainPanel domain="size"> + <DomainPanel> <DomainNutshell> <MeasuresList> {this.renderLanguageDistribution()} diff --git a/server/sonar-web/src/main/js/apps/overview/overview.js b/server/sonar-web/src/main/js/apps/overview/overview.js index 8301fd6add4..706f8b68d2e 100644 --- a/server/sonar-web/src/main/js/apps/overview/overview.js +++ b/server/sonar-web/src/main/js/apps/overview/overview.js @@ -3,10 +3,10 @@ import React from 'react'; import Gate from './gate/gate'; import GeneralMain from './main/main'; import Meta from './meta'; -import { SizeMain } from './domains/size-domain'; +import { StructureMain } from './domains/structure-domain'; import { DuplicationsMain } from './domains/duplications-domain'; import { CoverageMain } from './domains/coverage-domain'; -import { IssuesMain } from './domains/debt-domain'; +import { DebtMain } from './domains/debt-domain'; import { getMetrics } from '../../api/metrics'; import { RouterMixin } from '../../components/router/router'; @@ -45,7 +45,7 @@ export const Overview = React.createClass({ renderSize () { return <div className="overview"> - <SizeMain {...this.props} {...this.state}/> + <StructureMain {...this.props} {...this.state}/> </div>; }, @@ -63,7 +63,7 @@ export const Overview = React.createClass({ renderIssues () { return <div className="overview"> - <IssuesMain {...this.props} {...this.state}/> + <DebtMain {...this.props} {...this.state}/> </div>; }, @@ -74,13 +74,13 @@ export const Overview = React.createClass({ switch (this.state.route) { case '': return this.renderMain(); - case '/size': + case '/structure': return this.renderSize(); case '/duplications': return this.renderDuplications(); - case '/tests': + case '/coverage': return this.renderTests(); - case '/issues': + case '/debt': return this.renderIssues(); default: throw new Error('Unknown route: ' + this.state.route); diff --git a/server/sonar-web/src/main/js/apps/projects/form-view.js b/server/sonar-web/src/main/js/apps/projects/form-view.js index c5e12ab40d8..8f8951c7b1a 100644 --- a/server/sonar-web/src/main/js/apps/projects/form-view.js +++ b/server/sonar-web/src/main/js/apps/projects/form-view.js @@ -1,5 +1,4 @@ -import ModalForm from 'components/common/modal-form'; -import './templates'; +import ModalForm from '../../components/common/modal-form'; export default ModalForm.extend({ @@ -19,5 +18,3 @@ export default ModalForm.extend({ } }); - - diff --git a/server/sonar-web/src/main/js/apps/quality-gates/gate-condition-view.js b/server/sonar-web/src/main/js/apps/quality-gates/gate-condition-view.js index 9ab319a78e7..fef2d7638ac 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/gate-condition-view.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/gate-condition-view.js @@ -90,11 +90,9 @@ export default Marionette.ItemView.extend({ return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { canEdit: this.options.canEdit, periods: this.options.periods, - periodText: period ? period.text : t('value'), + periodText: period ? period.text : window.t('value'), metric: this.getMetric(), isDiffMetric: this.isDiffMetric() }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/quality-gates/gate-conditions-view.js b/server/sonar-web/src/main/js/apps/quality-gates/gate-conditions-view.js index 4994a9da37b..e7f75a33107 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/gate-conditions-view.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/gate-conditions-view.js @@ -34,7 +34,7 @@ export default Marionette.CompositeView.extend({ this.ui.metricSelect.select2({ allowClear: false, width: '250px', - placeholder: t('alerts.select_metric') + placeholder: window.t('alerts.select_metric') }); }, @@ -71,5 +71,3 @@ export default Marionette.CompositeView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/quality-gates/gate-projects-view.js b/server/sonar-web/src/main/js/apps/quality-gates/gate-projects-view.js index ff7816bd659..5d0493a59f5 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/gate-projects-view.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/gate-projects-view.js @@ -25,14 +25,14 @@ export default Marionette.ItemView.extend({ selectParameter: 'projectId', selectParameterValue: 'id', labels: { - selected: t('quality_gates.projects.with'), - deselected: t('quality_gates.projects.without'), - all: t('quality_gates.projects.all'), - noResults: t('quality_gates.projects.noResults') + selected: window.t('quality_gates.projects.with'), + deselected: window.t('quality_gates.projects.without'), + all: window.t('quality_gates.projects.all'), + noResults: window.t('quality_gates.projects.noResults') }, tooltips: { - select: t('quality_gates.projects.select_hint'), - deselect: t('quality_gates.projects.deselect_hint') + select: window.t('quality_gates.projects.select_hint'), + deselect: window.t('quality_gates.projects.deselect_hint') } }); } @@ -44,5 +44,3 @@ export default Marionette.ItemView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/helpers.js b/server/sonar-web/src/main/js/apps/quality-profiles/helpers.js index 7e060b9599b..479b9b18299 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/helpers.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/helpers.js @@ -15,15 +15,19 @@ Handlebars.registerHelper('exporterUrl', function (profile, exporterKey) { }); Handlebars.registerHelper('severityChangelog', function (severity) { - var label = '<i class="icon-severity-' + severity.toLowerCase() + '"></i> ' + t('severity', severity), - message = tp('quality_profiles.severity_set_to_x', label); + var label = '<i class="icon-severity-' + severity.toLowerCase() + '"></i> ' + window.t('severity', severity), + message = window.tp('quality_profiles.severity_set_to_x', label); return new Handlebars.SafeString(message); }); Handlebars.registerHelper('parameterChangelog', function (value, parameter) { if (parameter) { - return new Handlebars.SafeString(tp('quality_profiles.parameter_set_to_x', value, parameter)); + return new Handlebars.SafeString( + window.tp('quality_profiles.parameter_set_to_x', value, parameter) + ); } else { - return new Handlebars.SafeString(tp('quality_profiles.changelog.parameter_reset_to_default_value_x', parameter)); + return new Handlebars.SafeString( + window.tp('quality_profiles.changelog.parameter_reset_to_default_value_x', parameter) + ); } }); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/profile-details-view.js b/server/sonar-web/src/main/js/apps/quality-profiles/profile-details-view.js index b5f9167033d..10fc51c4a30 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/profile-details-view.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/profile-details-view.js @@ -74,14 +74,14 @@ export default Marionette.LayoutView.extend({ selectParameter: 'projectUuid', selectParameterValue: 'uuid', labels: { - selected: t('quality_gates.projects.with'), - deselected: t('quality_gates.projects.without'), - all: t('quality_gates.projects.all'), - noResults: t('quality_gates.projects.noResults') + selected: window.t('quality_gates.projects.with'), + deselected: window.t('quality_gates.projects.without'), + all: window.t('quality_gates.projects.all'), + noResults: window.t('quality_gates.projects.noResults') }, tooltips: { - select: t('quality_profiles.projects.select_hint'), - deselect: t('quality_profiles.projects.deselect_hint') + select: window.t('quality_profiles.projects.select_hint'), + deselect: window.t('quality_profiles.projects.deselect_hint') } }); this.listenTo(this.projectsSelectList.collection, 'change:selected', this.onProjectsChange); @@ -158,5 +158,3 @@ export default Marionette.LayoutView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/components/charts/bubble-chart.js b/server/sonar-web/src/main/js/components/charts/bubble-chart.js index 270bec31d12..9df80a47cf6 100644 --- a/server/sonar-web/src/main/js/components/charts/bubble-chart.js +++ b/server/sonar-web/src/main/js/components/charts/bubble-chart.js @@ -6,6 +6,9 @@ import { ResizeMixin } from './../mixins/resize-mixin'; import { TooltipsMixin } from './../mixins/tooltips-mixin'; +const TICKS_COUNT = 5; + + export const Bubble = React.createClass({ propTypes: { x: React.PropTypes.number.isRequired, @@ -85,12 +88,19 @@ export const BubbleChart = React.createClass({ return [availableHeight - dMaxY, dMinY]; }, - renderXGrid (xScale, yScale) { + getTicks(scale, format) { + let ticks = scale.ticks(TICKS_COUNT).map(tick => format(tick)); + const uniqueTicksCount = _.uniq(ticks).length; + const ticksCount = uniqueTicksCount < TICKS_COUNT ? uniqueTicksCount - 1 : TICKS_COUNT; + return scale.ticks(ticksCount); + }, + + renderXGrid (ticks, xScale, yScale) { if (!this.props.displayXGrid) { return null; } - let lines = xScale.ticks().map((tick, index) => { + let lines = ticks.map((tick, index) => { let x = xScale(tick); let y1 = yScale.range()[0]; let y2 = yScale.range()[1]; @@ -105,12 +115,12 @@ export const BubbleChart = React.createClass({ return <g ref="xGrid">{lines}</g>; }, - renderYGrid (xScale, yScale) { + renderYGrid (ticks, xScale, yScale) { if (!this.props.displayYGrid) { return null; } - let lines = yScale.ticks(5).map((tick, index) => { + let lines = ticks.map((tick, index) => { let y = yScale(tick); let x1 = xScale.range()[0]; let x2 = xScale.range()[1]; @@ -125,12 +135,12 @@ export const BubbleChart = React.createClass({ return <g ref="yGrid">{lines}</g>; }, - renderXTicks (xScale, yScale) { + renderXTicks (xTicks, xScale, yScale) { if (!this.props.displayXTicks) { return null; } - let ticks = xScale.ticks().map((tick, index) => { + let ticks = xTicks.map((tick, index) => { let x = xScale(tick); let y = yScale.range()[0]; let innerText = this.props.formatXTick(tick); @@ -144,12 +154,12 @@ export const BubbleChart = React.createClass({ return <g>{ticks}</g>; }, - renderYTicks (xScale, yScale) { + renderYTicks (yTicks, xScale, yScale) { if (!this.props.displayYTicks) { return null; } - let ticks = yScale.ticks(5).map((tick, index) => { + let ticks = yTicks.map((tick, index) => { let x = xScale.range()[0]; let y = yScale(tick); let innerText = this.props.formatYTick(tick); @@ -198,12 +208,15 @@ export const BubbleChart = React.createClass({ x={xScale(item.x)} y={yScale(item.y)} r={sizeScale(item.size)}/>; }); + let xTicks = this.getTicks(xScale, this.props.formatXTick); + let yTicks = this.getTicks(yScale, this.props.formatYTick); + return <svg className="bubble-chart" width={this.state.width} height={this.state.height}> <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}> - {this.renderXGrid(xScale, yScale)} - {this.renderXTicks(xScale, yScaleOriginal)} - {this.renderYGrid(xScale, yScale)} - {this.renderYTicks(xScaleOriginal, yScale)} + {this.renderXGrid(xTicks, xScale, yScale)} + {this.renderXTicks(xTicks, xScale, yScaleOriginal)} + {this.renderYGrid(yTicks, xScale, yScale)} + {this.renderYTicks(yTicks, xScaleOriginal, yScale)} {bubbles} </g> </svg>; diff --git a/server/sonar-web/src/main/js/components/charts/histogram.js b/server/sonar-web/src/main/js/components/charts/histogram.js index ffac187583c..c64146f2d28 100644 --- a/server/sonar-web/src/main/js/components/charts/histogram.js +++ b/server/sonar-web/src/main/js/components/charts/histogram.js @@ -40,17 +40,24 @@ export const Histogram = React.createClass({ return null; } let ticks = this.props.yTicks.map((tick, index) => { - let point = this.props.data[index]; - let x = xScale.range()[0]; - let y = Math.round(yScale(point.y) + yScale.rangeBand() / 2 + this.props.barsHeight / 2); - return <text key={index} - className="bar-chart-tick histogram-tick" - onClick={this.props.onBarClick && this.handleClick.bind(this, point)} - style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }} - x={x} - y={y} - dx="-1em" - dy="0.3em">{tick}</text>; + const point = this.props.data[index]; + const x = xScale.range()[0]; + const y = Math.round(yScale(point.y) + yScale.rangeBand() / 2 + this.props.barsHeight / 2); + const label = tick.label ? tick.label : tick; + const tooltip = tick.tooltip ? tick.tooltip : null; + return <text + key={index} + className="bar-chart-tick histogram-tick" + onClick={this.props.onBarClick && this.handleClick.bind(this, point)} + style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }} + data-title={tooltip} + data-toggle={tooltip ? 'tooltip' : null} + x={x} + y={y} + dx="-1em" + dy="0.3em"> + {label} + </text>; }); return <g>{ticks}</g>; }, diff --git a/server/sonar-web/src/main/js/components/charts/treemap.js b/server/sonar-web/src/main/js/components/charts/treemap.js index 63e974f5995..44d54dd698f 100644 --- a/server/sonar-web/src/main/js/components/charts/treemap.js +++ b/server/sonar-web/src/main/js/components/charts/treemap.js @@ -56,7 +56,7 @@ export const TreemapRect = React.createClass({ if (this.props.tooltip) { tooltipAttrs = { 'data-toggle': 'tooltip', - 'title': this.props.tooltip + 'data-title': this.props.tooltip }; } let cellStyles = { @@ -126,10 +126,11 @@ export const Treemap = React.createClass({ let prefix = mostCommitPrefix(this.props.items.map(item => item.label)); let prefixLength = prefix.length; - let rectangles = nodes.map((node, index) => { + let rectangles = nodes.map(node => { + const key = node.label; let label = prefixLength ? `${prefix}<br>${node.label.substr(prefixLength)}` : node.label; const onClick = this.props.canBeClicked(node) ? () => this.props.onRectangleClick(node) : null; - return <TreemapRect key={index} + return <TreemapRect key={key} x={node.x} y={node.y} width={node.dx} diff --git a/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js b/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js index e732493b89a..76f1ea1eb1a 100644 --- a/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/assign-form-view.js @@ -122,7 +122,7 @@ export default ActionOptionsView.extend({ if (this.assignees) { return this.assignees; } - var assignees = [{ id: '', text: t('unassigned') }], + var assignees = [{ id: '', text: window.t('unassigned') }], currentUser = window.SS.user, currentUserName = window.SS.userName; assignees.push({ id: currentUser, text: currentUserName }); @@ -138,5 +138,3 @@ export default ActionOptionsView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js b/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js index 244d65e6a79..ad924a6302e 100644 --- a/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js +++ b/server/sonar-web/src/main/js/components/issue/views/plan-form-view.js @@ -26,7 +26,7 @@ export default ActionOptionsView.extend({ }, getActionPlans: function () { - return [{ key: '', name: t('issue.unplanned') }].concat(this.collection.toJSON()); + return [{ key: '', name: window.t('issue.unplanned') }].concat(this.collection.toJSON()); }, serializeData: function () { @@ -35,5 +35,3 @@ export default ActionOptionsView.extend({ }); } }); - - diff --git a/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js b/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js index 153cae4fc9e..f3df5eea122 100644 --- a/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js +++ b/server/sonar-web/src/main/js/components/navigator/filters/choice-filters.js @@ -250,7 +250,7 @@ var ChoiceFilterView = BaseFilters.BaseFilterView.extend({ }), defaultValue = this.model.has('defaultValue') ? this.model.get('defaultValue') : - this.model.get('multiple') ? t('all') : t('any'); + this.model.get('multiple') ? window.t('all') : window.t('any'); return this.isDefaultValue() ? defaultValue : value.join(', '); }, @@ -387,5 +387,3 @@ export default { DetailsChoiceFilterView: DetailsChoiceFilterView, ChoiceFilterView: ChoiceFilterView }; - - diff --git a/server/sonar-web/src/main/js/components/source-viewer/main.js b/server/sonar-web/src/main/js/components/source-viewer/main.js index cf0ef14db0a..27b9af66d37 100644 --- a/server/sonar-web/src/main/js/components/source-viewer/main.js +++ b/server/sonar-web/src/main/js/components/source-viewer/main.js @@ -712,7 +712,7 @@ export default Marionette.LayoutView.extend({ $(e.currentTarget).tooltip({ container: 'body', placement: 'right', - title: tp('source_viewer.tooltip.new_code', this.sinceLabel), + title: window.tp('source_viewer.tooltip.new_code', this.sinceLabel), trigger: 'manual' }).tooltip('show'); }, diff --git a/server/sonar-web/src/main/js/components/widgets/barchart.js b/server/sonar-web/src/main/js/components/widgets/barchart.js index ea15e5ea684..03fca21da0d 100644 --- a/server/sonar-web/src/main/js/components/widgets/barchart.js +++ b/server/sonar-web/src/main/js/components/widgets/barchart.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import _ from 'underscore'; import moment from 'moment'; +import d3 from 'd3'; function trans (left, top) { return 'translate(' + left + ', ' + top + ')'; diff --git a/server/sonar-web/src/main/js/helpers/handlebars-helpers.js b/server/sonar-web/src/main/js/helpers/handlebars-helpers.js index e2a5110ee74..b9c54ea4562 100644 --- a/server/sonar-web/src/main/js/helpers/handlebars-helpers.js +++ b/server/sonar-web/src/main/js/helpers/handlebars-helpers.js @@ -1,5 +1,6 @@ import _ from 'underscore'; import moment from 'moment'; +import numeral from 'numeral'; import Handlebars from 'hbsfy/runtime'; import md5 from 'blueimp-md5'; import { formatMeasure, formatMeasureVariation } from './measures'; @@ -77,7 +78,7 @@ Handlebars.registerHelper('severityIcon', function (severity) { Handlebars.registerHelper('severityHelper', function (severity) { return new Handlebars.SafeString( - '<i class="icon-severity-' + severity.toLowerCase() + '"></i> ' + t('severity', severity) + '<i class="icon-severity-' + severity.toLowerCase() + '"></i> ' + window.t('severity', severity) ); }); @@ -88,9 +89,9 @@ Handlebars.registerHelper('statusIcon', function (status) { }); Handlebars.registerHelper('statusHelper', function (status, resolution) { - var s = '<i class="icon-status-' + status.toLowerCase() + '"></i> ' + t('issue.status', status); + var s = '<i class="icon-status-' + status.toLowerCase() + '"></i> ' + window.t('issue.status', status); if (resolution != null) { - s = s + ' (' + t('issue.resolution', resolution) + ')'; + s = s + ' (' + window.t('issue.resolution', resolution) + ')'; } return new Handlebars.SafeString(s); }); @@ -450,13 +451,13 @@ Handlebars.registerHelper('operators', function (options) { Handlebars.registerHelper('changelog', function (diff) { var message = ''; if (diff.newValue != null) { - message = tp('issue.changelog.changed_to', t('issue.changelog.field', diff.key), diff.newValue); + message = window.tp('issue.changelog.changed_to', window.t('issue.changelog.field', diff.key), diff.newValue); } else { - message = tp('issue.changelog.removed', t('issue.changelog.field', diff.key)); + message = window.tp('issue.changelog.removed', window.t('issue.changelog.field', diff.key)); } if (diff.oldValue != null) { message += ' ('; - message += tp('issue.changelog.was', diff.oldValue); + message += window.tp('issue.changelog.was', diff.oldValue); message += ')'; } return message; diff --git a/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js b/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js index bffbb2ba094..b55e44cc2b3 100644 --- a/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js +++ b/server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js @@ -14,10 +14,10 @@ import { const FIXED_DASHBOARDS = [ { link: '', name: 'overview.page' }, - { link: '/issues', name: 'overview.domain.debt' }, - { link: '/tests', name: 'overview.domain.coverage' }, + { link: '/debt', name: 'overview.domain.debt' }, + { link: '/coverage', name: 'overview.domain.coverage' }, { link: '/duplications', name: 'overview.domain.duplications' }, - { link: '/size', name: 'overview.domain.size' } + { link: '/structure', name: 'overview.domain.structure' } ]; const SETTINGS_URLS = [ diff --git a/server/sonar-web/src/main/js/main/nav/global/search-view.js b/server/sonar-web/src/main/js/main/nav/global/search-view.js index 65a3a4a7740..fbe9f3bcddc 100644 --- a/server/sonar-web/src/main/js/main/nav/global/search-view.js +++ b/server/sonar-web/src/main/js/main/nav/global/search-view.js @@ -155,16 +155,16 @@ export default Marionette.LayoutView.extend({ url: url, name: historyItem.name, q: historyItem.icon, - extra: index === 0 ? t('browsed_recently') : null + extra: index === 0 ? window.t('browsed_recently') : null }; }), favorite = _.first(this.favorite, 6).map(function (f, index) { - return _.extend(f, { extra: index === 0 ? t('favorite') : null }); + return _.extend(f, { extra: index === 0 ? window.t('favorite') : null }); }), qualifiers = this.model.get('qualifiers').map(function (q, index) { return { url: baseUrl + '/all_projects?qualifier=' + encodeURIComponent(q), - name: t('qualifiers.all', q), + name: window.t('qualifiers.all', q), extra: index === 0 ? '' : null }; }); @@ -201,22 +201,22 @@ export default Marionette.LayoutView.extend({ getNavigationFindings: function (q) { var DEFAULT_ITEMS = [ - { name: t('issues.page'), url: baseUrl + '/issues/search' }, - { name: t('layout.measures'), url: baseUrl + '/measures/search?qualifiers[]=TRK' }, - { name: t('coding_rules.page'), url: baseUrl + '/coding_rules' }, - { name: t('quality_profiles.page'), url: baseUrl + '/profiles' }, - { name: t('quality_gates.page'), url: baseUrl + '/quality_gates' }, - { name: t('comparison_global.page'), url: baseUrl + '/comparison' } + { name: window.t('issues.page'), url: baseUrl + '/issues/search' }, + { name: window.t('layout.measures'), url: baseUrl + '/measures/search?qualifiers[]=TRK' }, + { name: window.t('coding_rules.page'), url: baseUrl + '/coding_rules' }, + { name: window.t('quality_profiles.page'), url: baseUrl + '/profiles' }, + { name: window.t('quality_gates.page'), url: baseUrl + '/quality_gates' }, + { name: window.t('comparison_global.page'), url: baseUrl + '/comparison' } ], customItems = []; if (window.SS.isUserAdmin) { - customItems.push({ name: t('layout.settings'), url: baseUrl + '/settings' }); + customItems.push({ name: window.t('layout.settings'), url: baseUrl + '/settings' }); } var findings = [].concat(DEFAULT_ITEMS, customItems).filter(function (f) { return f.name.match(new RegExp(q, 'i')); }); if (findings.length > 0) { - findings[0].extra = t('navigation'); + findings[0].extra = window.t('navigation'); } return _.first(findings, 6); }, @@ -230,7 +230,7 @@ export default Marionette.LayoutView.extend({ return f.name.match(new RegExp(q, 'i')); }); if (findings.length > 0) { - findings[0].extra = t('dashboard.global_dashboards'); + findings[0].extra = window.t('dashboard.global_dashboards'); } return _.first(findings, 6); }, @@ -240,10 +240,8 @@ export default Marionette.LayoutView.extend({ return f.name.match(new RegExp(q, 'i')); }); if (findings.length > 0) { - findings[0].extra = t('favorite'); + findings[0].extra = window.t('favorite'); } return _.first(findings, 6); } }); - - diff --git a/server/sonar-web/src/main/js/main/processes.js b/server/sonar-web/src/main/js/main/processes.js index 1d685ab953d..af67b1b6197 100644 --- a/server/sonar-web/src/main/js/main/processes.js +++ b/server/sonar-web/src/main/js/main/processes.js @@ -30,7 +30,7 @@ var Process = Backbone.Model.extend({ fail: function (message) { var that = this, - msg = message || t('process.fail'); + msg = message || window.t('process.fail'); if (msg === 'process.fail') { // no translation msg = 'An error happened, some parts of the page might not render correctly. ' + diff --git a/server/sonar-web/src/main/js/widgets/old/tag-cloud.js b/server/sonar-web/src/main/js/widgets/old/tag-cloud.js index d09f38b55bb..cd2851ab8a2 100644 --- a/server/sonar-web/src/main/js/widgets/old/tag-cloud.js +++ b/server/sonar-web/src/main/js/widgets/old/tag-cloud.js @@ -64,7 +64,7 @@ TagCloud.prototype.tooltip = function (d) { var suffixKey = d.value === 1 ? 'issue' : 'issues', - suffix = t(suffixKey); + suffix = window.t(suffixKey); return (d.value + '\u00a0') + suffix; }; diff --git a/server/sonar-web/src/main/less/pages/overview.less b/server/sonar-web/src/main/less/pages/overview.less index 1f4b4793bb9..2c283b1fefe 100644 --- a/server/sonar-web/src/main/less/pages/overview.less +++ b/server/sonar-web/src/main/less/pages/overview.less @@ -167,10 +167,10 @@ .overview-domain-leak { flex: 1; - background-color: #fffae7; + background-color: #fbf3d5; .line-chart-backdrop { - fill: #f1ecd1; + fill: #efe7b8; } } @@ -250,7 +250,8 @@ .overview-domain-leak-title { padding: 0 10px; - background: #fffae7; + border: 1px solid @barBorderColor; + background: #fbf3d5; } } @@ -290,9 +291,10 @@ flex-flow: column nowrap; justify-content: flex-start; align-items: stretch; + flex: 3 0 auto; .overview-detailed-measure-value { - flex: 1; + flex: 1 0 auto; display: flex; justify-content: center; align-items: center; @@ -339,7 +341,7 @@ .overview-detailed-measure-leak { flex: 1; - background-color: #fffae7; + background-color: #fbf3d5; text-align: center; } @@ -373,9 +375,9 @@ right: -1px; padding: 5px 0 2px; border: 1px solid @barBorderColor; - border-bottom: none; font-size: 14px; text-align: center; + transform: translateY(-4px); } /* @@ -436,7 +438,7 @@ } .line-chart-backdrop { - fill: #fffae7; + fill: #fbf3d5; } .line-chart-tick { @@ -566,7 +568,7 @@ } .overview-leak { - background-color: #fffae7; + background-color: #fbf3d5; } /* diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java index 24e1783e97b..00a4029330f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java @@ -70,10 +70,10 @@ class DefaultBlameOutput implements BlameOutput { public synchronized void blameResult(InputFile file, List<BlameLine> lines) { Preconditions.checkNotNull(file); Preconditions.checkNotNull(lines); - Preconditions.checkArgument(allFilesToBlame.contains(file), "It was not expected to blame file " + file.relativePath()); + Preconditions.checkArgument(allFilesToBlame.contains(file), "It was not expected to blame file %s", file.relativePath()); if (lines.size() != file.lines()) { - LOG.debug("Ignoring blame result since provider returned " + lines.size() + " blame lines but file " + file.relativePath() + " has " + file.lines() + " lines"); + LOG.debug("Ignoring blame result since provider returned {} blame lines but file {} has {} lines", lines.size(), file.relativePath(), file.lines()); return; } @@ -82,8 +82,9 @@ class DefaultBlameOutput implements BlameOutput { scmBuilder.setComponentRef(batchComponent.batchId()); Map<String, Integer> changesetsIdByRevision = new HashMap<>(); + int lineId = 1; for (BlameLine line : lines) { - validateLine(line); + validateLine(line, lineId, file); Integer changesetId = changesetsIdByRevision.get(line.revision()); if (changesetId == null) { addChangeset(scmBuilder, line); @@ -91,6 +92,7 @@ class DefaultBlameOutput implements BlameOutput { changesetsIdByRevision.put(line.revision(), changesetId); } scmBuilder.addChangesetIndexByLine(changesetId); + lineId++; } writer.writeComponentChangesets(scmBuilder.build()); allFilesToBlame.remove(file); @@ -98,9 +100,9 @@ class DefaultBlameOutput implements BlameOutput { progressReport.message(count + "/" + total + " files analyzed"); } - private static void validateLine(BlameLine line) { - Preconditions.checkNotNull(line.revision(), "Blame revision cannot be null"); - Preconditions.checkNotNull(line.date(), "Blame date cannot be null"); + private static void validateLine(BlameLine line, int lineId, InputFile file) { + Preconditions.checkArgument(StringUtils.isNotBlank(line.revision()), "Blame revision is blank for file %s at line %s", file.relativePath(), lineId); + Preconditions.checkArgument(line.date() != null, "Blame date is null for file %s at line %s", file.relativePath(), lineId); } private static void addChangeset(Builder scmBuilder, BlameLine line) { @@ -131,7 +133,7 @@ class DefaultBlameOutput implements BlameOutput { private static String removeNonAsciiCharacters(String inputString) { return NON_ASCII_CHARS.matcher(inputString).replaceAll("_"); } - + public void finish() { progressReport.stop(count + "/" + total + " files analyzed"); if (!allFilesToBlame.isEmpty()) { diff --git a/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java b/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java index e7f00149111..3060951b4e9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java @@ -19,6 +19,8 @@ */ package org.sonar.batch.scm; +import java.util.Arrays; +import java.util.Date; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -30,11 +32,7 @@ import org.sonar.api.batch.scm.BlameLine; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; -import java.util.Arrays; -import java.util.Date; - import static org.mockito.Matchers.any; - import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -75,8 +73,8 @@ public class DefaultBlameOutputTest { public void shouldFailIfNullDate() { InputFile file = new DefaultInputFile("foo", "src/main/java/Foo.java").setLines(1); - thrown.expect(NullPointerException.class); - thrown.expectMessage("Blame date cannot be null"); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Blame date is null for file src/main/java/Foo.java at line 1"); new DefaultBlameOutput(null, componentCache, Arrays.<InputFile>asList(file)) .blameResult(file, Arrays.asList(new BlameLine().revision("1").author("guy"))); @@ -86,8 +84,8 @@ public class DefaultBlameOutputTest { public void shouldFailIfNullRevision() { InputFile file = new DefaultInputFile("foo", "src/main/java/Foo.java").setLines(1); - thrown.expect(NullPointerException.class); - thrown.expectMessage("Blame revision cannot be null"); + thrown.expect(IllegalArgumentException.class); + thrown.expectMessage("Blame revision is blank for file src/main/java/Foo.java at line 1"); new DefaultBlameOutput(null, componentCache, Arrays.<InputFile>asList(file)) .blameResult(file, Arrays.asList(new BlameLine().date(new Date()).author("guy"))); diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 033d44b6fd4..01d36315595 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3146,7 +3146,7 @@ overview.gate.view.errors=The view failed the quality gate on the following cond overview.domain.debt=Technical Debt overview.domain.coverage=Coverage overview.domain.duplications=Duplications -overview.domain.size=Size +overview.domain.structure=Structure overview.chart.files=Files overview.chart.files.limit_message=Only {0} files are displayed. |