From 86e6f18da4522029e21bc0ddaac0404edb73d08a Mon Sep 17 00:00:00 2001 From: braimbault Date: Tue, 10 Dec 2024 15:31:43 +0100 Subject: [PATCH] fix: refactor Timeline --- src/components/periods/Timeline.js | 120 ++++++------------ .../periods/styles/Timeline.module.css | 1 - src/util/periods.js | 61 ++++++++- 3 files changed, 101 insertions(+), 81 deletions(-) diff --git a/src/components/periods/Timeline.js b/src/components/periods/Timeline.js index 12ec73577..62c2a22d1 100644 --- a/src/components/periods/Timeline.js +++ b/src/components/periods/Timeline.js @@ -1,10 +1,13 @@ -import { PERIOD_TYPE_REGEX } from '@dhis2/analytics' import cx from 'classnames' import { axisBottom } from 'd3-axis' import { scaleTime } from 'd3-scale' import { select } from 'd3-selection' import PropTypes from 'prop-types' import React, { Component } from 'react' +import { + getPeriodTypeFromId, + getPeriodLevelFromPeriodType, +} from '../../util/periods.js' import timeTicks from '../../util/timeTicks.js' import styles from './styles/Timeline.module.css' @@ -15,86 +18,48 @@ const delay = 1500 const playBtn = const pauseBtn = const doubleTicksPeriods = ['LAST_6_BIMONTHS', 'BIMONTHS_THIS_YEAR'] +const rectHeight = 7 +const rectOffset = 10 -const addPeriodType = (item) => { - const periodTypes = Object.keys(PERIOD_TYPE_REGEX) - let i = 0 - let type = undefined - let match = undefined - - while (i < periodTypes.length && !match) { - type = periodTypes[i] - match = item.id.match(PERIOD_TYPE_REGEX[type]) - i++ - } - - let level - switch (type) { - case 'DAILY': - level = 0 - break - case 'WEEKLY': - case 'WEEKLYWED': - case 'WEEKLYTHU': - case 'WEEKLYSAT': - case 'WEEKLYSUN': - level = 1 - break - case 'BIWEEKLY': - level = 2 - break - case 'MONTHLY': - level = 3 - break - case 'BIMONTHLY': - level = 4 - break - case 'QUARTERLY': - level = 5 - break - case 'SIXMONTHLY': - case 'SIXMONTHLYAPR': - level = 6 - break - case 'YEARLY': - case 'FYNOV': - case 'FYOCT': - case 'FYJUL': - case 'FYAPR': - level = 7 - break - default: - level = 8 - } - - item.type = type - item.level = level - +const addPeriodTypeAndLevel = (item) => { + item.type = getPeriodTypeFromId(item.id) + item.level = getPeriodLevelFromPeriodType(item.type) return item } +const listLevelsFromPeriods = (periodsWithType) => [ + ...new Set(periodsWithType.map((item) => item.level)), +] + const countUniqueRanks = (periods) => { - const periodsWithType = periods.map((item) => addPeriodType(item)) - const levels = [...new Set(periodsWithType.map((item) => item.level))] - return levels.length + const periodsWithType = periods.map((item) => addPeriodTypeAndLevel(item)) + return listLevelsFromPeriods(periodsWithType).length } -const sortPeriods = (periods) => { - let periodsWithType = periods.map((item) => addPeriodType(item)) +const sortPeriodsByLevelRank = (periods) => { + let periodsWithDetails + periodsWithDetails = periods.map((item) => addPeriodTypeAndLevel(item)) - const levels = [...new Set(periodsWithType.map((item) => item.level))].sort( + const sortedLevels = listLevelsFromPeriods(periodsWithDetails).sort( (a, b) => b - a ) - - periodsWithType = periodsWithType.map((item) => ({ + periodsWithDetails = periodsWithDetails.map((item) => ({ ...item, - levelRank: levels.indexOf(item.level), + levelRank: sortedLevels.indexOf(item.level), })) - const sortedPeriods = periodsWithType.sort( + const sortedPeriods = periodsWithDetails.sort( (a, b) => a.levelRank - b.levelRank ) + return sortedPeriods +} +const sortPeriodsByLevelAndStartDate = (periods) => { + let sortedPeriods + sortedPeriods = periods.sort((a, b) => b.level - a.level) + sortedPeriods = periods.sort( + (a, b) => new Date(a.startDate) - new Date(b.startDate) + ) return sortedPeriods } @@ -133,29 +98,32 @@ class Timeline extends Component { const uniqueRanks = countUniqueRanks(this.props.periods) this.setTimeScale() - + const rectTotalHeight = rectHeight + (uniqueRanks - 1) * rectOffset return ( + // play/pause button {mode === 'play' ? pauseBtn : playBtn} + // rectangles {this.getPeriodRects()} + // x axis (this.node = node)} /> @@ -167,7 +135,7 @@ class Timeline extends Component { getPeriodRects = () => { const { period, periods } = this.props - const sortedPeriods = sortPeriods(periods) + const sortedPeriods = sortPeriodsByLevelRank(periods) return sortedPeriods.map((item) => { const isCurrent = period.id === item.id @@ -182,9 +150,9 @@ class Timeline extends Component { [styles.selected]: isCurrent, })} x={x} - y={item.levelRank * 4} + y={item.levelRank * rectOffset} width={width} - height={10} + height={rectHeight} onClick={() => this.onPeriodClick(item)} /> ) @@ -273,11 +241,7 @@ class Timeline extends Component { // Play animation play = () => { const { period, periods, onChange } = this.props - let sortedPeriods - sortedPeriods = periods.sort((a, b) => b.level - a.level) - sortedPeriods = periods.sort( - (a, b) => new Date(a.startDate) - new Date(b.startDate) - ) + const sortedPeriods = sortPeriodsByLevelAndStartDate(periods) const index = sortedPeriods.findIndex((p) => p.id === period.id) const isLastPeriod = index === sortedPeriods.length - 1 diff --git a/src/components/periods/styles/Timeline.module.css b/src/components/periods/styles/Timeline.module.css index 0eef902ee..11c431358 100644 --- a/src/components/periods/styles/Timeline.module.css +++ b/src/components/periods/styles/Timeline.module.css @@ -3,7 +3,6 @@ width: calc(100% - 20px); position: absolute; left: 10px; - bottom: 32px; z-index: 1000px; user-select: none; } diff --git a/src/util/periods.js b/src/util/periods.js index e7912a976..5ce5eb96b 100644 --- a/src/util/periods.js +++ b/src/util/periods.js @@ -1,7 +1,26 @@ import { + DAILY, + WEEKLY, + WEEKLYWED, + WEEKLYTHU, + WEEKLYSAT, + WEEKLYSUN, + BIWEEKLY, + MONTHLY, + BIMONTHLY, + QUARTERLY, + SIXMONTHLY, + SIXMONTHLYAPR, + YEARLY, + FINANCIAL, + FYNOV, + FYOCT, + FYJUL, + FYAPR, getFixedPeriodsOptionsById, getRelativePeriodsOptionsById, getRelativePeriodsDetails, + PERIOD_TYPE_REGEX, } from '@dhis2/analytics' import { periodTypes, @@ -88,7 +107,7 @@ export const getHiddenPeriods = (systemSettings) => { } // Count maximum number of periods returned by analytics api - +// Preliminary step export const getPeriodsDurationByType = ( periods, periodsDetails, @@ -123,7 +142,7 @@ export const getPeriodsDurationByType = ( }, {}) } } - +// Total count export const countPeriods = (periods, deduplication) => { const periodsDetails = getRelativePeriodsDetails() const periodsDurationByType = getPeriodsDurationByType( @@ -133,3 +152,41 @@ export const countPeriods = (periods, deduplication) => { ) return sumObjectValues(periodsDurationByType) } + +export const getPeriodTypeFromId = (periodId) => { + return Object.keys(PERIOD_TYPE_REGEX).find((type) => + periodId.match(PERIOD_TYPE_REGEX[type]) + ) +} + +export const getPeriodLevelFromPeriodType = (periodType) => { + switch (periodType) { + case DAILY: + return 0 + case WEEKLY: + case WEEKLYWED: + case WEEKLYTHU: + case WEEKLYSAT: + case WEEKLYSUN: + return 1 + case BIWEEKLY: + return 2 + case MONTHLY: + return 3 + case BIMONTHLY: + return 4 + case QUARTERLY: + return 5 + case SIXMONTHLY: + case SIXMONTHLYAPR: + return 6 + case YEARLY: + case FYNOV: + case FYOCT: + case FYJUL: + case FYAPR: + return 7 + default: + return 8 + } +}