aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/projects
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-06-29 17:10:48 +0200
committerSonarTech <sonartech@sonarsource.com>2018-06-29 20:21:33 +0200
commit1de495806592ec053c70322de93f797019a448d3 (patch)
tree4bc22bdeac6320c5c5db7cb671fca5c0569259ef /server/sonar-web/src/main/js/apps/projects
parent9973bacbfa4a945e509bf1b574d7e5aae4ba155a (diff)
downloadsonarqube-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')
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCard.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardLeak.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectCardOverall.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ProjectsList.tsx63
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardLeak-test.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ProjectCardOverall-test.tsx12
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardLeak-test.tsx.snap5
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectCardOverall-test.tsx.snap5
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/__snapshots__/ProjectsList-test.tsx.snap26
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>
`;