Skip to content

feat: Improved Period Selection and Usability Enhancements #3407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 90 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
0ee3fad
feat: use PeriodDimension in ThematicDialog
BRaimbault Nov 18, 2024
537c0f7
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Nov 18, 2024
06d6d71
feat: support multiple periods
BRaimbault Nov 19, 2024
67ff60d
fix: PeriodDimension style
BRaimbault Nov 20, 2024
7b3545a
fix: get default relative periods labels
BRaimbault Nov 25, 2024
b2be0ed
feat: use PeriodDimension in ThematicDialog
BRaimbault Dec 2, 2024
748150e
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Dec 2, 2024
c224835
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Dec 3, 2024
fcda751
feat: use PeriodDimension in ThematicDialog
BRaimbault Dec 3, 2024
c1c8a4a
feat: use PeriodDimension in ThematicDialog
BRaimbault Dec 4, 2024
12159df
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Dec 5, 2024
68ac83b
fix: correct RenderingStrategy periods count
BRaimbault Dec 5, 2024
a4322fb
fix: use CalendarInput in StartEndDate
BRaimbault Dec 6, 2024
b80c33c
feat: handle multiple periods in timeline
BRaimbault Dec 6, 2024
dbd09ba
feat: use PeriodDimension in ThematicDialog
BRaimbault Dec 9, 2024
245848a
fix: add sumObjectValues helper and test
BRaimbault Dec 10, 2024
e744748
fix: add getPeriodsDurationByType util and test
BRaimbault Dec 10, 2024
25d9700
fix: refactor RenderingStrategy and add test
BRaimbault Dec 10, 2024
86e6f18
fix: refactor Timeline
BRaimbault Dec 10, 2024
c6c6fcf
fix: refactor Timeline
BRaimbault Dec 11, 2024
170ac85
fix: refactor Timeline
BRaimbault Dec 11, 2024
cd32b22
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Dec 11, 2024
709a8ba
chore: clean-up
BRaimbault Dec 12, 2024
2d74cb0
chore: clean-up
BRaimbault Dec 12, 2024
051a9bd
fix: update periodError handling
BRaimbault Dec 12, 2024
5d7c55d
fix: handle multiple periods in interpretations
BRaimbault Dec 13, 2024
9f4ad67
fix: avoid defaulting to period tab
BRaimbault Dec 13, 2024
07dd32f
feat: add closing buttons "x"
BRaimbault Dec 13, 2024
1487d0b
feat: additional keyboard controls
BRaimbault Dec 13, 2024
aff5044
fix: timeline not visible in Firefox
BRaimbault Dec 18, 2024
c0d7028
chore: fix cypress tests
BRaimbault Dec 20, 2024
91a69bb
chore: fix cypress tests
BRaimbault Dec 20, 2024
5b09c6e
chore: cypress update
BRaimbault Dec 20, 2024
ddb7e98
chore: add useKeyDown jest test
BRaimbault Dec 23, 2024
7af9ac1
chore: add RadioGroup jest test
BRaimbault Dec 23, 2024
6756f8f
chore: fix lint error
BRaimbault Dec 23, 2024
5866c66
chore: fix jest tests
BRaimbault Dec 23, 2024
f5027c4
chore: refactor Timeline to functional component
BRaimbault Dec 24, 2024
340c227
fix: fix Timeline sorting
BRaimbault Dec 24, 2024
f6f71c9
chore: StartEndDate refactor and tests
BRaimbault Dec 27, 2024
f1f9029
chore: StartEndDate refactor
BRaimbault Dec 27, 2024
74adf06
chore: add jest test for StartEndDate
BRaimbault Dec 27, 2024
cc6ae9a
chore: constants clean-up
BRaimbault Dec 27, 2024
0213833
chore: add jest tests for util/periods.js
BRaimbault Dec 27, 2024
0ca7358
chore: add jest test for utils/analytics.js
BRaimbault Dec 27, 2024
12ac3a2
chore: update cypress tests
BRaimbault Dec 27, 2024
a059aec
chore: eventlayer cypress test fix
BRaimbault Dec 28, 2024
ca590a6
feat: backup and restore periods or dates when switching between peri…
BRaimbault Jan 9, 2025
921d99c
fix: prevent Calendar crashing when YYYY-MM-0 is typed and input is f…
BRaimbault Jan 9, 2025
3c270db
chore: update eventlayer cypress test
BRaimbault Jan 9, 2025
e241433
chore: support startDate endDate clear in Layer
BRaimbault Jan 10, 2025
af3a261
chore: fix eventlayer cypress test
BRaimbault Jan 10, 2025
ad4ad52
fix: periodError not shown on layer edit
BRaimbault Jan 10, 2025
3e6a753
fix: support hyphen typing in 5th and 8th place in StartEndDate
BRaimbault Jan 10, 2025
298371b
chore: fix lint error
BRaimbault Jan 10, 2025
98b01d8
fix: first period selection in Timeline and cypress tests
BRaimbault Jan 10, 2025
c21683a
chore: selectPeriodType to accept object in cypress test
BRaimbault Jan 13, 2025
69950fe
chore: create constants in cypress tests for clarity
BRaimbault Jan 13, 2025
511fa82
fix: general styling imporvements
BRaimbault Jan 14, 2025
43cbcd9
chore: clean-up
BRaimbault Jan 14, 2025
c64f21b
chore: 'play' and 'pause' as constants in Timeline
BRaimbault Jan 14, 2025
547f8b3
chore: remove unecessary key props
BRaimbault Jan 16, 2025
7be4cdf
chore: remove unecessary key props
BRaimbault Jan 16, 2025
7409635
fix: improve periods validation in ThematicDialog
BRaimbault Jan 16, 2025
9487fbd
fix: update StartEndDate placeholder for consistency with other apps
BRaimbault Jan 16, 2025
ee9b3cb
chore: date utils improvements
BRaimbault Jan 16, 2025
52dc8ad
fix: StartEndDate improvments
BRaimbault Jan 16, 2025
39401b8
chore: thematiclayer cypress test for user OU and other OU
BRaimbault Jan 16, 2025
c66280a
chore: add multi-periods cypress test to thematiclayer
BRaimbault Jan 17, 2025
5a72118
fix: StartEndDate improvements
BRaimbault Jan 17, 2025
c435237
chore: add keyboard navigation cypress test
BRaimbault Jan 17, 2025
2edae69
fix: repeated periods in split map
BRaimbault Jan 20, 2025
6498f07
chore: lint error fix
BRaimbault Jan 21, 2025
0c2333e
chore: devDependencies version bump
BRaimbault Jan 21, 2025
f895e2a
chore: devDependencies version bump
BRaimbault Jan 21, 2025
ad420ec
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Jan 21, 2025
ea1b521
Merge branch 'master' into feat/DHIS2-15796
BRaimbault Jan 21, 2025
1b33c00
chore: devDependencies version bump
BRaimbault Jan 21, 2025
d426860
chore: fix lint error
BRaimbault Jan 21, 2025
d2cb927
chore: fix lint errors
BRaimbault Jan 21, 2025
4ec1523
fix: set default calendar to iso8601
BRaimbault Jan 21, 2025
c1fd52b
fix: calendarInput caret repositioning on insert
BRaimbault Jan 31, 2025
a309baa
fix: calendarInput caret repositioning on insert
BRaimbault Feb 3, 2025
255082d
fix: refactor RenderingStrategy
BRaimbault Feb 3, 2025
418c426
chore: update theamaticlayer cypress test
BRaimbault Feb 3, 2025
d36a1d4
fix: styling adjustments
BRaimbault Feb 4, 2025
338f3ff
docs: periods docs update
BRaimbault Feb 4, 2025
7160e5b
fix: StartEndDate onDateSelect and SegmentedControl onChange bug fixes
BRaimbault Feb 6, 2025
e17203b
docs: reformulation
BRaimbault Feb 6, 2025
85b88d4
chore: @dhis2/analytics version bump
BRaimbault Feb 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cypress/elements/event_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export class EventLayer extends Layer {
return this
}

selectPeriodType(periodType) {
selectPeriodType({ periodType } = {}) {
if (!periodType) {
throw new Error("The 'periodType' parameter is required.")
}

cy.getByDataTest('relative-period-select-content').click()
cy.contains(periodType).click()

Expand Down
31 changes: 19 additions & 12 deletions cypress/elements/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class Layer {
.contains(level)
.find('input')
.check()
cy.get('body').click() // Close the modal menu
cy.get('body').click()

return this
}
Expand All @@ -59,27 +59,34 @@ export class Layer {
.find('input')
.uncheck()

cy.get('body').click() // Close the modal menu
cy.get('body').click()

return this
}

typeStartDate(dateString) {
cy.get('label')
.contains('Start date')
.next()
.find('input')
.type(dateString)
cy.getByDataTest('calendar-clear-button').eq(0).click()

if (dateString) {
cy.getByDataTest('start-date-input-content')
.find('input')
.type(dateString)
cy.get('body').click(0, 0)
}

return this
}

typeEndDate(dateString) {
cy.get('label')
.contains('End date')
.next()
.find('input')
.type(dateString)
cy.getByDataTest('calendar-clear-button').eq(1).click()

if (dateString) {
cy.getByDataTest('end-date-input-content')
.find('input')
.type(dateString)
cy.get('body').click(0, 0)
}

return this
}

Expand Down
77 changes: 74 additions & 3 deletions cypress/elements/thematic_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,80 @@ export class ThematicLayer extends Layer {
return this
}

selectPeriodType(periodType) {
cy.get('[data-test="periodtypeselect"]').click()
cy.contains(periodType).click()
removeAllPeriods() {
cy.getByDataTest('period-dimension-transfer-actions-removeall').click()

return this
}

selectPeriodType({
periodType,
periodDimension = 'fixed',
n = 'last',
y = '',
removeAll = true,
} = {}) {
if (!periodType) {
throw new Error("The 'periodType' parameter is required.")
}

// Select fixed / relative periods
cy.getByDataTest(
`period-dimension-${periodDimension}-periods-button`
).click()
// Open dropdown for period type
cy.getByDataTest(
`period-dimension-${periodDimension}-period-filter${
periodDimension === 'fixed' ? '-period-type' : ''
}-content`
).click()
// Select period type in dropdown if not active already
cy.get(`[data-value="${periodType}"]`).then(($el) => {
if ($el.hasClass('active')) {
cy.get('body').click('topLeft')
} else {
cy.wrap($el).click()
}
})

if (removeAll) {
cy.getByDataTest(
'period-dimension-transfer-actions-removeall'
).click()
}

if (y !== '') {
cy.getByDataTest(
'period-dimension-fixed-period-filter-year-content'
)
.get('input[type="number"]')
.clear()
cy.getByDataTest(
'period-dimension-fixed-period-filter-year-content'
)
.get('input[type="number"]')
.type(y)
}
if (n === 'last') {
cy.getByDataTest('period-dimension-transfer-option-content')
.last()
.dblclick()
} else {
cy.getByDataTest('period-dimension-transfer-option-content')
.eq(n)
.dblclick()
}

return this
}

selectPresets() {
cy.contains('Choose from presets').click()

return this
}
selectStartEndDates() {
cy.contains('Define start - end dates').click()

return this
}
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion cypress/integration/dataTable.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ describe('data table', () => {
.selectProgram('Inpatient morbidity and mortality')
.validateStage('Inpatient morbidity and mortality')
.selectTab('Period')
.selectPeriodType('Start/end dates')
.selectPeriodType({ periodType: 'Start/end dates' })
.typeStartDate(`${CURRENT_YEAR - 1}-01-01`)
.typeEndDate(`${CURRENT_YEAR - 1}-01-03`)
.addToMap()
Expand Down
81 changes: 81 additions & 0 deletions cypress/integration/keyboard.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { EXTENDED_TIMEOUT } from '../support/util.js'

const map = {
id: 'eDlFx0jTtV9',
cardTitle: 'ANC LLITN coverage',
}

const alt = {
group: 'HIV',
name: 'VCCT post-test counselling rate',
}

describe('keyboard navigation', () => {
it('tab', () => {
cy.visit('/')

// StartEndDate
cy.getByDataTest('add-layer-button').click()

cy.get(`[data-test="addlayeritem-thematic"]`).click()
cy.getByDataTest('layeredit').should('be.visible')

cy.getByDataTest('dhis2-uicore-tabbar-tabs')
.find('button')
.contains('Period')
.click()
cy.contains('Define start - end dates').click()
cy.getByDataTest('calendar-clear-button').eq(0).click()
cy.getByDataTest('start-date-input-content').find('input').type('123')
cy.getByDataTest('calendar').should('be.visible')
cy.realPress('Tab')
cy.getByDataTest('calendar').should('not.exist')
cy.realPress('Tab')
cy.getByDataTest('calendar').should('be.visible')
cy.realPress('Tab')
cy.getByDataTest('calendar').should('not.exist')
})
it('esc', () => {
cy.visit(`/#/${map.id}`, EXTENDED_TIMEOUT)
cy.get('canvas', EXTENDED_TIMEOUT).should('be.visible')

// Layer popover
cy.getByDataTest('add-layer-button').click()
cy.getByDataTest('addlayerpopover').should('be.visible')
cy.realPress('Escape')
cy.getByDataTest('addlayerpopover').should('not.exist')

// Manage layer sources modal
cy.getByDataTest('add-layer-button').click()
cy.getByDataTest('managelayersources-button').click()
cy.getByDataTest('managelayersourcesmodal').should('be.visible')
cy.realPress('Escape')
cy.getByDataTest('managelayersourcesmodal').should('not.exist')

// Download mode
cy.getByDataTest('dhis2-analytics-hovermenubar')
.find('button')
.contains('Download')
.click()
cy.getByDataTest('download-settings').should('be.visible')
cy.realPress('Escape')
cy.getByDataTest('download-settings').should('not.exist')

// Layer edit
cy.getByDataTest('layer-edit-button').click()
cy.getByDataTest('layeredit').should('be.visible')
cy.get('[data-test="indicatorgroupselect"]').click()
cy.contains(alt.group).click()
cy.get('[data-test="indicatorselect"]').click()
cy.contains(alt.name).click()
cy.realPress('Escape')
cy.getByDataTest('layeredit').should('not.exist')
cy.getByDataTest('layercard')
.contains(map.cardTitle, { timeout: 50000 })
.should('be.visible')

// StartEndDate
cy.getByDataTest('layer-edit-button').click()
cy.getByDataTest('layeredit').should('be.visible')
})
})
112 changes: 86 additions & 26 deletions cypress/integration/layers/eventlayer.cy.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,51 @@
import { EventLayer } from '../../elements/event_layer.js'
import { EXTENDED_TIMEOUT } from '../../support/util.js'
import { CURRENT_YEAR, EXTENDED_TIMEOUT } from '../../support/util.js'

const programE2E = {
name: 'E2E program',
stage: 'Stage 1 - Repeatable',
de: 'E2E - Yes/no',
options: ['Yes', 'No', 'Not set'],
}

const programIP = {
name: 'Inpatient morbidity and mortality',
stage: 'Inpatient morbidity and mortality',
startDate: `${CURRENT_YEAR - 5}-00-00`,
endDate: `${CURRENT_YEAR}-11-30`,
periodText: `Jan 1, ${CURRENT_YEAR - 5} - Nov 30, ${CURRENT_YEAR}`,
ous: ['Bombali', 'Bo'],
}

context('Event Layers', () => {
beforeEach(() => {
cy.visit('/', EXTENDED_TIMEOUT)
cy.visit('/')
})

const Layer = new EventLayer()

it('adds an event layer and applies style for boolean data element', () => {
Layer.openDialog('Events')
.selectProgram(programE2E.name)
.validateStage(programE2E.stage)
.selectTab('Style')

cy.getByDataTest('style-by-data-element-select').click()

cy.getByDataTest('dhis2-uicore-singleselectoption')
.contains(programE2E.de)
.click()

cy.getByDataTest('dhis2-uicore-modalactions')
.contains('Add layer')
.click()

Layer.validateDialogClosed(true)

Layer.validateCardTitle(programE2E.stage)
Layer.validateCardItems(programE2E.options)
})

it('shows error if no program selected', () => {
Layer.openDialog('Events').addToMap()

Expand All @@ -16,47 +54,69 @@ context('Event Layers', () => {
cy.contains('Program is required').should('be.visible')
})

it('adds an event layer', () => {
it('shows error if no endDate is specified', () => {
Layer.openDialog('Events')
.selectProgram('Inpatient morbidity and mortality')
.validateStage('Inpatient morbidity and mortality')
.selectProgram(programIP.name)
.validateStage(programIP.stage)
.selectTab('Period')
.selectPeriodType({ periodType: 'Start/end dates' })
.typeEndDate()
.addToMap()

Layer.validateDialogClosed(false)
cy.contains('End date is invalid').should('be.visible')

Layer.selectTab('Period').typeEndDate('2')

cy.contains('End date is invalid').should('not.exist')
})

it('adds an event layer - relative period', () => {
Layer.openDialog('Events')
.selectProgram(programIP.name)
.validateStage(programIP.stage)
.selectTab('Org Units')
.selectOu('Bombali')
.selectOu('Bo')
.selectOu(programIP.ous[0])
.selectOu(programIP.ous[1])
.addToMap()

Layer.validateDialogClosed(true)

Layer.validateCardTitle('Inpatient morbidity and mortality')
Layer.validateCardTitle(programIP.name)
Layer.validateCardItems(['Event'])
})

it('adds an event layer and applies style for boolean data element', () => {
it('adds an event layer - start-end dates', () => {
Layer.openDialog('Events')
.selectProgram('E2E program')
.validateStage('Stage 1 - Repeatable')
.selectProgram(programIP.name)
.validateStage(programIP.stage)
.selectTab('Period')
.selectPeriodType({ periodType: 'Start/end dates' })
.typeStartDate(programIP.startDate)
.typeEndDate(programIP.endDate)
.selectTab('Org Units')
.selectOu(programIP.ous[0])
.selectOu(programIP.ous[1])
.selectTab('Style')

cy.getByDataTest('style-by-data-element-select').click()

cy.getByDataTest('dhis2-uicore-singleselectoption')
.contains('E2E - Yes/no')
.click()

cy.getByDataTest('dhis2-uicore-modalactions')
.contains('Add layer')
.click()
.selectViewAllEvents()
.addToMap()

Layer.validateDialogClosed(true)

Layer.validateCardTitle('Stage 1 - Repeatable')
Layer.validateCardItems(['Yes', 'No', 'Not set'])
Layer.validateCardTitle(programIP.name).validateCardPeriod(
programIP.periodText
)
Layer.validateCardItems(['Event'])
})

it('opens an event popup', () => {
Layer.openDialog('Events')
.selectProgram('Inpatient morbidity and mortality')
.validateStage('Inpatient morbidity and mortality')
.selectProgram(programIP.name)
.validateStage(programIP.stage)
.selectTab('Period')
.selectPeriodType({ periodType: 'Start/end dates' })
.typeStartDate(programIP.startDate)
.typeEndDate(programIP.endDate)
.selectTab('Style')
.selectViewAllEvents()
.selectTab('Org Units')
Expand Down Expand Up @@ -106,7 +166,7 @@ context('Event Layers', () => {
.contains('Mode of Discharge')
.should('be.visible')

Layer.validateCardTitle('Inpatient morbidity and mortality')
Layer.validateCardTitle(programIP.name)
Layer.validateCardItems(['Event'])
})
})
Loading
Loading