Skip to content

Commit

Permalink
feat(period-select): skip to previous year if no ended periods in cur…
Browse files Browse the repository at this point in the history
…rent year (#50)

* chore(fixed-periods): remove redundant functions, tests and deps

* feat(period-select): set the initial year value based on period type

* fix(period-select): allow workflow period type to be undefined

* fix(period-select): avoid recomputing maxYear on every render

* test(period-select): update failing year navigator test

* test(fixed-periods): add unit test for getMostRecentCompletedYear

* test(fixed-period): test period type with different start and end year

* chore(period-select): remove redundant const currentYear
  • Loading branch information
HendrikThePendric authored Aug 17, 2021
1 parent 5d618cd commit d8be02b
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 419 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
"@testing-library/user-event": "^13.1.9",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"identity-obj-proxy": "^3.0.0",
"mockdate": "^3.0.5"
"identity-obj-proxy": "^3.0.0"
},
"dependencies": {
"@dhis2/app-runtime": "^2.9.0-beta.6",
Expand Down
141 changes: 45 additions & 96 deletions src/shared/fixed-periods/fixed-periods.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ import i18n from '@dhis2/d2-i18n'
*/

// Period types
export const DAILY = 'Daily'
export const WEEKLY = 'Weekly'
export const WEEKLY_WEDNESDAY = 'WeeklyWednesday'
export const WEEKLY_THURSDAY = 'WeeklyThursday'
export const WEEKLY_SATURDAY = 'WeeklySaturday'
export const WEEKLY_SUNDAY = 'WeeklySunday'
export const BI_WEEKLY = 'BiWeekly'
export const MONTHLY = 'Monthly'
export const BI_MONTHLY = 'BiMonthly'
export const QUARTERLY = 'Quarterly'
export const SIX_MONTHLY = 'SixMonthly'
export const SIX_MONTHLY_APRIL = 'SixMonthlyApril'
// export const SIX_MONTHLY_NOV = 'SixMonthlyNov'
export const YEARLY = 'Yearly'
export const FINANCIAL_APRIL = 'FinancialApril'
export const FINANCIAL_JULY = 'FinancialJuly'
export const FINANCIAL_OCT = 'FinancialOct'
export const FINANCIAL_NOV = 'FinancialNov'
const DAILY = 'Daily'
const WEEKLY = 'Weekly'
const WEEKLY_WEDNESDAY = 'WeeklyWednesday'
const WEEKLY_THURSDAY = 'WeeklyThursday'
const WEEKLY_SATURDAY = 'WeeklySaturday'
const WEEKLY_SUNDAY = 'WeeklySunday'
const BI_WEEKLY = 'BiWeekly'
const MONTHLY = 'Monthly'
const BI_MONTHLY = 'BiMonthly'
const QUARTERLY = 'Quarterly'
const SIX_MONTHLY = 'SixMonthly'
const SIX_MONTHLY_APRIL = 'SixMonthlyApril'
// const SIX_MONTHLY_NOV = 'SixMonthlyNov'
const YEARLY = 'Yearly'
const FINANCIAL_APRIL = 'FinancialApril'
const FINANCIAL_JULY = 'FinancialJuly'
const FINANCIAL_OCT = 'FinancialOct'
const FINANCIAL_NOV = 'FinancialNov'

const getMonthName = key => {
const monthNames = [
Expand Down Expand Up @@ -777,87 +777,36 @@ export const getFixedPeriodsForTypeAndDateRange = (
return convertedPeriods.reverse()
}

const FIXED_PERIODS_BY_LENGTH = [
[DAILY],
[WEEKLY, WEEKLY_WEDNESDAY, WEEKLY_THURSDAY, WEEKLY_SATURDAY, WEEKLY_SUNDAY],
[BI_WEEKLY],
[MONTHLY],
[BI_MONTHLY],
[QUARTERLY],
[SIX_MONTHLY, SIX_MONTHLY_APRIL],
[YEARLY, FINANCIAL_APRIL, FINANCIAL_JULY, FINANCIAL_OCT, FINANCIAL_NOV],
]

export const PERIOD_GREATER = 1
export const PERIOD_EQUAL = 0
export const PERIOD_SHORTER = -1
export const getMostRecentCompletedYear = periodType => {
if (!periodType) {
throw new Error(
'No "periodType" supplied to "getMostRecentCompletedYear"'
)
}

/*
* IF left < right THEN return 1
* IF left > right THEN return -1
* IF left = right THEN return 0
*
* Why right > left = 1 and not the other way?
* When partially applying this function, it makes sense this way:
*
* const compareWithWeekly = partial(compareFixedPeriodLength, 'WEEKLY')
* const isGreater = compareWithWeekly('YEARLY') === PERIOD_GREATER
* -> isGreater is true
*
* @param {string} right
* @param {string} left
* @returns {Int}
*/
export const compareFixedPeriodLength = (left, right) => {
const leftIndex = FIXED_PERIODS_BY_LENGTH.findIndex(types =>
types.includes(left)
)
const rightIndex = FIXED_PERIODS_BY_LENGTH.findIndex(types =>
types.includes(right)
const endDate = new Date(Date.now())
let year = endDate.getFullYear()
let periods = getFixedPeriodsForTypeAndDateRange(
periodType,
`${endDate.getFullYear()}-01-01`,
endDate
)

if (leftIndex === rightIndex) return PERIOD_EQUAL
return leftIndex > rightIndex ? PERIOD_SHORTER : PERIOD_GREATER
}

export const getCurrentPeriodForType = type => {
const currentDate = new Date()
let year = currentDate.getFullYear()

// cover this and the next years as that
// should cover all existing period types
for (let i = 0; i < 2; ++i) {
const periods = getFixedPeriodsByTypeAndYear(type, year).reverse()

for (const period of periods) {
const periodStart = new Date(period.startDate)
const periodEnd = new Date(period.endDate)
const endsBeforePeriodEnd = currentDate <= periodEnd
const startsAfterPeriodStart = currentDate >= periodStart

if (endsBeforePeriodEnd && startsAfterPeriodStart) {
return period
}
if (periods.length > 0) {
return year
} else {
/**
* Practically speaking we could also just return `year - 1` here
* but this logic would allow for periods to span over multiple years
*/
while (periods.length === 0) {
--year
periods = getFixedPeriodsForTypeAndDateRange(
periodType,
`${year}-01-01`,
`${year}-12-31`
)
}

++year
return year
}

return null
}

export const isGreaterPeriodTypeEndDateWithinShorterPeriod = (
greaterPeriodType,
shorterPeriod
) => {
const greaterPeriod = getCurrentPeriodForType(greaterPeriodType)
const greaterPeriodEndDate = new Date(greaterPeriod.endDate)
const shorterPeriodEndDate = new Date(shorterPeriod.endDate)
const shorterPeriodStartDate = new Date(shorterPeriod.startDate)
const greaterEndsAfterShorterStarts =
greaterPeriodEndDate >= shorterPeriodStartDate
const greaterEndsBeforeShorterEnds =
greaterPeriodEndDate <= shorterPeriodEndDate

return greaterEndsAfterShorterStarts && greaterEndsBeforeShorterEnds
}
Loading

0 comments on commit d8be02b

Please sign in to comment.