]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8959 display portfolios link near projects link (#1802)
authorStas Vilchik <stas-vilchik@users.noreply.github.com>
Fri, 17 Mar 2017 09:34:33 +0000 (10:34 +0100)
committerGitHub <noreply@github.com>
Fri, 17 Mar 2017 09:34:33 +0000 (10:34 +0100)
server/sonar-web/src/main/js/app/components/extensions/Extension.js
server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js [new file with mode: 0644]
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js
server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js
server/sonar-web/src/main/js/app/utils/exposeLibraries.js
server/sonar-web/src/main/js/app/utils/startReactApp.js
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 3889e58612d0b6767ad6e7cc96647e29993fe761..7b87579722da8a01ec8b985790f0cc29a909bf9e 100644 (file)
@@ -25,6 +25,7 @@ import { addGlobalErrorMessage } from '../../../store/globalMessages/duck';
 import { getCurrentUser } from '../../../store/rootReducer';
 import { translate } from '../../../helpers/l10n';
 import { getExtensionStart } from './utils';
+import getStore from '../../utils/getStore';
 
 type Props = {
   currentUser: Object,
@@ -58,7 +59,9 @@ class Extension extends React.Component {
   }
 
   handleStart = (start: Function) => {
+    const store = getStore();
     this.stop = start({
+      store,
       el: this.container,
       currentUser: this.props.currentUser,
       router: this.props.router,
diff --git a/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js b/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js
new file mode 100644 (file)
index 0000000..c899d29
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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.
+ */
+// @flow
+import React from 'react';
+import GlobalPageExtension from './GlobalPageExtension';
+
+export default class PortfoliosPage extends React.Component {
+  render () {
+    return (
+        <GlobalPageExtension
+            location={this.props.location}
+            params={{ pluginKey: 'governance', extensionKey: 'portfolios' }}/>
+    );
+  }
+}
index b1e556af9d063e6852763dd27a2cc79de6cb3f96..7eebc3d03935f78acd1c6b15c12f0d7671bbc2ad 100644 (file)
@@ -47,6 +47,16 @@ export default class GlobalNavMenu extends React.Component {
     );
   }
 
+  renderPortfolios() {
+    return (
+      <li>
+        <Link to="/portfolios" activeClassName="active">
+          {translate('portfolios.page')}
+        </Link>
+      </li>
+    );
+  }
+
   renderIssuesLink() {
     const query = this.props.currentUser.isLoggedIn
       ? '#resolved=false|assigned_to_me=true'
@@ -114,7 +124,8 @@ export default class GlobalNavMenu extends React.Component {
 
   renderMore() {
     const { globalPages } = this.props.appState;
-    if (globalPages.length === 0) {
+    const withoutPortfolios = globalPages.filter(page => page.key !== 'governance/portfolios');
+    if (withoutPortfolios.length === 0) {
       return null;
     }
     return (
@@ -124,16 +135,19 @@ export default class GlobalNavMenu extends React.Component {
           <span className="icon-dropdown" />
         </a>
         <ul className="dropdown-menu">
-          {globalPages.map(this.renderGlobalPageLink)}
+          {withoutPortfolios.map(this.renderGlobalPageLink)}
         </ul>
       </li>
     );
   }
 
   render() {
+    const governanceInstalled = this.props.appState.qualifiers.includes('VW');
+
     return (
       <ul className="nav navbar-nav">
         {this.renderProjects()}
+        {governanceInstalled && this.renderPortfolios()}
         {this.renderIssuesLink()}
         {this.renderRulesLink()}
         {this.renderProfilesLink()}
index 8631913e07f86fa3551e746123565596d78d7d20..d21f3f609ee597bb69c04c96d8a529ea7dcfb32c 100644 (file)
@@ -23,7 +23,8 @@ import GlobalNavMenu from '../GlobalNavMenu';
 
 it('should work with extensions', () => {
   const appState = {
-    globalPages: [{ key: 'foo', name: 'Foo' }]
+    globalPages: [{ key: 'foo', name: 'Foo' }],
+    qualifiers: ['TRK']
   };
   const currentUser = {
     isLoggedIn: false,
index 6dc1cf76fcd7642ea117b7331fb96b8b3bbb4e39..843319f234147914a1712bfc59b43e2b0679a754 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import moment from 'moment';
+import * as ReactRedux from 'react-redux';
 import * as measures from '../../helpers/measures';
 import * as request from '../../helpers/request';
+import FavoriteContainer from '../../components/controls/FavoriteContainer';
+import ListFooter from '../../components/controls/ListFooter';
 
 const exposeLibraries = () => {
   window.moment = moment;
+  window.ReactRedux = ReactRedux;
   window.SonarMeasures = measures;
   window.SonarRequest = request;
+  window.SonarComponents = {
+    FavoriteContainer,
+    ListFooter
+  };
 };
 
 export default exposeLibraries;
index 71f53ddfe0fd04763052e1965114a7af6223a628..5f92bfa369776913b02691bdae4b9eba701f62cc 100644 (file)
@@ -32,6 +32,7 @@ import ProjectAdminContainer from '../components/ProjectAdminContainer';
 import ProjectPageExtension from '../components/extensions/ProjectPageExtension';
 import ProjectAdminPageExtension from '../components/extensions/ProjectAdminPageExtension';
 import ViewDashboard from '../components/extensions/ViewDashboard';
+import PortfoliosPage from '../components/extensions/PortfoliosPage';
 import AdminContainer from '../components/AdminContainer';
 import GlobalPageExtension from '../components/extensions/GlobalPageExtension';
 import GlobalAdminPageExtension from '../components/extensions/GlobalAdminPageExtension';
@@ -93,6 +94,8 @@ const startReactApp = () => {
           }}
         />
 
+        <Redirect from="/extension/governance/portfolios" to="/portfolios" />
+
         <Route path="markdown/help" component={MarkdownHelp} />
 
         <Route component={LocalizationContainer}>
@@ -126,6 +129,7 @@ const startReactApp = () => {
                 <Route path="organizations">{organizationsRouters}</Route>
                 <Route path="projects">{projectsRoutes}</Route>
                 <Route path="quality_gates">{qualityGatesRoutes}</Route>
+                <Route path="portfolios" component={PortfoliosPage} />
                 <Route path="profiles">{qualityProfilesRoutes}</Route>
                 <Route path="web_api">{webAPIRoutes}</Route>
 
index 5e5ca82eddd9ff55bf1b443c588ecfd6bcff9187..30915d798659254a46da577cabc81682d66c1aa0 100644 (file)
@@ -560,6 +560,7 @@ source.page=Source
 timemachine.page=Time Machine
 comparison.page=Compare
 view_projects.page=Projects
+portfolios.page=Portfolios
 project_activity.page=Activity
 project_activity.page.description=The page shows the history of project analyses.