diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-06-29 17:10:48 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-06-29 20:21:33 +0200 |
commit | 1de495806592ec053c70322de93f797019a448d3 (patch) | |
tree | 4bc22bdeac6320c5c5db7cb671fca5c0569259ef /server/sonar-web/src/main/js/apps/projects | |
parent | 9973bacbfa4a945e509bf1b574d7e5aae4ba155a (diff) | |
download | sonarqube-1de495806592ec053c70322de93f797019a448d3.tar.gz sonarqube-1de495806592ec053c70322de93f797019a448d3.zip |
SONAR-10677 Reduce amount of DOM nodes on Projects page (#456)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projects')
9 files changed, 88 insertions, 44 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.tsx index 05d94b9e787..d572edb0d5b 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCard.tsx @@ -23,6 +23,7 @@ import ProjectCardOverall from './ProjectCardOverall'; import { Project } from '../types'; interface Props { + height: number; organization?: { key: string }; project: Project; type?: string; diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.tsx index c0328c25e07..b6a3c63c2b4 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.tsx @@ -31,18 +31,19 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Project } from '../types'; interface Props { + height: number; organization?: { key: string }; project: Project; } -export default function ProjectCardLeak({ organization, project }: Props) { +export default function ProjectCardLeak({ height, organization, project }: Props) { const { measures } = project; const isPrivate = project.visibility === 'private'; const hasTags = project.tags.length > 0; return ( - <div className="boxed-group project-card" data-key={project.key}> + <div className="boxed-group project-card" data-key={project.key} style={{ height }}> <div className="boxed-group-header clearfix"> <div className="project-card-header"> {project.isFavorite != null && ( diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.tsx index 72d44b470f7..f653d14975d 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.tsx @@ -30,18 +30,19 @@ import { translate, translateWithParameters } from '../../../helpers/l10n'; import { Project } from '../types'; interface Props { + height: number; organization?: { key: string }; project: Project; } -export default function ProjectCardOverall({ organization, project }: Props) { +export default function ProjectCardOverall({ height, organization, project }: Props) { const { measures } = project; const isPrivate = project.visibility === 'private'; const hasTags = project.tags.length > 0; return ( - <div className="boxed-group project-card" data-key={project.key}> + <div className="boxed-group project-card" data-key={project.key} style={{ height }}> <div className="boxed-group-header clearfix"> <div className="project-card-header"> {project.isFavorite !== undefined && ( diff --git a/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx index 491da7f539b..a019fca6cbf 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx @@ -18,6 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer'; +import { List, ListRowProps } from 'react-virtualized/dist/commonjs/List'; +import { WindowScroller } from 'react-virtualized/dist/commonjs/WindowScroller'; import ProjectCard from './ProjectCard'; import NoFavoriteProjects from './NoFavoriteProjects'; import EmptyInstance from './EmptyInstance'; @@ -36,6 +39,10 @@ interface Props { } export default class ProjectsList extends React.PureComponent<Props> { + getCardHeight = () => { + return this.props.cardType === 'leak' ? 159 : 143; + }; + renderNoProjects() { const { isFavorite, isFiltered, query } = this.props; if (isFiltered) { @@ -44,21 +51,57 @@ export default class ProjectsList extends React.PureComponent<Props> { return isFavorite ? <NoFavoriteProjects /> : <EmptyInstance />; } + renderRow = ({ index, key, style }: ListRowProps) => { + const project = this.props.projects[index]; + const height = this.getCardHeight(); + return ( + <div key={key} style={{ ...style, height }}> + <ProjectCard + height={height} + key={project.key} + organization={this.props.organization} + project={project} + type={this.props.cardType} + /> + </div> + ); + }; + + renderList() { + const cardHeight = this.getCardHeight(); + return ( + <WindowScroller> + {({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => ( + <AutoSizer disableHeight={true}> + {({ width }) => ( + <div ref={registerChild as any}> + <List + autoHeight={true} + height={height} + isScrolling={isScrolling} + onScroll={onChildScroll} + overscanRowCount={2} + rowCount={this.props.projects.length} + rowHeight={cardHeight + 20} + rowRenderer={this.renderRow} + scrollTop={scrollTop} + style={{ outline: 'none' }} + width={width} + /> + </div> + )} + </AutoSizer> + )} + </WindowScroller> + ); + } + render() { const { projects } = this.props; return ( <div className="projects-list"> - {projects.length > 0 - ? projects.map(project => ( - <ProjectCard - key={project.key} - organization={this.props.organization} - project={project} - type={this.props.cardType} - /> - )) - : this.renderNoProjects()} + {projects.length > 0 ? this.renderList() : this.renderNoProjects()} </div> ); } diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.tsx index 70bf9401111..3a25da57bf3 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.tsx @@ -40,7 +40,7 @@ const PROJECT = { }; it('should display analysis date and leak start date', () => { - const card = shallow(<ProjectCardLeak project={PROJECT} />); + const card = shallow(<ProjectCardLeak height={100} project={PROJECT} />); expect(card.find('.project-card-dates').exists()).toBeTruthy(); expect(card.find('.project-card-dates').find('DateFromNow')).toHaveLength(1); expect(card.find('.project-card-dates').find('DateTimeFormatter')).toHaveLength(1); @@ -48,14 +48,14 @@ it('should display analysis date and leak start date', () => { it('should not display analysis date or leak start date', () => { const project = { ...PROJECT, analysisDate: undefined }; - const card = shallow(<ProjectCardLeak project={project} />); + const card = shallow(<ProjectCardLeak height={100} project={project} />); expect(card.find('.project-card-dates').exists()).toBeFalsy(); }); it('should display tags', () => { const project = { ...PROJECT, tags: ['foo', 'bar'] }; expect( - shallow(<ProjectCardLeak project={project} />) + shallow(<ProjectCardLeak height={100} project={project} />) .find('TagsList') .exists() ).toBeTruthy(); @@ -64,12 +64,12 @@ it('should display tags', () => { it('should private badge', () => { const project = { ...PROJECT, visibility: 'private' }; expect( - shallow(<ProjectCardLeak project={project} />) + shallow(<ProjectCardLeak height={100} project={project} />) .find('PrivateBadge') .exists() ).toBeTruthy(); }); it('should display the leak measures and quality gate', () => { - expect(shallow(<ProjectCardLeak project={PROJECT} />)).toMatchSnapshot(); + expect(shallow(<ProjectCardLeak height={100} project={PROJECT} />)).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.tsx index 10dc9eaa739..fc3e58bbd80 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.tsx @@ -40,12 +40,12 @@ const PROJECT = { it('should display analysis date (and not leak period) when defined', () => { expect( - shallow(<ProjectCardOverall project={PROJECT} />) + shallow(<ProjectCardOverall height={100} project={PROJECT} />) .find('.project-card-dates') .exists() ).toBeTruthy(); expect( - shallow(<ProjectCardOverall project={{ ...PROJECT, analysisDate: undefined }} />) + shallow(<ProjectCardOverall height={100} project={{ ...PROJECT, analysisDate: undefined }} />) .find('.project-card-dates') .exists() ).toBeFalsy(); @@ -54,7 +54,7 @@ it('should display analysis date (and not leak period) when defined', () => { it('should not display the quality gate', () => { const project = { ...PROJECT, analysisDate: undefined }; expect( - shallow(<ProjectCardOverall project={project} />) + shallow(<ProjectCardOverall height={100} project={project} />) .find('ProjectCardOverallQualityGate') .exists() ).toBeFalsy(); @@ -63,7 +63,7 @@ it('should not display the quality gate', () => { it('should display tags', () => { const project = { ...PROJECT, tags: ['foo', 'bar'] }; expect( - shallow(<ProjectCardOverall project={project} />) + shallow(<ProjectCardOverall height={100} project={project} />) .find('TagsList') .exists() ).toBeTruthy(); @@ -72,12 +72,12 @@ it('should display tags', () => { it('should private badge', () => { const project = { ...PROJECT, visibility: 'private' }; expect( - shallow(<ProjectCardOverall project={project} />) + shallow(<ProjectCardOverall height={100} project={project} />) .find('PrivateBadge') .exists() ).toBeTruthy(); }); it('should display the overall measures and quality gate', () => { - expect(shallow(<ProjectCardOverall project={PROJECT} />)).toMatchSnapshot(); + expect(shallow(<ProjectCardOverall height={100} project={PROJECT} />)).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.tsx.snap index deca57a4c53..fa106ed2ac6 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.tsx.snap @@ -4,6 +4,11 @@ exports[`should display the leak measures and quality gate 1`] = ` <div className="boxed-group project-card" data-key="foo" + style={ + Object { + "height": 100, + } + } > <div className="boxed-group-header clearfix" diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.tsx.snap index a6697e18b23..263d0bf5fd0 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.tsx.snap @@ -4,6 +4,11 @@ exports[`should display the overall measures and quality gate 1`] = ` <div className="boxed-group project-card" data-key="foo" + style={ + Object { + "height": 100, + } + } > <div className="boxed-group-header clearfix" diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsList-test.tsx.snap b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsList-test.tsx.snap index b2552033bef..7dcb16317c2 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsList-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsList-test.tsx.snap @@ -4,25 +4,13 @@ exports[`renders 1`] = ` <div className="projects-list" > - <ProjectCard - key="foo" - project={ - Object { - "key": "foo", - "name": "Foo", - } - } - type="overall" - /> - <ProjectCard - key="bar" - project={ - Object { - "key": "bar", - "name": "Bar", - } - } - type="overall" + <WindowScroller + onResize={[Function]} + onScroll={[Function]} + scrollElement={[Window]} + scrollingResetTimeInterval={150} + serverHeight={0} + serverWidth={0} /> </div> `; |