aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/quality-profiles/home
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main/js/apps/quality-profiles/home')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js)82
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js)37
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js96
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx86
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js)44
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js80
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx73
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js)53
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js)45
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js)54
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js)19
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListRow.js)38
-rw-r--r--server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx (renamed from server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js)54
13 files changed, 349 insertions, 412 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx
index d95984ce033..8f6d589cff8 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/CreateProfileForm.tsx
@@ -17,39 +17,33 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import Modal from 'react-modal';
-import Select from 'react-select';
+import * as Select from 'react-select';
import { sortBy } from 'lodash';
import { getImporters, createQualityProfile } from '../../../api/quality-profiles';
import { translate } from '../../../helpers/l10n';
-/*::
-type Props = {
- languages: Array<{ key: string, name: string }>,
- onClose: () => void,
- onCreate: Function,
- onRequestFail: Object => void,
- organization: ?string
-};
-*/
-
-/*::
-type State = {
- importers: Array<{ key: string, languages: Array<string>, name: string }>,
- language?: string,
- loading: boolean,
- name: string,
- preloading: boolean
-};
-*/
-
-export default class CreateProfileForm extends React.PureComponent {
+interface Props {
+ languages: Array<{ key: string; name: string }>;
+ onClose: () => void;
+ onCreate: Function;
+ onRequestFail: (reasong: any) => void;
+ organization: string | null;
+}
+
+interface State {
+ importers: Array<{ key: string; languages: Array<string>; name: string }>;
+ language?: string;
+ loading: boolean;
+ name: string;
+ preloading: boolean;
+}
+
+export default class CreateProfileForm extends React.PureComponent<Props, State> {
/*:: form: HTMLFormElement; */
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { importers: [], loading: false, name: '', preloading: true };
+ mounted: boolean;
+ state: State = { importers: [], loading: false, name: '', preloading: true };
componentDidMount() {
this.mounted = true;
@@ -61,39 +55,41 @@ export default class CreateProfileForm extends React.PureComponent {
}
fetchImporters() {
- getImporters().then(importers => {
- if (this.mounted) {
- this.setState({ importers, preloading: false });
+ getImporters().then(
+ (importers: Array<{ key: string; languages: Array<string>; name: string }>) => {
+ if (this.mounted) {
+ this.setState({ importers, preloading: false });
+ }
}
- });
+ );
}
- handleCancelClick = (event /*: Event */) => {
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
this.props.onClose();
};
- handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => {
+ handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
this.setState({ name: event.currentTarget.value });
};
- handleLanguageChange = (option /*: { value: string } */) => {
+ handleLanguageChange = (option: { value: string }) => {
this.setState({ language: option.value });
};
- handleFormSubmit = (event /*: Event */) => {
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
this.setState({ loading: true });
- const data = new FormData(this.form);
+ const data = new FormData(event.currentTarget);
if (this.props.organization) {
data.append('organization', this.props.organization);
}
createQualityProfile(data).then(
- response => this.props.onCreate(response.profile),
- error => {
+ (response: any) => this.props.onCreate(response.profile),
+ (error: any) => {
if (this.mounted) {
this.setState({ loading: false });
}
@@ -118,10 +114,7 @@ export default class CreateProfileForm extends React.PureComponent {
className="modal"
overlayClassName="modal-overlay"
onRequestClose={this.props.onClose}>
- <form
- id="create-profile-form"
- onSubmit={this.handleFormSubmit}
- ref={node => (this.form = node)}>
+ <form id="create-profile-form" onSubmit={this.handleFormSubmit}>
<div className="modal-head">
<h2>
{header}
@@ -141,11 +134,11 @@ export default class CreateProfileForm extends React.PureComponent {
<input
autoFocus={true}
id="create-profile-name"
- maxLength="100"
+ maxLength={100}
name="name"
onChange={this.handleNameChange}
required={true}
- size="50"
+ size={50}
type="text"
value={this.state.name}
/>
@@ -157,7 +150,6 @@ export default class CreateProfileForm extends React.PureComponent {
</label>
<Select
clearable={false}
- id="create-profile-language"
name="language"
onChange={this.handleLanguageChange}
options={languages.map(language => ({
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.tsx
index 4be28f3dd04..f238580d1e2 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/Evolution.tsx
@@ -17,32 +17,23 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import EvolutionDeprecated from './EvolutionDeprecated';
import EvolutionStagnant from './EvolutionStagnant';
import EvolutionRules from './EvolutionRules';
-/*:: import type { Profile } from '../propTypes'; */
+import { IProfile } from '../types';
-/*::
-type Props = {
- organization: ?string,
- profiles: Array<Profile>
-};
-*/
-
-export default class Evolution extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { organization, profiles } = this.props;
+interface Props {
+ organization: string | null;
+ profiles: IProfile[];
+}
- return (
- <div className="quality-profiles-evolution">
- <EvolutionDeprecated organization={organization} profiles={profiles} />
- <EvolutionStagnant organization={organization} profiles={profiles} />
- <EvolutionRules organization={organization} />
- </div>
- );
- }
+export default function Evolution({ organization, profiles }: Props) {
+ return (
+ <div className="quality-profiles-evolution">
+ <EvolutionDeprecated organization={organization} profiles={profiles} />
+ <EvolutionStagnant organization={organization} profiles={profiles} />
+ <EvolutionRules organization={organization} />
+ </div>
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js
deleted file mode 100644
index a3eaef27bd2..00000000000
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.js
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import { Link } from 'react-router';
-import { sortBy } from 'lodash';
-import ProfileLink from '../components/ProfileLink';
-import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls';
-import { translateWithParameters, translate } from '../../../helpers/l10n';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- organization: ?string,
- profiles: Array<Profile>
-};
-*/
-
-export default class EvolutionDeprecated extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const profilesWithDeprecations = this.props.profiles.filter(
- profile => profile.activeDeprecatedRuleCount > 0
- );
-
- if (profilesWithDeprecations.length === 0) {
- return null;
- }
-
- const sortedProfiles = sortBy(profilesWithDeprecations, p => -p.activeDeprecatedRuleCount);
-
- return (
- <div className="quality-profile-box quality-profiles-evolution-deprecated">
- <div className="spacer-bottom">
- <strong>
- {translate('quality_profiles.deprecated_rules')}
- </strong>
- </div>
- <div className="spacer-bottom">
- {translateWithParameters(
- 'quality_profiles.deprecated_rules_are_still_activated',
- profilesWithDeprecations.length
- )}
- </div>
- <ul>
- {sortedProfiles.map(profile =>
- <li key={profile.key} className="spacer-top">
- <div className="text-ellipsis">
- <ProfileLink
- className="link-no-underline"
- language={profile.language}
- name={profile.name}
- organization={this.props.organization}>
- {profile.name}
- </ProfileLink>
- </div>
- <div className="note">
- {profile.languageName}
- {', '}
- <Link
- to={getDeprecatedActiveRulesUrl(
- { qprofile: profile.key },
- this.props.organization
- )}
- className="text-muted">
- {translateWithParameters(
- 'quality_profile.x_rules',
- profile.activeDeprecatedRuleCount
- )}
- </Link>
- </div>
- </li>
- )}
- </ul>
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx
new file mode 100644
index 00000000000..0f8da8a3e9a
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionDeprecated.tsx
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { Link } from 'react-router';
+import { sortBy } from 'lodash';
+import ProfileLink from '../components/ProfileLink';
+import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls';
+import { translateWithParameters, translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ organization: string | null;
+ profiles: IProfile[];
+}
+
+export default function EvolutionDeprecated(props: Props) {
+ const profilesWithDeprecations = props.profiles.filter(
+ profile => profile.activeDeprecatedRuleCount > 0
+ );
+
+ if (profilesWithDeprecations.length === 0) {
+ return null;
+ }
+
+ const sortedProfiles = sortBy(profilesWithDeprecations, p => -p.activeDeprecatedRuleCount);
+
+ return (
+ <div className="quality-profile-box quality-profiles-evolution-deprecated">
+ <div className="spacer-bottom">
+ <strong>
+ {translate('quality_profiles.deprecated_rules')}
+ </strong>
+ </div>
+ <div className="spacer-bottom">
+ {translateWithParameters(
+ 'quality_profiles.deprecated_rules_are_still_activated',
+ profilesWithDeprecations.length
+ )}
+ </div>
+ <ul>
+ {sortedProfiles.map(profile =>
+ <li key={profile.key} className="spacer-top">
+ <div className="text-ellipsis">
+ <ProfileLink
+ className="link-no-underline"
+ language={profile.language}
+ name={profile.name}
+ organization={props.organization}>
+ {profile.name}
+ </ProfileLink>
+ </div>
+ <div className="note">
+ {profile.languageName}
+ {', '}
+ <Link
+ to={getDeprecatedActiveRulesUrl({ qprofile: profile.key }, props.organization)}
+ className="text-muted">
+ {translateWithParameters(
+ 'quality_profile.x_rules',
+ profile.activeDeprecatedRuleCount
+ )}
+ </Link>
+ </div>
+ </li>
+ )}
+ </ul>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx
index 042c04a73b6..c9e3e1f46e1 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx
@@ -17,10 +17,9 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { Link } from 'react-router';
-import moment from 'moment';
+import * as moment from 'moment';
import { sortBy } from 'lodash';
import { searchRules } from '../../../api/rules';
import { translateWithParameters, translate } from '../../../helpers/l10n';
@@ -31,24 +30,33 @@ const RULES_LIMIT = 10;
const PERIOD_START_MOMENT = moment().subtract(1, 'year');
-function parseRules(r) {
+function parseRules(r: any) {
const { rules, actives } = r;
- return rules.map(rule => {
+ return rules.map((rule: any) => {
const activations = actives[rule.key];
return { ...rule, activations: activations ? activations.length : 0 };
});
}
-/*::
-type Props = {
- organization: ?string
-};
-*/
+interface Props {
+ organization: string | null;
+}
+
+interface IRule {
+ activations: number;
+ key: string;
+ langName: string;
+ name: string;
+}
+
+interface State {
+ latestRules?: Array<IRule>;
+ latestRulesTotal?: number;
+}
-export default class EvolutionRules extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state = {};
+export default class EvolutionRules extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = {};
componentDidMount() {
this.mounted = true;
@@ -68,10 +76,10 @@ export default class EvolutionRules extends React.PureComponent {
f: 'name,langName,actives'
};
- searchRules(data).then(r => {
+ searchRules(data).then((r: any) => {
if (this.mounted) {
this.setState({
- latestRules: sortBy(parseRules(r), 'langName'),
+ latestRules: sortBy<IRule>(parseRules(r), 'langName'),
latestRulesTotal: r.total
});
}
@@ -79,7 +87,7 @@ export default class EvolutionRules extends React.PureComponent {
}
render() {
- if (!this.state.latestRulesTotal) {
+ if (!this.state.latestRulesTotal || !this.state.latestRules) {
return null;
}
@@ -125,7 +133,7 @@ export default class EvolutionRules extends React.PureComponent {
{this.state.latestRulesTotal > RULES_LIMIT &&
<div className="spacer-top">
<Link to={newRulesUrl} className="small">
- {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT')}
+ {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)}
</Link>
</div>}
</div>
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js
deleted file mode 100644
index 1eda4c0b8e3..00000000000
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import moment from 'moment';
-import ProfileLink from '../components/ProfileLink';
-import { translate } from '../../../helpers/l10n';
-import { isStagnant } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- organization: ?string,
- profiles: Array<Profile>
-};
-*/
-
-export default class EvolutionStagnant extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- // TODO filter built-in out
-
- const outdated = this.props.profiles.filter(isStagnant);
-
- if (outdated.length === 0) {
- return null;
- }
-
- return (
- <div className="quality-profile-box quality-profiles-evolution-stagnant">
- <div className="spacer-bottom">
- <strong>
- {translate('quality_profiles.stagnant_profiles')}
- </strong>
- </div>
- <div className="spacer-bottom">
- {translate('quality_profiles.not_updated_more_than_year')}
- </div>
- <ul>
- {outdated.map(profile =>
- <li key={profile.key} className="spacer-top">
- <div className="text-ellipsis">
- <ProfileLink
- className="link-no-underline"
- language={profile.language}
- name={profile.name}
- organization={this.props.organization}>
- {profile.name}
- </ProfileLink>
- </div>
- <div className="note">
- {profile.languageName}
- {', '}
- updated on {moment(profile.rulesUpdatedAt).format('LL')}
- </div>
- </li>
- )}
- </ul>
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx
new file mode 100644
index 00000000000..8b3fc2eae90
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionStagnant.tsx
@@ -0,0 +1,73 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import * as moment from 'moment';
+import ProfileLink from '../components/ProfileLink';
+import { translate } from '../../../helpers/l10n';
+import { isStagnant } from '../utils';
+import { IProfile } from '../types';
+
+interface Props {
+ organization: string | null;
+ profiles: IProfile[];
+}
+
+export default function EvolutionStagnan(props: Props) {
+ // TODO filter built-in out
+
+ const outdated = props.profiles.filter(isStagnant);
+
+ if (outdated.length === 0) {
+ return null;
+ }
+
+ return (
+ <div className="quality-profile-box quality-profiles-evolution-stagnant">
+ <div className="spacer-bottom">
+ <strong>
+ {translate('quality_profiles.stagnant_profiles')}
+ </strong>
+ </div>
+ <div className="spacer-bottom">
+ {translate('quality_profiles.not_updated_more_than_year')}
+ </div>
+ <ul>
+ {outdated.map(profile =>
+ <li key={profile.key} className="spacer-top">
+ <div className="text-ellipsis">
+ <ProfileLink
+ className="link-no-underline"
+ language={profile.language}
+ name={profile.name}
+ organization={props.organization}>
+ {profile.name}
+ </ProfileLink>
+ </div>
+ <div className="note">
+ {profile.languageName}
+ {', '}
+ updated on {moment(profile.rulesUpdatedAt).format('LL')}
+ </div>
+ </li>
+ )}
+ </ul>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx
index 95f63d8cd4c..cd3b21502a5 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx
@@ -17,42 +17,35 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import PageHeader from './PageHeader';
import Evolution from './Evolution';
import ProfilesList from './ProfilesList';
-/*:: import type { Profile } from '../propTypes'; */
+import { IProfile } from '../types';
-/*::
-type Props = {
- canAdmin: boolean,
- languages: Array<{ key: string, name: string }>,
- location: { query: { [string]: string } },
- onRequestFail: Object => void,
- organization?: string,
- profiles: Array<Profile>,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class HomeContainer extends React.PureComponent {
- /*:: props: Props; */
+interface Props {
+ canAdmin: boolean;
+ languages: Array<{ key: string; name: string }>;
+ location: { query: { [p: string]: string } };
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ profiles: Array<IProfile>;
+ updateProfiles: () => Promise<void>;
+}
- render() {
- return (
- <div>
- <PageHeader {...this.props} />
+export default function HomeContainer(props: Props) {
+ return (
+ <div>
+ <PageHeader {...props} />
- <div className="page-with-sidebar">
- <div className="page-main">
- <ProfilesList {...this.props} />
- </div>
- <div className="page-sidebar">
- <Evolution {...this.props} />
- </div>
+ <div className="page-with-sidebar">
+ <div className="page-main">
+ <ProfilesList {...props} />
+ </div>
+ <div className="page-sidebar">
+ <Evolution {...props} />
</div>
</div>
- );
- }
+ </div>
+ );
}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
index 44ba30feeb7..0f3b2b9c19f 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/PageHeader.tsx
@@ -17,51 +17,44 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
-import PropTypes from 'prop-types';
+import * as React from 'react';
+import * as PropTypes from 'prop-types';
import CreateProfileForm from './CreateProfileForm';
import RestoreProfileForm from './RestoreProfileForm';
-/*:: import type { Profile } from '../propTypes'; */
import { getProfilePath } from '../utils';
import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
-/*::
-type Props = {
- canAdmin: boolean,
- languages: Array<{ key: string, name: string }>,
- onRequestFail: Object => void,
- organization: ?string,
- updateProfiles: () => Promise<*>
-};
-*/
-
-/*::
-type State = {
- createFormOpen: boolean,
- restoreFormOpen: boolean
-};
-*/
+interface Props {
+ canAdmin: boolean;
+ languages: Array<{ key: string; name: string }>;
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ updateProfiles: () => Promise<void>;
+}
-export default class PageHeader extends React.PureComponent {
- /*:: props: Props; */
+interface State {
+ createFormOpen: boolean;
+ restoreFormOpen: boolean;
+}
+export default class PageHeader extends React.PureComponent<Props, State> {
static contextTypes = {
router: PropTypes.object
};
- state /*: State */ = {
+ state = {
createFormOpen: false,
restoreFormOpen: false
};
- handleCreateClick = (event /*: Event & { currentTarget: HTMLButtonElement } */) => {
+ handleCreateClick = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
event.currentTarget.blur();
this.setState({ createFormOpen: true });
};
- handleCreate = (profile /*: Profile */) => {
+ handleCreate = (profile: IProfile) => {
this.props.updateProfiles().then(() => {
this.context.router.push(
getProfilePath(profile.name, profile.language, this.props.organization)
@@ -73,7 +66,7 @@ export default class PageHeader extends React.PureComponent {
this.setState({ createFormOpen: false });
};
- handleRestoreClick = (event /*: Event */) => {
+ handleRestoreClick = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
this.setState({ restoreFormOpen: true });
};
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx
index b912a9662a5..6f4c8f8c17b 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesList.tsx
@@ -17,31 +17,25 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { groupBy, pick, sortBy } from 'lodash';
import ProfilesListRow from './ProfilesListRow';
import ProfilesListHeader from './ProfilesListHeader';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-/*:: import type { Profile } from '../propTypes'; */
+import { IProfile } from '../types';
-/*::
-type Props = {
- canAdmin: boolean,
- languages: Array<{ key: string, name: string }>,
- location: { query: { [string]: string } },
- onRequestFail: Object => void,
- organization: ?string,
- profiles: Array<Profile>,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfilesList extends React.PureComponent {
- /*:: props: Props; */
+interface Props {
+ canAdmin: boolean;
+ languages: Array<{ key: string; name: string }>;
+ location: { query: { [p: string]: string } };
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ profiles: IProfile[];
+ updateProfiles: () => Promise<void>;
+}
- renderProfiles(profiles /*: Array<Profile> */) {
+export default class ProfilesList extends React.PureComponent<Props> {
+ renderProfiles(profiles: IProfile[]) {
return profiles.map(profile =>
<ProfilesListRow
canAdmin={this.props.canAdmin}
@@ -54,7 +48,7 @@ export default class ProfilesList extends React.PureComponent {
);
}
- renderHeader(languageKey /*: string */, profilesCount /*: number */) {
+ renderHeader(languageKey: string, profilesCount: number) {
const language = this.props.languages.find(l => l.key === languageKey);
if (!language) {
@@ -91,8 +85,14 @@ export default class ProfilesList extends React.PureComponent {
const { profiles, languages } = this.props;
const { language } = this.props.location.query;
- const profilesIndex = groupBy(profiles, profile => profile.language);
- const profilesToShow = language ? pick(profilesIndex, language) : profilesIndex;
+ const profilesIndex: { [language: string]: IProfile[] } = groupBy<IProfile>(
+ profiles,
+ profile => profile.language
+ );
+
+ const profilesToShow: { [language: string]: IProfile[] } = language
+ ? pick(profilesIndex, language)
+ : profilesIndex;
const languagesToShow = sortBy(Object.keys(profilesToShow));
@@ -115,12 +115,10 @@ export default class ProfilesList extends React.PureComponent {
{profilesToShow[languageKey] != null &&
this.renderHeader(languageKey, profilesToShow[languageKey].length)}
- <TooltipsContainer>
- <tbody>
- {profilesToShow[languageKey] != null &&
- this.renderProfiles(profilesToShow[languageKey])}
- </tbody>
- </TooltipsContainer>
+ <tbody>
+ {profilesToShow[languageKey] != null &&
+ this.renderProfiles(profilesToShow[languageKey])}
+ </tbody>
</table>
</div>
)}
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx
index ab76d1a4df3..15b98d6a2d4 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/ProfilesListHeader.tsx
@@ -17,23 +17,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { IndexLink } from 'react-router';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { getProfilesPath, getProfilesForLanguagePath } from '../utils';
-/*::
-type Props = {
- currentFilter?: string,
- languages: Array<{ key: string, name: string }>,
- organization: ?string
-};
-*/
-
-export default class ProfilesListHeader extends React.PureComponent {
- /*:: props: Props; */
+interface Props {
+ currentFilter?: string;
+ languages: Array<{ key: string; name: string }>;
+ organization: string | null;
+}
+export default class ProfilesListHeader extends React.PureComponent<Props> {
renderFilterToggle() {
const { languages, currentFilter } = this.props;
const currentLanguage = currentFilter && languages.find(l => l.key === currentFilter);
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.tsx
index f9d18056d2e..2d982c34db4 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.tsx
@@ -17,8 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import { Link } from 'react-router';
import ProfileLink from '../components/ProfileLink';
import ProfileDate from '../components/ProfileDate';
@@ -27,21 +26,18 @@ import BuiltInBadge from '../components/BuiltInBadge';
import { translate } from '../../../helpers/l10n';
import { getRulesUrl } from '../../../helpers/urls';
import { isStagnant } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
+import { IProfile } from '../types';
+import Tooltip from '../../../components/controls/Tooltip';
-/*::
-type Props = {
- canAdmin: boolean,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfilesListRow extends React.PureComponent {
- /*:: props: Props; */
+interface Props {
+ canAdmin: boolean;
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ profile: IProfile;
+ updateProfiles: () => Promise<void>;
+}
+export default class ProfilesListRow extends React.PureComponent<Props> {
renderName() {
const { profile } = this.props;
const offset = 25 * (profile.depth - 1);
@@ -100,13 +96,11 @@ export default class ProfilesListRow extends React.PureComponent {
<div>
{profile.activeDeprecatedRuleCount > 0 &&
<span className="spacer-right">
- <Link
- to={deprecatedRulesUrl}
- className="badge badge-normal-size badge-danger-light"
- title={translate('quality_profiles.deprecated_rules')}
- data-toggle="tooltip">
- {profile.activeDeprecatedRuleCount}
- </Link>
+ <Tooltip overlay={translate('quality_profiles.deprecated_rules')}>
+ <Link to={deprecatedRulesUrl} className="badge badge-normal-size badge-danger-light">
+ {profile.activeDeprecatedRuleCount}
+ </Link>
+ </Tooltip>
</span>}
<Link to={activeRulesUrl}>
diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx
index 26411abb34c..5f12d61f662 100644
--- a/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.js
+++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/RestoreProfileForm.tsx
@@ -17,35 +17,28 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
+import * as React from 'react';
import Modal from 'react-modal';
import { restoreQualityProfile } from '../../../api/quality-profiles';
import { translate, translateWithParameters } from '../../../helpers/l10n';
-/*::
-type Props = {
- onClose: () => void,
- onRequestFail: Object => void,
- onRestore: Function,
- organization: ?string
-};
-*/
+interface Props {
+ onClose: () => void;
+ onRequestFail: (reason: any) => void;
+ onRestore: () => void;
+ organization: string | null;
+}
-/*::
-type State = {
- loading: boolean,
- profile?: { name: string },
- ruleFailures?: number,
- ruleSuccesses?: number
-};
-*/
+interface State {
+ loading: boolean;
+ profile?: { name: string };
+ ruleFailures?: number;
+ ruleSuccesses?: number;
+}
-export default class RestoreProfileForm extends React.PureComponent {
- /*:: form: HTMLFormElement; */
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { loading: false };
+export default class RestoreProfileForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: false };
componentDidMount() {
this.mounted = true;
@@ -55,23 +48,23 @@ export default class RestoreProfileForm extends React.PureComponent {
this.mounted = false;
}
- handleCancelClick = (event /*: Event */) => {
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
event.preventDefault();
this.props.onClose();
};
- handleFormSubmit = (event /*: Event */) => {
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
this.setState({ loading: true });
- const data = new FormData(this.form);
+ const data = new FormData(event.currentTarget);
if (this.props.organization) {
data.append('organization', this.props.organization);
}
restoreQualityProfile(data).then(
- response => {
+ (response: any) => {
if (this.mounted) {
this.setState({
loading: false,
@@ -82,7 +75,7 @@ export default class RestoreProfileForm extends React.PureComponent {
}
this.props.onRestore();
},
- error => {
+ (error: any) => {
if (this.mounted) {
this.setState({ loading: false });
}
@@ -103,10 +96,7 @@ export default class RestoreProfileForm extends React.PureComponent {
className="modal"
overlayClassName="modal-overlay"
onRequestClose={this.props.onClose}>
- <form
- id="restore-profile-form"
- onSubmit={this.handleFormSubmit}
- ref={node => (this.form = node)}>
+ <form id="restore-profile-form" onSubmit={this.handleFormSubmit}>
<div className="modal-head">
<h2>
{header}