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/apps | |
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/apps')
239 files changed, 1442 insertions, 1742 deletions
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() { |