Skip to content
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

feat: prefix time dimension ids with program id when tracked entity output type #480

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
9 changes: 7 additions & 2 deletions src/actions/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,19 @@ export const tSetUiProgram =
(dispatch, getState) => {
const state = getState()
dispatch(acClearUiProgram())
if (sGetUiInputType(state) !== OUTPUT_TYPE_TRACKED_ENTITY) {
const inputType = sGetUiInputType(state)
if (inputType !== OUTPUT_TYPE_TRACKED_ENTITY) {
dispatch(tClearUiProgramRelatedDimensions())
}
program &&
dispatch(
acUpdateUiProgramId(program.id, {
...getProgramAsMetadata(program),
...getDynamicTimeDimensionsMetadata(program, stage),
...getDynamicTimeDimensionsMetadata(
program,
stage,
inputType
),
})
)
stage && dispatch(acUpdateUiProgramStageId(stage.id))
Expand Down
22 changes: 18 additions & 4 deletions src/components/Dialogs/PeriodDimension/PeriodDimension.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@ import {
SYSTEM_SETTINGS_HIDE_BIMONTHLY_PERIODS,
} from '../../../modules/systemSettings.js'
import { USER_SETTINGS_UI_LOCALE } from '../../../modules/userSettings.js'
import {
extractDimensionIdParts,
formatDimensionId,
} from '../../../modules/utils.js'
import {
sGetDimensionIdsFromLayout,
sGetUiItemsByDimension,
sGetUiInputType,
} from '../../../reducers/ui.js'
import DimensionModal from '../DimensionModal.js'
import styles from './PeriodDimension.module.css'
Expand Down Expand Up @@ -118,18 +123,27 @@ export const PeriodDimension = ({ dimension, onClose }) => {
: OPTION_PRESETS
)

const outputType = useSelector(sGetUiInputType)

const { programId } = extractDimensionIdParts(dimension.id, outputType)

const updatePeriodDimensionItems = (items) => {
const { uiItems, metadata } = items.reduce(
(acc, item) => {
acc.uiItems.push(item.id)
const id = formatDimensionId({
dimensionId: item.id,
programId,
outputType,
})
acc.uiItems.push(id)

if (isStartEndDate(item.id)) {
acc.metadata[item.id] = {
id: item.id,
acc.metadata[id] = {
id,
name: formatStartEndDate(item.id),
}
} else {
acc.metadata[item.id] = item
acc.metadata[id] = { ...item, id }
}

return acc
Expand Down
85 changes: 85 additions & 0 deletions src/modules/__tests__/metadata.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { getDynamicTimeDimensionsMetadata } from '../metadata.js'

describe('getDynamicTimeDimensionsMetadata', () => {
it('should return correct dynamic time dimensions metadata when inputType is OUTPUT_TYPE_TRACKED_ENTITY', () => {
const program = {
id: 'programId',
displayEnrollmentDateLabel: 'Custom Enrollment Date',
displayIncidentDateLabel: 'Custom Incident Date',
}
const stage = { displayExecutionDateLabel: 'Stage Execution Date' }
const inputType = 'TRACKED_ENTITY_INSTANCE' // OUTPUT_TYPE_TRACKED_ENTITY

const result = getDynamicTimeDimensionsMetadata(
program,
stage,
inputType
)

const expected = {
'programId.eventDate': {
id: 'programId.eventDate',
dimensionType: 'PERIOD',
name: 'Stage Execution Date',
},
'programId.enrollmentDate': {
id: 'programId.enrollmentDate',
dimensionType: 'PERIOD',
name: 'Custom Enrollment Date',
},
'programId.incidentDate': {
id: 'programId.incidentDate',
dimensionType: 'PERIOD',
name: 'Custom Incident Date',
},
'programId.scheduledDate': {
id: 'programId.scheduledDate',
dimensionType: 'PERIOD',
name: 'Scheduled date',
},
}

expect(result).toEqual(expected)
})

it('should return correct dynamic time dimensions metadata when inputType is not OUTPUT_TYPE_TRACKED_ENTITY', () => {
const program = {
id: 'programId',
displayEnrollmentDateLabel: 'Program Enrollment Date',
displayIncidentDateLabel: 'Custom Incident Date',
}
const stage = { displayExecutionDateLabel: 'Stage Execution Date' }
const inputType = 'OTHER_TYPE'

const result = getDynamicTimeDimensionsMetadata(
program,
stage,
inputType
)

const expected = {
eventDate: {
id: 'eventDate',
dimensionType: 'PERIOD',
name: 'Stage Execution Date',
},
enrollmentDate: {
id: 'enrollmentDate',
dimensionType: 'PERIOD',
name: 'Program Enrollment Date',
},
incidentDate: {
id: 'incidentDate',
dimensionType: 'PERIOD',
name: 'Custom Incident Date',
},
scheduledDate: {
id: 'scheduledDate',
dimensionType: 'PERIOD',
name: 'Scheduled date',
},
}

expect(result).toEqual(expected)
})
})
34 changes: 17 additions & 17 deletions src/modules/__tests__/timeDimensions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('ER > Dimensions > getTimeDimensionName', () => {
}
Object.values(getTimeDimensions()).forEach((dimension) => {
expect(getTimeDimensionName(dimension, program, stage)).toEqual(
dimension.name
dimension.defaultName
)
})
})
Expand All @@ -57,16 +57,16 @@ describe('ER > Dimensions > getTimeDimensionName', () => {

expect(
getTimeDimensionName(eventDateDimension, program, stage)
).toEqual(stage.displayExecutionDateLabel)
).toEqual('le event date')
expect(
getTimeDimensionName(enrollmentDateDimension, program, stage)
).toEqual(enrollmentDateDimension.name)
).toEqual('Enrollment date')
expect(
getTimeDimensionName(incidentDateDimension, program, stage)
).toEqual(incidentDateDimension.name)
).toEqual('Incident date')
expect(
getTimeDimensionName(scheduledDateDimension, program, stage)
).toEqual(scheduledDateDimension.name)
).toEqual('Scheduled date')
})
it('uses displayEnrollmentDateLabel from program for enrollment date', () => {
const program = {
Expand All @@ -85,16 +85,16 @@ describe('ER > Dimensions > getTimeDimensionName', () => {

expect(
getTimeDimensionName(eventDateDimension, program, stage)
).toEqual(eventDateDimension.name)
).toEqual('Event date')
expect(
getTimeDimensionName(enrollmentDateDimension, program, stage)
).toEqual(program.displayEnrollmentDateLabel)
).toEqual('le enrollment date')
expect(
getTimeDimensionName(incidentDateDimension, program, stage)
).toEqual(incidentDateDimension.name)
).toEqual('Incident date')
expect(
getTimeDimensionName(scheduledDateDimension, program, stage)
).toEqual(scheduledDateDimension.name)
).toEqual('Scheduled date')
})
it('uses displayDueDateLabel from stage for scheduled date', () => {
const program = {
Expand All @@ -113,16 +113,16 @@ describe('ER > Dimensions > getTimeDimensionName', () => {

expect(
getTimeDimensionName(eventDateDimension, program, stage)
).toEqual(eventDateDimension.name)
).toEqual('Event date')
expect(
getTimeDimensionName(enrollmentDateDimension, program, stage)
).toEqual(enrollmentDateDimension.name)
).toEqual('Enrollment date')
expect(
getTimeDimensionName(incidentDateDimension, program, stage)
).toEqual(incidentDateDimension.name)
).toEqual('Incident date')
expect(
getTimeDimensionName(scheduledDateDimension, program, stage)
).toEqual(stage.displayDueDateLabel)
).toEqual('le due date')
})
it('uses displayIncidentDateLabel from program for incident date', () => {
const program = {
Expand All @@ -141,16 +141,16 @@ describe('ER > Dimensions > getTimeDimensionName', () => {

expect(
getTimeDimensionName(eventDateDimension, program, stage)
).toEqual(eventDateDimension.name)
).toEqual('Event date')
expect(
getTimeDimensionName(enrollmentDateDimension, program, stage)
).toEqual(enrollmentDateDimension.name)
).toEqual('Enrollment date')
expect(
getTimeDimensionName(incidentDateDimension, program, stage)
).toEqual(program.displayIncidentDateLabel)
).toEqual('le incident date')
expect(
getTimeDimensionName(scheduledDateDimension, program, stage)
).toEqual(scheduledDateDimension.name)
).toEqual('Scheduled date')
})
})

Expand Down
17 changes: 14 additions & 3 deletions src/modules/metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import i18n from '@dhis2/d2-i18n'
import { getMainDimensions, getCreatedDimension } from './mainDimensions.js'
import { getProgramDimensions } from './programDimensions.js'
import { getTimeDimensions, getTimeDimensionName } from './timeDimensions.js'
import { formatDimensionId } from './utils.js'
import { OUTPUT_TYPE_TRACKED_ENTITY, getStatusNames } from './visualization.js'

const formatObject = (object) =>
Expand Down Expand Up @@ -70,10 +71,20 @@ export const getProgramAsMetadata = (program) => ({
[program.id]: program,
})

export const getDynamicTimeDimensionsMetadata = (program, stage) => ({
export const getDynamicTimeDimensionsMetadata = (
program,
stage,
inputType
) => ({
...Object.values(getTimeDimensions()).reduce((acc, dimension) => {
acc[dimension.id] = {
id: dimension.id,
const id = formatDimensionId({
dimensionId: dimension.id,
programId: program?.id,
outputType: inputType,
})

acc[id] = {
id,
dimensionType: dimension.dimensionType,
name: getTimeDimensionName(dimension, program, stage),
}
Expand Down
12 changes: 6 additions & 6 deletions src/modules/timeDimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,43 +21,43 @@ export const getTimeDimensions = () => ({
[DIMENSION_ID_EVENT_DATE]: {
id: DIMENSION_ID_EVENT_DATE,
dimensionType: DIMENSION_TYPE_PERIOD,
name: i18n.t('Event date'),
defaultName: i18n.t('Event date'),
nameParentProperty: NAME_PARENT_PROPERTY_STAGE,
nameProperty: 'displayExecutionDateLabel',
},
[DIMENSION_ID_ENROLLMENT_DATE]: {
id: DIMENSION_ID_ENROLLMENT_DATE,
dimensionType: DIMENSION_TYPE_PERIOD,
name: i18n.t('Enrollment date'),
defaultName: i18n.t('Enrollment date'),
nameParentProperty: NAME_PARENT_PROPERTY_PROGRAM,
nameProperty: 'displayEnrollmentDateLabel',
},
[DIMENSION_ID_INCIDENT_DATE]: {
id: DIMENSION_ID_INCIDENT_DATE,
dimensionType: DIMENSION_TYPE_PERIOD,
name: i18n.t('Incident date'),
defaultName: i18n.t('Incident date'),
nameParentProperty: NAME_PARENT_PROPERTY_PROGRAM,
nameProperty: 'displayIncidentDateLabel',
},
[DIMENSION_ID_SCHEDULED_DATE]: {
id: DIMENSION_ID_SCHEDULED_DATE,
dimensionType: DIMENSION_TYPE_PERIOD,
name: i18n.t('Scheduled date'),
defaultName: i18n.t('Scheduled date'),
nameParentProperty: NAME_PARENT_PROPERTY_STAGE,
nameProperty: 'displayDueDateLabel',
},
})

export const getTimeDimensionName = (dimension, program, stage) => {
if (!dimension.nameParentProperty || !program) {
return dimension.name
return dimension.defaultName
}
const name =
dimension.nameParentProperty === NAME_PARENT_PROPERTY_PROGRAM
? program[dimension.nameProperty]
: stage?.[dimension.nameProperty]

return name || dimension.name
return name || dimension.defaultName
}

export const getHiddenTimeDimensions = (inputType, program, stage) => {
Expand Down
32 changes: 24 additions & 8 deletions src/reducers/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
} from '../modules/programDimensions.js'
import { getHiddenTimeDimensions } from '../modules/timeDimensions.js'
import { getAdaptedUiByType, getUiFromVisualization } from '../modules/ui.js'
import { formatDimensionId, extractDimensionIdParts } from '../modules/utils.js'
import {
OUTPUT_TYPE_EVENT,
OUTPUT_TYPE_TRACKED_ENTITY,
Expand Down Expand Up @@ -489,17 +490,24 @@ export const useProgramDimensions = () => {
const programId = useSelector(sGetUiProgramId)
const programStageId = useSelector(sGetUiProgramStageId)

const getId = (dimensionId) =>
formatDimensionId({
dimensionId,
programId,
outputType: inputType,
})

const eventDateDim = useSelector((state) =>
sGetMetadataById(state, DIMENSION_ID_EVENT_DATE)
sGetMetadataById(state, getId(DIMENSION_ID_EVENT_DATE))
)
const enrollmentDateDim = useSelector((state) =>
sGetMetadataById(state, DIMENSION_ID_ENROLLMENT_DATE)
sGetMetadataById(state, getId(DIMENSION_ID_ENROLLMENT_DATE))
)
const incidentDateDim = useSelector((state) =>
sGetMetadataById(state, DIMENSION_ID_INCIDENT_DATE)
sGetMetadataById(state, getId(DIMENSION_ID_INCIDENT_DATE))
)
const scheduledDateDim = useSelector((state) =>
sGetMetadataById(state, DIMENSION_ID_SCHEDULED_DATE)
sGetMetadataById(state, getId(DIMENSION_ID_SCHEDULED_DATE))
)

return useMemo(() => {
Expand All @@ -520,10 +528,18 @@ export const useProgramDimensions = () => {
? [scheduledDateDim]
: []),
incidentDateDim,
].filter(
(dimension) =>
!!dimension && !hiddenTimeDimensions.includes(dimension.id)
)
].filter((dimension) => {
// TODO this filter used to return !!dimension && !hiddenTimeDimensions.includes(dimension.id)
// is there a reason the dimension is checked for existence?
if (!dimension) {
return false
}
const { dimensionId } = extractDimensionIdParts(
dimension.id,
inputType
)
return !hiddenTimeDimensions.includes(dimensionId)
})

const programDimensions = Object.values(
getProgramDimensions(
Expand Down
Loading