"devDependencies": {
"@types/classnames": "2.2.0",
"@types/enzyme": "2.8.6",
+ "@types/escape-html": "0.0.19",
"@types/jest": "20.0.7",
+ "@types/jquery": "3.2.11",
"@types/lodash": "4.14.73",
"@types/prop-types": "15.5.1",
"@types/react": "16.0.2",
"@types/react-dom": "15.5.2",
+ "@types/react-helmet": "5.0.3",
+ "@types/react-modal": "2.2.0",
"@types/react-redux": "5.0.3",
"@types/react-router": "3.0.5",
+ "@types/react-select": "1.0.51",
"autoprefixer": "7.1.1",
"awesome-typescript-loader": "3.2.3",
"babel-core": "^6.22.1",
],
"jest": {
"coverageDirectory": "<rootDir>/target/coverage",
- "coveragePathIgnorePatterns": ["<rootDir>/node_modules", "<rootDir>/tests"],
- "moduleFileExtensions": ["ts", "tsx", "js", "json"],
+ "coveragePathIgnorePatterns": [
+ "<rootDir>/node_modules",
+ "<rootDir>/tests"
+ ],
+ "moduleFileExtensions": [
+ "ts",
+ "tsx",
+ "js",
+ "json"
+ ],
"moduleNameMapper": {
"^.+\\.(hbs|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/config/jest/FileStub.js",
"^.+\\.css$": "<rootDir>/config/jest/CSSStub.js"
"<rootDir>/config/polyfills.js",
"<rootDir>/config/jest/SetupTestEnvironment.js"
],
- "snapshotSerializers": ["enzyme-to-json/serializer"],
+ "snapshotSerializers": [
+ "enzyme-to-json/serializer"
+ ],
"testPathIgnorePatterns": [
"<rootDir>/node_modules",
"<rootDir>/src/main/webapp",
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/AboutApp').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/AboutApp').then(i => callback(null, { component: i.default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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 React from 'react';
-import moment from 'moment';
-import { sortBy } from 'lodash';
-import { Link } from 'react-router';
-import Level from '../../../components/ui/Level';
-import { projectType } from './propTypes';
-import { translateWithParameters, translate } from '../../../helpers/l10n';
-
-export default class ProjectCard extends React.PureComponent {
- static propTypes = {
- project: projectType.isRequired
- };
-
- render() {
- const { project } = this.props;
- const isAnalyzed = project.lastAnalysisDate != null;
- const analysisMoment = isAnalyzed && moment(project.lastAnalysisDate);
- const links = sortBy(project.links, 'type');
-
- return (
- <div className="account-project-card clearfix">
- <aside className="account-project-side">
- {isAnalyzed
- ? <div className="account-project-analysis" title={analysisMoment.format('LLL')}>
- {translateWithParameters(
- 'my_account.projects.analyzed_x',
- analysisMoment.fromNow()
- )}
- </div>
- : <div className="account-project-analysis">
- {translate('my_account.projects.never_analyzed')}
- </div>}
-
- {project.qualityGate != null &&
- <div className="account-project-quality-gate">
- <Level level={project.qualityGate} />
- </div>}
- </aside>
-
- <h3 className="account-project-name">
- <Link to={{ pathname: '/dashboard', query: { id: project.key } }}>
- {project.name}
- </Link>
- </h3>
-
- {links.length > 0 &&
- <div className="account-project-links">
- <ul className="list-inline">
- {links.map(link =>
- <li key={link.type}>
- <a
- className="link-with-icon"
- href={link.href}
- title={link.name}
- target="_blank"
- rel="nofollow">
- <i className={`icon-color-link icon-${link.type}`} />
- </a>
- </li>
- )}
- </ul>
- </div>}
-
- <div className="account-project-key">
- {project.key}
- </div>
-
- {!!project.description &&
- <div className="account-project-description">
- {project.description}
- </div>}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { sortBy } from 'lodash';
+import { Link } from 'react-router';
+import { IProject } from './types';
+import Level from '../../../components/ui/Level';
+import { translateWithParameters, translate } from '../../../helpers/l10n';
+
+interface Props {
+ project: IProject;
+}
+
+export default function ProjectCard(props: Props) {
+ const { project } = props;
+ const isAnalyzed = project.lastAnalysisDate != null;
+ const analysisMoment = isAnalyzed && moment(project.lastAnalysisDate);
+ const links = sortBy(project.links, 'type');
+
+ return (
+ <div className="account-project-card clearfix">
+ <aside className="account-project-side">
+ {isAnalyzed
+ ? <div
+ className="account-project-analysis"
+ title={analysisMoment ? analysisMoment.format('LLL') : undefined}>
+ {translateWithParameters(
+ 'my_account.projects.analyzed_x',
+ analysisMoment ? analysisMoment.fromNow() : undefined
+ )}
+ </div>
+ : <div className="account-project-analysis">
+ {translate('my_account.projects.never_analyzed')}
+ </div>}
+
+ {project.qualityGate != null &&
+ <div className="account-project-quality-gate">
+ <Level level={project.qualityGate} />
+ </div>}
+ </aside>
+
+ <h3 className="account-project-name">
+ <Link to={{ pathname: '/dashboard', query: { id: project.key } }}>
+ {project.name}
+ </Link>
+ </h3>
+
+ {links.length > 0 &&
+ <div className="account-project-links">
+ <ul className="list-inline">
+ {links.map(link =>
+ <li key={link.type}>
+ <a
+ className="link-with-icon"
+ href={link.href}
+ title={link.name}
+ target="_blank"
+ rel="nofollow">
+ <i className={`icon-color-link icon-${link.type}`} />
+ </a>
+ </li>
+ )}
+ </ul>
+ </div>}
+
+ <div className="account-project-key">
+ {project.key}
+ </div>
+
+ {!!project.description &&
+ <div className="account-project-description">
+ {project.description}
+ </div>}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import PropTypes from 'prop-types';
-import ProjectCard from './ProjectCard';
-import ListFooter from '../../../components/controls/ListFooter';
-import { projectsListType } from './propTypes';
-import { translate } from '../../../helpers/l10n';
-
-export default class Projects extends React.PureComponent {
- static propTypes = {
- projects: projectsListType.isRequired,
- total: PropTypes.number.isRequired,
- loading: PropTypes.bool.isRequired,
- loadMore: PropTypes.func.isRequired
- };
-
- render() {
- const { projects } = this.props;
-
- return (
- <div id="account-projects">
- {projects.length === 0
- ? <div className="js-no-results">
- {translate('my_account.projects.no_results')}
- </div>
- : <p>
- {translate('my_account.projects.description')}
- </p>}
-
- {projects.length > 0 &&
- <ul className="account-projects-list">
- {projects.map(project =>
- <li key={project.key}>
- <ProjectCard project={project} />
- </li>
- )}
- </ul>}
-
- {projects.length > 0 &&
- <ListFooter
- count={projects.length}
- total={this.props.total}
- ready={!this.props.loading}
- loadMore={this.props.loadMore}
- />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ProjectCard from './ProjectCard';
+import { IProject } from './types';
+import ListFooter from '../../../components/controls/ListFooter';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ loading: boolean;
+ loadMore: () => void;
+ projects: IProject[];
+ search: (query: string) => void;
+ total?: number;
+}
+
+export default function Projects(props: Props) {
+ const { projects } = props;
+
+ return (
+ <div id="account-projects">
+ {projects.length === 0
+ ? <div className="js-no-results">
+ {translate('my_account.projects.no_results')}
+ </div>
+ : <p>
+ {translate('my_account.projects.description')}
+ </p>}
+
+ {projects.length > 0 &&
+ <ul className="account-projects-list">
+ {projects.map(project =>
+ <li key={project.key}>
+ <ProjectCard project={project} />
+ </li>
+ )}
+ </ul>}
+
+ {projects.length > 0 &&
+ <ListFooter
+ count={projects.length}
+ total={props.total || 0}
+ ready={!props.loading}
+ loadMore={props.loadMore}
+ />}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import Helmet from 'react-helmet';
-import Projects from './Projects';
-import { getMyProjects } from '../../../api/components';
-import { translate } from '../../../helpers/l10n';
-
-export default class ProjectsContainer extends React.PureComponent {
- state = {
- loading: true,
- page: 1,
- query: ''
- };
-
- componentWillMount() {
- this.loadMore = this.loadMore.bind(this);
- this.search = this.search.bind(this);
- }
-
- componentDidMount() {
- this.mounted = true;
- this.loadProjects();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadProjects(page = this.state.page, query = this.state.query) {
- this.setState({ loading: true });
- const data = { ps: 100 };
- if (page > 1) {
- data.p = page;
- }
- if (query) {
- data.q = query;
- }
- return getMyProjects(data).then(r => {
- const projects = page > 1 ? [...this.state.projects, ...r.projects] : r.projects;
- this.setState({
- projects,
- query,
- loading: false,
- page: r.paging.pageIndex,
- total: r.paging.total
- });
- });
- }
-
- loadMore() {
- return this.loadProjects(this.state.page + 1);
- }
-
- search(query) {
- return this.loadProjects(1, query);
- }
-
- render() {
- const helmet = <Helmet title={translate('my_account.projects')} />;
-
- if (this.state.projects == null) {
- return (
- <div className="text-center">
- {helmet}
- <i className="spinner spinner-margin" />
- </div>
- );
- }
-
- return (
- <div className="account-body account-container">
- {helmet}
- <Projects
- projects={this.state.projects}
- total={this.state.total}
- loading={this.state.loading}
- loadMore={this.loadMore}
- search={this.search}
- />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Helmet from 'react-helmet';
+import Projects from './Projects';
+import { getMyProjects } from '../../../api/components';
+import { translate } from '../../../helpers/l10n';
+
+interface State {
+ loading: boolean;
+ page: number;
+ projects?: any[];
+ query: string;
+ total?: number;
+}
+
+export default class ProjectsContainer extends React.PureComponent<{}, State> {
+ mounted: boolean;
+ state: State = {
+ loading: true,
+ page: 1,
+ query: ''
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadProjects();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadProjects(page = this.state.page, query = this.state.query) {
+ this.setState({ loading: true });
+ const data: { [p: string]: any } = { ps: 100 };
+ if (page > 1) {
+ data.p = page;
+ }
+ if (query) {
+ data.q = query;
+ }
+ return getMyProjects(data).then((r: any) => {
+ const projects = page > 1 ? [...(this.state.projects || []), ...r.projects] : r.projects;
+ this.setState({
+ projects,
+ query,
+ loading: false,
+ page: r.paging.pageIndex,
+ total: r.paging.total
+ });
+ });
+ }
+
+ loadMore = () => this.loadProjects(this.state.page + 1);
+
+ search = (query: string) => this.loadProjects(1, query);
+
+ render() {
+ const helmet = <Helmet title={translate('my_account.projects')} />;
+
+ if (this.state.projects == null) {
+ return (
+ <div className="text-center">
+ {helmet}
+ <i className="spinner spinner-margin" />
+ </div>
+ );
+ }
+
+ return (
+ <div className="account-body account-container">
+ {helmet}
+ <Projects
+ projects={this.state.projects}
+ total={this.state.total}
+ loading={this.state.loading}
+ loadMore={this.loadMore}
+ search={this.search}
+ />
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-
-const { shape, string, array, arrayOf } = PropTypes;
-
-export const projectType = shape({
- id: string.isRequired,
- key: string.isRequired,
- name: string.isRequired,
- lastAnalysisDate: string,
- description: string,
- links: array.isRequired,
- qualityGate: string
-});
-
-export const projectsListType = arrayOf(projectType);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+export interface IProject {
+ id: string;
+ key: string;
+ name: string;
+ lastAnalysisDate: string;
+ description: string;
+ links: Array<{
+ href: string;
+ name: string;
+ type: string;
+ }>;
+ qualityGate: string;
+}
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getComponent(_, callback) {
- import('./components/Account').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- getIndexRoute(_, callback) {
- import('./profile/Profile').then(i => callback(null, { component: i.default }));
- }
- },
- {
- path: 'security',
- getComponent(_, callback) {
- import('./components/Security').then(i => callback(null, i.default));
- }
- },
- {
- path: 'projects',
- getComponent(_, callback) {
- import('./projects/ProjectsContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'notifications',
- getComponent(_, callback) {
- import('./notifications/Notifications').then(i => callback(null, i.default));
- }
- },
- {
- path: 'organizations',
- getComponent(_, callback) {
- import('./organizations/UserOrganizations').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- path: 'create',
- getComponent(_, callback) {
- import('./organizations/CreateOrganizationForm').then(i => callback(null, i.default));
- }
- }
- ]
- }
- ]
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/Account').then(i => callback(null, i.default));
+ },
+ childRoutes: [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./profile/Profile').then(i => callback(null, { component: i.default }));
+ }
+ },
+ {
+ path: 'security',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/Security').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'projects',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./projects/ProjectsContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'notifications',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./notifications/Notifications').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'organizations',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./organizations/UserOrganizations').then(i => callback(null, i.default));
+ },
+ childRoutes: [
+ {
+ path: 'create',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./organizations/CreateOrganizationForm').then(i => callback(null, i.default));
+ }
+ }
+ ]
+ }
+ ]
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/BackgroundTasksApp').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/BackgroundTasksApp').then(i => callback(null, { component: i.default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/App').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/App').then(i => callback(null, { component: i.default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- indexRoute: {
- getComponent(_, callback) {
- import('./components/CodingRulesAppContainer').then(i => callback(null, i.default));
- }
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ indexRoute: {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/CodingRulesAppContainer').then(i => callback(null, i.default));
+ }
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/AppContainer').then(i => callback(null, { component: i.default }));
- }
- },
- {
- path: 'domain/:domainName',
- onEnter(nextState, replace) {
- replace({
- pathname: '/component_measures',
- query: {
- ...nextState.location.query,
- metric: nextState.params.domainName
- }
- });
- }
- },
- {
- path: 'metric/:metricKey(/:view)',
- onEnter(nextState, replace) {
- if (nextState.params.view === 'history') {
- replace({
- pathname: '/project/activity',
- query: {
- id: nextState.location.query.id,
- graph: 'custom',
- custom_metrics: nextState.params.metricKey
- }
- });
- } else {
- replace({
- pathname: '/component_measures',
- query: {
- ...nextState.location.query,
- metric: nextState.params.metricKey,
- view: nextState.params.view
- }
- });
- }
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps, RedirectFunction } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/AppContainer').then(i => callback(null, { component: i.default }));
+ }
+ },
+ {
+ path: 'domain/:domainName',
+ onEnter(nextState: RouterState, replace: RedirectFunction) {
+ replace({
+ pathname: '/component_measures',
+ query: {
+ ...nextState.location.query,
+ metric: nextState.params.domainName
+ }
+ });
+ }
+ },
+ {
+ path: 'metric/:metricKey(/:view)',
+ onEnter(nextState: RouterState, replace: RedirectFunction) {
+ if (nextState.params.view === 'history') {
+ replace({
+ pathname: '/project/activity',
+ query: {
+ id: nextState.location.query.id,
+ graph: 'custom',
+ custom_metrics: nextState.params.metricKey
+ }
+ });
+ } else {
+ replace({
+ pathname: '/component_measures',
+ query: {
+ ...nextState.location.query,
+ metric: nextState.params.metricKey,
+ view: nextState.params.view
+ }
+ });
+ }
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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 SourceViewer from '../../../components/SourceViewer/SourceViewer';
-
-export default class App extends React.PureComponent {
- /*:: props: {
- location: {
- query: {
- id: string,
- line?: string
- }
- }
- };
-*/
- scrollToLine = () => {
- const { line } = this.props.location.query;
- if (line) {
- const row = document.querySelector(`.source-line[data-line-number="${line}"]`);
- if (row) {
- const rect = row.getBoundingClientRect();
- const topOffset = window.innerHeight / 2 - 60;
- const goal = rect.top - topOffset;
- window.scrollTo(0, goal);
- }
- }
- };
-
- render() {
- const { id, line } = this.props.location.query;
-
- const finalLine = line != null ? Number(line) : null;
-
- return (
- <div className="page page-limited">
- <SourceViewer
- aroundLine={finalLine}
- component={id}
- highlightedLine={finalLine}
- onLoaded={this.scrollToLine}
- />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 SourceViewer from '../../../components/SourceViewer/SourceViewer';
+
+interface Props {
+ location: {
+ query: {
+ id: string;
+ line?: string;
+ };
+ };
+}
+
+export default class App extends React.PureComponent<Props> {
+ scrollToLine = () => {
+ const { line } = this.props.location.query;
+ if (line) {
+ const row = document.querySelector(`.source-line[data-line-number="${line}"]`);
+ if (row) {
+ const rect = row.getBoundingClientRect();
+ const topOffset = window.innerHeight / 2 - 60;
+ const goal = rect.top - topOffset;
+ window.scrollTo(0, goal);
+ }
+ }
+ };
+
+ render() {
+ const { id, line } = this.props.location.query;
+
+ const finalLine = line != null ? Number(line) : null;
+
+ return (
+ <div className="page page-limited">
+ <SourceViewer
+ aroundLine={finalLine}
+ component={id}
+ highlightedLine={finalLine}
+ onLoaded={this.scrollToLine}
+ />
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- indexRoute: {
- getComponent(_, callback) {
- import('./components/App').then(i => callback(null, i.default));
- }
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ indexRoute: {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/App').then(i => callback(null, i.default));
+ }
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/CustomMeasuresAppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/CustomMeasuresAppContainer').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- Promise.all([
- import('./components/GroupsAppContainer').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([GroupsAppContainer, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(GroupsAppContainer) })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ Promise.all([
+ import('./components/GroupsAppContainer').then(i => i.default),
+ import('../organizations/forSingleOrganization').then(i => i.default)
+ ]).then(([GroupsAppContainer, forSingleOrganization]) =>
+ callback(null, { component: forSingleOrganization(GroupsAppContainer) })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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 { onEnter } from './redirects';
-
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/AppContainer').then(i =>
- callback(null, { component: i.default, onEnter })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+import { onEnter } from './redirects';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/AppContainer').then(i =>
+ callback(null, { component: i.default, onEnter })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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 React from 'react';
-import init from '../init';
-
-export default class MaintenanceAppContainer extends React.PureComponent {
- componentDidMount() {
- init(this.refs.container, false);
- }
-
- render() {
- return <div ref="container" />;
- }
-}
--- /dev/null
+/*
+ * 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 init from '../init';
+
+export default class MaintenanceAppContainer extends React.PureComponent {
+ componentDidMount() {
+ init(this.refs.container, false);
+ }
+
+ render() {
+ return <div ref="container" />;
+ }
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import init from '../init';
-
-export default class SetupAppContainer extends React.PureComponent {
- componentDidMount() {
- init(this.refs.container, true);
- }
-
- render() {
- return <div ref="container" />;
- }
-}
--- /dev/null
+/*
+ * 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 init from '../init';
+
+export default class SetupAppContainer extends React.PureComponent {
+ componentDidMount() {
+ init(this.refs.container, true);
+ }
+
+ render() {
+ return <div ref="container" />;
+ }
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import { IndexRoute } from 'react-router';
-import MaintenanceAppContainer from './components/MaintenanceAppContainer';
-import SetupAppContainer from './components/SetupAppContainer';
-
-export const maintenanceRoutes = <IndexRoute component={MaintenanceAppContainer} />;
-
-export const setupRoutes = <IndexRoute component={SetupAppContainer} />;
--- /dev/null
+/*
+ * 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 { IndexRoute } from 'react-router';
+import MaintenanceAppContainer from './components/MaintenanceAppContainer';
+import SetupAppContainer from './components/SetupAppContainer';
+
+export const maintenanceRoutes = <IndexRoute component={MaintenanceAppContainer} />;
+
+export const setupRoutes = <IndexRoute component={SetupAppContainer} />;
+++ /dev/null
-/*
- * 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 React from 'react';
-import Helmet from 'react-helmet';
-import init from '../init';
-import { translate } from '../../../helpers/l10n';
-
-export default class MetricsAppContainer extends React.PureComponent {
- componentDidMount() {
- init(this.refs.container);
- }
-
- render() {
- return (
- <div>
- <Helmet title={translate('custom_metrics.page')} />
- <div ref="container" />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Helmet from 'react-helmet';
+import init from '../init';
+import { translate } from '../../../helpers/l10n';
+
+export default class MetricsAppContainer extends React.PureComponent {
+ componentDidMount() {
+ init(this.refs.container);
+ }
+
+ render() {
+ return (
+ <div>
+ <Helmet title={translate('custom_metrics.page')} />
+ <div ref="container" />
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/MetricsAppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/MetricsAppContainer').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ }
+];
+
+export default routes;
overview.quality_gate
<Level
level="ERROR"
- muted={false}
- small={false}
/>
</h2>
<div
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/AppContainer').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/AppContainer').then(i => callback(null, { component: i.default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- Promise.all([
- import('./components/AppContainer').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([AppContainer, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(AppContainer) })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ Promise.all([
+ import('./components/AppContainer').then(i => i.default),
+ import('../organizations/forSingleOrganization').then(i => i.default)
+ ]).then(([AppContainer, forSingleOrganization]) =>
+ callback(null, { component: forSingleOrganization(AppContainer) })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-export const globalPermissionsRoutes = [
- {
- getIndexRoute(_, callback) {
- Promise.all([
- import('./global/components/App').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([App, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(App) })
- );
- }
- }
-];
-
-export const projectPermissionsRoutes = [
- {
- getIndexRoute(_, callback) {
- import('./project/components/AppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- }
-];
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+export const globalPermissionsRoutes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ Promise.all([
+ import('./global/components/App').then(i => i.default),
+ import('../organizations/forSingleOrganization').then(i => i.default)
+ ]).then(([App, forSingleOrganization]) =>
+ callback(null, { component: forSingleOrganization(App) })
+ );
+ }
+ }
+];
+
+export const projectPermissionsRoutes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./project/components/AppContainer').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ }
+];
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/ProjectActivityAppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/ProjectActivityAppContainer').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- Promise.all([
- import('./AppContainer').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([AppContainer, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(AppContainer) })
- );
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ Promise.all([
+ import('./AppContainer').then(i => i.default),
+ import('../organizations/forSingleOrganization').then(i => i.default)
+ ]).then(([AppContainer, forSingleOrganization]) =>
+ callback(null, { component: forSingleOrganization(AppContainer) })
+ );
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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';
-
-export default class App extends React.PureComponent {
- componentDidMount() {
- const elem = document.querySelector('html');
- if (elem) {
- elem.classList.add('dashboard-page');
- }
- }
-
- componentWillUnmount() {
- const elem = document.querySelector('html');
- if (elem) {
- elem.classList.remove('dashboard-page');
- }
- }
-
- render() {
- return (
- <div id="projects-page">
- {this.props.children}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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';
+
+export default class App extends React.PureComponent {
+ componentDidMount() {
+ const elem = document.querySelector('html');
+ if (elem) {
+ elem.classList.add('dashboard-page');
+ }
+ }
+
+ componentWillUnmount() {
+ const elem = document.querySelector('html');
+ if (elem) {
+ elem.classList.remove('dashboard-page');
+ }
+ }
+
+ render() {
+ return (
+ <div id="projects-page">
+ {this.props.children}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { saveAll } from '../../helpers/storage';
-
-const routes = [
- {
- getComponent(_, callback) {
- import('./components/App').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- getIndexRoute(_, callback) {
- import('./components/DefaultPageSelector').then(i =>
- callback(null, { component: i.default })
- );
- }
- },
- {
- path: 'all',
- onEnter(_, replace) {
- saveAll();
- replace('/projects');
- }
- },
- {
- path: 'favorite',
- getComponent(_, callback) {
- import('./components/FavoriteProjectsContainer').then(i => callback(null, i.default));
- }
- }
- ]
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps, RouteComponent, RedirectFunction } from 'react-router';
+import { saveAll } from '../../helpers/storage';
+
+const routes = [
+ {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/App').then(i => callback(null, i.default));
+ },
+ childRoutes: [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/DefaultPageSelector').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ },
+ {
+ path: 'all',
+ onEnter(_: RouterState, replace: RedirectFunction) {
+ saveAll();
+ replace('/projects');
+ }
+ },
+ {
+ path: 'favorite',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/FavoriteProjectsContainer').then(i => callback(null, i.default));
+ }
+ }
+ ]
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getComponent(_, callback) {
- import('./containers/QualityGatesAppContainer').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- getIndexRoute(_, callback) {
- import('./components/Intro').then(i => callback(null, { component: i.default }));
- }
- },
- {
- path: 'show/:id',
- getComponent(_, callback) {
- import('./containers/DetailsContainer').then(i => callback(null, i.default));
- }
- }
- ]
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./containers/QualityGatesAppContainer').then(i => callback(null, i.default));
+ },
+ childRoutes: [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/Intro').then(i => callback(null, { component: i.default }));
+ }
+ },
+ {
+ path: 'show/:id',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./containers/DetailsContainer').then(i => callback(null, i.default));
+ }
+ }
+ ]
+ }
+];
+
+export default routes;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`#sortProfiles should sort by name 1`] = `
-Array [
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile1",
- "name": "profile1",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile2",
- "name": "profile2",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile3",
- "name": "profile3",
- "parentKey": undefined,
- },
-]
-`;
-
-exports[`#sortProfiles should sort single branch 1`] = `
-Array [
- Object {
- "childrenCount": 1,
- "depth": 1,
- "key": "profile1",
- "name": "profile1",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 1,
- "depth": 2,
- "key": "profile3",
- "name": "profile3",
- "parentKey": "profile1",
- },
- Object {
- "childrenCount": 0,
- "depth": 3,
- "key": "profile2",
- "name": "profile2",
- "parentKey": "profile3",
- },
-]
-`;
-
-exports[`#sortProfiles should sort when no parents 1`] = `
-Array [
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile1",
- "name": "profile1",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile2",
- "name": "profile2",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile3",
- "name": "profile3",
- "parentKey": undefined,
- },
-]
-`;
-
-exports[`#sortProfiles should sort with children 1`] = `
-Array [
- Object {
- "childrenCount": 2,
- "depth": 1,
- "key": "parent",
- "name": "parent",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 2,
- "key": "child1",
- "name": "child1",
- "parentKey": "parent",
- },
- Object {
- "childrenCount": 0,
- "depth": 2,
- "key": "child2",
- "name": "child2",
- "parentKey": "parent",
- },
-]
-`;
-
-exports[`#sortProfiles sorts partial set of inherited profiles 1`] = `
-Array [
- Object {
- "childrenCount": 0,
- "depth": 1,
- "key": "profile1",
- "name": "profile1",
- "parentKey": "x",
- },
- Object {
- "childrenCount": 1,
- "depth": 1,
- "key": "profile2",
- "name": "profile2",
- "parentKey": undefined,
- },
- Object {
- "childrenCount": 0,
- "depth": 2,
- "key": "profile3",
- "name": "profile3",
- "parentKey": "profile2",
- },
-]
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`#sortProfiles should sort by name 1`] = `
+Array [
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile1",
+ "name": "profile1",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile2",
+ "name": "profile2",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile3",
+ "name": "profile3",
+ "parentKey": undefined,
+ },
+]
+`;
+
+exports[`#sortProfiles should sort single branch 1`] = `
+Array [
+ Object {
+ "childrenCount": 1,
+ "depth": 1,
+ "key": "profile1",
+ "name": "profile1",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 1,
+ "depth": 2,
+ "key": "profile3",
+ "name": "profile3",
+ "parentKey": "profile1",
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 3,
+ "key": "profile2",
+ "name": "profile2",
+ "parentKey": "profile3",
+ },
+]
+`;
+
+exports[`#sortProfiles should sort when no parents 1`] = `
+Array [
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile1",
+ "name": "profile1",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile2",
+ "name": "profile2",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile3",
+ "name": "profile3",
+ "parentKey": undefined,
+ },
+]
+`;
+
+exports[`#sortProfiles should sort with children 1`] = `
+Array [
+ Object {
+ "childrenCount": 2,
+ "depth": 1,
+ "key": "parent",
+ "name": "parent",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 2,
+ "key": "child1",
+ "name": "child1",
+ "parentKey": "parent",
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 2,
+ "key": "child2",
+ "name": "child2",
+ "parentKey": "parent",
+ },
+]
+`;
+
+exports[`#sortProfiles sorts partial set of inherited profiles 1`] = `
+Array [
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "foo",
+ "name": "foo",
+ "parentKey": "bar",
+ },
+]
+`;
+
+exports[`#sortProfiles sorts partial set of inherited profiles 2`] = `
+Array [
+ Object {
+ "childrenCount": 0,
+ "depth": 1,
+ "key": "profile1",
+ "name": "profile1",
+ "parentKey": "x",
+ },
+ Object {
+ "childrenCount": 1,
+ "depth": 1,
+ "key": "profile2",
+ "name": "profile2",
+ "parentKey": undefined,
+ },
+ Object {
+ "childrenCount": 0,
+ "depth": 2,
+ "key": "profile3",
+ "name": "profile3",
+ "parentKey": "profile2",
+ },
+]
+`;
+++ /dev/null
-/*
- * 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 { sortProfiles } from '../utils';
-
-function createProfile(key, parentKey) {
- return { name: key, key, parentKey };
-}
-
-describe('#sortProfiles', () => {
- it('should sort when no parents', () => {
- const profile1 = createProfile('profile1');
- const profile2 = createProfile('profile2');
- const profile3 = createProfile('profile3');
- expect(sortProfiles([profile1, profile2, profile3])).toMatchSnapshot();
- });
-
- it('should sort by name', () => {
- const profile1 = createProfile('profile1');
- const profile2 = createProfile('profile2');
- const profile3 = createProfile('profile3');
- expect(sortProfiles([profile3, profile1, profile2])).toMatchSnapshot();
- });
-
- it('should sort with children', () => {
- const child1 = createProfile('child1', 'parent');
- const child2 = createProfile('child2', 'parent');
- const parent = createProfile('parent');
- expect(sortProfiles([child1, child2, parent])).toMatchSnapshot();
- });
-
- it('should sort single branch', () => {
- const profile1 = createProfile('profile1');
- const profile2 = createProfile('profile2', 'profile3');
- const profile3 = createProfile('profile3', 'profile1');
- expect(sortProfiles([profile3, profile2, profile1])).toMatchSnapshot();
- });
-
- it('sorts partial set of inherited profiles', () => {
- const foo = createProfile('foo', 'bar');
- expect(sortProfiles([foo]), ['foo']);
-
- const profile1 = createProfile('profile1', 'x');
- const profile2 = createProfile('profile2');
- const profile3 = createProfile('profile3', 'profile2');
- expect(sortProfiles([profile1, profile2, profile3])).toMatchSnapshot();
- });
-});
--- /dev/null
+/*
+ * 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 { sortProfiles } from '../utils';
+import { IProfile } from '../types';
+
+function createProfile(key: string, parentKey?: string) {
+ return { name: key, key, parentKey } as IProfile;
+}
+
+describe('#sortProfiles', () => {
+ it('should sort when no parents', () => {
+ const profile1 = createProfile('profile1');
+ const profile2 = createProfile('profile2');
+ const profile3 = createProfile('profile3');
+ expect(sortProfiles([profile1, profile2, profile3])).toMatchSnapshot();
+ });
+
+ it('should sort by name', () => {
+ const profile1 = createProfile('profile1');
+ const profile2 = createProfile('profile2');
+ const profile3 = createProfile('profile3');
+ expect(sortProfiles([profile3, profile1, profile2])).toMatchSnapshot();
+ });
+
+ it('should sort with children', () => {
+ const child1 = createProfile('child1', 'parent');
+ const child2 = createProfile('child2', 'parent');
+ const parent = createProfile('parent');
+ expect(sortProfiles([child1, child2, parent])).toMatchSnapshot();
+ });
+
+ it('should sort single branch', () => {
+ const profile1 = createProfile('profile1');
+ const profile2 = createProfile('profile2', 'profile3');
+ const profile3 = createProfile('profile3', 'profile1');
+ expect(sortProfiles([profile3, profile2, profile1])).toMatchSnapshot();
+ });
+
+ it('sorts partial set of inherited profiles', () => {
+ const foo = createProfile('foo', 'bar');
+ expect(sortProfiles([foo])).toMatchSnapshot();
+
+ const profile1 = createProfile('profile1', 'x');
+ const profile2 = createProfile('profile2');
+ const profile3 = createProfile('profile3', 'profile2');
+ expect(sortProfiles([profile1, profile2, profile3])).toMatchSnapshot();
+ });
+});
+++ /dev/null
-/*
- * 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 moment from 'moment';
-import ChangesList from './ChangesList';
-import { translate } from '../../../helpers/l10n';
-import { getRulesUrl } from '../../../helpers/urls';
-
-/*::
-type Props = {
- events: Array<{
- action: string,
- authorName: string,
- date: string,
- params?: {},
- ruleKey: string,
- ruleName: string
- }>,
- organization: ?string
-};
-*/
-
-export default class Changelog extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- let isEvenRow = false;
-
- const rows = this.props.events.map((event, index) => {
- const prev = index > 0 ? this.props.events[index - 1] : null;
- const isSameDate = prev != null && moment(prev.date).diff(event.date, 'seconds') < 10;
- const isBulkChange =
- prev != null &&
- isSameDate &&
- prev.authorName === event.authorName &&
- prev.action === event.action;
-
- if (!isBulkChange) {
- isEvenRow = !isEvenRow;
- }
-
- const className = 'js-profile-changelog-event ' + (isEvenRow ? 'even' : 'odd');
-
- return (
- <tr key={index} className={className}>
- <td className="thin nowrap">
- {!isBulkChange && moment(event.date).format('LLL')}
- </td>
-
- <td className="thin nowrap">
- {!isBulkChange &&
- (event.authorName
- ? <span>
- {event.authorName}
- </span>
- : <span className="note">System</span>)}
- </td>
-
- <td className="thin nowrap">
- {!isBulkChange && translate('quality_profiles.changelog', event.action)}
- </td>
-
- <td style={{ lineHeight: '1.5' }}>
- <Link to={getRulesUrl({ rule_key: event.ruleKey }, this.props.organization)}>
- {event.ruleName}
- </Link>
- </td>
-
- <td className="thin nowrap">
- <ChangesList changes={event.params} />
- </td>
- </tr>
- );
- });
-
- return (
- <table className="data zebra-hover">
- <thead>
- <tr>
- <th className="thin nowrap">
- {translate('date')} <i className="icon-sort-desc" />
- </th>
- <th className="thin nowrap">
- {translate('user')}
- </th>
- <th className="thin nowrap">
- {translate('action')}
- </th>
- <th>
- {translate('rule')}
- </th>
- <th className="thin nowrap">
- {translate('parameters')}
- </th>
- </tr>
- </thead>
- <tbody>
- {rows}
- </tbody>
- </table>
- );
- }
-}
--- /dev/null
+/*
+ * 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 * as moment from 'moment';
+import ChangesList from './ChangesList';
+import { translate } from '../../../helpers/l10n';
+import { getRulesUrl } from '../../../helpers/urls';
+import { IProfileChangelogEvent } from '../types';
+
+interface Props {
+ events: IProfileChangelogEvent[];
+ organization: string | null;
+}
+
+export default function Changelog(props: Props) {
+ let isEvenRow = false;
+
+ const rows = props.events.map((event, index) => {
+ const prev = index > 0 ? props.events[index - 1] : null;
+ const isSameDate = prev != null && moment(prev.date).diff(event.date, 'seconds') < 10;
+ const isBulkChange =
+ prev != null &&
+ isSameDate &&
+ prev.authorName === event.authorName &&
+ prev.action === event.action;
+
+ if (!isBulkChange) {
+ isEvenRow = !isEvenRow;
+ }
+
+ const className = 'js-profile-changelog-event ' + (isEvenRow ? 'even' : 'odd');
+
+ return (
+ <tr key={index} className={className}>
+ <td className="thin nowrap">
+ {!isBulkChange && moment(event.date).format('LLL')}
+ </td>
+
+ <td className="thin nowrap">
+ {!isBulkChange &&
+ (event.authorName
+ ? <span>
+ {event.authorName}
+ </span>
+ : <span className="note">System</span>)}
+ </td>
+
+ <td className="thin nowrap">
+ {!isBulkChange && translate('quality_profiles.changelog', event.action)}
+ </td>
+
+ <td style={{ lineHeight: '1.5' }}>
+ <Link to={getRulesUrl({ rule_key: event.ruleKey }, props.organization)}>
+ {event.ruleName}
+ </Link>
+ </td>
+
+ <td className="thin nowrap">
+ {event.params && <ChangesList changes={event.params} />}
+ </td>
+ </tr>
+ );
+ });
+
+ return (
+ <table className="data zebra-hover">
+ <thead>
+ <tr>
+ <th className="thin nowrap">
+ {translate('date')} <i className="icon-sort-desc" />
+ </th>
+ <th className="thin nowrap">
+ {translate('user')}
+ </th>
+ <th className="thin nowrap">
+ {translate('action')}
+ </th>
+ <th>
+ {translate('rule')}
+ </th>
+ <th className="thin nowrap">
+ {translate('parameters')}
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {rows}
+ </tbody>
+ </table>
+ );
+}
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-import Changelog from './Changelog';
-import ChangelogSearch from './ChangelogSearch';
-import ChangelogEmpty from './ChangelogEmpty';
-import { getProfileChangelog } from '../../../api/quality-profiles';
-import { translate } from '../../../helpers/l10n';
-import { getProfileChangelogPath } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- location: {
- query: {
- since?: string,
- to?: string
- }
- },
- organization: ?string,
- profile: Profile
-};
-*/
-
-/*::
-type State = {
- events?: Array<*>,
- loading: boolean,
- page?: number,
- total?: number
-};
-*/
-
-export default class ChangelogContainer extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
-
- static contextTypes = {
- router: PropTypes.object
- };
-
- state /*: State */ = {
- loading: true
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadChangelog();
- }
-
- componentDidUpdate(prevProps /*: Props */) {
- if (prevProps.location !== this.props.location) {
- this.loadChangelog();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadChangelog() {
- this.setState({ loading: true });
- const { query } = this.props.location;
- const data /*: Object */ = { profileKey: this.props.profile.key };
- if (query.since) {
- data.since = query.since;
- }
- if (query.to) {
- data.to = query.to;
- }
-
- getProfileChangelog(data).then(r => {
- if (this.mounted) {
- this.setState({
- events: r.events,
- total: r.total,
- page: r.p,
- loading: false
- });
- }
- });
- }
-
- loadMore(e /*: SyntheticInputEvent */) {
- e.preventDefault();
- e.target.blur();
-
- this.setState({ loading: true });
- const { query } = this.props.location;
- const data /*: Object */ = {
- profileKey: this.props.profile.key,
- p: this.state.page + 1
- };
- if (query.since) {
- data.since = query.since;
- }
- if (query.to) {
- data.to = query.to;
- }
-
- getProfileChangelog(data).then(r => {
- if (this.mounted && this.state.events) {
- this.setState({
- events: [...this.state.events, ...r.events],
- total: r.total,
- page: r.p,
- loading: false
- });
- }
- });
- }
-
- handleFromDateChange = (fromDate /*: string | void */) => {
- const path = getProfileChangelogPath(
- this.props.profile.name,
- this.props.profile.language,
- this.props.organization,
- {
- since: fromDate,
- to: this.props.location.query.to
- }
- );
- this.context.router.push(path);
- };
-
- handleToDateChange = (toDate /*: string | void */) => {
- const path = getProfileChangelogPath(
- this.props.profile.name,
- this.props.profile.language,
- this.props.organization,
- {
- since: this.props.location.query.since,
- to: toDate
- }
- );
- this.context.router.push(path);
- };
-
- handleReset = () => {
- const path = getProfileChangelogPath(
- this.props.profile.name,
- this.props.profile.language,
- this.props.organization
- );
- this.context.router.push(path);
- };
-
- render() {
- const { query } = this.props.location;
-
- const shouldDisplayFooter =
- this.state.events != null &&
- this.state.total != null &&
- this.state.events.length < this.state.total;
-
- return (
- <div className="quality-profile-box js-profile-changelog">
- <header className="spacer-bottom">
- <ChangelogSearch
- fromDate={query.since}
- toDate={query.to}
- onFromDateChange={this.handleFromDateChange}
- onToDateChange={this.handleToDateChange}
- onReset={this.handleReset}
- />
-
- {this.state.loading && <i className="spinner spacer-left" />}
- </header>
-
- {this.state.events != null && this.state.events.length === 0 && <ChangelogEmpty />}
-
- {this.state.events != null &&
- this.state.events.length > 0 &&
- <Changelog events={this.state.events} organization={this.props.organization} />}
-
- {shouldDisplayFooter &&
- <footer className="text-center spacer-top small">
- <a href="#" onClick={this.loadMore.bind(this)}>
- {translate('show_more')}
- </a>
- </footer>}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 PropTypes from 'prop-types';
+import Changelog from './Changelog';
+import ChangelogSearch from './ChangelogSearch';
+import ChangelogEmpty from './ChangelogEmpty';
+import { getProfileChangelog } from '../../../api/quality-profiles';
+import { translate } from '../../../helpers/l10n';
+import { getProfileChangelogPath } from '../utils';
+import { IProfile, IProfileChangelogEvent } from '../types';
+
+interface Props {
+ location: {
+ query: {
+ since?: string;
+ to?: string;
+ };
+ };
+ organization: string | null;
+ profile: IProfile;
+}
+
+interface State {
+ events?: IProfileChangelogEvent[];
+ loading: boolean;
+ page?: number;
+ total?: number;
+}
+
+export default class ChangelogContainer extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ static contextTypes = {
+ router: PropTypes.object
+ };
+
+ state: State = {
+ loading: true
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadChangelog();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.location !== this.props.location) {
+ this.loadChangelog();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadChangelog() {
+ this.setState({ loading: true });
+ const { query } = this.props.location;
+ const data: any = { profileKey: this.props.profile.key };
+ if (query.since) {
+ data.since = query.since;
+ }
+ if (query.to) {
+ data.to = query.to;
+ }
+
+ getProfileChangelog(data).then((r: any) => {
+ if (this.mounted) {
+ this.setState({
+ events: r.events,
+ total: r.total,
+ page: r.p,
+ loading: false
+ });
+ }
+ });
+ }
+
+ loadMore(event: React.SyntheticEvent<HTMLElement>) {
+ event.preventDefault();
+ event.currentTarget.blur();
+
+ if (this.state.page != null) {
+ this.setState({ loading: true });
+ const { query } = this.props.location;
+ const data: any = {
+ profileKey: this.props.profile.key,
+ p: this.state.page + 1
+ };
+ if (query.since) {
+ data.since = query.since;
+ }
+ if (query.to) {
+ data.to = query.to;
+ }
+
+ getProfileChangelog(data).then((r: any) => {
+ if (this.mounted && this.state.events) {
+ this.setState({
+ events: [...this.state.events, ...r.events],
+ total: r.total,
+ page: r.p,
+ loading: false
+ });
+ }
+ });
+ }
+ }
+
+ handleFromDateChange = (fromDate?: string) => {
+ const path = getProfileChangelogPath(
+ this.props.profile.name,
+ this.props.profile.language,
+ this.props.organization,
+ {
+ since: fromDate,
+ to: this.props.location.query.to
+ }
+ );
+ this.context.router.push(path);
+ };
+
+ handleToDateChange = (toDate?: string) => {
+ const path = getProfileChangelogPath(
+ this.props.profile.name,
+ this.props.profile.language,
+ this.props.organization,
+ {
+ since: this.props.location.query.since,
+ to: toDate
+ }
+ );
+ this.context.router.push(path);
+ };
+
+ handleReset = () => {
+ const path = getProfileChangelogPath(
+ this.props.profile.name,
+ this.props.profile.language,
+ this.props.organization
+ );
+ this.context.router.push(path);
+ };
+
+ render() {
+ const { query } = this.props.location;
+
+ const shouldDisplayFooter =
+ this.state.events != null &&
+ this.state.total != null &&
+ this.state.events.length < this.state.total;
+
+ return (
+ <div className="quality-profile-box js-profile-changelog">
+ <header className="spacer-bottom">
+ <ChangelogSearch
+ fromDate={query.since}
+ toDate={query.to}
+ onFromDateChange={this.handleFromDateChange}
+ onToDateChange={this.handleToDateChange}
+ onReset={this.handleReset}
+ />
+
+ {this.state.loading && <i className="spinner spacer-left" />}
+ </header>
+
+ {this.state.events != null && this.state.events.length === 0 && <ChangelogEmpty />}
+
+ {this.state.events != null &&
+ this.state.events.length > 0 &&
+ <Changelog events={this.state.events} organization={this.props.organization} />}
+
+ {shouldDisplayFooter &&
+ <footer className="text-center spacer-top small">
+ <a href="#" onClick={this.loadMore.bind(this)}>
+ {translate('show_more')}
+ </a>
+ </footer>}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { translate } from '../../../helpers/l10n';
-
-export default class ChangelogEmpty extends React.PureComponent {
- render() {
- return (
- <div className="big-spacer-top">
- {translate('no_results')}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { translate } from '../../../helpers/l10n';
+
+export default function ChangelogEmpty() {
+ return (
+ <div className="big-spacer-top">
+ {translate('no_results')}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 DateInput from '../../../components/controls/DateInput';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- fromDate?: string,
- toDate?: string,
- onFromDateChange: () => void,
- onReset: () => void,
- onToDateChange: () => void
-};
-*/
-
-export default class ChangelogSearch extends React.PureComponent {
- /*:: props: Props; */
-
- handleResetClick(e /*: SyntheticInputEvent */) {
- e.preventDefault();
- e.target.blur();
- this.props.onReset();
- }
-
- render() {
- return (
- <div className="display-inline-block" id="quality-profile-changelog-form">
- <DateInput
- name="since"
- value={this.props.fromDate}
- placeholder="From"
- onChange={this.props.onFromDateChange}
- />
- {' — '}
- <DateInput
- name="to"
- value={this.props.toDate}
- placeholder="To"
- onChange={this.props.onToDateChange}
- />
- <button className="spacer-left" onClick={this.handleResetClick.bind(this)}>
- {translate('reset_verb')}
- </button>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 DateInput from '../../../components/controls/DateInput';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ fromDate?: string;
+ toDate?: string;
+ onFromDateChange: () => void;
+ onReset: () => void;
+ onToDateChange: () => void;
+}
+
+export default class ChangelogSearch extends React.PureComponent<Props> {
+ handleResetClick(event: React.SyntheticEvent<HTMLElement>) {
+ event.preventDefault();
+ event.currentTarget.blur();
+ this.props.onReset();
+ }
+
+ render() {
+ return (
+ <div className="display-inline-block" id="quality-profile-changelog-form">
+ <DateInput
+ name="since"
+ value={this.props.fromDate}
+ placeholder="From"
+ onChange={this.props.onFromDateChange}
+ />
+ {' — '}
+ <DateInput
+ name="to"
+ value={this.props.toDate}
+ placeholder="To"
+ onChange={this.props.onToDateChange}
+ />
+ <button className="spacer-left" onClick={this.handleResetClick.bind(this)}>
+ {translate('reset_verb')}
+ </button>
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 SeverityChange from './SeverityChange';
-import ParameterChange from './ParameterChange';
-
-/*::
-type Props = {
- changes: { [string]: ?string }
-};
-*/
-
-export default class ChangesList extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { changes } = this.props;
-
- return (
- <ul>
- {Object.keys(changes).map(key =>
- <li key={key}>
- {key === 'severity'
- ? <SeverityChange severity={changes[key]} />
- : <ParameterChange name={key} value={changes[key]} />}
- </li>
- )}
- </ul>
- );
- }
-}
--- /dev/null
+/*
+ * 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 SeverityChange from './SeverityChange';
+import ParameterChange from './ParameterChange';
+
+interface Props {
+ changes: { [change: string]: string | null };
+}
+
+export default function ChangesList({ changes }: Props) {
+ return (
+ <ul>
+ {Object.keys(changes).map(key =>
+ <li key={key}>
+ {key === 'severity'
+ ? <SeverityChange severity={changes[key]} />
+ : <ParameterChange name={key} value={changes[key]} />}
+ </li>
+ )}
+ </ul>
+ );
+}
+++ /dev/null
-/*
- * 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 { translateWithParameters } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- name: string,
- value: ?string
-};
-*/
-
-export default class ParameterChange extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { name, value } = this.props;
-
- if (value == null) {
- return (
- <div style={{ whiteSpace: 'normal' }}>
- {translateWithParameters(
- 'quality_profiles.changelog.parameter_reset_to_default_value',
- name
- )}
- </div>
- );
- }
-
- return (
- <div style={{ whiteSpace: 'normal' }}>
- {translateWithParameters('quality_profiles.parameter_set_to', name, value)}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { translateWithParameters } from '../../../helpers/l10n';
+
+interface Props {
+ name: string;
+ value: string | null;
+}
+
+export default function ParameterChange({ name, value }: Props) {
+ if (value == null) {
+ return (
+ <div style={{ whiteSpace: 'normal' }}>
+ {translateWithParameters(
+ 'quality_profiles.changelog.parameter_reset_to_default_value',
+ name
+ )}
+ </div>
+ );
+ }
+
+ return (
+ <div style={{ whiteSpace: 'normal' }}>
+ {translateWithParameters('quality_profiles.parameter_set_to', name, value)}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 SeverityHelper from '../../../components/shared/SeverityHelper';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- severity: ?string
-};
-*/
-
-export default class SeverityChange extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- return (
- <div>
- {translate('quality_profiles.severity_set_to')}{' '}
- <SeverityHelper severity={this.props.severity} />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 SeverityHelper from '../../../components/shared/SeverityHelper';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ severity: string | null;
+}
+
+export default function SeverityChange({ severity }: Props) {
+ return (
+ <div>
+ {translate('quality_profiles.severity_set_to')} <SeverityHelper severity={severity} />
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import Changelog from '../Changelog';
-import ChangesList from '../ChangesList';
-
-function createEvent(overrides) {
- return {
- date: '2016-01-01',
- authorName: 'John',
- action: 'ACTIVATED',
- ruleKey: 'squid1234',
- ruleName: 'Do not do this',
- params: {},
- ...overrides
- };
-}
-
-it('should render events', () => {
- const events = [createEvent(), createEvent()];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.find('tbody').find('tr').length).toBe(2);
-});
-
-it('should render event date', () => {
- const events = [createEvent()];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.text()).toContain('2016');
-});
-
-it('should render author', () => {
- const events = [createEvent()];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.text()).toContain('John');
-});
-
-it('should render system author', () => {
- const events = [createEvent({ authorName: undefined })];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.text()).toContain('System');
-});
-
-it('should render action', () => {
- const events = [createEvent()];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.text()).toContain('ACTIVATED');
-});
-
-it('should render rule', () => {
- const events = [createEvent()];
- const changelog = shallow(<Changelog events={events} />);
- expect(changelog.find('Link').prop('to')).toContain('rule_key=squid1234');
-});
-
-it('should render ChangesList', () => {
- const params = { severity: 'BLOCKER' };
- const events = [createEvent({ params })];
- const changelog = shallow(<Changelog events={events} />);
- const changesList = changelog.find(ChangesList);
- expect(changesList.length).toBe(1);
- expect(changesList.prop('changes')).toBe(params);
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import Changelog from '../Changelog';
+import ChangesList from '../ChangesList';
+import { IProfileChangelogEvent } from '../../types';
+
+function createEvent(overrides?: { [p: string]: any }): IProfileChangelogEvent {
+ return {
+ date: '2016-01-01',
+ authorName: 'John',
+ action: 'ACTIVATED',
+ ruleKey: 'squid1234',
+ ruleName: 'Do not do this',
+ params: {},
+ organization: null,
+ ...overrides
+ };
+}
+
+it('should render events', () => {
+ const events = [createEvent(), createEvent()];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.find('tbody').find('tr').length).toBe(2);
+});
+
+it('should render event date', () => {
+ const events = [createEvent()];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.text()).toContain('2016');
+});
+
+it('should render author', () => {
+ const events = [createEvent()];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.text()).toContain('John');
+});
+
+it('should render system author', () => {
+ const events = [createEvent({ authorName: undefined })];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.text()).toContain('System');
+});
+
+it('should render action', () => {
+ const events = [createEvent()];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.text()).toContain('ACTIVATED');
+});
+
+it('should render rule', () => {
+ const events = [createEvent()];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ expect(changelog.find('Link').prop('to')).toContain('rule_key=squid1234');
+});
+
+it('should render ChangesList', () => {
+ const params = { severity: 'BLOCKER' };
+ const events = [createEvent({ params })];
+ const changelog = shallow(<Changelog events={events} organization={null} />);
+ const changesList = changelog.find(ChangesList);
+ expect(changesList.length).toBe(1);
+ expect(changesList.prop('changes')).toBe(params);
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import ChangelogSearch from '../ChangelogSearch';
-import DateInput from '../../../../components/controls/DateInput';
-import { click } from '../../../../helpers/testUtils';
-
-it('should render DateInput', () => {
- const onFromDateChange = jest.fn();
- const onToDateChange = jest.fn();
- const output = shallow(
- <ChangelogSearch
- fromDate="2016-01-01"
- toDate="2016-05-05"
- onFromDateChange={onFromDateChange}
- onToDateChange={onToDateChange}
- onReset={jest.fn()}
- />
- );
- const dateInputs = output.find(DateInput);
- expect(dateInputs.length).toBe(2);
- expect(dateInputs.at(0).prop('value')).toBe('2016-01-01');
- expect(dateInputs.at(0).prop('onChange')).toBe(onFromDateChange);
- expect(dateInputs.at(1).prop('value')).toBe('2016-05-05');
- expect(dateInputs.at(1).prop('onChange')).toBe(onToDateChange);
-});
-
-it('should reset', () => {
- const onReset = jest.fn();
- const output = shallow(
- <ChangelogSearch
- fromDate="2016-01-01"
- toDate="2016-05-05"
- onFromDateChange={jest.fn()}
- onToDateChange={jest.fn()}
- onReset={onReset}
- />
- );
- expect(onReset).not.toBeCalled();
- click(output.find('button'));
- expect(onReset).toBeCalled();
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import ChangelogSearch from '../ChangelogSearch';
+import DateInput from '../../../../components/controls/DateInput';
+import { click } from '../../../../helpers/testUtils';
+
+it('should render DateInput', () => {
+ const onFromDateChange = jest.fn();
+ const onToDateChange = jest.fn();
+ const output = shallow(
+ <ChangelogSearch
+ fromDate="2016-01-01"
+ toDate="2016-05-05"
+ onFromDateChange={onFromDateChange}
+ onToDateChange={onToDateChange}
+ onReset={jest.fn()}
+ />
+ );
+ const dateInputs = output.find(DateInput);
+ expect(dateInputs.length).toBe(2);
+ expect(dateInputs.at(0).prop('value')).toBe('2016-01-01');
+ expect(dateInputs.at(0).prop('onChange')).toBe(onFromDateChange);
+ expect(dateInputs.at(1).prop('value')).toBe('2016-05-05');
+ expect(dateInputs.at(1).prop('onChange')).toBe(onToDateChange);
+});
+
+it('should reset', () => {
+ const onReset = jest.fn();
+ const output = shallow(
+ <ChangelogSearch
+ fromDate="2016-01-01"
+ toDate="2016-05-05"
+ onFromDateChange={jest.fn()}
+ onToDateChange={jest.fn()}
+ onReset={onReset}
+ />
+ );
+ expect(onReset).not.toBeCalled();
+ click(output.find('button'));
+ expect(onReset).toBeCalled();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import ChangesList from '../ChangesList';
-import SeverityChange from '../SeverityChange';
-import ParameterChange from '../ParameterChange';
-
-it('should render changes', () => {
- const changes = { severity: 'BLOCKER', foo: 'bar' };
- const output = shallow(<ChangesList changes={changes} />);
- expect(output.find('li').length).toBe(2);
-});
-
-it('should render severity change', () => {
- const changes = { severity: 'BLOCKER' };
- const output = shallow(<ChangesList changes={changes} />).find(SeverityChange);
- expect(output.length).toBe(1);
- expect(output.prop('severity')).toBe('BLOCKER');
-});
-
-it('should render parameter change', () => {
- const changes = { foo: 'bar' };
- const output = shallow(<ChangesList changes={changes} />).find(ParameterChange);
- expect(output.length).toBe(1);
- expect(output.prop('name')).toBe('foo');
- expect(output.prop('value')).toBe('bar');
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import ChangesList from '../ChangesList';
+import SeverityChange from '../SeverityChange';
+import ParameterChange from '../ParameterChange';
+
+it('should render changes', () => {
+ const changes = { severity: 'BLOCKER', foo: 'bar' };
+ const output = shallow(<ChangesList changes={changes} />);
+ expect(output.find('li').length).toBe(2);
+});
+
+it('should render severity change', () => {
+ const changes = { severity: 'BLOCKER' };
+ const output = shallow(<ChangesList changes={changes} />).find(SeverityChange);
+ expect(output.length).toBe(1);
+ expect(output.prop('severity')).toBe('BLOCKER');
+});
+
+it('should render parameter change', () => {
+ const changes = { foo: 'bar' };
+ const output = shallow(<ChangesList changes={changes} />).find(ParameterChange);
+ expect(output.length).toBe(1);
+ expect(output.prop('name')).toBe('foo');
+ expect(output.prop('value')).toBe('bar');
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import ParameterChange from '../ParameterChange';
-
-it('should render different messages', () => {
- const first = shallow(<ParameterChange name="foo" />);
- const second = shallow(<ParameterChange name="foo" value="bar" />);
- expect(first.text()).not.toBe(second.text());
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import ParameterChange from '../ParameterChange';
+
+it('should render different messages', () => {
+ const first = shallow(<ParameterChange name="foo" value={null} />);
+ const second = shallow(<ParameterChange name="foo" value="bar" />);
+ expect(first.text()).not.toBe(second.text());
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import SeverityChange from '../SeverityChange';
-import SeverityHelper from '../../../../components/shared/SeverityHelper';
-
-it('should render SeverityHelper', () => {
- const output = shallow(<SeverityChange severity="BLOCKER" />).find(SeverityHelper);
- expect(output.length).toBe(1);
- expect(output.prop('severity')).toBe('BLOCKER');
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import SeverityChange from '../SeverityChange';
+import SeverityHelper from '../../../../components/shared/SeverityHelper';
+
+it('should render SeverityHelper', () => {
+ const output = shallow(<SeverityChange severity="BLOCKER" />).find(SeverityHelper);
+ expect(output.length).toBe(1);
+ expect(output.prop('severity')).toBe('BLOCKER');
+});
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-import ComparisonForm from './ComparisonForm';
-import ComparisonResults from './ComparisonResults';
-import { compareProfiles } from '../../../api/quality-profiles';
-import { getProfileComparePath } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- location: { query: { withKey?: string } },
- organization: ?string,
- profile: Profile,
- profiles: Array<Profile>
-};
-*/
-
-/*::
-type State = {
- loading: boolean,
- left?: { name: string },
- right?: { name: string },
- inLeft?: Array<*>,
- inRight?: Array<*>,
- modified?: Array<*>
-};
-*/
-
-export default class ComparisonContainer extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- /*:: state: State; */
-
- static contextTypes = {
- router: PropTypes.object
- };
-
- constructor(props /*: Props */) {
- super(props);
- this.state = { loading: false };
- }
-
- componentDidMount() {
- this.mounted = true;
- this.loadResults();
- }
-
- componentDidUpdate(prevProps /*: Props */) {
- if (prevProps.profile !== this.props.profile || prevProps.location !== this.props.location) {
- this.loadResults();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadResults() {
- const { withKey } = this.props.location.query;
- if (!withKey) {
- this.setState({ left: undefined, loading: false });
- return;
- }
-
- this.setState({ loading: true });
- compareProfiles(this.props.profile.key, withKey).then(r => {
- if (this.mounted) {
- this.setState({
- left: r.left,
- right: r.right,
- inLeft: r.inLeft,
- inRight: r.inRight,
- modified: r.modified,
- loading: false
- });
- }
- });
- }
-
- handleCompare = (withKey /*: string */) => {
- const path = getProfileComparePath(
- this.props.profile.name,
- this.props.profile.language,
- this.props.organization,
- withKey
- );
- this.context.router.push(path);
- };
-
- render() {
- const { profile, profiles, location } = this.props;
- const { withKey } = location.query;
- const { left, right, inLeft, inRight, modified } = this.state;
-
- return (
- <div className="quality-profile-box js-profile-comparison">
- <header className="spacer-bottom">
- <ComparisonForm
- withKey={withKey}
- profile={profile}
- profiles={profiles}
- onCompare={this.handleCompare}
- />
-
- {this.state.loading && <i className="spinner spacer-left" />}
- </header>
-
- {left != null &&
- <ComparisonResults
- left={left}
- right={right}
- inLeft={inLeft}
- inRight={inRight}
- modified={modified}
- organization={this.props.organization}
- />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 PropTypes from 'prop-types';
+import ComparisonForm from './ComparisonForm';
+import ComparisonResults from './ComparisonResults';
+import { compareProfiles } from '../../../api/quality-profiles';
+import { getProfileComparePath } from '../utils';
+import { IProfile } from '../types';
+
+interface Props {
+ location: { query: { withKey?: string } };
+ organization: string | null;
+ profile: IProfile;
+ profiles: IProfile[];
+}
+
+type Params = { [p: string]: string };
+
+interface State {
+ loading: boolean;
+ left?: { name: string };
+ right?: { name: string };
+ inLeft?: Array<{ key: string; name: string; severity: string }>;
+ inRight?: Array<{ key: string; name: string; severity: string }>;
+ modified?: Array<{
+ key: string;
+ name: string;
+ left: { params: Params; severity: string };
+ right: { params: Params; severity: string };
+ }>;
+}
+
+export default class ComparisonContainer extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ static contextTypes = {
+ router: PropTypes.object
+ };
+
+ constructor(props: Props) {
+ super(props);
+ this.state = { loading: false };
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadResults();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.profile !== this.props.profile || prevProps.location !== this.props.location) {
+ this.loadResults();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadResults() {
+ const { withKey } = this.props.location.query;
+ if (!withKey) {
+ this.setState({ left: undefined, loading: false });
+ return;
+ }
+
+ this.setState({ loading: true });
+ compareProfiles(this.props.profile.key, withKey).then((r: any) => {
+ if (this.mounted) {
+ this.setState({
+ left: r.left,
+ right: r.right,
+ inLeft: r.inLeft,
+ inRight: r.inRight,
+ modified: r.modified,
+ loading: false
+ });
+ }
+ });
+ }
+
+ handleCompare = (withKey: string) => {
+ const path = getProfileComparePath(
+ this.props.profile.name,
+ this.props.profile.language,
+ this.props.organization,
+ withKey
+ );
+ this.context.router.push(path);
+ };
+
+ render() {
+ const { profile, profiles, location } = this.props;
+ const { withKey } = location.query;
+ const { left, right, inLeft, inRight, modified } = this.state;
+
+ return (
+ <div className="quality-profile-box js-profile-comparison">
+ <header className="spacer-bottom">
+ <ComparisonForm
+ withKey={withKey}
+ profile={profile}
+ profiles={profiles}
+ onCompare={this.handleCompare}
+ />
+
+ {this.state.loading && <i className="spinner spacer-left" />}
+ </header>
+
+ {left != null &&
+ inLeft != null &&
+ right != null &&
+ inRight != null &&
+ modified != null &&
+ <ComparisonResults
+ left={left}
+ right={right}
+ inLeft={inLeft}
+ inRight={inRight}
+ modified={modified}
+ organization={this.props.organization}
+ />}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { translate } from '../../../helpers/l10n';
-
-export default class ComparisonEmpty extends React.PureComponent {
- render() {
- return (
- <div className="big-spacer-top">
- {translate('quality_profile.empty_comparison')}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { translate } from '../../../helpers/l10n';
+
+export default function ComparisonEmpty() {
+ return (
+ <div className="big-spacer-top">
+ {translate('quality_profile.empty_comparison')}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 Select from 'react-select';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- profile: Profile,
- profiles: Array<Profile>,
- onCompare: string => void,
- withKey: string
-};
-*/
-
-export default class ComparisonForm extends React.PureComponent {
- /*:: props: Props; */
-
- handleChange(option /*: { value: string } */) {
- this.props.onCompare(option.value);
- }
-
- render() {
- const { profile, profiles, withKey } = this.props;
- const options = profiles
- .filter(p => p.language === profile.language && p !== profile)
- .map(p => ({ value: p.key, label: p.name }));
-
- return (
- <div className="display-inline-block">
- <label className="spacer-right">
- {translate('quality_profiles.compare_with')}
- </label>
- <Select
- value={withKey}
- options={options}
- clearable={false}
- className="input-large"
- onChange={this.handleChange.bind(this)}
- />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Select from 'react-select';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ profile: IProfile;
+ profiles: IProfile[];
+ onCompare: (rule: string) => void;
+ withKey?: string;
+}
+
+export default class ComparisonForm extends React.PureComponent<Props> {
+ handleChange(option: { value: string }) {
+ this.props.onCompare(option.value);
+ }
+
+ render() {
+ const { profile, profiles, withKey } = this.props;
+ const options = profiles
+ .filter(p => p.language === profile.language && p !== profile)
+ .map(p => ({ value: p.key, label: p.name }));
+
+ return (
+ <div className="display-inline-block">
+ <label className="spacer-right">
+ {translate('quality_profiles.compare_with')}
+ </label>
+ <Select
+ value={withKey}
+ options={options}
+ clearable={false}
+ className="input-large"
+ onChange={this.handleChange.bind(this)}
+ />
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 ComparisonEmpty from './ComparisonEmpty';
-import SeverityIcon from '../../../components/shared/SeverityIcon';
-import { translateWithParameters } from '../../../helpers/l10n';
-import { getRulesUrl } from '../../../helpers/urls';
-
-/*::
-type Params = { [string]: string };
-*/
-
-/*::
-type Props = {
- left: { name: string },
- right: { name: string },
- inLeft: Array<*>,
- inRight: Array<*>,
- modified: Array<*>,
- organization: ?string
-};
-*/
-
-export default class ComparisonResults extends React.PureComponent {
- /*:: props: Props; */
-
- renderRule(rule /*: { key: string, name: string } */, severity /*: string */) {
- return (
- <div>
- <SeverityIcon severity={severity} />{' '}
- <Link to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}>{rule.name}</Link>
- </div>
- );
- }
-
- renderParameters(params /*: Params */) {
- if (!params) {
- return null;
- }
- return (
- <ul>
- {Object.keys(params).map(key =>
- <li key={key} className="spacer-top">
- <code>
- {key}
- {': '}
- {params[key]}
- </code>
- </li>
- )}
- </ul>
- );
- }
-
- renderLeft() {
- if (this.props.inLeft.length === 0) {
- return null;
- }
- const header = (
- <tr key="left-header">
- <td>
- <h6>
- {translateWithParameters(
- 'quality_profiles.x_rules_only_in',
- this.props.inLeft.length
- )}{' '}
- {this.props.left.name}
- </h6>
- </td>
- <td> </td>
- </tr>
- );
- const rows = this.props.inLeft.map(rule =>
- <tr key={`left-${rule.key}`} className="js-comparison-in-left">
- <td>
- {this.renderRule(rule, rule.severity)}
- </td>
- <td> </td>
- </tr>
- );
- return [header, ...rows];
- }
-
- renderRight() {
- if (this.props.inRight.length === 0) {
- return null;
- }
- const header = (
- <tr key="right-header">
- <td> </td>
- <td>
- <h6>
- {translateWithParameters(
- 'quality_profiles.x_rules_only_in',
- this.props.inRight.length
- )}{' '}
- {this.props.right.name}
- </h6>
- </td>
- </tr>
- );
- const rows = this.props.inRight.map(rule =>
- <tr key={`right-${rule.key}`} className="js-comparison-in-right">
- <td> </td>
- <td>
- {this.renderRule(rule, rule.severity)}
- </td>
- </tr>
- );
- return [header, ...rows];
- }
-
- renderModified() {
- if (this.props.modified.length === 0) {
- return null;
- }
- const header = (
- <tr key="modified-header">
- <td colSpan="2" className="text-center">
- <h6>
- {translateWithParameters(
- 'quality_profiles.x_rules_have_different_configuration',
- this.props.modified.length
- )}
- </h6>
- </td>
- </tr>
- );
- const secondHeader = (
- <tr key="modified-second-header">
- <td>
- <h6>
- {this.props.left.name}
- </h6>
- </td>
- <td>
- <h6>
- {this.props.right.name}
- </h6>
- </td>
- </tr>
- );
- const rows = this.props.modified.map(rule =>
- <tr key={`modified-${rule.key}`} className="js-comparison-modified">
- <td>
- {this.renderRule(rule, rule.left.severity)}
- {this.renderParameters(rule.left.params)}
- </td>
- <td>
- {this.renderRule(rule, rule.right.severity)}
- {this.renderParameters(rule.right.params)}
- </td>
- </tr>
- );
- return [header, secondHeader, ...rows];
- }
-
- render() {
- if (!this.props.inLeft.length && !this.props.inRight.length && !this.props.modified.length) {
- return <ComparisonEmpty />;
- }
-
- return (
- <table className="data zebra quality-profile-comparison-table">
- <tbody>
- {this.renderLeft()}
- {this.renderRight()}
- {this.renderModified()}
- </tbody>
- </table>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ComparisonEmpty from './ComparisonEmpty';
+import SeverityIcon from '../../../components/shared/SeverityIcon';
+import { translateWithParameters } from '../../../helpers/l10n';
+import { getRulesUrl } from '../../../helpers/urls';
+
+type Params = { [p: string]: string };
+
+interface Props {
+ left: { name: string };
+ right: { name: string };
+ inLeft: Array<{ key: string; name: string; severity: string }>;
+ inRight: Array<{ key: string; name: string; severity: string }>;
+ modified: Array<{
+ key: string;
+ name: string;
+ left: { params: Params; severity: string };
+ right: { params: Params; severity: string };
+ }>;
+ organization: string | null;
+}
+
+export default class ComparisonResults extends React.PureComponent<Props> {
+ renderRule(rule: { key: string; name: string }, severity: string) {
+ return (
+ <div>
+ <SeverityIcon severity={severity} />{' '}
+ <Link to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}>{rule.name}</Link>
+ </div>
+ );
+ }
+
+ renderParameters(params: Params) {
+ if (!params) {
+ return null;
+ }
+ return (
+ <ul>
+ {Object.keys(params).map(key =>
+ <li key={key} className="spacer-top">
+ <code>
+ {key}
+ {': '}
+ {params[key]}
+ </code>
+ </li>
+ )}
+ </ul>
+ );
+ }
+
+ renderLeft() {
+ if (this.props.inLeft.length === 0) {
+ return null;
+ }
+ const header = (
+ <tr key="left-header">
+ <td>
+ <h6>
+ {translateWithParameters(
+ 'quality_profiles.x_rules_only_in',
+ this.props.inLeft.length
+ )}{' '}
+ {this.props.left.name}
+ </h6>
+ </td>
+ <td> </td>
+ </tr>
+ );
+ const rows = this.props.inLeft.map(rule =>
+ <tr key={`left-${rule.key}`} className="js-comparison-in-left">
+ <td>
+ {this.renderRule(rule, rule.severity)}
+ </td>
+ <td> </td>
+ </tr>
+ );
+ return [header, ...rows];
+ }
+
+ renderRight() {
+ if (this.props.inRight.length === 0) {
+ return null;
+ }
+ const header = (
+ <tr key="right-header">
+ <td> </td>
+ <td>
+ <h6>
+ {translateWithParameters(
+ 'quality_profiles.x_rules_only_in',
+ this.props.inRight.length
+ )}{' '}
+ {this.props.right.name}
+ </h6>
+ </td>
+ </tr>
+ );
+ const rows = this.props.inRight.map(rule =>
+ <tr key={`right-${rule.key}`} className="js-comparison-in-right">
+ <td> </td>
+ <td>
+ {this.renderRule(rule, rule.severity)}
+ </td>
+ </tr>
+ );
+ return [header, ...rows];
+ }
+
+ renderModified() {
+ if (this.props.modified.length === 0) {
+ return null;
+ }
+ const header = (
+ <tr key="modified-header">
+ <td colSpan={2} className="text-center">
+ <h6>
+ {translateWithParameters(
+ 'quality_profiles.x_rules_have_different_configuration',
+ this.props.modified.length
+ )}
+ </h6>
+ </td>
+ </tr>
+ );
+ const secondHeader = (
+ <tr key="modified-second-header">
+ <td>
+ <h6>
+ {this.props.left.name}
+ </h6>
+ </td>
+ <td>
+ <h6>
+ {this.props.right.name}
+ </h6>
+ </td>
+ </tr>
+ );
+ const rows = this.props.modified.map(rule =>
+ <tr key={`modified-${rule.key}`} className="js-comparison-modified">
+ <td>
+ {this.renderRule(rule, rule.left.severity)}
+ {this.renderParameters(rule.left.params)}
+ </td>
+ <td>
+ {this.renderRule(rule, rule.right.severity)}
+ {this.renderParameters(rule.right.params)}
+ </td>
+ </tr>
+ );
+ return [header, secondHeader, ...rows];
+ }
+
+ render() {
+ if (!this.props.inLeft.length && !this.props.inRight.length && !this.props.modified.length) {
+ return <ComparisonEmpty />;
+ }
+
+ return (
+ <table className="data zebra quality-profile-comparison-table">
+ <tbody>
+ {this.renderLeft()}
+ {this.renderRight()}
+ {this.renderModified()}
+ </tbody>
+ </table>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import Select from 'react-select';
-import ComparisonForm from '../ComparisonForm';
-import { createFakeProfile } from '../../utils';
-
-it('should render Select with right options', () => {
- const profile = createFakeProfile();
- const profiles = [
- profile,
- createFakeProfile({ key: 'another', name: 'another name' }),
- createFakeProfile({ key: 'java', name: 'java', language: 'java' })
- ];
-
- const output = shallow(
- <ComparisonForm
- withKey="another"
- profile={profile}
- profiles={profiles}
- onCompare={() => true}
- />
- ).find(Select);
- expect(output.length).toBe(1);
- expect(output.prop('value')).toBe('another');
- expect(output.prop('options')).toEqual([{ value: 'another', label: 'another name' }]);
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import ComparisonForm from '../ComparisonForm';
+import { createFakeProfile } from '../../utils';
+
+it('should render Select with right options', () => {
+ const profile = createFakeProfile();
+ const profiles = [
+ profile,
+ createFakeProfile({ key: 'another', name: 'another name' }),
+ createFakeProfile({ key: 'java', name: 'java', language: 'java' })
+ ];
+
+ const output = shallow(
+ <ComparisonForm
+ withKey="another"
+ profile={profile}
+ profiles={profiles}
+ onCompare={() => true}
+ />
+ ).find('Select');
+ expect(output.length).toBe(1);
+ expect(output.prop('value')).toBe('another');
+ expect(output.prop('options')).toEqual([{ value: 'another', label: 'another name' }]);
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import { Link } from 'react-router';
-import ComparisonResults from '../ComparisonResults';
-import ComparisonEmpty from '../ComparisonEmpty';
-import SeverityIcon from '../../../../components/shared/SeverityIcon';
-
-it('should render ComparisonEmpty', () => {
- const output = shallow(
- <ComparisonResults
- left={{ name: 'left' }}
- right={{ name: 'right' }}
- inLeft={[]}
- inRight={[]}
- modified={[]}
- />
- );
- expect(output.is(ComparisonEmpty)).toBe(true);
-});
-
-it('should compare', () => {
- const inLeft = [{ key: 'rule1', name: 'rule1', severity: 'BLOCKER' }];
- const inRight = [
- { key: 'rule2', name: 'rule2', severity: 'CRITICAL' },
- { key: 'rule3', name: 'rule3', severity: 'MAJOR' }
- ];
- const modified = [
- {
- key: 'rule4',
- name: 'rule4',
- left: {
- severity: 'BLOCKER',
- params: { foo: 'bar' }
- },
- right: {
- severity: 'INFO',
- params: { foo: 'qwe' }
- }
- }
- ];
-
- const output = shallow(
- <ComparisonResults
- left={{ name: 'left' }}
- right={{ name: 'right' }}
- inLeft={inLeft}
- inRight={inRight}
- modified={modified}
- />
- );
-
- const leftDiffs = output.find('.js-comparison-in-left');
- expect(leftDiffs.length).toBe(1);
- expect(leftDiffs.find(Link).length).toBe(1);
- expect(leftDiffs.find(Link).prop('to')).toContain('rule_key=rule1');
- expect(leftDiffs.find(Link).prop('children')).toContain('rule1');
- expect(leftDiffs.find(SeverityIcon).length).toBe(1);
- expect(leftDiffs.find(SeverityIcon).prop('severity')).toBe('BLOCKER');
-
- const rightDiffs = output.find('.js-comparison-in-right');
- expect(rightDiffs.length).toBe(2);
- expect(rightDiffs.at(0).find(Link).length).toBe(1);
- expect(rightDiffs.at(0).find(Link).prop('to')).toContain('rule_key=rule2');
- expect(rightDiffs.at(0).find(Link).prop('children')).toContain('rule2');
- expect(rightDiffs.at(0).find(SeverityIcon).length).toBe(1);
- expect(rightDiffs.at(0).find(SeverityIcon).prop('severity')).toBe('CRITICAL');
-
- const modifiedDiffs = output.find('.js-comparison-modified');
- expect(modifiedDiffs.length).toBe(1);
- expect(modifiedDiffs.find(Link).at(0).prop('to')).toContain('rule_key=rule4');
- expect(modifiedDiffs.find(Link).at(0).prop('children')).toContain('rule4');
- expect(modifiedDiffs.find(SeverityIcon).length).toBe(2);
- expect(modifiedDiffs.text()).toContain('bar');
- expect(modifiedDiffs.text()).toContain('qwe');
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { Link } from 'react-router';
+import ComparisonResults from '../ComparisonResults';
+import ComparisonEmpty from '../ComparisonEmpty';
+import SeverityIcon from '../../../../components/shared/SeverityIcon';
+
+it('should render ComparisonEmpty', () => {
+ const output = shallow(
+ <ComparisonResults
+ left={{ name: 'left' }}
+ right={{ name: 'right' }}
+ inLeft={[]}
+ inRight={[]}
+ modified={[]}
+ organization={null}
+ />
+ );
+ expect(output.is(ComparisonEmpty)).toBe(true);
+});
+
+it('should compare', () => {
+ const inLeft = [{ key: 'rule1', name: 'rule1', severity: 'BLOCKER' }];
+ const inRight = [
+ { key: 'rule2', name: 'rule2', severity: 'CRITICAL' },
+ { key: 'rule3', name: 'rule3', severity: 'MAJOR' }
+ ];
+ const modified = [
+ {
+ key: 'rule4',
+ name: 'rule4',
+ left: {
+ severity: 'BLOCKER',
+ params: { foo: 'bar' }
+ },
+ right: {
+ severity: 'INFO',
+ params: { foo: 'qwe' }
+ }
+ }
+ ];
+
+ const output = shallow(
+ <ComparisonResults
+ left={{ name: 'left' }}
+ right={{ name: 'right' }}
+ inLeft={inLeft}
+ inRight={inRight}
+ modified={modified}
+ organization={null}
+ />
+ );
+
+ const leftDiffs = output.find('.js-comparison-in-left');
+ expect(leftDiffs.length).toBe(1);
+ expect(leftDiffs.find(Link).length).toBe(1);
+ expect(leftDiffs.find(Link).prop('to')).toContain('rule_key=rule1');
+ expect(leftDiffs.find(Link).prop('children')).toContain('rule1');
+ expect(leftDiffs.find(SeverityIcon).length).toBe(1);
+ expect(leftDiffs.find(SeverityIcon).prop('severity')).toBe('BLOCKER');
+
+ const rightDiffs = output.find('.js-comparison-in-right');
+ expect(rightDiffs.length).toBe(2);
+ expect(rightDiffs.at(0).find(Link).length).toBe(1);
+ expect(rightDiffs.at(0).find(Link).prop('to')).toContain('rule_key=rule2');
+ expect(rightDiffs.at(0).find(Link).prop('children')).toContain('rule2');
+ expect(rightDiffs.at(0).find(SeverityIcon).length).toBe(1);
+ expect(rightDiffs.at(0).find(SeverityIcon).prop('severity')).toBe('CRITICAL');
+
+ const modifiedDiffs = output.find('.js-comparison-modified');
+ expect(modifiedDiffs.length).toBe(1);
+ expect(modifiedDiffs.find(Link).at(0).prop('to')).toContain('rule_key=rule4');
+ expect(modifiedDiffs.find(Link).at(0).prop('children')).toContain('rule4');
+ expect(modifiedDiffs.find(SeverityIcon).length).toBe(2);
+ expect(modifiedDiffs.text()).toContain('bar');
+ expect(modifiedDiffs.text()).toContain('qwe');
+});
+++ /dev/null
-/*
- * 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 { searchQualityProfiles, getExporters } from '../../../api/quality-profiles';
-import { sortProfiles } from '../utils';
-import { translate } from '../../../helpers/l10n';
-import OrganizationHelmet from '../../../components/common/OrganizationHelmet';
-/*:: import type { Exporter } from '../propTypes'; */
-import '../styles.css';
-
-/*::
-type Props = {
- children: React.Element<*>,
- currentUser: { permissions: { global: Array<string> } },
- languages: Array<*>,
- onRequestFail: Object => void,
- organization: { name: string, canAdmin?: boolean, key: string } | null
-};
-*/
-
-/*::
-type State = {
- loading: boolean,
- exporters?: Array<Exporter>,
- profiles?: Array<*>
-};
-*/
-
-export default class App extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { loading: true };
-
- componentWillMount() {
- const html = document.querySelector('html');
- if (html) {
- html.classList.add('dashboard-page');
- }
- }
-
- componentDidMount() {
- this.mounted = true;
- this.loadData();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- const html = document.querySelector('html');
- if (html) {
- html.classList.remove('dashboard-page');
- }
- }
-
- fetchProfiles() {
- const { organization } = this.props;
- const data = organization ? { organization: organization.key } : {};
- return searchQualityProfiles(data);
- }
-
- loadData() {
- this.setState({ loading: true });
- Promise.all([getExporters(), this.fetchProfiles()]).then(responses => {
- if (this.mounted) {
- const [exporters, profiles] = responses;
- this.setState({
- exporters,
- profiles: sortProfiles(profiles),
- loading: false
- });
- }
- });
- }
-
- updateProfiles = () => {
- return this.fetchProfiles().then(profiles => {
- if (this.mounted) {
- this.setState({ profiles: sortProfiles(profiles) });
- }
- });
- };
-
- renderChild() {
- if (this.state.loading) {
- return <i className="spinner" />;
- }
- const { organization } = this.props;
- const finalLanguages = Object.values(this.props.languages);
-
- const canAdmin = organization
- ? organization.canAdmin
- : this.props.currentUser.permissions.global.includes('profileadmin');
-
- return React.cloneElement(this.props.children, {
- profiles: this.state.profiles,
- languages: finalLanguages,
- exporters: this.state.exporters,
- updateProfiles: this.updateProfiles,
- onRequestFail: this.props.onRequestFail,
- organization: organization ? organization.key : null,
- canAdmin
- });
- }
-
- render() {
- return (
- <div className="page page-limited">
- <OrganizationHelmet
- title={translate('quality_profiles.page')}
- organization={this.props.organization}
- />
-
- {this.renderChild()}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { searchQualityProfiles, getExporters } from '../../../api/quality-profiles';
+import { sortProfiles } from '../utils';
+import { translate } from '../../../helpers/l10n';
+import OrganizationHelmet from '../../../components/common/OrganizationHelmet';
+import '../styles.css';
+import { IExporter, IProfile } from '../types';
+
+interface Props {
+ children: React.ReactElement<any>;
+ currentUser: { permissions: { global: Array<string> } };
+ languages: Array<{}>;
+ onRequestFail: (reasong: any) => void;
+ organization: { name: string; canAdmin?: boolean; key: string } | null;
+}
+
+interface State {
+ loading: boolean;
+ exporters?: IExporter[];
+ profiles?: IProfile[];
+}
+
+export default class App extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: true };
+
+ componentWillMount() {
+ const html = document.querySelector('html');
+ if (html) {
+ html.classList.add('dashboard-page');
+ }
+ }
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadData();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ const html = document.querySelector('html');
+ if (html) {
+ html.classList.remove('dashboard-page');
+ }
+ }
+
+ fetchProfiles() {
+ const { organization } = this.props;
+ const data = organization ? { organization: organization.key } : {};
+ return searchQualityProfiles(data);
+ }
+
+ loadData() {
+ this.setState({ loading: true });
+ Promise.all([getExporters(), this.fetchProfiles()]).then(responses => {
+ if (this.mounted) {
+ const [exporters, profiles] = responses;
+ this.setState({
+ exporters,
+ profiles: sortProfiles(profiles),
+ loading: false
+ });
+ }
+ });
+ }
+
+ updateProfiles = () => {
+ return this.fetchProfiles().then((profiles: any) => {
+ if (this.mounted) {
+ this.setState({ profiles: sortProfiles(profiles) });
+ }
+ });
+ };
+
+ renderChild() {
+ if (this.state.loading) {
+ return <i className="spinner" />;
+ }
+ const { organization } = this.props;
+ const finalLanguages = Object.values(this.props.languages);
+
+ const canAdmin = organization
+ ? organization.canAdmin
+ : this.props.currentUser.permissions.global.includes('profileadmin');
+
+ return React.cloneElement(this.props.children, {
+ profiles: this.state.profiles,
+ languages: finalLanguages,
+ exporters: this.state.exporters,
+ updateProfiles: this.updateProfiles,
+ onRequestFail: this.props.onRequestFail,
+ organization: organization ? organization.key : null,
+ canAdmin
+ });
+ }
+
+ render() {
+ return (
+ <div className="page page-limited">
+ <OrganizationHelmet
+ title={translate('quality_profiles.page')}
+ organization={this.props.organization}
+ />
+
+ {this.renderChild()}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { connect } from 'react-redux';
-import App from './App';
-import { getLanguages, getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer';
-import { onFail } from '../../../store/rootActions';
-
-const mapStateToProps = (state, ownProps) => ({
- currentUser: getCurrentUser(state),
- languages: getLanguages(state),
- organization: ownProps.params.organizationKey
- ? getOrganizationByKey(state, ownProps.params.organizationKey)
- : null
-});
-
-const mapDispatchToProps = dispatch => ({
- onRequestFail: error => onFail(dispatch)(error)
-});
-
-export default connect(mapStateToProps, mapDispatchToProps)(App);
--- /dev/null
+/*
+ * 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 { connect } from 'react-redux';
+import App from './App';
+import { getLanguages, getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer';
+import { onFail } from '../../../store/rootActions';
+
+const mapStateToProps = (state: any, ownProps: any) => ({
+ currentUser: getCurrentUser(state),
+ languages: getLanguages(state),
+ organization: ownProps.params.organizationKey
+ ? getOrganizationByKey(state, ownProps.params.organizationKey)
+ : null
+});
+
+const mapDispatchToProps = (dispatch: any) => ({
+ onRequestFail: (error: any) => onFail(dispatch)(error)
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(App as any);
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import Tooltip from '../../../components/controls/Tooltip';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {|
- className?: string,
- tooltip?: boolean
-|};
-*/
-
-export default function BuiltInBadge(props /*: Props */) {
- const badge = (
- <div className={classNames('outline-badge', props.className)}>
- {translate('quality_profiles.built_in')}
- </div>
- );
-
- const overlay = (
- <span>
- {translate('quality_profiles.built_in.description.1')}{' '}
- {translate('quality_profiles.built_in.description.2')}
- </span>
- );
-
- return props.tooltip
- ? <Tooltip overlay={overlay}>
- {badge}
- </Tooltip>
- : badge;
-}
-
-BuiltInBadge.defaultProps = {
- tooltip: true
-};
--- /dev/null
+/*
+ * 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 classNames from 'classnames';
+import Tooltip from '../../../components/controls/Tooltip';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ className?: string;
+ tooltip?: boolean;
+}
+
+export default function BuiltInBadge({ className, tooltip = true }: Props) {
+ const badge = (
+ <div className={classNames('outline-badge', className)}>
+ {translate('quality_profiles.built_in')}
+ </div>
+ );
+
+ const overlay = (
+ <span>
+ {translate('quality_profiles.built_in.description.1')}{' '}
+ {translate('quality_profiles.built_in.description.2')}
+ </span>
+ );
+
+ return tooltip
+ ? <Tooltip overlay={overlay}>
+ {badge}
+ </Tooltip>
+ : badge;
+}
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-/*:: import type { Profile } from '../propTypes'; */
-import { copyProfile } from '../../../api/quality-profiles';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- onClose: () => void,
- onCopy: string => void,
- onRequestFail: Object => void,
- profile: Profile
-};
-*/
-
-/*::
-type State = {
- loading: boolean,
- name: ?string
-};
-*/
-
-export default class CopyProfileForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { loading: false, name: null };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => {
- this.setState({ name: event.currentTarget.value });
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
-
- const { name } = this.state;
-
- if (name != null) {
- this.setState({ loading: true });
- copyProfile(this.props.profile.key, name).then(
- profile => this.props.onCopy(profile.name),
- error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- }
- );
- }
- };
-
- render() {
- const { profile } = this.props;
- const header = translateWithParameters(
- 'quality_profiles.copy_x_title',
- profile.name,
- profile.languageName
- );
- const submitDisabled =
- this.state.loading || !this.state.name || this.state.name === profile.name;
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form id="copy-profile-form" onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
- <div className="modal-body">
- <div className="modal-field">
- <label htmlFor="copy-profile-name">
- {translate('quality_profiles.copy_new_name')}
- <em className="mandatory">*</em>
- </label>
- <input
- autoFocus={true}
- id="copy-profile-name"
- maxLength="100"
- name="name"
- onChange={this.handleNameChange}
- required={true}
- size="50"
- type="text"
- value={this.state.name != null ? this.state.name : profile.name}
- />
- </div>
- </div>
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- <button disabled={submitDisabled} id="copy-profile-submit">
- {translate('copy')}
- </button>
- <a href="#" id="copy-profile-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import { copyProfile } from '../../../api/quality-profiles';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ onClose: () => void;
+ onCopy: (name: string) => void;
+ onRequestFail: (reasong: any) => void;
+ profile: IProfile;
+}
+
+interface State {
+ loading: boolean;
+ name: string | null;
+}
+
+export default class CopyProfileForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: false, name: null };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
+ this.setState({ name: event.currentTarget.value });
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+
+ const { name } = this.state;
+
+ if (name != null) {
+ this.setState({ loading: true });
+ copyProfile(this.props.profile.key, name).then(
+ (profile: any) => this.props.onCopy(profile.name),
+ (error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ }
+ );
+ }
+ };
+
+ render() {
+ const { profile } = this.props;
+ const header = translateWithParameters(
+ 'quality_profiles.copy_x_title',
+ profile.name,
+ profile.languageName
+ );
+ const submitDisabled =
+ this.state.loading || !this.state.name || this.state.name === profile.name;
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="copy-profile-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+ <div className="modal-body">
+ <div className="modal-field">
+ <label htmlFor="copy-profile-name">
+ {translate('quality_profiles.copy_new_name')}
+ <em className="mandatory">*</em>
+ </label>
+ <input
+ autoFocus={true}
+ id="copy-profile-name"
+ maxLength={100}
+ name="name"
+ onChange={this.handleNameChange}
+ required={true}
+ size={50}
+ type="text"
+ value={this.state.name != null ? this.state.name : profile.name}
+ />
+ </div>
+ </div>
+ <div className="modal-foot">
+ {this.state.loading && <i className="spinner spacer-right" />}
+ <button disabled={submitDisabled} id="copy-profile-submit">
+ {translate('copy')}
+ </button>
+ <a href="#" id="copy-profile-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-/*:: import type { Profile } from '../propTypes'; */
-import { deleteProfile } from '../../../api/quality-profiles';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- onClose: () => void,
- onDelete: () => void,
- onRequestFail: Object => void,
- profile: Profile
-};
-*/
-
-/*::
-type State = {
- loading: boolean
-};
-*/
-
-export default class DeleteProfileForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { loading: false, name: null };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ loading: true });
- deleteProfile(this.props.profile.key).then(this.props.onDelete, error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- });
- };
-
- render() {
- const { profile } = this.props;
- const header = translate('quality_profiles.delete_confirm_title');
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form id="delete-profile-form" onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
- <div className="modal-body">
- <div className="js-modal-messages" />
- {profile.childrenCount > 0
- ? <div>
- <div className="alert alert-warning">
- {translate('quality_profiles.this_profile_has_descendants')}
- </div>
- <p>
- {translateWithParameters(
- 'quality_profiles.are_you_sure_want_delete_profile_x_and_descendants',
- profile.name,
- profile.languageName
- )}
- </p>
- </div>
- : <p>
- {translateWithParameters(
- 'quality_profiles.are_you_sure_want_delete_profile_x',
- profile.name,
- profile.languageName
- )}
- </p>}
- </div>
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- <button className="button-red" disabled={this.state.loading} id="delete-profile-submit">
- {translate('delete')}
- </button>
- <a href="#" id="delete-profile-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import { deleteProfile } from '../../../api/quality-profiles';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ onClose: () => void;
+ onDelete: () => void;
+ onRequestFail: (reason: any) => void;
+ profile: IProfile;
+}
+
+interface State {
+ loading: boolean;
+ name: string | null;
+}
+
+export default class DeleteProfileForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: false, name: null };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+ this.setState({ loading: true });
+ deleteProfile(this.props.profile.key).then(this.props.onDelete, (error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ });
+ };
+
+ render() {
+ const { profile } = this.props;
+ const header = translate('quality_profiles.delete_confirm_title');
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="delete-profile-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+ <div className="modal-body">
+ <div className="js-modal-messages" />
+ {profile.childrenCount > 0
+ ? <div>
+ <div className="alert alert-warning">
+ {translate('quality_profiles.this_profile_has_descendants')}
+ </div>
+ <p>
+ {translateWithParameters(
+ 'quality_profiles.are_you_sure_want_delete_profile_x_and_descendants',
+ profile.name,
+ profile.languageName
+ )}
+ </p>
+ </div>
+ : <p>
+ {translateWithParameters(
+ 'quality_profiles.are_you_sure_want_delete_profile_x',
+ profile.name,
+ profile.languageName
+ )}
+ </p>}
+ </div>
+ <div className="modal-foot">
+ {this.state.loading && <i className="spinner spacer-right" />}
+ <button className="button-red" disabled={this.state.loading} id="delete-profile-submit">
+ {translate('delete')}
+ </button>
+ <a href="#" id="delete-profile-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-import { Link } from 'react-router';
-import RenameProfileForm from './RenameProfileForm';
-import CopyProfileForm from './CopyProfileForm';
-import DeleteProfileForm from './DeleteProfileForm';
-import { translate } from '../../../helpers/l10n';
-import { getRulesUrl } from '../../../helpers/urls';
-import { setDefaultProfile } from '../../../api/quality-profiles';
-import { getProfilePath, getProfileComparePath, getProfilesPath } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- fromList: boolean,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- updateProfiles: () => Promise<*>
-};
-*/
-
-/*::
-type State = {
- copyFormOpen: boolean,
- deleteFormOpen: boolean,
- renameFormOpen: boolean
-};
-*/
-
-export default class ProfileActions extends React.PureComponent {
- /*:: props: Props; */
- /*:: state: State; */
-
- static defaultProps = {
- fromList: false
- };
-
- static contextTypes = {
- router: PropTypes.object
- };
-
- constructor(props /*: Props */) {
- super(props);
- this.state = {
- copyFormOpen: false,
- deleteFormOpen: false,
- renameFormOpen: false
- };
- }
-
- handleRenameClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ renameFormOpen: true });
- };
-
- handleProfileRename = (name /*: string */) => {
- this.closeRenameForm();
- this.props.updateProfiles().then(() => {
- if (!this.props.fromList) {
- this.context.router.replace(
- getProfilePath(name, this.props.profile.language, this.props.organization)
- );
- }
- });
- };
-
- closeRenameForm = () => {
- this.setState({ renameFormOpen: false });
- };
-
- handleCopyClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ copyFormOpen: true });
- };
-
- handleProfileCopy = (name /*: string */) => {
- this.props.updateProfiles().then(() => {
- this.context.router.push(
- getProfilePath(name, this.props.profile.language, this.props.organization)
- );
- });
- };
-
- closeCopyForm = () => {
- this.setState({ copyFormOpen: false });
- };
-
- handleSetDefaultClick = (e /*: SyntheticInputEvent */) => {
- e.preventDefault();
- setDefaultProfile(this.props.profile.key).then(this.props.updateProfiles);
- };
-
- handleDeleteClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ deleteFormOpen: true });
- };
-
- handleProfileDelete = () => {
- this.context.router.replace(getProfilesPath(this.props.organization));
- this.props.updateProfiles();
- };
-
- closeDeleteForm = () => {
- this.setState({ deleteFormOpen: false });
- };
-
- render() {
- const { profile, canAdmin } = this.props;
-
- // FIXME use org, name and lang
- const backupUrl =
- window.baseUrl + '/api/qualityprofiles/backup?profileKey=' + encodeURIComponent(profile.key);
-
- const activateMoreUrl = getRulesUrl(
- {
- qprofile: profile.key,
- activation: 'false'
- },
- this.props.organization
- );
-
- return (
- <ul className="dropdown-menu dropdown-menu-right">
- {canAdmin &&
- !profile.isBuiltIn &&
- <li>
- <Link to={activateMoreUrl}>
- {translate('quality_profiles.activate_more_rules')}
- </Link>
- </li>}
- {!profile.isBuiltIn &&
- <li>
- <a id="quality-profile-backup" href={backupUrl}>
- {translate('backup_verb')}
- </a>
- </li>}
- <li>
- <Link
- to={getProfileComparePath(profile.name, profile.language, this.props.organization)}
- id="quality-profile-compare">
- {translate('compare')}
- </Link>
- </li>
- {canAdmin &&
- <li>
- <a id="quality-profile-copy" href="#" onClick={this.handleCopyClick}>
- {translate('copy')}
- </a>
- </li>}
- {canAdmin &&
- !profile.isBuiltIn &&
- <li>
- <a id="quality-profile-rename" href="#" onClick={this.handleRenameClick}>
- {translate('rename')}
- </a>
- </li>}
- {canAdmin &&
- !profile.isDefault &&
- <li>
- <a id="quality-profile-set-as-default" href="#" onClick={this.handleSetDefaultClick}>
- {translate('set_as_default')}
- </a>
- </li>}
- {canAdmin &&
- !profile.isDefault &&
- !profile.isBuiltIn &&
- <li>
- <a id="quality-profile-delete" href="#" onClick={this.handleDeleteClick}>
- {translate('delete')}
- </a>
- </li>}
-
- {this.state.copyFormOpen &&
- <CopyProfileForm
- onClose={this.closeCopyForm}
- onCopy={this.handleProfileCopy}
- onRequestFail={this.props.onRequestFail}
- profile={profile}
- />}
-
- {this.state.deleteFormOpen &&
- <DeleteProfileForm
- onClose={this.closeDeleteForm}
- onDelete={this.handleProfileDelete}
- onRequestFail={this.props.onRequestFail}
- profile={profile}
- />}
-
- {this.state.renameFormOpen &&
- <RenameProfileForm
- onClose={this.closeRenameForm}
- onRename={this.handleProfileRename}
- onRequestFail={this.props.onRequestFail}
- profile={profile}
- />}
- </ul>
- );
- }
-}
--- /dev/null
+/*
+ * 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 PropTypes from 'prop-types';
+import { Link } from 'react-router';
+import RenameProfileForm from './RenameProfileForm';
+import CopyProfileForm from './CopyProfileForm';
+import DeleteProfileForm from './DeleteProfileForm';
+import { translate } from '../../../helpers/l10n';
+import { getRulesUrl } from '../../../helpers/urls';
+import { setDefaultProfile } from '../../../api/quality-profiles';
+import { getProfilePath, getProfileComparePath, getProfilesPath } from '../utils';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ fromList?: boolean;
+ onRequestFail: (reasong: any) => void;
+ organization: string | null;
+ profile: IProfile;
+ updateProfiles: () => Promise<void>;
+}
+
+interface State {
+ copyFormOpen: boolean;
+ deleteFormOpen: boolean;
+ renameFormOpen: boolean;
+}
+
+export default class ProfileActions extends React.PureComponent<Props, State> {
+ static defaultProps = {
+ fromList: false
+ };
+
+ static contextTypes = {
+ router: PropTypes.object
+ };
+
+ constructor(props: Props) {
+ super(props);
+ this.state = {
+ copyFormOpen: false,
+ deleteFormOpen: false,
+ renameFormOpen: false
+ };
+ }
+
+ handleRenameClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ renameFormOpen: true });
+ };
+
+ handleProfileRename = (name: string) => {
+ this.closeRenameForm();
+ this.props.updateProfiles().then(() => {
+ if (!this.props.fromList) {
+ this.context.router.replace(
+ getProfilePath(name, this.props.profile.language, this.props.organization)
+ );
+ }
+ });
+ };
+
+ closeRenameForm = () => {
+ this.setState({ renameFormOpen: false });
+ };
+
+ handleCopyClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ copyFormOpen: true });
+ };
+
+ handleProfileCopy = (name: string) => {
+ this.props.updateProfiles().then(() => {
+ this.context.router.push(
+ getProfilePath(name, this.props.profile.language, this.props.organization)
+ );
+ });
+ };
+
+ closeCopyForm = () => {
+ this.setState({ copyFormOpen: false });
+ };
+
+ handleSetDefaultClick = (e: React.SyntheticEvent<HTMLElement>) => {
+ e.preventDefault();
+ setDefaultProfile(this.props.profile.key).then(this.props.updateProfiles);
+ };
+
+ handleDeleteClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ deleteFormOpen: true });
+ };
+
+ handleProfileDelete = () => {
+ this.context.router.replace(getProfilesPath(this.props.organization));
+ this.props.updateProfiles();
+ };
+
+ closeDeleteForm = () => {
+ this.setState({ deleteFormOpen: false });
+ };
+
+ render() {
+ const { profile, canAdmin } = this.props;
+
+ // FIXME use org, name and lang
+ const backupUrl =
+ (window as any).baseUrl +
+ '/api/qualityprofiles/backup?profileKey=' +
+ encodeURIComponent(profile.key);
+
+ const activateMoreUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'false'
+ },
+ this.props.organization
+ );
+
+ return (
+ <ul className="dropdown-menu dropdown-menu-right">
+ {canAdmin &&
+ !profile.isBuiltIn &&
+ <li>
+ <Link to={activateMoreUrl}>
+ {translate('quality_profiles.activate_more_rules')}
+ </Link>
+ </li>}
+ {!profile.isBuiltIn &&
+ <li>
+ <a id="quality-profile-backup" href={backupUrl}>
+ {translate('backup_verb')}
+ </a>
+ </li>}
+ <li>
+ <Link
+ to={getProfileComparePath(profile.name, profile.language, this.props.organization)}
+ id="quality-profile-compare">
+ {translate('compare')}
+ </Link>
+ </li>
+ {canAdmin &&
+ <li>
+ <a id="quality-profile-copy" href="#" onClick={this.handleCopyClick}>
+ {translate('copy')}
+ </a>
+ </li>}
+ {canAdmin &&
+ !profile.isBuiltIn &&
+ <li>
+ <a id="quality-profile-rename" href="#" onClick={this.handleRenameClick}>
+ {translate('rename')}
+ </a>
+ </li>}
+ {canAdmin &&
+ !profile.isDefault &&
+ <li>
+ <a id="quality-profile-set-as-default" href="#" onClick={this.handleSetDefaultClick}>
+ {translate('set_as_default')}
+ </a>
+ </li>}
+ {canAdmin &&
+ !profile.isDefault &&
+ !profile.isBuiltIn &&
+ <li>
+ <a id="quality-profile-delete" href="#" onClick={this.handleDeleteClick}>
+ {translate('delete')}
+ </a>
+ </li>}
+
+ {this.state.copyFormOpen &&
+ <CopyProfileForm
+ onClose={this.closeCopyForm}
+ onCopy={this.handleProfileCopy}
+ onRequestFail={this.props.onRequestFail}
+ profile={profile}
+ />}
+
+ {this.state.deleteFormOpen &&
+ <DeleteProfileForm
+ onClose={this.closeDeleteForm}
+ onDelete={this.handleProfileDelete}
+ onRequestFail={this.props.onRequestFail}
+ profile={profile}
+ />}
+
+ {this.state.renameFormOpen &&
+ <RenameProfileForm
+ onClose={this.closeRenameForm}
+ onRename={this.handleProfileRename}
+ onRequestFail={this.props.onRequestFail}
+ profile={profile}
+ />}
+ </ul>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 Helmet from 'react-helmet';
-import ProfileNotFound from './ProfileNotFound';
-import ProfileHeader from '../details/ProfileHeader';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- children: React.Element<*>,
- location: {
- pathname: string,
- query: { key?: string, language: string, name: string }
- },
- onRequestFail: Object => void,
- organization: ?string,
- profiles: Array<Profile>,
- router: { replace: ({}) => void },
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfileContainer extends React.PureComponent {
- /*:: props: Props; */
-
- componentDidMount() {
- const { location, profiles, router } = this.props;
- if (location.query.key) {
- // try to find a quality profile with the given key
- // if managed to find one, redirect to a new version
- // otherwise do nothing, `render` will show not found page
- const profile = profiles.find(profile => profile.key === location.query.key);
- if (profile) {
- router.replace({
- pathname: location.pathname,
- query: { language: profile.language, name: profile.name }
- });
- }
- }
- }
-
- render() {
- const { organization, profiles, location, ...other } = this.props;
- const { key, language, name } = location.query;
-
- if (key) {
- // if there is a `key` parameter,
- // then if we managed to find a quality profile with this key
- // then we will be redirected in `componentDidMount`
- // otherwise show `ProfileNotFound`
- const profile = profiles.find(profile => profile.key === location.query.key);
- return profile ? null : <ProfileNotFound organization={organization} />;
- }
-
- const profile = profiles.find(
- profile => profile.language === language && profile.name === name
- );
-
- if (!profile) {
- return <ProfileNotFound organization={organization} />;
- }
-
- const child = React.cloneElement(this.props.children, {
- onRequestFail: this.props.onRequestFail,
- organization,
- profile,
- profiles,
- ...other
- });
-
- return (
- <div id="quality-profile">
- <Helmet title={profile.name} />
- <ProfileHeader
- canAdmin={this.props.canAdmin}
- onRequestFail={this.props.onRequestFail}
- organization={organization}
- profile={profile}
- updateProfiles={this.props.updateProfiles}
- />
- {child}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Helmet from 'react-helmet';
+import ProfileNotFound from './ProfileNotFound';
+import ProfileHeader from '../details/ProfileHeader';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ children: React.ReactElement<any>;
+ location: {
+ pathname: string;
+ query: { key?: string; language: string; name: string };
+ };
+ onRequestFail: (reasong: any) => void;
+ organization: string | null;
+ profiles: IProfile[];
+ router: { replace: ({}) => void };
+ updateProfiles: () => Promise<void>;
+}
+
+export default class ProfileContainer extends React.PureComponent<Props> {
+ componentDidMount() {
+ const { location, profiles, router } = this.props;
+ if (location.query.key) {
+ // try to find a quality profile with the given key
+ // if managed to find one, redirect to a new version
+ // otherwise do nothing, `render` will show not found page
+ const profile = profiles.find(profile => profile.key === location.query.key);
+ if (profile) {
+ router.replace({
+ pathname: location.pathname,
+ query: { language: profile.language, name: profile.name }
+ });
+ }
+ }
+ }
+
+ render() {
+ const { organization, profiles, location, ...other } = this.props;
+ const { key, language, name } = location.query;
+
+ if (key) {
+ // if there is a `key` parameter,
+ // then if we managed to find a quality profile with this key
+ // then we will be redirected in `componentDidMount`
+ // otherwise show `ProfileNotFound`
+ const profile = profiles.find(profile => profile.key === location.query.key);
+ return profile ? null : <ProfileNotFound organization={organization} />;
+ }
+
+ const profile = profiles.find(
+ profile => profile.language === language && profile.name === name
+ );
+
+ if (!profile) {
+ return <ProfileNotFound organization={organization} />;
+ }
+
+ const child = React.cloneElement(this.props.children, {
+ onRequestFail: this.props.onRequestFail,
+ organization,
+ profile,
+ profiles,
+ ...other
+ });
+
+ return (
+ <div id="quality-profile">
+ <Helmet title={profile.name} />
+ <ProfileHeader
+ canAdmin={this.props.canAdmin}
+ onRequestFail={this.props.onRequestFail}
+ organization={organization}
+ profile={profile}
+ updateProfiles={this.props.updateProfiles}
+ />
+ {child}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- date?: string
-};
-*/
-
-export default class ProfileDate extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { date } = this.props;
-
- if (!date) {
- return (
- <span>
- {translate('never')}
- </span>
- );
- }
-
- return (
- <span title={moment(date).format('LLL')} data-toggle="tooltip">
- {moment(date).fromNow()}
- </span>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { translate } from '../../../helpers/l10n';
+
+interface Props {
+ date?: string;
+}
+
+export default function ProfileDate({ date }: Props) {
+ return date
+ ? <span title={moment(date).format('LLL')} data-toggle="tooltip">
+ {moment(date).fromNow()}
+ </span>
+ : <span>
+ {translate('never')}
+ </span>;
+}
+++ /dev/null
-/*
- * 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 { getProfilePath } from '../utils';
-
-/*::
-type Props = {
- children?: React.Element<*>,
- language: string,
- name: string,
- organization: ?string
-};
-*/
-
-export default class ProfileLink extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { name, language, organization, children, ...other } = this.props;
- return (
- <Link
- to={getProfilePath(name, language, organization)}
- activeClassName="link-no-underline"
- {...other}>
- {children}
- </Link>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { getProfilePath } from '../utils';
+
+interface Props {
+ className?: string;
+ children?: React.ReactElement<any> | string;
+ language: string;
+ name: string;
+ organization: string | null;
+}
+
+export default function ProfileLink({ name, language, organization, children, ...other }: Props) {
+ return (
+ <Link
+ to={getProfilePath(name, language, organization)}
+ activeClassName="link-no-underline"
+ {...other}>
+ {children}
+ </Link>
+ );
+}
+++ /dev/null
-/*
- * 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 { IndexLink } from 'react-router';
-import { translate } from '../../../helpers/l10n';
-import { getProfilesPath } from '../utils';
-
-/*::
-type Props = {
- organization: ?string
-};
-*/
-
-export default class ProfileNotFound extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- return (
- <div className="quality-profile-not-found">
- <div className="note spacer-bottom">
- <IndexLink to={getProfilesPath(this.props.organization)} className="text-muted">
- {translate('quality_profiles.page')}
- </IndexLink>
- </div>
-
- <div>
- {translate('quality_profiles.not_found')}
- </div>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { IndexLink } from 'react-router';
+import { translate } from '../../../helpers/l10n';
+import { getProfilesPath } from '../utils';
+
+interface Props {
+ organization: string | null;
+}
+
+export default function ProfileNotFound(props: Props) {
+ return (
+ <div className="quality-profile-not-found">
+ <div className="note spacer-bottom">
+ <IndexLink to={getProfilesPath(props.organization)} className="text-muted">
+ {translate('quality_profiles.page')}
+ </IndexLink>
+ </div>
+
+ <div>
+ {translate('quality_profiles.not_found')}
+ </div>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-/*:: import type { Profile } from '../propTypes'; */
-import { renameProfile } from '../../../api/quality-profiles';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- onClose: () => void,
- onRename: string => void,
- onRequestFail: Object => void,
- profile: Profile
-};
-*/
-
-/*::
-type State = {
- loading: boolean,
- name: ?string
-};
-*/
-
-export default class RenameProfileForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { loading: false, name: null };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => {
- this.setState({ name: event.currentTarget.value });
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
-
- const { name } = this.state;
-
- if (name != null) {
- this.setState({ loading: true });
- renameProfile(this.props.profile.key, name).then(
- () => this.props.onRename(name),
- error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- }
- );
- }
- };
-
- render() {
- const { profile } = this.props;
- const header = translateWithParameters(
- 'quality_profiles.rename_x_title',
- profile.name,
- profile.languageName
- );
- const submitDisabled =
- this.state.loading || !this.state.name || this.state.name === profile.name;
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form id="rename-profile-form" onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
- <div className="modal-body">
- <div className="modal-field">
- <label htmlFor="rename-profile-name">
- {translate('quality_profiles.new_name')}
- <em className="mandatory">*</em>
- </label>
- <input
- autoFocus={true}
- id="rename-profile-name"
- maxLength="100"
- name="name"
- onChange={this.handleNameChange}
- required={true}
- size="50"
- type="text"
- value={this.state.name != null ? this.state.name : profile.name}
- />
- </div>
- </div>
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- <button disabled={submitDisabled} id="rename-profile-submit">
- {translate('rename')}
- </button>
- <a href="#" id="rename-profile-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import { renameProfile } from '../../../api/quality-profiles';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ onClose: () => void;
+ onRename: (name: string) => void;
+ onRequestFail: (reason: any) => void;
+ profile: IProfile;
+}
+
+interface State {
+ loading: boolean;
+ name: string | null;
+}
+
+export default class RenameProfileForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: false, name: null };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
+ this.setState({ name: event.currentTarget.value });
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ const { name } = this.state;
+
+ if (name != null) {
+ this.setState({ loading: true });
+ renameProfile(this.props.profile.key, name).then(
+ () => this.props.onRename(name),
+ (error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ }
+ );
+ }
+ };
+
+ render() {
+ const { profile } = this.props;
+ const header = translateWithParameters(
+ 'quality_profiles.rename_x_title',
+ profile.name,
+ profile.languageName
+ );
+ const submitDisabled =
+ this.state.loading || !this.state.name || this.state.name === profile.name;
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="rename-profile-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+ <div className="modal-body">
+ <div className="modal-field">
+ <label htmlFor="rename-profile-name">
+ {translate('quality_profiles.new_name')}
+ <em className="mandatory">*</em>
+ </label>
+ <input
+ autoFocus={true}
+ id="rename-profile-name"
+ maxLength={100}
+ name="name"
+ onChange={this.handleNameChange}
+ required={true}
+ size={50}
+ type="text"
+ value={this.state.name != null ? this.state.name : profile.name}
+ />
+ </div>
+ </div>
+ <div className="modal-foot">
+ {this.state.loading && <i className="spinner spacer-right" />}
+ <button disabled={submitDisabled} id="rename-profile-submit">
+ {translate('rename')}
+ </button>
+ <a href="#" id="rename-profile-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import Helmet from 'react-helmet';
-import ProfileContainer from '../ProfileContainer';
-import ProfileNotFound from '../ProfileNotFound';
-import ProfileHeader from '../../details/ProfileHeader';
-import { createFakeProfile } from '../../utils';
-
-it('should render ProfileHeader', () => {
- const targetProfile = createFakeProfile({ language: 'js', name: 'fake' });
- const profiles = [targetProfile, createFakeProfile({ language: 'js', name: 'another' })];
- const updateProfiles = jest.fn();
- const output = shallow(
- <ProfileContainer
- location={{ query: { language: 'js', name: 'fake' } }}
- profiles={profiles}
- canAdmin={false}
- updateProfiles={updateProfiles}>
- <div />
- </ProfileContainer>
- );
- const header = output.find(ProfileHeader);
- expect(header.length).toBe(1);
- expect(header.prop('profile')).toBe(targetProfile);
- expect(header.prop('canAdmin')).toBe(false);
- expect(header.prop('updateProfiles')).toBe(updateProfiles);
-});
-
-it('should render ProfileNotFound', () => {
- const profiles = [
- createFakeProfile({ language: 'js', name: 'fake' }),
- createFakeProfile({ language: 'js', name: 'another' })
- ];
- const output = shallow(
- <ProfileContainer
- location={{ query: { language: 'js', name: 'random' } }}
- profiles={profiles}
- canAdmin={false}
- updateProfiles={() => true}>
- <div />
- </ProfileContainer>
- );
- expect(output.is(ProfileNotFound)).toBe(true);
-});
-
-it('should render Helmet', () => {
- const profiles = [createFakeProfile({ language: 'js', name: 'First Profile' })];
- const updateProfiles = jest.fn();
- const output = shallow(
- <ProfileContainer
- location={{ query: { language: 'js', name: 'First Profile' } }}
- profiles={profiles}
- canAdmin={false}
- updateProfiles={updateProfiles}>
- <div />
- </ProfileContainer>
- );
- const helmet = output.find(Helmet);
- expect(helmet.length).toBe(1);
- expect(helmet.prop('title')).toContain('First Profile');
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import Helmet from 'react-helmet';
+import ProfileContainer from '../ProfileContainer';
+import ProfileNotFound from '../ProfileNotFound';
+import ProfileHeader from '../../details/ProfileHeader';
+import { createFakeProfile } from '../../utils';
+
+it('should render ProfileHeader', () => {
+ const targetProfile = createFakeProfile({ language: 'js', name: 'fake' });
+ const profiles = [targetProfile, createFakeProfile({ language: 'js', name: 'another' })];
+ const updateProfiles = jest.fn();
+ const output = shallow(
+ <ProfileContainer
+ canAdmin={false}
+ location={{ pathname: '', query: { language: 'js', name: 'fake' } }}
+ onRequestFail={jest.fn()}
+ organization={null}
+ profiles={profiles}
+ router={{} as any}
+ updateProfiles={updateProfiles}>
+ <div />
+ </ProfileContainer>
+ );
+ const header = output.find(ProfileHeader);
+ expect(header.length).toBe(1);
+ expect(header.prop('profile')).toBe(targetProfile);
+ expect(header.prop('canAdmin')).toBe(false);
+ expect(header.prop('updateProfiles')).toBe(updateProfiles);
+});
+
+it('should render ProfileNotFound', () => {
+ const profiles = [
+ createFakeProfile({ language: 'js', name: 'fake' }),
+ createFakeProfile({ language: 'js', name: 'another' })
+ ];
+ const output = shallow(
+ <ProfileContainer
+ canAdmin={false}
+ location={{ pathname: '', query: { language: 'js', name: 'random' } }}
+ onRequestFail={jest.fn()}
+ organization={null}
+ profiles={profiles}
+ router={{} as any}
+ updateProfiles={jest.fn()}>
+ <div />
+ </ProfileContainer>
+ );
+ expect(output.is(ProfileNotFound)).toBe(true);
+});
+
+it('should render Helmet', () => {
+ const profiles = [createFakeProfile({ language: 'js', name: 'First Profile' })];
+ const updateProfiles = jest.fn();
+ const output = shallow(
+ <ProfileContainer
+ canAdmin={false}
+ location={{ pathname: '', query: { language: 'js', name: 'First Profile' } }}
+ onRequestFail={jest.fn()}
+ organization={null}
+ profiles={profiles}
+ router={{} as any}
+ updateProfiles={updateProfiles}>
+ <div />
+ </ProfileContainer>
+ );
+ const helmet = output.find(Helmet);
+ expect(helmet.length).toBe(1);
+ expect(helmet.prop('title')).toContain('First Profile');
+});
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-import Select from 'react-select';
-import { sortBy } from 'lodash';
-import { changeProfileParent } from '../../../api/quality-profiles';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- onChange: () => void,
- onClose: () => void,
- onRequestFail: Object => void,
- profile: Profile,
- profiles: Array<Profile>
-};
-*/
-
-/*::
-type State = {
- loading: boolean,
- selected: ?string
-};
-*/
-
-export default class ChangeParentForm extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- loading: false,
- selected: null
- };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleSelectChange = (option /*: { value: string } */) => {
- this.setState({ selected: option.value });
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
-
- const parent = this.state.selected;
-
- if (parent != null) {
- this.setState({ loading: true });
- changeProfileParent(this.props.profile.key, parent).then(this.props.onChange).catch(error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- });
- }
- };
-
- render() {
- const { profiles } = this.props;
-
- const options = [
- { label: translate('none'), value: '' },
- ...sortBy(profiles, 'name').map(profile => ({
- label: profile.isBuiltIn
- ? `${profile.name} (${translate('quality_profiles.built_in')})`
- : profile.name,
- value: profile.key
- }))
- ];
-
- const submitDisabled =
- this.state.loading ||
- this.state.selected == null ||
- this.state.selected === this.props.profile.parentKey;
-
- return (
- <Modal
- isOpen={true}
- contentLabel={translate('quality_profiles.change_parent')}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form id="change-profile-parent-form" onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>
- {translate('quality_profiles.change_parent')}
- </h2>
- </div>
- <div className="modal-body">
- <div className="modal-field">
- <label htmlFor="change-profile-parent">
- {translate('quality_profiles.parent')}: <em className="mandatory">*</em>
- </label>
- <Select
- clearable={false}
- id="change-profile-parent"
- name="parentKey"
- onChange={this.handleSelectChange}
- options={options}
- value={
- this.state.selected != null
- ? this.state.selected
- : this.props.profile.parentKey || ''
- }
- />
- </div>
- </div>
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- <button disabled={submitDisabled} id="change-profile-parent-submit">
- {translate('change_verb')}
- </button>
- <a href="#" id="change-profile-parent-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import * as Select from 'react-select';
+import { sortBy } from 'lodash';
+import { changeProfileParent } from '../../../api/quality-profiles';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ onChange: () => void;
+ onClose: () => void;
+ onRequestFail: (reasong: any) => void;
+ profile: IProfile;
+ profiles: IProfile[];
+}
+
+interface State {
+ loading: boolean;
+ selected: string | null;
+}
+
+export default class ChangeParentForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = {
+ loading: false,
+ selected: null
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleSelectChange = (option: { value: string }) => {
+ this.setState({ selected: option.value });
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ const parent = this.state.selected;
+
+ if (parent != null) {
+ this.setState({ loading: true });
+ changeProfileParent(this.props.profile.key, parent)
+ .then(this.props.onChange)
+ .catch((error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ });
+ }
+ };
+
+ render() {
+ const { profiles } = this.props;
+
+ const options = [
+ { label: translate('none'), value: '' },
+ ...sortBy(profiles, 'name').map(profile => ({
+ label: profile.isBuiltIn
+ ? `${profile.name} (${translate('quality_profiles.built_in')})`
+ : profile.name,
+ value: profile.key
+ }))
+ ];
+
+ const submitDisabled =
+ this.state.loading ||
+ this.state.selected == null ||
+ this.state.selected === this.props.profile.parentKey;
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={translate('quality_profiles.change_parent')}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="change-profile-parent-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {translate('quality_profiles.change_parent')}
+ </h2>
+ </div>
+ <div className="modal-body">
+ <div className="modal-field">
+ <label htmlFor="change-profile-parent">
+ {translate('quality_profiles.parent')}: <em className="mandatory">*</em>
+ </label>
+ <Select
+ clearable={false}
+ name="parentKey"
+ onChange={this.handleSelectChange}
+ options={options}
+ value={
+ this.state.selected != null
+ ? this.state.selected
+ : this.props.profile.parentKey || ''
+ }
+ />
+ </div>
+ </div>
+ <div className="modal-foot">
+ {this.state.loading && <i className="spinner spacer-right" />}
+ <button disabled={submitDisabled} id="change-profile-parent-submit">
+ {translate('change_verb')}
+ </button>
+ <a href="#" id="change-profile-parent-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-import escapeHtml from 'escape-html';
-/*:: import type { Profile } from '../propTypes'; */
-import SelectList from '../../../components/SelectList';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- onClose: () => void,
- organization: ?string,
- profile: Profile
-};
-*/
-
-export default class ChangeProjectsForm extends React.PureComponent {
- /*:: container: HTMLElement; */
- /*:: props: Props; */
-
- handleCloseClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- renderSelectList = () => {
- const { key } = this.props.profile;
-
- const searchUrl =
- window.baseUrl + '/api/qualityprofiles/projects?key=' + encodeURIComponent(key);
-
- new SelectList({
- searchUrl,
- el: this.container,
- width: '100%',
- readOnly: false,
- focusSearch: false,
- dangerouslyUnescapedHtmlFormat: item => escapeHtml(item.name),
- selectUrl: window.baseUrl + '/api/qualityprofiles/add_project',
- deselectUrl: window.baseUrl + '/api/qualityprofiles/remove_project',
- extra: { profileKey: key },
- selectParameter: 'projectUuid',
- selectParameterValue: 'uuid',
- labels: {
- selected: translate('quality_gates.projects.with'),
- deselected: translate('quality_gates.projects.without'),
- all: translate('quality_gates.projects.all'),
- noResults: translate('quality_gates.projects.noResults')
- },
- tooltips: {
- select: translate('quality_profiles.projects.select_hint'),
- deselect: translate('quality_profiles.projects.deselect_hint')
- }
- });
- };
-
- render() {
- const header = translate('projects');
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- onAfterOpen={this.renderSelectList}
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
-
- <div className="modal-body">
- <div id="profile-projects" ref={node => (this.container = node)} />
- </div>
-
- <div className="modal-foot">
- <a href="#" onClick={this.handleCloseClick}>
- {translate('close')}
- </a>
- </div>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import * as escapeHtml from 'escape-html';
+import SelectList from '../../../components/SelectList';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ onClose: () => void;
+ organization: string | null;
+ profile: IProfile;
+}
+
+export default class ChangeProjectsForm extends React.PureComponent<Props> {
+ container: HTMLElement;
+
+ handleCloseClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ renderSelectList = () => {
+ const { key } = this.props.profile;
+
+ const searchUrl =
+ (window as any).baseUrl + '/api/qualityprofiles/projects?key=' + encodeURIComponent(key);
+
+ new (SelectList as any)({
+ searchUrl,
+ el: this.container,
+ width: '100%',
+ readOnly: false,
+ focusSearch: false,
+ dangerouslyUnescapedHtmlFormat: (item: { name: string }) => escapeHtml(item.name),
+ selectUrl: (window as any).baseUrl + '/api/qualityprofiles/add_project',
+ deselectUrl: (window as any).baseUrl + '/api/qualityprofiles/remove_project',
+ extra: { profileKey: key },
+ selectParameter: 'projectUuid',
+ selectParameterValue: 'uuid',
+ labels: {
+ selected: translate('quality_gates.projects.with'),
+ deselected: translate('quality_gates.projects.without'),
+ all: translate('quality_gates.projects.all'),
+ noResults: translate('quality_gates.projects.noResults')
+ },
+ tooltips: {
+ select: translate('quality_profiles.projects.select_hint'),
+ deselect: translate('quality_profiles.projects.deselect_hint')
+ }
+ });
+ };
+
+ render() {
+ const header = translate('projects');
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ onAfterOpen={this.renderSelectList}
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+
+ <div className="modal-body">
+ <div id="profile-projects" ref={node => (this.container = node as HTMLElement)} />
+ </div>
+
+ <div className="modal-foot">
+ <a href="#" onClick={this.handleCloseClick}>
+ {translate('close')}
+ </a>
+ </div>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 ProfileRules from './ProfileRules';
-import ProfileProjects from './ProfileProjects';
-import ProfileInheritance from './ProfileInheritance';
-import ProfileExporters from './ProfileExporters';
-/*:: import type { Profile, Exporter } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- exporters: Array<Exporter>,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- profiles: Array<Profile>,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfileDetails extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- return (
- <div>
- <div className="quality-profile-grid">
- <div className="quality-profile-grid-left">
- <ProfileRules {...this.props} />
- <ProfileExporters {...this.props} />
- </div>
- <div className="quality-profile-grid-right">
- <ProfileInheritance {...this.props} />
- <ProfileProjects {...this.props} />
- </div>
- </div>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ProfileRules from './ProfileRules';
+import ProfileProjects from './ProfileProjects';
+import ProfileInheritance from './ProfileInheritance';
+import ProfileExporters from './ProfileExporters';
+import { IExporter, IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ exporters: IExporter[];
+ onRequestFail: (reasong: any) => void;
+ organization: string | null;
+ profile: IProfile;
+ profiles: IProfile[];
+ updateProfiles: () => Promise<void>;
+}
+
+export default function ProfileDetails(props: Props) {
+ return (
+ <div>
+ <div className="quality-profile-grid">
+ <div className="quality-profile-grid-left">
+ <ProfileRules {...props} />
+ <ProfileExporters {...props} />
+ </div>
+ <div className="quality-profile-grid-right">
+ <ProfileInheritance {...props} />
+ <ProfileProjects {...props} />
+ </div>
+ </div>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 { stringify } from 'querystring';
-import React from 'react';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Profile, Exporter } from '../propTypes'; */
-
-/*::
-type Props = {
- exporters: Array<Exporter>,
- organization: ?string,
- profile: Profile
-};
-*/
-
-export default class ProfileExporters extends React.PureComponent {
- /*:: props: Props; */
-
- getExportUrl(exporter /*: Exporter */) {
- const { organization, profile } = this.props;
-
- const path = '/api/qualityprofiles/export';
- const parameters /*: { [string]: string } */ = {
- exporterKey: exporter.key,
- language: profile.language,
- name: profile.name
- };
- if (organization) {
- Object.assign(parameters, { organization });
- }
- return window.baseUrl + path + '?' + stringify(parameters);
- }
-
- render() {
- const { exporters, profile } = this.props;
- const exportersForLanguage = exporters.filter(e => e.languages.includes(profile.language));
-
- if (exportersForLanguage.length === 0) {
- return null;
- }
-
- return (
- <div className="quality-profile-box quality-profile-exporters">
- <header className="big-spacer-bottom">
- <h2>
- {translate('quality_profiles.exporters')}
- </h2>
- </header>
- <ul>
- {exportersForLanguage.map(exporter =>
- <li key={exporter.key} data-key={exporter.key} className="spacer-top">
- <a href={this.getExportUrl(exporter)} target="_blank">
- {exporter.name}
- </a>
- </li>
- )}
- </ul>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { stringify } from 'querystring';
+import * as React from 'react';
+import { translate } from '../../../helpers/l10n';
+import { IProfile, IExporter } from '../types';
+
+interface Props {
+ exporters: IExporter[];
+ organization: string | null;
+ profile: IProfile;
+}
+
+export default class ProfileExporters extends React.PureComponent<Props> {
+ getExportUrl(exporter: IExporter) {
+ const { organization, profile } = this.props;
+
+ const path = '/api/qualityprofiles/export';
+ const parameters = {
+ exporterKey: exporter.key,
+ language: profile.language,
+ name: profile.name
+ };
+ if (organization) {
+ Object.assign(parameters, { organization });
+ }
+ return (window as any).baseUrl + path + '?' + stringify(parameters);
+ }
+
+ render() {
+ const { exporters, profile } = this.props;
+ const exportersForLanguage = exporters.filter(e => e.languages.includes(profile.language));
+
+ if (exportersForLanguage.length === 0) {
+ return null;
+ }
+
+ return (
+ <div className="quality-profile-box quality-profile-exporters">
+ <header className="big-spacer-bottom">
+ <h2>
+ {translate('quality_profiles.exporters')}
+ </h2>
+ </header>
+ <ul>
+ {exportersForLanguage.map(exporter =>
+ <li key={exporter.key} data-key={exporter.key} className="spacer-top">
+ <a href={this.getExportUrl(exporter)} target="_blank">
+ {exporter.name}
+ </a>
+ </li>
+ )}
+ </ul>
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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, IndexLink } from 'react-router';
-import ProfileLink from '../components/ProfileLink';
-import ProfileActions from '../components/ProfileActions';
-import ProfileDate from '../components/ProfileDate';
-import BuiltInBadge from '../components/BuiltInBadge';
-import { translate } from '../../../helpers/l10n';
-import {
- isStagnant,
- getProfilesPath,
- getProfilesForLanguagePath,
- getProfileChangelogPath
-} from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfileHeader extends React.PureComponent {
- /*:: props: Props; */
-
- renderUpdateDate() {
- const { profile } = this.props;
- let inner = (
- <span>
- {translate('quality_profiles.updated_')} <ProfileDate date={profile.userUpdatedAt} />
- </span>
- );
- if (isStagnant(profile)) {
- inner = (
- <span className="badge badge-normal-size badge-focus">
- {inner}
- </span>
- );
- }
- return (
- <li className="small spacer-right">
- {inner}
- </li>
- );
- }
-
- renderUsageDate() {
- const { profile } = this.props;
- let inner = (
- <span>
- {translate('quality_profiles.used_')} <ProfileDate date={profile.lastUsed} />
- </span>
- );
- if (!profile.lastUsed) {
- inner = (
- <span className="badge badge-normal-size badge-focus">
- {inner}
- </span>
- );
- }
-
- return (
- <li className="small big-spacer-right">
- {inner}
- </li>
- );
- }
-
- render() {
- const { organization, profile } = this.props;
-
- return (
- <header className="page-header quality-profile-header">
- <div className="note spacer-bottom">
- <IndexLink to={getProfilesPath(organization)} className="text-muted">
- {translate('quality_profiles.page')}
- </IndexLink>
- {' / '}
- <Link
- to={getProfilesForLanguagePath(profile.language, organization)}
- className="text-muted">
- {profile.languageName}
- </Link>
- </div>
-
- <h1 className="page-title">
- <ProfileLink
- className="link-base-color"
- language={profile.language}
- name={profile.name}
- organization={organization}>
- <span>
- {profile.name}
- </span>
- </ProfileLink>
- {profile.isBuiltIn && <BuiltInBadge className="spacer-left" tooltip={false} />}
- </h1>
-
- <div className="pull-right">
- <ul className="list-inline" style={{ lineHeight: '24px' }}>
- {this.renderUpdateDate()}
- {this.renderUsageDate()}
- <li>
- <Link
- to={getProfileChangelogPath(profile.name, profile.language, organization)}
- className="button">
- {translate('changelog')}
- </Link>
- </li>
- <li>
- <div className="pull-left dropdown">
- <button className="dropdown-toggle" data-toggle="dropdown">
- {translate('actions')} <i className="icon-dropdown" />
- </button>
- <ProfileActions
- canAdmin={this.props.canAdmin}
- onRequestFail={this.props.onRequestFail}
- organization={organization}
- profile={profile}
- updateProfiles={this.props.updateProfiles}
- />
- </div>
- </li>
- </ul>
- </div>
-
- {profile.isBuiltIn &&
- <div className="page-description">
- {translate('quality_profiles.built_in.description.1')}
- <br />
- {translate('quality_profiles.built_in.description.2')}
- </div>}
- </header>
- );
- }
-}
--- /dev/null
+/*
+ * 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, IndexLink } from 'react-router';
+import ProfileLink from '../components/ProfileLink';
+import ProfileActions from '../components/ProfileActions';
+import ProfileDate from '../components/ProfileDate';
+import BuiltInBadge from '../components/BuiltInBadge';
+import { translate } from '../../../helpers/l10n';
+import {
+ isStagnant,
+ getProfilesPath,
+ getProfilesForLanguagePath,
+ getProfileChangelogPath
+} from '../utils';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ onRequestFail: (reasong: any) => void;
+ profile: IProfile;
+ organization: string | null;
+ updateProfiles: () => Promise<void>;
+}
+
+export default class ProfileHeader extends React.PureComponent<Props> {
+ renderUpdateDate() {
+ const { profile } = this.props;
+ let inner = (
+ <span>
+ {translate('quality_profiles.updated_')} <ProfileDate date={profile.userUpdatedAt} />
+ </span>
+ );
+ if (isStagnant(profile)) {
+ inner = (
+ <span className="badge badge-normal-size badge-focus">
+ {inner}
+ </span>
+ );
+ }
+ return (
+ <li className="small spacer-right">
+ {inner}
+ </li>
+ );
+ }
+
+ renderUsageDate() {
+ const { profile } = this.props;
+ let inner = (
+ <span>
+ {translate('quality_profiles.used_')} <ProfileDate date={profile.lastUsed} />
+ </span>
+ );
+ if (!profile.lastUsed) {
+ inner = (
+ <span className="badge badge-normal-size badge-focus">
+ {inner}
+ </span>
+ );
+ }
+
+ return (
+ <li className="small big-spacer-right">
+ {inner}
+ </li>
+ );
+ }
+
+ render() {
+ const { organization, profile } = this.props;
+
+ return (
+ <header className="page-header quality-profile-header">
+ <div className="note spacer-bottom">
+ <IndexLink to={getProfilesPath(organization)} className="text-muted">
+ {translate('quality_profiles.page')}
+ </IndexLink>
+ {' / '}
+ <Link
+ to={getProfilesForLanguagePath(profile.language, organization)}
+ className="text-muted">
+ {profile.languageName}
+ </Link>
+ </div>
+
+ <h1 className="page-title">
+ <ProfileLink
+ className="link-base-color"
+ language={profile.language}
+ name={profile.name}
+ organization={organization}>
+ <span>
+ {profile.name}
+ </span>
+ </ProfileLink>
+ {profile.isBuiltIn && <BuiltInBadge className="spacer-left" tooltip={false} />}
+ </h1>
+
+ <div className="pull-right">
+ <ul className="list-inline" style={{ lineHeight: '24px' }}>
+ {this.renderUpdateDate()}
+ {this.renderUsageDate()}
+ <li>
+ <Link
+ to={getProfileChangelogPath(profile.name, profile.language, organization)}
+ className="button">
+ {translate('changelog')}
+ </Link>
+ </li>
+ <li>
+ <div className="pull-left dropdown">
+ <button className="dropdown-toggle" data-toggle="dropdown">
+ {translate('actions')} <i className="icon-dropdown" />
+ </button>
+ <ProfileActions
+ canAdmin={this.props.canAdmin}
+ onRequestFail={this.props.onRequestFail}
+ organization={organization}
+ profile={profile}
+ updateProfiles={this.props.updateProfiles}
+ />
+ </div>
+ </li>
+ </ul>
+ </div>
+
+ {profile.isBuiltIn &&
+ <div className="page-description">
+ {translate('quality_profiles.built_in.description.1')}
+ <br />
+ {translate('quality_profiles.built_in.description.2')}
+ </div>}
+ </header>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import ProfileInheritanceBox from './ProfileInheritanceBox';
-import ChangeParentForm from './ChangeParentForm';
-import { translate } from '../../../helpers/l10n';
-import { getProfileInheritance } from '../../../api/quality-profiles';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- profiles: Array<Profile>,
- updateProfiles: () => Promise<*>
-};
-*/
-
-/*::
-type ProfileInheritanceDetails = {
- activeRuleCount: number,
- isBuiltIn: boolean,
- key: string,
- language: string,
- name: string,
- overridingRuleCount?: number
-};
-*/
-
-/*::
-type State = {
- ancestors?: Array<ProfileInheritanceDetails>,
- children?: Array<ProfileInheritanceDetails>,
- formOpen: boolean,
- loading: boolean,
- profile?: ProfileInheritanceDetails
-};
-*/
-
-export default class ProfileInheritance extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- formOpen: false,
- loading: true
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadData();
- }
-
- componentDidUpdate(prevProps /*: Props */) {
- if (prevProps.profile !== this.props.profile) {
- this.loadData();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadData() {
- getProfileInheritance(this.props.profile.key).then(r => {
- if (this.mounted) {
- const { ancestors, children } = r;
- this.setState({
- children,
- ancestors: ancestors.reverse(),
- profile: r.profile,
- loading: false
- });
- }
- });
- }
-
- handleChangeParentClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ formOpen: true });
- };
-
- closeForm = () => {
- this.setState({ formOpen: false });
- };
-
- handleParentChange = () => {
- this.props.updateProfiles();
- this.closeForm();
- };
-
- render() {
- const { profile, profiles } = this.props;
- const { ancestors } = this.state;
-
- const highlightCurrent =
- !this.state.loading &&
- ancestors != null &&
- this.state.children != null &&
- (ancestors.length > 0 || this.state.children.length > 0);
-
- const currentClassName = classNames('js-inheritance-current', {
- selected: highlightCurrent
- });
-
- const extendsBuiltIn = ancestors != null && ancestors.some(profile => profile.isBuiltIn);
-
- return (
- <div className="quality-profile-inheritance">
- <header className="big-spacer-bottom clearfix">
- <h2 className="pull-left">
- {translate('quality_profiles.profile_inheritance')}
- </h2>
- {this.props.canAdmin &&
- !this.props.profile.isBuiltIn &&
- <button className="pull-right js-change-parent" onClick={this.handleChangeParentClick}>
- {translate('quality_profiles.change_parent')}
- </button>}
- </header>
-
- {!this.state.loading &&
- <table className="data zebra">
- <tbody>
- {ancestors != null &&
- ancestors.map((ancestor, index) =>
- <ProfileInheritanceBox
- className="js-inheritance-ancestor"
- depth={index}
- key={ancestor.key}
- language={profile.language}
- organization={this.props.organization}
- profile={ancestor}
- />
- )}
-
- <ProfileInheritanceBox
- className={currentClassName}
- depth={ancestors ? ancestors.length : 0}
- displayLink={false}
- extendsBuiltIn={extendsBuiltIn}
- language={profile.language}
- organization={this.props.organization}
- profile={this.state.profile}
- />
-
- {this.state.children != null &&
- this.state.children.map(child =>
- <ProfileInheritanceBox
- className="js-inheritance-child"
- depth={ancestors ? ancestors.length + 1 : 0}
- key={child.key}
- language={profile.language}
- organization={this.props.organization}
- profile={child}
- />
- )}
- </tbody>
- </table>}
-
- {this.state.formOpen &&
- <ChangeParentForm
- onChange={this.handleParentChange}
- onClose={this.closeForm}
- onRequestFail={this.props.onRequestFail}
- profile={profile}
- profiles={profiles.filter(p => p !== profile && p.language === profile.language)}
- />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 classNames from 'classnames';
+import ProfileInheritanceBox from './ProfileInheritanceBox';
+import ChangeParentForm from './ChangeParentForm';
+import { translate } from '../../../helpers/l10n';
+import { getProfileInheritance } from '../../../api/quality-profiles';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ profile: IProfile;
+ profiles: IProfile[];
+ updateProfiles: () => Promise<void>;
+}
+
+interface ProfileInheritanceDetails {
+ activeRuleCount: number;
+ isBuiltIn: boolean;
+ key: string;
+ language: string;
+ name: string;
+ overridingRuleCount?: number;
+}
+
+interface State {
+ ancestors?: Array<ProfileInheritanceDetails>;
+ children?: Array<ProfileInheritanceDetails>;
+ formOpen: boolean;
+ loading: boolean;
+ profile?: ProfileInheritanceDetails;
+}
+
+export default class ProfileInheritance extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ state: State = {
+ formOpen: false,
+ loading: true
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadData();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.profile !== this.props.profile) {
+ this.loadData();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadData() {
+ getProfileInheritance(this.props.profile.key).then((r: any) => {
+ if (this.mounted) {
+ const { ancestors, children } = r;
+ this.setState({
+ children,
+ ancestors: ancestors.reverse(),
+ profile: r.profile,
+ loading: false
+ });
+ }
+ });
+ }
+
+ handleChangeParentClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ formOpen: true });
+ };
+
+ closeForm = () => {
+ this.setState({ formOpen: false });
+ };
+
+ handleParentChange = () => {
+ this.props.updateProfiles();
+ this.closeForm();
+ };
+
+ render() {
+ const { profile, profiles } = this.props;
+ const { ancestors } = this.state;
+
+ const highlightCurrent =
+ !this.state.loading &&
+ ancestors != null &&
+ this.state.children != null &&
+ (ancestors.length > 0 || this.state.children.length > 0);
+
+ const currentClassName = classNames('js-inheritance-current', {
+ selected: highlightCurrent
+ });
+
+ const extendsBuiltIn = ancestors != null && ancestors.some(profile => profile.isBuiltIn);
+
+ return (
+ <div className="quality-profile-inheritance">
+ <header className="big-spacer-bottom clearfix">
+ <h2 className="pull-left">
+ {translate('quality_profiles.profile_inheritance')}
+ </h2>
+ {this.props.canAdmin &&
+ !this.props.profile.isBuiltIn &&
+ <button className="pull-right js-change-parent" onClick={this.handleChangeParentClick}>
+ {translate('quality_profiles.change_parent')}
+ </button>}
+ </header>
+
+ {!this.state.loading &&
+ <table className="data zebra">
+ <tbody>
+ {ancestors != null &&
+ ancestors.map((ancestor, index) =>
+ <ProfileInheritanceBox
+ className="js-inheritance-ancestor"
+ depth={index}
+ key={ancestor.key}
+ language={profile.language}
+ organization={this.props.organization}
+ profile={ancestor}
+ />
+ )}
+
+ {this.state.profile != null &&
+ <ProfileInheritanceBox
+ className={currentClassName}
+ depth={ancestors ? ancestors.length : 0}
+ displayLink={false}
+ extendsBuiltIn={extendsBuiltIn}
+ language={profile.language}
+ organization={this.props.organization}
+ profile={this.state.profile}
+ />}
+
+ {this.state.children != null &&
+ this.state.children.map(child =>
+ <ProfileInheritanceBox
+ className="js-inheritance-child"
+ depth={ancestors ? ancestors.length + 1 : 0}
+ key={child.key}
+ language={profile.language}
+ organization={this.props.organization}
+ profile={child}
+ />
+ )}
+ </tbody>
+ </table>}
+
+ {this.state.formOpen &&
+ <ChangeParentForm
+ onChange={this.handleParentChange}
+ onClose={this.closeForm}
+ onRequestFail={this.props.onRequestFail}
+ profile={profile}
+ profiles={profiles.filter(p => p !== profile && p.language === profile.language)}
+ />}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 ProfileLink from '../components/ProfileLink';
-import BuiltInBadge from '../components/BuiltInBadge';
-import Tooltip from '../../../components/controls/Tooltip';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-/*::
-type Props = {|
- className?: string,
- depth: number,
- displayLink?: boolean,
- extendsBuiltIn?: boolean,
- language: string,
- organization: ?string,
- profile: {
- activeRuleCount: number,
- isBuiltIn: boolean,
- key: string,
- language: string,
- name: string,
- overridingRuleCount?: number
- }
-|};
-*/
-
-export default class ProfileInheritanceBox extends React.PureComponent {
- /*:: props: Props; */
-
- static defaultProps = {
- displayLink: true
- };
-
- render() {
- const { profile, className, extendsBuiltIn } = this.props;
- const offset = 25 * this.props.depth;
-
- return (
- <tr className={className}>
- <td>
- <div style={{ paddingLeft: offset }}>
- {this.props.displayLink
- ? <ProfileLink
- language={this.props.language}
- name={profile.name}
- organization={this.props.organization}>
- {profile.name}
- </ProfileLink>
- : profile.name}
- {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />}
- {extendsBuiltIn &&
- <Tooltip overlay={translate('quality_profiles.extends_built_in')}>
- <i className="icon-help spacer-left" />
- </Tooltip>}
- </div>
- </td>
-
- <td>
- {translateWithParameters('quality_profile.x_active_rules', profile.activeRuleCount)}
- </td>
-
- <td>
- {profile.overridingRuleCount != null &&
- <p>
- {translateWithParameters(
- 'quality_profiles.x_overridden_rules',
- profile.overridingRuleCount
- )}
- </p>}
- </td>
- </tr>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ProfileLink from '../components/ProfileLink';
+import BuiltInBadge from '../components/BuiltInBadge';
+import Tooltip from '../../../components/controls/Tooltip';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+interface Props {
+ className?: string;
+ depth: number;
+ displayLink?: boolean;
+ extendsBuiltIn?: boolean;
+ language: string;
+ organization: string | null;
+ profile: {
+ activeRuleCount: number;
+ isBuiltIn: boolean;
+ key: string;
+ language: string;
+ name: string;
+ overridingRuleCount?: number;
+ };
+}
+
+export default function ProfileInheritanceBox({ displayLink = true, ...props }: Props) {
+ const { profile, className, extendsBuiltIn } = props;
+ const offset = 25 * props.depth;
+
+ return (
+ <tr className={className}>
+ <td>
+ <div style={{ paddingLeft: offset }}>
+ {displayLink
+ ? <ProfileLink
+ language={props.language}
+ name={profile.name}
+ organization={props.organization}>
+ {profile.name}
+ </ProfileLink>
+ : profile.name}
+ {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />}
+ {extendsBuiltIn &&
+ <Tooltip overlay={translate('quality_profiles.extends_built_in')}>
+ <i className="icon-help spacer-left" />
+ </Tooltip>}
+ </div>
+ </td>
+
+ <td>
+ {translateWithParameters('quality_profile.x_active_rules', profile.activeRuleCount)}
+ </td>
+
+ <td>
+ {profile.overridingRuleCount != null &&
+ <p>
+ {translateWithParameters(
+ 'quality_profiles.x_overridden_rules',
+ profile.overridingRuleCount
+ )}
+ </p>}
+ </td>
+ </tr>
+ );
+}
+++ /dev/null
-/*
- * 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 ChangeProjectsForm from './ChangeProjectsForm';
-import QualifierIcon from '../../../components/shared/QualifierIcon';
-import { getProfileProjects } from '../../../api/quality-profiles';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- organization: ?string,
- profile: Profile,
- updateProfiles: () => Promise<*>
-};
-*/
-
-/*::
-type State = {
- formOpen: boolean,
- loading: boolean,
- more?: boolean,
- projects: ?Array<*>
-};
-*/
-
-export default class ProfileProjects extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- formOpen: false,
- loading: true,
- projects: null
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadProjects();
- }
-
- componentDidUpdate(prevProps /*: Props */) {
- if (prevProps.profile !== this.props.profile) {
- this.loadProjects();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadProjects() {
- if (this.props.profile.isDefault) {
- return;
- }
-
- const data = { key: this.props.profile.key };
- getProfileProjects(data).then(r => {
- if (this.mounted) {
- this.setState({
- projects: r.results,
- more: r.more,
- loading: false
- });
- }
- });
- }
-
- handleChangeClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ formOpen: true });
- };
-
- closeForm = () => {
- this.setState({ formOpen: false });
- this.props.updateProfiles();
- };
-
- renderDefault() {
- return (
- <div>
- <span className="badge spacer-right">
- {translate('default')}
- </span>
- {translate('quality_profiles.projects_for_default')}
- </div>
- );
- }
-
- renderProjects() {
- const { projects } = this.state;
-
- if (projects == null) {
- return null;
- }
-
- if (projects.length === 0) {
- return (
- <div>
- {translate('quality_profiles.no_projects_associated_to_profile')}
- </div>
- );
- }
-
- return (
- <ul>
- {projects.map(project =>
- <li key={project.uuid} className="spacer-top js-profile-project" data-key={project.key}>
- <Link
- to={{ pathname: '/dashboard', query: { id: project.key } }}
- className="link-with-icon">
- <QualifierIcon qualifier="TRK" /> <span>{project.name}</span>
- </Link>
- </li>
- )}
- </ul>
- );
- }
-
- render() {
- return (
- <div className="quality-profile-projects">
- <header className="page-header">
- <h2 className="page-title">
- {translate('projects')}
- </h2>
-
- {this.props.canAdmin &&
- !this.props.profile.isDefault &&
- <div className="pull-right">
- <button className="js-change-projects" onClick={this.handleChangeClick}>
- {translate('quality_profiles.change_projects')}
- </button>
- </div>}
- </header>
-
- {this.props.profile.isDefault ? this.renderDefault() : this.renderProjects()}
-
- {this.state.formOpen &&
- <ChangeProjectsForm
- onClose={this.closeForm}
- organization={this.props.organization}
- profile={this.props.profile}
- />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ChangeProjectsForm from './ChangeProjectsForm';
+import QualifierIcon from '../../../components/shared/QualifierIcon';
+import { getProfileProjects } from '../../../api/quality-profiles';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ organization: string | null;
+ profile: IProfile;
+ updateProfiles: () => Promise<void>;
+}
+
+interface State {
+ formOpen: boolean;
+ loading: boolean;
+ more?: boolean;
+ projects: Array<{ key: string; name: string; uuid: string }> | null;
+}
+
+export default class ProfileProjects extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ state: State = {
+ formOpen: false,
+ loading: true,
+ projects: null
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadProjects();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.profile !== this.props.profile) {
+ this.loadProjects();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadProjects() {
+ if (this.props.profile.isDefault) {
+ return;
+ }
+
+ const data = { key: this.props.profile.key };
+ getProfileProjects(data).then((r: any) => {
+ if (this.mounted) {
+ this.setState({
+ projects: r.results,
+ more: r.more,
+ loading: false
+ });
+ }
+ });
+ }
+
+ handleChangeClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ formOpen: true });
+ };
+
+ closeForm = () => {
+ this.setState({ formOpen: false });
+ this.props.updateProfiles();
+ };
+
+ renderDefault() {
+ return (
+ <div>
+ <span className="badge spacer-right">
+ {translate('default')}
+ </span>
+ {translate('quality_profiles.projects_for_default')}
+ </div>
+ );
+ }
+
+ renderProjects() {
+ const { projects } = this.state;
+
+ if (projects == null) {
+ return null;
+ }
+
+ if (projects.length === 0) {
+ return (
+ <div>
+ {translate('quality_profiles.no_projects_associated_to_profile')}
+ </div>
+ );
+ }
+
+ return (
+ <ul>
+ {projects.map(project =>
+ <li key={project.uuid} className="spacer-top js-profile-project" data-key={project.key}>
+ <Link
+ to={{ pathname: '/dashboard', query: { id: project.key } }}
+ className="link-with-icon">
+ <QualifierIcon qualifier="TRK" /> <span>{project.name}</span>
+ </Link>
+ </li>
+ )}
+ </ul>
+ );
+ }
+
+ render() {
+ return (
+ <div className="quality-profile-projects">
+ <header className="page-header">
+ <h2 className="page-title">
+ {translate('projects')}
+ </h2>
+
+ {this.props.canAdmin &&
+ !this.props.profile.isDefault &&
+ <div className="pull-right">
+ <button className="js-change-projects" onClick={this.handleChangeClick}>
+ {translate('quality_profiles.change_projects')}
+ </button>
+ </div>}
+ </header>
+
+ {this.props.profile.isDefault ? this.renderDefault() : this.renderProjects()}
+
+ {this.state.formOpen &&
+ <ChangeProjectsForm
+ onClose={this.closeForm}
+ organization={this.props.organization}
+ profile={this.props.profile}
+ />}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { keyBy } from 'lodash';
-import ProfileRulesRowOfType from './ProfileRulesRowOfType';
-import ProfileRulesRowTotal from './ProfileRulesRowTotal';
-import ProfileRulesDeprecatedWarning from './ProfileRulesDeprecatedWarning';
-import ProfileRulesSonarWayComparison from './ProfileRulesSonarWayComparison';
-import { searchRules, takeFacet } from '../../../api/rules';
-import { getQualityProfiles } from '../../../api/quality-profiles';
-import { getRulesUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
-/*:: import type { Profile } from '../propTypes'; */
-
-const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
-
-/*::
-type Props = {
- canAdmin: boolean,
- organization: ?string,
- profile: Profile
-};
-*/
-
-/*::
-type State = {
- activatedTotal: ?number,
- activatedByType?: { [string]: ?{ val: string, count: ?number } },
- allByType?: { [string]: ?{ val: string, count: ?number } },
- compareToSonarWay: ?{ profile: string, profileName: string, missingRuleCount: number },
- loading: boolean,
- total: ?number
-};
-*/
-
-export default class ProfileRules extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {
- activatedTotal: null,
- activatedByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'),
- allByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'),
- compareToSonarWay: null,
- loading: true,
- total: null
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadRules();
- }
-
- componentDidUpdate(prevProps /*: Props */) {
- if (prevProps.profile !== this.props.profile) {
- this.loadRules();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadProfile() {
- if (this.props.profile.isBuiltIn) {
- return Promise.resolve(null);
- }
- return getQualityProfiles({
- compareToSonarWay: true,
- profile: this.props.profile.key
- });
- }
-
- loadAllRules() {
- return searchRules({
- languages: this.props.profile.language,
- ps: 1,
- facets: 'types'
- });
- }
-
- loadActivatedRules() {
- return searchRules({
- qprofile: this.props.profile.key,
- activation: 'true',
- ps: 1,
- facets: 'types'
- });
- }
-
- loadRules() {
- this.setState({ loading: true });
- Promise.all([
- this.loadAllRules(),
- this.loadActivatedRules(),
- this.loadProfile()
- ]).then(responses => {
- if (this.mounted) {
- const [allRules, activatedRules, showProfile] = responses;
- this.setState({
- activatedTotal: activatedRules.total,
- allByType: keyBy(takeFacet(allRules, 'types'), 'val'),
- activatedByType: keyBy(takeFacet(activatedRules, 'types'), 'val'),
- compareToSonarWay: showProfile && showProfile.compareToSonarWay,
- loading: false,
- total: allRules.total
- });
- }
- });
- }
-
- getRulesCountForType(type /*: string */) /*: ?number */ {
- return this.state.activatedByType && this.state.activatedByType[type]
- ? this.state.activatedByType[type].count
- : null;
- }
-
- getRulesTotalForType(type /*: string */) /*: ?number */ {
- return this.state.allByType && this.state.allByType[type]
- ? this.state.allByType[type].count
- : null;
- }
-
- render() {
- const { organization, profile } = this.props;
- const { compareToSonarWay } = this.state;
- const activateMoreUrl = getRulesUrl(
- { qprofile: profile.key, activation: 'false' },
- organization
- );
-
- return (
- <div className="quality-profile-rules">
- <div className="quality-profile-rules-distribution">
- <table className="data condensed">
- <thead>
- <tr>
- <th>
- <h2>
- {translate('rules')}
- </h2>
- </th>
- <th>
- {translate('active')}
- </th>
- <th>
- {translate('inactive')}
- </th>
- </tr>
- </thead>
- <tbody>
- <ProfileRulesRowTotal
- key="all"
- count={this.state.activatedTotal}
- organization={organization}
- qprofile={profile.key}
- total={this.state.total}
- />
- {TYPES.map(type =>
- <ProfileRulesRowOfType
- key={type}
- count={this.getRulesCountForType(type)}
- organization={organization}
- qprofile={profile.key}
- total={this.getRulesTotalForType(type)}
- type={type}
- />
- )}
- </tbody>
- </table>
-
- {this.props.canAdmin &&
- !profile.isBuiltIn &&
- <div className="text-right big-spacer-top">
- <Link to={activateMoreUrl} className="button js-activate-rules">
- {translate('quality_profiles.activate_more')}
- </Link>
- </div>}
- </div>
- {profile.activeDeprecatedRuleCount > 0 &&
- <ProfileRulesDeprecatedWarning
- activeDeprecatedRules={profile.activeDeprecatedRuleCount}
- organization={organization}
- profile={profile.key}
- />}
- {compareToSonarWay != null &&
- compareToSonarWay.missingRuleCount > 0 &&
- <ProfileRulesSonarWayComparison
- language={profile.language}
- organization={organization}
- profile={profile.key}
- sonarway={compareToSonarWay.profile}
- sonarWayMissingRules={compareToSonarWay.missingRuleCount}
- />}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { keyBy } from 'lodash';
+import ProfileRulesRowOfType from './ProfileRulesRowOfType';
+import ProfileRulesRowTotal from './ProfileRulesRowTotal';
+import ProfileRulesDeprecatedWarning from './ProfileRulesDeprecatedWarning';
+import ProfileRulesSonarWayComparison from './ProfileRulesSonarWayComparison';
+import { searchRules, takeFacet } from '../../../api/rules';
+import { getQualityProfiles } from '../../../api/quality-profiles';
+import { getRulesUrl } from '../../../helpers/urls';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+const TYPES = ['BUG', 'VULNERABILITY', 'CODE_SMELL'];
+
+interface Props {
+ canAdmin: boolean;
+ organization: string | null;
+ profile: IProfile;
+}
+
+interface ByType {
+ val: string;
+ count: number | null;
+}
+
+interface State {
+ activatedTotal: number | null;
+ activatedByType: { [type: string]: ByType };
+ allByType: { [type: string]: ByType };
+ compareToSonarWay: { profile: string; profileName: string; missingRuleCount: number } | null;
+ loading: boolean;
+ total: number | null;
+}
+
+export default class ProfileRules extends React.PureComponent<Props, State> {
+ mounted: boolean;
+
+ state: State = {
+ activatedTotal: null,
+ activatedByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'),
+ allByType: keyBy(TYPES.map(t => ({ val: t, count: null })), 'val'),
+ compareToSonarWay: null,
+ loading: true,
+ total: null
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadRules();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.profile !== this.props.profile) {
+ this.loadRules();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadProfile() {
+ if (this.props.profile.isBuiltIn) {
+ return Promise.resolve(null);
+ }
+ return getQualityProfiles({
+ compareToSonarWay: true,
+ profile: this.props.profile.key
+ });
+ }
+
+ loadAllRules() {
+ return searchRules({
+ languages: this.props.profile.language,
+ ps: 1,
+ facets: 'types'
+ });
+ }
+
+ loadActivatedRules() {
+ return searchRules({
+ qprofile: this.props.profile.key,
+ activation: 'true',
+ ps: 1,
+ facets: 'types'
+ });
+ }
+
+ loadRules() {
+ this.setState({ loading: true });
+ Promise.all([
+ this.loadAllRules(),
+ this.loadActivatedRules(),
+ this.loadProfile()
+ ]).then(responses => {
+ if (this.mounted) {
+ const [allRules, activatedRules, showProfile] = responses;
+ this.setState({
+ activatedTotal: activatedRules.total,
+ allByType: keyBy<ByType>(takeFacet(allRules, 'types'), 'val'),
+ activatedByType: keyBy<ByType>(takeFacet(activatedRules, 'types'), 'val'),
+ compareToSonarWay: showProfile && showProfile.compareToSonarWay,
+ loading: false,
+ total: allRules.total
+ });
+ }
+ });
+ }
+
+ getRulesCountForType(type: string) {
+ return this.state.activatedByType && this.state.activatedByType[type]
+ ? this.state.activatedByType[type].count
+ : null;
+ }
+
+ getRulesTotalForType(type: string) {
+ return this.state.allByType && this.state.allByType[type]
+ ? this.state.allByType[type].count
+ : null;
+ }
+
+ render() {
+ const { organization, profile } = this.props;
+ const { compareToSonarWay } = this.state;
+ const activateMoreUrl = getRulesUrl(
+ { qprofile: profile.key, activation: 'false' },
+ organization
+ );
+
+ return (
+ <div className="quality-profile-rules">
+ <div className="quality-profile-rules-distribution">
+ <table className="data condensed">
+ <thead>
+ <tr>
+ <th>
+ <h2>
+ {translate('rules')}
+ </h2>
+ </th>
+ <th>
+ {translate('active')}
+ </th>
+ <th>
+ {translate('inactive')}
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <ProfileRulesRowTotal
+ key="all"
+ count={this.state.activatedTotal}
+ organization={organization}
+ qprofile={profile.key}
+ total={this.state.total}
+ />
+ {TYPES.map(type =>
+ <ProfileRulesRowOfType
+ key={type}
+ count={this.getRulesCountForType(type)}
+ organization={organization}
+ qprofile={profile.key}
+ total={this.getRulesTotalForType(type)}
+ type={type}
+ />
+ )}
+ </tbody>
+ </table>
+
+ {this.props.canAdmin &&
+ !profile.isBuiltIn &&
+ <div className="text-right big-spacer-top">
+ <Link to={activateMoreUrl} className="button js-activate-rules">
+ {translate('quality_profiles.activate_more')}
+ </Link>
+ </div>}
+ </div>
+ {profile.activeDeprecatedRuleCount > 0 &&
+ <ProfileRulesDeprecatedWarning
+ activeDeprecatedRules={profile.activeDeprecatedRuleCount}
+ organization={organization}
+ profile={profile.key}
+ />}
+ {compareToSonarWay != null &&
+ compareToSonarWay.missingRuleCount > 0 &&
+ <ProfileRulesSonarWayComparison
+ language={profile.language}
+ organization={organization}
+ profile={profile.key}
+ sonarway={compareToSonarWay.profile}
+ sonarWayMissingRules={compareToSonarWay.missingRuleCount}
+ />}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 Tooltip from '../../../components/controls/Tooltip';
-import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = { activeDeprecatedRules: number, organization: ?string, profile: string };
-*/
-
-export default function ProfileRulesDeprecatedWarning(props /*: Props */) {
- const url = getDeprecatedActiveRulesUrl({ qprofile: props.profile }, props.organization);
- return (
- <div className="quality-profile-rules-deprecated clearfix">
- <span className="pull-left">
- {translate('quality_profiles.deprecated_rules')}
- <Tooltip overlay={translate('quality_profiles.deprecated_rules_description')}>
- <i className="icon-help spacer-left" />
- </Tooltip>
- </span>
- <Link className="pull-right" to={url}>
- {props.activeDeprecatedRules}
- </Link>
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 Tooltip from '../../../components/controls/Tooltip';
+import { getDeprecatedActiveRulesUrl } from '../../../helpers/urls';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ activeDeprecatedRules: number;
+ organization: string | null;
+ profile: string;
+}
+
+export default function ProfileRulesDeprecatedWarning(props: Props) {
+ const url = getDeprecatedActiveRulesUrl({ qprofile: props.profile }, props.organization);
+ return (
+ <div className="quality-profile-rules-deprecated clearfix">
+ <span className="pull-left">
+ {translate('quality_profiles.deprecated_rules')}
+ <Tooltip overlay={translate('quality_profiles.deprecated_rules_description')}>
+ <i className="icon-help spacer-left" />
+ </Tooltip>
+ </span>
+ <Link className="pull-right" to={url}>
+ {props.activeDeprecatedRules}
+ </Link>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
-import { formatMeasure } from '../../../helpers/measures';
-import { getRulesUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- count: ?number,
- organization: ?string,
- qprofile: string,
- total: ?number,
- type: string
-};
-*/
-
-export default function ProfileRulesRowOfType(props /*: Props */) {
- const activeRulesUrl = getRulesUrl(
- { qprofile: props.qprofile, activation: 'true', types: props.type },
- props.organization
- );
- const inactiveRulesUrl = getRulesUrl(
- { qprofile: props.qprofile, activation: 'false', types: props.type },
- props.organization
- );
- let inactiveCount = null;
- if (props.count != null && props.total != null) {
- inactiveCount = props.total - props.count;
- }
-
- return (
- <tr>
- <td>
- <span>
- <IssueTypeIcon query={props.type} className="little-spacer-right" />
- {translate('issue.type', props.type, 'plural')}
- </span>
- </td>
- <td className="thin nowrap text-right">
- {props.count != null &&
- <Link to={activeRulesUrl}>
- {formatMeasure(props.count, 'SHORT_INT')}
- </Link>}
- </td>
- <td className="thin nowrap text-right">
- {inactiveCount != null &&
- (inactiveCount > 0
- ? <Link to={inactiveRulesUrl} className="small text-muted">
- {formatMeasure(inactiveCount, 'SHORT_INT')}
- </Link>
- : <span className="note text-muted">0</span>)}
- </td>
- </tr>
- );
-}
--- /dev/null
+/*
+ * 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 IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
+import { formatMeasure } from '../../../helpers/measures';
+import { getRulesUrl } from '../../../helpers/urls';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ count: number | null;
+ organization: string | null;
+ qprofile: string;
+ total: number | null;
+ type: string;
+}
+
+export default function ProfileRulesRowOfType(props: Props) {
+ const activeRulesUrl = getRulesUrl(
+ { qprofile: props.qprofile, activation: 'true', types: props.type },
+ props.organization
+ );
+ const inactiveRulesUrl = getRulesUrl(
+ { qprofile: props.qprofile, activation: 'false', types: props.type },
+ props.organization
+ );
+ let inactiveCount = null;
+ if (props.count != null && props.total != null) {
+ inactiveCount = props.total - props.count;
+ }
+
+ return (
+ <tr>
+ <td>
+ <span>
+ <IssueTypeIcon query={props.type} className="little-spacer-right" />
+ {translate('issue.type', props.type, 'plural')}
+ </span>
+ </td>
+ <td className="thin nowrap text-right">
+ {props.count != null &&
+ <Link to={activeRulesUrl}>
+ {formatMeasure(props.count, 'SHORT_INT', null)}
+ </Link>}
+ </td>
+ <td className="thin nowrap text-right">
+ {inactiveCount != null &&
+ (inactiveCount > 0
+ ? <Link to={inactiveRulesUrl} className="small text-muted">
+ {formatMeasure(inactiveCount, 'SHORT_INT', null)}
+ </Link>
+ : <span className="note text-muted">0</span>)}
+ </td>
+ </tr>
+ );
+}
+++ /dev/null
-/*
- * 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 { formatMeasure } from '../../../helpers/measures';
-import { getRulesUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- count: ?number,
- organization: ?string,
- qprofile: string,
- total: ?number
-};
-*/
-
-export default function ProfileRulesRowTotal(props /*: Props */) {
- const activeRulesUrl = getRulesUrl(
- { qprofile: props.qprofile, activation: 'true' },
- props.organization
- );
- const inactiveRulesUrl = getRulesUrl(
- { qprofile: props.qprofile, activation: 'false' },
- props.organization
- );
- let inactiveCount = null;
- if (props.count != null && props.total != null) {
- inactiveCount = props.total - props.count;
- }
-
- return (
- <tr>
- <td>
- <strong>
- {translate('total')}
- </strong>
- </td>
- <td className="thin nowrap text-right">
- {props.count != null &&
- <Link to={activeRulesUrl}>
- <strong>
- {formatMeasure(props.count, 'SHORT_INT')}
- </strong>
- </Link>}
- </td>
- <td className="thin nowrap text-right">
- {inactiveCount != null &&
- (inactiveCount > 0
- ? <Link to={inactiveRulesUrl} className="small text-muted">
- <strong>
- {formatMeasure(inactiveCount, 'SHORT_INT')}
- </strong>
- </Link>
- : <span className="note text-muted">0</span>)}
- </td>
- </tr>
- );
-}
--- /dev/null
+/*
+ * 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 { formatMeasure } from '../../../helpers/measures';
+import { getRulesUrl } from '../../../helpers/urls';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ count: number | null;
+ organization: string | null;
+ qprofile: string;
+ total: number | null;
+}
+
+export default function ProfileRulesRowTotal(props: Props) {
+ const activeRulesUrl = getRulesUrl(
+ { qprofile: props.qprofile, activation: 'true' },
+ props.organization
+ );
+ const inactiveRulesUrl = getRulesUrl(
+ { qprofile: props.qprofile, activation: 'false' },
+ props.organization
+ );
+ let inactiveCount = null;
+ if (props.count != null && props.total != null) {
+ inactiveCount = props.total - props.count;
+ }
+
+ return (
+ <tr>
+ <td>
+ <strong>
+ {translate('total')}
+ </strong>
+ </td>
+ <td className="thin nowrap text-right">
+ {props.count != null &&
+ <Link to={activeRulesUrl}>
+ <strong>
+ {formatMeasure(props.count, 'SHORT_INT', null)}
+ </strong>
+ </Link>}
+ </td>
+ <td className="thin nowrap text-right">
+ {inactiveCount != null &&
+ (inactiveCount > 0
+ ? <Link to={inactiveRulesUrl} className="small text-muted">
+ <strong>
+ {formatMeasure(inactiveCount, 'SHORT_INT', null)}
+ </strong>
+ </Link>
+ : <span className="note text-muted">0</span>)}
+ </td>
+ </tr>
+ );
+}
+++ /dev/null
-/*
- * 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 Tooltip from '../../../components/controls/Tooltip';
-import { getRulesUrl } from '../../../helpers/urls';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- language: string,
- organization: ?string,
- profile: string,
- sonarway: string,
- sonarWayMissingRules: number
-};
-*/
-
-export default function ProfileRulesSonarWayComparison(props /*: Props */) {
- const url = getRulesUrl(
- {
- qprofile: props.profile,
- activation: false,
- compareToProfile: props.sonarway,
- languages: props.language
- },
- props.organization
- );
-
- return (
- <div className="quality-profile-rules-sonarway-missing clearfix">
- <span className="pull-left">
- {translate('quality_profiles.sonarway_missing_rules')}
- <Tooltip overlay={translate('quality_profiles.sonarway_missing_rules_description')}>
- <i className="icon-help spacer-left" />
- </Tooltip>
- </span>
- <Link className="pull-right" to={url}>
- {props.sonarWayMissingRules}
- </Link>
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 Tooltip from '../../../components/controls/Tooltip';
+import { getRulesUrl } from '../../../helpers/urls';
+import { translate } from '../../../helpers/l10n';
+
+interface Props {
+ language: string;
+ organization: string | null;
+ profile: string;
+ sonarway: string;
+ sonarWayMissingRules: number;
+}
+
+export default function ProfileRulesSonarWayComparison(props: Props) {
+ const url = getRulesUrl(
+ {
+ qprofile: props.profile,
+ activation: false,
+ compareToProfile: props.sonarway,
+ languages: props.language
+ },
+ props.organization
+ );
+
+ return (
+ <div className="quality-profile-rules-sonarway-missing clearfix">
+ <span className="pull-left">
+ {translate('quality_profiles.sonarway_missing_rules')}
+ <Tooltip overlay={translate('quality_profiles.sonarway_missing_rules_description')}>
+ <i className="icon-help spacer-left" />
+ </Tooltip>
+ </span>
+ <Link className="pull-right" to={url}>
+ {props.sonarWayMissingRules}
+ </Link>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import { shallow } from 'enzyme';
-import ProfileRules from '../ProfileRules';
-import { doAsync } from '../../../../helpers/testUtils';
-import * as apiRules from '../../../../api/rules';
-import * as apiQP from '../../../../api/quality-profiles';
-
-const PROFILE = {
- key: 'foo',
- name: 'Foo',
- isBuiltIn: false,
- isDefault: false,
- isInherited: false,
- language: 'java',
- languageName: 'Java',
- activeRuleCount: 68,
- activeDeprecatedRuleCount: 0,
- rulesUpdatedAt: '2017-06-28T12:58:44+0000',
- depth: 0,
- childrenCount: 0
-};
-
-const apiResponseAll = {
- total: 243,
- facets: [
- {
- property: 'types',
- values: [
- { val: 'CODE_SMELL', count: 168 },
- { val: 'BUG', count: 68 },
- { val: 'VULNERABILITY', count: 7 }
- ]
- }
- ]
-};
-
-const apiResponseActive = {
- total: 68,
- facets: [
- {
- property: 'types',
- values: [
- { val: 'BUG', count: 68 },
- { val: 'CODE_SMELL', count: 0 },
- { val: 'VULNERABILITY', count: 0 }
- ]
- }
- ]
-};
-
-// Mock api some api functions
-// eslint-disable-next-line
-apiRules.searchRules = data =>
- Promise.resolve(data.activation === 'true' ? apiResponseActive : apiResponseAll);
-// eslint-disable-next-line
-apiQP.getQualityProfiles = () =>
- Promise.resolve({
- compareToSonarWay: {
- profile: 'sonarway',
- profileName: 'Sonar way',
- missingRuleCount: 4
- }
- });
-
-it('should render the quality profiles rules with sonarway comparison', () => {
- const wrapper = shallow(<ProfileRules canAdmin={false} organization="foo" profile={PROFILE} />);
- wrapper.instance().mounted = true;
- wrapper.instance().loadRules();
- return doAsync(() => {
- wrapper.update();
- expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(1);
- expect(wrapper).toMatchSnapshot();
- });
-});
-
-it('should show a button to activate more rules for admins', () => {
- const wrapper = shallow(<ProfileRules canAdmin={true} organization="foo" profile={PROFILE} />);
- expect(wrapper.find('.js-activate-rules')).toMatchSnapshot();
-});
-
-it('should show a deprecated rules warning message', () => {
- const wrapper = shallow(
- <ProfileRules
- canAdmin={true}
- organization="foo"
- profile={{ ...PROFILE, activeDeprecatedRuleCount: 8 }}
- />
- );
- expect(wrapper.find('ProfileRulesDeprecatedWarning')).toMatchSnapshot();
-});
-
-it('should not show a button to activate more rules on built in profiles', () => {
- const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
- );
- expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
-});
-
-it('should not show a button to activate more rules on built in profiles', () => {
- const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
- );
- expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
-});
-
-it('should not show sonarway comparison for built in profiles', () => {
- // eslint-disable-next-line
- apiQP.getQualityProfiles = jest.fn(() => Promise.resolve());
- const wrapper = shallow(
- <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
- );
- wrapper.instance().mounted = true;
- wrapper.instance().loadRules();
- return doAsync(() => {
- wrapper.update();
- expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(0);
- expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0);
- });
-});
-
-it('should not show sonarway comparison if there is no missing rules', () => {
- // eslint-disable-next-line
- apiQP.getQualityProfiles = jest.fn(() =>
- Promise.resolve({
- compareToSonarWay: {
- profile: 'sonarway',
- profileName: 'Sonar way',
- missingRuleCount: 0
- }
- })
- );
- const wrapper = shallow(<ProfileRules canAdmin={true} organization={null} profile={PROFILE} />);
- wrapper.instance().mounted = true;
- wrapper.instance().loadRules();
- return doAsync(() => {
- wrapper.update();
- expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(1);
- expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0);
- });
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import ProfileRules from '../ProfileRules';
+import { doAsync } from '../../../../helpers/testUtils';
+import * as apiRules from '../../../../api/rules';
+import * as apiQP from '../../../../api/quality-profiles';
+
+const PROFILE = {
+ key: 'foo',
+ name: 'Foo',
+ isBuiltIn: false,
+ isDefault: false,
+ isInherited: false,
+ language: 'java',
+ languageName: 'Java',
+ activeRuleCount: 68,
+ activeDeprecatedRuleCount: 0,
+ rulesUpdatedAt: '2017-06-28T12:58:44+0000',
+ depth: 0,
+ childrenCount: 0
+};
+
+const apiResponseAll = {
+ total: 243,
+ facets: [
+ {
+ property: 'types',
+ values: [
+ { val: 'CODE_SMELL', count: 168 },
+ { val: 'BUG', count: 68 },
+ { val: 'VULNERABILITY', count: 7 }
+ ]
+ }
+ ]
+};
+
+const apiResponseActive = {
+ total: 68,
+ facets: [
+ {
+ property: 'types',
+ values: [
+ { val: 'BUG', count: 68 },
+ { val: 'CODE_SMELL', count: 0 },
+ { val: 'VULNERABILITY', count: 0 }
+ ]
+ }
+ ]
+};
+
+// Mock api some api functions
+(apiRules as any).searchRules = (data: any) =>
+ Promise.resolve(data.activation === 'true' ? apiResponseActive : apiResponseAll);
+(apiQP as any).getQualityProfiles = () =>
+ Promise.resolve({
+ compareToSonarWay: {
+ profile: 'sonarway',
+ profileName: 'Sonar way',
+ missingRuleCount: 4
+ }
+ });
+
+it('should render the quality profiles rules with sonarway comparison', () => {
+ const wrapper = shallow(<ProfileRules canAdmin={false} organization="foo" profile={PROFILE} />);
+ const instance = wrapper.instance() as any;
+ instance.mounted = true;
+ instance.loadRules();
+ return doAsync(() => {
+ wrapper.update();
+ expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(1);
+ expect(wrapper).toMatchSnapshot();
+ });
+});
+
+it('should show a button to activate more rules for admins', () => {
+ const wrapper = shallow(<ProfileRules canAdmin={true} organization="foo" profile={PROFILE} />);
+ expect(wrapper.find('.js-activate-rules')).toMatchSnapshot();
+});
+
+it('should show a deprecated rules warning message', () => {
+ const wrapper = shallow(
+ <ProfileRules
+ canAdmin={true}
+ organization="foo"
+ profile={{ ...PROFILE, activeDeprecatedRuleCount: 8 }}
+ />
+ );
+ expect(wrapper.find('ProfileRulesDeprecatedWarning')).toMatchSnapshot();
+});
+
+it('should not show a button to activate more rules on built in profiles', () => {
+ const wrapper = shallow(
+ <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
+ );
+ expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
+});
+
+it('should not show a button to activate more rules on built in profiles', () => {
+ const wrapper = shallow(
+ <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
+ );
+ expect(wrapper.find('.js-activate-rules')).toHaveLength(0);
+});
+
+it('should not show sonarway comparison for built in profiles', () => {
+ (apiQP as any).getQualityProfiles = jest.fn(() => Promise.resolve());
+ const wrapper = shallow(
+ <ProfileRules canAdmin={true} organization={null} profile={{ ...PROFILE, isBuiltIn: true }} />
+ );
+ const instance = wrapper.instance() as any;
+ instance.mounted = true;
+ instance.loadRules();
+ return doAsync(() => {
+ wrapper.update();
+ expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(0);
+ expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0);
+ });
+});
+
+it('should not show sonarway comparison if there is no missing rules', () => {
+ (apiQP as any).getQualityProfiles = jest.fn(() =>
+ Promise.resolve({
+ compareToSonarWay: {
+ profile: 'sonarway',
+ profileName: 'Sonar way',
+ missingRuleCount: 0
+ }
+ })
+ );
+ const wrapper = shallow(<ProfileRules canAdmin={true} organization={null} profile={PROFILE} />);
+ const instance = wrapper.instance() as any;
+ instance.mounted = true;
+ instance.loadRules();
+ return doAsync(() => {
+ wrapper.update();
+ expect(apiQP.getQualityProfiles).toHaveBeenCalledTimes(1);
+ expect(wrapper.find('ProfileRulesSonarWayComparison')).toHaveLength(0);
+ });
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import ProfileRulesDeprecatedWarning from '../ProfileRulesDeprecatedWarning';
-
-it('should render correctly', () => {
- expect(
- shallow(
- <ProfileRulesDeprecatedWarning activeDeprecatedRules={18} organization="foo" profile="bar" />
- )
- ).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import ProfileRulesDeprecatedWarning from '../ProfileRulesDeprecatedWarning';
+
+it('should render correctly', () => {
+ expect(
+ shallow(
+ <ProfileRulesDeprecatedWarning activeDeprecatedRules={18} organization="foo" profile="bar" />
+ )
+ ).toMatchSnapshot();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import ProfileRulesRowOfType from '../ProfileRulesRowOfType';
-
-it('should render correctly', () => {
- expect(
- shallow(
- <ProfileRulesRowOfType count={3} organization="foo" qprofile="bar" total={10} type="BUG" />
- )
- ).toMatchSnapshot();
-});
-
-it('should render correctly if there is 0 rules', () => {
- expect(
- shallow(
- <ProfileRulesRowOfType
- count={0}
- organization={null}
- qprofile="bar"
- total={0}
- type="VULNERABILITY"
- />
- )
- ).toMatchSnapshot();
-});
-
-it('should render correctly if there is missing data', () => {
- expect(
- shallow(
- <ProfileRulesRowOfType
- count={5}
- organization={null}
- qprofile="bar"
- total={null}
- type="VULNERABILITY"
- />
- )
- ).toMatchSnapshot();
- expect(
- shallow(
- <ProfileRulesRowOfType
- count={null}
- organization={null}
- qprofile="foo"
- total={10}
- type="VULNERABILITY"
- />
- )
- ).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import ProfileRulesRowOfType from '../ProfileRulesRowOfType';
+
+it('should render correctly', () => {
+ expect(
+ shallow(
+ <ProfileRulesRowOfType count={3} organization="foo" qprofile="bar" total={10} type="BUG" />
+ )
+ ).toMatchSnapshot();
+});
+
+it('should render correctly if there is 0 rules', () => {
+ expect(
+ shallow(
+ <ProfileRulesRowOfType
+ count={0}
+ organization={null}
+ qprofile="bar"
+ total={0}
+ type="VULNERABILITY"
+ />
+ )
+ ).toMatchSnapshot();
+});
+
+it('should render correctly if there is missing data', () => {
+ expect(
+ shallow(
+ <ProfileRulesRowOfType
+ count={5}
+ organization={null}
+ qprofile="bar"
+ total={null}
+ type="VULNERABILITY"
+ />
+ )
+ ).toMatchSnapshot();
+ expect(
+ shallow(
+ <ProfileRulesRowOfType
+ count={null}
+ organization={null}
+ qprofile="foo"
+ total={10}
+ type="VULNERABILITY"
+ />
+ )
+ ).toMatchSnapshot();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import ProfileRulesRowTotal from '../ProfileRulesRowTotal';
-
-it('should render correctly', () => {
- expect(
- shallow(<ProfileRulesRowTotal count={3} organization="foo" qprofile="bar" total={10} />)
- ).toMatchSnapshot();
-});
-
-it('should render correctly if there is 0 rules', () => {
- expect(
- shallow(<ProfileRulesRowTotal count={0} organization={null} qprofile="bar" total={0} />)
- ).toMatchSnapshot();
-});
-
-it('should render correctly if there is missing data', () => {
- expect(
- shallow(<ProfileRulesRowTotal count={5} organization={null} qprofile="bar" total={null} />)
- ).toMatchSnapshot();
- expect(
- shallow(<ProfileRulesRowTotal count={null} organization={null} qprofile="foo" total={10} />)
- ).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import ProfileRulesRowTotal from '../ProfileRulesRowTotal';
+
+it('should render correctly', () => {
+ expect(
+ shallow(<ProfileRulesRowTotal count={3} organization="foo" qprofile="bar" total={10} />)
+ ).toMatchSnapshot();
+});
+
+it('should render correctly if there is 0 rules', () => {
+ expect(
+ shallow(<ProfileRulesRowTotal count={0} organization={null} qprofile="bar" total={0} />)
+ ).toMatchSnapshot();
+});
+
+it('should render correctly if there is missing data', () => {
+ expect(
+ shallow(<ProfileRulesRowTotal count={5} organization={null} qprofile="bar" total={null} />)
+ ).toMatchSnapshot();
+ expect(
+ shallow(<ProfileRulesRowTotal count={null} organization={null} qprofile="foo" total={10} />)
+ ).toMatchSnapshot();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import ProfileRulesSonarWayComparison from '../ProfileRulesSonarWayComparison';
-
-it('should render correctly', () => {
- expect(
- shallow(
- <ProfileRulesSonarWayComparison
- language="Java"
- organization="foo"
- profile="bar"
- sonarway="baz"
- sonarWayMissingRules={158}
- />
- )
- ).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import ProfileRulesSonarWayComparison from '../ProfileRulesSonarWayComparison';
+
+it('should render correctly', () => {
+ expect(
+ shallow(
+ <ProfileRulesSonarWayComparison
+ language="Java"
+ organization="foo"
+ profile="bar"
+ sonarway="baz"
+ sonarWayMissingRules={158}
+ />
+ )
+ ).toMatchSnapshot();
+});
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render the quality profiles rules with sonarway comparison 1`] = `
-<div
- className="quality-profile-rules"
->
- <div
- className="quality-profile-rules-distribution"
- >
- <table
- className="data condensed"
- >
- <thead>
- <tr>
- <th>
- <h2>
- rules
- </h2>
- </th>
- <th>
- active
- </th>
- <th>
- inactive
- </th>
- </tr>
- </thead>
- <tbody>
- <ProfileRulesRowTotal
- count={68}
- organization="foo"
- qprofile="foo"
- total={243}
- />
- <ProfileRulesRowOfType
- count={68}
- organization="foo"
- qprofile="foo"
- total={68}
- type="BUG"
- />
- <ProfileRulesRowOfType
- count={0}
- organization="foo"
- qprofile="foo"
- total={7}
- type="VULNERABILITY"
- />
- <ProfileRulesRowOfType
- count={0}
- organization="foo"
- qprofile="foo"
- total={168}
- type="CODE_SMELL"
- />
- </tbody>
- </table>
- </div>
- <ProfileRulesSonarWayComparison
- language="java"
- organization="foo"
- profile="foo"
- sonarWayMissingRules={4}
- sonarway="sonarway"
- />
-</div>
-`;
-
-exports[`should show a button to activate more rules for admins 1`] = `
-<Link
- className="button js-activate-rules"
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=foo|activation=false"
->
- quality_profiles.activate_more
-</Link>
-`;
-
-exports[`should show a deprecated rules warning message 1`] = `
-<ProfileRulesDeprecatedWarning
- activeDeprecatedRules={8}
- organization="foo"
- profile="foo"
-/>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render the quality profiles rules with sonarway comparison 1`] = `
+<div
+ className="quality-profile-rules"
+>
+ <div
+ className="quality-profile-rules-distribution"
+ >
+ <table
+ className="data condensed"
+ >
+ <thead>
+ <tr>
+ <th>
+ <h2>
+ rules
+ </h2>
+ </th>
+ <th>
+ active
+ </th>
+ <th>
+ inactive
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ <ProfileRulesRowTotal
+ count={68}
+ organization="foo"
+ qprofile="foo"
+ total={243}
+ />
+ <ProfileRulesRowOfType
+ count={68}
+ organization="foo"
+ qprofile="foo"
+ total={68}
+ type="BUG"
+ />
+ <ProfileRulesRowOfType
+ count={0}
+ organization="foo"
+ qprofile="foo"
+ total={7}
+ type="VULNERABILITY"
+ />
+ <ProfileRulesRowOfType
+ count={0}
+ organization="foo"
+ qprofile="foo"
+ total={168}
+ type="CODE_SMELL"
+ />
+ </tbody>
+ </table>
+ </div>
+ <ProfileRulesSonarWayComparison
+ language="java"
+ organization="foo"
+ profile="foo"
+ sonarWayMissingRules={4}
+ sonarway="sonarway"
+ />
+</div>
+`;
+
+exports[`should show a button to activate more rules for admins 1`] = `
+<Link
+ className="button js-activate-rules"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=foo|activation=false"
+>
+ quality_profiles.activate_more
+</Link>
+`;
+
+exports[`should show a deprecated rules warning message 1`] = `
+<ProfileRulesDeprecatedWarning
+ activeDeprecatedRules={8}
+ organization="foo"
+ profile="foo"
+/>
+`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
- className="quality-profile-rules-deprecated clearfix"
->
- <span
- className="pull-left"
- >
- quality_profiles.deprecated_rules
- <Tooltip
- overlay="quality_profiles.deprecated_rules_description"
- placement="bottom"
- >
- <i
- className="icon-help spacer-left"
- />
- </Tooltip>
- </span>
- <Link
- className="pull-right"
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=true|statuses=DEPRECATED"
- >
- 18
- </Link>
-</div>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="quality-profile-rules-deprecated clearfix"
+>
+ <span
+ className="pull-left"
+ >
+ quality_profiles.deprecated_rules
+ <Tooltip
+ overlay="quality_profiles.deprecated_rules_description"
+ placement="bottom"
+ >
+ <i
+ className="icon-help spacer-left"
+ />
+ </Tooltip>
+ </span>
+ <Link
+ className="pull-right"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=true|statuses=DEPRECATED"
+ >
+ 18
+ </Link>
+</div>
+`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<tr>
- <td>
- <span>
- <IssueTypeIcon
- className="little-spacer-right"
- query="BUG"
- />
- issue.type.BUG.plural
- </span>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=true|types=BUG"
- >
- 3
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- className="small text-muted"
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=false|types=BUG"
- >
- 7
- </Link>
- </td>
-</tr>
-`;
-
-exports[`should render correctly if there is 0 rules 1`] = `
-<tr>
- <td>
- <span>
- <IssueTypeIcon
- className="little-spacer-right"
- query="VULNERABILITY"
- />
- issue.type.VULNERABILITY.plural
- </span>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/coding_rules#qprofile=bar|activation=true|types=VULNERABILITY"
- >
- 0
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <span
- className="note text-muted"
- >
- 0
- </span>
- </td>
-</tr>
-`;
-
-exports[`should render correctly if there is missing data 1`] = `
-<tr>
- <td>
- <span>
- <IssueTypeIcon
- className="little-spacer-right"
- query="VULNERABILITY"
- />
- issue.type.VULNERABILITY.plural
- </span>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/coding_rules#qprofile=bar|activation=true|types=VULNERABILITY"
- >
- 5
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- />
-</tr>
-`;
-
-exports[`should render correctly if there is missing data 2`] = `
-<tr>
- <td>
- <span>
- <IssueTypeIcon
- className="little-spacer-right"
- query="VULNERABILITY"
- />
- issue.type.VULNERABILITY.plural
- </span>
- </td>
- <td
- className="thin nowrap text-right"
- />
- <td
- className="thin nowrap text-right"
- />
-</tr>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<tr>
+ <td>
+ <span>
+ <IssueTypeIcon
+ className="little-spacer-right"
+ query="BUG"
+ />
+ issue.type.BUG.plural
+ </span>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=true|types=BUG"
+ >
+ 3
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ className="small text-muted"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=false|types=BUG"
+ >
+ 7
+ </Link>
+ </td>
+</tr>
+`;
+
+exports[`should render correctly if there is 0 rules 1`] = `
+<tr>
+ <td>
+ <span>
+ <IssueTypeIcon
+ className="little-spacer-right"
+ query="VULNERABILITY"
+ />
+ issue.type.VULNERABILITY.plural
+ </span>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/coding_rules#qprofile=bar|activation=true|types=VULNERABILITY"
+ >
+ 0
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <span
+ className="note text-muted"
+ >
+ 0
+ </span>
+ </td>
+</tr>
+`;
+
+exports[`should render correctly if there is missing data 1`] = `
+<tr>
+ <td>
+ <span>
+ <IssueTypeIcon
+ className="little-spacer-right"
+ query="VULNERABILITY"
+ />
+ issue.type.VULNERABILITY.plural
+ </span>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/coding_rules#qprofile=bar|activation=true|types=VULNERABILITY"
+ >
+ 5
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ />
+</tr>
+`;
+
+exports[`should render correctly if there is missing data 2`] = `
+<tr>
+ <td>
+ <span>
+ <IssueTypeIcon
+ className="little-spacer-right"
+ query="VULNERABILITY"
+ />
+ issue.type.VULNERABILITY.plural
+ </span>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ />
+ <td
+ className="thin nowrap text-right"
+ />
+</tr>
+`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<tr>
- <td>
- <strong>
- total
- </strong>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=true"
- >
- <strong>
- 3
- </strong>
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- className="small text-muted"
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=false"
- >
- <strong>
- 7
- </strong>
- </Link>
- </td>
-</tr>
-`;
-
-exports[`should render correctly if there is 0 rules 1`] = `
-<tr>
- <td>
- <strong>
- total
- </strong>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/coding_rules#qprofile=bar|activation=true"
- >
- <strong>
- 0
- </strong>
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <span
- className="note text-muted"
- >
- 0
- </span>
- </td>
-</tr>
-`;
-
-exports[`should render correctly if there is missing data 1`] = `
-<tr>
- <td>
- <strong>
- total
- </strong>
- </td>
- <td
- className="thin nowrap text-right"
- >
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/coding_rules#qprofile=bar|activation=true"
- >
- <strong>
- 5
- </strong>
- </Link>
- </td>
- <td
- className="thin nowrap text-right"
- />
-</tr>
-`;
-
-exports[`should render correctly if there is missing data 2`] = `
-<tr>
- <td>
- <strong>
- total
- </strong>
- </td>
- <td
- className="thin nowrap text-right"
- />
- <td
- className="thin nowrap text-right"
- />
-</tr>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<tr>
+ <td>
+ <strong>
+ total
+ </strong>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=true"
+ >
+ <strong>
+ 3
+ </strong>
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ className="small text-muted"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=false"
+ >
+ <strong>
+ 7
+ </strong>
+ </Link>
+ </td>
+</tr>
+`;
+
+exports[`should render correctly if there is 0 rules 1`] = `
+<tr>
+ <td>
+ <strong>
+ total
+ </strong>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/coding_rules#qprofile=bar|activation=true"
+ >
+ <strong>
+ 0
+ </strong>
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <span
+ className="note text-muted"
+ >
+ 0
+ </span>
+ </td>
+</tr>
+`;
+
+exports[`should render correctly if there is missing data 1`] = `
+<tr>
+ <td>
+ <strong>
+ total
+ </strong>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/coding_rules#qprofile=bar|activation=true"
+ >
+ <strong>
+ 5
+ </strong>
+ </Link>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ />
+</tr>
+`;
+
+exports[`should render correctly if there is missing data 2`] = `
+<tr>
+ <td>
+ <strong>
+ total
+ </strong>
+ </td>
+ <td
+ className="thin nowrap text-right"
+ />
+ <td
+ className="thin nowrap text-right"
+ />
+</tr>
+`;
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render correctly 1`] = `
-<div
- className="quality-profile-rules-sonarway-missing clearfix"
->
- <span
- className="pull-left"
- >
- quality_profiles.sonarway_missing_rules
- <Tooltip
- overlay="quality_profiles.sonarway_missing_rules_description"
- placement="bottom"
- >
- <i
- className="icon-help spacer-left"
- />
- </Tooltip>
- </span>
- <Link
- className="pull-right"
- onlyActiveOnIndex={false}
- style={Object {}}
- to="/organizations/foo/rules#qprofile=bar|activation=false|compareToProfile=baz|languages=Java"
- >
- 158
- </Link>
-</div>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="quality-profile-rules-sonarway-missing clearfix"
+>
+ <span
+ className="pull-left"
+ >
+ quality_profiles.sonarway_missing_rules
+ <Tooltip
+ overlay="quality_profiles.sonarway_missing_rules_description"
+ placement="bottom"
+ >
+ <i
+ className="icon-help spacer-left"
+ />
+ </Tooltip>
+ </span>
+ <Link
+ className="pull-right"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="/organizations/foo/rules#qprofile=bar|activation=false|compareToProfile=baz|languages=Java"
+ >
+ 158
+ </Link>
+</div>
+`;
+++ /dev/null
-/*
- * 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 Modal from 'react-modal';
-import 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 {
- /*:: form: HTMLFormElement; */
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = { importers: [], loading: false, name: '', preloading: true };
-
- componentDidMount() {
- this.mounted = true;
- this.fetchImporters();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- fetchImporters() {
- getImporters().then(importers => {
- if (this.mounted) {
- this.setState({ importers, preloading: false });
- }
- });
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleNameChange = (event /*: { currentTarget: HTMLInputElement } */) => {
- this.setState({ name: event.currentTarget.value });
- };
-
- handleLanguageChange = (option /*: { value: string } */) => {
- this.setState({ language: option.value });
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
-
- this.setState({ loading: true });
-
- const data = new FormData(this.form);
- if (this.props.organization) {
- data.append('organization', this.props.organization);
- }
-
- createQualityProfile(data).then(
- response => this.props.onCreate(response.profile),
- error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- }
- );
- };
-
- render() {
- const header = translate('quality_profiles.new_profile');
-
- const languages = sortBy(this.props.languages, 'name');
- const selectedLanguage = this.state.language || languages[0].key;
- const importers = this.state.importers.filter(importer =>
- importer.languages.includes(selectedLanguage)
- );
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form
- id="create-profile-form"
- onSubmit={this.handleFormSubmit}
- ref={node => (this.form = node)}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
-
- {this.state.preloading
- ? <div className="modal-body">
- <i className="spinner" />
- </div>
- : <div className="modal-body">
- <div className="modal-field">
- <label htmlFor="create-profile-name">
- {translate('name')}
- <em className="mandatory">*</em>
- </label>
- <input
- autoFocus={true}
- id="create-profile-name"
- maxLength="100"
- name="name"
- onChange={this.handleNameChange}
- required={true}
- size="50"
- type="text"
- value={this.state.name}
- />
- </div>
- <div className="modal-field spacer-bottom">
- <label htmlFor="create-profile-language">
- {translate('language')}
- <em className="mandatory">*</em>
- </label>
- <Select
- clearable={false}
- id="create-profile-language"
- name="language"
- onChange={this.handleLanguageChange}
- options={languages.map(language => ({
- label: language.name,
- value: language.key
- }))}
- value={selectedLanguage}
- />
- </div>
- {importers.map(importer =>
- <div
- className="modal-field spacer-bottom js-importer"
- data-key={importer.key}
- key={importer.key}>
- <label htmlFor={'create-profile-form-backup-' + importer.key}>
- {importer.name}
- </label>
- <input
- id={'create-profile-form-backup-' + importer.key}
- name={'backup_' + importer.key}
- type="file"
- />
- <p className="note">
- {translate('quality_profiles.optional_configuration_file')}
- </p>
- </div>
- )}
- </div>}
-
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- {!this.state.preloading &&
- <button disabled={this.state.loading} id="create-profile-submit">
- {translate('create')}
- </button>}
- <a href="#" id="create-profile-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import * as Select from 'react-select';
+import { sortBy } from 'lodash';
+import { getImporters, createQualityProfile } from '../../../api/quality-profiles';
+import { translate } from '../../../helpers/l10n';
+
+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;
+ state: State = { importers: [], loading: false, name: '', preloading: true };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchImporters();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ fetchImporters() {
+ getImporters().then(
+ (importers: Array<{ key: string; languages: Array<string>; name: string }>) => {
+ if (this.mounted) {
+ this.setState({ importers, preloading: false });
+ }
+ }
+ );
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleNameChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
+ this.setState({ name: event.currentTarget.value });
+ };
+
+ handleLanguageChange = (option: { value: string }) => {
+ this.setState({ language: option.value });
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ this.setState({ loading: true });
+
+ const data = new FormData(event.currentTarget);
+ if (this.props.organization) {
+ data.append('organization', this.props.organization);
+ }
+
+ createQualityProfile(data).then(
+ (response: any) => this.props.onCreate(response.profile),
+ (error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ }
+ );
+ };
+
+ render() {
+ const header = translate('quality_profiles.new_profile');
+
+ const languages = sortBy(this.props.languages, 'name');
+ const selectedLanguage = this.state.language || languages[0].key;
+ const importers = this.state.importers.filter(importer =>
+ importer.languages.includes(selectedLanguage)
+ );
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="create-profile-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+
+ {this.state.preloading
+ ? <div className="modal-body">
+ <i className="spinner" />
+ </div>
+ : <div className="modal-body">
+ <div className="modal-field">
+ <label htmlFor="create-profile-name">
+ {translate('name')}
+ <em className="mandatory">*</em>
+ </label>
+ <input
+ autoFocus={true}
+ id="create-profile-name"
+ maxLength={100}
+ name="name"
+ onChange={this.handleNameChange}
+ required={true}
+ size={50}
+ type="text"
+ value={this.state.name}
+ />
+ </div>
+ <div className="modal-field spacer-bottom">
+ <label htmlFor="create-profile-language">
+ {translate('language')}
+ <em className="mandatory">*</em>
+ </label>
+ <Select
+ clearable={false}
+ name="language"
+ onChange={this.handleLanguageChange}
+ options={languages.map(language => ({
+ label: language.name,
+ value: language.key
+ }))}
+ value={selectedLanguage}
+ />
+ </div>
+ {importers.map(importer =>
+ <div
+ className="modal-field spacer-bottom js-importer"
+ data-key={importer.key}
+ key={importer.key}>
+ <label htmlFor={'create-profile-form-backup-' + importer.key}>
+ {importer.name}
+ </label>
+ <input
+ id={'create-profile-form-backup-' + importer.key}
+ name={'backup_' + importer.key}
+ type="file"
+ />
+ <p className="note">
+ {translate('quality_profiles.optional_configuration_file')}
+ </p>
+ </div>
+ )}
+ </div>}
+
+ <div className="modal-foot">
+ {this.state.loading && <i className="spinner spacer-right" />}
+ {!this.state.preloading &&
+ <button disabled={this.state.loading} id="create-profile-submit">
+ {translate('create')}
+ </button>}
+ <a href="#" id="create-profile-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 EvolutionDeprecated from './EvolutionDeprecated';
-import EvolutionStagnant from './EvolutionStagnant';
-import EvolutionRules from './EvolutionRules';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- organization: ?string,
- profiles: Array<Profile>
-};
-*/
-
-export default class Evolution extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- const { organization, profiles } = this.props;
-
- return (
- <div className="quality-profiles-evolution">
- <EvolutionDeprecated organization={organization} profiles={profiles} />
- <EvolutionStagnant organization={organization} profiles={profiles} />
- <EvolutionRules organization={organization} />
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 EvolutionDeprecated from './EvolutionDeprecated';
+import EvolutionStagnant from './EvolutionStagnant';
+import EvolutionRules from './EvolutionRules';
+import { IProfile } from '../types';
+
+interface Props {
+ organization: string | null;
+ profiles: IProfile[];
+}
+
+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>
+ );
+}
+++ /dev/null
-/*
- * 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>
- );
- }
-}
--- /dev/null
+/*
+ * 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>
+ );
+}
+++ /dev/null
-/*
- * 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 moment from 'moment';
-import { sortBy } from 'lodash';
-import { searchRules } from '../../../api/rules';
-import { translateWithParameters, translate } from '../../../helpers/l10n';
-import { getRulesUrl } from '../../../helpers/urls';
-import { formatMeasure } from '../../../helpers/measures';
-
-const RULES_LIMIT = 10;
-
-const PERIOD_START_MOMENT = moment().subtract(1, 'year');
-
-function parseRules(r) {
- const { rules, actives } = r;
- return rules.map(rule => {
- const activations = actives[rule.key];
- return { ...rule, activations: activations ? activations.length : 0 };
- });
-}
-
-/*::
-type Props = {
- organization: ?string
-};
-*/
-
-export default class EvolutionRules extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state = {};
-
- componentDidMount() {
- this.mounted = true;
- this.loadLatestRules();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- loadLatestRules() {
- const data = {
- available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD'),
- s: 'createdAt',
- asc: false,
- ps: RULES_LIMIT,
- f: 'name,langName,actives'
- };
-
- searchRules(data).then(r => {
- if (this.mounted) {
- this.setState({
- latestRules: sortBy(parseRules(r), 'langName'),
- latestRulesTotal: r.total
- });
- }
- });
- }
-
- render() {
- if (!this.state.latestRulesTotal) {
- return null;
- }
-
- const newRulesUrl = getRulesUrl(
- {
- available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD')
- },
- this.props.organization
- );
-
- return (
- <div className="quality-profile-box quality-profiles-evolution-rules">
- <div className="clearfix">
- <strong className="pull-left">
- {translate('quality_profiles.latest_new_rules')}
- </strong>
- </div>
- <ul>
- {this.state.latestRules.map(rule =>
- <li key={rule.key} className="spacer-top">
- <div className="text-ellipsis">
- <Link
- to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}
- className="link-no-underline">
- {' '}{rule.name}
- </Link>
- <div className="note">
- {rule.activations
- ? translateWithParameters(
- 'quality_profiles.latest_new_rules.activated',
- rule.langName,
- rule.activations
- )
- : translateWithParameters(
- 'quality_profiles.latest_new_rules.not_activated',
- rule.langName
- )}
- </div>
- </div>
- </li>
- )}
- </ul>
- {this.state.latestRulesTotal > RULES_LIMIT &&
- <div className="spacer-top">
- <Link to={newRulesUrl} className="small">
- {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT')}
- </Link>
- </div>}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 * as moment from 'moment';
+import { sortBy } from 'lodash';
+import { searchRules } from '../../../api/rules';
+import { translateWithParameters, translate } from '../../../helpers/l10n';
+import { getRulesUrl } from '../../../helpers/urls';
+import { formatMeasure } from '../../../helpers/measures';
+
+const RULES_LIMIT = 10;
+
+const PERIOD_START_MOMENT = moment().subtract(1, 'year');
+
+function parseRules(r: any) {
+ const { rules, actives } = r;
+ return rules.map((rule: any) => {
+ const activations = actives[rule.key];
+ return { ...rule, activations: activations ? activations.length : 0 };
+ });
+}
+
+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<Props, State> {
+ mounted: boolean;
+ state: State = {};
+
+ componentDidMount() {
+ this.mounted = true;
+ this.loadLatestRules();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ loadLatestRules() {
+ const data = {
+ available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD'),
+ s: 'createdAt',
+ asc: false,
+ ps: RULES_LIMIT,
+ f: 'name,langName,actives'
+ };
+
+ searchRules(data).then((r: any) => {
+ if (this.mounted) {
+ this.setState({
+ latestRules: sortBy<IRule>(parseRules(r), 'langName'),
+ latestRulesTotal: r.total
+ });
+ }
+ });
+ }
+
+ render() {
+ if (!this.state.latestRulesTotal || !this.state.latestRules) {
+ return null;
+ }
+
+ const newRulesUrl = getRulesUrl(
+ {
+ available_since: PERIOD_START_MOMENT.format('YYYY-MM-DD')
+ },
+ this.props.organization
+ );
+
+ return (
+ <div className="quality-profile-box quality-profiles-evolution-rules">
+ <div className="clearfix">
+ <strong className="pull-left">
+ {translate('quality_profiles.latest_new_rules')}
+ </strong>
+ </div>
+ <ul>
+ {this.state.latestRules.map(rule =>
+ <li key={rule.key} className="spacer-top">
+ <div className="text-ellipsis">
+ <Link
+ to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}
+ className="link-no-underline">
+ {' '}{rule.name}
+ </Link>
+ <div className="note">
+ {rule.activations
+ ? translateWithParameters(
+ 'quality_profiles.latest_new_rules.activated',
+ rule.langName,
+ rule.activations
+ )
+ : translateWithParameters(
+ 'quality_profiles.latest_new_rules.not_activated',
+ rule.langName
+ )}
+ </div>
+ </div>
+ </li>
+ )}
+ </ul>
+ {this.state.latestRulesTotal > RULES_LIMIT &&
+ <div className="spacer-top">
+ <Link to={newRulesUrl} className="small">
+ {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)}
+ </Link>
+ </div>}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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>
- );
- }
-}
--- /dev/null
+/*
+ * 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>
+ );
+}
+++ /dev/null
-/*
- * 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 PageHeader from './PageHeader';
-import Evolution from './Evolution';
-import ProfilesList from './ProfilesList';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-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; */
-
- render() {
- return (
- <div>
- <PageHeader {...this.props} />
-
- <div className="page-with-sidebar">
- <div className="page-main">
- <ProfilesList {...this.props} />
- </div>
- <div className="page-sidebar">
- <Evolution {...this.props} />
- </div>
- </div>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 PageHeader from './PageHeader';
+import Evolution from './Evolution';
+import ProfilesList from './ProfilesList';
+import { IProfile } from '../types';
+
+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>;
+}
+
+export default function HomeContainer(props: Props) {
+ return (
+ <div>
+ <PageHeader {...props} />
+
+ <div className="page-with-sidebar">
+ <div className="page-main">
+ <ProfilesList {...props} />
+ </div>
+ <div className="page-sidebar">
+ <Evolution {...props} />
+ </div>
+ </div>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 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';
-
-/*::
-type Props = {
- canAdmin: boolean,
- languages: Array<{ key: string, name: string }>,
- onRequestFail: Object => void,
- organization: ?string,
- updateProfiles: () => Promise<*>
-};
-*/
-
-/*::
-type State = {
- createFormOpen: boolean,
- restoreFormOpen: boolean
-};
-*/
-
-export default class PageHeader extends React.PureComponent {
- /*:: props: Props; */
-
- static contextTypes = {
- router: PropTypes.object
- };
-
- state /*: State */ = {
- createFormOpen: false,
- restoreFormOpen: false
- };
-
- handleCreateClick = (event /*: Event & { currentTarget: HTMLButtonElement } */) => {
- event.preventDefault();
- event.currentTarget.blur();
- this.setState({ createFormOpen: true });
- };
-
- handleCreate = (profile /*: Profile */) => {
- this.props.updateProfiles().then(() => {
- this.context.router.push(
- getProfilePath(profile.name, profile.language, this.props.organization)
- );
- });
- };
-
- closeCreateForm = () => {
- this.setState({ createFormOpen: false });
- };
-
- handleRestoreClick = (event /*: Event */) => {
- event.preventDefault();
- this.setState({ restoreFormOpen: true });
- };
-
- closeRestoreForm = () => {
- this.setState({ restoreFormOpen: false });
- };
-
- render() {
- return (
- <header className="page-header">
- <h1 className="page-title">
- {translate('quality_profiles.page')}
- </h1>
-
- {this.props.canAdmin &&
- <div className="page-actions button-group dropdown">
- <button id="quality-profiles-create" onClick={this.handleCreateClick}>
- {translate('create')}
- </button>
- <button className="dropdown-toggle js-more-admin-actions" data-toggle="dropdown">
- <i className="icon-dropdown" />
- </button>
- <ul className="dropdown-menu dropdown-menu-right">
- <li>
- <a href="#" id="quality-profiles-restore" onClick={this.handleRestoreClick}>
- {translate('quality_profiles.restore_profile')}
- </a>
- </li>
- </ul>
- </div>}
-
- <div className="page-description markdown">
- {translate('quality_profiles.intro1')}
- <br />
- {translate('quality_profiles.intro2')}
- </div>
-
- {this.state.restoreFormOpen &&
- <RestoreProfileForm
- onClose={this.closeRestoreForm}
- onRequestFail={this.props.onRequestFail}
- onRestore={this.props.updateProfiles}
- organization={this.props.organization}
- />}
-
- {this.state.createFormOpen &&
- <CreateProfileForm
- languages={this.props.languages}
- onClose={this.closeCreateForm}
- onRequestFail={this.props.onRequestFail}
- onCreate={this.handleCreate}
- organization={this.props.organization}
- />}
- </header>
- );
- }
-}
--- /dev/null
+/*
+ * 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 PropTypes from 'prop-types';
+import CreateProfileForm from './CreateProfileForm';
+import RestoreProfileForm from './RestoreProfileForm';
+import { getProfilePath } from '../utils';
+import { translate } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+interface Props {
+ canAdmin: boolean;
+ languages: Array<{ key: string; name: string }>;
+ onRequestFail: (reason: any) => void;
+ organization: string | null;
+ updateProfiles: () => Promise<void>;
+}
+
+interface State {
+ createFormOpen: boolean;
+ restoreFormOpen: boolean;
+}
+
+export default class PageHeader extends React.PureComponent<Props, State> {
+ static contextTypes = {
+ router: PropTypes.object
+ };
+
+ state = {
+ createFormOpen: false,
+ restoreFormOpen: false
+ };
+
+ handleCreateClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ event.currentTarget.blur();
+ this.setState({ createFormOpen: true });
+ };
+
+ handleCreate = (profile: IProfile) => {
+ this.props.updateProfiles().then(() => {
+ this.context.router.push(
+ getProfilePath(profile.name, profile.language, this.props.organization)
+ );
+ });
+ };
+
+ closeCreateForm = () => {
+ this.setState({ createFormOpen: false });
+ };
+
+ handleRestoreClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.setState({ restoreFormOpen: true });
+ };
+
+ closeRestoreForm = () => {
+ this.setState({ restoreFormOpen: false });
+ };
+
+ render() {
+ return (
+ <header className="page-header">
+ <h1 className="page-title">
+ {translate('quality_profiles.page')}
+ </h1>
+
+ {this.props.canAdmin &&
+ <div className="page-actions button-group dropdown">
+ <button id="quality-profiles-create" onClick={this.handleCreateClick}>
+ {translate('create')}
+ </button>
+ <button className="dropdown-toggle js-more-admin-actions" data-toggle="dropdown">
+ <i className="icon-dropdown" />
+ </button>
+ <ul className="dropdown-menu dropdown-menu-right">
+ <li>
+ <a href="#" id="quality-profiles-restore" onClick={this.handleRestoreClick}>
+ {translate('quality_profiles.restore_profile')}
+ </a>
+ </li>
+ </ul>
+ </div>}
+
+ <div className="page-description markdown">
+ {translate('quality_profiles.intro1')}
+ <br />
+ {translate('quality_profiles.intro2')}
+ </div>
+
+ {this.state.restoreFormOpen &&
+ <RestoreProfileForm
+ onClose={this.closeRestoreForm}
+ onRequestFail={this.props.onRequestFail}
+ onRestore={this.props.updateProfiles}
+ organization={this.props.organization}
+ />}
+
+ {this.state.createFormOpen &&
+ <CreateProfileForm
+ languages={this.props.languages}
+ onClose={this.closeCreateForm}
+ onRequestFail={this.props.onRequestFail}
+ onCreate={this.handleCreate}
+ organization={this.props.organization}
+ />}
+ </header>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { 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'; */
-
-/*::
-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; */
-
- renderProfiles(profiles /*: Array<Profile> */) {
- return profiles.map(profile =>
- <ProfilesListRow
- canAdmin={this.props.canAdmin}
- key={profile.key}
- onRequestFail={this.props.onRequestFail}
- organization={this.props.organization}
- profile={profile}
- updateProfiles={this.props.updateProfiles}
- />
- );
- }
-
- renderHeader(languageKey /*: string */, profilesCount /*: number */) {
- const language = this.props.languages.find(l => l.key === languageKey);
-
- if (!language) {
- return null;
- }
-
- return (
- <thead>
- <tr>
- <th>
- {language.name}
- {', '}
- {translateWithParameters('quality_profiles.x_profiles', profilesCount)}
- </th>
- <th className="text-right nowrap">
- {translate('quality_profiles.list.projects')}
- </th>
- <th className="text-right nowrap">
- {translate('quality_profiles.list.rules')}
- </th>
- <th className="text-right nowrap">
- {translate('quality_profiles.list.updated')}
- </th>
- <th className="text-right nowrap">
- {translate('quality_profiles.list.used')}
- </th>
- {this.props.canAdmin && <th> </th>}
- </tr>
- </thead>
- );
- }
-
- render() {
- 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 languagesToShow = sortBy(Object.keys(profilesToShow));
-
- return (
- <div>
- <ProfilesListHeader
- currentFilter={language}
- languages={languages}
- organization={this.props.organization}
- />
-
- {Object.keys(profilesToShow).length === 0 &&
- <div className="alert alert-warning spacer-top">
- {translate('no_results')}
- </div>}
-
- {languagesToShow.map(languageKey =>
- <div key={languageKey} className="quality-profile-box quality-profiles-table">
- <table data-language={languageKey} className="data zebra zebra-hover">
- {profilesToShow[languageKey] != null &&
- this.renderHeader(languageKey, profilesToShow[languageKey].length)}
-
- <TooltipsContainer>
- <tbody>
- {profilesToShow[languageKey] != null &&
- this.renderProfiles(profilesToShow[languageKey])}
- </tbody>
- </TooltipsContainer>
- </table>
- </div>
- )}
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { groupBy, pick, sortBy } from 'lodash';
+import ProfilesListRow from './ProfilesListRow';
+import ProfilesListHeader from './ProfilesListHeader';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { IProfile } from '../types';
+
+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>;
+}
+
+export default class ProfilesList extends React.PureComponent<Props> {
+ renderProfiles(profiles: IProfile[]) {
+ return profiles.map(profile =>
+ <ProfilesListRow
+ canAdmin={this.props.canAdmin}
+ key={profile.key}
+ onRequestFail={this.props.onRequestFail}
+ organization={this.props.organization}
+ profile={profile}
+ updateProfiles={this.props.updateProfiles}
+ />
+ );
+ }
+
+ renderHeader(languageKey: string, profilesCount: number) {
+ const language = this.props.languages.find(l => l.key === languageKey);
+
+ if (!language) {
+ return null;
+ }
+
+ return (
+ <thead>
+ <tr>
+ <th>
+ {language.name}
+ {', '}
+ {translateWithParameters('quality_profiles.x_profiles', profilesCount)}
+ </th>
+ <th className="text-right nowrap">
+ {translate('quality_profiles.list.projects')}
+ </th>
+ <th className="text-right nowrap">
+ {translate('quality_profiles.list.rules')}
+ </th>
+ <th className="text-right nowrap">
+ {translate('quality_profiles.list.updated')}
+ </th>
+ <th className="text-right nowrap">
+ {translate('quality_profiles.list.used')}
+ </th>
+ {this.props.canAdmin && <th> </th>}
+ </tr>
+ </thead>
+ );
+ }
+
+ render() {
+ const { profiles, languages } = this.props;
+ const { language } = this.props.location.query;
+
+ 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));
+
+ return (
+ <div>
+ <ProfilesListHeader
+ currentFilter={language}
+ languages={languages}
+ organization={this.props.organization}
+ />
+
+ {Object.keys(profilesToShow).length === 0 &&
+ <div className="alert alert-warning spacer-top">
+ {translate('no_results')}
+ </div>}
+
+ {languagesToShow.map(languageKey =>
+ <div key={languageKey} className="quality-profile-box quality-profiles-table">
+ <table data-language={languageKey} className="data zebra zebra-hover">
+ {profilesToShow[languageKey] != null &&
+ this.renderHeader(languageKey, profilesToShow[languageKey].length)}
+
+ <tbody>
+ {profilesToShow[languageKey] != null &&
+ this.renderProfiles(profilesToShow[languageKey])}
+ </tbody>
+ </table>
+ </div>
+ )}
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { 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; */
-
- renderFilterToggle() {
- const { languages, currentFilter } = this.props;
- const currentLanguage = currentFilter && languages.find(l => l.key === currentFilter);
-
- const label = currentLanguage
- ? translateWithParameters('quality_profiles.x_Profiles', currentLanguage.name)
- : translate('quality_profiles.all_profiles');
-
- return (
- <a
- className="dropdown-toggle link-no-underline js-language-filter"
- href="#"
- data-toggle="dropdown">
- {label} <i className="icon-dropdown" />
- </a>
- );
- }
-
- renderFilterMenu() {
- return (
- <ul className="dropdown-menu">
- <li>
- <IndexLink to={getProfilesPath(this.props.organization)}>
- {translate('quality_profiles.all_profiles')}
- </IndexLink>
- </li>
- {this.props.languages.map(language =>
- <li key={language.key}>
- <IndexLink
- to={getProfilesForLanguagePath(language.key, this.props.organization)}
- className="js-language-filter-option"
- data-language={language.key}>
- {language.name}
- </IndexLink>
- </li>
- )}
- </ul>
- );
- }
-
- render() {
- if (this.props.languages.length < 2) {
- return null;
- }
-
- const { languages, currentFilter } = this.props;
- const currentLanguage = currentFilter && languages.find(l => l.key === currentFilter);
-
- // if unknown language, then
- if (currentFilter && !currentLanguage) {
- return null;
- }
-
- return (
- <header className="quality-profiles-list-header clearfix">
- <div className="dropdown">
- {this.renderFilterToggle()}
- {this.renderFilterMenu()}
- </div>
- </header>
- );
- }
-}
--- /dev/null
+/*
+ * 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 { IndexLink } from 'react-router';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+import { getProfilesPath, getProfilesForLanguagePath } from '../utils';
+
+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);
+
+ const label = currentLanguage
+ ? translateWithParameters('quality_profiles.x_Profiles', currentLanguage.name)
+ : translate('quality_profiles.all_profiles');
+
+ return (
+ <a
+ className="dropdown-toggle link-no-underline js-language-filter"
+ href="#"
+ data-toggle="dropdown">
+ {label} <i className="icon-dropdown" />
+ </a>
+ );
+ }
+
+ renderFilterMenu() {
+ return (
+ <ul className="dropdown-menu">
+ <li>
+ <IndexLink to={getProfilesPath(this.props.organization)}>
+ {translate('quality_profiles.all_profiles')}
+ </IndexLink>
+ </li>
+ {this.props.languages.map(language =>
+ <li key={language.key}>
+ <IndexLink
+ to={getProfilesForLanguagePath(language.key, this.props.organization)}
+ className="js-language-filter-option"
+ data-language={language.key}>
+ {language.name}
+ </IndexLink>
+ </li>
+ )}
+ </ul>
+ );
+ }
+
+ render() {
+ if (this.props.languages.length < 2) {
+ return null;
+ }
+
+ const { languages, currentFilter } = this.props;
+ const currentLanguage = currentFilter && languages.find(l => l.key === currentFilter);
+
+ // if unknown language, then
+ if (currentFilter && !currentLanguage) {
+ return null;
+ }
+
+ return (
+ <header className="quality-profiles-list-header clearfix">
+ <div className="dropdown">
+ {this.renderFilterToggle()}
+ {this.renderFilterMenu()}
+ </div>
+ </header>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 ProfileLink from '../components/ProfileLink';
-import ProfileDate from '../components/ProfileDate';
-import ProfileActions from '../components/ProfileActions';
-import BuiltInBadge from '../components/BuiltInBadge';
-import { translate } from '../../../helpers/l10n';
-import { getRulesUrl } from '../../../helpers/urls';
-import { isStagnant } from '../utils';
-/*:: import type { Profile } from '../propTypes'; */
-
-/*::
-type Props = {
- canAdmin: boolean,
- onRequestFail: Object => void,
- organization: ?string,
- profile: Profile,
- updateProfiles: () => Promise<*>
-};
-*/
-
-export default class ProfilesListRow extends React.PureComponent {
- /*:: props: Props; */
-
- renderName() {
- const { profile } = this.props;
- const offset = 25 * (profile.depth - 1);
- return (
- <div style={{ paddingLeft: offset }}>
- <ProfileLink
- language={profile.language}
- name={profile.name}
- organization={this.props.organization}>
- {profile.name}
- </ProfileLink>
- {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />}
- </div>
- );
- }
-
- renderProjects() {
- const { profile } = this.props;
-
- if (profile.isDefault) {
- return (
- <span className="badge">
- {translate('default')}
- </span>
- );
- }
-
- return (
- <span>
- {profile.projectCount}
- </span>
- );
- }
-
- renderRules() {
- const { profile } = this.props;
-
- const activeRulesUrl = getRulesUrl(
- {
- qprofile: profile.key,
- activation: 'true'
- },
- this.props.organization
- );
-
- const deprecatedRulesUrl = getRulesUrl(
- {
- qprofile: profile.key,
- activation: 'true',
- statuses: 'DEPRECATED'
- },
- this.props.organization
- );
-
- return (
- <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>
- </span>}
-
- <Link to={activeRulesUrl}>
- {profile.activeRuleCount}
- </Link>
- </div>
- );
- }
-
- renderUpdateDate() {
- const date = <ProfileDate date={this.props.profile.userUpdatedAt} />;
- if (isStagnant(this.props.profile)) {
- return (
- <span className="badge badge-normal-size badge-focus">
- {date}
- </span>
- );
- } else {
- return date;
- }
- }
-
- renderUsageDate() {
- const { lastUsed } = this.props.profile;
- const date = <ProfileDate date={lastUsed} />;
- if (!lastUsed) {
- return (
- <span className="badge badge-normal-size badge-focus">
- {date}
- </span>
- );
- } else {
- return date;
- }
- }
-
- render() {
- return (
- <tr
- className="quality-profiles-table-row"
- data-key={this.props.profile.key}
- data-name={this.props.profile.name}>
- <td className="quality-profiles-table-name">
- {this.renderName()}
- </td>
- <td className="quality-profiles-table-projects thin nowrap text-right">
- {this.renderProjects()}
- </td>
- <td className="quality-profiles-table-rules thin nowrap text-right">
- {this.renderRules()}
- </td>
- <td className="quality-profiles-table-date thin nowrap text-right">
- {this.renderUpdateDate()}
- </td>
- <td className="quality-profiles-table-date thin nowrap text-right">
- {this.renderUsageDate()}
- </td>
- {this.props.canAdmin &&
- <td className="quality-profiles-table-actions thin nowrap text-right">
- <div className="dropdown">
- <button className="dropdown-toggle" data-toggle="dropdown">
- <i className="icon-dropdown" />
- </button>
- <ProfileActions
- canAdmin={this.props.canAdmin}
- fromList={true}
- onRequestFail={this.props.onRequestFail}
- organization={this.props.organization}
- profile={this.props.profile}
- updateProfiles={this.props.updateProfiles}
- />
- </div>
- </td>}
- </tr>
- );
- }
-}
--- /dev/null
+/*
+ * 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 ProfileLink from '../components/ProfileLink';
+import ProfileDate from '../components/ProfileDate';
+import ProfileActions from '../components/ProfileActions';
+import BuiltInBadge from '../components/BuiltInBadge';
+import { translate } from '../../../helpers/l10n';
+import { getRulesUrl } from '../../../helpers/urls';
+import { isStagnant } from '../utils';
+import { IProfile } from '../types';
+import Tooltip from '../../../components/controls/Tooltip';
+
+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);
+ return (
+ <div style={{ paddingLeft: offset }}>
+ <ProfileLink
+ language={profile.language}
+ name={profile.name}
+ organization={this.props.organization}>
+ {profile.name}
+ </ProfileLink>
+ {profile.isBuiltIn && <BuiltInBadge className="spacer-left" />}
+ </div>
+ );
+ }
+
+ renderProjects() {
+ const { profile } = this.props;
+
+ if (profile.isDefault) {
+ return (
+ <span className="badge">
+ {translate('default')}
+ </span>
+ );
+ }
+
+ return (
+ <span>
+ {profile.projectCount}
+ </span>
+ );
+ }
+
+ renderRules() {
+ const { profile } = this.props;
+
+ const activeRulesUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'true'
+ },
+ this.props.organization
+ );
+
+ const deprecatedRulesUrl = getRulesUrl(
+ {
+ qprofile: profile.key,
+ activation: 'true',
+ statuses: 'DEPRECATED'
+ },
+ this.props.organization
+ );
+
+ return (
+ <div>
+ {profile.activeDeprecatedRuleCount > 0 &&
+ <span className="spacer-right">
+ <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}>
+ {profile.activeRuleCount}
+ </Link>
+ </div>
+ );
+ }
+
+ renderUpdateDate() {
+ const date = <ProfileDate date={this.props.profile.userUpdatedAt} />;
+ if (isStagnant(this.props.profile)) {
+ return (
+ <span className="badge badge-normal-size badge-focus">
+ {date}
+ </span>
+ );
+ } else {
+ return date;
+ }
+ }
+
+ renderUsageDate() {
+ const { lastUsed } = this.props.profile;
+ const date = <ProfileDate date={lastUsed} />;
+ if (!lastUsed) {
+ return (
+ <span className="badge badge-normal-size badge-focus">
+ {date}
+ </span>
+ );
+ } else {
+ return date;
+ }
+ }
+
+ render() {
+ return (
+ <tr
+ className="quality-profiles-table-row"
+ data-key={this.props.profile.key}
+ data-name={this.props.profile.name}>
+ <td className="quality-profiles-table-name">
+ {this.renderName()}
+ </td>
+ <td className="quality-profiles-table-projects thin nowrap text-right">
+ {this.renderProjects()}
+ </td>
+ <td className="quality-profiles-table-rules thin nowrap text-right">
+ {this.renderRules()}
+ </td>
+ <td className="quality-profiles-table-date thin nowrap text-right">
+ {this.renderUpdateDate()}
+ </td>
+ <td className="quality-profiles-table-date thin nowrap text-right">
+ {this.renderUsageDate()}
+ </td>
+ {this.props.canAdmin &&
+ <td className="quality-profiles-table-actions thin nowrap text-right">
+ <div className="dropdown">
+ <button className="dropdown-toggle" data-toggle="dropdown">
+ <i className="icon-dropdown" />
+ </button>
+ <ProfileActions
+ canAdmin={this.props.canAdmin}
+ fromList={true}
+ onRequestFail={this.props.onRequestFail}
+ organization={this.props.organization}
+ profile={this.props.profile}
+ updateProfiles={this.props.updateProfiles}
+ />
+ </div>
+ </td>}
+ </tr>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 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
-};
-*/
-
-/*::
-type 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 };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleCancelClick = (event /*: Event */) => {
- event.preventDefault();
- this.props.onClose();
- };
-
- handleFormSubmit = (event /*: Event */) => {
- event.preventDefault();
-
- this.setState({ loading: true });
-
- const data = new FormData(this.form);
- if (this.props.organization) {
- data.append('organization', this.props.organization);
- }
-
- restoreQualityProfile(data).then(
- response => {
- if (this.mounted) {
- this.setState({
- loading: false,
- profile: response.profile,
- ruleFailures: response.ruleFailures,
- ruleSuccesses: response.ruleSuccesses
- });
- }
- this.props.onRestore();
- },
- error => {
- if (this.mounted) {
- this.setState({ loading: false });
- }
- this.props.onRequestFail(error);
- }
- );
- };
-
- render() {
- const header = translate('quality_profiles.restore_profile');
-
- const { loading, profile, ruleFailures, ruleSuccesses } = this.state;
-
- return (
- <Modal
- isOpen={true}
- contentLabel={header}
- className="modal"
- overlayClassName="modal-overlay"
- onRequestClose={this.props.onClose}>
- <form
- id="restore-profile-form"
- onSubmit={this.handleFormSubmit}
- ref={node => (this.form = node)}>
- <div className="modal-head">
- <h2>
- {header}
- </h2>
- </div>
-
- <div className="modal-body">
- {profile != null && ruleSuccesses != null
- ? ruleFailures
- ? <div className="alert alert-warning">
- {translateWithParameters(
- 'quality_profiles.restore_profile.warning',
- profile.name,
- ruleSuccesses,
- ruleFailures
- )}
- </div>
- : <div className="alert alert-success">
- {translateWithParameters(
- 'quality_profiles.restore_profile.success',
- profile.name,
- ruleSuccesses
- )}
- </div>
- : <div className="modal-field">
- <label htmlFor="restore-profile-backup">
- {translate('backup')}
- <em className="mandatory">*</em>
- </label>
- <input id="restore-profile-backup" name="backup" required={true} type="file" />
- </div>}
- </div>
-
- {ruleSuccesses == null
- ? <div className="modal-foot">
- {loading && <i className="spinner spacer-right" />}
- <button disabled={loading} id="restore-profile-submit">
- {translate('restore')}
- </button>
- <a href="#" id="restore-profile-cancel" onClick={this.handleCancelClick}>
- {translate('cancel')}
- </a>
- </div>
- : <div className="modal-foot">
- <a href="#" onClick={this.handleCancelClick}>
- {translate('close')}
- </a>
- </div>}
- </form>
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from 'react-modal';
+import { restoreQualityProfile } from '../../../api/quality-profiles';
+import { translate, translateWithParameters } from '../../../helpers/l10n';
+
+interface Props {
+ onClose: () => void;
+ onRequestFail: (reason: any) => void;
+ onRestore: () => void;
+ organization: string | null;
+}
+
+interface State {
+ loading: boolean;
+ profile?: { name: string };
+ ruleFailures?: number;
+ ruleSuccesses?: number;
+}
+
+export default class RestoreProfileForm extends React.PureComponent<Props, State> {
+ mounted: boolean;
+ state: State = { loading: false };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ handleCancelClick = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ this.props.onClose();
+ };
+
+ handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
+ event.preventDefault();
+
+ this.setState({ loading: true });
+
+ const data = new FormData(event.currentTarget);
+ if (this.props.organization) {
+ data.append('organization', this.props.organization);
+ }
+
+ restoreQualityProfile(data).then(
+ (response: any) => {
+ if (this.mounted) {
+ this.setState({
+ loading: false,
+ profile: response.profile,
+ ruleFailures: response.ruleFailures,
+ ruleSuccesses: response.ruleSuccesses
+ });
+ }
+ this.props.onRestore();
+ },
+ (error: any) => {
+ if (this.mounted) {
+ this.setState({ loading: false });
+ }
+ this.props.onRequestFail(error);
+ }
+ );
+ };
+
+ render() {
+ const header = translate('quality_profiles.restore_profile');
+
+ const { loading, profile, ruleFailures, ruleSuccesses } = this.state;
+
+ return (
+ <Modal
+ isOpen={true}
+ contentLabel={header}
+ className="modal"
+ overlayClassName="modal-overlay"
+ onRequestClose={this.props.onClose}>
+ <form id="restore-profile-form" onSubmit={this.handleFormSubmit}>
+ <div className="modal-head">
+ <h2>
+ {header}
+ </h2>
+ </div>
+
+ <div className="modal-body">
+ {profile != null && ruleSuccesses != null
+ ? ruleFailures
+ ? <div className="alert alert-warning">
+ {translateWithParameters(
+ 'quality_profiles.restore_profile.warning',
+ profile.name,
+ ruleSuccesses,
+ ruleFailures
+ )}
+ </div>
+ : <div className="alert alert-success">
+ {translateWithParameters(
+ 'quality_profiles.restore_profile.success',
+ profile.name,
+ ruleSuccesses
+ )}
+ </div>
+ : <div className="modal-field">
+ <label htmlFor="restore-profile-backup">
+ {translate('backup')}
+ <em className="mandatory">*</em>
+ </label>
+ <input id="restore-profile-backup" name="backup" required={true} type="file" />
+ </div>}
+ </div>
+
+ {ruleSuccesses == null
+ ? <div className="modal-foot">
+ {loading && <i className="spinner spacer-right" />}
+ <button disabled={loading} id="restore-profile-submit">
+ {translate('restore')}
+ </button>
+ <a href="#" id="restore-profile-cancel" onClick={this.handleCancelClick}>
+ {translate('cancel')}
+ </a>
+ </div>
+ : <div className="modal-foot">
+ <a href="#" onClick={this.handleCancelClick}>
+ {translate('close')}
+ </a>
+ </div>}
+ </form>
+ </Modal>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { shape, string, number, bool, arrayOf } from 'prop-types';
-
-/*::
-export type Profile = {
- key: string,
- name: string,
- isBuiltIn: boolean,
- isDefault: boolean,
- isInherited: boolean,
- language: string,
- languageName: string,
- activeRuleCount: number,
- activeDeprecatedRuleCount: number,
- projectCount?: number,
- parentKey?: string,
- parentName?: string,
- userUpdatedAt?: string,
- lastUsed?: string,
- rulesUpdatedAt: string,
- depth: number,
- childrenCount: number
-};
-*/
-
-/*::
-export type Exporter = {
- key: string,
- name: string,
- languages: Array<string>
-};
-*/
-
-export const ProfileType = shape({
- key: string.isRequired,
- name: string.isRequired,
- isDefault: bool.isRequired,
- isInherited: bool.isRequired,
- language: string.isRequired,
- languageName: string.isRequired,
- activeRuleCount: number.isRequired,
- activeDeprecatedRuleCount: number.isRequired,
- projectCount: number,
- parentKey: string,
- parentName: string,
- userUpdatedAt: string,
- lastUsed: string
-});
-
-export const ProfilesListType = arrayOf(ProfileType);
-
-const LanguageType = shape({
- key: string.isRequired,
- name: string.isRequired
-});
-
-export const LanguagesListType = arrayOf(LanguageType);
+++ /dev/null
-/*
- * 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 { withRouter } from 'react-router';
-
-const routes = [
- {
- getComponent(state, callback) {
- import('./components/AppContainer').then(i => i.default).then(AppContainer => {
- if (state.params.organizationKey) {
- callback(null, AppContainer);
- } else {
- import('../organizations/forSingleOrganization')
- .then(i => i.default)
- .then(forSingleOrganization => callback(null, forSingleOrganization(AppContainer)));
- }
- });
- },
- getIndexRoute(_, callback) {
- import('./home/HomeContainer').then(i => callback(null, { component: i.default }));
- },
- childRoutes: [
- {
- getComponent(_, callback) {
- import('./components/ProfileContainer').then(i => callback(null, withRouter(i.default)));
- },
- childRoutes: [
- {
- path: 'show',
- getComponent(_, callback) {
- import('./details/ProfileDetails').then(i => callback(null, i.default));
- }
- },
- {
- path: 'changelog',
- getComponent(_, callback) {
- import('./changelog/ChangelogContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'compare',
- getComponent(_, callback) {
- import('./compare/ComparisonContainer').then(i => callback(null, i.default));
- }
- }
- ]
- }
- ]
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { withRouter, RouterState, IndexRouteProps, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ getComponent(state: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/AppContainer').then(i => i.default).then(AppContainer => {
+ if (state.params.organizationKey) {
+ callback(null, AppContainer);
+ } else {
+ import('../organizations/forSingleOrganization')
+ .then(i => i.default)
+ .then(forSingleOrganization => callback(null, forSingleOrganization(AppContainer)));
+ }
+ });
+ },
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./home/HomeContainer').then(i => callback(null, { component: i.default }));
+ },
+ childRoutes: [
+ {
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/ProfileContainer').then(i => callback(null, withRouter(i.default)));
+ },
+ childRoutes: [
+ {
+ path: 'show',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./details/ProfileDetails').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'changelog',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./changelog/ChangelogContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'compare',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./compare/ComparisonContainer').then(i => callback(null, i.default));
+ }
+ }
+ ]
+ }
+ ]
+ }
+];
+
+export default routes;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+export interface IProfile {
+ key: string;
+ name: string;
+ isBuiltIn: boolean;
+ isDefault: boolean;
+ isInherited: boolean;
+ language: string;
+ languageName: string;
+ activeRuleCount: number;
+ activeDeprecatedRuleCount: number;
+ projectCount?: number;
+ parentKey?: string;
+ parentName?: string;
+ userUpdatedAt?: string;
+ lastUsed?: string;
+ rulesUpdatedAt: string;
+ depth: number;
+ childrenCount: number;
+}
+
+export interface IExporter {
+ key: string;
+ name: string;
+ languages: string[];
+}
+
+export interface IProfileChangelogEvent {
+ action: string;
+ authorName: string;
+ date: string;
+ params?: { [change: string]: string | null };
+ ruleKey: string;
+ ruleName: string;
+}
+++ /dev/null
-/*
- * 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 { sortBy } from 'lodash';
-import moment from 'moment';
-/*:: import type { Profile } from './propTypes'; */
-
-export function sortProfiles(profiles /*: Array<Profile> */) {
- const result = [];
- const sorted = sortBy(profiles, 'name');
-
- function retrieveChildren(parent) {
- return sorted.filter(
- p => (parent == null && p.parentKey == null) || (parent != null && p.parentKey === parent.key)
- );
- }
-
- function putProfile(profile = null, depth = 1) {
- const children = retrieveChildren(profile);
-
- if (profile != null) {
- result.push({ ...profile, childrenCount: children.length, depth });
- }
-
- children.forEach(child => putProfile(child, depth + 1));
- }
-
- sorted
- .filter(
- profile => profile.parentKey == null || sorted.find(p => p.key === profile.parentKey) == null
- )
- .forEach(profile => putProfile(profile));
-
- return result;
-}
-
-export function createFakeProfile(overrides /*: {} */) {
- return {
- key: 'key',
- name: 'name',
- isDefault: false,
- isInherited: false,
- language: 'js',
- languageName: 'JavaScript',
- activeRuleCount: 10,
- activeDeprecatedRuleCount: 2,
- projectCount: 3,
- ...overrides
- };
-}
-
-export function isStagnant(profile /*: Profile */) {
- return moment().diff(moment(profile.userUpdatedAt), 'years') >= 1;
-}
-
-export const getProfilesPath = (organization /*: ?string */) =>
- organization ? `/organizations/${organization}/quality_profiles` : '/profiles';
-
-export const getProfilesForLanguagePath = (
- language /*: string */,
- organization /*: ?string */
-) => ({
- pathname: getProfilesPath(organization),
- query: { language }
-});
-
-export const getProfilePath = (
- name /*: string */,
- language /*: string */,
- organization /*: ?string */
-) => ({
- pathname: getProfilesPath(organization) + '/show',
- query: { name, language }
-});
-
-export const getProfileComparePath = (
- name /*: string */,
- language /*: string */,
- organization /*: ?string */,
- withKey /*: ?string */
-) => {
- const query /*: Object */ = { language, name };
- if (withKey) {
- Object.assign(query, { withKey });
- }
- return {
- pathname: getProfilesPath(organization) + '/compare',
- query
- };
-};
-
-export const getProfileChangelogPath = (
- name /*: string */,
- language /*: string */,
- organization /*: ?string */,
- filter /*: ?{ since?: string, to?: string } */
-) => {
- const query /*: Object */ = { language, name };
- if (filter) {
- if (filter.since) {
- Object.assign(query, { since: filter.since });
- }
- if (filter.to) {
- Object.assign(query, { to: filter.to });
- }
- }
- return {
- pathname: getProfilesPath(organization) + '/changelog',
- query
- };
-};
--- /dev/null
+/*
+ * 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 { sortBy } from 'lodash';
+import * as moment from 'moment';
+import { IProfile } from './types';
+
+export function sortProfiles(profiles: IProfile[]) {
+ const result: IProfile[] = [];
+ const sorted = sortBy(profiles, 'name');
+
+ function retrieveChildren(parent: IProfile | null) {
+ return sorted.filter(
+ p => (parent == null && p.parentKey == null) || (parent != null && p.parentKey === parent.key)
+ );
+ }
+
+ function putProfile(profile: IProfile | null = null, depth: number = 1) {
+ const children = retrieveChildren(profile);
+
+ if (profile != null) {
+ result.push({ ...profile, childrenCount: children.length, depth });
+ }
+
+ children.forEach(child => putProfile(child, depth + 1));
+ }
+
+ sorted
+ .filter(
+ profile => profile.parentKey == null || sorted.find(p => p.key === profile.parentKey) == null
+ )
+ .forEach(profile => putProfile(profile));
+
+ return result;
+}
+
+export function createFakeProfile(overrides?: any) {
+ return {
+ key: 'key',
+ name: 'name',
+ isDefault: false,
+ isInherited: false,
+ language: 'js',
+ languageName: 'JavaScript',
+ activeRuleCount: 10,
+ activeDeprecatedRuleCount: 2,
+ projectCount: 3,
+ ...overrides
+ };
+}
+
+export function isStagnant(profile: IProfile) {
+ return moment().diff(moment(profile.userUpdatedAt), 'years') >= 1;
+}
+
+export const getProfilesPath = (organization: string | null) =>
+ organization ? `/organizations/${organization}/quality_profiles` : '/profiles';
+
+export const getProfilesForLanguagePath = (language: string, organization: string | null) => ({
+ pathname: getProfilesPath(organization),
+ query: { language }
+});
+
+export const getProfilePath = (name: string, language: string, organization: string | null) => ({
+ pathname: getProfilesPath(organization) + '/show',
+ query: { name, language }
+});
+
+export const getProfileComparePath = (
+ name: string,
+ language: string,
+ organization: string | null,
+ withKey?: string
+) => {
+ const query = { language, name };
+ if (withKey) {
+ Object.assign(query, { withKey });
+ }
+ return {
+ pathname: getProfilesPath(organization) + '/compare',
+ query
+ };
+};
+
+export const getProfileChangelogPath = (
+ name: string,
+ language: string,
+ organization: string | null,
+ filter?: { since?: string; to?: string }
+) => {
+ const query = { language, name };
+ if (filter) {
+ if (filter.since) {
+ Object.assign(query, { since: filter.since });
+ }
+ if (filter.to) {
+ Object.assign(query, { to: filter.to });
+ }
+ }
+ return {
+ pathname: getProfilesPath(organization) + '/changelog',
+ query
+ };
+};
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-
-export default class Unauthorized extends React.PureComponent {
- static propTypes = {
- location: PropTypes.object.isRequired
- };
-
- render() {
- const { message } = this.props.location.query;
-
- return (
- <div className="text-center">
- <p id="unauthorized">
- {"You're not authorized to access this page. Please contact the administrator."}
- </p>
-
- {!!message &&
- <p className="spacer-top">
- Reason : {message}
- </p>}
-
- <div className="big-spacer-top">
- <a href={window.baseUrl + '/'}>Home</a>
- </div>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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';
+
+interface Props {
+ location: {
+ query: {
+ message: string;
+ };
+ };
+}
+
+export default function Unauthorized(props: Props) {
+ const { message } = props.location.query;
+
+ return (
+ <div className="text-center">
+ <p id="unauthorized">
+ {"You're not authorized to access this page. Please contact the administrator."}
+ </p>
+
+ {!!message &&
+ <p className="spacer-top">
+ Reason : {message}
+ </p>}
+
+ <div className="big-spacer-top">
+ <Link to="/">Home</Link>
+ </div>
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- path: 'new',
- getComponent(_, callback) {
- import('./components/LoginFormContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'logout',
- getComponent(_, callback) {
- import('./components/Logout').then(i => callback(null, i.default));
- }
- },
- {
- path: 'unauthorized',
- getComponent(_, callback) {
- import('./components/Unauthorized').then(i => callback(null, i.default));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent } from 'react-router';
+
+const routes = [
+ {
+ path: 'new',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/LoginFormContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'logout',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/Logout').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'unauthorized',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/Unauthorized').then(i => callback(null, i.default));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/AppContainer').then(i => callback(null, { component: i.default }));
- }
- },
- {
- path: 'licenses',
- getComponent(_, callback) {
- import('./licenses/LicensesApp').then(i => callback(null, i.default));
- }
- },
- {
- path: 'encryption',
- getComponent(_, callback) {
- import('./encryption/EncryptionAppContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'server_id',
- getComponent(_, callback) {
- import('./serverId/ServerIdAppContainer').then(i => callback(null, i.default));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/AppContainer').then(i => callback(null, { component: i.default }));
+ }
+ },
+ {
+ path: 'licenses',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./licenses/LicensesApp').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'encryption',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./encryption/EncryptionAppContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'server_id',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./serverId/ServerIdAppContainer').then(i => callback(null, i.default));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./main').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./main').then(i => callback(null, { component: (i as any).default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/UpdateCenterAppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- },
- {
- path: 'installed',
- getComponent(_, callback) {
- import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'updates',
- getComponent(_, callback) {
- import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'available',
- getComponent(_, callback) {
- import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'system',
- getComponent(_, callback) {
- import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/UpdateCenterAppContainer').then(i =>
+ callback(null, { component: i.default })
+ );
+ }
+ },
+ {
+ path: 'installed',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'updates',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'available',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
+ }
+ },
+ {
+ path: 'system',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/UpdateCenterAppContainer').then(i => callback(null, i.default));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/UsersAppContainer').then(i => callback(null, { component: i.default }));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/UsersAppContainer').then(i => callback(null, { component: i.default }));
+ }
+ }
+];
+
+export default routes;
+++ /dev/null
-/*
- * 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.
- */
-const routes = [
- {
- getIndexRoute(_, callback) {
- import('./components/WebApiApp').then(i => callback(null, { component: i.default }));
- }
- },
- {
- path: '**',
- getComponent(_, callback) {
- import('./components/WebApiApp').then(i => callback(null, i.default));
- }
- }
-];
-
-export default routes;
--- /dev/null
+/*
+ * 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 { RouterState, RouteComponent, IndexRouteProps } from 'react-router';
+
+const routes = [
+ {
+ getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
+ import('./components/WebApiApp').then(i => callback(null, { component: (i as any).default }));
+ }
+ },
+ {
+ path: '**',
+ getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
+ import('./components/WebApiApp').then(i => callback(null, (i as any).default));
+ }
+ }
+];
+
+export default routes;
remove(postpone) {
if (postpone) {
- const that = this;
- that.$el.addClass(this.model.get('selected') ? 'added' : 'removed');
- setTimeout(function() {
- Backbone.View.prototype.remove.call(that, arguments);
+ this.$el.addClass(this.model.get('selected') ? 'added' : 'removed');
+ setTimeout(() => {
+ Backbone.View.prototype.remove.call(this, arguments);
}, 500);
} else {
Backbone.View.prototype.remove.call(this, arguments);
+++ /dev/null
-/*
- * 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 $ from 'jquery';
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { pick } from 'lodash';
-import './styles.css';
-
-export default class DateInput extends React.PureComponent {
- static propTypes = {
- className: PropTypes.string,
- value: PropTypes.string,
- format: PropTypes.string,
- name: PropTypes.string,
- placeholder: PropTypes.string,
- onChange: PropTypes.func.isRequired
- };
-
- static defaultProps = {
- value: '',
- format: 'yy-mm-dd'
- };
-
- componentDidMount() {
- this.attachDatePicker();
- }
-
- componentWillReceiveProps(nextProps) {
- this.refs.input.value = nextProps.value;
- }
-
- handleChange() {
- const { value } = this.refs.input;
- this.props.onChange(value);
- }
-
- attachDatePicker() {
- const opts = {
- dateFormat: this.props.format,
- changeMonth: true,
- changeYear: true,
- onSelect: this.handleChange.bind(this)
- };
-
- if ($.fn && $.fn.datepicker) {
- $(this.refs.input).datepicker(opts);
- }
- }
-
- render() {
- const inputProps = pick(this.props, ['placeholder', 'name']);
-
- /* eslint max-len: 0 */
- return (
- <span className={classNames('date-input-control', this.props.className)}>
- <input
- className="date-input-control-input"
- ref="input"
- type="text"
- defaultValue={this.props.value}
- readOnly={true}
- {...inputProps}
- />
- <span className="date-input-control-icon">
- <svg width="14" height="14" viewBox="0 0 16 16">
- <path d="M5.5 6h2v2h-2V6zm3 0h2v2h-2V6zm3 0h2v2h-2V6zm-9 6h2v2h-2v-2zm3 0h2v2h-2v-2zm3 0h2v2h-2v-2zm-3-3h2v2h-2V9zm3 0h2v2h-2V9zm3 0h2v2h-2V9zm-9 0h2v2h-2V9zm11-9v1h-2V0h-7v1h-2V0h-2v16h15V0h-2zm1 15h-13V4h13v11z" />
- </svg>
- </span>
- </span>
- );
- }
-}
--- /dev/null
+/*
+ * 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 $ from 'jquery';
+import * as React from 'react';
+import * as classNames from 'classnames';
+import { pick } from 'lodash';
+import './styles.css';
+
+interface Props {
+ className?: string;
+ value?: string;
+ format?: string;
+ name: string;
+ placeholder: string;
+ onChange: (value: string) => void;
+}
+
+export default class DateInput extends React.PureComponent<Props> {
+ input: HTMLInputElement;
+
+ static defaultProps = {
+ value: '',
+ format: 'yy-mm-dd'
+ };
+
+ componentDidMount() {
+ this.attachDatePicker();
+ }
+
+ componentWillReceiveProps(nextProps: Props) {
+ if (nextProps.value != null) {
+ this.input.value = nextProps.value;
+ }
+ }
+
+ handleChange() {
+ const { value } = this.input;
+ this.props.onChange(value);
+ }
+
+ attachDatePicker() {
+ const opts = {
+ dateFormat: this.props.format,
+ changeMonth: true,
+ changeYear: true,
+ onSelect: this.handleChange.bind(this)
+ };
+
+ if ($.fn && ($.fn as any).datepicker) {
+ ($(this.refs.input) as any).datepicker(opts);
+ }
+ }
+
+ render() {
+ const inputProps = pick(this.props, ['placeholder', 'name']);
+
+ return (
+ <span className={classNames('date-input-control', this.props.className)}>
+ <input
+ className="date-input-control-input"
+ ref={node => (this.input = node as HTMLInputElement)}
+ type="text"
+ defaultValue={this.props.value}
+ readOnly={true}
+ {...inputProps}
+ />
+ <span className="date-input-control-icon">
+ <svg width="14" height="14" viewBox="0 0 16 16">
+ <path d="M5.5 6h2v2h-2V6zm3 0h2v2h-2V6zm3 0h2v2h-2V6zm-9 6h2v2h-2v-2zm3 0h2v2h-2v-2zm3 0h2v2h-2v-2zm-3-3h2v2h-2V9zm3 0h2v2h-2V9zm3 0h2v2h-2V9zm-9 0h2v2h-2V9zm11-9v1h-2V0h-7v1h-2V0h-2v16h15V0h-2zm1 15h-13V4h13v11z" />
+ </svg>
+ </span>
+ </span>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import React from 'react';
-import PropTypes from 'prop-types';
-import { translate, translateWithParameters } from '../../helpers/l10n';
-import { formatMeasure } from '../../helpers/measures';
-
-export default class ListFooter extends React.PureComponent {
- static propTypes = {
- count: PropTypes.number.isRequired,
- total: PropTypes.number.isRequired,
- loadMore: PropTypes.func,
- ready: PropTypes.bool
- };
-
- static defaultProps = {
- ready: true
- };
-
- canLoadMore() {
- return typeof this.props.loadMore === 'function';
- }
-
- handleLoadMore = event => {
- event.preventDefault();
- event.target.blur();
- this.props.loadMore();
- };
-
- render() {
- const hasMore = this.props.total > this.props.count;
- const loadMoreLink = (
- <a className="spacer-left" href="#" onClick={this.handleLoadMore}>
- {translate('show_more')}
- </a>
- );
- const className = classNames('spacer-top note text-center', {
- 'new-loading': !this.props.ready
- });
-
- return (
- <footer className={className}>
- {translateWithParameters(
- 'x_of_y_shown',
- formatMeasure(this.props.count, 'INT'),
- formatMeasure(this.props.total, 'INT')
- )}
- {this.canLoadMore() && hasMore ? loadMoreLink : null}
- </footer>
- );
- }
-}
--- /dev/null
+/*
+ * 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 classNames from 'classnames';
+import { translate, translateWithParameters } from '../../helpers/l10n';
+import { formatMeasure } from '../../helpers/measures';
+
+interface Props {
+ count: number;
+ loadMore?: () => void;
+ ready?: boolean;
+ total: number;
+}
+
+export default function ListFooter({ ready = true, ...props }: Props) {
+ const handleLoadMore = (event: React.SyntheticEvent<HTMLElement>) => {
+ event.preventDefault();
+ event.currentTarget.blur();
+ if (props.loadMore) {
+ props.loadMore();
+ }
+ };
+
+ const hasMore = props.total > props.count;
+ const loadMoreLink = (
+ <a className="spacer-left" href="#" onClick={handleLoadMore}>
+ {translate('show_more')}
+ </a>
+ );
+ const className = classNames('spacer-top note text-center', {
+ 'new-loading': !ready
+ });
+
+ return (
+ <footer className={className}>
+ {translateWithParameters(
+ 'x_of_y_shown',
+ formatMeasure(props.count, 'INT', null),
+ formatMeasure(props.total, 'INT', null)
+ )}
+ {props.loadMore != null && hasMore ? loadMoreLink : null}
+ </footer>
+ );
+}
+++ /dev/null
-/*
- * 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 TooltipCore from 'rc-tooltip';
-
-export default class Tooltip extends React.PureComponent {
- /*:: props: {
- placement?: string
- };
-*/
-
- static defaultProps = {
- placement: 'bottom'
- };
-
- render() {
- return (
- <TooltipCore destroyTooltipOnHide={true} placement={this.props.placement} {...this.props} />
- );
- }
-}
--- /dev/null
+/*
+ * 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 TooltipCore from 'rc-tooltip';
+
+interface Props {
+ overlay: React.ReactNode;
+ placement?: string;
+ [attr: string]: any;
+}
+
+export default function Tooltip(props: Props) {
+ return <TooltipCore destroyTooltipOnHide={true} placement={props.placement} {...props} />;
+}
+
+(Tooltip as React.StatelessComponent).defaultProps = {
+ placement: 'bottom'
+};
+++ /dev/null
-/*
- * 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';
-
-/*::
-type Props = { className?: string, size?: number };
-*/
-
-export default function BugIcon({ className, size = 16 } /*: Props */) {
- /* eslint-disable max-len */
- return (
- <svg
- className={className}
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 16 16"
- width={size}
- height={size}>
- <path
- style={{ fill: 'currentColor' }}
- d="M11 9h1.3l.5.8.8-.5-.8-1.3H11v-.3l2-2.3V3h-1v2l-1 1.2V5c-.1-.8-.7-1.5-1.4-1.9L11 1.8l-.7-.7-1.8 1.6-1.8-1.6-.7.7 1.5 1.3C6.7 3.5 6.1 4.2 6 5v1.1L5 5V3H4v2.3l2 2.3V8H4.2l-.7 1.2.8.5.4-.7H6v.3l-2 1.9V14h1v-2.4l1-1C6 12 7.1 13 8.4 13h.8c.7 0 1.4-.3 1.8-.9.3-.4.3-.9.2-1.4l.9.9V14h1v-2.8l-2-1.9V9zm-2 2H8V6h1v5z"
- />
- </svg>
- );
-}
--- /dev/null
+/*
+ * 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';
+
+interface Props {
+ className?: string;
+ size?: number;
+}
+
+export default function BugIcon({ className, size = 16 }: Props) {
+ /* eslint-disable max-len */
+ return (
+ <svg
+ className={className}
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 16 16"
+ width={size}
+ height={size}>
+ <path
+ style={{ fill: 'currentColor' }}
+ d="M11 9h1.3l.5.8.8-.5-.8-1.3H11v-.3l2-2.3V3h-1v2l-1 1.2V5c-.1-.8-.7-1.5-1.4-1.9L11 1.8l-.7-.7-1.8 1.6-1.8-1.6-.7.7 1.5 1.3C6.7 3.5 6.1 4.2 6 5v1.1L5 5V3H4v2.3l2 2.3V8H4.2l-.7 1.2.8.5.4-.7H6v.3l-2 1.9V14h1v-2.4l1-1C6 12 7.1 13 8.4 13h.8c.7 0 1.4-.3 1.8-.9.3-.4.3-.9.2-1.4l.9.9V14h1v-2.8l-2-1.9V9zm-2 2H8V6h1v5z"
+ />
+ </svg>
+ );
+}
+++ /dev/null
-/*
- * 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';
-
-/*::
-type Props = { className?: string, size?: number };
-*/
-
-export default function CodeSmellIcon({ className, size = 16 } /*: Props */) {
- /* eslint-disable max-len */
- return (
- <svg
- className={className}
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 16 16"
- width={size}
- height={size}>
- <path
- style={{ fill: 'currentColor' }}
- d="M8 2C4.7 2 2 4.7 2 8s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zm-.5 5.5h.9v.9h-.9v-.9zm-3.8.2c-.1 0-.2-.1-.2-.2 0-.4.1-1.2.6-2S5.3 4.2 5.6 4c.2 0 .3 0 .3.1l1.3 2.3c0 .1 0 .2-.1.2-.1.2-.2.3-.3.5-.1.2-.2.4-.2.5 0 .1-.1.2-.2.2l-2.7-.1zM9.9 12c-.3.2-1.1.5-2 .5-.9 0-1.7-.3-2-.5-.1 0-.1-.2-.1-.3l1.3-2.3c0-.1.1-.1.2-.1.2.1.3.1.5.1s.4 0 .5-.1c.1 0 .2 0 .2.1l1.3 2.3c.2.2.2.3.1.3zm2.5-4.1L9.7 8c-.1 0-.2-.1-.2-.2 0-.2-.1-.4-.2-.5 0-.1-.2-.3-.3-.4-.1 0-.1-.1-.1-.2l1.3-2.3c.1-.1.2-.1.3-.1.3.2 1 .7 1.5 1.5s.6 1.6.6 2c0 0-.1.1-.2.1z"
- />
- </svg>
- );
-}
--- /dev/null
+/*
+ * 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';
+
+interface Props {
+ className?: string;
+ size?: number;
+}
+
+export default function CodeSmellIcon({ className, size = 16 }: Props) {
+ /* eslint-disable max-len */
+ return (
+ <svg
+ className={className}
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 16 16"
+ width={size}
+ height={size}>
+ <path
+ style={{ fill: 'currentColor' }}
+ d="M8 2C4.7 2 2 4.7 2 8s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zm-.5 5.5h.9v.9h-.9v-.9zm-3.8.2c-.1 0-.2-.1-.2-.2 0-.4.1-1.2.6-2S5.3 4.2 5.6 4c.2 0 .3 0 .3.1l1.3 2.3c0 .1 0 .2-.1.2-.1.2-.2.3-.3.5-.1.2-.2.4-.2.5 0 .1-.1.2-.2.2l-2.7-.1zM9.9 12c-.3.2-1.1.5-2 .5-.9 0-1.7-.3-2-.5-.1 0-.1-.2-.1-.3l1.3-2.3c0-.1.1-.1.2-.1.2.1.3.1.5.1s.4 0 .5-.1c.1 0 .2 0 .2.1l1.3 2.3c.2.2.2.3.1.3zm2.5-4.1L9.7 8c-.1 0-.2-.1-.2-.2 0-.2-.1-.4-.2-.5 0-.1-.2-.3-.3-.4-.1 0-.1-.1-.1-.2l1.3-2.3c.1-.1.2-.1.3-.1.3.2 1 .7 1.5 1.5s.6 1.6.6 2c0 0-.1.1-.2.1z"
+ />
+ </svg>
+ );
+}
+++ /dev/null
-/*
- * 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';
-
-/*::
-type Props = { className?: string, size?: number };
-*/
-
-export default function VulnerabilityIcon({ className, size = 16 } /*: Props */) {
- /* eslint-disable max-len */
- return (
- <svg
- className={className}
- xmlns="http://www.w3.org/2000/svg"
- viewBox="0 0 16 16"
- width={size}
- height={size}>
- <path
- style={{ fill: 'currentColor' }}
- d="M10.8 5H6V3.9a2.28 2.28 0 0 1 2-2.5 2.22 2.22 0 0 1 1.8 1.2.48.48 0 0 0 .7.2.48.48 0 0 0 .2-.7A3 3 0 0 0 8 .4a3.34 3.34 0 0 0-3 3.5v1.2a2.16 2.16 0 0 0-2 2.1v4.4a2.22 2.22 0 0 0 2.2 2.2h5.6a2.22 2.22 0 0 0 2.2-2.2V7.2A2.22 2.22 0 0 0 10.8 5zm-2.2 5.5v1.2H7.4v-1.2a1.66 1.66 0 0 1-1.1-1.6A1.75 1.75 0 0 1 8 7.2a1.71 1.71 0 0 1 .6 3.3z"
- />
- </svg>
- );
-}
--- /dev/null
+/*
+ * 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';
+
+interface Props {
+ className?: string;
+ size?: number;
+}
+
+export default function VulnerabilityIcon({ className, size = 16 }: Props) {
+ /* eslint-disable max-len */
+ return (
+ <svg
+ className={className}
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 16 16"
+ width={size}
+ height={size}>
+ <path
+ style={{ fill: 'currentColor' }}
+ d="M10.8 5H6V3.9a2.28 2.28 0 0 1 2-2.5 2.22 2.22 0 0 1 1.8 1.2.48.48 0 0 0 .7.2.48.48 0 0 0 .2-.7A3 3 0 0 0 8 .4a3.34 3.34 0 0 0-3 3.5v1.2a2.16 2.16 0 0 0-2 2.1v4.4a2.22 2.22 0 0 0 2.2 2.2h5.6a2.22 2.22 0 0 0 2.2-2.2V7.2A2.22 2.22 0 0 0 10.8 5zm-2.2 5.5v1.2H7.4v-1.2a1.66 1.66 0 0 1-1.1-1.6A1.75 1.75 0 0 1 8 7.2a1.71 1.71 0 0 1 .6 3.3z"
+ />
+ </svg>
+ );
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import classNames from 'classnames';
-
-/*::
-type Props = {
- className?: string,
- qualifier: ?string
-};
-*/
-
-export default class QualifierIcon extends React.PureComponent {
- /*:: props: Props; */
-
- render() {
- if (!this.props.qualifier) {
- return null;
- }
-
- const className = classNames(
- 'icon-qualifier-' + this.props.qualifier.toLowerCase(),
- this.props.className
- );
-
- return <i className={className} />;
- }
-}
--- /dev/null
+/*
+ * 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 classNames from 'classnames';
+
+interface Props {
+ className?: string;
+ qualifier: string | null;
+}
+
+export default function QualifierIcon(props: Props) {
+ if (!props.qualifier) {
+ return null;
+ }
+
+ const className = classNames('icon-qualifier-' + props.qualifier.toLowerCase(), props.className);
+
+ return <i className={className} />;
+}
+++ /dev/null
-/*
- * 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 BugIcon from '../icons-components/BugIcon';
-import VulnerabilityIcon from '../icons-components/VulnerabilityIcon';
-import CodeSmellIcon from '../icons-components/CodeSmellIcon';
-
-export default class IssueTypeIcon extends React.PureComponent {
- /*:: props: {
- className?: string,
- query: string
- };
-*/
-
- renderIcon() {
- switch (this.props.query.toLowerCase()) {
- case 'bug':
- case 'bugs':
- case 'new_bugs':
- return <BugIcon />;
- case 'vulnerability':
- case 'vulnerabilities':
- case 'new_vulnerabilities':
- return <VulnerabilityIcon />;
- case 'code_smell':
- case 'code_smells':
- case 'new_code_smells':
- return <CodeSmellIcon />;
- default:
- return null;
- }
- }
-
- render() {
- const icon = this.renderIcon();
-
- if (!icon) {
- return null;
- }
-
- return this.props.className
- ? <span className={this.props.className}>
- {icon}
- </span>
- : icon;
- }
-}
--- /dev/null
+/*
+ * 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 BugIcon from '../icons-components/BugIcon';
+import VulnerabilityIcon from '../icons-components/VulnerabilityIcon';
+import CodeSmellIcon from '../icons-components/CodeSmellIcon';
+
+interface Props {
+ className?: string;
+ query: string;
+}
+
+export default function IssueTypeIcon(props: Props) {
+ let icon;
+
+ switch (props.query.toLowerCase()) {
+ case 'bug':
+ case 'bugs':
+ case 'new_bugs':
+ icon = <BugIcon />;
+ break;
+ case 'vulnerability':
+ case 'vulnerabilities':
+ case 'new_vulnerabilities':
+ icon = <VulnerabilityIcon />;
+ break;
+ case 'code_smell':
+ case 'code_smells':
+ case 'new_code_smells':
+ icon = <CodeSmellIcon />;
+ break;
+ }
+
+ if (!icon) {
+ return null;
+ }
+
+ return props.className
+ ? <span className={props.className}>
+ {icon}
+ </span>
+ : icon;
+}
+++ /dev/null
-/*
- * 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 React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { formatMeasure } from '../../helpers/measures';
-import './Level.css';
-
-export default class Level extends React.PureComponent {
- static propTypes = {
- className: PropTypes.string,
- level: PropTypes.oneOf(['ERROR', 'WARN', 'OK', 'NONE']).isRequired,
- small: PropTypes.bool,
- muted: PropTypes.bool
- };
-
- static defaultProps = {
- small: false,
- muted: false
- };
-
- render() {
- const formatted = formatMeasure(this.props.level, 'LEVEL');
- const className = classNames(this.props.className, 'level', 'level-' + this.props.level, {
- 'level-small': this.props.small,
- 'level-muted': this.props.muted
- });
- return (
- <span className={className}>
- {formatted}
- </span>
- );
- }
-}
--- /dev/null
+/*
+ * 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 classNames from 'classnames';
+import { formatMeasure } from '../../helpers/measures';
+import './Level.css';
+
+interface Props {
+ className?: string;
+ level: string;
+ small?: boolean;
+ muted?: boolean;
+}
+
+export default function Level(props: Props) {
+ const formatted = formatMeasure(props.level, 'LEVEL', null);
+ const className = classNames(props.className, 'level', 'level-' + props.level, {
+ 'level-small': props.small,
+ 'level-muted': props.muted
+ });
+ return (
+ <span className={className}>
+ {formatted}
+ </span>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+declare module 'rc-tooltip' {
+ export type Trigger = 'hover' | 'click' | 'focus';
+ export type Placement =
+ | 'left'
+ | 'right'
+ | 'top'
+ | 'bottom'
+ | 'topLeft'
+ | 'topRight'
+ | 'bottomLeft'
+ | 'bottomRight';
+
+ export interface Props extends React.Props<any> {
+ overlayClassName?: string;
+ trigger?: Trigger[];
+ mouseEnterDelay?: number;
+ mouseLeaveDelay?: number;
+ overlayStyle?: React.CSSProperties;
+ prefixCls?: string;
+ transitionName?: string;
+ onVisibleChange?: () => void;
+ visible?: boolean;
+ defaultVisible?: boolean;
+ placement?: Placement | Object;
+ align?: Object;
+ onPopupAlign?: (popupDomNode: Element, align: Object) => void;
+ overlay: React.ReactNode;
+ arrowContent?: React.ReactNode;
+ getTooltipContainer?: () => Element;
+ destroyTooltipOnHide?: boolean;
+ }
+
+ // the next line is crucial, it is absent in the original typings
+ export default class Tooltip extends React.Component<Props> {}
+}
"target": "es5",
"jsx": "react",
"lib": ["es2017", "dom"],
- "module": "es2015",
+ "module": "esnext",
"moduleResolution": "node",
"typeRoots": ["./src/main/js/typings", "./node_modules/@types"]
},
"@types/cheerio" "*"
"@types/react" "*"
+"@types/escape-html@0.0.19":
+ version "0.0.19"
+ resolved "https://registry.yarnpkg.com/@types/escape-html/-/escape-html-0.0.19.tgz#595ff7bd7ee510af54517819de24abdcea6f3507"
+
"@types/history@^3":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@types/history/-/history-3.2.1.tgz#0039ab0e0be2a0cc22bac171d27a44588103d123"
version "20.0.7"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-20.0.7.tgz#39cd215db8bda03928dceb933a1e63eb2cbd210e"
+"@types/jquery@3.2.11":
+ version "3.2.11"
+ resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.11.tgz#9119f91bb103b16ae8c4375b019a9b341b409f50"
+
"@types/lodash@4.14.73":
version "4.14.73"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.73.tgz#9837e47db8643ba5bcef2c7921f37d90f9c24213"
"@types/node" "*"
"@types/react" "*"
+"@types/react-helmet@5.0.3":
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-5.0.3.tgz#614e706cb73120936c7c067404809f8c2f1a840c"
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-modal@2.2.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@types/react-modal/-/react-modal-2.2.0.tgz#e92bb8454e53030581f263e3fb7e7d27e3eb85b8"
+ dependencies:
+ "@types/react" "*"
+
"@types/react-redux@5.0.3":
version "5.0.3"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-5.0.3.tgz#cd68de0c49c516b940fdc6f688535596b5d6eca4"
"@types/history" "^3"
"@types/react" "*"
+"@types/react-select@1.0.51":
+ version "1.0.51"
+ resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-1.0.51.tgz#47e7787b068c34395251e95a0981cff8034eddcc"
+ dependencies:
+ "@types/react" "*"
+
"@types/react@*", "@types/react@16.0.2":
version "16.0.2"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.0.2.tgz#0b31a73cdde6272b719e5b05a7df6d1e2654a804"