diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2016-10-18 09:46:22 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2016-10-21 10:24:17 +0200 |
commit | b7129679327efeeb44f9205656b46376adfe9689 (patch) | |
tree | f01159db52a79aae8e478dcafe79a7d9d22156c6 /server/sonar-web/src/main/js/apps/projects/components | |
parent | 3d8cdcbf8558e40385f481272045056d5435a3e6 (diff) | |
download | sonarqube-b7129679327efeeb44f9205656b46376adfe9689.tar.gz sonarqube-b7129679327efeeb44f9205656b46376adfe9689.zip |
SONAR-8300 Create new "Projects" page [first iter]
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projects/components')
14 files changed, 713 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/App.js b/server/sonar-web/src/main/js/apps/projects/components/App.js new file mode 100644 index 00000000000..b6abec6f45f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/App.js @@ -0,0 +1,82 @@ +/* + * 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. + */ +import React from 'react'; +import Helmet from 'react-helmet'; +import PageHeaderContainer from './PageHeaderContainer'; +import ProjectsListContainer from './ProjectsListContainer'; +import ProjectsListFooterContainer from './ProjectsListFooterContainer'; +import PageSidebar from './PageSidebar'; +import GlobalMessagesContainer from '../../../app/components/GlobalMessagesContainer'; +import { parseUrlQuery } from '../store/utils'; +import '../styles.css'; +import { translate } from '../../../helpers/l10n'; + +export default class App extends React.Component { + static propTypes = { + fetchProjects: React.PropTypes.func.isRequired + }; + + state = { + query: {} + }; + + componentDidMount () { + document.querySelector('html').classList.add('dashboard-page'); + this.handleQueryChange(); + } + + componentDidUpdate (prevProps) { + if (prevProps.location.query !== this.props.location.query) { + this.handleQueryChange(); + } + } + + componentWillUnmount () { + document.querySelector('html').classList.remove('dashboard-page'); + } + + handleQueryChange () { + const query = parseUrlQuery(this.props.location.query); + this.setState({ query }); + this.props.fetchProjects(query); + } + + render () { + return ( + <div id="projects-page" className="page page-limited"> + <Helmet title={translate('projects.page')} titleTemplate="SonarQube - %s"/> + + <PageHeaderContainer/> + + <GlobalMessagesContainer/> + + <div className="page-with-sidebar page-with-left-sidebar"> + <div className="page-main"> + <ProjectsListContainer/> + <ProjectsListFooterContainer query={this.state.query}/> + </div> + <aside className="page-sidebar-fixed"> + <PageSidebar query={this.state.query}/> + </aside> + </div> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/AppContainer.js b/server/sonar-web/src/main/js/apps/projects/components/AppContainer.js new file mode 100644 index 00000000000..f2956e0b14a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/AppContainer.js @@ -0,0 +1,27 @@ +/* + * 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. + */ +import { connect } from 'react-redux'; +import App from './App'; +import { fetchProjects } from '../store/actions'; + +export default connect( + () => ({}), + { fetchProjects } +)(App); diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js new file mode 100644 index 00000000000..4043e0176f9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/PageHeader.js @@ -0,0 +1,52 @@ +/* + * 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. + */ +import React from 'react'; +import { translate } from '../../../helpers/l10n'; + +export default class PageHeader extends React.Component { + static propTypes = { + total: React.PropTypes.number, + loading: React.PropTypes.bool + }; + + render () { + const { total, loading } = this.props; + + return ( + <header className="page-header"> + <h1 className="page-title">{translate('projects.page')}</h1> + + {!!loading && ( + <i className="spinner"/> + )} + + <div className="page-actions"> + {total != null && ( + <span><strong>{total}</strong> {translate('projects._projects')}</span> + )} + </div> + + <div className="page-description"> + {translate('projects.page.description')} + </div> + </header> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageHeaderContainer.js b/server/sonar-web/src/main/js/apps/projects/components/PageHeaderContainer.js new file mode 100644 index 00000000000..fe8c6fd6043 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/PageHeaderContainer.js @@ -0,0 +1,26 @@ +/* + * 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. + */ +import { connect } from 'react-redux'; +import PageHeader from './PageHeader'; +import { getProjectsAppState } from '../../../app/store/rootReducer'; + +export default connect( + state => getProjectsAppState(state) +)(PageHeader); diff --git a/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js new file mode 100644 index 00000000000..c250d97c141 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/PageSidebar.js @@ -0,0 +1,37 @@ +/* + * 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. + */ +import React from 'react'; +import CoverageFilterContainer from '../filters/CoverageFilterContainer'; +import DuplicationsFilterContainer from '../filters/DuplicationsFilterContainer'; +import SizeFilterContainer from '../filters/SizeFilterContainer'; +import QualityGateFilterContainer from '../filters/QualityGateFilterContainer'; + +export default class PageSidebar extends React.Component { + render () { + return ( + <div> + <CoverageFilterContainer query={this.props.query}/> + <DuplicationsFilterContainer query={this.props.query}/> + <SizeFilterContainer query={this.props.query}/> + <QualityGateFilterContainer query={this.props.query}/> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js new file mode 100644 index 00000000000..e76fa0e975d --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.js @@ -0,0 +1,47 @@ +/* + * 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. + */ +import React from 'react'; +import ProjectCardMeasures from './ProjectCardMeasures'; +import { getComponentUrl } from '../../../helpers/urls'; + +export default class ProjectCard extends React.Component { + static propTypes = { + project: React.PropTypes.object + }; + + render () { + const { project } = this.props; + + if (project == null) { + return null; + } + + return ( + <div className="boxed-group project-card"> + <h2 className="project-card-name"> + <a className="link-base-color" href={getComponentUrl(project.key)}>{project.name}</a> + </h2> + <div className="boxed-group-inner"> + <ProjectCardMeasures measures={this.props.measures}/> + </div> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js new file mode 100644 index 00000000000..f3f9713ffb9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardContainer.js @@ -0,0 +1,29 @@ +/* + * 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. + */ +import { connect } from 'react-redux'; +import ProjectCard from './ProjectCard'; +import { getComponent, getComponentMeasures } from '../../../app/store/rootReducer'; + +export default connect( + (state, ownProps) => ({ + project: getComponent(state, ownProps.projectKey), + measures: getComponentMeasures(state, ownProps.projectKey), + }) +)(ProjectCard); diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js new file mode 100644 index 00000000000..f91571ab8c3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLanguages.js @@ -0,0 +1,55 @@ +/* + * 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. + */ +import React from 'react'; +import sortBy from 'lodash/sortBy'; +import { connect } from 'react-redux'; +import { getLanguages } from '../../../app/store/rootReducer'; +import { translate } from '../../../helpers/l10n'; + +class ProjectCardLanguages extends React.Component { + getLanguageName (key) { + if (key === '<null>') { + return translate('unknown'); + } + const language = this.props.languages[key]; + return language != null ? language.name : key; + } + + render () { + const { distribution } = this.props; + + if (distribution == null) { + return null; + } + + const parsedLanguages = distribution.split(';').map(item => item.split('=')); + const finalLanguages = sortBy(parsedLanguages, l => -1 * Number(l[1])) + .slice(0, 2) + .map(l => this.getLanguageName(l[0])); + + return <span>{finalLanguages.join(', ')}</span>; + } +} + +const mapStateToProps = state => ({ + languages: getLanguages(state) +}); + +export default connect(mapStateToProps)(ProjectCardLanguages); diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardMeasures.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardMeasures.js new file mode 100644 index 00000000000..9c7cc99abfd --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardMeasures.js @@ -0,0 +1,129 @@ +/* + * 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. + */ +import React from 'react'; +import ProjectCardLanguages from './ProjectCardLanguages'; +import ProjectCardQualityGate from './ProjectCardQualityGate'; +import Measure from '../../component-measures/components/Measure'; +import Rating from '../../../components/ui/Rating'; +import CoverageRating from '../../../components/ui/CoverageRating'; +import DuplicationsRating from '../../../components/ui/DuplicationsRating'; +import SizeRating from '../../../components/ui/SizeRating'; +import { translate } from '../../../helpers/l10n'; + +export default class ProjectCardMeasures extends React.Component { + static propTypes = { + measures: React.PropTypes.object, + languages: React.PropTypes.array + }; + + render () { + const { measures } = this.props; + + if (measures == null) { + return null; + } + + return ( + <div className="project-card-measures"> + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + <Rating value={measures['reliability_rating']}/> + </div> + <div className="project-card-measure-label"> + {translate('metric_domain.Reliability')} + </div> + </div> + </div> + + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + <Rating value={measures['security_rating']}/> + </div> + <div className="project-card-measure-label"> + {translate('metric_domain.Security')} + </div> + </div> + </div> + + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + <Rating value={measures['sqale_rating']}/> + </div> + <div className="project-card-measure-label"> + {translate('metric_domain.Maintainability')} + </div> + </div> + </div> + + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + {measures['coverage'] != null && ( + <span className="spacer-right"> + <CoverageRating value={measures['coverage']}/> + </span> + )} + <Measure measure={{ value: measures['coverage'] }} + metric={{ key: 'coverage', type: 'PERCENT' }}/> + </div> + <div className="project-card-measure-label"> + {translate('metric.coverage.name')} + </div> + </div> + </div> + + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + <span className="spacer-right"> + <DuplicationsRating value={measures['duplicated_lines_density']}/> + </span> + <Measure measure={{ value: measures['duplicated_lines_density'] }} + metric={{ key: 'duplicated_lines_density', type: 'PERCENT' }}/> + </div> + <div className="project-card-measure-label"> + {translate('metric.duplicated_lines_density.short_name')} + </div> + </div> + </div> + + <div className="project-card-measure"> + <div className="project-card-measure-inner"> + <div className="project-card-measure-number"> + <span className="spacer-right"> + <SizeRating value={measures['ncloc']}/> + </span> + <Measure measure={{ value: measures['ncloc'] }} + metric={{ key: 'ncloc', type: 'SHORT_INT' }}/> + </div> + <div className="project-card-measure-label"> + <ProjectCardLanguages distribution={measures['ncloc_language_distribution']}/> + </div> + </div> + </div> + + <ProjectCardQualityGate status={measures['alert_status']}/> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js new file mode 100644 index 00000000000..cc542cabefa --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardQualityGate.js @@ -0,0 +1,49 @@ +/* + * 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. + */ +import React from 'react'; +import Level from '../../../components/ui/Level'; +import { translate } from '../../../helpers/l10n'; + +export default class ProjectCardQualityGate extends React.Component { + static propTypes = { + status: React.PropTypes.string + }; + + render () { + const { status } = this.props; + + if (!status) { + return null; + } + + return ( + <div className="project-card-measure pull-right"> + <div className="project-card-measure-inner"> + <div> + <Level level={status}/> + </div> + <div className="project-card-measure-label"> + {translate('overview.quality_gate')} + </div> + </div> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js new file mode 100644 index 00000000000..47f4a105589 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.js @@ -0,0 +1,75 @@ +/* + * 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. + */ +import React from 'react'; +import { List, AutoSizer, WindowScroller } from 'react-virtualized'; +import ProjectCardContainer from './ProjectCardContainer'; +import { translate } from '../../../helpers/l10n'; + +export default class ProjectsList extends React.Component { + static propTypes = { + projects: React.PropTypes.arrayOf(React.PropTypes.string) + }; + + render () { + const { projects } = this.props; + + if (projects == null) { + return null; + } + + if (projects.length === 0) { + return ( + <div className="projects-empty-list"> + <h3>{translate('projects.no_projects.1')}</h3> + <p className="big-spacer-top">{translate('projects.no_projects.2')}</p> + </div> + ); + } + + const rowRenderer = ({ key, index, style }) => { + const projectKey = projects[index]; + return ( + <div key={key} style={style}> + <ProjectCardContainer projectKey={projectKey}/> + </div> + ); + }; + + return ( + <WindowScroller> + {({ height, scrollTop }) => ( + <AutoSizer disableHeight> + {({ width }) => ( + <List + className="projects-list" + autoHeight + width={width} + height={height} + rowCount={projects.length} + rowHeight={135} + rowRenderer={rowRenderer} + scrollTop={scrollTop}/> + )} + </AutoSizer> + )} + </WindowScroller> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsListContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListContainer.js new file mode 100644 index 00000000000..bdeb573a65a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListContainer.js @@ -0,0 +1,28 @@ +/* + * 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. + */ +import { connect } from 'react-redux'; +import ProjectsList from './ProjectsList'; +import { getProjects } from '../../../app/store/rootReducer'; + +export default connect( + state => ({ + projects: getProjects(state) + }) +)(ProjectsList); diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js new file mode 100644 index 00000000000..d256492d68e --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooter.js @@ -0,0 +1,35 @@ +/* + * 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. + */ +import React from 'react'; +import ListFooter from '../../../components/controls/ListFooter'; + +export default class ProjectsListFooter extends React.Component { + static propTypes = { + total: React.PropTypes.number.isRequired, + }; + + render () { + if (!this.props.total) { + return null; + } + + return <ListFooter {...this.props}/>; + } +} diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooterContainer.js b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooterContainer.js new file mode 100644 index 00000000000..d30f699c723 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsListFooterContainer.js @@ -0,0 +1,42 @@ +/* + * 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. + */ +import { connect } from 'react-redux'; +import { getProjects, getProjectsAppState } from '../../../app/store/rootReducer'; +import { fetchMoreProjects } from '../store/actions'; +import ProjectsListFooter from './ProjectsListFooter'; + +const mapStateToProps = state => { + const projects = getProjects(state); + const appState = getProjectsAppState(state); + return { + count: projects != null ? projects.length : 0, + total: appState.total != null ? appState.total : 0, + ready: !appState.loading + }; +}; + +const mapDispatchToProps = (dispatch, ownProps) => ({ + loadMore: () => dispatch(fetchMoreProjects(ownProps.query)) +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ProjectsListFooter); |