diff options
author | Stas Vilchik <stas-vilchik@users.noreply.github.com> | 2017-04-19 08:51:45 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-19 08:51:45 +0200 |
commit | d030db77d634090dddc1345ea16b0b2cb0aa3ba2 (patch) | |
tree | df0af8c6587d767e660f7d3925ab6c101fd355ae /server/sonar-web/src/main/js | |
parent | 4df60a42ed232f82c6c97c00296c4dbb8ac4398e (diff) | |
download | sonarqube-d030db77d634090dddc1345ea16b0b2cb0aa3ba2.tar.gz sonarqube-d030db77d634090dddc1345ea16b0b2cb0aa3ba2.zip |
improve react usage (#1936)
* remove React.createClass
* remove react-addons-shallow-compare
* convert to functional components
* replace Component with PureComponent
* remove react-router-redux
* declare function components consistently
* fix quality flaws
* fix typo
* declare children prop consistently
* pass location to ComponentNavMenu
Diffstat (limited to 'server/sonar-web/src/main/js')
318 files changed, 1951 insertions, 2278 deletions
diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.js b/server/sonar-web/src/main/js/app/components/AdminContainer.js index 84ca940e53a..05d64849395 100644 --- a/server/sonar-web/src/main/js/app/components/AdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/AdminContainer.js @@ -26,7 +26,7 @@ import { onFail } from '../../store/rootActions'; import { getSettingsNavigation } from '../../api/nav'; import { setAdminPages } from '../../store/appState/duck'; -class AdminContainer extends React.Component { +class AdminContainer extends React.PureComponent { componentDidMount() { if (!isUserAdmin(this.props.currentUser)) { // workaround cyclic dependencies diff --git a/server/sonar-web/src/main/js/app/components/App.js b/server/sonar-web/src/main/js/app/components/App.js index bc1904c6386..578556bbb3f 100644 --- a/server/sonar-web/src/main/js/app/components/App.js +++ b/server/sonar-web/src/main/js/app/components/App.js @@ -24,7 +24,7 @@ import GlobalLoading from './GlobalLoading'; import { fetchCurrentUser } from '../../store/users/actions'; import { fetchLanguages, fetchAppState, fetchOrganizations } from '../../store/rootActions'; -class App extends React.Component { +class App extends React.PureComponent { mounted: boolean; static propTypes = { diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.js b/server/sonar-web/src/main/js/app/components/GlobalContainer.js index e59fd05b2c6..181cdb9ac86 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.js +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.js @@ -23,21 +23,19 @@ import GlobalNav from './nav/global/GlobalNav'; import GlobalFooter from './GlobalFooter'; import GlobalMessagesContainer from './GlobalMessagesContainer'; -export default class GlobalContainer extends React.Component { - render() { - // it is important to pass `location` down to `GlobalNav` to trigger render on url change +export default function GlobalContainer(props: Object) { + // it is important to pass `location` down to `GlobalNav` to trigger render on url change - return ( - <div className="global-container"> - <div className="page-wrapper page-wrapper-global" id="container"> - <div className="page-container"> - <GlobalNav location={this.props.location} /> - <GlobalMessagesContainer /> - {this.props.children} - </div> + return ( + <div className="global-container"> + <div className="page-wrapper page-wrapper-global" id="container"> + <div className="page-container"> + <GlobalNav location={props.location} /> + <GlobalMessagesContainer /> + {props.children} </div> - <GlobalFooter /> </div> - ); - } + <GlobalFooter /> + </div> + ); } diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooter.js b/server/sonar-web/src/main/js/app/components/GlobalFooter.js index b88d06cc1c8..0a8dd3789ab 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooter.js +++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.js @@ -24,48 +24,46 @@ import { connect } from 'react-redux'; import { getAppState } from '../../store/rootReducer'; import GlobalFooterBranding from './GlobalFooterBranding'; -class GlobalFooter extends React.Component { - render() { - const { sonarqubeVersion, productionDatabase } = this.props; +function GlobalFooter(props: Object) { + const { sonarqubeVersion, productionDatabase } = props; - return ( - <div id="footer" className="page-footer page-container"> - {productionDatabase === false && - <div className="alert alert-danger"> - <p className="big" id="evaluation_warning"> - Embedded database should be used for evaluation purpose only - </p> - <p> - The embedded database will not scale, it will not support upgrading to newer - {' '} - versions of SonarQube, and there is no support for migrating your data out of it - {' '} - into a different database engine. - </p> - </div>} + return ( + <div id="footer" className="page-footer page-container"> + {productionDatabase === false && + <div className="alert alert-danger"> + <p className="big" id="evaluation_warning"> + Embedded database should be used for evaluation purpose only + </p> + <p> + The embedded database will not scale, it will not support upgrading to newer + {' '} + versions of SonarQube, and there is no support for migrating your data out of it + {' '} + into a different database engine. + </p> + </div>} - <GlobalFooterBranding /> + <GlobalFooterBranding /> - <div> - Version {sonarqubeVersion} - {' - '} - <a href="http://www.gnu.org/licenses/lgpl-3.0.txt">LGPL v3</a> - {' - '} - <a href="http://www.sonarqube.org">Community</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/home.html">Documentation</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/community.html">Get Support</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/plugin-library.html">Plugins</a> - {' - '} - <Link to="/web_api">Web API</Link> - {' - '} - <Link to="/about">About</Link> - </div> + <div> + Version {sonarqubeVersion} + {' - '} + <a href="http://www.gnu.org/licenses/lgpl-3.0.txt">LGPL v3</a> + {' - '} + <a href="http://www.sonarqube.org">Community</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/home.html">Documentation</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/community.html">Get Support</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/plugin-library.html">Plugins</a> + {' - '} + <Link to="/web_api">Web API</Link> + {' - '} + <Link to="/about">About</Link> </div> - ); - } + </div> + ); } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js b/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js index 1ca8a72c20a..bfe622734c1 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js +++ b/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js @@ -20,18 +20,16 @@ // @flow import React from 'react'; -export default class GlobalFooterBranding extends React.Component { - render() { - return ( - <div> - This application is based on - {' '} - <a href="http://www.sonarqube.org/" title="SonarQubeâ„¢">SonarQube™</a> - {' '} - but is <strong>not</strong> an official version provided by - {' '} - <a href="http://www.sonarsource.com" title="SonarSource SA">SonarSource SA</a>. - </div> - ); - } +export default function GlobalFooterBranding() { + return ( + <div> + This application is based on + {' '} + <a href="http://www.sonarqube.org/" title="SonarQubeâ„¢">SonarQubeâ„¢</a> + {' '} + but is <strong>not</strong> an official version provided by + {' '} + <a href="http://www.sonarsource.com" title="SonarSource SA">SonarSource SA</a>. + </div> + ); } diff --git a/server/sonar-web/src/main/js/app/components/GlobalLoading.js b/server/sonar-web/src/main/js/app/components/GlobalLoading.js index b5e45197357..28917188145 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalLoading.js +++ b/server/sonar-web/src/main/js/app/components/GlobalLoading.js @@ -21,13 +21,11 @@ import React from 'react'; import './GlobalLoading.css'; -export default class GlobalLoading extends React.Component { - render() { - return ( - <div className="global-loading"> - <i className="spinner global-loading-spinner" /> - <span className="global-loading-text">Loading...</span> - </div> - ); - } +export default function GlobalLoading() { + return ( + <div className="global-loading"> + <i className="spinner global-loading-spinner" /> + <span className="global-loading-text">Loading...</span> + </div> + ); } diff --git a/server/sonar-web/src/main/js/app/components/Landing.js b/server/sonar-web/src/main/js/app/components/Landing.js index 5239df6f93b..42a3bd47a77 100644 --- a/server/sonar-web/src/main/js/app/components/Landing.js +++ b/server/sonar-web/src/main/js/app/components/Landing.js @@ -23,7 +23,7 @@ import { withRouter } from 'react-router'; import { connect } from 'react-redux'; import { getCurrentUser } from '../../store/rootReducer'; -class Landing extends React.Component { +class Landing extends React.PureComponent { static propTypes = { currentUser: React.PropTypes.oneOfType([ React.PropTypes.bool, diff --git a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js index 341d4ff8121..94223fc453a 100644 --- a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js +++ b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js @@ -21,7 +21,7 @@ import React from 'react'; import { requestMessages } from '../../helpers/l10n'; -export default class LocalizationContainer extends React.Component { +export default class LocalizationContainer extends React.PureComponent { mounted: boolean; state = { diff --git a/server/sonar-web/src/main/js/app/components/MarkdownHelp.js b/server/sonar-web/src/main/js/app/components/MarkdownHelp.js index bf30a114454..e957fe31bdd 100644 --- a/server/sonar-web/src/main/js/app/components/MarkdownHelp.js +++ b/server/sonar-web/src/main/js/app/components/MarkdownHelp.js @@ -20,115 +20,113 @@ // @flow import React from 'react'; -export default class MarkdownHelp extends React.Component { - render() { - return ( - <div className="page page-limited"> - <h2 className="spacer-bottom">Markdown Syntax</h2> - <table className="width-100 data zebra"> - <thead> - <tr> - <th>Write:</th> - <th>To display:</th> - </tr> - </thead> - <tbody> - <tr> - <td>*this text is bold*</td> - <td className="markdown"><strong>this text is bold</strong></td> - </tr> - <tr> - <td>{'http://sonarqube.org'}</td> - <td className="markdown"> - <a href="http://sonarqube.org">{'http://sonarqube.org'}</a> - </td> - </tr> - <tr> - <td className="text-top"> - [SonarQubeâ„¢ Home Page](http://www.sonarqube.org) - </td> - <td className="markdown text-top"> - <a href="http://www.sonarqube.org" target="_blank">SonarQubeâ„¢ Home Page</a> - </td> - </tr> - <tr> - <td className="text-top"> - * first item<br /> - * second item - </td> - <td className="markdown"> - <ul> - <li>first item</li> - <li>second item</li> - </ul> - </td> - </tr> - <tr> - <td className="text-top"> - 1. first item<br /> - 1. second item - </td> - <td className="markdown text-top"> - <ol> - <li>first item</li> - <li>second item</li> - </ol> - </td> - </tr> - <tr> - <td className="text-top"> - = Heading Level 1<br /> - == Heading Level 2<br /> - === Heading Level 3<br /> - ==== Heading Level 4<br /> - ===== Heading Level 5<br /> - ====== Heading Level 6<br /> - </td> - <td className="markdown text-top"> - <h1>Heading Level 1</h1> - <h2>Heading Level 2</h2> - <h3>Heading Level 3</h3> - <h4>Heading Level 4</h4> - <h5>Heading Level 5</h5> - <h6>Heading Level 6</h6> - </td> - </tr> - <tr> - <td className="text-top">``Lists#newArrayList()``</td> - <td className="markdown text-top"><code>Lists#newArrayList()</code></td> - </tr> - <tr> - <td className="text-top"> - ``<br /> - // code on multiple lines<br /> - {'public void foo() {'}<br /> - {'// do some logic here'}<br /> - {'}'}<br /> - `` - </td> - <td className="markdown text-top"> - <pre> - {'// code on multiple lines\npublic void foo() {\n // do some logic here\n}'} - </pre> - </td> - </tr> - <tr> - <td className="text-top"> - Standard text<br /> - > Blockquoted text<br /> - > that spans multiple lines<br /> - </td> - <td className="markdown text-top"> - <p>Standard text</p> - <blockquote> - Blockquoted text<br /> - that spans multiple lines<br /> - </blockquote> - </td> - </tr> - </tbody> - </table> - </div> - ); - } +export default function MarkdownHelp() { + return ( + <div className="page page-limited"> + <h2 className="spacer-bottom">Markdown Syntax</h2> + <table className="width-100 data zebra"> + <thead> + <tr> + <th>Write:</th> + <th>To display:</th> + </tr> + </thead> + <tbody> + <tr> + <td>*this text is bold*</td> + <td className="markdown"><strong>this text is bold</strong></td> + </tr> + <tr> + <td>{'http://sonarqube.org'}</td> + <td className="markdown"> + <a href="http://sonarqube.org">{'http://sonarqube.org'}</a> + </td> + </tr> + <tr> + <td className="text-top"> + [SonarQubeâ„¢ Home Page](http://www.sonarqube.org) + </td> + <td className="markdown text-top"> + <a href="http://www.sonarqube.org" target="_blank">SonarQubeâ„¢ Home Page</a> + </td> + </tr> + <tr> + <td className="text-top"> + * first item<br /> + * second item + </td> + <td className="markdown"> + <ul> + <li>first item</li> + <li>second item</li> + </ul> + </td> + </tr> + <tr> + <td className="text-top"> + 1. first item<br /> + 1. second item + </td> + <td className="markdown text-top"> + <ol> + <li>first item</li> + <li>second item</li> + </ol> + </td> + </tr> + <tr> + <td className="text-top"> + = Heading Level 1<br /> + == Heading Level 2<br /> + === Heading Level 3<br /> + ==== Heading Level 4<br /> + ===== Heading Level 5<br /> + ====== Heading Level 6<br /> + </td> + <td className="markdown text-top"> + <h1>Heading Level 1</h1> + <h2>Heading Level 2</h2> + <h3>Heading Level 3</h3> + <h4>Heading Level 4</h4> + <h5>Heading Level 5</h5> + <h6>Heading Level 6</h6> + </td> + </tr> + <tr> + <td className="text-top">``Lists#newArrayList()``</td> + <td className="markdown text-top"><code>Lists#newArrayList()</code></td> + </tr> + <tr> + <td className="text-top"> + ``<br /> + // code on multiple lines<br /> + {'public void foo() {'}<br /> + {'// do some logic here'}<br /> + {'}'}<br /> + `` + </td> + <td className="markdown text-top"> + <pre> + {'// code on multiple lines\npublic void foo() {\n // do some logic here\n}'} + </pre> + </td> + </tr> + <tr> + <td className="text-top"> + Standard text<br /> + > Blockquoted text<br /> + > that spans multiple lines<br /> + </td> + <td className="markdown text-top"> + <p>Standard text</p> + <blockquote> + Blockquoted text<br /> + that spans multiple lines<br /> + </blockquote> + </td> + </tr> + </tbody> + </table> + </div> + ); } diff --git a/server/sonar-web/src/main/js/app/components/MigrationContainer.js b/server/sonar-web/src/main/js/app/components/MigrationContainer.js index 4441e3e8373..69b989f8925 100644 --- a/server/sonar-web/src/main/js/app/components/MigrationContainer.js +++ b/server/sonar-web/src/main/js/app/components/MigrationContainer.js @@ -22,9 +22,9 @@ import React from 'react'; import { withRouter } from 'react-router'; import { getSystemStatus } from '../../api/system'; -class MigrationContainer extends React.Component { +class MigrationContainer extends React.PureComponent { props: { - children: Object, + children?: React.Element<*>, router: { push: (path: string) => void } }; diff --git a/server/sonar-web/src/main/js/app/components/NotFound.js b/server/sonar-web/src/main/js/app/components/NotFound.js index 2692a72a90d..c3191e6b8ea 100644 --- a/server/sonar-web/src/main/js/app/components/NotFound.js +++ b/server/sonar-web/src/main/js/app/components/NotFound.js @@ -21,16 +21,14 @@ import React from 'react'; import { Link } from 'react-router'; import SimpleContainer from './SimpleContainer'; -export default class NotFound extends React.Component { - render() { - return ( - <SimpleContainer> - <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> - <p className="spacer-bottom"> - You may have mistyped the address or the page may have moved. - </p> - <p><Link to="/">Go back to the homepage</Link></p> - </SimpleContainer> - ); - } +export default function NotFound() { + return ( + <SimpleContainer> + <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> + <p className="spacer-bottom"> + You may have mistyped the address or the page may have moved. + </p> + <p><Link to="/">Go back to the homepage</Link></p> + </SimpleContainer> + ); } diff --git a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js index 79c773e10af..4891093f745 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import { getComponent } from '../../store/rootReducer'; import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; -class ProjectAdminContainer extends React.Component { +class ProjectAdminContainer extends React.PureComponent { props: { project: { configuration?: { diff --git a/server/sonar-web/src/main/js/app/components/ProjectContainer.js b/server/sonar-web/src/main/js/app/components/ProjectContainer.js index 4dd98290d38..3023b1a7628 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectContainer.js @@ -27,10 +27,10 @@ import { addGlobalErrorMessage } from '../../store/globalMessages/duck'; import { parseError } from '../../apps/code/utils'; import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; -class ProjectContainer extends React.Component { +class ProjectContainer extends React.PureComponent { props: { addGlobalErrorMessage: () => void, - children: {}, + children?: React.Element<*>, location: { query: { id: string } }, @@ -73,7 +73,12 @@ class ProjectContainer extends React.Component { return ( <div> - {!isFile && <ComponentNav component={this.props.project} conf={configuration} />} + {!isFile && + <ComponentNav + component={this.props.project} + conf={configuration} + location={this.props.location} + />} {this.props.children} </div> ); diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.js b/server/sonar-web/src/main/js/app/components/SimpleContainer.js index 1d1ecb7595d..cc3309d0a25 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.js +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.js @@ -21,7 +21,7 @@ import React from 'react'; import GlobalFooter from './GlobalFooter'; -export default class SimpleContainer extends React.Component { +export default class SimpleContainer extends React.PureComponent { static propTypes = { children: React.PropTypes.oneOfType([ React.PropTypes.element, diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.js b/server/sonar-web/src/main/js/app/components/extensions/Extension.js index 7b87579722d..1013c2c2823 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.js @@ -38,7 +38,7 @@ type Props = { router: Object }; -class Extension extends React.Component { +class Extension extends React.PureComponent { container: Object; props: Props; stop: ?Function; diff --git a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js index 8bbf9940238..a634c3556d2 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js @@ -21,7 +21,7 @@ import React from 'react'; import { Link } from 'react-router'; -export default class ExtensionNotFound extends React.Component { +export default class ExtensionNotFound extends React.PureComponent { componentDidMount() { const html = document.querySelector('html'); if (html) { diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js index 54f9f231b36..056623556f1 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js @@ -24,19 +24,18 @@ import Extension from './Extension'; import ExtensionNotFound from './ExtensionNotFound'; import { getAppState } from '../../../store/rootReducer'; -class GlobalAdminPageExtension extends React.Component { - props: { - adminPages: Array<{ key: string }>, - params: { - extensionKey: string, - pluginKey: string - } - }; - render() { - const { extensionKey, pluginKey } = this.props.params; - const extension = this.props.adminPages.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; +type Props = { + adminPages: Array<{ key: string }>, + params: { + extensionKey: string, + pluginKey: string } +}; + +function GlobalAdminPageExtension(props: Props) { + const { extensionKey, pluginKey } = props.params; + const extension = props.adminPages.find(p => p.key === `${pluginKey}/${extensionKey}`); + return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js index 147564cf34a..c31c9c81608 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js @@ -24,19 +24,18 @@ import Extension from './Extension'; import ExtensionNotFound from './ExtensionNotFound'; import { getAppState } from '../../../store/rootReducer'; -class GlobalPageExtension extends React.Component { - props: { - globalPages: Array<{ key: string }>, - params: { - extensionKey: string, - pluginKey: string - } - }; - render() { - const { extensionKey, pluginKey } = this.props.params; - const extension = this.props.globalPages.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; +type Props = { + globalPages: Array<{ key: string }>, + params: { + extensionKey: string, + pluginKey: string } +}; + +function GlobalPageExtension(props: Props) { + const { extensionKey, pluginKey } = props.params; + const extension = props.globalPages.find(p => p.key === `${pluginKey}/${extensionKey}`); + return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; } const mapStateToProps = state => ({ 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 index 6d129279a92..a7f47a2fa3a 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js +++ b/server/sonar-web/src/main/js/app/components/extensions/PortfoliosPage.js @@ -21,13 +21,11 @@ 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' }} - /> - ); - } +export default function PortfoliosPage(props: Object) { + return ( + <GlobalPageExtension + location={props.location} + params={{ pluginKey: 'governance', extensionKey: 'portfolios' }} + /> + ); } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js index 4e753ae6459..9e01ad26655 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js @@ -38,18 +38,14 @@ type Props = { } }; -class ProjectAdminPageExtension extends React.Component { - props: Props; - - render() { - const { extensionKey, pluginKey } = this.props.params; - const { component } = this.props; - const extension = component.configuration && - component.configuration.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension - ? <Extension extension={extension} options={{ component }} /> - : <ExtensionNotFound />; - } +function ProjectAdminPageExtension(props: Props) { + const { extensionKey, pluginKey } = props.params; + const { component } = props; + const extension = component.configuration && + component.configuration.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); + return extension + ? <Extension extension={extension} options={{ component }} /> + : <ExtensionNotFound />; } const mapStateToProps = (state, ownProps: Props) => ({ diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js index 3f2d684c04f..ddf910693b3 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js @@ -36,17 +36,13 @@ type Props = { } }; -class ProjectPageExtension extends React.Component { - props: Props; - - render() { - const { extensionKey, pluginKey } = this.props.params; - const { component } = this.props; - const extension = component.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension - ? <Extension extension={extension} options={{ component }} /> - : <ExtensionNotFound />; - } +function ProjectPageExtension(props: Props) { + const { extensionKey, pluginKey } = props.params; + const { component } = props; + const extension = component.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); + return extension + ? <Extension extension={extension} options={{ component }} /> + : <ExtensionNotFound />; } const mapStateToProps = (state, ownProps: Props) => ({ diff --git a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js index eb38960ee66..f1c5419f6b2 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js @@ -21,13 +21,11 @@ import React from 'react'; import ProjectPageExtension from './ProjectPageExtension'; -export default class ViewDashboard extends React.Component { - render() { - return ( - <ProjectPageExtension - location={this.props.location} - params={{ pluginKey: 'governance', extensionKey: 'governance' }} - /> - ); - } +export default function ViewDashboard(props: Object) { + return ( + <ProjectPageExtension + location={props.location} + params={{ pluginKey: 'governance', extensionKey: 'governance' }} + /> + ); } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js index ed484f8453f..31ed72b442e 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js @@ -27,19 +27,19 @@ import { TooltipsContainer } from '../../../../components/mixins/tooltips-mixin' import { getTasksForComponent } from '../../../../api/ce'; import { STATUSES } from '../../../../apps/background-tasks/constants'; -export default React.createClass({ +export default class ComponentNav extends React.PureComponent { componentDidMount() { this.mounted = true; this.loadStatus(); this.populateRecentHistory(); - }, + } componentWillUnmount() { this.mounted = false; - }, + } - loadStatus() { + loadStatus = () => { getTasksForComponent(this.props.component.id).then(r => { if (this.mounted) { this.setState({ @@ -49,9 +49,9 @@ export default React.createClass({ }); } }); - }, + }; - populateRecentHistory() { + populateRecentHistory = () => { const { breadcrumbs } = this.props.component; const { qualifier } = breadcrumbs[breadcrumbs.length - 1]; if (['TRK', 'VW', 'DEV'].indexOf(qualifier) !== -1) { @@ -62,7 +62,7 @@ export default React.createClass({ this.props.component.organization ); } - }, + }; render() { return ( @@ -88,10 +88,14 @@ export default React.createClass({ /> </TooltipsContainer> - <ComponentNavMenu component={this.props.component} conf={this.props.conf} /> + <ComponentNavMenu + component={this.props.component} + conf={this.props.conf} + location={this.props.location} + /> </div> </div> </nav> ); } -}); +} diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js index 0d4200d6bf5..653ad06f901 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js @@ -24,7 +24,7 @@ import QualifierIcon from '../../../../components/shared/QualifierIcon'; import { getOrganizationByKey, areThereCustomOrganizations } from '../../../../store/rootReducer'; import OrganizationLink from '../../../../components/ui/OrganizationLink'; -class ComponentNavBreadcrumbs extends React.Component { +class ComponentNavBreadcrumbs extends React.PureComponent { static propTypes = { breadcrumbs: React.PropTypes.array }; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js index 4ae31ef1fb7..6b3fd012d28 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import Favorite from '../../../../components/controls/Favorite'; import { getCurrentUser } from '../../../../store/rootReducer'; -class ComponentNavFavorite extends React.Component { +class ComponentNavFavorite extends React.PureComponent { static propTypes = { currentUser: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js index 6c68203c03b..0b5327f5513 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js @@ -35,7 +35,7 @@ const SETTINGS_URLS = [ '/project/deletion' ]; -export default class ComponentNavMenu extends React.Component { +export default class ComponentNavMenu extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, conf: React.PropTypes.object.isRequired diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js index 21fc78a5de4..63246b7407b 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js @@ -22,7 +22,7 @@ import React from 'react'; import PendingIcon from '../../../../components/shared/pending-icon'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; -export default React.createClass({ +export default class ComponentNavMeta extends React.PureComponent { render() { const metaList = []; const canSeeBackgroundTasks = this.props.conf.showBackgroundTasks; @@ -77,4 +77,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js index ef83aed3921..7e62d596890 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js @@ -26,7 +26,7 @@ import GlobalNavSearch from './GlobalNavSearch'; import ShortcutsHelpView from './ShortcutsHelpView'; import { getCurrentUser, getAppState } from '../../../../store/rootReducer'; -class GlobalNav extends React.Component { +class GlobalNav extends React.PureComponent { componentDidMount() { window.addEventListener('keypress', this.onKeyPress); } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js index 8e6dd891305..996391f2fd0 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import { getSettingValue, getCurrentUser } from '../../../../store/rootReducer'; import { translate } from '../../../../helpers/l10n'; -class GlobalNavBranding extends React.Component { +class GlobalNavBranding extends React.PureComponent { static propTypes = { customLogoUrl: React.PropTypes.string, customLogoWidth: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]) diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js index 3a5f67cdada..644c05296ff 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js @@ -22,7 +22,7 @@ import { Link } from 'react-router'; import { translate } from '../../../../helpers/l10n'; import { isUserAdmin } from '../../../../helpers/users'; -export default class GlobalNavMenu extends React.Component { +export default class GlobalNavMenu extends React.PureComponent { static propTypes = { appState: React.PropTypes.object.isRequired, currentUser: React.PropTypes.object.isRequired, diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js index d7089b5a536..9b40ecb2b8c 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js @@ -34,7 +34,7 @@ function contains(root, node) { return false; } -class GlobalNavSearch extends React.Component { +class GlobalNavSearch extends React.PureComponent { state = { open: false }; componentDidMount() { diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js index 01db375a81b..004d3c20eb2 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js @@ -23,7 +23,7 @@ import { Link, withRouter } from 'react-router'; import Avatar from '../../../../components/ui/Avatar'; import { translate } from '../../../../helpers/l10n'; -class GlobalNavUser extends React.Component { +class GlobalNavUser extends React.PureComponent { props: { currentUser: { email?: string, diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js index 4c183f4e4ab..50454783e43 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js @@ -24,7 +24,7 @@ import { connect } from 'react-redux'; import { translate } from '../../../../helpers/l10n'; import { areThereCustomOrganizations } from '../../../../store/rootReducer'; -class SettingsNav extends React.Component { +class SettingsNav extends React.PureComponent { static defaultProps = { extensions: [] }; diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js index d76e6e3b4ba..9485847305b 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js @@ -41,7 +41,7 @@ import '../styles.css'; type State = { loading: boolean, - projectsCount?: number, + projectsCount: number, issueTypes?: { [key: string]: ?{ count: number @@ -49,7 +49,7 @@ type State = { } }; -class AboutApp extends React.Component { +class AboutApp extends React.PureComponent { mounted: boolean; props: { @@ -64,7 +64,8 @@ class AboutApp extends React.Component { }; state: State = { - loading: true + loading: true, + projectsCount: 0 }; componentDidMount() { diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js index addce0a2496..6d7030247c3 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js @@ -32,87 +32,85 @@ import AboutScanners from './AboutScanners'; import { translate } from '../../../helpers/l10n'; import '../sonarqube-dot-com-styles.css'; -export default class AboutAppForSonarQubeDotCom extends React.Component { - props: { - appState: { - defaultOrganization: string, - organizationsEnabled: boolean - }, - bugs: number, - codeSmells: number, - currentUser: { isLoggedIn: boolean }, - customText?: string, - projectsCount: number, - vulnerabilities: number - }; +type Props = { + appState: { + defaultOrganization: string, + organizationsEnabled: boolean + }, + bugs: number, + codeSmells: number, + currentUser: { isLoggedIn: boolean }, + customText?: string, + projectsCount: number, + vulnerabilities: number +}; - render() { - const { customText } = this.props; +export default function AboutAppForSonarQubeDotCom(props: Props) { + const { customText } = props; - return ( - <div id="about-page" className="about-page sqcom-about-page"> - <div className="sqcom-about-page-entry"> - <div className="about-page-container"> - <div className="sqcom-about-page-intro"> - <h1 className="big-spacer-bottom"> - Continuous Code Quality<br />as a Service - </h1> - <a - className="button button-active" - href="https://about.sonarqube.com/get-started/" - target="_blank"> - Get Started - </a> - {!this.props.currentUser.isLoggedIn && - <Link to="/sessions/new" className="button big-spacer-left"> - {translate('layout.login')} - </Link>} - </div> + return ( + <div id="about-page" className="about-page sqcom-about-page"> + <div className="sqcom-about-page-entry"> + <div className="about-page-container"> + <div className="sqcom-about-page-intro"> + <h1 className="big-spacer-bottom"> + Continuous Code Quality<br />as a Service + </h1> + <a + className="button button-active" + href="https://about.sonarqube.com/get-started/" + target="_blank"> + Get Started + </a> + {!props.currentUser.isLoggedIn && + <Link to="/sessions/new" className="button big-spacer-left"> + {translate('layout.login')} + </Link>} + </div> - <div className="sqcom-about-page-instance"> - <AboutProjects count={this.props.projectsCount} /> - <EntryIssueTypesForSonarQubeDotCom - bugs={this.props.bugs} - vulnerabilities={this.props.vulnerabilities} - codeSmells={this.props.codeSmells} - /> - </div> + <div className="sqcom-about-page-instance"> + <AboutProjects count={props.projectsCount} /> + <EntryIssueTypesForSonarQubeDotCom + bugs={props.bugs} + vulnerabilities={props.vulnerabilities} + codeSmells={props.codeSmells} + /> </div> </div> + </div> - <AboutRulesForSonarQubeDotCom appState={this.props.appState} /> + <AboutRulesForSonarQubeDotCom appState={props.appState} /> - <div className="about-page-container"> - {customText != null && - customText.value && - <div - className="about-page-section" - dangerouslySetInnerHTML={{ __html: customText.value }} - />} + <div className="about-page-container"> + {customText != null && + customText.value && + <div + className="about-page-section" + dangerouslySetInnerHTML={{ __html: customText.value }} + />} - <AboutQualityModelForSonarQubeDotCom /> + <AboutQualityModelForSonarQubeDotCom /> - <div className="flex-columns"> - <div className="flex-column flex-column-half about-page-group-boxes"> - <AboutCleanCode /> - </div> - <div className="flex-column flex-column-half about-page-group-boxes"> - <AboutLeakPeriod /> - </div> + <div className="flex-columns"> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutCleanCode /> </div> - - <div className="flex-columns"> - <div className="flex-column flex-column-half about-page-group-boxes"> - <AboutQualityGates /> - </div> - <div className="flex-column flex-column-half about-page-group-boxes"> - <AboutStandards appState={this.props.appState} /> - </div> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutLeakPeriod /> </div> + </div> - <AboutScanners /> + <div className="flex-columns"> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutQualityGates /> + </div> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutStandards appState={props.appState} /> + </div> </div> + + <AboutScanners /> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js b/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js index 0100b0fbe1b..1ed36c5127b 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js @@ -23,16 +23,14 @@ import { translate } from '../../../helpers/l10n'; const link = 'https://redirect.sonarsource.com/doc/issues.html'; -export default class AboutCleanCode extends React.Component { - render() { - return ( - <div className="boxed-group"> - <h2>{translate('about_page.clean_code')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.clean_code.text')}</p> - <ReadMore link={link} /> - </div> +export default function AboutCleanCode() { + return ( + <div className="boxed-group"> + <h2>{translate('about_page.clean_code')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.clean_code.text')}</p> + <ReadMore link={link} /> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutLanguages.js b/server/sonar-web/src/main/js/apps/about/components/AboutLanguages.js index 0876d2078d2..dffb976146d 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutLanguages.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutLanguages.js @@ -45,25 +45,23 @@ const languages = [ const half = (languages.length + 1) / 2; -export default class AboutLanguages extends React.Component { - render() { - return ( - <div className="boxed-group"> - <h2>{translate('about_page.languages')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.languages.text')}</p> - <ul className="about-page-languages"> - {languages.slice(0, half).map((language, index) => ( - <li key={index}> - <a href={languages[index].url}>{languages[index].name}</a> - <br /> - {index + half < languages.length && - <a href={languages[index + half].url}>{languages[index + half].name}</a>} - </li> - ))} - </ul> - </div> +export default function AboutLanguages() { + return ( + <div className="boxed-group"> + <h2>{translate('about_page.languages')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.languages.text')}</p> + <ul className="about-page-languages"> + {languages.slice(0, half).map((language, index) => ( + <li key={index}> + <a href={languages[index].url}>{languages[index].name}</a> + <br /> + {index + half < languages.length && + <a href={languages[index + half].url}>{languages[index + half].name}</a>} + </li> + ))} + </ul> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js b/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js index edf09b00582..f959dd97cbb 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js @@ -23,16 +23,14 @@ import { translate } from '../../../helpers/l10n'; const link = 'https://redirect.sonarsource.com/doc/fix-the-leak.html'; -export default class AboutLeakPeriod extends React.Component { - render() { - return ( - <div className="boxed-group"> - <h2>{translate('about_page.fix_the_leak')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.fix_the_leak.text')}</p> - <ReadMore link={link} /> - </div> +export default function AboutLeakPeriod() { + return ( + <div className="boxed-group"> + <h2>{translate('about_page.fix_the_leak')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.fix_the_leak.text')}</p> + <ReadMore link={link} /> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js index 785214d854b..4d240868177 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js @@ -22,7 +22,7 @@ import { Link } from 'react-router'; import { formatMeasure } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; -export default class AboutProjects extends React.Component { +export default class AboutProjects extends React.PureComponent { static propTypes = { count: React.PropTypes.number.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js b/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js index 6e49863472a..e83d8d77b95 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js @@ -23,16 +23,14 @@ import { translate } from '../../../helpers/l10n'; const link = 'https://redirect.sonarsource.com/doc/quality-gates.html'; -export default class AboutQualityGates extends React.Component { - render() { - return ( - <div className="boxed-group"> - <h2>{translate('about_page.quality_gates')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.quality_gates.text')}</p> - <ReadMore link={link} /> - </div> +export default function AboutQualityGates() { + return ( + <div className="boxed-group"> + <h2>{translate('about_page.quality_gates')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.quality_gates.text')}</p> + <ReadMore link={link} /> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutQualityModel.js b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModel.js index f107c0d2195..9e50b5e6a7d 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutQualityModel.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModel.js @@ -23,43 +23,41 @@ import BugIcon from '../../../components/ui/BugIcon'; import VulnerabilityIcon from '../../../components/ui/VulnerabilityIcon'; import CodeSmellIcon from '../../../components/ui/CodeSmellIcon'; -export default class AboutQualityModel extends React.Component { - render() { - return ( - <div className="boxed-group about-quality-model"> - <h2>{translate('about_page.quality_model')}</h2> +export default function AboutQualityModel() { + return ( + <div className="boxed-group about-quality-model"> + <h2>{translate('about_page.quality_model')}</h2> - <div className="boxed-group-inner clearfix"> - <div className="flex-columns"> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"><BugIcon /></div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.BUG.plural')}</strong> - {' '} - {translate('about_page.quality_model.bugs')} - </p> - </div> + <div className="boxed-group-inner clearfix"> + <div className="flex-columns"> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><BugIcon /></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.BUG.plural')}</strong> + {' '} + {translate('about_page.quality_model.bugs')} + </p> + </div> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"><VulnerabilityIcon /></div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.VULNERABILITY.plural')}</strong> - {' '} - {translate('about_page.quality_model.vulnerabilities')} - </p> - </div> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><VulnerabilityIcon /></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.VULNERABILITY.plural')}</strong> + {' '} + {translate('about_page.quality_model.vulnerabilities')} + </p> + </div> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"><CodeSmellIcon /></div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.CODE_SMELL.plural')}</strong> - {' '} - {translate('about_page.quality_model.code_smells')} - </p> - </div> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><CodeSmellIcon /></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.CODE_SMELL.plural')}</strong> + {' '} + {translate('about_page.quality_model.code_smells')} + </p> </div> </div> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js index 077d9b8c736..6f7ff4125cb 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js @@ -23,47 +23,45 @@ import BugIconForSonarQubeDotCom from './BugIconForSonarQubeDotCom'; import VulnerabilityIconForSonarQubeDotCom from './VulnerabilityIconForSonarQubeDotCom'; import CodeSmellIconForSonarQubeDotCom from './CodeSmellIconForSonarQubeDotCom'; -export default class AboutQualityModelForSonarQubeDotCom extends React.Component { - render() { - return ( - <div className="boxed-group about-quality-model sqcom-about-quality-model"> - <h2>{translate('about_page.quality_model')}</h2> +export default function AboutQualityModelForSonarQubeDotCom() { + return ( + <div className="boxed-group about-quality-model sqcom-about-quality-model"> + <h2>{translate('about_page.quality_model')}</h2> - <div className="boxed-group-inner clearfix"> - <div className="flex-columns"> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"><BugIconForSonarQubeDotCom /></div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.BUG.plural')}</strong> - {' '} - {translate('about_page.quality_model.bugs')} - </p> - </div> + <div className="boxed-group-inner clearfix"> + <div className="flex-columns"> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><BugIconForSonarQubeDotCom /></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.BUG.plural')}</strong> + {' '} + {translate('about_page.quality_model.bugs')} + </p> + </div> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"> - <VulnerabilityIconForSonarQubeDotCom /> - </div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.VULNERABILITY.plural')}</strong> - {' '} - {translate('about_page.quality_model.vulnerabilities')} - </p> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"> + <VulnerabilityIconForSonarQubeDotCom /> </div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.VULNERABILITY.plural')}</strong> + {' '} + {translate('about_page.quality_model.vulnerabilities')} + </p> + </div> - <div className="flex-column flex-column-third"> - <div className="pull-left little-spacer-right"> - <CodeSmellIconForSonarQubeDotCom /> - </div> - <p className="about-page-text overflow-hidden"> - <strong>{translate('issue.type.CODE_SMELL.plural')}</strong> - {' '} - {translate('about_page.quality_model.code_smells')} - </p> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"> + <CodeSmellIconForSonarQubeDotCom /> </div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.CODE_SMELL.plural')}</strong> + {' '} + {translate('about_page.quality_model.code_smells')} + </p> </div> </div> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js index 59fef3421c9..da03f74b956 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js @@ -22,56 +22,54 @@ import React from 'react'; import { Link } from 'react-router'; import { getRulesUrl } from '../../../helpers/urls'; -export default class AboutRulesForSonarQubeDotCom extends React.Component { - props: { - appState: { - defaultOrganization: string, - organizationsEnabled: boolean - } - }; +type Props = { + appState: { + defaultOrganization: string, + organizationsEnabled: boolean + } +}; - render() { - const organization = this.props.appState.defaultOrganization; +export default function AboutRulesForSonarQubeDotCom(props: Props) { + const organization = props.appState.defaultOrganization; - return ( - <div className="sqcom-about-rules"> - <div className="about-page-container"> - <Link to={getRulesUrl(null, organization)} className="sqcom-about-rules-link"> - +3,000 rules - <span className="spacer-left"> - <svg width="15" height="36" viewBox="0 0 15 36"> - <g transform="matrix(1,0,0,1,-267,-362)"> - <path - d="M268,363L281,380L269,397" - style={{ fill: 'none', stroke: '#c1d9ea', strokeWidth: 1 }} - /> - </g> - </svg> - </span> - </Link> - <Link - to={getRulesUrl({ languages: 'js' }, organization)} - className="sqcom-about-rules-link"> - JavaScript - </Link> - <Link - to={getRulesUrl({ languages: 'java' }, organization)} - className="sqcom-about-rules-link"> - Java - </Link> - <Link - to={getRulesUrl({ languages: 'c,cpp' }, organization)} - className="sqcom-about-rules-link"> - C/C++ - </Link> - <Link - to={getRulesUrl({ languages: 'cs' }, organization)} - className="sqcom-about-rules-link"> - C# - </Link> - <Link to={getRulesUrl(null, organization)} className="button">And More</Link> - </div> + return ( + <div className="sqcom-about-rules"> + <div className="about-page-container"> + <Link to={getRulesUrl(null, organization)} className="sqcom-about-rules-link"> + +3,000 rules + <span className="spacer-left"> + <svg width="15" height="36" viewBox="0 0 15 36"> + <g transform="matrix(1,0,0,1,-267,-362)"> + <path + d="M268,363L281,380L269,397" + style={{ fill: 'none', stroke: '#c1d9ea', strokeWidth: 1 }} + /> + </g> + </svg> + </span> + </Link> + <Link + to={getRulesUrl({ languages: 'js' }, organization)} + className="sqcom-about-rules-link"> + JavaScript + </Link> + <Link + to={getRulesUrl({ languages: 'java' }, organization)} + className="sqcom-about-rules-link"> + Java + </Link> + <Link + to={getRulesUrl({ languages: 'c,cpp' }, organization)} + className="sqcom-about-rules-link"> + C/C++ + </Link> + <Link + to={getRulesUrl({ languages: 'cs' }, organization)} + className="sqcom-about-rules-link"> + C# + </Link> + <Link to={getRulesUrl(null, organization)} className="button">And More</Link> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js index 981e8c90a3b..8396fa6289b 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js @@ -47,26 +47,24 @@ const scanners = [ } ]; -export default class AboutScanners extends React.Component { - render() { - return ( - <div className="boxed-group"> - <h2>{translate('about_page.scanners')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.scanners.text')}</p> - <div className="about-page-analyzers"> - {scanners.map(scanner => ( - <a key={scanner.key} className="about-page-analyzer-box" href={scanner.link}> - <img - src={`${window.baseUrl}/images/scanner-logos/${scanner.key}.svg`} - height={60} - alt={translate('about_page.scanners', scanner.key)} - /> - </a> - ))} - </div> +export default function AboutScanners() { + return ( + <div className="boxed-group"> + <h2>{translate('about_page.scanners')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.scanners.text')}</p> + <div className="about-page-analyzers"> + {scanners.map(scanner => ( + <a key={scanner.key} className="about-page-analyzer-box" href={scanner.link}> + <img + src={`${window.baseUrl}/images/scanner-logos/${scanner.key}.svg`} + height={60} + alt={translate('about_page.scanners', scanner.key)} + /> + </a> + ))} </div> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js index a2991500f31..8a46026312e 100644 --- a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js +++ b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js @@ -29,67 +29,61 @@ const owaspTags = 'owasp-a1,owasp-a2,owasp-a3,owasp-a4,owasp-a5,' + 'owasp-a6,owasp-a7,owasp-a8,owasp-a9,owasp-a10'; const sans25Tags = 'sans-top25-porous,sans-top25-risky,sans-top25-insecure'; -export default class AboutStandards extends React.Component { - props: { - appState: { - defaultOrganization: string, - organizationsEnabled: boolean - } - }; - - render() { - const organization = this.props.appState.organizationsEnabled - ? this.props.appState.defaultOrganization - : null; +type Props = { + appState: { + defaultOrganization: string, + organizationsEnabled: boolean + } +}; - return ( - <div className="boxed-group"> - <h2>{translate('about_page.standards')}</h2> - <div className="boxed-group-inner"> - <p className="about-page-text">{translate('about_page.standards.text')}</p> +export default function AboutStandards(props: Props) { + const organization = props.appState.organizationsEnabled + ? props.appState.defaultOrganization + : null; - <div className="spacer-top"> - <ul className="list-inline"> - <li> - <Link to={getRulesUrl({ tags: 'misra' }, organization)} className="link-with-icon"> - <i className="icon-tags" /> - <span className="little-spacer-left">MISRA</span> - </Link> - </li> - <li> - <Link to={getRulesUrl({ tags: 'cert' }, organization)} className="link-with-icon"> - <i className="icon-tags" /> - <span className="little-spacer-left">CERT</span> - </Link> - </li> - <li> - <Link to={getRulesUrl({ tags: 'cwe' }, organization)} className="link-with-icon"> - <i className="icon-tags" /> - <span className="little-spacer-left">CWE</span> - </Link> - </li> - <li> - <Link - to={getRulesUrl({ tags: owaspTags }, organization)} - className="link-with-icon"> - <i className="icon-tags" /> - <span className="little-spacer-left">OWASP Top 10</span> - </Link> - </li> - <li> - <Link - to={getRulesUrl({ tags: sans25Tags }, organization)} - className="link-with-icon"> - <i className="icon-tags" /> - <span className="little-spacer-left">SANS Top 25</span> - </Link> - </li> - </ul> - </div> + return ( + <div className="boxed-group"> + <h2>{translate('about_page.standards')}</h2> + <div className="boxed-group-inner"> + <p className="about-page-text">{translate('about_page.standards.text')}</p> - <ReadMore link={link} /> + <div className="spacer-top"> + <ul className="list-inline"> + <li> + <Link to={getRulesUrl({ tags: 'misra' }, organization)} className="link-with-icon"> + <i className="icon-tags" /> + <span className="little-spacer-left">MISRA</span> + </Link> + </li> + <li> + <Link to={getRulesUrl({ tags: 'cert' }, organization)} className="link-with-icon"> + <i className="icon-tags" /> + <span className="little-spacer-left">CERT</span> + </Link> + </li> + <li> + <Link to={getRulesUrl({ tags: 'cwe' }, organization)} className="link-with-icon"> + <i className="icon-tags" /> + <span className="little-spacer-left">CWE</span> + </Link> + </li> + <li> + <Link to={getRulesUrl({ tags: owaspTags }, organization)} className="link-with-icon"> + <i className="icon-tags" /> + <span className="little-spacer-left">OWASP Top 10</span> + </Link> + </li> + <li> + <Link to={getRulesUrl({ tags: sans25Tags }, organization)} className="link-with-icon"> + <i className="icon-tags" /> + <span className="little-spacer-left">SANS Top 25</span> + </Link> + </li> + </ul> </div> + + <ReadMore link={link} /> </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js index a116f7331e6..808b95d011f 100644 --- a/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class BugIconForSonarQubeDotCom extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg viewBox="0 0 26 26" width="26" height="26"> - <path - style={{ fill: 'currentcolor' }} - d="M23.737 15.91l-2.298-2.297a.797.797 0 0 0-.542-.232h-2.18v-1.588l2.722-2.723a.773.773 0 0 0 .233-.542V4.243a.777.777 0 0 0-.775-.775.777.777 0 0 0-.774.775v3.962l-1.407 1.407v-.633a.777.777 0 0 0-.774-.774h-.517a4.51 4.51 0 0 0-2.852-3.446l2.698-2.698a.787.787 0 0 0 0-1.097.787.787 0 0 0-1.098 0L12.985 4.14 9.823.99a.787.787 0 0 0-1.097 0 .787.787 0 0 0 0 1.097l2.672 2.672a4.51 4.51 0 0 0-2.853 3.446H7.99a.777.777 0 0 0-.774.774v.633L5.81 8.192v-3.95a.777.777 0 0 0-.774-.774.777.777 0 0 0-.775.775v4.272c0 .206.078.4.233.542l2.723 2.723v1.6H5.035c-.207 0-.4.078-.542.233L2.195 15.91a.787.787 0 0 0 0 1.098.764.764 0 0 0 .542.232c.194 0 .4-.078.542-.232l2.078-2.078h1.86v.761l-2.789 3.64a.783.783 0 0 0-.155.477v4.505c0 .426.349.774.775.774a.777.777 0 0 0 .774-.774v-4.247l1.433-1.884a5.77 5.77 0 0 0 2.788 4.298l.077.039c.84.49 1.82.761 2.853.761a5.825 5.825 0 0 0 2.865-.761c.013-.013.039-.013.051-.026a5.75 5.75 0 0 0 2.801-4.31l1.446 1.883v4.247c0 .426.348.774.774.774a.777.777 0 0 0 .775-.774v-4.505a.811.811 0 0 0-.155-.477l-2.788-3.64v-.761H20.6l2.078 2.078a.764.764 0 0 0 .542.232c.193 0 .4-.078.542-.232a.787.787 0 0 0-.026-1.098zm-10.752-9.9c1.369 0 2.517.93 2.853 2.182h-5.705a2.954 2.954 0 0 1 2.852-2.181zm-4.22 11.527V9.754h3.433v9.254l-1.82 1.82a4.172 4.172 0 0 1-1.613-3.291zm3.046 4.04l1.149-1.15 1.148 1.15a4.188 4.188 0 0 1-1.148.167c-.388 0-.775-.064-1.15-.167zm5.356-4.04c0 1.342-.632 2.53-1.6 3.304l-1.82-1.82V9.754h3.433v7.783h-.013z" - /> - </svg> - ); - } +export default function BugIconForSonarQubeDotCom() { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path + style={{ fill: 'currentcolor' }} + d="M23.737 15.91l-2.298-2.297a.797.797 0 0 0-.542-.232h-2.18v-1.588l2.722-2.723a.773.773 0 0 0 .233-.542V4.243a.777.777 0 0 0-.775-.775.777.777 0 0 0-.774.775v3.962l-1.407 1.407v-.633a.777.777 0 0 0-.774-.774h-.517a4.51 4.51 0 0 0-2.852-3.446l2.698-2.698a.787.787 0 0 0 0-1.097.787.787 0 0 0-1.098 0L12.985 4.14 9.823.99a.787.787 0 0 0-1.097 0 .787.787 0 0 0 0 1.097l2.672 2.672a4.51 4.51 0 0 0-2.853 3.446H7.99a.777.777 0 0 0-.774.774v.633L5.81 8.192v-3.95a.777.777 0 0 0-.774-.774.777.777 0 0 0-.775.775v4.272c0 .206.078.4.233.542l2.723 2.723v1.6H5.035c-.207 0-.4.078-.542.233L2.195 15.91a.787.787 0 0 0 0 1.098.764.764 0 0 0 .542.232c.194 0 .4-.078.542-.232l2.078-2.078h1.86v.761l-2.789 3.64a.783.783 0 0 0-.155.477v4.505c0 .426.349.774.775.774a.777.777 0 0 0 .774-.774v-4.247l1.433-1.884a5.77 5.77 0 0 0 2.788 4.298l.077.039c.84.49 1.82.761 2.853.761a5.825 5.825 0 0 0 2.865-.761c.013-.013.039-.013.051-.026a5.75 5.75 0 0 0 2.801-4.31l1.446 1.883v4.247c0 .426.348.774.774.774a.777.777 0 0 0 .775-.774v-4.505a.811.811 0 0 0-.155-.477l-2.788-3.64v-.761H20.6l2.078 2.078a.764.764 0 0 0 .542.232c.193 0 .4-.078.542-.232a.787.787 0 0 0-.026-1.098zm-10.752-9.9c1.369 0 2.517.93 2.853 2.182h-5.705a2.954 2.954 0 0 1 2.852-2.181zm-4.22 11.527V9.754h3.433v9.254l-1.82 1.82a4.172 4.172 0 0 1-1.613-3.291zm3.046 4.04l1.149-1.15 1.148 1.15a4.188 4.188 0 0 1-1.148.167c-.388 0-.775-.064-1.15-.167zm5.356-4.04c0 1.342-.632 2.53-1.6 3.304l-1.82-1.82V9.754h3.433v7.783h-.013z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js index 1b951e1d3fe..e4c0df6452b 100644 --- a/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class CodeSmellIconForSonarQubeDotCom extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg viewBox="0 0 26 26" width="26" height="26"> - <path - style={{ fill: 'currentcolor' }} - d="M19.957 5.099a10.455 10.455 0 0 0-7.424-3.077c-1.42 0-2.792.278-4.087.825a10.426 10.426 0 0 0-3.338 2.249 10.462 10.462 0 0 0-3.076 7.427c0 1.418.279 2.791.826 4.087a10.497 10.497 0 0 0 2.25 3.338 10.426 10.426 0 0 0 3.338 2.25c1.295.546 2.67.825 4.086.825 1.419 0 2.791-.279 4.087-.826a10.426 10.426 0 0 0 3.338-2.249 10.465 10.465 0 0 0 3.075-7.425c0-1.417-.278-2.793-.823-4.086a10.396 10.396 0 0 0-2.252-3.338zm.393 10.725a8.436 8.436 0 0 1-1.818 2.695 8.452 8.452 0 0 1-5.996 2.486 8.442 8.442 0 0 1-5.997-2.486 8.455 8.455 0 0 1-2.486-5.996 8.43 8.43 0 0 1 2.486-5.995 8.452 8.452 0 0 1 5.996-2.486 8.445 8.445 0 0 1 5.997 2.486 8.452 8.452 0 0 1 2.485 5.995 8.35 8.35 0 0 1-.667 3.3zm-7.794 4.202h-.037a7.767 7.767 0 0 1-3.426-.835.317.317 0 0 1-.13-.44l2.25-3.923a.32.32 0 0 1 .403-.132c.284.119.595.189.92.189.326 0 .639-.067.92-.19a.32.32 0 0 1 .404.133l2.255 3.922c.09.157.03.36-.133.441a7.896 7.896 0 0 1-3.426.835zm-1.58-7.457c0-.003 0-.009-.003-.013a1.56 1.56 0 0 1 2.337-1.35c.468.269.781.77.781 1.35v.013a1.557 1.557 0 0 1-3.115 0zm-1.068.015H5.384a.318.318 0 0 1-.32-.334c.03-.614.19-1.992.981-3.391l.008-.016.007-.016a7.806 7.806 0 0 1 2.428-2.554.317.317 0 0 1 .448.106l2.282 3.903a.316.316 0 0 1-.082.414 2.371 2.371 0 0 0-.914 1.605.325.325 0 0 1-.314.283zm9.776-.007h-4.526a.32.32 0 0 1-.316-.282 2.371 2.371 0 0 0-.913-1.604.322.322 0 0 1-.082-.414l2.284-3.904a.317.317 0 0 1 .449-.106 7.787 7.787 0 0 1 2.426 2.554l.016.033a7.74 7.74 0 0 1 .98 3.387.319.319 0 0 1-.318.336z" - /> - </svg> - ); - } +export default function CodeSmellIconForSonarQubeDotCom() { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path + style={{ fill: 'currentcolor' }} + d="M19.957 5.099a10.455 10.455 0 0 0-7.424-3.077c-1.42 0-2.792.278-4.087.825a10.426 10.426 0 0 0-3.338 2.249 10.462 10.462 0 0 0-3.076 7.427c0 1.418.279 2.791.826 4.087a10.497 10.497 0 0 0 2.25 3.338 10.426 10.426 0 0 0 3.338 2.25c1.295.546 2.67.825 4.086.825 1.419 0 2.791-.279 4.087-.826a10.426 10.426 0 0 0 3.338-2.249 10.465 10.465 0 0 0 3.075-7.425c0-1.417-.278-2.793-.823-4.086a10.396 10.396 0 0 0-2.252-3.338zm.393 10.725a8.436 8.436 0 0 1-1.818 2.695 8.452 8.452 0 0 1-5.996 2.486 8.442 8.442 0 0 1-5.997-2.486 8.455 8.455 0 0 1-2.486-5.996 8.43 8.43 0 0 1 2.486-5.995 8.452 8.452 0 0 1 5.996-2.486 8.445 8.445 0 0 1 5.997 2.486 8.452 8.452 0 0 1 2.485 5.995 8.35 8.35 0 0 1-.667 3.3zm-7.794 4.202h-.037a7.767 7.767 0 0 1-3.426-.835.317.317 0 0 1-.13-.44l2.25-3.923a.32.32 0 0 1 .403-.132c.284.119.595.189.92.189.326 0 .639-.067.92-.19a.32.32 0 0 1 .404.133l2.255 3.922c.09.157.03.36-.133.441a7.896 7.896 0 0 1-3.426.835zm-1.58-7.457c0-.003 0-.009-.003-.013a1.56 1.56 0 0 1 2.337-1.35c.468.269.781.77.781 1.35v.013a1.557 1.557 0 0 1-3.115 0zm-1.068.015H5.384a.318.318 0 0 1-.32-.334c.03-.614.19-1.992.981-3.391l.008-.016.007-.016a7.806 7.806 0 0 1 2.428-2.554.317.317 0 0 1 .448.106l2.282 3.903a.316.316 0 0 1-.082.414 2.371 2.371 0 0 0-.914 1.605.325.325 0 0 1-.314.283zm9.776-.007h-4.526a.32.32 0 0 1-.316-.282 2.371 2.371 0 0 0-.913-1.604.322.322 0 0 1-.082-.414l2.284-3.904a.317.317 0 0 1 .449-.106 7.787 7.787 0 0 1 2.426 2.554l.016.033a7.74 7.74 0 0 1 .98 3.387.319.319 0 0 1-.318.336z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js index fd231aa512b..010c2912f5c 100644 --- a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js @@ -26,7 +26,7 @@ import BugIcon from '../../../components/ui/BugIcon'; import VulnerabilityIcon from '../../../components/ui/VulnerabilityIcon'; import CodeSmellIcon from '../../../components/ui/CodeSmellIcon'; -export default class EntryIssueTypes extends React.Component { +export default class EntryIssueTypes extends React.PureComponent { static propTypes = { bugs: React.PropTypes.number.isRequired, vulnerabilities: React.PropTypes.number.isRequired, diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js index 11db35cac3b..e2a8e7ad16c 100644 --- a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js @@ -26,7 +26,7 @@ import BugIconForSonarQubeDotCom from './BugIconForSonarQubeDotCom'; import VulnerabilityIconForSonarQubeDotCom from './VulnerabilityIconForSonarQubeDotCom'; import CodeSmellIconForSonarQubeDotCom from './CodeSmellIconForSonarQubeDotCom'; -export default class EntryIssueTypesForSonarQubeDotCom extends React.Component { +export default class EntryIssueTypesForSonarQubeDotCom extends React.PureComponent { static propTypes = { bugs: React.PropTypes.number.isRequired, vulnerabilities: React.PropTypes.number.isRequired, diff --git a/server/sonar-web/src/main/js/apps/about/components/ReadMore.js b/server/sonar-web/src/main/js/apps/about/components/ReadMore.js index 2f9c515b713..7318f5eb703 100644 --- a/server/sonar-web/src/main/js/apps/about/components/ReadMore.js +++ b/server/sonar-web/src/main/js/apps/about/components/ReadMore.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class ReadMore extends React.Component { +export default class ReadMore extends React.PureComponent { static propTypes = { link: React.PropTypes.string.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js index 2576a3d5cd5..8f666af2f04 100644 --- a/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js +++ b/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class VulnerabilityIconForSonarQubeDotCom extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg viewBox="0 0 26 26" width="26" height="26"> - <path - style={{ fill: 'currentcolor' }} - d="M7.688 9.224V5.818c0-2.622 2.16-4.756 4.813-4.756 2.654 0 4.802 2.134 4.813 4.756v.931c0 .5-.413.909-.919.909a.916.916 0 0 1-.919-.909v-.93c0-1.624-1.332-2.94-2.975-2.94s-2.975 1.316-2.975 2.94v3.405h7.892c1.401 0 2.539 1.124 2.539 2.509v9.706c0 1.442-1.195 2.623-2.654 2.623H7.688c-1.46 0-2.654-1.18-2.654-2.623v-9.706c0-1.385 1.137-2.509 2.539-2.509h.115zm9.615 13.033a.814.814 0 0 0 .816-.806v-9.718a.692.692 0 0 0-.701-.692H7.573c-.39 0-.7.306-.7.692v9.718c0 .442.367.806.815.806h9.615zm-4.802-8.98c-1.045 0-1.907.84-1.907 1.884 0 .704.402 1.329.988 1.647v2.304c0 .5.414.908.92.908a.916.916 0 0 0 .918-.908v-2.316c.586-.318.988-.942.988-1.646a1.904 1.904 0 0 0-1.907-1.873zM22.99 8.804l-1.7-.681c-.47-.182-1.01.034-1.194.5a.904.904 0 0 0 .505 1.18l1.712.681c.115.046.23.068.344.068a.908.908 0 0 0 .85-.567.91.91 0 0 0-.517-1.18zm-2.837-1.703a.939.939 0 0 0 1.206.488l1.689-.715a.9.9 0 0 0 .482-1.192c-.195-.465-.735-.67-1.206-.477l-1.689.716a.876.876 0 0 0-.482 1.18zm-1.068-1.124c-.471-.181-.69-.715-.506-1.192l.69-1.68c.183-.465.723-.681 1.194-.5.471.182.69.716.506 1.181l-.69 1.692a.908.908 0 0 1-.85.567.932.932 0 0 1-.344-.068z" - /> - </svg> - ); - } +export default function VulnerabilityIconForSonarQubeDotCom() { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path + style={{ fill: 'currentcolor' }} + d="M7.688 9.224V5.818c0-2.622 2.16-4.756 4.813-4.756 2.654 0 4.802 2.134 4.813 4.756v.931c0 .5-.413.909-.919.909a.916.916 0 0 1-.919-.909v-.93c0-1.624-1.332-2.94-2.975-2.94s-2.975 1.316-2.975 2.94v3.405h7.892c1.401 0 2.539 1.124 2.539 2.509v9.706c0 1.442-1.195 2.623-2.654 2.623H7.688c-1.46 0-2.654-1.18-2.654-2.623v-9.706c0-1.385 1.137-2.509 2.539-2.509h.115zm9.615 13.033a.814.814 0 0 0 .816-.806v-9.718a.692.692 0 0 0-.701-.692H7.573c-.39 0-.7.306-.7.692v9.718c0 .442.367.806.815.806h9.615zm-4.802-8.98c-1.045 0-1.907.84-1.907 1.884 0 .704.402 1.329.988 1.647v2.304c0 .5.414.908.92.908a.916.916 0 0 0 .918-.908v-2.316c.586-.318.988-.942.988-1.646a1.904 1.904 0 0 0-1.907-1.873zM22.99 8.804l-1.7-.681c-.47-.182-1.01.034-1.194.5a.904.904 0 0 0 .505 1.18l1.712.681c.115.046.23.068.344.068a.908.908 0 0 0 .85-.567.91.91 0 0 0-.517-1.18zm-2.837-1.703a.939.939 0 0 0 1.206.488l1.689-.715a.9.9 0 0 0 .482-1.192c-.195-.465-.735-.67-1.206-.477l-1.689.716a.876.876 0 0 0-.482 1.18zm-1.068-1.124c-.471-.181-.69-.715-.506-1.192l.69-1.68c.183-.465.723-.681 1.194-.5.471.182.69.716.506 1.181l-.69 1.692a.908.908 0 0 1-.85.567.932.932 0 0 1-.344-.068z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/apps/account/components/Account.js b/server/sonar-web/src/main/js/apps/account/components/Account.js index 2240231a9e9..aed774b7bac 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Account.js +++ b/server/sonar-web/src/main/js/apps/account/components/Account.js @@ -25,7 +25,7 @@ import { getCurrentUser, areThereCustomOrganizations } from '../../../store/root import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; import '../account.css'; -class Account extends React.Component { +class Account extends React.PureComponent { componentDidMount() { if (!this.props.currentUser.isLoggedIn) { handleRequiredAuthentication(); diff --git a/server/sonar-web/src/main/js/apps/account/components/Nav.js b/server/sonar-web/src/main/js/apps/account/components/Nav.js index c2770721d8a..65c06efeb12 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Nav.js +++ b/server/sonar-web/src/main/js/apps/account/components/Nav.js @@ -26,38 +26,38 @@ type Props = { customOrganizations: boolean }; -const Nav = ({ customOrganizations }: Props) => ( - <nav className="account-nav clearfix"> - <ul className="nav navbar-nav nav-tabs"> - <li> - <IndexLink to="/account/" activeClassName="active"> - {translate('my_account.profile')} - </IndexLink> - </li> - <li> - <Link to="/account/security/" activeClassName="active"> - {translate('my_account.security')} - </Link> - </li> - <li> - <Link to="/account/notifications" activeClassName="active"> - {translate('my_account.notifications')} - </Link> - </li> - {!customOrganizations && +export default function Nav({ customOrganizations }: Props) { + return ( + <nav className="account-nav clearfix"> + <ul className="nav navbar-nav nav-tabs"> <li> - <Link to="/account/projects/" activeClassName="active"> - {translate('my_account.projects')} + <IndexLink to="/account/" activeClassName="active"> + {translate('my_account.profile')} + </IndexLink> + </li> + <li> + <Link to="/account/security/" activeClassName="active"> + {translate('my_account.security')} </Link> - </li>} - {customOrganizations && + </li> <li> - <Link to="/account/organizations" activeClassName="active"> - {translate('my_account.organizations')} + <Link to="/account/notifications" activeClassName="active"> + {translate('my_account.notifications')} </Link> - </li>} - </ul> - </nav> -); - -export default Nav; + </li> + {!customOrganizations && + <li> + <Link to="/account/projects/" activeClassName="active"> + {translate('my_account.projects')} + </Link> + </li>} + {customOrganizations && + <li> + <Link to="/account/organizations" activeClassName="active"> + {translate('my_account.organizations')} + </Link> + </li>} + </ul> + </nav> + ); +} diff --git a/server/sonar-web/src/main/js/apps/account/components/Security.js b/server/sonar-web/src/main/js/apps/account/components/Security.js index 6e4a670d143..f444538f1ee 100644 --- a/server/sonar-web/src/main/js/apps/account/components/Security.js +++ b/server/sonar-web/src/main/js/apps/account/components/Security.js @@ -25,24 +25,22 @@ import Tokens from './Tokens'; import { translate } from '../../../helpers/l10n'; import { getCurrentUser } from '../../../store/rootReducer'; -class Security extends React.Component { - render() { - const { user } = this.props; +function Security(props) { + const { user } = props; - const title = translate('my_account.page') + ' - ' + translate('my_account.security'); + const title = translate('my_account.page') + ' - ' + translate('my_account.security'); - return ( - <div className="account-body account-container"> - <Helmet title={title} titleTemplate="SonarQube - %s" /> + return ( + <div className="account-body account-container"> + <Helmet title={title} titleTemplate="SonarQube - %s" /> - <Tokens user={user} /> + <Tokens user={user} /> - {user.local && <hr className="account-separator" />} + {user.local && <hr className="account-separator" />} - {user.local && <Password user={user} />} - </div> - ); - } + {user.local && <Password user={user} />} + </div> + ); } export default connect(state => ({ user: getCurrentUser(state) }))(Security); diff --git a/server/sonar-web/src/main/js/apps/account/components/UserCard.js b/server/sonar-web/src/main/js/apps/account/components/UserCard.js index 5635f828279..0659fc188e1 100644 --- a/server/sonar-web/src/main/js/apps/account/components/UserCard.js +++ b/server/sonar-web/src/main/js/apps/account/components/UserCard.js @@ -20,7 +20,7 @@ import React from 'react'; import Avatar from '../../../components/ui/Avatar'; -export default class UserCard extends React.Component { +export default class UserCard extends React.PureComponent { static propTypes = { user: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js index 46cf99ccb4b..71cfd434b77 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/GlobalNotifications.js @@ -34,46 +34,44 @@ import type { } from '../../../store/notifications/duck'; import { addNotification, removeNotification } from './actions'; -class GlobalNotifications extends React.Component { - props: { - notifications: NotificationsState, - channels: ChannelsState, - types: TypesState, - addNotification: (n: Notification) => void, - removeNotification: (n: Notification) => void - }; +type Props = { + notifications: NotificationsState, + channels: ChannelsState, + types: TypesState, + addNotification: (n: Notification) => void, + removeNotification: (n: Notification) => void +}; - render() { - return ( - <section> - <h2 className="spacer-bottom"> - {translate('my_profile.overall_notifications.title')} - </h2> +function GlobalNotifications(props: Props) { + return ( + <section> + <h2 className="spacer-bottom"> + {translate('my_profile.overall_notifications.title')} + </h2> - <table className="form"> - <thead> - <tr> - <th /> - {this.props.channels.map(channel => ( - <th key={channel} className="text-center"> - <h4>{translate('notification.channel', channel)}</h4> - </th> - ))} - </tr> - </thead> + <table className="form"> + <thead> + <tr> + <th /> + {props.channels.map(channel => ( + <th key={channel} className="text-center"> + <h4>{translate('notification.channel', channel)}</h4> + </th> + ))} + </tr> + </thead> - <NotificationsList - notifications={this.props.notifications} - channels={this.props.channels} - types={this.props.types} - checkboxId={(d, c) => `global-notification-${d}-${c}`} - onAdd={this.props.addNotification} - onRemove={this.props.removeNotification} - /> - </table> - </section> - ); - } + <NotificationsList + notifications={props.notifications} + channels={props.channels} + types={props.types} + checkboxId={(d, c) => `global-notification-${d}-${c}`} + onAdd={props.addNotification} + onRemove={props.removeNotification} + /> + </table> + </section> + ); } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js index 8d852e2b567..6f27b3141dc 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Notifications.js @@ -26,7 +26,7 @@ import Projects from './Projects'; import { translate } from '../../../helpers/l10n'; import { fetchNotifications } from './actions'; -class Notifications extends React.Component { +class Notifications extends React.PureComponent { props: { fetchNotifications: () => void }; diff --git a/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js b/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js index 193381d9110..31c21caf958 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/NotificationsList.js @@ -27,7 +27,7 @@ import { TypesState } from '../../../store/notifications/duck'; -export default class NotificationsList extends React.Component { +export default class NotificationsList extends React.PureComponent { props: { onAdd: (n: Notification) => void, onRemove: (n: Notification) => void, diff --git a/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js b/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js index 1f2359717c4..f79f666e9db 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/ProjectNotifications.js @@ -37,7 +37,7 @@ import type { import { addNotification, removeNotification } from './actions'; import { getProjectUrl } from '../../../helpers/urls'; -class ProjectNotifications extends React.Component { +class ProjectNotifications extends React.PureComponent { props: { project: { key: string, diff --git a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js index e378b4a0a95..89a3a5e7661 100644 --- a/server/sonar-web/src/main/js/apps/account/notifications/Projects.js +++ b/server/sonar-web/src/main/js/apps/account/notifications/Projects.js @@ -41,7 +41,7 @@ type State = { }> }; -class Projects extends React.Component { +class Projects extends React.PureComponent { props: Props; state: State = { diff --git a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js index 04b822d40b2..7a9f2104777 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/CreateOrganizationForm.js @@ -36,7 +36,7 @@ type State = { url: string }; -class CreateOrganizationForm extends React.Component { +class CreateOrganizationForm extends React.PureComponent { mounted: boolean; state: State; props: { diff --git a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js index e3adb69a2d8..8627962b54b 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationCard.js @@ -22,42 +22,40 @@ import React from 'react'; import OrganizationLink from '../../../components/ui/OrganizationLink'; import type { Organization } from '../../../store/organizations/duck'; -export default class OrganizationCard extends React.Component { - props: { - organization: Organization - }; +type Props = { + organization: Organization +}; - render() { - const { organization } = this.props; +export default function OrganizationCard(props: Props) { + const { organization } = props; - return ( - <div className="account-project-card clearfix"> - <aside className="account-project-side"> - {!!organization.avatar && - <div className="spacer-bottom"> - <img src={organization.avatar} height={30} alt={organization.name} /> - </div>} - {!!organization.url && - <div className="text-limited text-top spacer-bottom"> - <a className="small" href={organization.url} title={organization.url} rel="nofollow"> - {organization.url} - </a> - </div>} - </aside> + return ( + <div className="account-project-card clearfix"> + <aside className="account-project-side"> + {!!organization.avatar && + <div className="spacer-bottom"> + <img src={organization.avatar} height={30} alt={organization.name} /> + </div>} + {!!organization.url && + <div className="text-limited text-top spacer-bottom"> + <a className="small" href={organization.url} title={organization.url} rel="nofollow"> + {organization.url} + </a> + </div>} + </aside> - <h3 className="account-project-name"> - <OrganizationLink organization={organization}> - {organization.name} - </OrganizationLink> - </h3> + <h3 className="account-project-name"> + <OrganizationLink organization={organization}> + {organization.name} + </OrganizationLink> + </h3> - <div className="account-project-key">{organization.key}</div> + <div className="account-project-key">{organization.key}</div> - {!!organization.description && - <div className="account-project-description"> - {organization.description} - </div>} - </div> - ); - } + {!!organization.description && + <div className="account-project-description"> + {organization.description} + </div>} + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js index a41bf9b2bef..222f9df73ab 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/OrganizationsList.js @@ -22,20 +22,18 @@ import React from 'react'; import OrganizationCard from './OrganizationCard'; import type { Organization } from '../../../store/organizations/duck'; -export default class OrganizationsList extends React.Component { - props: { - organizations: Array<Organization> - }; +type Props = { + organizations: Array<Organization> +}; - render() { - return ( - <ul className="account-projects-list"> - {this.props.organizations.map(organization => ( - <li key={organization.key}> - <OrganizationCard organization={organization} /> - </li> - ))} - </ul> - ); - } +export default function OrganizationsList(props: Props) { + return ( + <ul className="account-projects-list"> + {props.organizations.map(organization => ( + <li key={organization.key}> + <OrganizationCard organization={organization} /> + </li> + ))} + </ul> + ); } diff --git a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js index 00cf8d9b1fe..e34189eb809 100644 --- a/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js +++ b/server/sonar-web/src/main/js/apps/account/organizations/UserOrganizations.js @@ -29,13 +29,13 @@ import { getMyOrganizations, getSettingValue, getCurrentUser } from '../../../st import type { Organization } from '../../../store/organizations/duck'; import { isUserAdmin } from '../../../helpers/users'; -class UserOrganizations extends React.Component { +class UserOrganizations extends React.PureComponent { mounted: boolean; props: { anyoneCanCreate?: { value: string }, currentUser: Object, - children: Object, + children?: React.Element<*>, organizations: Array<Organization>, fetchIfAnyoneCanCreateOrganizations: () => Promise<*>, fetchMyOrganizations: () => Promise<*> diff --git a/server/sonar-web/src/main/js/apps/account/profile/Profile.js b/server/sonar-web/src/main/js/apps/account/profile/Profile.js index ebcbf0d8a07..f4216612dcb 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/Profile.js +++ b/server/sonar-web/src/main/js/apps/account/profile/Profile.js @@ -25,48 +25,46 @@ import UserGroups from './UserGroups'; import UserScmAccounts from './UserScmAccounts'; import { getCurrentUser, areThereCustomOrganizations } from '../../../store/rootReducer'; -class Profile extends React.Component { - props: { - customOrganizations: boolean, - user: { - email?: string, - externalProvider?: string, - groups: Array<*>, - local: boolean, - login: string, - scmAccounts: Array<*> - } - }; +type Props = { + customOrganizations: boolean, + user: { + email?: string, + externalProvider?: string, + groups: Array<*>, + local: boolean, + login: string, + scmAccounts: Array<*> + } +}; - render() { - const { customOrganizations, user } = this.props; +function Profile(props: Props) { + const { customOrganizations, user } = props; - return ( - <div className="account-body account-container"> - <div className="spacer-bottom"> - Login: <strong id="login">{user.login}</strong> - </div> + return ( + <div className="account-body account-container"> + <div className="spacer-bottom"> + Login: <strong id="login">{user.login}</strong> + </div> - {!user.local && - user.externalProvider !== 'sonarqube' && - <div id="identity-provider" className="spacer-bottom"> - <UserExternalIdentity user={user} /> - </div>} + {!user.local && + user.externalProvider !== 'sonarqube' && + <div id="identity-provider" className="spacer-bottom"> + <UserExternalIdentity user={user} /> + </div>} - {!!user.email && - <div className="spacer-bottom"> - Email: <strong id="email">{user.email}</strong> - </div>} + {!!user.email && + <div className="spacer-bottom"> + Email: <strong id="email">{user.email}</strong> + </div>} - {!customOrganizations && <hr className="account-separator" />} - {!customOrganizations && <UserGroups groups={user.groups} />} + {!customOrganizations && <hr className="account-separator" />} + {!customOrganizations && <UserGroups groups={user.groups} />} - <hr className="account-separator" /> + <hr className="account-separator" /> - <UserScmAccounts user={user} scmAccounts={user.scmAccounts} /> - </div> - ); - } + <UserScmAccounts user={user} scmAccounts={user.scmAccounts} /> + </div> + ); } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js index 8cbb30de069..775716fa43e 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js +++ b/server/sonar-web/src/main/js/apps/account/profile/UserExternalIdentity.js @@ -20,7 +20,7 @@ import React from 'react'; import { getIdentityProviders } from '../../../api/users'; -export default class UserExternalIdentity extends React.Component { +export default class UserExternalIdentity extends React.PureComponent { state = { loading: true }; diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js b/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js index f71360cdb1c..f67ab5124ac 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js +++ b/server/sonar-web/src/main/js/apps/account/profile/UserGroups.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class UserGroups extends React.Component { +export default class UserGroups extends React.PureComponent { static propTypes = { groups: React.PropTypes.arrayOf(React.PropTypes.string).isRequired }; diff --git a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js index fa42ae4262a..d1da44d3290 100644 --- a/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js +++ b/server/sonar-web/src/main/js/apps/account/profile/UserScmAccounts.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class UserScmAccounts extends React.Component { +export default class UserScmAccounts extends React.PureComponent { static propTypes = { user: React.PropTypes.object.isRequired, scmAccounts: React.PropTypes.arrayOf(React.PropTypes.string).isRequired diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js index 074fd288f8b..2d263a0daf8 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectCard.js @@ -25,7 +25,7 @@ import Level from '../../../components/ui/Level'; import { projectType } from './propTypes'; import { translateWithParameters, translate } from '../../../helpers/l10n'; -export default class ProjectCard extends React.Component { +export default class ProjectCard extends React.PureComponent { static propTypes = { project: projectType.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/account/projects/Projects.js b/server/sonar-web/src/main/js/apps/account/projects/Projects.js index 6fe13a1e67a..9ecc0a633ee 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/Projects.js +++ b/server/sonar-web/src/main/js/apps/account/projects/Projects.js @@ -23,7 +23,7 @@ import ListFooter from '../../../components/controls/ListFooter'; import { projectsListType } from './propTypes'; import { translate } from '../../../helpers/l10n'; -export default class Projects extends React.Component { +export default class Projects extends React.PureComponent { static propTypes = { projects: projectsListType.isRequired, total: React.PropTypes.number.isRequired, diff --git a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js index 240815f2602..b944998be0f 100644 --- a/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js +++ b/server/sonar-web/src/main/js/apps/account/projects/ProjectsContainer.js @@ -23,7 +23,7 @@ import Projects from './Projects'; import { getMyProjects } from '../../../api/components'; import { translate } from '../../../helpers/l10n'; -export default class ProjectsContainer extends React.Component { +export default class ProjectsContainer extends React.PureComponent { state = { loading: true, page: 1, diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js index a0994d4bef8..af0e2743612 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/BackgroundTasksApp.js @@ -19,7 +19,6 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { debounce, uniq } from 'lodash'; import { connect } from 'react-redux'; import { DEFAULT_FILTERS, DEBOUNCE_DELAY, STATUSES, CURRENTS } from './../constants'; @@ -56,7 +55,7 @@ type State = { failingCount: number }; -class BackgroundTasksApp extends React.Component { +class BackgroundTasksApp extends React.PureComponent { loadTasksDebounced: Function; mounted: boolean; props: Props; @@ -90,10 +89,6 @@ class BackgroundTasksApp extends React.Component { }); } - shouldComponentUpdate(nextProps: Props, nextState: State) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate(prevProps: Props) { if ( prevProps.component !== this.props.component || prevProps.location !== this.props.location diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js index 58d8fd12cff..f14ff423f91 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Search.js @@ -26,7 +26,7 @@ import DateFilter from './DateFilter'; import { DEFAULT_FILTERS } from './../constants'; import { translate } from '../../../helpers/l10n'; -export default class Search extends React.Component { +export default class Search extends React.PureComponent { static propTypes = { loading: React.PropTypes.bool.isRequired, status: React.PropTypes.any.isRequired, diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js index 8a8be6ad4f0..4c57544f5a5 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Stats.js @@ -19,7 +19,6 @@ */ /* @flow */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { translate } from '../../../helpers/l10n'; type Props = { @@ -31,14 +30,10 @@ type Props = { type State = Object; -export default class Stats extends React.Component { +export default class Stats extends React.PureComponent { props: Props; state: State; - shouldComponentUpdate(nextProps: Props, nextState: State) { - return shallowCompare(this, nextProps, nextState); - } - handleCancelAllPending(e: Object) { e.preventDefault(); e.target.blur(); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js index 3caf3566f24..ca8cc8c84fd 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Task.js @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import TaskStatus from './TaskStatus'; import TaskComponent from './TaskComponent'; import TaskId from './TaskId'; @@ -27,7 +26,7 @@ import TaskDate from './TaskDate'; import TaskExecutionTime from './TaskExecutionTime'; import TaskActions from './TaskActions'; -export default class Task extends React.Component { +export default class Task extends React.PureComponent { static propTypes = { task: React.PropTypes.object.isRequired, index: React.PropTypes.number.isRequired, @@ -38,10 +37,6 @@ export default class Task extends React.Component { onFilterTask: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - render() { const { task, index, tasks, component, types, onCancelTask, onFilterTask } = this.props; diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js index e9d9c48c4bb..1acde211d5f 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskActions.js @@ -18,17 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import ScannerContextView from '../views/ScannerContextView'; import StacktraceView from '../views/StacktraceView'; import { STATUSES } from './../constants'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -export default class TaskActions extends React.Component { - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - +export default class TaskActions extends React.PureComponent { handleFilterClick(e) { e.preventDefault(); this.props.onFilterTask(this.props.task); diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js index 2a9fb4157ae..7f803d325db 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/TaskComponent.js @@ -25,38 +25,36 @@ import QualifierIcon from '../../../components/shared/QualifierIcon'; import Organization from '../../../components/shared/Organization'; import { Task } from '../types'; -export default class TaskComponent extends React.Component { - props: { - task: Task, - types: Array<string> - }; +type Props = { + task: Task, + types: Array<string> +}; - render() { - const { task, types } = this.props; - - if (!task.componentKey) { - return ( - <td> - <span className="note">{task.id}</span> - {types.length > 1 && <TaskType task={task} />} - </td> - ); - } +export default function TaskComponent(props: Props) { + const { task, types } = props; + if (!task.componentKey) { return ( <td> - <span className="little-spacer-right"> - <QualifierIcon qualifier={task.componentQualifier} /> - </span> - - {task.organization != null && <Organization organizationKey={task.organization} />} - - <Link to={{ pathname: '/dashboard', query: { id: task.componentKey } }}> - {task.componentName} - </Link> - + <span className="note">{task.id}</span> {types.length > 1 && <TaskType task={task} />} </td> ); } + + return ( + <td> + <span className="little-spacer-right"> + <QualifierIcon qualifier={task.componentQualifier} /> + </span> + + {task.organization != null && <Organization organizationKey={task.organization} />} + + <Link to={{ pathname: '/dashboard', query: { id: task.componentKey } }}> + {task.componentName} + </Link> + + {types.length > 1 && <TaskType task={task} />} + </td> + ); } diff --git a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js index 1fa5cf0aee4..5b8903a9b58 100644 --- a/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js +++ b/server/sonar-web/src/main/js/apps/background-tasks/components/Tasks.js @@ -19,7 +19,6 @@ */ /* @flow */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import classNames from 'classnames'; import Task from './Task'; import { translate } from '../../../helpers/l10n'; @@ -35,14 +34,10 @@ type Props = { type State = Object; -export default class Tasks extends React.Component { +export default class Tasks extends React.PureComponent { props: Props; state: State; - shouldComponentUpdate(nextProps: Props, nextState: State) { - return shallowCompare(this, nextProps, nextState); - } - render() { const { tasks, component, types, loading, onCancelTask, onFilterTask } = this.props; diff --git a/server/sonar-web/src/main/js/apps/code/components/App.js b/server/sonar-web/src/main/js/apps/code/components/App.js index a8a8fd02a51..00f0dee1302 100644 --- a/server/sonar-web/src/main/js/apps/code/components/App.js +++ b/server/sonar-web/src/main/js/apps/code/components/App.js @@ -35,7 +35,7 @@ import { addComponent, addComponentBreadcrumbs, clearBucket } from '../bucket'; import { getComponent } from '../../../store/rootReducer'; import '../code.css'; -class App extends React.Component { +class App extends React.PureComponent { state = { loading: true, baseComponent: null, diff --git a/server/sonar-web/src/main/js/apps/code/components/Breadcrumb.js b/server/sonar-web/src/main/js/apps/code/components/Breadcrumb.js index 99dc00ab670..3e0ce74f384 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Breadcrumb.js +++ b/server/sonar-web/src/main/js/apps/code/components/Breadcrumb.js @@ -20,8 +20,8 @@ import React from 'react'; import ComponentName from './ComponentName'; -const Breadcrumb = ({ rootComponent, component, canBrowse }) => ( - <ComponentName rootComponent={rootComponent} component={component} canBrowse={canBrowse} /> -); - -export default Breadcrumb; +export default function Breadcrumb({ rootComponent, component, canBrowse }) { + return ( + <ComponentName rootComponent={rootComponent} component={component} canBrowse={canBrowse} /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/code/components/Breadcrumbs.js b/server/sonar-web/src/main/js/apps/code/components/Breadcrumbs.js index fe9116f7cfc..1770620d9dd 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Breadcrumbs.js +++ b/server/sonar-web/src/main/js/apps/code/components/Breadcrumbs.js @@ -20,18 +20,18 @@ import React from 'react'; import Breadcrumb from './Breadcrumb'; -const Breadcrumbs = ({ rootComponent, breadcrumbs }) => ( - <ul className="code-breadcrumbs"> - {breadcrumbs.map((component, index) => ( - <li key={component.key}> - <Breadcrumb - rootComponent={rootComponent} - component={component} - canBrowse={index < breadcrumbs.length - 1} - /> - </li> - ))} - </ul> -); - -export default Breadcrumbs; +export default function Breadcrumbs({ rootComponent, breadcrumbs }) { + return ( + <ul className="code-breadcrumbs"> + {breadcrumbs.map((component, index) => ( + <li key={component.key}> + <Breadcrumb + rootComponent={rootComponent} + component={component} + canBrowse={index < breadcrumbs.length - 1} + /> + </li> + ))} + </ul> + ); +} diff --git a/server/sonar-web/src/main/js/apps/code/components/Component.js b/server/sonar-web/src/main/js/apps/code/components/Component.js index 9166c570e7a..5d55a82684c 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Component.js +++ b/server/sonar-web/src/main/js/apps/code/components/Component.js @@ -20,7 +20,6 @@ import classNames from 'classnames'; import React from 'react'; import ReactDOM from 'react-dom'; -import shallowCompare from 'react-addons-shallow-compare'; import ComponentName from './ComponentName'; import ComponentMeasure from './ComponentMeasure'; import ComponentDetach from './ComponentDetach'; @@ -29,15 +28,11 @@ import ComponentPin from './ComponentPin'; const TOP_OFFSET = 200; const BOTTOM_OFFSET = 10; -export default class Component extends React.Component { +export default class Component extends React.PureComponent { componentDidMount() { this.handleUpdate(); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate() { this.handleUpdate(); } diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentDetach.js b/server/sonar-web/src/main/js/apps/code/components/ComponentDetach.js index 69e1aafd253..5277be98427 100644 --- a/server/sonar-web/src/main/js/apps/code/components/ComponentDetach.js +++ b/server/sonar-web/src/main/js/apps/code/components/ComponentDetach.js @@ -21,12 +21,12 @@ import React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; -const ComponentDetach = ({ component }) => ( - <Link - to={{ pathname: '/dashboard', query: { id: component.refKey || component.key } }} - className="icon-detach" - title={translate('code.open_component_page')} - /> -); - -export default ComponentDetach; +export default function ComponentDetach({ component }) { + return ( + <Link + to={{ pathname: '/dashboard', query: { id: component.refKey || component.key } }} + className="icon-detach" + title={translate('code.open_component_page')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/code/components/Components.js b/server/sonar-web/src/main/js/apps/code/components/Components.js index 62d653d3543..2d492285a2c 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Components.js +++ b/server/sonar-web/src/main/js/apps/code/components/Components.js @@ -22,35 +22,35 @@ import Component from './Component'; import ComponentsEmpty from './ComponentsEmpty'; import ComponentsHeader from './ComponentsHeader'; -const Components = ({ rootComponent, baseComponent, components, selected }) => ( - <table className="data zebra"> - <ComponentsHeader baseComponent={baseComponent} rootComponent={rootComponent} /> - {baseComponent && +export default function Components({ rootComponent, baseComponent, components, selected }) { + return ( + <table className="data zebra"> + <ComponentsHeader baseComponent={baseComponent} rootComponent={rootComponent} /> + {baseComponent && + <tbody> + <Component + key={baseComponent.key} + rootComponent={rootComponent} + component={baseComponent} + /> + <tr className="blank"> + <td colSpan="8"> </td> + </tr> + </tbody>} <tbody> - <Component - key={baseComponent.key} - rootComponent={rootComponent} - component={baseComponent} - /> - <tr className="blank"> - <td colSpan="8"> </td> - </tr> - </tbody>} - <tbody> - {components.length - ? components.map((component, index, list) => ( - <Component - key={component.key} - rootComponent={rootComponent} - component={component} - selected={component === selected} - previous={index > 0 ? list[index - 1] : null} - canBrowse={true} - /> - )) - : <ComponentsEmpty />} - </tbody> - </table> -); - -export default Components; + {components.length + ? components.map((component, index, list) => ( + <Component + key={component.key} + rootComponent={rootComponent} + component={component} + selected={component === selected} + previous={index > 0 ? list[index - 1] : null} + canBrowse={true} + /> + )) + : <ComponentsEmpty />} + </tbody> + </table> + ); +} diff --git a/server/sonar-web/src/main/js/apps/code/components/ComponentsEmpty.js b/server/sonar-web/src/main/js/apps/code/components/ComponentsEmpty.js index ea40873c8db..02169f172db 100644 --- a/server/sonar-web/src/main/js/apps/code/components/ComponentsEmpty.js +++ b/server/sonar-web/src/main/js/apps/code/components/ComponentsEmpty.js @@ -20,13 +20,13 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -const ComponentsEmpty = () => ( - <tr> - <td colSpan="2"> - {translate('no_results')} - </td> - <td colSpan="6" /> - </tr> -); - -export default ComponentsEmpty; +export default function ComponentsEmpty() { + return ( + <tr> + <td colSpan="2"> + {translate('no_results')} + </td> + <td colSpan="6" /> + </tr> + ); +} diff --git a/server/sonar-web/src/main/js/apps/code/components/Search.js b/server/sonar-web/src/main/js/apps/code/components/Search.js index 0c2d95a7209..508487eaea0 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Search.js +++ b/server/sonar-web/src/main/js/apps/code/components/Search.js @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import classNames from 'classnames'; import { debounce } from 'lodash'; import Components from './Components'; @@ -27,7 +26,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { parseError } from '../utils'; import { getComponentUrl } from '../../../helpers/urls'; -export default class Search extends React.Component { +export default class Search extends React.PureComponent { static contextTypes = { router: React.PropTypes.object.isRequired }; @@ -66,10 +65,6 @@ export default class Search extends React.Component { } } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentWillUnmount() { this.mounted = false; } diff --git a/server/sonar-web/src/main/js/apps/code/components/Truncated.js b/server/sonar-web/src/main/js/apps/code/components/Truncated.js index 82c6cd14fdd..c6e380859db 100644 --- a/server/sonar-web/src/main/js/apps/code/components/Truncated.js +++ b/server/sonar-web/src/main/js/apps/code/components/Truncated.js @@ -19,10 +19,10 @@ */ import React from 'react'; -const Truncated = ({ children, title }) => ( - <span className="code-truncated" title={title}> - {children} - </span> -); - -export default Truncated; +export default function Truncated({ children, title }) { + return ( + <span className="code-truncated" title={title}> + {children} + </span> + ); +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/app/App.js b/server/sonar-web/src/main/js/apps/component-measures/app/App.js index b8e50e87846..1e005ee4c70 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/app/App.js +++ b/server/sonar-web/src/main/js/apps/component-measures/app/App.js @@ -21,7 +21,7 @@ import React from 'react'; import Spinner from './../components/Spinner'; import '../styles.css'; -export default class App extends React.Component { +export default class App extends React.PureComponent { state = { componentSet: false }; componentDidMount() { diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js b/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js index 31f66a71fdb..4700219e15b 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/Measure.js @@ -24,7 +24,7 @@ import { formatMeasure } from '../../../helpers/measures'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { formatLeak, isDiffMetric, getRatingTooltip } from '../utils'; -export default class Measure extends React.Component { +export default class Measure extends React.PureComponent { static propTypes = { measure: React.PropTypes.object, metric: React.PropTypes.object diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js b/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js index 00340d6af08..4729500df36 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/bubbleChart/BubbleChart.js @@ -34,7 +34,7 @@ function getMeasure(component, metric) { return Number(component.measures[metric]) || 0; } -export default class BubbleChart extends React.Component { +export default class BubbleChart extends React.PureComponent { state = { fetching: 0, files: [] diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js b/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js index 46571e5077b..0c6f0cfd625 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/MeasureDetails.js @@ -26,7 +26,7 @@ import MetricNotFound from './MetricNotFound'; import { getPeriod, getPeriodDate } from '../../../helpers/periods'; import { translate, translateWithParameters } from '../../../helpers/l10n'; -export default class MeasureDetails extends React.Component { +export default class MeasureDetails extends React.PureComponent { mounted: boolean; state = { diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js b/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js index f16edc1f4d5..57b5fee5844 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/MetricNotFound.js @@ -21,14 +21,12 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class MetricNotFound extends React.Component { - render() { - return ( - <div className="page page-limited"> - <div className="alert alert-danger"> - {translate('component_measures.not_found')} - </div> +export default function MetricNotFound() { + return ( + <div className="page page-limited"> + <div className="alert alert-danger"> + {translate('component_measures.not_found')} </div> - ); - } + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js index b6d5f03ca38..b3413a23c7c 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/ListView.js @@ -26,7 +26,7 @@ import Spinner from '../../components/Spinner'; import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; import ListFooter from '../../../../components/controls/ListFooter'; -export default class ListView extends React.Component { +export default class ListView extends React.PureComponent { static contextTypes = { router: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js index 699bba21e71..fdde4ab81bf 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/MeasureDrilldown.js @@ -27,82 +27,80 @@ import IconHistory from './../../components/IconHistory'; import { hasHistory, hasBubbleChart, hasTreemap } from '../../utils'; import { translate } from '../../../../helpers/l10n'; -export default class MeasureDrilldown extends React.Component { - render() { - const { children, component, metric, ...other } = this.props; +export default function MeasureDrilldown(props) { + const { children, component, metric, ...other } = props; - const child = React.cloneElement(children, { ...other }); - - return ( - <div className="measure-details-drilldown"> - <ul className="measure-details-drilldown-mode"> - {component.qualifier !== 'DEV' && - <li> - <Link - activeClassName="active" - to={{ - pathname: `/component_measures/metric/${metric.key}/list`, - query: { id: component.key } - }}> - <IconList /> - {translate('component_measures.tab.list')} - </Link> - </li>} + const child = React.cloneElement(children, { ...other }); + return ( + <div className="measure-details-drilldown"> + <ul className="measure-details-drilldown-mode"> + {component.qualifier !== 'DEV' && <li> <Link activeClassName="active" to={{ - pathname: `/component_measures/metric/${metric.key}/tree`, + pathname: `/component_measures/metric/${metric.key}/list`, query: { id: component.key } }}> - <IconTree /> - {translate('component_measures.tab.tree')} + <IconList /> + {translate('component_measures.tab.list')} </Link> - </li> + </li>} - {hasBubbleChart(metric.key) && - <li> - <Link - activeClassName="active" - to={{ - pathname: `/component_measures/metric/${metric.key}/bubbles`, - query: { id: component.key } - }}> - <IconBubbles /> - {translate('component_measures.tab.bubbles')} - </Link> - </li>} + <li> + <Link + activeClassName="active" + to={{ + pathname: `/component_measures/metric/${metric.key}/tree`, + query: { id: component.key } + }}> + <IconTree /> + {translate('component_measures.tab.tree')} + </Link> + </li> - {hasTreemap(metric) && - <li> - <Link - activeClassName="active" - to={{ - pathname: `/component_measures/metric/${metric.key}/treemap`, - query: { id: component.key } - }}> - <IconTreemap /> - {translate('component_measures.tab.treemap')} - </Link> - </li>} + {hasBubbleChart(metric.key) && + <li> + <Link + activeClassName="active" + to={{ + pathname: `/component_measures/metric/${metric.key}/bubbles`, + query: { id: component.key } + }}> + <IconBubbles /> + {translate('component_measures.tab.bubbles')} + </Link> + </li>} - {hasHistory(metric.key) && - <li> - <Link - activeClassName="active" - to={{ - pathname: `/component_measures/metric/${metric.key}/history`, - query: { id: component.key } - }}> - <IconHistory /> - {translate('component_measures.tab.history')} - </Link> - </li>} - </ul> + {hasTreemap(metric) && + <li> + <Link + activeClassName="active" + to={{ + pathname: `/component_measures/metric/${metric.key}/treemap`, + query: { id: component.key } + }}> + <IconTreemap /> + {translate('component_measures.tab.treemap')} + </Link> + </li>} + + {hasHistory(metric.key) && + <li> + <Link + activeClassName="active" + to={{ + pathname: `/component_measures/metric/${metric.key}/history`, + query: { id: component.key } + }}> + <IconHistory /> + {translate('component_measures.tab.history')} + </Link> + </li>} + </ul> - {child} - </div> - ); - } + {child} + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js index 5a038da60e8..a66f31d6c64 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/drilldown/TreeView.js @@ -25,7 +25,7 @@ import Spinner from '../../components/Spinner'; import SourceViewer from '../../../../components/SourceViewer/SourceViewer'; import ListFooter from '../../../../components/controls/ListFooter'; -export default class TreeView extends React.Component { +export default class TreeView extends React.PureComponent { componentDidMount() { this.handleChangeBaseComponent(this.props.component); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/history/MeasureHistory.js b/server/sonar-web/src/main/js/apps/component-measures/details/history/MeasureHistory.js index dc1202526b1..e37cdd2c688 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/history/MeasureHistory.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/history/MeasureHistory.js @@ -29,7 +29,7 @@ import { translate } from '../../../../helpers/l10n'; const HEIGHT = 500; -export default class MeasureHistory extends React.Component { +export default class MeasureHistory extends React.PureComponent { state = { components: [], selected: null, diff --git a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js b/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js index 5287d9f05a6..2516b8d9d02 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js +++ b/server/sonar-web/src/main/js/apps/component-measures/details/treemap/MeasureTreemap.js @@ -34,7 +34,7 @@ import Workspace from '../../../../components/workspace/main'; const HEIGHT = 500; -export default class MeasureTreemap extends React.Component { +export default class MeasureTreemap extends React.PureComponent { state = { fetching: true, components: [], diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js index c1782709ea0..eafc7bcc324 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js +++ b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasures.js @@ -21,22 +21,20 @@ import React from 'react'; import AllMeasuresDomain from './AllMeasuresDomain'; import { getLeakPeriodLabel } from '../../../helpers/periods'; -export default class AllMeasures extends React.Component { - render() { - const { component, domains, periods } = this.props; - const leakPeriodLabel = getLeakPeriodLabel(periods); +export default function AllMeasures(props) { + const { component, domains, periods } = props; + const leakPeriodLabel = getLeakPeriodLabel(periods); - return ( - <ul className="measures-domains"> - {domains.map(domain => ( - <AllMeasuresDomain - key={domain.name} - domain={domain} - component={component} - leakPeriodLabel={leakPeriodLabel} - /> - ))} - </ul> - ); - } + return ( + <ul className="measures-domains"> + {domains.map(domain => ( + <AllMeasuresDomain + key={domain.name} + domain={domain} + component={component} + leakPeriodLabel={leakPeriodLabel} + /> + ))} + </ul> + ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js index be68ff12f75..a4512876a18 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js +++ b/server/sonar-web/src/main/js/apps/component-measures/home/AllMeasuresDomain.js @@ -21,23 +21,21 @@ import React from 'react'; import HomeMeasuresList from './HomeMeasuresList'; import { getLocalizedMetricDomain } from '../../../helpers/l10n'; -export default class AllMeasuresDomain extends React.Component { - render() { - const { domain, component, displayHeader } = this.props; +export default function AllMeasuresDomain(props) { + const { domain, component, displayHeader } = props; - return ( - <li> - {displayHeader && - <header className="page-header"> - <h3 className="page-title"> - {getLocalizedMetricDomain(domain.name)} - </h3> - </header>} + return ( + <li> + {displayHeader && + <header className="page-header"> + <h3 className="page-title"> + {getLocalizedMetricDomain(domain.name)} + </h3> + </header>} - <HomeMeasuresList domain={domain} component={component} /> - </li> - ); - } + <HomeMeasuresList domain={domain} component={component} /> + </li> + ); } AllMeasuresDomain.defaultProps = { diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js b/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js index ce868f213f3..22343bc704e 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js +++ b/server/sonar-web/src/main/js/apps/component-measures/home/DomainMeasures.js @@ -22,18 +22,16 @@ import HomeMeasuresList from './HomeMeasuresList'; import MeasureBubbleChartContainer from '../components/bubbleChart/MeasureBubbleChartContainer'; import { hasBubbleChart } from '../utils'; -export default class DomainMeasures extends React.Component { - render() { - const { component, domains } = this.props; - const { domainName } = this.props.params; - const domain = domains.find(d => d.name === domainName); +export default function DomainMeasures(props) { + const { component, domains } = props; + const { domainName } = props.params; + const domain = domains.find(d => d.name === domainName); - return ( - <section id="component-measures-domain"> - <HomeMeasuresList domain={domain} component={component} /> + return ( + <section id="component-measures-domain"> + <HomeMeasuresList domain={domain} component={component} /> - {hasBubbleChart(domainName) && <MeasureBubbleChartContainer domainName={domainName} />} - </section> - ); - } + {hasBubbleChart(domainName) && <MeasureBubbleChartContainer domainName={domainName} />} + </section> + ); } diff --git a/server/sonar-web/src/main/js/apps/component-measures/home/Home.js b/server/sonar-web/src/main/js/apps/component-measures/home/Home.js index 14de2b1a12b..14cbdcdab61 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/home/Home.js +++ b/server/sonar-web/src/main/js/apps/component-measures/home/Home.js @@ -23,7 +23,7 @@ import LeakPeriodLegend from '../components/LeakPeriodLegend'; import { getLeakPeriod } from '../../../helpers/periods'; import { translate, getLocalizedMetricDomain } from '../../../helpers/l10n'; -export default class Home extends React.Component { +export default class Home extends React.PureComponent { componentDidMount() { document.querySelector('html').classList.add('dashboard-page'); this.props.onDisplay(); diff --git a/server/sonar-web/src/main/js/apps/component/components/App.js b/server/sonar-web/src/main/js/apps/component/components/App.js index 8771c039178..96bf963b4a4 100644 --- a/server/sonar-web/src/main/js/apps/component/components/App.js +++ b/server/sonar-web/src/main/js/apps/component/components/App.js @@ -21,7 +21,7 @@ import React from 'react'; import SourceViewer from '../../../components/SourceViewer/SourceViewer'; -export default class App extends React.Component { +export default class App extends React.PureComponent { props: { location: { query: { diff --git a/server/sonar-web/src/main/js/apps/custom-measures/components/CustomMeasuresAppContainer.js b/server/sonar-web/src/main/js/apps/custom-measures/components/CustomMeasuresAppContainer.js index f632095516c..3ce24f3779d 100644 --- a/server/sonar-web/src/main/js/apps/custom-measures/components/CustomMeasuresAppContainer.js +++ b/server/sonar-web/src/main/js/apps/custom-measures/components/CustomMeasuresAppContainer.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import init from '../init'; import { getComponent } from '../../../store/rootReducer'; -class CustomMeasuresAppContainer extends React.Component { +class CustomMeasuresAppContainer extends React.PureComponent { componentDidMount() { init(this.refs.container, this.props.component); } diff --git a/server/sonar-web/src/main/js/apps/groups/components/GroupsAppContainer.js b/server/sonar-web/src/main/js/apps/groups/components/GroupsAppContainer.js index 6b2f868851c..acd77e833cb 100644 --- a/server/sonar-web/src/main/js/apps/groups/components/GroupsAppContainer.js +++ b/server/sonar-web/src/main/js/apps/groups/components/GroupsAppContainer.js @@ -20,7 +20,7 @@ import React from 'react'; import init from '../init'; -export default class GroupsAppContainer extends React.Component { +export default class GroupsAppContainer extends React.PureComponent { componentDidMount() { init(this.refs.container); } diff --git a/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js b/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js index a8f6441b1fd..51fad9f386b 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js +++ b/server/sonar-web/src/main/js/apps/issues/components/MyIssuesFilter.js @@ -27,7 +27,7 @@ type Props = {| onMyIssuesChange: (boolean) => void |}; -export default class MyIssuesFilter extends React.Component { +export default class MyIssuesFilter extends React.PureComponent { props: Props; handleClick = (myIssues: boolean) => diff --git a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js index 262c3ad8699..d1b1d6cfdd8 100644 --- a/server/sonar-web/src/main/js/apps/issues/components/PageActions.js +++ b/server/sonar-web/src/main/js/apps/issues/components/PageActions.js @@ -31,7 +31,7 @@ type Props = {| selectedIndex: ?number |}; -export default class PageActions extends React.Component { +export default class PageActions extends React.PureComponent { props: Props; renderShortcuts() { diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetBox.js b/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetBox.js index 358f6ee3a19..9f0c6cf98ee 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetBox.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetBox.js @@ -25,10 +25,10 @@ type Props = {| property: string |}; -const FacetBox = (props: Props) => ( - <div className="search-navigator-facet-box" data-property={props.property}> - {props.children} - </div> -); - -export default FacetBox; +export default function FacetBox(props: Props) { + return ( + <div className="search-navigator-facet-box" data-property={props.property}> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetItemsList.js b/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetItemsList.js index 4a203f0c071..5d36d9934e3 100644 --- a/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetItemsList.js +++ b/server/sonar-web/src/main/js/apps/issues/sidebar/components/FacetItemsList.js @@ -24,10 +24,10 @@ type Props = {| children?: Array<React.Element<*>> |}; -const FacetItemsList = (props: Props) => ( - <div className="search-navigator-facet-list"> - {props.children} - </div> -); - -export default FacetItemsList; +export default function FacetItemsList(props: Props) { + return ( + <div className="search-navigator-facet-list"> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js b/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js index e7c94acd956..bf151b827ac 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js +++ b/server/sonar-web/src/main/js/apps/maintenance/components/MaintenanceAppContainer.js @@ -20,7 +20,7 @@ import React from 'react'; import init from '../init'; -export default class MaintenanceAppContainer extends React.Component { +export default class MaintenanceAppContainer extends React.PureComponent { componentDidMount() { init(this.refs.container, false); } diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js b/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js index d29ec360bdd..c28492700ce 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js +++ b/server/sonar-web/src/main/js/apps/maintenance/components/SetupAppContainer.js @@ -20,7 +20,7 @@ import React from 'react'; import init from '../init'; -export default class SetupAppContainer extends React.Component { +export default class SetupAppContainer extends React.PureComponent { componentDidMount() { init(this.refs.container, true); } diff --git a/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js b/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js index d150c1997d6..6193721adef 100644 --- a/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js +++ b/server/sonar-web/src/main/js/apps/metrics/components/MetricsAppContainer.js @@ -20,7 +20,7 @@ import React from 'react'; import init from '../init'; -export default class MetricsAppContainer extends React.Component { +export default class MetricsAppContainer extends React.PureComponent { componentDidMount() { init(this.refs.container); } diff --git a/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js b/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js index 1a8f6999f77..b0c175f8b82 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/MembersPageHeader.js @@ -23,7 +23,7 @@ import React from 'react'; type Props = { loading: boolean, total?: number, - children?: {} + children?: React.Element<*> }; export default class MembersPageHeader extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js index 5fe8271e694..19fd1852e9a 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationAdmin.js @@ -23,9 +23,9 @@ import { connect } from 'react-redux'; import { getOrganizationByKey } from '../../../store/rootReducer'; import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization'; -class OrganizationAdmin extends React.Component { +class OrganizationAdmin extends React.PureComponent { props: { - children: Object, + children?: React.Element<*>, organization: { canAdmin: boolean } }; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js index ece826b126b..9e8af35cf0f 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.js @@ -27,7 +27,7 @@ import { translate } from '../../../helpers/l10n'; import { getOrganizationByKey } from '../../../store/rootReducer'; import { deleteOrganization } from '../actions'; -class OrganizationDelete extends React.Component { +class OrganizationDelete extends React.PureComponent { props: { organization: { key: string, diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js index a7052a459ed..d5d9870c116 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationEdit.js @@ -31,7 +31,7 @@ type Props = { updateOrganization: (string, Object) => Promise<*> }; -class OrganizationEdit extends React.Component { +class OrganizationEdit extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js index 1fba6f72119..53654f58b01 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationFavoriteProjects.js @@ -26,9 +26,9 @@ import { getOrganizationByKey } from '../../../store/rootReducer'; import { updateOrganization } from '../actions'; import { translate } from '../../../helpers/l10n'; -class OrganizationFavoriteProjects extends React.Component { +class OrganizationFavoriteProjects extends React.PureComponent { props: { - children: Object, + children?: React.Element<*>, location: Object, organization: { key: string diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js index e760b783bad..521d40d9184 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationGroups.js @@ -24,7 +24,7 @@ import init from '../../groups/init'; import { getOrganizationByKey } from '../../../store/rootReducer'; import type { Organization } from '../../../store/organizations/duck'; -class OrganizationGroups extends React.Component { +class OrganizationGroups extends React.PureComponent { props: { organization: Organization }; diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js index 709801728d3..2175d7dbc6a 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.js @@ -30,11 +30,11 @@ type OwnProps = { params: { organizationKey: string } }; -class OrganizationPage extends React.Component { +class OrganizationPage extends React.PureComponent { mounted: boolean; props: { - children: Object, + children?: React.Element<*>, location: Object, organization: null | Organization, params: { organizationKey: string }, diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js index e5df0d8557b..f00469c5ebd 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissionTemplates.js @@ -24,15 +24,13 @@ import AppContainer from '../../permission-templates/components/AppContainer'; import { getOrganizationByKey } from '../../../store/rootReducer'; import type { Organization } from '../../../store/organizations/duck'; -class OrganizationPermissionTemplates extends React.Component { - props: { - location: {}, - organization: Organization - }; +type Props = { + location: {}, + organization: Organization +}; - render() { - return <AppContainer location={this.props.location} organization={this.props.organization} />; - } +function OrganizationPermissionTemplates(props: Props) { + return <AppContainer location={props.location} organization={props.organization} />; } const mapStateToProps = (state, ownProps) => ({ diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js index 79fb720a1e0..e78bad3db9b 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationPermissions.js @@ -24,14 +24,12 @@ import GlobalPermissionsApp from '../../permissions/global/components/App'; import { getOrganizationByKey } from '../../../store/rootReducer'; import type { Organization } from '../../../store/organizations/duck'; -class OrganizationPermissions extends React.Component { - props: { - organization: Organization - }; +type Props = { + organization: Organization +}; - render() { - return <GlobalPermissionsApp organization={this.props.organization} />; - } +function OrganizationPermissions(props: Props) { + return <GlobalPermissionsApp organization={props.organization} />; } const mapStateToProps = (state, ownProps) => ({ diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js index 67dbdf8bcd4..99b789f1af4 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjects.js @@ -26,9 +26,9 @@ import { getOrganizationByKey } from '../../../store/rootReducer'; import { updateOrganization } from '../actions'; import { translate } from '../../../helpers/l10n'; -class OrganizationProjects extends React.Component { +class OrganizationProjects extends React.PureComponent { props: { - children: Object, + children?: React.Element<*>, location: Object, organization: { key: string diff --git a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js index 5a16f004c63..ef06e033d86 100644 --- a/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js +++ b/server/sonar-web/src/main/js/apps/organizations/components/OrganizationProjectsManagement.js @@ -24,14 +24,12 @@ import AppContainer from '../../projects-admin/AppContainer'; import { getOrganizationByKey } from '../../../store/rootReducer'; import type { Organization } from '../../../store/organizations/duck'; -class OrganizationProjectsManagement extends React.Component { - props: { - organization: Organization - }; +type Props = { + organization: Organization +}; - render() { - return <AppContainer organization={this.props.organization} />; - } +function OrganizationProjectsManagement(props: Props) { + return <AppContainer organization={props.organization} />; } const mapStateToProps = (state, ownProps) => ({ diff --git a/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js b/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js index a171c1c7485..5936b86e244 100644 --- a/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js +++ b/server/sonar-web/src/main/js/apps/organizations/forSingleOrganization.js @@ -24,7 +24,7 @@ import { withRouter } from 'react-router'; import { areThereCustomOrganizations } from '../../store/rootReducer'; const forSingleOrganization = (ComposedComponent: Object) => { - class X extends React.Component { + class X extends React.PureComponent { static displayName = `forSingleOrganization(${ComposedComponent.displayName})}`; render() { diff --git a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js index 3fc479d5b54..3c0494351c2 100644 --- a/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js +++ b/server/sonar-web/src/main/js/apps/organizations/navigation/OrganizationNavigation.js @@ -33,7 +33,7 @@ const ADMIN_PATHS = [ 'projects_management' ]; -export default class OrganizationNavigation extends React.Component { +export default class OrganizationNavigation extends React.PureComponent { props: { location: { pathname: string }, organization: Organization diff --git a/server/sonar-web/src/main/js/apps/overview/components/App.js b/server/sonar-web/src/main/js/apps/overview/components/App.js index 517569d47f9..d1c73df1555 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/App.js +++ b/server/sonar-web/src/main/js/apps/overview/components/App.js @@ -19,7 +19,6 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { withRouter } from 'react-router'; import OverviewApp from './OverviewApp'; import EmptyOverview from './EmptyOverview'; @@ -35,7 +34,7 @@ type Props = { router: Object }; -class App extends React.Component { +class App extends React.PureComponent { props: Props; state: Object; @@ -48,10 +47,6 @@ class App extends React.Component { } } - shouldComponentUpdate(nextProps: Props) { - return shallowCompare(this, nextProps); - } - render() { const { component } = this.props; diff --git a/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js b/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js index c8c51930f06..5f71c846631 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js +++ b/server/sonar-web/src/main/js/apps/overview/components/LeakPeriodLegend.js @@ -58,29 +58,25 @@ type Period = | PreviousAnalysisPeriod | PreviousVersionPeriod; -export default class LeakPeriodLegend extends React.Component { - props: { period: Period }; +export default function LeakPeriodLegend(props: { period: Period }) { + const { period } = props; + const leakPeriodLabel = getPeriodLabel(period); + const leakPeriodDate = getPeriodDate(period); - render() { - const { period } = this.props; - const leakPeriodLabel = getPeriodLabel(period); - const leakPeriodDate = getPeriodDate(period); + const momentDate = moment(leakPeriodDate); + const fromNow = momentDate.fromNow(); + const note = ['date', 'days'].includes(period.mode) + ? translateWithParameters('overview.last_analysis_x', fromNow) + : translateWithParameters('overview.started_x', fromNow); + const tooltip = ['date', 'days'].includes(period.mode) + ? translateWithParameters('overview.last_analysis_on_x', momentDate.format('LL')) + : translateWithParameters('overview.started_on_x', momentDate.format('LL')); - const momentDate = moment(leakPeriodDate); - const fromNow = momentDate.fromNow(); - const note = ['date', 'days'].includes(period.mode) - ? translateWithParameters('overview.last_analysis_x', fromNow) - : translateWithParameters('overview.started_x', fromNow); - const tooltip = ['date', 'days'].includes(period.mode) - ? translateWithParameters('overview.last_analysis_on_x', momentDate.format('LL')) - : translateWithParameters('overview.started_on_x', momentDate.format('LL')); - - return ( - <div className="overview-legend" title={tooltip} data-toggle="tooltip"> - {translateWithParameters('overview.leak_period_x', leakPeriodLabel)} - <br /> - <span className="note">{note}</span> - </div> - ); - } + return ( + <div className="overview-legend" title={tooltip} data-toggle="tooltip"> + {translateWithParameters('overview.leak_period_x', leakPeriodLabel)} + <br /> + <span className="note">{note}</span> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js index 50ff0bffd7c..9075797656f 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js +++ b/server/sonar-web/src/main/js/apps/overview/components/OverviewApp.js @@ -19,7 +19,6 @@ */ import React from 'react'; import moment from 'moment'; -import shallowCompare from 'react-addons-shallow-compare'; import QualityGate from '../qualityGate/QualityGate'; import BugsAndVulnerabilities from '../main/BugsAndVulnerabilities'; import CodeSmells from '../main/CodeSmells'; @@ -78,7 +77,7 @@ const METRICS = [ const HISTORY_METRICS_LIST = ['sqale_index', 'duplicated_lines_density', 'ncloc', 'coverage']; -export default class OverviewApp extends React.Component { +export default class OverviewApp extends React.PureComponent { static propTypes = { component: ComponentType.isRequired }; @@ -93,10 +92,6 @@ export default class OverviewApp extends React.Component { this.loadMeasures(this.props.component.key).then(() => this.loadHistory(this.props.component)); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate(prevProps) { if (this.props.component.key !== prevProps.component.key) { this.loadMeasures(this.props.component.key).then(() => diff --git a/server/sonar-web/src/main/js/apps/overview/components/Timeline.js b/server/sonar-web/src/main/js/apps/overview/components/Timeline.js index f2fd61c218a..4edc52bff06 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/Timeline.js +++ b/server/sonar-web/src/main/js/apps/overview/components/Timeline.js @@ -18,23 +18,18 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { max } from 'd3-array'; import { LineChart } from '../../../components/charts/line-chart'; const HEIGHT = 80; -export default class Timeline extends React.Component { +export default class Timeline extends React.PureComponent { static propTypes = { history: React.PropTypes.arrayOf(React.PropTypes.object).isRequired, before: React.PropTypes.object, after: React.PropTypes.object }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - filterSnapshots() { const { history, before, after } = this.props; diff --git a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js index a152ea9b021..cd4ef7c68e4 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js +++ b/server/sonar-web/src/main/js/apps/overview/events/AnalysesList.js @@ -33,7 +33,7 @@ type Props = { fetchRecentProjectActivity: (project: string) => Promise<*> }; -class AnalysesList extends React.Component { +class AnalysesList extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/overview/events/Analysis.js b/server/sonar-web/src/main/js/apps/overview/events/Analysis.js index f01c4aa9ae6..582b64b64a4 100644 --- a/server/sonar-web/src/main/js/apps/overview/events/Analysis.js +++ b/server/sonar-web/src/main/js/apps/overview/events/Analysis.js @@ -24,28 +24,22 @@ import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { translate } from '../../../helpers/l10n'; import type { Analysis as AnalysisType } from '../../../store/projectActivity/duck'; -export default class Analysis extends React.Component { - props: { - analysis: AnalysisType - }; +export default function Analysis(props: { analysis: AnalysisType }) { + const { analysis } = props; - render() { - const { analysis } = this.props; + return ( + <TooltipsContainer> + <li className="overview-analysis"> + <div className="small little-spacer-bottom"> + <strong> + <FormattedDate date={analysis.date} format="LL" /> + </strong> + </div> - return ( - <TooltipsContainer> - <li className="overview-analysis"> - <div className="small little-spacer-bottom"> - <strong> - <FormattedDate date={analysis.date} format="LL" /> - </strong> - </div> - - {analysis.events.length > 0 - ? <Events events={analysis.events} canAdmin={false} /> - : <span className="note">{translate('project_activity.project_analyzed')}</span>} - </li> - </TooltipsContainer> - ); - } + {analysis.events.length > 0 + ? <Events events={analysis.events} canAdmin={false} /> + : <span className="note">{translate('project_activity.project_analyzed')}</span>} + </li> + </TooltipsContainer> + ); } diff --git a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js index aaeaececee4..b0fa2c9ee06 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js +++ b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.js @@ -26,7 +26,7 @@ import { translate } from '../../../helpers/l10n'; import BugIcon from '../../../components/ui/BugIcon'; import VulnerabilityIcon from '../../../components/ui/VulnerabilityIcon'; -class BugsAndVulnerabilities extends React.Component { +class BugsAndVulnerabilities extends React.PureComponent { renderHeader() { const { component } = this.props; const bugsDomainUrl = { diff --git a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js index 0010c70c199..1b7f13b95e7 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js +++ b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.js @@ -27,7 +27,7 @@ import { formatMeasure, isDiffMetric } from '../../../helpers/measures'; import { getComponentIssuesUrl } from '../../../helpers/urls'; import CodeSmellIcon from '../../../components/ui/CodeSmellIcon'; -class CodeSmells extends React.Component { +class CodeSmells extends React.PureComponent { renderHeader() { return this.props.renderHeader('Maintainability', translate('metric.code_smells.name')); } 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 73804604e7d..c9aa1f9a576 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 @@ -25,7 +25,7 @@ import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import CoverageRating from '../../../components/ui/CoverageRating'; -class Coverage extends React.Component { +class Coverage extends React.PureComponent { getCoverage() { const { measures } = this.props; const { value } = measures.find(measure => measure.metric.key === 'coverage'); 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 9c5980e6260..1a090d6fdb9 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 @@ -25,7 +25,7 @@ import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import DuplicationsRating from '../../../components/ui/DuplicationsRating'; -class Duplications extends React.Component { +class Duplications extends React.PureComponent { renderHeader() { return this.props.renderHeader('Duplications', translate('overview.domain.duplications')); } diff --git a/server/sonar-web/src/main/js/apps/overview/main/enhance.js b/server/sonar-web/src/main/js/apps/overview/main/enhance.js index 4b71fb7f615..1b21260cfeb 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/enhance.js +++ b/server/sonar-web/src/main/js/apps/overview/main/enhance.js @@ -20,7 +20,6 @@ import React from 'react'; import { Link } from 'react-router'; import moment from 'moment'; -import shallowCompare from 'react-addons-shallow-compare'; import { DrilldownLink } from '../../../components/shared/drilldown-link'; import Rating from './../../../components/ui/Rating'; import Timeline from '../components/Timeline'; @@ -37,13 +36,9 @@ import { getPeriodDate } from '../../../helpers/periods'; import { getComponentIssuesUrl } from '../../../helpers/urls'; export default function enhance(ComposedComponent) { - return class extends React.Component { + return class extends React.PureComponent { static displayName = `enhance(${ComposedComponent.displayName})}`; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - getValue(measure) { const { leakPeriod } = this.props; diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js index 731bb5f9d1f..c777e17f7ca 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.js @@ -33,7 +33,7 @@ type State = {| expanded: boolean |}; -export default class MetaLink extends React.Component { +export default class MetaLink extends React.PureComponent { props: { link: Link }; diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.js index 3d6711101a5..c88e57977a6 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaLinks.js @@ -22,7 +22,7 @@ import MetaLink from './MetaLink'; import { getProjectLinks } from '../../../api/projectLinks'; import { orderLinks } from '../../project-admin/links/utils'; -export default class MetaLinks extends React.Component { +export default class MetaLinks extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js index 13484c3ca0a..5ee7797c2b2 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaQualityProfiles.js @@ -27,7 +27,7 @@ import { getQualityProfileUrl } from '../../../helpers/urls'; import { searchRules } from '../../../api/rules'; import { getLanguages } from '../../../store/rootReducer'; -class MetaQualityProfiles extends React.Component { +class MetaQualityProfiles extends React.PureComponent { mounted: boolean; props: { diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js index 41659f64124..4028e1a6a8a 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.js @@ -24,7 +24,7 @@ import { formatMeasure } from '../../../helpers/measures'; import { getMetricName } from '../helpers/metrics'; import SizeRating from '../../../components/ui/SizeRating'; -export default class MetaSize extends React.Component { +export default class MetaSize extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, measures: React.PropTypes.array.isRequired diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js index 8d021bdc5fc..8fec8fdfba6 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js @@ -29,7 +29,7 @@ import { getPeriod, getPeriodDate } from '../../../helpers/periods'; import { getComponentIssuesUrl } from '../../../helpers/urls'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; -export default class QualityGateCondition extends React.Component { +export default class QualityGateCondition extends React.PureComponent { props: { component: { key: string }, periods: Array<{ @@ -93,7 +93,7 @@ export default class QualityGateCondition extends React.Component { : this.getUrlForBugsOrVulnerabilities(type, sinceLeakPeriod); } - wrapWithLink(children: Object) { + wrapWithLink(children: React.Element<*>) { const { component, periods, condition } = this.props; const period = getPeriod(periods, condition.period); diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js index 9011b370cd9..eba9b2a268f 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { sortBy } from 'lodash'; import QualityGateCondition from './QualityGateCondition'; import { ComponentType, ConditionsListType } from '../propTypes'; @@ -34,7 +33,7 @@ function enhanceConditions(conditions, measures) { }); } -export default class QualityGateConditions extends React.Component { +export default class QualityGateConditions extends React.PureComponent { static propTypes = { component: ComponentType.isRequired, conditions: ConditionsListType.isRequired @@ -49,10 +48,6 @@ export default class QualityGateConditions extends React.Component { this.loadFailedMeasures(); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate(prevProps) { if ( prevProps.conditions !== this.props.conditions || prevProps.component !== this.props.component diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js b/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js index 9fd4ffc417e..5b837056713 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/ActionsCell.js @@ -28,7 +28,7 @@ import DeleteView from '../views/DeleteView'; import { translate } from '../../../helpers/l10n'; import { setDefaultPermissionTemplate } from '../../../api/permissions'; -export default class ActionsCell extends React.Component { +export default class ActionsCell extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, permissionTemplate: PermissionTemplateType.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/App.js b/server/sonar-web/src/main/js/apps/permission-templates/components/App.js index 911468cc821..270137e277f 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/App.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/App.js @@ -24,7 +24,7 @@ import { getPermissionTemplates } from '../../../api/permissions'; import { sortPermissions, mergePermissionsToTemplates, mergeDefaultsToTemplates } from '../utils'; import '../../permissions/styles.css'; -export default class App extends React.Component { +export default class App extends React.PureComponent { static propTypes = { location: React.PropTypes.object.isRequired, organization: React.PropTypes.object, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Defaults.js b/server/sonar-web/src/main/js/apps/permission-templates/components/Defaults.js index a3b3b0675bf..0a8e7782061 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Defaults.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Defaults.js @@ -22,7 +22,7 @@ import { sortBy } from 'lodash'; import { translate } from '../../../helpers/l10n'; import { PermissionTemplateType } from '../propTypes'; -export default class Defaults extends React.Component { +export default class Defaults extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, permissionTemplate: PermissionTemplateType.isRequired diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Header.js b/server/sonar-web/src/main/js/apps/permission-templates/components/Header.js index 4a1d348bf0e..17eb68d06c3 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Header.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Header.js @@ -22,7 +22,7 @@ import CreateView from '../views/CreateView'; import { translate } from '../../../helpers/l10n'; import { CallbackType } from '../propTypes'; -export default class Header extends React.Component { +export default class Header extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, ready: React.PropTypes.bool.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Home.js b/server/sonar-web/src/main/js/apps/permission-templates/components/Home.js index aa23792c19f..b649d54728e 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Home.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Home.js @@ -24,7 +24,7 @@ import List from './List'; import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin'; import { translate } from '../../../helpers/l10n'; -export default class Home extends React.Component { +export default class Home extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, topQualifiers: React.PropTypes.array.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/List.js b/server/sonar-web/src/main/js/apps/permission-templates/components/List.js index dbee8b797c3..84a834f6689 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/List.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/List.js @@ -22,7 +22,7 @@ import ListHeader from './ListHeader'; import ListItem from './ListItem'; import { PermissionTemplateType, CallbackType } from '../propTypes'; -export default class List extends React.Component { +export default class List extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, permissionTemplates: React.PropTypes.arrayOf(PermissionTemplateType).isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js b/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js index 29a1cf51d33..19181043a58 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/ListHeader.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default class ListHeader extends React.Component { +export default class ListHeader extends React.PureComponent { static propTypes = { permissions: React.PropTypes.array.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/ListItem.js b/server/sonar-web/src/main/js/apps/permission-templates/components/ListItem.js index 15c586572a7..9d60a805bf1 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/ListItem.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/ListItem.js @@ -25,7 +25,7 @@ import UsersView from '../views/UsersView'; import GroupsView from '../views/GroupsView'; import { PermissionTemplateType, CallbackType } from '../propTypes'; -export default class ListItem extends React.Component { +export default class ListItem extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, permissionTemplate: PermissionTemplateType.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/NameCell.js b/server/sonar-web/src/main/js/apps/permission-templates/components/NameCell.js index 73c0f217530..0cac1b1bac1 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/NameCell.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/NameCell.js @@ -22,7 +22,7 @@ import { Link } from 'react-router'; import Defaults from './Defaults'; import { PermissionTemplateType } from '../propTypes'; -export default class NameCell extends React.Component { +export default class NameCell extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, permissionTemplate: PermissionTemplateType.isRequired diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/PermissionCell.js b/server/sonar-web/src/main/js/apps/permission-templates/components/PermissionCell.js index 8ff09842585..326b2f7d68b 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/PermissionCell.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/PermissionCell.js @@ -21,7 +21,7 @@ import React from 'react'; import { PermissionType } from '../propTypes'; import { translate } from '../../../helpers/l10n'; -export default class PermissionCell extends React.Component { +export default class PermissionCell extends React.PureComponent { static propTypes = { permission: PermissionType.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/Template.js b/server/sonar-web/src/main/js/apps/permission-templates/components/Template.js index d92e0a069a0..e9a566c8af7 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/Template.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/Template.js @@ -29,7 +29,7 @@ import * as api from '../../../api/permissions'; import { translate } from '../../../helpers/l10n'; import withStore from '../../../store/utils/withStore'; -class Template extends React.Component { +class Template extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, template: React.PropTypes.object.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateDetails.js b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateDetails.js index a5cc6f61e5c..ef4b83905ae 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateDetails.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateDetails.js @@ -20,7 +20,7 @@ import React from 'react'; import Defaults from './Defaults'; -export default class TemplateDetails extends React.Component { +export default class TemplateDetails extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, template: React.PropTypes.object.isRequired diff --git a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.js b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.js index 8a2d07fb13d..e7a81092fa5 100644 --- a/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.js +++ b/server/sonar-web/src/main/js/apps/permission-templates/components/TemplateHeader.js @@ -22,7 +22,7 @@ import { Link } from 'react-router'; import ActionsCell from './ActionsCell'; import { translate } from '../../../helpers/l10n'; -export default class TemplateHeader extends React.Component { +export default class TemplateHeader extends React.PureComponent { static propTypes = { organization: React.PropTypes.object, template: React.PropTypes.object.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js index bad51b688b5..8aac3051ea2 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/AllHoldersList.js @@ -45,7 +45,7 @@ const PERMISSIONS_ORDER = ['admin', 'profileadmin', 'gateadmin', 'scan', 'provis const PERMISSIONS_FOR_CUSTOM_ORG = ['admin', 'scan', 'provisioning']; -class AllHoldersList extends React.Component { +class AllHoldersList extends React.PureComponent { componentDidMount() { this.props.loadHolders(); } diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js index f0ee0912120..d7a02f5c987 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/App.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/App.js @@ -26,18 +26,12 @@ import '../../styles.css'; // TODO helmet -export default class App extends React.Component { - props: { - organization?: {} - }; - - render() { - return ( - <div className="page page-limited"> - <PageHeader organization={this.props.organization} /> - <PageError /> - <AllHoldersList organization={this.props.organization} /> - </div> - ); - } +export default function App(props: { organization?: {} }) { + return ( + <div className="page page-limited"> + <PageHeader organization={props.organization} /> + <PageError /> + <AllHoldersList organization={props.organization} /> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js b/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js index 4475144a332..a75573a643a 100644 --- a/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/permissions/global/components/PageHeader.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import { translate } from '../../../../helpers/l10n'; import { isPermissionsAppLoading } from '../../../../store/rootReducer'; -class PageHeader extends React.Component { +class PageHeader extends React.PureComponent { props: { loading?: boolean, organization?: {} diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js b/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js index 8b4ccc364df..8be316b38bc 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/AllHoldersList.js @@ -42,7 +42,7 @@ import { getPermissionsAppSelectedPermission } from '../../../../store/rootReducer'; -class AllHoldersList extends React.Component { +class AllHoldersList extends React.PureComponent { static propTypes = { project: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/App.js b/server/sonar-web/src/main/js/apps/permissions/project/components/App.js index e43ab53f8b1..c12071e4b67 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/App.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/App.js @@ -27,7 +27,7 @@ import '../../styles.css'; // TODO helmet -class App extends React.Component { +class App extends React.PureComponent { static propTypes = { component: React.PropTypes.object }; diff --git a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js index 6e8c970e55b..36ce09f2218 100644 --- a/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/permissions/project/components/PageHeader.js @@ -24,7 +24,7 @@ import ApplyTemplateView from '../views/ApplyTemplateView'; import { loadHolders } from '../store/actions'; import { isPermissionsAppLoading } from '../../../../store/rootReducer'; -class PageHeader extends React.Component { +class PageHeader extends React.PureComponent { static propTypes = { project: React.PropTypes.object.isRequired, loadHolders: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js index c9a188dcf33..fa051cd0b4c 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/GroupHolder.js @@ -18,10 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import GroupIcon from './GroupIcon'; -export default class GroupHolder extends React.Component { +export default class GroupHolder extends React.PureComponent { static propTypes = { group: React.PropTypes.object.isRequired, permissions: React.PropTypes.array.isRequired, @@ -30,10 +29,6 @@ export default class GroupHolder extends React.Component { onToggle: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleClick(permission, e) { e.preventDefault(); e.target.blur(); diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js index f71911a5638..68ff9ef7635 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/HoldersList.js @@ -23,7 +23,7 @@ import GroupHolder from './GroupHolder'; import { TooltipsContainer } from '../../../../components/mixins/tooltips-mixin'; import { translate } from '../../../../helpers/l10n'; -export default class HoldersList extends React.Component { +export default class HoldersList extends React.PureComponent { static propTypes = { permissions: React.PropTypes.array.isRequired, users: React.PropTypes.array.isRequired, diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js index 18ce601f8c6..da53c30b9ef 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/PageError.js @@ -21,7 +21,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { getPermissionsAppError } from '../../../../store/rootReducer'; -class PageError extends React.Component { +class PageError extends React.PureComponent { static propTypes = { message: React.PropTypes.string }; diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js index 464cd508eed..9d370f93081 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/SearchForm.js @@ -21,7 +21,7 @@ import React from 'react'; import RadioToggle from '../../../../components/controls/RadioToggle'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; -export default class SearchForm extends React.Component { +export default class SearchForm extends React.PureComponent { static propTypes = { query: React.PropTypes.string, filter: React.PropTypes.oneOf(['all', 'users', 'groups']), diff --git a/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js b/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js index df72afc0bd5..18a8a125aa8 100644 --- a/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js +++ b/server/sonar-web/src/main/js/apps/permissions/shared/components/UserHolder.js @@ -18,11 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import Avatar from '../../../../components/ui/Avatar'; import { translate } from '../../../../helpers/l10n'; -export default class UserHolder extends React.Component { +export default class UserHolder extends React.PureComponent { static propTypes = { user: React.PropTypes.object.isRequired, permissions: React.PropTypes.array.isRequired, @@ -31,10 +30,6 @@ export default class UserHolder extends React.Component { onToggle: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleClick(permission, e) { e.preventDefault(); e.target.blur(); diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js index 76c74ed02c8..6ef724f1b77 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js +++ b/server/sonar-web/src/main/js/apps/project-admin/deletion/Deletion.js @@ -23,7 +23,7 @@ import Header from './Header'; import Form from './Form'; import { getComponent } from '../../../store/rootReducer'; -class Deletion extends React.Component { +class Deletion extends React.PureComponent { static propTypes = { component: React.PropTypes.object }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js index 77a6faf9591..1a848accaee 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js +++ b/server/sonar-web/src/main/js/apps/project-admin/deletion/Form.js @@ -21,7 +21,7 @@ import React from 'react'; import ConfirmationModal from './ConfirmationModal'; import { translate } from '../../../helpers/l10n'; -export default class Form extends React.Component { +export default class Form extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js b/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js index 68622ed0e78..d236654ed98 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/deletion/Header.js @@ -21,25 +21,19 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class Header extends React.Component { - props: { - component: { qualifier: string } - }; +export default function Header(props: { component: { qualifier: string } }) { + const description = ['VW', 'SVW'].includes(props.component.qualifier) + ? translate('portfolio_deletion.page.description') + : translate('project_deletion.page.description'); - render() { - const description = ['VW', 'SVW'].includes(this.props.component.qualifier) - ? translate('portfolio_deletion.page.description') - : translate('project_deletion.page.description'); - - return ( - <header className="page-header"> - <h1 className="page-title"> - {translate('deletion.page')} - </h1> - <div className="page-description"> - {description} - </div> - </header> - ); - } + return ( + <header className="page-header"> + <h1 className="page-title"> + {translate('deletion.page')} + </h1> + <div className="page-description"> + {description} + </div> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js index 5a8e3755950..34f9228be1e 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdate.js @@ -32,7 +32,7 @@ import { import { reloadUpdateKeyPage } from './utils'; import RecentHistory from '../../../app/components/nav/component/RecentHistory'; -class BulkUpdate extends React.Component { +class BulkUpdate extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, addGlobalErrorMessage: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateForm.js b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateForm.js index 24938cafc3c..3c58171ebdb 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateForm.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateForm.js @@ -20,7 +20,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class BulkUpdateForm extends React.Component { +export default class BulkUpdateForm extends React.PureComponent { static propTypes = { onSubmit: React.PropTypes.func.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateResults.js b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateResults.js index a23d6307d7d..b7beb6b213e 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateResults.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/BulkUpdateResults.js @@ -21,7 +21,7 @@ import React from 'react'; import { some } from 'lodash'; import { translateWithParameters, translate } from '../../../helpers/l10n'; -export default class BulkUpdateResults extends React.Component { +export default class BulkUpdateResults extends React.PureComponent { static propTypes = { results: React.PropTypes.array.isRequired, onConfirm: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js b/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js index bb722731c4f..cc148816e40 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/FineGrainedUpdate.js @@ -21,30 +21,28 @@ import React from 'react'; import UpdateKeyForm from './UpdateKeyForm'; import QualifierIcon from '../../../components/shared/QualifierIcon'; -export default class FineGrainedUpdate extends React.Component { - render() { - const { component, modules } = this.props; - const components = [component, ...modules]; +export default function FineGrainedUpdate(props) { + const { component, modules } = props; + const components = [component, ...modules]; - return ( - <div id="project-key-fine-grained-update"> - <table className="data zebra"> - <tbody> - {components.map(component => ( - <tr key={component.key}> - <td className="width-40"> - <QualifierIcon qualifier={component.qualifier} /> - {' '} - {component.name} - </td> - <td> - <UpdateKeyForm component={component} onKeyChange={this.props.onKeyChange} /> - </td> - </tr> - ))} - </tbody> - </table> - </div> - ); - } + return ( + <div id="project-key-fine-grained-update"> + <table className="data zebra"> + <tbody> + {components.map(component => ( + <tr key={component.key}> + <td className="width-40"> + <QualifierIcon qualifier={component.qualifier} /> + {' '} + {component.name} + </td> + <td> + <UpdateKeyForm component={component} onKeyChange={props.onKeyChange} /> + </td> + </tr> + ))} + </tbody> + </table> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/Header.js b/server/sonar-web/src/main/js/apps/project-admin/key/Header.js index 8b079387c1b..619326823fb 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/Header.js @@ -20,17 +20,15 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class Header extends React.Component { - render() { - return ( - <header className="page-header"> - <h1 className="page-title"> - {translate('update_key.page')} - </h1> - <div className="page-description"> - {translate('update_key.page.description')} - </div> - </header> - ); - } +export default function Header() { + return ( + <header className="page-header"> + <h1 className="page-title"> + {translate('update_key.page')} + </h1> + <div className="page-description"> + {translate('update_key.page.description')} + </div> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/Key.js b/server/sonar-web/src/main/js/apps/project-admin/key/Key.js index 87b2b3bb9fb..9ba721d3308 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/Key.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/Key.js @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { connect } from 'react-redux'; import Header from './Header'; import UpdateForm from './UpdateForm'; @@ -36,7 +35,7 @@ import { reloadUpdateKeyPage } from './utils'; import RecentHistory from '../../../app/components/nav/component/RecentHistory'; import { getProjectAdminProjectModules, getComponent } from '../../../store/rootReducer'; -class Key extends React.Component { +class Key extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, fetchProjectModules: React.PropTypes.func.isRequired, @@ -54,10 +53,6 @@ class Key extends React.Component { this.props.fetchProjectModules(this.props.component.key); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleChangeKey(key, newKey) { return this.props .changeKey(key, newKey) diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js index f81eba6b593..99ec9764f52 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateForm.js @@ -21,7 +21,7 @@ import React from 'react'; import UpdateKeyConfirmation from './views/UpdateKeyConfirmation'; import { translate } from '../../../helpers/l10n'; -export default class UpdateForm extends React.Component { +export default class UpdateForm extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, onKeyChange: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateKeyForm.js b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateKeyForm.js index 847324cec15..bb510a4ca26 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/key/UpdateKeyForm.js +++ b/server/sonar-web/src/main/js/apps/project-admin/key/UpdateKeyForm.js @@ -21,7 +21,7 @@ import React from 'react'; import UpdateKeyConfirmation from './views/UpdateKeyConfirmation'; import { translate } from '../../../helpers/l10n'; -export default class UpdateKeyForm extends React.Component { +export default class UpdateKeyForm extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/links/Header.js b/server/sonar-web/src/main/js/apps/project-admin/links/Header.js index d8df7093718..9173d97c1aa 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/links/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/links/Header.js @@ -21,7 +21,7 @@ import React from 'react'; import CreationModal from './views/CreationModal'; import { translate } from '../../../helpers/l10n'; -export default class Header extends React.Component { +export default class Header extends React.PureComponent { static propTypes = { onCreate: React.PropTypes.func.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/project-admin/links/LinkRow.js b/server/sonar-web/src/main/js/apps/project-admin/links/LinkRow.js index 8ebe995b727..3c32c80fc84 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/links/LinkRow.js +++ b/server/sonar-web/src/main/js/apps/project-admin/links/LinkRow.js @@ -18,21 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { isProvided, isClickable } from './utils'; import { translate } from '../../../helpers/l10n'; import BugTrackerIcon from '../../../components/ui/BugTrackerIcon'; -export default class LinkRow extends React.Component { +export default class LinkRow extends React.PureComponent { static propTypes = { link: React.PropTypes.object.isRequired, onDelete: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleDeleteClick(e) { e.preventDefault(); e.target.blur(); diff --git a/server/sonar-web/src/main/js/apps/project-admin/links/Links.js b/server/sonar-web/src/main/js/apps/project-admin/links/Links.js index 00807d9adad..b8ac2300dc9 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/links/Links.js +++ b/server/sonar-web/src/main/js/apps/project-admin/links/Links.js @@ -18,7 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { connect } from 'react-redux'; import Header from './Header'; import Table from './Table'; @@ -26,7 +25,7 @@ import DeletionModal from './views/DeletionModal'; import { fetchProjectLinks, deleteProjectLink, createProjectLink } from '../store/actions'; import { getProjectAdminProjectLinks, getComponent } from '../../../store/rootReducer'; -class Links extends React.Component { +class Links extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, links: React.PropTypes.array @@ -41,10 +40,6 @@ class Links extends React.Component { this.props.fetchProjectLinks(this.props.component.key); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleCreateLink(name, url) { return this.props.createProjectLink(this.props.component.key, name, url); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/links/Table.js b/server/sonar-web/src/main/js/apps/project-admin/links/Table.js index d71f6709220..8aa1aad70e0 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/links/Table.js +++ b/server/sonar-web/src/main/js/apps/project-admin/links/Table.js @@ -18,21 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import LinkRow from './LinkRow'; import { orderLinks } from './utils'; import { translate } from '../../../helpers/l10n'; -export default class Table extends React.Component { +export default class Table extends React.PureComponent { static propTypes = { links: React.PropTypes.array.isRequired, onDelete: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleDeleteLink(link) { this.props.onDelete(link); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Form.js b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Form.js index 154115c58e0..cbe9b7e9fdc 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Form.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Form.js @@ -19,11 +19,10 @@ */ import React from 'react'; import Select from 'react-select'; -import shallowCompare from 'react-addons-shallow-compare'; import { some } from 'lodash'; import { translate } from '../../../helpers/l10n'; -export default class Form extends React.Component { +export default class Form extends React.PureComponent { static propTypes = { allGates: React.PropTypes.array.isRequired, gate: React.PropTypes.object, @@ -39,10 +38,6 @@ export default class Form extends React.Component { this.renderGateName = this.renderGateName.bind(this); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate(prevProps) { if (prevProps.gate !== this.props.gate) { this.stopLoading(); diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Header.js b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Header.js index 4562e4faccd..fb3dd5ff053 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/Header.js @@ -20,17 +20,15 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class Header extends React.Component { - render() { - return ( - <header className="page-header"> - <h1 className="page-title"> - {translate('project_quality_gate.page')} - </h1> - <div className="page-description"> - {translate('project_quality_gate.page.description')} - </div> - </header> - ); - } +export default function Header() { + return ( + <header className="page-header"> + <h1 className="page-title"> + {translate('project_quality_gate.page')} + </h1> + <div className="page-description"> + {translate('project_quality_gate.page.description')} + </div> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/QualityGate.js b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/QualityGate.js index 855b23f82e9..944be04082b 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-gate/QualityGate.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-gate/QualityGate.js @@ -19,7 +19,6 @@ */ import React from 'react'; import { connect } from 'react-redux'; -import shallowCompare from 'react-addons-shallow-compare'; import Header from './Header'; import Form from './Form'; import { fetchProjectGate, setProjectGate } from '../store/actions'; @@ -29,7 +28,7 @@ import { getComponent } from '../../../store/rootReducer'; -class QualityGate extends React.Component { +class QualityGate extends React.PureComponent { static propTypes = { component: React.PropTypes.object.isRequired, allGates: React.PropTypes.array, @@ -40,10 +39,6 @@ class QualityGate extends React.Component { this.props.fetchProjectGate(this.props.component.key); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleChangeGate(oldId, newId) { this.props.setProjectGate(this.props.component.key, oldId, newId); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Header.js b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Header.js index 2e7f7dca3ed..0ecebfdd8cb 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Header.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Header.js @@ -20,17 +20,15 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class Header extends React.Component { - render() { - return ( - <header className="page-header"> - <h1 className="page-title"> - {translate('project_quality_profiles.page')} - </h1> - <div className="page-description"> - {translate('project_quality_profiles.page.description')} - </div> - </header> - ); - } +export default function Header() { + return ( + <header className="page-header"> + <h1 className="page-title"> + {translate('project_quality_profiles.page')} + </h1> + <div className="page-description"> + {translate('project_quality_profiles.page.description')} + </div> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/ProfileRow.js b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/ProfileRow.js index aaeab20a652..a0f3c132f30 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/ProfileRow.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/ProfileRow.js @@ -18,11 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import Select from 'react-select'; import { translate } from '../../../helpers/l10n'; -export default class ProfileRow extends React.Component { +export default class ProfileRow extends React.PureComponent { static propTypes = { profile: React.PropTypes.object.isRequired, possibleProfiles: React.PropTypes.array.isRequired, @@ -33,10 +32,6 @@ export default class ProfileRow extends React.Component { loading: false }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentWillUpdate(nextProps) { if (nextProps.profile !== this.props.profile) { this.setState({ loading: false }); diff --git a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Table.js b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Table.js index 10251c140c2..3bb5c8ab603 100644 --- a/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Table.js +++ b/server/sonar-web/src/main/js/apps/project-admin/quality-profiles/Table.js @@ -18,22 +18,17 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { groupBy, orderBy } from 'lodash'; import ProfileRow from './ProfileRow'; import { translate } from '../../../helpers/l10n'; -export default class Table extends React.Component { +export default class Table extends React.PureComponent { static propTypes = { allProfiles: React.PropTypes.array.isRequired, profiles: React.PropTypes.array.isRequired, onChangeProfile: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - renderHeader() { // keep one empty cell for the spinner return ( diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ChangeIcon.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ChangeIcon.js index c2593893c77..e47455c3c1b 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ChangeIcon.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ChangeIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class ChangeIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg width="12" height="12" viewBox="0 0 14 14"> - <path - fill="#236a97" - d="M3.35 12.82l.85-.84L2.02 9.8l-.84.85v.98h1.2v1.2h.97zM8.2 4.24c0-.13-.08-.2-.22-.2-.06 0-.1.02-.15.06l-5 5c-.05.05-.08.1-.08.17 0 .13.07.2.2.2.07 0 .12-.02.16-.06l5.02-5c.05-.04.07-.1.07-.16zm-.5-1.77l3.83 3.84-7.7 7.7H0v-3.84l7.7-7.7zm6.3.88c0 .33-.1.6-.34.84L12.12 5.7 8.28 1.88 9.8.35c.24-.23.5-.35.85-.35.32 0 .6.12.84.35l2.16 2.16c.23.25.34.53.34.85z" - /> - </svg> - ); - } +export default function ChangeIcon() { + /* eslint-disable max-len */ + return ( + <svg width="12" height="12" viewBox="0 0 14 14"> + <path + fill="#236a97" + d="M3.35 12.82l.85-.84L2.02 9.8l-.84.85v.98h1.2v1.2h.97zM8.2 4.24c0-.13-.08-.2-.22-.2-.06 0-.1.02-.15.06l-5 5c-.05.05-.08.1-.08.17 0 .13.07.2.2.2.07 0 .12-.02.16-.06l5.02-5c.05-.04.07-.1.07-.16zm-.5-1.77l3.83 3.84-7.7 7.7H0v-3.84l7.7-7.7zm6.3.88c0 .33-.1.6-.34.84L12.12 5.7 8.28 1.88 9.8.35c.24-.23.5-.35.85-.35.32 0 .6.12.84.35l2.16 2.16c.23.25.34.53.34.85z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/DeleteIcon.js b/server/sonar-web/src/main/js/apps/projectActivity/components/DeleteIcon.js index ddea41d70bb..99a349e2ed3 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/DeleteIcon.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/DeleteIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class DeleteIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg width="12" height="12" viewBox="0 0 14 14"> - <path - fill="#d4333f" - d="M14 11.27c0 .3-.1.58-.33.8l-1.6 1.6c-.22.22-.5.33-.8.33-.32 0-.6-.1-.8-.33L7 10.2l-3.46 3.47c-.22.22-.5.33-.8.33-.32 0-.6-.1-.8-.33l-1.6-1.6c-.23-.22-.34-.5-.34-.8 0-.32.1-.6.33-.8L3.8 7 .32 3.54C.1 3.32 0 3.04 0 2.74c0-.32.1-.6.33-.8l1.6-1.6c.22-.23.5-.34.8-.34.32 0 .6.1.8.33L7 3.8 10.46.32c.22-.22.5-.33.8-.33.32 0 .6.1.8.33l1.6 1.6c.23.22.34.5.34.8 0 .32-.1.6-.33.8L10.2 7l3.47 3.46c.22.22.33.5.33.8z" - /> - </svg> - ); - } +export default function DeleteIcon() { + /* eslint-disable max-len */ + return ( + <svg width="12" height="12" viewBox="0 0 14 14"> + <path + fill="#d4333f" + d="M14 11.27c0 .3-.1.58-.33.8l-1.6 1.6c-.22.22-.5.33-.8.33-.32 0-.6-.1-.8-.33L7 10.2l-3.46 3.47c-.22.22-.5.33-.8.33-.32 0-.6-.1-.8-.33l-1.6-1.6c-.23-.22-.34-.5-.34-.8 0-.32.1-.6.33-.8L3.8 7 .32 3.54C.1 3.32 0 3.04 0 2.74c0-.32.1-.6.33-.8l1.6-1.6c.22-.23.5-.34.8-.34.32 0 .6.1.8.33L7 3.8 10.46.32c.22-.22.5-.33.8-.33.32 0 .6.1.8.33l1.6 1.6c.23.22.34.5.34.8 0 .32-.1.6-.33.8L10.2 7l3.47 3.46c.22.22.33.5.33.8z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js b/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js index a604e60ae26..1902f12fc68 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/Event.js @@ -38,7 +38,7 @@ type State = { deleting: boolean }; -export default class Event extends React.Component { +export default class Event extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js b/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js index b133876e44b..4135b322fda 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/EventInner.js @@ -24,26 +24,20 @@ import type { Event as EventType } from '../../../store/projectActivity/duck'; import { translate } from '../../../helpers/l10n'; import './Event.css'; -export default class EventInner extends React.Component { - props: { - event: EventType - }; +export default function EventInner(props: { event: EventType }) { + const { event } = props; - render() { - const { event } = this.props; - - if (event.category === 'VERSION') { - return <span className="badge project-activity-version-badge">{this.props.event.name}</span>; - } - - return ( - <TooltipsContainer> - <span> - <span className="note">{translate('event.category', event.category)}:</span> - {' '} - <strong title={event.description} data-toggle="tooltip">{event.name}</strong> - </span> - </TooltipsContainer> - ); + if (event.category === 'VERSION') { + return <span className="badge project-activity-version-badge">{props.event.name}</span>; } + + return ( + <TooltipsContainer> + <span> + <span className="note">{translate('event.category', event.category)}:</span> + {' '} + <strong title={event.description} data-toggle="tooltip">{event.name}</strong> + </span> + </TooltipsContainer> + ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js index 87afe5b5e5a..6779c389924 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js @@ -23,35 +23,33 @@ import { sortBy } from 'lodash'; import Event from './Event'; import type { Event as EventType } from '../../../store/projectActivity/duck'; -export default class Events extends React.Component { - props: { - analysis: string, - events: Array<EventType>, - isFirst: boolean, - canAdmin: boolean - }; +type Props = { + analysis: string, + events: Array<EventType>, + isFirst: boolean, + canAdmin: boolean +}; - render() { - const sortedEvents: Array<EventType> = sortBy( - this.props.events, - // versions first - (event: EventType) => event.category === 'VERSION' ? 0 : 1, - // then the rest sorted by category - 'category' - ); +export default function Events(props: Props) { + const sortedEvents: Array<EventType> = sortBy( + props.events, + // versions first + (event: EventType) => event.category === 'VERSION' ? 0 : 1, + // then the rest sorted by category + 'category' + ); - return ( - <div className="project-activity-events"> - {sortedEvents.map(event => ( - <Event - key={event.key} - analysis={this.props.analysis} - event={event} - isFirst={this.props.isFirst} - canAdmin={this.props.canAdmin} - /> - ))} - </div> - ); - } + return ( + <div className="project-activity-events"> + {sortedEvents.map(event => ( + <Event + key={event.key} + analysis={props.analysis} + event={event} + isFirst={props.isFirst} + canAdmin={props.canAdmin} + /> + ))} + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js index 7acb76cd43b..6e95edb3b25 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js @@ -29,57 +29,54 @@ import { getAnalyses } from '../../../store/projectActivity/duck'; import { translate } from '../../../helpers/l10n'; import type { Analysis } from '../../../store/projectActivity/duck'; -class ProjectActivityAnalysesList extends React.Component { - props: { - project: string, - analyses?: Array<Analysis>, - canAdmin: boolean - }; +type Props = { + project: string, + analyses?: Array<Analysis>, + canAdmin: boolean +}; - render() { - if (!this.props.analyses) { - return null; - } +function ProjectActivityAnalysesList(props: Props) { + if (!props.analyses) { + return null; + } - if (this.props.analyses.length === 0) { - return <div className="note">{translate('no_results')}</div>; - } + if (props.analyses.length === 0) { + return <div className="note">{translate('no_results')}</div>; + } - const firstAnalysis = this.props.analyses[0]; + const firstAnalysis = props.analyses[0]; - const byDay = groupBy(this.props.analyses, analysis => - moment(analysis.date).startOf('day').valueOf()); + const byDay = groupBy(props.analyses, analysis => moment(analysis.date).startOf('day').valueOf()); - return ( - <div className="boxed-group boxed-group-inner"> - <ul className="project-activity-days-list"> - {Object.keys(byDay).map(day => ( - <li - key={day} - className="project-activity-day" - data-day={moment(Number(day)).format('YYYY-MM-DD')}> - <div className="project-activity-date"> - <FormattedDate date={Number(day)} format="LL" /> - </div> + return ( + <div className="boxed-group boxed-group-inner"> + <ul className="project-activity-days-list"> + {Object.keys(byDay).map(day => ( + <li + key={day} + className="project-activity-day" + data-day={moment(Number(day)).format('YYYY-MM-DD')}> + <div className="project-activity-date"> + <FormattedDate date={Number(day)} format="LL" /> + </div> - <ul className="project-activity-analyses-list"> - {byDay[day] != null && - byDay[day].map(analysis => ( - <ProjectActivityAnalysis - key={analysis.key} - analysis={analysis} - isFirst={analysis === firstAnalysis} - project={this.props.project} - canAdmin={this.props.canAdmin} - /> - ))} - </ul> - </li> - ))} - </ul> - </div> - ); - } + <ul className="project-activity-analyses-list"> + {byDay[day] != null && + byDay[day].map(analysis => ( + <ProjectActivityAnalysis + key={analysis.key} + analysis={analysis} + isFirst={analysis === firstAnalysis} + project={props.project} + canAdmin={props.canAdmin} + /> + ))} + </ul> + </li> + ))} + </ul> + </div> + ); } const mapStateToProps = (state, ownProps) => ({ diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js index 019047c157b..0774d09abb7 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js @@ -27,57 +27,55 @@ import FormattedDate from '../../../components/ui/FormattedDate'; import type { Analysis } from '../../../store/projectActivity/duck'; import { translate } from '../../../helpers/l10n'; -export default class ProjectActivityAnalysis extends React.Component { - props: { - analysis: Analysis, - isFirst: boolean, - project: string, - canAdmin: boolean - }; +type Props = { + analysis: Analysis, + isFirst: boolean, + project: string, + canAdmin: boolean +}; - render() { - const { date, events } = this.props.analysis; - const { isFirst, canAdmin } = this.props; +export default function ProjectActivityAnalysis(props: Props) { + const { date, events } = props.analysis; + const { isFirst, canAdmin } = props; - const version = events.find(event => event.category === 'VERSION'); + const version = events.find(event => event.category === 'VERSION'); - return ( - <li className="project-activity-analysis clearfix"> - {canAdmin && - <div className="project-activity-analysis-actions"> - <div className="dropdown display-inline-block"> - <button className="js-create button-small" data-toggle="dropdown"> - {translate('create')} <i className="icon-dropdown" /> - </button> - <ul className="dropdown-menu dropdown-menu-right"> - {version == null && - <li> - <AddVersionForm analysis={this.props.analysis} /> - </li>} + return ( + <li className="project-activity-analysis clearfix"> + {canAdmin && + <div className="project-activity-analysis-actions"> + <div className="dropdown display-inline-block"> + <button className="js-create button-small" data-toggle="dropdown"> + {translate('create')} <i className="icon-dropdown" /> + </button> + <ul className="dropdown-menu dropdown-menu-right"> + {version == null && <li> - <AddCustomEventForm analysis={this.props.analysis} /> - </li> - </ul> - </div> + <AddVersionForm analysis={props.analysis} /> + </li>} + <li> + <AddCustomEventForm analysis={props.analysis} /> + </li> + </ul> + </div> - {!isFirst && - <div className="display-inline-block little-spacer-left"> - <RemoveAnalysisForm analysis={this.props.analysis} project={this.props.project} /> - </div>} - </div>} + {!isFirst && + <div className="display-inline-block little-spacer-left"> + <RemoveAnalysisForm analysis={props.analysis} project={props.project} /> + </div>} + </div>} - <div className="project-activity-time"> - <FormattedDate date={date} format="LT" tooltipFormat="LTS" /> - </div> + <div className="project-activity-time"> + <FormattedDate date={date} format="LT" tooltipFormat="LTS" /> + </div> - {events.length > 0 && - <Events - analysis={this.props.analysis.key} - events={events} - isFirst={this.props.isFirst} - canAdmin={canAdmin} - />} - </li> - ); - } + {events.length > 0 && + <Events + analysis={props.analysis.key} + events={events} + isFirst={props.isFirst} + canAdmin={canAdmin} + />} + </li> + ); } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js index ed02adadef5..8cf6bcf2522 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js @@ -37,7 +37,7 @@ type State = { filter: ?string }; -class ProjectActivityApp extends React.Component { +class ProjectActivityApp extends React.PureComponent { props: Props; state: State = { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js index a1d8b47b9de..4bf4d21b3ac 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageFooter.js @@ -26,7 +26,7 @@ import { getAnalyses, getPaging } from '../../../store/projectActivity/duck'; import { fetchMoreProjectActivity } from '../actions'; import type { Paging } from '../../../store/projectActivity/duck'; -class ProjectActivityPageFooter extends React.Component { +class ProjectActivityPageFooter extends React.PureComponent { props: { analyses: Array<*>, paging: ?Paging, diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js index fd30a408880..624559acd4c 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityPageHeader.js @@ -27,7 +27,7 @@ type Props = { filter: ?string }; -export default class ProjectActivityPageHeader extends React.Component { +export default class ProjectActivityPageHeader extends React.PureComponent { props: Props; handleChange = (option: null | { value: string }) => { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddCustomEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddCustomEventForm.js index b5e58a800b6..3dcea1662d4 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddCustomEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddCustomEventForm.js @@ -29,9 +29,9 @@ type Props = { analysis: Analysis }; -const AddCustomEventForm = (props: Props) => ( - <AddEventForm {...props} addEventButtonText="project_activity.add_custom_event" /> -); +function AddCustomEventForm(props: Props) { + return <AddEventForm {...props} addEventButtonText="project_activity.add_custom_event" />; +} const mapStateToProps = null; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js index a820b6ff328..2d0576c5705 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddEventForm.js @@ -35,7 +35,7 @@ type State = { name: string }; -export default class AddEventForm extends React.Component { +export default class AddEventForm extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddVersionForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddVersionForm.js index 769bf5ba45b..dd1c3e43990 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddVersionForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/AddVersionForm.js @@ -29,9 +29,9 @@ type Props = { analysis: Analysis }; -const AddVersionForm = (props: Props) => ( - <AddEventForm {...props} addEventButtonText="project_activity.add_version" /> -); +function AddVersionForm(props: Props) { + return <AddEventForm {...props} addEventButtonText="project_activity.add_version" />; +} const mapStateToProps = null; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js index 4dfd72bfda8..3fcdd54cc2a 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeEventForm.js @@ -35,7 +35,7 @@ type State = { name: string }; -export default class ChangeEventForm extends React.Component { +export default class ChangeEventForm extends React.PureComponent { mounted: boolean; props: Props; state: State; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeVersionForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeVersionForm.js index d57f9234939..db2f13ae4e8 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeVersionForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/ChangeVersionForm.js @@ -30,9 +30,9 @@ type Props = { onClose: () => void }; -const ChangeVersionForm = (props: Props) => ( - <ChangeEventForm {...props} changeEventButtonText="project_activity.change_version" /> -); +function ChangeVersionForm(props: Props) { + return <ChangeEventForm {...props} changeEventButtonText="project_activity.change_version" />; +} const mapStateToProps = null; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js index af543faae99..620d2980691 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveAnalysisForm.js @@ -36,7 +36,7 @@ type State = { processing: boolean }; -class RemoveAnalysisForm extends React.Component { +class RemoveAnalysisForm extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveCustomEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveCustomEventForm.js index 4f18821b611..26d0ccc9234 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveCustomEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveCustomEventForm.js @@ -31,13 +31,15 @@ type Props = { onClose: () => void }; -const RemoveCustomEventForm = (props: Props) => ( - <RemoveEventForm - {...props} - removeEventButtonText="project_activity.remove_custom_event" - removeEventQuestion="project_activity.remove_custom_event.question" - /> -); +function RemoveCustomEventForm(props: Props) { + return ( + <RemoveEventForm + {...props} + removeEventButtonText="project_activity.remove_custom_event" + removeEventQuestion="project_activity.remove_custom_event.question" + /> + ); +} const mapStateToProps = null; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js index 34366af0a37..e251e23f507 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveEventForm.js @@ -36,7 +36,7 @@ type State = { processing: boolean }; -export default class RemoveEventForm extends React.Component { +export default class RemoveEventForm extends React.PureComponent { mounted: boolean; props: Props; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveVersionForm.js b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveVersionForm.js index 1a8938719cb..8f896c89d86 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveVersionForm.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/forms/RemoveVersionForm.js @@ -31,13 +31,15 @@ type Props = { onClose: () => void }; -const RemoveVersionForm = (props: Props) => ( - <RemoveEventForm - {...props} - removeEventButtonText="project_activity.remove_version" - removeEventQuestion="project_activity.remove_version.question" - /> -); +function RemoveVersionForm(props: Props) { + return ( + <RemoveEventForm + {...props} + removeEventButtonText="project_activity.remove_version" + removeEventQuestion="project_activity.remove_version.question" + /> + ); +} const mapStateToProps = null; diff --git a/server/sonar-web/src/main/js/apps/projects-admin/AppContainer.js b/server/sonar-web/src/main/js/apps/projects-admin/AppContainer.js index dc382be6fc6..baf6f106889 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/AppContainer.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/AppContainer.js @@ -23,24 +23,22 @@ import Main from './main'; import { getCurrentUser, getAppState } from '../../store/rootReducer'; import { getRootQualifiers } from '../../store/appState/duck'; -class AppContainer extends React.Component { - render() { - const hasProvisionPermission = this.props.organization - ? this.props.organization.canProvisionProjects - : this.props.user.permissions.global.indexOf('provisioning') !== -1; +function AppContainer(props) { + const hasProvisionPermission = props.organization + ? props.organization.canProvisionProjects + : props.user.permissions.global.indexOf('provisioning') !== -1; - const topLevelQualifiers = this.props.organization && !this.props.organization.isDefault - ? ['TRK'] - : this.props.rootQualifiers; + const topLevelQualifiers = props.organization && !props.organization.isDefault + ? ['TRK'] + : props.rootQualifiers; - return ( - <Main - hasProvisionPermission={hasProvisionPermission} - topLevelQualifiers={topLevelQualifiers} - organization={this.props.organization} - /> - ); - } + return ( + <Main + hasProvisionPermission={hasProvisionPermission} + topLevelQualifiers={topLevelQualifiers} + organization={props.organization} + /> + ); } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/apps/projects-admin/header.js b/server/sonar-web/src/main/js/apps/projects-admin/header.js index 2906d358630..e2bc02294d9 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/header.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/header.js @@ -21,7 +21,7 @@ import React from 'react'; import CreateView from './create-view'; import BulkApplyTemplateView from './views/BulkApplyTemplateView'; -export default class Header extends React.Component { +export default class Header extends React.PureComponent { static propTypes = { hasProvisionPermission: React.PropTypes.bool.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/projects-admin/main.js b/server/sonar-web/src/main/js/apps/projects-admin/main.js index 29278721294..c7b6340673e 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/main.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/main.js @@ -26,14 +26,15 @@ import { PAGE_SIZE, TYPE } from './constants'; import { getComponents, getProvisioned, getGhosts, deleteComponents } from '../../api/components'; import ListFooter from '../../components/controls/ListFooter'; -export default React.createClass({ - propTypes: { +export default class Main extends React.PureComponent { + static propTypes = { hasProvisionPermission: React.PropTypes.bool.isRequired, organization: React.PropTypes.object - }, + }; - getInitialState() { - return { + constructor(props) { + super(props); + this.state = { ready: false, projects: [], total: 0, @@ -43,17 +44,14 @@ export default React.createClass({ type: TYPE.ALL, selection: [] }; - }, - - componentWillMount() { this.requestProjects = debounce(this.requestProjects, 250); - }, + } componentDidMount() { this.requestProjects(); - }, + } - getFilters() { + getFilters = () => { const filters = { ps: PAGE_SIZE }; if (this.state.page !== 1) { filters.p = this.state.page; @@ -65,9 +63,9 @@ export default React.createClass({ filters.organization = this.props.organization.key; } return filters; - }, + }; - requestProjects() { + requestProjects = () => { switch (this.state.type) { case TYPE.ALL: this.requestAllProjects(); @@ -82,9 +80,9 @@ export default React.createClass({ // should never happen } - }, + }; - requestGhosts() { + requestGhosts = () => { const data = this.getFilters(); getGhosts(data).then(r => { let projects = r.projects.map(project => ({ @@ -97,9 +95,9 @@ export default React.createClass({ } this.setState({ ready: true, projects, total: r.total }); }); - }, + }; - requestProvisioned() { + requestProvisioned = () => { const data = this.getFilters(); getProvisioned(data).then(r => { let projects = r.projects.map(project => ({ @@ -112,9 +110,9 @@ export default React.createClass({ } this.setState({ ready: true, projects, total: r.total }); }); - }, + }; - requestAllProjects() { + requestAllProjects = () => { const data = this.getFilters(); data.qualifiers = this.state.qualifiers; getComponents(data).then(r => { @@ -124,13 +122,13 @@ export default React.createClass({ } this.setState({ ready: true, projects, total: r.paging.total }); }); - }, + }; - loadMore() { + loadMore = () => { this.setState({ ready: false, page: this.state.page + 1 }, this.requestProjects); - }, + }; - onSearch(query) { + onSearch = query => { this.setState( { ready: false, @@ -140,9 +138,9 @@ export default React.createClass({ }, this.requestProjects ); - }, + }; - onTypeChanged(newType) { + onTypeChanged = newType => { this.setState( { ready: false, @@ -154,9 +152,9 @@ export default React.createClass({ }, this.requestProjects ); - }, + }; - onQualifierChanged(newQualifier) { + onQualifierChanged = newQualifier => { this.setState( { ready: false, @@ -168,28 +166,28 @@ export default React.createClass({ }, this.requestProjects ); - }, + }; - onProjectSelected(project) { + onProjectSelected = project => { const newSelection = uniq([].concat(this.state.selection, project.key)); this.setState({ selection: newSelection }); - }, + }; - onProjectDeselected(project) { + onProjectDeselected = project => { const newSelection = without(this.state.selection, project.key); this.setState({ selection: newSelection }); - }, + }; - onAllSelected() { + onAllSelected = () => { const newSelection = this.state.projects.map(project => project.key); this.setState({ selection: newSelection }); - }, + }; - onAllDeselected() { + onAllDeselected = () => { this.setState({ selection: [] }); - }, + }; - deleteProjects() { + deleteProjects = () => { this.setState({ ready: false }); const projects = this.state.selection.join(','); const data = { projects }; @@ -199,7 +197,7 @@ export default React.createClass({ deleteComponents(data).then(() => { this.setState({ page: 1, selection: [] }, this.requestProjects); }); - }, + }; render() { return ( @@ -244,4 +242,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/projects-admin/projects.js b/server/sonar-web/src/main/js/apps/projects-admin/projects.js index f3984b0cbdd..a6def849018 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/projects.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/projects.js @@ -26,7 +26,7 @@ import Checkbox from '../../components/controls/Checkbox'; import QualifierIcon from '../../components/shared/QualifierIcon'; import { translate } from '../../helpers/l10n'; -export default class Projects extends React.Component { +export default class Projects extends React.PureComponent { static propTypes = { projects: React.PropTypes.array.isRequired, selection: React.PropTypes.array.isRequired, diff --git a/server/sonar-web/src/main/js/apps/projects-admin/search.js b/server/sonar-web/src/main/js/apps/projects-admin/search.js index 2437b928026..c4b8c62c34e 100644 --- a/server/sonar-web/src/main/js/apps/projects-admin/search.js +++ b/server/sonar-web/src/main/js/apps/projects-admin/search.js @@ -25,51 +25,51 @@ import RadioToggle from '../../components/controls/RadioToggle'; import Checkbox from '../../components/controls/Checkbox'; import { translate } from '../../helpers/l10n'; -export default React.createClass({ - propTypes: { +export default class Search extends React.PureComponent { + static propTypes = { onSearch: React.PropTypes.func.isRequired - }, + }; - onSubmit(e) { + onSubmit = e => { e.preventDefault(); this.search(); - }, + }; - search() { + search = () => { const q = this.refs.input.value; this.props.onSearch(q); - }, + }; - getTypeOptions() { + getTypeOptions = () => { return [ { value: TYPE.ALL, label: 'All' }, { value: TYPE.PROVISIONED, label: 'Provisioned' }, { value: TYPE.GHOSTS, label: 'Ghosts' } ]; - }, + }; - getQualifierOptions() { + getQualifierOptions = () => { const options = this.props.topLevelQualifiers.map(q => { return { value: q, label: translate('qualifiers', q) }; }); return sortBy(options, option => QUALIFIERS_ORDER.indexOf(option.value)); - }, + }; - onCheck(checked) { + onCheck = checked => { if (checked) { this.props.onAllSelected(); } else { this.props.onAllDeselected(); } - }, + }; - deleteProjects() { + deleteProjects = () => { new DeleteView({ deleteProjects: this.props.deleteProjects }).render(); - }, + }; - renderCheckbox() { + renderCheckbox = () => { const isAllChecked = this.props.projects.length > 0 && this.props.selection.length === this.props.projects.length; const thirdState = this.props.projects.length > 0 && @@ -77,9 +77,9 @@ export default React.createClass({ this.props.selection.length < this.props.projects.length; const checked = isAllChecked || thirdState; return <Checkbox checked={checked} thirdState={thirdState} onCheck={this.onCheck} />; - }, + }; - renderGhostsDescription() { + renderGhostsDescription = () => { if (this.props.type !== TYPE.GHOSTS || !this.props.ready) { return null; } @@ -88,9 +88,9 @@ export default React.createClass({ {translate('bulk_deletion.ghosts.description')} </div> ); - }, + }; - renderQualifierFilter() { + renderQualifierFilter = () => { const options = this.getQualifierOptions(); if (options.length < 2) { return null; @@ -105,11 +105,9 @@ export default React.createClass({ /> </td> ); - }, + }; - renderSpinner() { - return <i className="spinner" />; - }, + renderSpinner = () => <i className="spinner" />; render() { const isSomethingSelected = this.props.projects.length > 0 && this.props.selection.length > 0; @@ -160,4 +158,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js index c62d9e8c612..92ddc79dde0 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js +++ b/server/sonar-web/src/main/js/apps/projects/components/AllProjects.js @@ -31,7 +31,7 @@ import PageSide from '../../../components/layout/PageSide'; import PageFilters from '../../../components/layout/PageFilters'; import '../styles.css'; -export default class AllProjects extends React.Component { +export default class AllProjects extends React.PureComponent { static propTypes = { isFavorite: React.PropTypes.bool.isRequired, location: React.PropTypes.object.isRequired, diff --git a/server/sonar-web/src/main/js/apps/projects/components/App.js b/server/sonar-web/src/main/js/apps/projects/components/App.js index 69c18380bb3..8897f1e6f36 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/App.js +++ b/server/sonar-web/src/main/js/apps/projects/components/App.js @@ -21,7 +21,7 @@ import React from 'react'; import Helmet from 'react-helmet'; import { translate } from '../../../helpers/l10n'; -export default class App extends React.Component { +export default class App extends React.PureComponent { componentDidMount() { document.querySelector('html').classList.add('dashboard-page'); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/EmptyInstance.js b/server/sonar-web/src/main/js/apps/projects/components/EmptyInstance.js index 8b4156532ab..1eb2241cfb1 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/EmptyInstance.js +++ b/server/sonar-web/src/main/js/apps/projects/components/EmptyInstance.js @@ -20,12 +20,10 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class EmptyInstance extends React.Component { - render() { - return ( - <div className="projects-empty-list"> - <h3>{translate('projects.no_projects.empty_instance')}</h3> - </div> - ); - } +export default function EmptyInstance() { + return ( + <div className="projects-empty-list"> + <h3>{translate('projects.no_projects.empty_instance')}</h3> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.js b/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.js index 43709aecbe3..f69fbebc834 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.js +++ b/server/sonar-web/src/main/js/apps/projects/components/NoFavoriteProjects.js @@ -21,18 +21,16 @@ import React from 'react'; import { Link } from 'react-router'; import { translate } from '../../../helpers/l10n'; -export default class NoFavoriteProjects extends React.Component { - render() { - return ( - <div className="projects-empty-list"> - <h3>{translate('projects.no_favorite_projects')}</h3> - <p className="big-spacer-top">{translate('projects.no_favorite_projects.engagement')}</p> - <p className="big-spacer-top"> - <Link to="/projects/all" className="button"> - {translate('projects.explore_projects')} - </Link> - </p> - </div> - ); - } +export default function NoFavoriteProjects() { + return ( + <div className="projects-empty-list"> + <h3>{translate('projects.no_favorite_projects')}</h3> + <p className="big-spacer-top">{translate('projects.no_favorite_projects.engagement')}</p> + <p className="big-spacer-top"> + <Link to="/projects/all" className="button"> + {translate('projects.explore_projects')} + </Link> + </p> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js index ee2cb6cf6d0..61a9bba24ab 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js @@ -22,30 +22,28 @@ import React from 'react'; import ViewSelect from './ViewSelect'; import { translate } from '../../../helpers/l10n'; -export default class PageHeader extends React.Component { - props: { - loading: boolean, - onViewChange: (string) => void, - total?: number, - view: string - }; +type Props = { + loading: boolean, + onViewChange: (string) => void, + total?: number, + view: string +}; - render() { - return ( - <header className="page-header"> - <ViewSelect onChange={this.props.onViewChange} view={this.props.view} /> +export default function PageHeader(props: Props) { + return ( + <header className="page-header"> + <ViewSelect onChange={props.onViewChange} view={props.view} /> - <div className="page-actions projects-page-actions"> - {!!this.props.loading && <i className="spinner spacer-right" />} + <div className="page-actions projects-page-actions"> + {!!props.loading && <i className="spinner spacer-right" />} - {this.props.total != null && - <span> - <strong id="projects-total">{this.props.total}</strong> - {' '} - {translate('projects._projects')} - </span>} - </div> - </header> - ); - } + {props.total != null && + <span> + <strong id="projects-total">{props.total}</strong> + {' '} + {translate('projects._projects')} + </span>} + </div> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js index 172d228f0d8..e4d4c283521 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js @@ -24,7 +24,7 @@ import Tooltip from '../../../components/controls/Tooltip'; import { getLanguages } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; -class ProjectCardLanguages extends React.Component { +class ProjectCardLanguages extends React.PureComponent { getLanguageName(key) { if (key === '<null>') { return translate('unknown'); diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js index 745b6683372..3a1f5d4c1fe 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js @@ -20,7 +20,7 @@ import React from 'react'; import ListFooter from '../../../components/controls/ListFooter'; -export default class ProjectsListFooter extends React.Component { +export default class ProjectsListFooter extends React.PureComponent { static propTypes = { total: React.PropTypes.number.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js b/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js index 7ac7113d587..11d9d790662 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/FilterHeader.js @@ -22,7 +22,7 @@ import React from 'react'; type Props = { name: string, - children?: {} + children?: React.Element<*> }; export default class FilterHeader extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/projects/filters/MaintainabilityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/MaintainabilityFilter.js index 2f8c422dac4..a02a5f70c57 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/MaintainabilityFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/MaintainabilityFilter.js @@ -20,8 +20,6 @@ import React from 'react'; import IssuesFilter from './IssuesFilter'; -export default class MaintainabilityFilter extends React.Component { - render() { - return <IssuesFilter {...this.props} name="Maintainability" property="maintainability" />; - } +export default function MaintainabilityFilter(props) { + return <IssuesFilter {...props} name="Maintainability" property="maintainability" />; } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/ReliabilityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/ReliabilityFilter.js index da1372a2a86..07852afe335 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/ReliabilityFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/ReliabilityFilter.js @@ -20,8 +20,6 @@ import React from 'react'; import IssuesFilter from './IssuesFilter'; -export default class ReliabilityFilter extends React.Component { - render() { - return <IssuesFilter {...this.props} name="Reliability" property="reliability" />; - } +export default function ReliabilityFilter(props) { + return <IssuesFilter {...props} name="Reliability" property="reliability" />; } diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js index b70d403a499..ec6bad4c55d 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SearchFilterContainer.js @@ -31,7 +31,7 @@ type Props = { organization?: {} }; -class SearchFilterContainer extends React.Component { +class SearchFilterContainer extends React.PureComponent { handleSearch: (userQuery?: string) => void; props: Props; diff --git a/server/sonar-web/src/main/js/apps/projects/filters/SecurityFilter.js b/server/sonar-web/src/main/js/apps/projects/filters/SecurityFilter.js index 22eac70799c..9f7fa7aa997 100644 --- a/server/sonar-web/src/main/js/apps/projects/filters/SecurityFilter.js +++ b/server/sonar-web/src/main/js/apps/projects/filters/SecurityFilter.js @@ -20,8 +20,6 @@ import React from 'react'; import IssuesFilter from './IssuesFilter'; -export default class SecurityFilter extends React.Component { - render() { - return <IssuesFilter {...this.props} name="Security" property="security" />; - } +export default function SecurityFilter(props) { + return <IssuesFilter {...props} name="Security" property="security" />; } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.js b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.js index 54830da056a..cfd353cc655 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.js @@ -28,7 +28,7 @@ function getKey(condition, index) { return condition.id ? condition.id : `new-${index}`; } -export default class Conditions extends React.Component { +export default class Conditions extends React.PureComponent { state = { error: null }; diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.js b/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.js index 43e3630fc4e..4b8f6980975 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ThresholdInput.js @@ -20,7 +20,7 @@ import React from 'react'; import Select from 'react-select'; -export default class ThresholdInput extends React.Component { +export default class ThresholdInput extends React.PureComponent { static propTypes = { name: React.PropTypes.string.isRequired, value: React.PropTypes.any, diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js index 158e6b9955b..7077dd39aaf 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/components/ProfileDate.js @@ -20,7 +20,6 @@ // @flow import React from 'react'; import moment from 'moment'; -import shallowCompare from 'react-addons-shallow-compare'; import { translate } from '../../../helpers/l10n'; type Props = { @@ -30,10 +29,6 @@ type Props = { export default class ProfileDate extends React.PureComponent { props: Props; - shouldComponentUpdate(nextProps: Props) { - return shallowCompare(this, nextProps); - } - render() { const { date } = this.props; diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js index 8f3e21c793e..85dcb48c1d3 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js @@ -20,7 +20,6 @@ // @flow import React from 'react'; import { Link } from 'react-router'; -import shallowCompare from 'react-addons-shallow-compare'; import ProfileLink from '../components/ProfileLink'; import ProfileDate from '../components/ProfileDate'; import ProfileActions from '../components/ProfileActions'; @@ -39,10 +38,6 @@ type Props = { export default class ProfilesListRow extends React.PureComponent { props: Props; - shouldComponentUpdate(nextProps: Props) { - return shallowCompare(this, nextProps); - } - renderName() { const { profile } = this.props; const offset = 25 * (profile.depth - 1); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js index e2e6188fcd4..06abd2f82c9 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginForm.js @@ -22,7 +22,7 @@ import React from 'react'; import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; import { translate } from '../../../helpers/l10n'; -export default class LoginForm extends React.Component { +export default class LoginForm extends React.PureComponent { static propTypes = { identityProviders: React.PropTypes.array.isRequired, onSubmit: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js index e7a9ee6849d..9208545732f 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginFormContainer.js @@ -25,7 +25,7 @@ import { doLogin } from '../../../store/rootActions'; import { getAppState } from '../../../store/rootReducer'; import { getIdentityProviders } from '../../../api/users'; -class LoginFormContainer extends React.Component { +class LoginFormContainer extends React.PureComponent { mounted: boolean; static propTypes = { diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Logout.js b/server/sonar-web/src/main/js/apps/sessions/components/Logout.js index 6d076682589..1ff047bb5f0 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Logout.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/Logout.js @@ -25,7 +25,7 @@ import { doLogout } from '../../../store/rootActions'; import { translate } from '../../../helpers/l10n'; import RecentHistory from '../../../app/components/nav/component/RecentHistory'; -class Logout extends React.Component { +class Logout extends React.PureComponent { componentDidMount() { this.props .doLogout() diff --git a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js index e5e1bf8f4e6..5be984a1524 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js +++ b/server/sonar-web/src/main/js/apps/sessions/components/Unauthorized.js @@ -20,7 +20,7 @@ // @flow import React from 'react'; -export default class Unauthorized extends React.Component { +export default class Unauthorized extends React.PureComponent { static propTypes = { location: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/settings/components/AllCategoriesList.js b/server/sonar-web/src/main/js/apps/settings/components/AllCategoriesList.js index f8777a4cfd8..684d418af7e 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/AllCategoriesList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/AllCategoriesList.js @@ -23,10 +23,8 @@ import { connect } from 'react-redux'; import CategoriesList from './CategoriesList'; import { getSettingsAppAllCategories } from '../../../store/rootReducer'; -class AllCategoriesList extends React.Component { - render() { - return <CategoriesList {...this.props} />; - } +function AllCategoriesList(props) { + return <CategoriesList {...props} />; } const mapStateToProps = state => ({ diff --git a/server/sonar-web/src/main/js/apps/settings/components/App.js b/server/sonar-web/src/main/js/apps/settings/components/App.js index e8963b39fc5..c86abf3956a 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/App.js +++ b/server/sonar-web/src/main/js/apps/settings/components/App.js @@ -19,7 +19,6 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { connect } from 'react-redux'; import PageHeader from './PageHeader'; import CategoryDefinitionsList from './CategoryDefinitionsList'; @@ -40,7 +39,7 @@ type State = { loaded: boolean }; -class App extends React.Component { +class App extends React.PureComponent { props: Props; state: State = { loaded: false }; @@ -55,10 +54,6 @@ class App extends React.Component { }); } - shouldComponentUpdate(nextProps: Props, nextState: ?{}) { - return shallowCompare(this, nextProps, nextState); - } - componentDidUpdate(prevProps) { if (prevProps.component !== this.props.component) { const componentKey = this.props.component ? this.props.component.key : null; diff --git a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js index 873dc94d63d..3ad92ee2b96 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/CategoriesList.js @@ -19,7 +19,6 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { sortBy } from 'lodash'; import { IndexLink } from 'react-router'; import { getCategoryName } from '../utils'; @@ -36,13 +35,9 @@ type Props = { selectedCategory: string }; -export default class CategoriesList extends React.Component { +export default class CategoriesList extends React.PureComponent { rops: Props; - shouldComponentUpdate(nextProps: Props, nextState: ?{}) { - return shallowCompare(this, nextProps, nextState); - } - renderLink(category: Category) { const query = {}; diff --git a/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.js index 2759f04b1e3..81a992dc894 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/CategoryDefinitionsList.js @@ -23,10 +23,8 @@ import { connect } from 'react-redux'; import SubCategoryDefinitionsList from './SubCategoryDefinitionsList'; import { getSettingsAppSettingsForCategory } from '../../../store/rootReducer'; -class CategoryDefinitionsList extends React.Component { - render() { - return <SubCategoryDefinitionsList {...this.props} />; - } +function CategoryDefinitionsList(props) { + return <SubCategoryDefinitionsList {...props} />; } const mapStateToProps = (state, ownProps) => ({ diff --git a/server/sonar-web/src/main/js/apps/settings/components/Definition.js b/server/sonar-web/src/main/js/apps/settings/components/Definition.js index b16c3207caf..3d765002dc9 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/Definition.js +++ b/server/sonar-web/src/main/js/apps/settings/components/Definition.js @@ -20,7 +20,6 @@ // @flow import React from 'react'; import { connect } from 'react-redux'; -import shallowCompare from 'react-addons-shallow-compare'; import classNames from 'classnames'; import Input from './inputs/Input'; import DefinitionDefaults from './DefinitionDefaults'; @@ -42,7 +41,7 @@ import { getSettingsAppValidationMessage } from '../../../store/rootReducer'; -class Definition extends React.Component { +class Definition extends React.PureComponent { mounted: boolean; timeout: number; @@ -68,10 +67,6 @@ class Definition extends React.Component { this.mounted = true; } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentWillUnmount() { this.mounted = false; } diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js index c32627b74ff..ef9c248ffd0 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js @@ -19,19 +19,14 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { translate } from '../../../helpers/l10n'; -export default class DefinitionChanges extends React.Component { +export default class DefinitionChanges extends React.PureComponent { static propTypes = { onSave: React.PropTypes.func.isRequired, onCancel: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps: {}, nextState: ?{}) { - return shallowCompare(this, nextProps, nextState); - } - handleSaveClick(e: Object) { e.preventDefault(); e.target.blur(); diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js index 7d3655801f8..4f156e2a521 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js @@ -22,7 +22,7 @@ import React from 'react'; import { getSettingValue, isEmptyValue, getDefaultValue } from '../utils'; import { translate } from '../../../helpers/l10n'; -export default class DefinitionDefaults extends React.Component { +export default class DefinitionDefaults extends React.PureComponent { static propTypes = { setting: React.PropTypes.object.isRequired, isDefault: React.PropTypes.bool.isRequired, diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js index ca8222a7496..7a6c4c6d8e5 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionsList.js @@ -19,19 +19,14 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import Definition from './Definition'; -export default class DefinitionsList extends React.Component { +export default class DefinitionsList extends React.PureComponent { static propTypes = { component: React.PropTypes.object, settings: React.PropTypes.array.isRequired }; - shouldComponentUpdate(nextProps: {}, nextState: ?{}) { - return shallowCompare(this, nextProps, nextState); - } - render() { return ( <ul className="settings-definitions-list"> diff --git a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js index e923f635443..2017a265f2c 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js +++ b/server/sonar-web/src/main/js/apps/settings/components/EmailForm.js @@ -24,7 +24,7 @@ import { sendTestEmail } from '../../../api/settings'; import { parseError } from '../../code/utils'; import { getCurrentUser } from '../../../store/rootReducer'; -class EmailForm extends React.Component { +class EmailForm extends React.PureComponent { constructor(props) { super(props); this.state = { diff --git a/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js b/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js index 0240fa7c61b..c4bf4675a9c 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js +++ b/server/sonar-web/src/main/js/apps/settings/components/PageHeader.js @@ -21,7 +21,7 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class PageHeader extends React.Component { +export default class PageHeader extends React.PureComponent { static propTypes = { component: React.PropTypes.object }; diff --git a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js index eb7b7fb045d..2f215d01723 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/SubCategoryDefinitionsList.js @@ -19,22 +19,17 @@ */ // @flow import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { groupBy, sortBy } from 'lodash'; import DefinitionsList from './DefinitionsList'; import EmailForm from './EmailForm'; import { getSubCategoryName, getSubCategoryDescription } from '../utils'; -export default class SubCategoryDefinitionsList extends React.Component { +export default class SubCategoryDefinitionsList extends React.PureComponent { static propTypes = { component: React.PropTypes.object, settings: React.PropTypes.array.isRequired }; - shouldComponentUpdate(nextProps: {}, nextState: ?{}) { - return shallowCompare(this, nextProps, nextState); - } - renderEmailForm(subCategoryKey: string) { const isEmailSettings = this.props.category === 'general' && subCategoryKey === 'email'; if (!isEmailSettings) { diff --git a/server/sonar-web/src/main/js/apps/settings/components/WildcardsHelp.js b/server/sonar-web/src/main/js/apps/settings/components/WildcardsHelp.js index c9e06ec513d..071989e672e 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/WildcardsHelp.js +++ b/server/sonar-web/src/main/js/apps/settings/components/WildcardsHelp.js @@ -19,107 +19,105 @@ */ import React from 'react'; -export default class WildcardsHelp extends React.Component { - render() { - return ( - <div className="huge-spacer-top"> - <h2 className="spacer-bottom">Wildcards</h2> - <p className="spacer-bottom">Following rules are applied:</p> +export default function WildcardsHelp() { + return ( + <div className="huge-spacer-top"> + <h2 className="spacer-bottom">Wildcards</h2> + <p className="spacer-bottom">Following rules are applied:</p> - <table className="data spacer-bottom"> - <tbody> - <tr> - <td>*</td> - <td>Match zero or more characters</td> - </tr> - <tr> - <td>**</td> - <td>Match zero or more directories</td> - </tr> - <tr> - <td>?</td> - <td>Match a single character</td> - </tr> - </tbody> - </table> + <table className="data spacer-bottom"> + <tbody> + <tr> + <td>*</td> + <td>Match zero or more characters</td> + </tr> + <tr> + <td>**</td> + <td>Match zero or more directories</td> + </tr> + <tr> + <td>?</td> + <td>Match a single character</td> + </tr> + </tbody> + </table> - <table className="data zebra"> - <thead> - <tr> - <th>Example</th> - <th>Matches</th> - <th>Does not match</th> - </tr> - </thead> - <tbody> - <tr> - <td>**/foo/*.js</td> - <td> - <ul> - <li>src/foo/bar.js</li> - <li>lib/ui/foo/bar.js</li> - </ul> - </td> - <td> - <ul> - <li>src/bar.js</li> - <li>src/foo2/bar.js</li> - </ul> - </td> - </tr> - <tr> - <td>src/foo/*bar*.js</td> - <td> - <ul> - <li>src/foo/bar.js</li> - <li>src/foo/bar1.js</li> - <li>src/foo/bar123.js</li> - <li>src/foo/123bar123.js</li> - </ul> - </td> - <td> - <ul> - <li>src/foo/ui/bar.js</li> - <li>src/bar.js</li> - </ul> - </td> - </tr> - <tr> - <td>src/foo/**</td> - <td> - <ul> - <li>src/foo/bar.js</li> - <li>src/foo/ui/bar.js</li> - </ul> - </td> - <td> - <ul> - <li>src/bar/foo/bar.js</li> - <li>src/bar.js</li> - </ul> - </td> - </tr> - <tr> - <td> - **/foo?.js - </td> - <td> - <ul> - <li>src/foo1.js</li> - <li>src/bar/foo1.js</li> - </ul> - </td> - <td> - <ul> - <li>src/foo.js</li> - <li>src/foo12.js</li> - <li>src/12foo3.js</li> - </ul> - </td> - </tr> - </tbody> - </table> - </div> - ); - } + <table className="data zebra"> + <thead> + <tr> + <th>Example</th> + <th>Matches</th> + <th>Does not match</th> + </tr> + </thead> + <tbody> + <tr> + <td>**/foo/*.js</td> + <td> + <ul> + <li>src/foo/bar.js</li> + <li>lib/ui/foo/bar.js</li> + </ul> + </td> + <td> + <ul> + <li>src/bar.js</li> + <li>src/foo2/bar.js</li> + </ul> + </td> + </tr> + <tr> + <td>src/foo/*bar*.js</td> + <td> + <ul> + <li>src/foo/bar.js</li> + <li>src/foo/bar1.js</li> + <li>src/foo/bar123.js</li> + <li>src/foo/123bar123.js</li> + </ul> + </td> + <td> + <ul> + <li>src/foo/ui/bar.js</li> + <li>src/bar.js</li> + </ul> + </td> + </tr> + <tr> + <td>src/foo/**</td> + <td> + <ul> + <li>src/foo/bar.js</li> + <li>src/foo/ui/bar.js</li> + </ul> + </td> + <td> + <ul> + <li>src/bar/foo/bar.js</li> + <li>src/bar.js</li> + </ul> + </td> + </tr> + <tr> + <td> + **/foo?.js + </td> + <td> + <ul> + <li>src/foo1.js</li> + <li>src/bar/foo1.js</li> + </ul> + </td> + <td> + <ul> + <li>src/foo.js</li> + <li>src/foo12.js</li> + <li>src/12foo3.js</li> + </ul> + </td> + </tr> + </tbody> + </table> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.js index 43daae89c40..ac0e51a76b6 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/Input.js @@ -18,23 +18,18 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import PropertySetInput from './PropertySetInput'; import MultiValueInput from './MultiValueInput'; import PrimitiveInput from './PrimitiveInput'; import { TYPE_PROPERTY_SET } from '../../constants'; -export default class Input extends React.Component { +export default class Input extends React.PureComponent { static propTypes = { setting: React.PropTypes.object.isRequired, value: React.PropTypes.any, onChange: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - render() { const { definition } = this.props.setting; diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForBoolean.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForBoolean.js index ff566af6e3f..66f02465338 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForBoolean.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForBoolean.js @@ -22,7 +22,7 @@ import Toggle from '../../../../components/controls/Toggle'; import { defaultInputPropTypes } from '../../propTypes'; import { translate } from '../../../../helpers/l10n'; -export default class InputForBoolean extends React.Component { +export default class InputForBoolean extends React.PureComponent { static propTypes = { ...defaultInputPropTypes, value: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.string]) diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForNumber.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForNumber.js index c0101776587..0d57941f0d3 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForNumber.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForNumber.js @@ -20,8 +20,6 @@ import React from 'react'; import SimpleInput from './SimpleInput'; -export default class InputForNumber extends React.Component { - render() { - return <SimpleInput {...this.props} className="input-small" type="text" />; - } +export default function InputForNumber(props) { + return <SimpleInput {...props} className="input-small" type="text" />; } diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForPassword.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForPassword.js index 0605da6d32e..9f7a35f3f4e 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForPassword.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForPassword.js @@ -21,7 +21,7 @@ import React from 'react'; import { translate } from '../../../../helpers/l10n'; import { defaultInputPropTypes } from '../../propTypes'; -export default class InputForPassword extends React.Component { +export default class InputForPassword extends React.PureComponent { static propTypes = defaultInputPropTypes; state = { diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.js index bfdfdd60996..06de1ca1c58 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForSingleSelectList.js @@ -21,7 +21,7 @@ import React from 'react'; import Select from 'react-select'; import { defaultInputPropTypes } from '../../propTypes'; -export default class InputForSingleSelectList extends React.Component { +export default class InputForSingleSelectList extends React.PureComponent { static propTypes = { ...defaultInputPropTypes, options: React.PropTypes.arrayOf(React.PropTypes.string).isRequired diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForString.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForString.js index 21083885163..e4826f07523 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForString.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForString.js @@ -20,8 +20,6 @@ import React from 'react'; import SimpleInput from './SimpleInput'; -export default class InputForString extends React.Component { - render() { - return <SimpleInput {...this.props} className="input-large" type="text" />; - } +export default function InputForString(props) { + return <SimpleInput {...props} className="input-large" type="text" />; } diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForText.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForText.js index 3a62920746d..36c9498c0d2 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForText.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/InputForText.js @@ -20,7 +20,7 @@ import React from 'react'; import { defaultInputPropTypes } from '../../propTypes'; -export default class InputForText extends React.Component { +export default class InputForText extends React.PureComponent { static propTypes = defaultInputPropTypes; handleInputChange(e) { diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/MultiValueInput.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/MultiValueInput.js index b2fe28e2da5..3e17e9db704 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/MultiValueInput.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/MultiValueInput.js @@ -21,7 +21,7 @@ import React from 'react'; import PrimitiveInput from './PrimitiveInput'; import { getEmptyValue } from '../../utils'; -export default class MultiValueInput extends React.Component { +export default class MultiValueInput extends React.PureComponent { static propTypes = { setting: React.PropTypes.object.isRequired, value: React.PropTypes.array, diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.js index 35ace9d8b47..3f39350f7b6 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/PrimitiveInput.js @@ -37,7 +37,7 @@ const typeMapping = { [types.TYPE_FLOAT]: InputForNumber }; -export default class PrimitiveInput extends React.Component { +export default class PrimitiveInput extends React.PureComponent { static propTypes = { setting: React.PropTypes.object.isRequired, value: React.PropTypes.any, diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/PropertySetInput.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/PropertySetInput.js index 9b958b18514..0c3884b288b 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/PropertySetInput.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/PropertySetInput.js @@ -21,7 +21,7 @@ import React from 'react'; import PrimitiveInput from './PrimitiveInput'; import { getEmptyValue, getUniqueName } from '../../utils'; -export default class PropertySetInput extends React.Component { +export default class PropertySetInput extends React.PureComponent { static propTypes = { setting: React.PropTypes.object.isRequired, value: React.PropTypes.array, diff --git a/server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.js b/server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.js index 31ec32c0360..0b0164407a3 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.js +++ b/server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.js @@ -20,7 +20,7 @@ import React from 'react'; import { defaultInputPropTypes } from '../../propTypes'; -export default class SimpleInput extends React.Component { +export default class SimpleInput extends React.PureComponent { static propTypes = { ...defaultInputPropTypes, value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]), diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js index 02a8c45b79f..05b0b9ca524 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js +++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionApp.js @@ -22,7 +22,7 @@ import GenerateSecretKeyForm from './GenerateSecretKeyForm'; import EncryptionForm from './EncryptionForm'; import { translate } from '../../../helpers/l10n'; -export default class EncryptionApp extends React.Component { +export default class EncryptionApp extends React.PureComponent { static propTypes = { loading: React.PropTypes.bool.isRequired, secretKeyAvailable: React.PropTypes.bool, diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js index 067a846800e..4fed5596a5e 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js +++ b/server/sonar-web/src/main/js/apps/settings/encryption/EncryptionForm.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default class EncryptionForm extends React.Component { +export default class EncryptionForm extends React.PureComponent { static propTypes = { encryptedValue: React.PropTypes.string, encryptValue: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js index e54d0ad6b9b..68e0cb74233 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js +++ b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default class GenerateSecretKeyForm extends React.Component { +export default class GenerateSecretKeyForm extends React.PureComponent { static propTypes = { secretKey: React.PropTypes.string, generateSecretKey: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseChangeForm.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseChangeForm.js index 246ead0856d..e3e443e51b6 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseChangeForm.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseChangeForm.js @@ -21,7 +21,7 @@ import React from 'react'; import LicenseValueView from './LicenseValueView'; import { translate } from '../../../helpers/l10n'; -export default class LicenseChangeForm extends React.Component { +export default class LicenseChangeForm extends React.PureComponent { static propTypes = { license: React.PropTypes.object.isRequired, onChange: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseRow.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseRow.js index 52271392ed6..94f12ae7720 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseRow.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseRow.js @@ -18,21 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import moment from 'moment'; import LicenseStatus from './LicenseStatus'; import LicenseChangeForm from './LicenseChangeForm'; -export default class LicenseRow extends React.Component { +export default class LicenseRow extends React.PureComponent { static propTypes = { license: React.PropTypes.object.isRequired, setLicense: React.PropTypes.func.isRequired }; - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - handleSet(value) { return this.props.setLicense(this.props.license.key, value).catch(() => { /* do nothing */ diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseStatus.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseStatus.js index eaea09253f7..086fb5f4eb0 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicenseStatus.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicenseStatus.js @@ -20,7 +20,7 @@ import React from 'react'; import { isLicenseInvalid } from './licenseUtils'; -export default class LicenseStatus extends React.Component { +export default class LicenseStatus extends React.PureComponent { static propTypes = { license: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesApp.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesApp.js index 924e219a6c0..5a2a95b6544 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesApp.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesApp.js @@ -21,13 +21,11 @@ import React from 'react'; import LicensesAppHeader from './LicensesAppHeader'; import LicensesListContainer from './LicensesListContainer'; -export default class LicensesApp extends React.Component { - render() { - return ( - <div id="licenses-page" className="page page-limited"> - <LicensesAppHeader /> - <LicensesListContainer /> - </div> - ); - } +export default function LicensesApp() { + return ( + <div id="licenses-page" className="page page-limited"> + <LicensesAppHeader /> + <LicensesListContainer /> + </div> + ); } diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesAppHeader.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesAppHeader.js index 6f7f8733a2f..153efb04fa5 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesAppHeader.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesAppHeader.js @@ -20,16 +20,14 @@ import React from 'react'; import { translate } from '../../../helpers/l10n'; -export default class LicensesAppHeader extends React.Component { - render() { - return ( - <header className="page-header"> - <h1 className="page-title">{translate('property.category.licenses')}</h1> - <div - className="page-description" - dangerouslySetInnerHTML={{ __html: translate('property.category.licenses.description') }} - /> - </header> - ); - } +export default function LicensesAppHeader() { + return ( + <header className="page-header"> + <h1 className="page-title">{translate('property.category.licenses')}</h1> + <div + className="page-description" + dangerouslySetInnerHTML={{ __html: translate('property.category.licenses.description') }} + /> + </header> + ); } diff --git a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesList.js b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesList.js index 9b7df9c18e7..afb1efc5c18 100644 --- a/server/sonar-web/src/main/js/apps/settings/licenses/LicensesList.js +++ b/server/sonar-web/src/main/js/apps/settings/licenses/LicensesList.js @@ -18,11 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import LicenseRowContainer from './LicenseRowContainer'; import { translate } from '../../../helpers/l10n'; -export default class LicensesList extends React.Component { +export default class LicensesList extends React.PureComponent { static propTypes = { licenses: React.PropTypes.array.isRequired, fetchLicenses: React.PropTypes.func.isRequired @@ -34,10 +33,6 @@ export default class LicensesList extends React.Component { }); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - render() { return ( <table className="data zebra zebra-hover" style={{ tableLayout: 'fixed' }}> diff --git a/server/sonar-web/src/main/js/apps/settings/serverId/ServerIdApp.js b/server/sonar-web/src/main/js/apps/settings/serverId/ServerIdApp.js index 9a21a86f293..40c7197b3dd 100644 --- a/server/sonar-web/src/main/js/apps/settings/serverId/ServerIdApp.js +++ b/server/sonar-web/src/main/js/apps/settings/serverId/ServerIdApp.js @@ -22,7 +22,7 @@ import { translate } from '../../../helpers/l10n'; import { getServerId, generateServerId } from '../../../api/settings'; import { parseError } from '../../code/utils'; -export default class ServerIdApp extends React.Component { +export default class ServerIdApp extends React.PureComponent { static propTypes = { addGlobalErrorMessage: React.PropTypes.func.isRequired, closeAllGlobalMessages: React.PropTypes.func.isRequired diff --git a/server/sonar-web/src/main/js/apps/system/item-boolean.js b/server/sonar-web/src/main/js/apps/system/item-boolean.js index aff28b869a1..aeac6e88390 100644 --- a/server/sonar-web/src/main/js/apps/system/item-boolean.js +++ b/server/sonar-web/src/main/js/apps/system/item-boolean.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default React.createClass({ +export default class ItemBoolean extends React.PureComponent { render() { if (this.props.value) { return <i className="icon-check" />; @@ -27,4 +27,4 @@ export default React.createClass({ return <i className="icon-delete" />; } } -}); +} diff --git a/server/sonar-web/src/main/js/apps/system/item-log-level.js b/server/sonar-web/src/main/js/apps/system/item-log-level.js index a992307fec0..473213a4870 100644 --- a/server/sonar-web/src/main/js/apps/system/item-log-level.js +++ b/server/sonar-web/src/main/js/apps/system/item-log-level.js @@ -23,17 +23,18 @@ import { translate } from '../../helpers/l10n'; const LOG_LEVELS = ['INFO', 'DEBUG', 'TRACE']; -export default React.createClass({ - getInitialState() { - return { level: this.props.value }; - }, +export default class ItemLogLevel extends React.PureComponent { + constructor(props) { + super(props); + this.state = { level: props.value }; + } - onChange() { + onChange = () => { const newValue = this.refs.select.value; setLogLevel(newValue).then(() => { this.setState({ level: newValue }); }); - }, + }; render() { const options = LOG_LEVELS.map(level => <option key={level} value={level}>{level}</option>); @@ -49,4 +50,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/system/item-object.js b/server/sonar-web/src/main/js/apps/system/item-object.js index c0f0b1919fb..32b81388595 100644 --- a/server/sonar-web/src/main/js/apps/system/item-object.js +++ b/server/sonar-web/src/main/js/apps/system/item-object.js @@ -20,7 +20,7 @@ import React from 'react'; import ItemValue from './item-value'; -export default React.createClass({ +export default class ItemObject extends React.PureComponent { render() { const rows = Object.keys(this.props.value).map(key => { return ( @@ -36,4 +36,4 @@ export default React.createClass({ </table> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/system/item-value.js b/server/sonar-web/src/main/js/apps/system/item-value.js index ac413fe061c..5461aa95e8b 100644 --- a/server/sonar-web/src/main/js/apps/system/item-value.js +++ b/server/sonar-web/src/main/js/apps/system/item-value.js @@ -22,7 +22,7 @@ import ItemBoolean from './item-boolean'; import ItemObject from './item-object'; import ItemLogLevel from './item-log-level'; -export default React.createClass({ +export default class ItemValue extends React.PureComponent { render() { if (this.props.name === 'Logs Level') { return <ItemLogLevel value={this.props.value} />; @@ -42,4 +42,4 @@ export default React.createClass({ } return formattedValue; } -}); +} diff --git a/server/sonar-web/src/main/js/apps/system/main.js b/server/sonar-web/src/main/js/apps/system/main.js index e826c097734..5707ee5604d 100644 --- a/server/sonar-web/src/main/js/apps/system/main.js +++ b/server/sonar-web/src/main/js/apps/system/main.js @@ -36,36 +36,32 @@ const SECTIONS_ORDER = [ 'JvmProperties' ]; -export default React.createClass({ +export default class Main extends React.PureComponent { componentDidMount() { getSystemInfo().then(info => this.setState({ sections: this.parseSections(info) })); - }, + } - parseSections(data) { + parseSections = data => { const sections = Object.keys(data).map(section => { return { name: section, items: this.parseItems(data[section]) }; }); return this.orderSections(sections); - }, + }; - orderSections(sections) { - return sortBy(sections, section => SECTIONS_ORDER.indexOf(section.name)); - }, + orderSections = sections => sortBy(sections, section => SECTIONS_ORDER.indexOf(section.name)); - parseItems(data) { + parseItems = data => { const items = Object.keys(data).map(item => { return { name: item, value: data[item] }; }); return this.orderItems(items); - }, + }; - orderItems(items) { - return sortBy(items, 'name'); - }, + orderItems = items => sortBy(items, 'name'); - handleServerRestart() { + handleServerRestart = () => { new RestartModal().render(); - }, + }; render() { let sections = null; @@ -120,4 +116,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/system/section.js b/server/sonar-web/src/main/js/apps/system/section.js index 1d890c02506..89b90e99c5d 100644 --- a/server/sonar-web/src/main/js/apps/system/section.js +++ b/server/sonar-web/src/main/js/apps/system/section.js @@ -20,7 +20,7 @@ import React from 'react'; import ItemValue from './item-value'; -export default React.createClass({ +export default class Section extends React.PureComponent { render() { const items = this.props.items.map(item => { return ( @@ -46,4 +46,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/apps/update-center/components/UpdateCenterAppContainer.js b/server/sonar-web/src/main/js/apps/update-center/components/UpdateCenterAppContainer.js index 469c5fc7347..4745b919ec2 100644 --- a/server/sonar-web/src/main/js/apps/update-center/components/UpdateCenterAppContainer.js +++ b/server/sonar-web/src/main/js/apps/update-center/components/UpdateCenterAppContainer.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import init from '../init'; import { getSettingValue } from '../../../store/rootReducer'; -class UpdateCenterAppContainer extends React.Component { +class UpdateCenterAppContainer extends React.PureComponent { componentDidMount() { this.stop = init(this.refs.container, this.props.updateCenterActive); } diff --git a/server/sonar-web/src/main/js/apps/users/components/UsersAppContainer.js b/server/sonar-web/src/main/js/apps/users/components/UsersAppContainer.js index 546ff44b7c9..99bdd44584a 100644 --- a/server/sonar-web/src/main/js/apps/users/components/UsersAppContainer.js +++ b/server/sonar-web/src/main/js/apps/users/components/UsersAppContainer.js @@ -22,7 +22,7 @@ import { connect } from 'react-redux'; import init from '../init'; import { getCurrentUser } from '../../../store/rootReducer'; -class UsersAppContainer extends React.Component { +class UsersAppContainer extends React.PureComponent { static propTypes = { currentUser: React.PropTypes.object.isRequired }; diff --git a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js index d11ecbbf0c7..87e242a676d 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js +++ b/server/sonar-web/src/main/js/apps/web-api/components/ResponseExample.js @@ -20,7 +20,7 @@ import React from 'react'; import { fetchResponseExample as fetchResponseExampleApi } from '../../../api/web-api'; -export default class ResponseExample extends React.Component { +export default class ResponseExample extends React.PureComponent { state = {}; componentDidMount() { diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js index 2e66388c3a1..a1e842b1629 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.js @@ -123,7 +123,7 @@ const loadSources = (key: string, from?: number, to?: number): Promise<Array<*>> return getSources(key, from, to); }; -export default class SourceViewerBase extends React.Component { +export default class SourceViewerBase extends React.PureComponent { mounted: boolean; node: HTMLElement; props: Props; diff --git a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerIssueLocations.js b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerIssueLocations.js index 5e2df2d6594..776fad074e1 100644 --- a/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerIssueLocations.js +++ b/server/sonar-web/src/main/js/components/SourceViewer/SourceViewerIssueLocations.js @@ -41,7 +41,7 @@ type State = { locationBlink: boolean }; -export default class SourceViewerIssueLocations extends React.Component { +export default class SourceViewerIssueLocations extends React.PureComponent { fixedNode: HTMLElement; locations: { [string]: HTMLElement }; node: HTMLElement; diff --git a/server/sonar-web/src/main/js/components/charts/LanguageDistribution.js b/server/sonar-web/src/main/js/components/charts/LanguageDistribution.js index aa76423e19c..d6fb2024693 100644 --- a/server/sonar-web/src/main/js/components/charts/LanguageDistribution.js +++ b/server/sonar-web/src/main/js/components/charts/LanguageDistribution.js @@ -19,13 +19,12 @@ */ import { find, sortBy } from 'lodash'; import React from 'react'; -import shallowCompare from 'react-addons-shallow-compare'; import { Histogram } from './histogram'; import { formatMeasure } from '../../helpers/measures'; import { getLanguages } from '../../api/languages'; import { translate } from '../../helpers/l10n'; -export default class LanguageDistribution extends React.Component { +export default class LanguageDistribution extends React.PureComponent { static propTypes = { distribution: React.PropTypes.string.isRequired }; @@ -37,10 +36,6 @@ export default class LanguageDistribution extends React.Component { this.requestLanguages(); } - shouldComponentUpdate(nextProps, nextState) { - return shallowCompare(this, nextProps, nextState); - } - componentWillUnmount() { this.mounted = false; } diff --git a/server/sonar-web/src/main/js/components/charts/treemap-breadcrumbs.js b/server/sonar-web/src/main/js/components/charts/treemap-breadcrumbs.js index 7b06317b39e..aeaab7525c0 100644 --- a/server/sonar-web/src/main/js/components/charts/treemap-breadcrumbs.js +++ b/server/sonar-web/src/main/js/components/charts/treemap-breadcrumbs.js @@ -20,8 +20,8 @@ import React from 'react'; import QualifierIcon from '../shared/QualifierIcon'; -export const TreemapBreadcrumbs = React.createClass({ - propTypes: { +export class TreemapBreadcrumbs extends React.PureComponent { + static propTypes = { breadcrumbs: React.PropTypes.arrayOf( React.PropTypes.shape({ key: React.PropTypes.string.isRequired, @@ -29,27 +29,27 @@ export const TreemapBreadcrumbs = React.createClass({ qualifier: React.PropTypes.string.isRequired }).isRequired ).isRequired - }, + }; - handleItemClick(item, e) { + handleItemClick = (item, e) => { e.preventDefault(); this.props.onRectangleClick(item); - }, + }; - handleReset(e) { + handleReset = e => { e.preventDefault(); this.props.onReset(); - }, + }; - renderHome() { + renderHome = () => { return ( <span className="treemap-breadcrumbs-item"> <a onClick={this.handleReset} className="icon-home" href="#" /> </span> ); - }, + }; - renderBreadcrumbsItems(b) { + renderBreadcrumbsItems = b => { return ( <span key={b.key} className="treemap-breadcrumbs-item" title={b.name}> <i className="icon-chevron-right" /> @@ -57,7 +57,7 @@ export const TreemapBreadcrumbs = React.createClass({ <a onClick={this.handleItemClick.bind(this, b)} href="#">{b.name}</a> </span> ); - }, + }; render() { const breadcrumbs = this.props.breadcrumbs.map(this.renderBreadcrumbsItems); @@ -68,4 +68,4 @@ export const TreemapBreadcrumbs = React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js index d298166d630..2873b55e9ce 100644 --- a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js +++ b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js @@ -22,13 +22,13 @@ import classNames from 'classnames'; type Props = { className?: string, - children: React.Component<*>, + children?: React.Element<*>, isOpen: boolean, offset?: { vertical: number, horizontal: number }, - popup: React.Component<*>, + popup: Object, position: 'bottomleft' | 'bottomright', togglePopup: (?boolean) => void }; diff --git a/server/sonar-web/src/main/js/components/common/SelectListItem.js b/server/sonar-web/src/main/js/components/common/SelectListItem.js index 9d432fd7faf..44dbf517296 100644 --- a/server/sonar-web/src/main/js/components/common/SelectListItem.js +++ b/server/sonar-web/src/main/js/components/common/SelectListItem.js @@ -24,7 +24,7 @@ import Tooltip from '../controls/Tooltip'; type Props = { active?: string, - children?: React.Component<*>, + children?: React.Element<*>, item: string, onSelect?: (string) => void, onHover?: (string) => void, diff --git a/server/sonar-web/src/main/js/components/controls/Checkbox.js b/server/sonar-web/src/main/js/components/controls/Checkbox.js index c81d49b8d8c..5762cff7c6b 100644 --- a/server/sonar-web/src/main/js/components/controls/Checkbox.js +++ b/server/sonar-web/src/main/js/components/controls/Checkbox.js @@ -20,7 +20,7 @@ import React from 'react'; import classNames from 'classnames'; -export default class Checkbox extends React.Component { +export default class Checkbox extends React.PureComponent { static propTypes = { id: React.PropTypes.string, onCheck: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/components/controls/DateInput.js b/server/sonar-web/src/main/js/components/controls/DateInput.js index f4070c12119..45acfbc26eb 100644 --- a/server/sonar-web/src/main/js/components/controls/DateInput.js +++ b/server/sonar-web/src/main/js/components/controls/DateInput.js @@ -23,7 +23,7 @@ import classNames from 'classnames'; import { pick } from 'lodash'; import './styles.css'; -export default class DateInput extends React.Component { +export default class DateInput extends React.PureComponent { static propTypes = { className: React.PropTypes.string, value: React.PropTypes.string, diff --git a/server/sonar-web/src/main/js/components/controls/Favorite.js b/server/sonar-web/src/main/js/components/controls/Favorite.js index 56f9c41dc12..f783d24b666 100644 --- a/server/sonar-web/src/main/js/components/controls/Favorite.js +++ b/server/sonar-web/src/main/js/components/controls/Favorite.js @@ -21,7 +21,7 @@ import React from 'react'; import FavoriteBase from './FavoriteBase'; import { addFavorite, removeFavorite } from '../../api/favorites'; -export default class Favorite extends React.Component { +export default class Favorite extends React.PureComponent { static propTypes = { favorite: React.PropTypes.bool.isRequired, component: React.PropTypes.string.isRequired, diff --git a/server/sonar-web/src/main/js/components/controls/FavoriteBase.js b/server/sonar-web/src/main/js/components/controls/FavoriteBase.js index 17be742c604..8518e646fcb 100644 --- a/server/sonar-web/src/main/js/components/controls/FavoriteBase.js +++ b/server/sonar-web/src/main/js/components/controls/FavoriteBase.js @@ -20,7 +20,7 @@ import React from 'react'; import classNames from 'classnames'; -export default class FavoriteBase extends React.Component { +export default class FavoriteBase extends React.PureComponent { static propTypes = { favorite: React.PropTypes.bool.isRequired, addFavorite: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.js b/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.js index 880a65d7552..f20f26f8967 100644 --- a/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.js +++ b/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.js @@ -20,7 +20,7 @@ import React from 'react'; import classNames from 'classnames'; -export default class FavoriteBaseStateless extends React.Component { +export default class FavoriteBaseStateless extends React.PureComponent { static propTypes = { favorite: React.PropTypes.bool.isRequired, addFavorite: React.PropTypes.func.isRequired, diff --git a/server/sonar-web/src/main/js/components/controls/FavoriteIssueFilter.js b/server/sonar-web/src/main/js/components/controls/FavoriteIssueFilter.js index 21711b2a40a..2cfaf29aa8a 100644 --- a/server/sonar-web/src/main/js/components/controls/FavoriteIssueFilter.js +++ b/server/sonar-web/src/main/js/components/controls/FavoriteIssueFilter.js @@ -21,7 +21,7 @@ import React from 'react'; import FavoriteBase from './FavoriteBase'; import { toggleIssueFilter } from '../../api/issue-filters'; -export default class FavoriteIssueFilter extends React.Component { +export default class FavoriteIssueFilter extends React.PureComponent { static propTypes = { favorite: React.PropTypes.bool.isRequired, filter: React.PropTypes.shape({ diff --git a/server/sonar-web/src/main/js/components/controls/GlobalMessages.js b/server/sonar-web/src/main/js/components/controls/GlobalMessages.js index 7b0bc7671f6..cad1d5df977 100644 --- a/server/sonar-web/src/main/js/components/controls/GlobalMessages.js +++ b/server/sonar-web/src/main/js/components/controls/GlobalMessages.js @@ -21,7 +21,7 @@ import React from 'react'; import classNames from 'classnames'; import { ERROR, SUCCESS } from '../../store/globalMessages/duck'; -export default class GlobalMessages extends React.Component { +export default class GlobalMessages extends React.PureComponent { static propTypes = { messages: React.PropTypes.arrayOf( React.PropTypes.shape({ diff --git a/server/sonar-web/src/main/js/components/controls/RadioToggle.js b/server/sonar-web/src/main/js/components/controls/RadioToggle.js index a0617262651..8725c67a1b3 100644 --- a/server/sonar-web/src/main/js/components/controls/RadioToggle.js +++ b/server/sonar-web/src/main/js/components/controls/RadioToggle.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default class RadioToggle extends React.Component { +export default class RadioToggle extends React.PureComponent { static propTypes = { value: React.PropTypes.string, options: React.PropTypes.arrayOf( diff --git a/server/sonar-web/src/main/js/components/controls/Toggle.js b/server/sonar-web/src/main/js/components/controls/Toggle.js index 30a6c121585..870ed5220ec 100644 --- a/server/sonar-web/src/main/js/components/controls/Toggle.js +++ b/server/sonar-web/src/main/js/components/controls/Toggle.js @@ -21,7 +21,7 @@ import React from 'react'; import classNames from 'classnames'; import './styles.css'; -export default class Toggle extends React.Component { +export default class Toggle extends React.PureComponent { static propTypes = { value: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.bool]).isRequired, name: React.PropTypes.string, diff --git a/server/sonar-web/src/main/js/components/layout/Page.js b/server/sonar-web/src/main/js/components/layout/Page.js index a8adef56e19..4ae98a6918f 100644 --- a/server/sonar-web/src/main/js/components/layout/Page.js +++ b/server/sonar-web/src/main/js/components/layout/Page.js @@ -33,10 +33,10 @@ const styles = css({ flexGrow: 1 }); -const Page = ({ className, children, ...other }: Props) => ( - <div className={styles + (className ? ` ${className}` : '')} {...other}> - {children} - </div> -); - -export default Page; +export default function Page({ className, children, ...other }: Props) { + return ( + <div className={styles + (className ? ` ${className}` : '')} {...other}> + {children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/layout/PageFilters.js b/server/sonar-web/src/main/js/components/layout/PageFilters.js index f969366de69..d5f181ffc35 100644 --- a/server/sonar-web/src/main/js/components/layout/PageFilters.js +++ b/server/sonar-web/src/main/js/components/layout/PageFilters.js @@ -25,10 +25,10 @@ type Props = { children?: React.Element<*> }; -const PageSide = (props: Props) => ( - <div className={css({ width: 260, padding: 20 })}> - {props.children} - </div> -); - -export default PageSide; +export default function PageSide(props: Props) { + return ( + <div className={css({ width: 260, padding: 20 })}> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/layout/PageMain.js b/server/sonar-web/src/main/js/components/layout/PageMain.js index 6195a1f651a..85a63058139 100644 --- a/server/sonar-web/src/main/js/components/layout/PageMain.js +++ b/server/sonar-web/src/main/js/components/layout/PageMain.js @@ -25,10 +25,10 @@ type Props = { children?: React.Element<*> }; -const PageMain = (props: Props) => ( - <div className={css({ flexGrow: 1, minWidth: 740, padding: 20 })}> - {props.children} - </div> -); - -export default PageMain; +export default function PageMain(props: Props) { + return ( + <div className={css({ flexGrow: 1, minWidth: 740, padding: 20 })}> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/layout/PageMainInner.js b/server/sonar-web/src/main/js/components/layout/PageMainInner.js index 41beed6518f..f4c07cd9c41 100644 --- a/server/sonar-web/src/main/js/components/layout/PageMainInner.js +++ b/server/sonar-web/src/main/js/components/layout/PageMainInner.js @@ -25,10 +25,10 @@ type Props = { children?: React.Element<*> }; -const PageMainInner = (props: Props) => ( - <div className={css({ minWidth: 740, maxWidth: 980 })}> - {props.children} - </div> -); - -export default PageMainInner; +export default function PageMainInner(props: Props) { + return ( + <div className={css({ minWidth: 740, maxWidth: 980 })}> + {props.children} + </div> + ); +} diff --git a/server/sonar-web/src/main/js/components/layout/PageSide.js b/server/sonar-web/src/main/js/components/layout/PageSide.js index 0488fbfceb9..24d810075ca 100644 --- a/server/sonar-web/src/main/js/components/layout/PageSide.js +++ b/server/sonar-web/src/main/js/components/layout/PageSide.js @@ -60,14 +60,14 @@ const sideInnerStyles = css( media('(max-width: 1320px)', { marginLeft: 0 }) ); -const PageSide = (props: Props) => ( - <div className={sideStyles}> - <div className={sideStickyStyles} style={{ top: props.top || 30 }}> - <div className={sideInnerStyles}> - {props.children} +export default function PageSide(props: Props) { + return ( + <div className={sideStyles}> + <div className={sideStickyStyles} style={{ top: props.top || 30 }}> + <div className={sideInnerStyles}> + {props.children} + </div> </div> </div> - </div> -); - -export default PageSide; + ); +} diff --git a/server/sonar-web/src/main/js/components/mixins/tooltips-mixin.js b/server/sonar-web/src/main/js/components/mixins/tooltips-mixin.js index 06bb959482f..5c2eccfadd9 100644 --- a/server/sonar-web/src/main/js/components/mixins/tooltips-mixin.js +++ b/server/sonar-web/src/main/js/components/mixins/tooltips-mixin.js @@ -61,24 +61,24 @@ export const TooltipsMixin = { } }; -export const TooltipsContainer = React.createClass({ +export class TooltipsContainer extends React.PureComponent { componentDidMount() { this.initTooltips(); - }, + } componentWillUpdate() { this.destroyTooltips(); - }, + } componentDidUpdate() { this.initTooltips(); - }, + } componentWillUnmount() { this.destroyTooltips(); - }, + } - initTooltips() { + initTooltips = () => { if ($.fn && $.fn.tooltip) { const options = Object.assign( { container: 'body', placement: 'bottom', html: true }, @@ -86,21 +86,21 @@ export const TooltipsContainer = React.createClass({ ); $('[data-toggle="tooltip"]', ReactDOM.findDOMNode(this)).tooltip(options); } - }, + }; - hideTooltips() { + hideTooltips = () => { if ($.fn && $.fn.tooltip) { $('[data-toggle="tooltip"]', ReactDOM.findDOMNode(this)).tooltip('hide'); } - }, + }; - destroyTooltips() { + destroyTooltips = () => { if ($.fn && $.fn.tooltip) { $('[data-toggle="tooltip"]', ReactDOM.findDOMNode(this)).tooltip('destroy'); } - }, + }; render() { return this.props.children; } -}); +} diff --git a/server/sonar-web/src/main/js/components/select-list/controls.js b/server/sonar-web/src/main/js/components/select-list/controls.js index 9ed3851a393..11a87067e9c 100644 --- a/server/sonar-web/src/main/js/components/select-list/controls.js +++ b/server/sonar-web/src/main/js/components/select-list/controls.js @@ -22,17 +22,17 @@ import { debounce } from 'lodash'; import RadioToggle from '../controls/RadioToggle'; import { translate } from '../../helpers/l10n'; -export default React.createClass({ +export default class Controls extends React.PureComponent { componentWillMount() { this.search = debounce(this.search, 100); - }, + } - search() { + search = () => { const query = this.refs.search.value; this.props.search(query); - }, + }; - onCheck(value) { + onCheck = value => { switch (value) { case 'selected': this.props.loadSelected(); @@ -43,7 +43,7 @@ export default React.createClass({ default: this.props.loadAll(); } - }, + }; render() { const selectionOptions = [ @@ -74,4 +74,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/select-list/footer.js b/server/sonar-web/src/main/js/components/select-list/footer.js index a3c7e89a70e..01c050650b9 100644 --- a/server/sonar-web/src/main/js/components/select-list/footer.js +++ b/server/sonar-web/src/main/js/components/select-list/footer.js @@ -19,25 +19,25 @@ */ import React from 'react'; -export default React.createClass({ - propTypes: { +export default class Footer extends React.PureComponent { + static propTypes = { count: React.PropTypes.number.isRequired, total: React.PropTypes.number.isRequired, loadMore: React.PropTypes.func.isRequired - }, + }; - loadMore(e) { + loadMore = e => { e.preventDefault(); this.props.loadMore(); - }, + }; - renderLoadMoreLink() { + renderLoadMoreLink = () => { const hasMore = this.props.total > this.props.count; if (!hasMore) { return null; } return <a onClick={this.loadMore} className="spacer-left" href="#">show more</a>; - }, + }; render() { return ( @@ -47,4 +47,4 @@ export default React.createClass({ </footer> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/select-list/item.js b/server/sonar-web/src/main/js/components/select-list/item.js index b7e1e49fb39..ecd5442c927 100644 --- a/server/sonar-web/src/main/js/components/select-list/item.js +++ b/server/sonar-web/src/main/js/components/select-list/item.js @@ -20,21 +20,21 @@ import React from 'react'; import Checkbox from '../controls/Checkbox'; -export default React.createClass({ - propTypes: { +export default class Item extends React.PureComponent { + static propTypes = { item: React.PropTypes.any.isRequired, renderItem: React.PropTypes.func.isRequired, selectItem: React.PropTypes.func.isRequired, deselectItem: React.PropTypes.func.isRequired - }, + }; - onCheck(checked) { + onCheck = checked => { if (checked) { this.props.selectItem(this.props.item); } else { this.props.deselectItem(this.props.item); } - }, + }; render() { const renderedItem = this.props.renderItem(this.props.item); @@ -50,4 +50,4 @@ export default React.createClass({ </li> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/select-list/list.js b/server/sonar-web/src/main/js/components/select-list/list.js index dbae011c81e..22462d40ee5 100644 --- a/server/sonar-web/src/main/js/components/select-list/list.js +++ b/server/sonar-web/src/main/js/components/select-list/list.js @@ -20,14 +20,14 @@ import React from 'react'; import Item from './item'; -export default React.createClass({ - propTypes: { +export default class List extends React.PureComponent { + static propTypes = { items: React.PropTypes.array.isRequired, renderItem: React.PropTypes.func.isRequired, getItemKey: React.PropTypes.func.isRequired, selectItem: React.PropTypes.func.isRequired, deselectItem: React.PropTypes.func.isRequired - }, + }; render() { const renderedItems = this.props.items.map(item => { @@ -36,4 +36,4 @@ export default React.createClass({ }); return <ul>{renderedItems}</ul>; } -}); +} diff --git a/server/sonar-web/src/main/js/components/select-list/main.js b/server/sonar-web/src/main/js/components/select-list/main.js index afe5a64bc95..64902383add 100644 --- a/server/sonar-web/src/main/js/components/select-list/main.js +++ b/server/sonar-web/src/main/js/components/select-list/main.js @@ -22,24 +22,27 @@ import Controls from './controls'; import List from './list'; import Footer from './footer'; -export default React.createClass({ - propTypes: { +export default class Main extends React.PureComponent { + static propTypes = { loadItems: React.PropTypes.func.isRequired, renderItem: React.PropTypes.func.isRequired, getItemKey: React.PropTypes.func.isRequired, selectItem: React.PropTypes.func.isRequired, deselectItem: React.PropTypes.func.isRequired - }, + }; - getInitialState() { - return { items: [], total: 0, selection: 'selected', query: null }; - }, + state = { + items: [], + total: 0, + selection: 'selected', + query: null + }; componentDidMount() { this.loadItems(); - }, + } - loadItems() { + loadItems = () => { const options = { selection: this.state.selection, query: this.state.query, @@ -48,9 +51,9 @@ export default React.createClass({ this.props.loadItems(options, (items, paging) => { this.setState({ items, total: paging.total, page: paging.pageIndex }); }); - }, + }; - loadMoreItems() { + loadMoreItems = () => { const options = { selection: this.state.selection, query: this.state.query, @@ -60,23 +63,23 @@ export default React.createClass({ const newItems = [].concat(this.state.items, items); this.setState({ items: newItems, total: paging.total, page: paging.pageIndex }); }); - }, + }; - loadSelected() { + loadSelected = () => { this.setState({ selection: 'selected', query: null }, this.loadItems); - }, + }; - loadDeselected() { + loadDeselected = () => { this.setState({ selection: 'deselected', query: null }, this.loadItems); - }, + }; - loadAll() { + loadAll = () => { this.setState({ selection: 'all', query: null }, this.loadItems); - }, + }; - search(query) { + search = query => { this.setState({ query }, this.loadItems); - }, + }; render() { return ( @@ -102,4 +105,4 @@ export default React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/shared/Organization.js b/server/sonar-web/src/main/js/components/shared/Organization.js index ac723440c9c..aae52f11127 100644 --- a/server/sonar-web/src/main/js/components/shared/Organization.js +++ b/server/sonar-web/src/main/js/components/shared/Organization.js @@ -35,7 +35,7 @@ type Props = { shouldBeDisplayed: boolean }; -class Organization extends React.Component { +class Organization extends React.PureComponent { props: Props; static defaultProps = { diff --git a/server/sonar-web/src/main/js/components/shared/WithStore.js b/server/sonar-web/src/main/js/components/shared/WithStore.js index 2c702a53940..5d8a41939cf 100644 --- a/server/sonar-web/src/main/js/components/shared/WithStore.js +++ b/server/sonar-web/src/main/js/components/shared/WithStore.js @@ -21,15 +21,19 @@ import React from 'react'; import getStore from '../../app/utils/getStore'; -export default class WithStore extends React.Component { +type Props = { + children: React.Element<*> +}; + +export default class WithStore extends React.PureComponent { + props: Props; store: {}; - props: { children: Object }; static childContextTypes = { store: React.PropTypes.object }; - constructor(props: { children: Object }) { + constructor(props: Props) { super(props); this.store = getStore(); } diff --git a/server/sonar-web/src/main/js/components/shared/complexity-distribution.js b/server/sonar-web/src/main/js/components/shared/complexity-distribution.js index 086a73b99d7..6c7b49221a5 100644 --- a/server/sonar-web/src/main/js/components/shared/complexity-distribution.js +++ b/server/sonar-web/src/main/js/components/shared/complexity-distribution.js @@ -24,13 +24,13 @@ import { translateWithParameters } from '../../helpers/l10n'; const HEIGHT = 80; -export const ComplexityDistribution = React.createClass({ - propTypes: { +export class ComplexityDistribution extends React.PureComponent { + static propTypes = { distribution: React.PropTypes.string.isRequired, of: React.PropTypes.string.isRequired - }, + }; - renderBarChart() { + renderBarChart = () => { const data = this.props.distribution.split(';').map((point, index) => { const tokens = point.split('='); const y = parseInt(tokens[1], 10); @@ -57,7 +57,7 @@ export const ComplexityDistribution = React.createClass({ padding={[25, 10, 25, 10]} /> ); - }, + }; render() { // TODO remove inline styling @@ -69,4 +69,4 @@ export const ComplexityDistribution = React.createClass({ </div> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/shared/drilldown-link.js b/server/sonar-web/src/main/js/components/shared/drilldown-link.js index a4b82a95f5d..fddfa758989 100644 --- a/server/sonar-web/src/main/js/components/shared/drilldown-link.js +++ b/server/sonar-web/src/main/js/components/shared/drilldown-link.js @@ -47,12 +47,12 @@ const ISSUE_MEASURES = [ 'new_vulnerabilities' ]; -export const DrilldownLink = React.createClass({ - isIssueMeasure() { +export class DrilldownLink extends React.PureComponent { + isIssueMeasure = () => { return ISSUE_MEASURES.indexOf(this.props.metric) !== -1; - }, + }; - propsToIssueParams() { + propsToIssueParams = () => { const params = {}; if (this.props.periodDate) { @@ -108,13 +108,13 @@ export const DrilldownLink = React.createClass({ Object.assign(params, { resolved: 'false' }); } return params; - }, + }; - renderIssuesLink() { + renderIssuesLink = () => { const url = getComponentIssuesUrl(this.props.component, this.propsToIssueParams()); return <Link to={url} className={this.props.className}>{this.props.children}</Link>; - }, + }; render() { if (this.isIssueMeasure()) { @@ -124,4 +124,4 @@ export const DrilldownLink = React.createClass({ const url = getComponentDrilldownUrl(this.props.component, this.props.metric); return <Link to={url} className={this.props.className}>{this.props.children}</Link>; } -}); +} diff --git a/server/sonar-web/src/main/js/components/shared/pending-icon.js b/server/sonar-web/src/main/js/components/shared/pending-icon.js index a64d9f4e915..333f901965d 100644 --- a/server/sonar-web/src/main/js/components/shared/pending-icon.js +++ b/server/sonar-web/src/main/js/components/shared/pending-icon.js @@ -19,7 +19,7 @@ */ import React from 'react'; -export default React.createClass({ +export default class PendingIcon extends React.PureComponent { render() { /* eslint max-len: 0 */ return ( @@ -32,4 +32,4 @@ export default React.createClass({ </svg> ); } -}); +} diff --git a/server/sonar-web/src/main/js/components/shared/pin-icon.js b/server/sonar-web/src/main/js/components/shared/pin-icon.js index 87b28754bdb..50b1c850daa 100644 --- a/server/sonar-web/src/main/js/components/shared/pin-icon.js +++ b/server/sonar-web/src/main/js/components/shared/pin-icon.js @@ -20,13 +20,13 @@ /* eslint max-len: 0 */ import React from 'react'; -const PinIcon = () => ( - <svg width="9" height="14" viewBox="0 0 288 448"> - <path - fill="#236a97" - d="M120 216v-112q0-3.5-2.25-5.75t-5.75-2.25-5.75 2.25-2.25 5.75v112q0 3.5 2.25 5.75t5.75 2.25 5.75-2.25 2.25-5.75zM288 304q0 6.5-4.75 11.25t-11.25 4.75h-107.25l-12.75 120.75q-0.5 3-2.625 5.125t-5.125 2.125h-0.25q-6.75 0-8-6.75l-19-121.25h-101q-6.5 0-11.25-4.75t-4.75-11.25q0-30.75 19.625-55.375t44.375-24.625v-128q-13 0-22.5-9.5t-9.5-22.5 9.5-22.5 22.5-9.5h160q13 0 22.5 9.5t9.5 22.5-9.5 22.5-22.5 9.5v128q24.75 0 44.375 24.625t19.625 55.375z" - /> - </svg> -); - -export default PinIcon; +export default function PinIcon() { + return ( + <svg width="9" height="14" viewBox="0 0 288 448"> + <path + fill="#236a97" + d="M120 216v-112q0-3.5-2.25-5.75t-5.75-2.25-5.75 2.25-2.25 5.75v112q0 3.5 2.25 5.75t5.75 2.25 5.75-2.25 2.25-5.75zM288 304q0 6.5-4.75 11.25t-11.25 4.75h-107.25l-12.75 120.75q-0.5 3-2.625 5.125t-5.125 2.125h-0.25q-6.75 0-8-6.75l-19-121.25h-101q-6.5 0-11.25-4.75t-4.75-11.25q0-30.75 19.625-55.375t44.375-24.625v-128q-13 0-22.5-9.5t-9.5-22.5 9.5-22.5 22.5-9.5h160q13 0 22.5 9.5t9.5 22.5-9.5 22.5-22.5 9.5v128q24.75 0 44.375 24.625t19.625 55.375z" + /> + </svg> + ); +} diff --git a/server/sonar-web/src/main/js/components/ui/Avatar.js b/server/sonar-web/src/main/js/components/ui/Avatar.js index dea1f233288..b17ce477592 100644 --- a/server/sonar-web/src/main/js/components/ui/Avatar.js +++ b/server/sonar-web/src/main/js/components/ui/Avatar.js @@ -23,7 +23,7 @@ import md5 from 'blueimp-md5'; import classNames from 'classnames'; import { getSettingValue } from '../../store/rootReducer'; -class Avatar extends React.Component { +class Avatar extends React.PureComponent { static propTypes = { enableGravatar: React.PropTypes.bool.isRequired, gravatarServerUrl: React.PropTypes.string.isRequired, diff --git a/server/sonar-web/src/main/js/components/ui/BugIcon.js b/server/sonar-web/src/main/js/components/ui/BugIcon.js index ce8a031654c..ada2170bc5b 100644 --- a/server/sonar-web/src/main/js/components/ui/BugIcon.js +++ b/server/sonar-web/src/main/js/components/ui/BugIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class BugIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> - <path - style={{ fill: 'currentColor' }} - d="M11 9h1.3l.5.8.8-.5-.8-1.3H11v-.3l2-2.3V3h-1v2l-1 1.2V5c-.1-.8-.7-1.5-1.4-1.9L11 1.8l-.7-.7-1.8 1.6-1.8-1.6-.7.7 1.5 1.3C6.7 3.5 6.1 4.2 6 5v1.1L5 5V3H4v2.3l2 2.3V8H4.2l-.7 1.2.8.5.4-.7H6v.3l-2 1.9V14h1v-2.4l1-1C6 12 7.1 13 8.4 13h.8c.7 0 1.4-.3 1.8-.9.3-.4.3-.9.2-1.4l.9.9V14h1v-2.8l-2-1.9V9zm-2 2H8V6h1v5z" - /> - </svg> - ); - } +export default function BugIcon() { + /* eslint-disable max-len */ + return ( + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> + <path + style={{ fill: 'currentColor' }} + d="M11 9h1.3l.5.8.8-.5-.8-1.3H11v-.3l2-2.3V3h-1v2l-1 1.2V5c-.1-.8-.7-1.5-1.4-1.9L11 1.8l-.7-.7-1.8 1.6-1.8-1.6-.7.7 1.5 1.3C6.7 3.5 6.1 4.2 6 5v1.1L5 5V3H4v2.3l2 2.3V8H4.2l-.7 1.2.8.5.4-.7H6v.3l-2 1.9V14h1v-2.4l1-1C6 12 7.1 13 8.4 13h.8c.7 0 1.4-.3 1.8-.9.3-.4.3-.9.2-1.4l.9.9V14h1v-2.8l-2-1.9V9zm-2 2H8V6h1v5z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/components/ui/BugTrackerIcon.js b/server/sonar-web/src/main/js/components/ui/BugTrackerIcon.js index 011d49db7c4..64f2c5ee858 100644 --- a/server/sonar-web/src/main/js/components/ui/BugTrackerIcon.js +++ b/server/sonar-web/src/main/js/components/ui/BugTrackerIcon.js @@ -20,24 +20,22 @@ // @flow import React from 'react'; -export default class BugTrackerIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" width="14" height="14"> - <g transform="matrix(1,0,0,1,0,1)"> - <path - style={{ - fill: 'none', - stroke: 'currentColor', - strokeWidth: 2, - strokeLinecap: 'round', - strokeMiterlimit: '10' - }} - d="M12 9h-2L8 5 6.5 9.5l-2-6L3 9H1" - /> - </g> - </svg> - ); - } +export default function BugTrackerIcon() { + /* eslint-disable max-len */ + return ( + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" width="14" height="14"> + <g transform="matrix(1,0,0,1,0,1)"> + <path + style={{ + fill: 'none', + stroke: 'currentColor', + strokeWidth: 2, + strokeLinecap: 'round', + strokeMiterlimit: '10' + }} + d="M12 9h-2L8 5 6.5 9.5l-2-6L3 9H1" + /> + </g> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/components/ui/CodeSmellIcon.js b/server/sonar-web/src/main/js/components/ui/CodeSmellIcon.js index 1dcf9e32b77..9673f988b24 100644 --- a/server/sonar-web/src/main/js/components/ui/CodeSmellIcon.js +++ b/server/sonar-web/src/main/js/components/ui/CodeSmellIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class CodeSmellIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> - <path - style={{ fill: 'currentColor' }} - d="M8 2C4.7 2 2 4.7 2 8s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zm-.5 5.5h.9v.9h-.9v-.9zm-3.8.2c-.1 0-.2-.1-.2-.2 0-.4.1-1.2.6-2S5.3 4.2 5.6 4c.2 0 .3 0 .3.1l1.3 2.3c0 .1 0 .2-.1.2-.1.2-.2.3-.3.5-.1.2-.2.4-.2.5 0 .1-.1.2-.2.2l-2.7-.1zM9.9 12c-.3.2-1.1.5-2 .5-.9 0-1.7-.3-2-.5-.1 0-.1-.2-.1-.3l1.3-2.3c0-.1.1-.1.2-.1.2.1.3.1.5.1s.4 0 .5-.1c.1 0 .2 0 .2.1l1.3 2.3c.2.2.2.3.1.3zm2.5-4.1L9.7 8c-.1 0-.2-.1-.2-.2 0-.2-.1-.4-.2-.5 0-.1-.2-.3-.3-.4-.1 0-.1-.1-.1-.2l1.3-2.3c.1-.1.2-.1.3-.1.3.2 1 .7 1.5 1.5s.6 1.6.6 2c0 0-.1.1-.2.1z" - /> - </svg> - ); - } +export default function CodeSmellIcon() { + /* eslint-disable max-len */ + return ( + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> + <path + style={{ fill: 'currentColor' }} + d="M8 2C4.7 2 2 4.7 2 8s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zm-.5 5.5h.9v.9h-.9v-.9zm-3.8.2c-.1 0-.2-.1-.2-.2 0-.4.1-1.2.6-2S5.3 4.2 5.6 4c.2 0 .3 0 .3.1l1.3 2.3c0 .1 0 .2-.1.2-.1.2-.2.3-.3.5-.1.2-.2.4-.2.5 0 .1-.1.2-.2.2l-2.7-.1zM9.9 12c-.3.2-1.1.5-2 .5-.9 0-1.7-.3-2-.5-.1 0-.1-.2-.1-.3l1.3-2.3c0-.1.1-.1.2-.1.2.1.3.1.5.1s.4 0 .5-.1c.1 0 .2 0 .2.1l1.3 2.3c.2.2.2.3.1.3zm2.5-4.1L9.7 8c-.1 0-.2-.1-.2-.2 0-.2-.1-.4-.2-.5 0-.1-.2-.3-.3-.4-.1 0-.1-.1-.1-.2l1.3-2.3c.1-.1.2-.1.3-.1.3.2 1 .7 1.5 1.5s.6 1.6.6 2c0 0-.1.1-.2.1z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/components/ui/CoverageRating.js b/server/sonar-web/src/main/js/components/ui/CoverageRating.js index 8546484cd2c..b2edbd48c38 100644 --- a/server/sonar-web/src/main/js/components/ui/CoverageRating.js +++ b/server/sonar-web/src/main/js/components/ui/CoverageRating.js @@ -33,7 +33,7 @@ const SIZE_TO_THICKNESS_MAPPING = { big: 3 }; -export default class CoverageRating extends React.Component { +export default class CoverageRating extends React.PureComponent { props: { value: number | string, size?: 'small' | 'normal' | 'big', diff --git a/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js b/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js index 7132052d4b6..d9a4e68fb6a 100644 --- a/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js +++ b/server/sonar-web/src/main/js/components/ui/DuplicationsRating.js @@ -23,7 +23,7 @@ import classNames from 'classnames'; import { inRange } from 'lodash'; import './DuplicationsRating.css'; -export default class DuplicationsRating extends React.Component { +export default class DuplicationsRating extends React.PureComponent { props: { value: number, size?: 'small' | 'normal' | 'big', diff --git a/server/sonar-web/src/main/js/components/ui/FormattedDate.js b/server/sonar-web/src/main/js/components/ui/FormattedDate.js index eb4129919b2..3c67005b7bf 100644 --- a/server/sonar-web/src/main/js/components/ui/FormattedDate.js +++ b/server/sonar-web/src/main/js/components/ui/FormattedDate.js @@ -21,7 +21,7 @@ import React from 'react'; import moment from 'moment'; -export default class FormattedDate extends React.Component { +export default class FormattedDate extends React.PureComponent { props: { date: string | number, format?: string, diff --git a/server/sonar-web/src/main/js/components/ui/Level.js b/server/sonar-web/src/main/js/components/ui/Level.js index 9a00eaf5337..35648bfdc1b 100644 --- a/server/sonar-web/src/main/js/components/ui/Level.js +++ b/server/sonar-web/src/main/js/components/ui/Level.js @@ -22,7 +22,7 @@ import classNames from 'classnames'; import { formatMeasure } from '../../helpers/measures'; import './Level.css'; -export default class Level extends React.Component { +export default class Level extends React.PureComponent { static propTypes = { level: React.PropTypes.oneOf(['ERROR', 'WARN', 'OK']).isRequired, small: React.PropTypes.bool, diff --git a/server/sonar-web/src/main/js/components/ui/OrganizationIcon.js b/server/sonar-web/src/main/js/components/ui/OrganizationIcon.js index 4a7435d438a..4b0de907c2c 100644 --- a/server/sonar-web/src/main/js/components/ui/OrganizationIcon.js +++ b/server/sonar-web/src/main/js/components/ui/OrganizationIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class OrganizationIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> - <path - style={{ fill: '#4b9fd5' }} - d="M13.5 6c-.4 0-.7.1-1.1.2L11 4.8v-.3C11 3.1 9.9 2 8.5 2S6 3.1 6 4.5v.2L4.5 6.2c-.3-.1-.7-.2-1-.2C2.1 6 1 7.1 1 8.5S2.1 11 3.5 11 6 9.9 6 8.5c0-.7-.3-1.3-.7-1.7l1-1c.4.6 1 1 1.7 1.1V9c-1.1.2-2 1.2-2 2.4C6 12.9 7.1 14 8.5 14s2.5-1.1 2.5-2.5c0-1.2-.9-2.2-2-2.4V6.9c.7-.1 1.2-.5 1.6-1.1l1 1c-.4.4-.6 1-.6 1.6 0 1.4 1.1 2.5 2.5 2.5s2.5-1 2.5-2.4S14.9 6 13.5 6zm-10 4C2.7 10 2 9.3 2 8.5S2.7 7 3.5 7 5 7.7 5 8.5 4.3 10 3.5 10zm6.5 1.5c0 .8-.7 1.5-1.5 1.5S7 12.3 7 11.5 7.7 10 8.5 10s1.5.7 1.5 1.5zM8.5 6C7.7 6 7 5.3 7 4.5S7.7 3 8.5 3s1.5.7 1.5 1.5S9.3 6 8.5 6zm5 4c-.8 0-1.5-.7-1.5-1.5S12.7 7 13.5 7s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z" - /> - </svg> - ); - } +export default function OrganizationIcon() { + /* eslint-disable max-len */ + return ( + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> + <path + style={{ fill: '#4b9fd5' }} + d="M13.5 6c-.4 0-.7.1-1.1.2L11 4.8v-.3C11 3.1 9.9 2 8.5 2S6 3.1 6 4.5v.2L4.5 6.2c-.3-.1-.7-.2-1-.2C2.1 6 1 7.1 1 8.5S2.1 11 3.5 11 6 9.9 6 8.5c0-.7-.3-1.3-.7-1.7l1-1c.4.6 1 1 1.7 1.1V9c-1.1.2-2 1.2-2 2.4C6 12.9 7.1 14 8.5 14s2.5-1.1 2.5-2.5c0-1.2-.9-2.2-2-2.4V6.9c.7-.1 1.2-.5 1.6-1.1l1 1c-.4.4-.6 1-.6 1.6 0 1.4 1.1 2.5 2.5 2.5s2.5-1 2.5-2.4S14.9 6 13.5 6zm-10 4C2.7 10 2 9.3 2 8.5S2.7 7 3.5 7 5 7.7 5 8.5 4.3 10 3.5 10zm6.5 1.5c0 .8-.7 1.5-1.5 1.5S7 12.3 7 11.5 7.7 10 8.5 10s1.5.7 1.5 1.5zM8.5 6C7.7 6 7 5.3 7 4.5S7.7 3 8.5 3s1.5.7 1.5 1.5S9.3 6 8.5 6zm5 4c-.8 0-1.5-.7-1.5-1.5S12.7 7 13.5 7s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/components/ui/OrganizationLink.js b/server/sonar-web/src/main/js/components/ui/OrganizationLink.js index 280338edd3c..9e2c14306e9 100644 --- a/server/sonar-web/src/main/js/components/ui/OrganizationLink.js +++ b/server/sonar-web/src/main/js/components/ui/OrganizationLink.js @@ -21,17 +21,15 @@ import React from 'react'; import { Link } from 'react-router'; -export default class OrganizationLink extends React.Component { +export default function OrganizationLink( props: { - children?: Object, + children?: React.Element<*>, organization: { key: string } - }; - - render() { - const { children, organization, ...other } = this.props; - - return <Link to={`/organizations/${organization.key}`} {...other}>{children}</Link>; } +) { + const { children, organization, ...other } = props; + + return <Link to={`/organizations/${organization.key}`} {...other}>{children}</Link>; } diff --git a/server/sonar-web/src/main/js/components/ui/Rating.js b/server/sonar-web/src/main/js/components/ui/Rating.js index c53eabe9d0f..87904d41041 100644 --- a/server/sonar-web/src/main/js/components/ui/Rating.js +++ b/server/sonar-web/src/main/js/components/ui/Rating.js @@ -22,7 +22,7 @@ import classNames from 'classnames'; import { formatMeasure } from '../../helpers/measures'; import './Rating.css'; -export default class Rating extends React.Component { +export default class Rating extends React.PureComponent { static propTypes = { value: (props, propName, componentName) => { // allow both numbers and strings diff --git a/server/sonar-web/src/main/js/components/ui/SizeRating.js b/server/sonar-web/src/main/js/components/ui/SizeRating.js index 0e0c8098c2b..db1a15f2a1a 100644 --- a/server/sonar-web/src/main/js/components/ui/SizeRating.js +++ b/server/sonar-web/src/main/js/components/ui/SizeRating.js @@ -23,7 +23,7 @@ import classNames from 'classnames'; import { inRange } from 'lodash'; import './SizeRating.css'; -export default class SizeRating extends React.Component { +export default class SizeRating extends React.PureComponent { props: { value: number, small?: boolean, diff --git a/server/sonar-web/src/main/js/components/ui/VulnerabilityIcon.js b/server/sonar-web/src/main/js/components/ui/VulnerabilityIcon.js index 1a5203fc94e..b3987cb4432 100644 --- a/server/sonar-web/src/main/js/components/ui/VulnerabilityIcon.js +++ b/server/sonar-web/src/main/js/components/ui/VulnerabilityIcon.js @@ -20,16 +20,14 @@ // @flow import React from 'react'; -export default class VulnerabilityIcon extends React.Component { - render() { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> - <path - style={{ fill: 'currentColor' }} - d="M10.8 5H6V3.9a2.28 2.28 0 0 1 2-2.5 2.22 2.22 0 0 1 1.8 1.2.48.48 0 0 0 .7.2.48.48 0 0 0 .2-.7A3 3 0 0 0 8 .4a3.34 3.34 0 0 0-3 3.5v1.2a2.16 2.16 0 0 0-2 2.1v4.4a2.22 2.22 0 0 0 2.2 2.2h5.6a2.22 2.22 0 0 0 2.2-2.2V7.2A2.22 2.22 0 0 0 10.8 5zm-2.2 5.5v1.2H7.4v-1.2a1.66 1.66 0 0 1-1.1-1.6A1.75 1.75 0 0 1 8 7.2a1.71 1.71 0 0 1 .6 3.3z" - /> - </svg> - ); - } +export default function VulnerabilityIcon() { + /* eslint-disable max-len */ + return ( + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"> + <path + style={{ fill: 'currentColor' }} + d="M10.8 5H6V3.9a2.28 2.28 0 0 1 2-2.5 2.22 2.22 0 0 1 1.8 1.2.48.48 0 0 0 .7.2.48.48 0 0 0 .2-.7A3 3 0 0 0 8 .4a3.34 3.34 0 0 0-3 3.5v1.2a2.16 2.16 0 0 0-2 2.1v4.4a2.22 2.22 0 0 0 2.2 2.2h5.6a2.22 2.22 0 0 0 2.2-2.2V7.2A2.22 2.22 0 0 0 10.8 5zm-2.2 5.5v1.2H7.4v-1.2a1.66 1.66 0 0 1-1.1-1.6A1.75 1.75 0 0 1 8 7.2a1.71 1.71 0 0 1 .6 3.3z" + /> + </svg> + ); } diff --git a/server/sonar-web/src/main/js/store/utils/withStore.js b/server/sonar-web/src/main/js/store/utils/withStore.js index ddcf29e471e..772ae8c9b52 100644 --- a/server/sonar-web/src/main/js/store/utils/withStore.js +++ b/server/sonar-web/src/main/js/store/utils/withStore.js @@ -28,7 +28,7 @@ const withStore = (ComposedComponent, initial = {}) => { const getStore = () => ({ ...store }); - return class extends React.Component { + return class extends React.PureComponent { static displayName = `withStore(${ComposedComponent.displayName})}`; componentWillMount() { |