From 3a2e4d3af7939b8017379527e0213b113a6d52e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Tue, 27 Jun 2017 16:13:00 +0200 Subject: [PATCH] SONAR-8550 Make the analysis version sticky in the project activity list --- .../apps/projectActivity/components/Events.js | 1 - .../components/ProjectActivityAnalysesList.js | 105 +++++++++++++----- .../components/ProjectActivityAnalysis.js | 4 +- .../components/projectActivity.css | 38 ++++++- 4 files changed, 114 insertions(+), 34 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js index 0dd5f89c054..8be0cb58165 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/Events.js @@ -20,7 +20,6 @@ // @flow import React from 'react'; import Event from './Event'; -import './projectActivity.css'; import type { Event as EventType } from '../types'; type Props = { diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js index c44ac7e4e79..d0655faec68 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js @@ -19,6 +19,7 @@ */ // @flow import React from 'react'; +import classNames from 'classnames'; import moment from 'moment'; import ProjectActivityAnalysis from './ProjectActivityAnalysis'; import FormattedDate from '../../../components/ui/FormattedDate'; @@ -39,28 +40,80 @@ type Props = { loading: boolean }; -export default function ProjectActivityAnalysesList(props: Props) { - if (props.analyses.length === 0) { - return ( -
- {props.loading - ?
- : {translate('no_results')}} -
- ); +export default class ProjectActivityAnalysesList extends React.PureComponent { + scrollContainer: HTMLElement; + badges: HTMLCollection; + props: Props; + + componentDidMount() { + this.badges = document.getElementsByClassName('project-activity-version-badge'); + } + + componentDidUpdate(prevProps: Props) { + if (prevProps.analysis !== this.props.analyses && this.scrollContainer) { + this.scrollContainer.scrollTop = 0; + for (let i = 1; i < this.badges.length; i++) { + this.badges[i].removeAttribute('originOffsetTop'); + this.badges[i].classList.remove('sticky'); + } + this.handleScroll(); + } } - const firstAnalysisKey = props.analyses[0].key; - const byVersionByDay = getAnalysesByVersionByDay(props.analyses); - return ( -
-
    + handleScroll = () => { + if (this.scrollContainer && this.badges) { + const scrollTop = this.scrollContainer.scrollTop; + if (scrollTop != null) { + let newScrollTop; + for (let i = 1; i < this.badges.length; i++) { + const badge = this.badges[i]; + let originOffsetTop = badge.getAttribute('originOffsetTop'); + if (originOffsetTop == null) { + originOffsetTop = badge.offsetTop; + badge.setAttribute('originOffsetTop', originOffsetTop.toString()); + } + if (Number(originOffsetTop) < scrollTop + 18 + i * 2) { + if (!badge.classList.contains('sticky')) { + newScrollTop = originOffsetTop; + } + badge.classList.add('sticky'); + } else { + badge.classList.remove('sticky'); + } + } + if (newScrollTop != null) { + this.scrollContainer.scrollTop = newScrollTop - 6; + } + } + } + }; + + render() { + if (this.props.analyses.length === 0) { + return ( +
    + {this.props.loading + ?
    + : {translate('no_results')}} +
    + ); + } + + const firstAnalysisKey = this.props.analyses[0].key; + const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses); + return ( +
      (this.scrollContainer = element)}> {byVersionByDay.map((version, idx) => (
    • {version.version && - - {version.version} - } +
      + + {version.version} + +
      }
        {Object.keys(version.byDay).map(day => (
      • (
      • ))} - {props.analysesLoading &&
      • } + {this.props.analysesLoading &&
      • }
      -
- ); + ); + } } diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js index 41133f90f55..5fbdb2bdf41 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.js @@ -41,7 +41,7 @@ type Props = { export default function ProjectActivityAnalysis(props: Props) { const { date, events } = props.analysis; const { isFirst, canAdmin } = props; - + const analysisTitle = translate('project_activity.analysis'); return (
  • @@ -49,7 +49,7 @@ export default function ProjectActivityAnalysis(props: Props) {
    {canAdmin && diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css index e27947e03aa..00e6a1a3134 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css @@ -4,9 +4,12 @@ } .project-activity-page-side-outer { + position: relative; width: 400px; - overflow: auto; margin-bottom: 0; + display: flex; + flex-direction: row; + align-items: stretch; } .project-activity-page-side-outer > .boxed-group-inner { @@ -31,8 +34,13 @@ align-items: stretch; } -.project-activity-list { +.project-activity-versions-list { max-width: 400px; + box-sizing: border-box; + overflow: auto; + flex-grow: 1; + flex-shrink: 0; + padding-top: 52px; } .project-activity-graph-container { @@ -57,7 +65,8 @@ .project-activity-days-list {} .project-activity-day { - margin-bottom: 32px; + margin-top: 8px; + margin-bottom: 24px; } .project-activity-day:last-child { @@ -169,9 +178,28 @@ } .project-activity-version-badge { + margin-left: -12px; + padding-top: 8px; + padding-bottom: 8px; + background-color: white; +} + +.project-activity-version-badge.sticky, .project-activity-version-badge.first { + position: absolute; + top: 0; + left: 12px; + right: 20px; + padding-top: 24px; + z-index: 100; +} + +.project-activity-version-badge.sticky + .project-activity-days-list { + padding-top: 36px; +} + +.project-activity-version-badge .badge { vertical-align: middle; - padding: 4px 14px 4px 16px; - margin-left: -14px; + padding: 4px 14px 4px 14px; border-radius: 2px; font-weight: bold; font-size: 12px; -- 2.39.5