]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7192 Create new 'Projects' page for views
authorStas Vilchik <vilchiks@gmail.com>
Tue, 12 Jan 2016 14:57:03 +0000 (15:57 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 13 Jan 2016 09:16:08 +0000 (10:16 +0100)
server/sonar-web/src/main/js/apps/code/actions/index.js
server/sonar-web/src/main/js/apps/code/components/Code.js
server/sonar-web/src/main/js/apps/code/components/Component.js
server/sonar-web/src/main/js/apps/code/components/ComponentName.js
server/sonar-web/src/main/js/apps/code/components/ComponentQualityGate.js [new file with mode: 0644]
server/sonar-web/src/main/js/apps/code/reducers/index.js
server/sonar-web/src/main/js/apps/code/styles/code.css
server/sonar-web/src/main/js/main/nav/component/component-nav-menu.js
server/sonar-web/src/main/webapp/WEB-INF/app/controllers/view_projects_controller.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/app/views/view_projects/index.html.erb [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index b387aad0aa0346396e122dc987518f3825f4d9be..040f07f5eb2dea44abb5af1434457ad118ab738a 100644 (file)
@@ -28,7 +28,8 @@ const METRICS = [
   'ncloc',
   'sqale_index',
   'violations',
-  'duplicated_lines_density'
+  'duplicated_lines_density',
+  'alert_status'
 ];
 
 const METRICS_WITH_COVERAGE = [
index 0a78c6e6d63dd6bb43b7de04098049e830bcf7b8..31f21e09890c303e2a8d6ec7b95fbf250581cd53 100644 (file)
@@ -72,15 +72,13 @@ class Code extends Component {
     return (
         <div className="page">
           <header className="page-header">
-            <h1 className="page-title">{translate('code.page')}</h1>
+            <Search component={this.props.component}/>
 
             <div
                 className="pull-left"
                 style={{ visibility: fetching ? 'visible' : 'hidden' }}>
               <i className="spinner"/>
             </div>
-
-            <Search component={this.props.component}/>
           </header>
 
           {errorMessage && (
index 4636da3028b287a4ad35ac3992e92ecf954b1192..11471eaf355ba96cf79f1f2036cc7d1232157a04 100644 (file)
@@ -24,6 +24,7 @@ import { connect } from 'react-redux';
 
 import ComponentName from './ComponentName';
 import ComponentMeasure from './ComponentMeasure';
+import ComponentQualityGate from './ComponentQualityGate';
 import ComponentDetach from './ComponentDetach';
 import ComponentPin from './ComponentPin';
 
@@ -62,7 +63,7 @@ class Component extends React.Component {
   }
 
   render () {
-    const { component, selected, previous, coverageMetric, onBrowse } = this.props;
+    const { component, selected, previous, coverageMetric, onBrowse, isView } = this.props;
 
     let componentAction = null;
 
@@ -83,6 +84,10 @@ class Component extends React.Component {
             </span>
           </td>
           <td className="code-name-cell">
+            {isView && (
+                <ComponentQualityGate
+                    component={component}/>
+            )}
             <ComponentName
                 component={component}
                 previous={previous}
@@ -136,7 +141,8 @@ class Component extends React.Component {
 
 function mapStateToProps (state, ownProps) {
   return {
-    selected: state.current.searchSelectedItem === ownProps.component
+    selected: state.current.searchSelectedItem === ownProps.component,
+    isView: state.current.isView
   };
 }
 
index 51ba9af79df05fdbc5463ec9ae5c0aa8a38c5018..914e93e057cdb539aaa8997734e84ce71c21883a 100644 (file)
@@ -62,12 +62,13 @@ const Component = ({ component, previous, onBrowse }) => {
         <span>{component.name.substr(prefix.length)}</span>
       </span>
   ) : component.name;
+  const canBrowse = !!onBrowse && !component.copy;
 
   return (
       <Truncated title={getTooltip(component)}>
         <QualifierIcon qualifier={component.qualifier}/>
         {' '}
-        {onBrowse ? (
+        {canBrowse ? (
             <a
                 onClick={handleClick}
                 href="#">
diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentQualityGate.js b/server/sonar-web/src/main/js/apps/code/components/ComponentQualityGate.js
new file mode 100644 (file)
index 0000000..b5bcfc7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube :: Web
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.
+ */
+import _ from 'underscore';
+import React from 'react';
+
+import { translate } from '../../../helpers/l10n';
+
+const METRIC = 'alert_status';
+
+const ComponentQualityGate = ({ component }) => {
+  const measure = _.findWhere(component.msr, { key: METRIC });
+  return measure ? (
+      <span
+          className="spacer-right"
+          title={translate('metric.level', measure.data)}
+          style={{ position: 'relative', top: '-1px' }}>
+        <i className={`icon-alert-${measure.data.toLowerCase()}`}/>
+      </span>
+  ) : <span/>;
+};
+
+
+export default ComponentQualityGate;
index 988140f717bd652c229b40c0e44fe81187550a09..938e26c0f204352e0b6ed46de6aea56e83386724 100644 (file)
@@ -99,6 +99,7 @@ export const initialState = {
   searchQuery: '',
   searchSelectedItem: null,
   coverageMetric: null,
+  isView: false,
   baseBreadcrumbs: [],
   errorMessage: null
 };
@@ -109,8 +110,9 @@ export function current (state = initialState, action) {
     case INIT:
       const coverageMetric = selectCoverageMetric(action.component);
       const baseBreadcrumbs = action.breadcrumbs.length > 1 ? _.initial(action.breadcrumbs) : [];
+      const isView = action.component.qualifier === 'VW' || action.component.qualifier === 'SVW';
 
-      return { ...state, coverageMetric, baseBreadcrumbs };
+      return { ...state, coverageMetric, baseBreadcrumbs, isView };
     case BROWSE:
       const baseComponent = hasSourceCode(action.component) ? null : action.component;
       const components = hasSourceCode(action.component) ? null : sortChildren(action.children);
index 4df9d26c78d0826e761389207bbbd39738b1493e..1f9b70b6c4f3d6ea5080052a2103c8004fc5da10 100644 (file)
@@ -50,6 +50,6 @@
 }
 
 .code-search-box {
-  padding-left: 10px;
-  overflow: hidden;
+  float: left;
+  padding-right: 10px;
 }
index c2ce247069a4e4920445c6c71a175fbb89b18a57..660dd0a4c7e4fe6e8a9ee0310ab579eb336f1c08 100644 (file)
@@ -167,6 +167,15 @@ export default React.createClass({
     return this.renderLink(url, translate('code.page'), '/code');
   },
 
+  renderProjectsLink() {
+    if (!this.isView()) {
+      return null;
+    }
+
+    const url = `/view_projects/index?id=${encodeURIComponent(this.props.component.key)}`;
+    return this.renderLink(url, translate('view_projects.page'), '/view_projects');
+  },
+
   renderComponentIssuesLink() {
     const url = `/component_issues/index?id=${encodeURIComponent(this.props.component.key)}`;
     return this.renderLink(url, translate('issues.page'), '/component_issues');
@@ -329,6 +338,7 @@ export default React.createClass({
           {!this.isDeveloper() && this.renderFixedDashboards()}
           {this.renderCustomDashboards()}
           {this.renderCodeLink()}
+          {this.renderProjectsLink()}
           {this.renderComponentIssuesLink()}
           {this.renderTools()}
           {this.renderAdministration()}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/view_projects_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/view_projects_controller.rb
new file mode 100644 (file)
index 0000000..a15997e
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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.
+#
+class ViewProjectsController < ApplicationController
+  before_filter :init_resource_for_user_role
+
+  SECTION=Navigation::SECTION_RESOURCE
+
+  def index
+
+  end
+
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/view_projects/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/view_projects/index.html.erb
new file mode 100644 (file)
index 0000000..f5600f6
--- /dev/null
@@ -0,0 +1,3 @@
+<% content_for :extra_script do %>
+  <script src="<%= ApplicationController.root_context -%>/js/bundles/code.js?v=<%= sonar_version -%>"></script>
+<% end %>
index a1b3baa983072beb20b70c7e47b1761b3306aa28..0c4ad89833b7beb0eea4e194859ba2adc91fdc9f 100644 (file)
@@ -541,6 +541,7 @@ source.page=Source
 timemachine.page=Time Machine
 comparison.page=Compare
 comparison_global.page=Compare Projects
+view_projects.page=Projects