Skip to content

Commit

Permalink
fix: display date values in calendar in audits, clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
tomzemp committed Oct 18, 2024
1 parent c07bd0e commit 1da7887
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 10 deletions.
30 changes: 28 additions & 2 deletions src/data-workspace/data-details-sidebar/audit-log.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useConfig } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import {
CircularLoader,
Expand All @@ -17,6 +18,8 @@ import {
ExpandableUnit,
useConnectionStatus,
DateText,
convertFromIso8601ToString,
VALUE_TYPES,
} from '../../shared/index.js'
import styles from './audit-log.module.css'
import useDataValueContext from './use-data-value-context.js'
Expand All @@ -29,6 +32,8 @@ export default function AuditLog({ item }) {
const { open, setOpen, openRef } = useOpenState(item)
const dataValueContext = useDataValueContext(item, openRef.current)
const timeZone = Intl.DateTimeFormat()?.resolvedOptions()?.timeZone
const { systemInfo = {} } = useConfig()
const { calendar = 'gregory' } = systemInfo

if (!offline && (!open || dataValueContext.isLoading)) {
return (
Expand Down Expand Up @@ -98,15 +103,35 @@ export default function AuditLog({ item }) {
{audits.map((audit) => {
const {
modifiedBy: user,
previousValue,
value,
previousValue: nonParsedPreviousValue,
value: nonParsedValue,
created,
auditType,
dataElement: de,
categoryOptionCombo: coc,
period: pe,
orgUnit: ou,
} = audit

const value = [
VALUE_TYPES.DATETIME,
VALUE_TYPES.DATE,
].includes(item.valueType)
? convertFromIso8601ToString(
nonParsedValue,
calendar
)
: nonParsedValue
const previousValue = [
VALUE_TYPES.DATETIME,
VALUE_TYPES.DATE,
].includes(item.valueType)
? convertFromIso8601ToString(
nonParsedPreviousValue,
calendar
)
: nonParsedPreviousValue

const key = `${de}-${pe}-${ou}-${coc}-${created}`

return (
Expand Down Expand Up @@ -160,6 +185,7 @@ AuditLog.propTypes = {
categoryOptionCombo: PropTypes.string.isRequired,
dataElement: PropTypes.string.isRequired,
comment: PropTypes.string,
valueType: PropTypes.string,
}).isRequired,
}

Expand Down
159 changes: 158 additions & 1 deletion src/data-workspace/data-details-sidebar/audit-log.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
import { useConfig } from '@dhis2/app-runtime'
import { waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import React from 'react'
import { render } from '../../test-utils/index.js'
import AuditLog from './audit-log.js'
import useDataValueContext from './use-data-value-context.js'

jest.mock('@dhis2/app-runtime', () => ({
...jest.requireActual('@dhis2/app-runtime'),
useConfig: jest.fn(() => ({
systemInfo: { serverTimeZoneId: 'Etc/UTC', calendar: 'gregory' },
})),
}))

jest.mock('./use-data-value-context.js', () => ({
__esModule: true,
default: jest.fn(),
Expand All @@ -18,6 +26,7 @@ describe('<AuditLog />', () => {
}

afterEach(() => {
jest.clearAllMocks()
useDataValueContext.mockClear()
})

Expand Down Expand Up @@ -79,7 +88,7 @@ describe('<AuditLog />', () => {
auditType: 'UPDATE',
created: new Date('2021-02-01').toISOString(),
modifiedBy: 'Firstname2 Lastname2',
prevValue: '19',
previousValue: '19',
value: '21',
},
{
Expand Down Expand Up @@ -140,4 +149,152 @@ describe('<AuditLog />', () => {
getByText('audit dates are given in UTC time')
).toBeInTheDocument()
})

it('renders the date/datetime values in system calendar (ethiopian)', async () => {
useConfig.mockImplementation(() => ({
systemInfo: {
calendar: 'ethiopian',
},
}))
const audits = [
{
auditType: 'DELETE',
created: new Date('2021-03-01').toISOString(),
modifiedBy: 'Firstname Lastname',
value: '2021-09-10',
},
{
auditType: 'UPDATE',
created: new Date('2021-02-01').toISOString(),
modifiedBy: 'Firstname2 Lastname2',
previousValue: '2021-09-10',
value: '2021-09-11',
},
]

const dateItem = {
categoryOptionCombo: 'coc-id',
dataElement: 'de-id',
comment: 'This is a comment',
valueType: 'DATE',
}

const data = { audits }
useDataValueContext.mockImplementation(() => ({
isLoading: false,
data,
}))

const { getByRole, getAllByRole, queryByRole, container } = render(
<AuditLog item={dateItem} />
)

// Expand and wait for data to load
userEvent.click(container.querySelector('summary'))
await waitFor(() => {
expect(getByRole('group')).toHaveAttribute('open')
expect(queryByRole('progressbar')).not.toBeInTheDocument()
})

// the number of rows is: the length of audits + 1 (for header row)
const auditRows = getAllByRole('row')

expect(auditRows).toHaveLength(audits.length + 1)

const firstChangeName = within(auditRows[1]).getByText(
'Firstname Lastname',
{}
)
expect(firstChangeName).toBeInTheDocument()
const firstChangeValue = within(auditRows[1]).getByText(
'2013-13-05',
{}
)
expect(firstChangeValue).toBeInTheDocument()

const secondChangeName = within(auditRows[2]).getByText(
'Firstname2 Lastname2',
{}
)
expect(secondChangeName).toBeInTheDocument()
const secondChangeValue = within(auditRows[2]).getByText(
'2014-01-01',
{}
)
expect(secondChangeValue).toBeInTheDocument()
})

it('renders the date/datetime values in system calendar (gregorian)', async () => {
useConfig.mockImplementation(() => ({
systemInfo: {
calendar: 'gregory',
},
}))
const audits = [
{
auditType: 'DELETE',
created: new Date('2021-03-01').toISOString(),
modifiedBy: 'Firstname Lastname',
value: '2021-09-10',
},
{
auditType: 'UPDATE',
created: new Date('2021-02-01').toISOString(),
modifiedBy: 'Firstname2 Lastname2',
previousValue: '2021-09-10',
value: '2021-09-11',
},
]

const dateItem = {
categoryOptionCombo: 'coc-id',
dataElement: 'de-id',
comment: 'This is a comment',
valueType: 'DATE',
}

const data = { audits }
useDataValueContext.mockImplementation(() => ({
isLoading: false,
data,
}))

const { getByRole, getAllByRole, queryByRole, container } = render(
<AuditLog item={dateItem} />
)

// Expand and wait for data to load
userEvent.click(container.querySelector('summary'))
await waitFor(() => {
expect(getByRole('group')).toHaveAttribute('open')
expect(queryByRole('progressbar')).not.toBeInTheDocument()
})

// the number of rows is: the length of audits + 1 (for header row)
const auditRows = getAllByRole('row')

expect(auditRows).toHaveLength(audits.length + 1)

const firstChangeName = within(auditRows[1]).getByText(
'Firstname Lastname',
{}
)
expect(firstChangeName).toBeInTheDocument()
const firstChangeValue = within(auditRows[1]).getByText(
'2021-09-10',
{}
)
expect(firstChangeValue).toBeInTheDocument()

const secondChangeName = within(auditRows[2]).getByText(
'Firstname2 Lastname2',
{}
)
expect(secondChangeName).toBeInTheDocument()
const secondChangeValue = within(auditRows[2]).getByText(
'2021-09-11',
{}
)
expect(secondChangeValue).toBeInTheDocument()
})
})
8 changes: 2 additions & 6 deletions src/data-workspace/inputs/date-input.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,7 @@ describe('date input field', () => {

// 2021-04-22 ISO = 2078-01-09 nepali
const { getByRole } = render(
<FormWrapper
initialValues={{ [DE]: { [COC]: '2021-04-22' } }}
>
<FormWrapper initialValues={{ [DE]: { [COC]: '2021-04-22' } }}>
<DateInput {...props} />
</FormWrapper>
)
Expand Down Expand Up @@ -269,9 +267,7 @@ describe('date input field', () => {

// 2021-04-22 ISO = 2013-08-14 ethiopian
const { getByRole } = render(
<FormWrapper
initialValues={{ [DE]: { [COC]: '2021-04-22' } }}
>
<FormWrapper initialValues={{ [DE]: { [COC]: '2021-04-22' } }}>
<DateInput {...props} />
</FormWrapper>
)
Expand Down
10 changes: 10 additions & 0 deletions src/shared/date/date-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ const formatDate = (date, withoutTimeStamp) => {
}

export const convertFromIso8601ToString = (date, calendar) => {
// skip if there is no date
if (!date) {
return undefined
}

// return without conversion if already a gregory date
if (GREGORY_CALENDARS.includes(calendar)) {
return date
Expand All @@ -55,6 +60,11 @@ export const convertFromIso8601ToString = (date, calendar) => {
}

export const convertToIso8601ToString = (date, calendar) => {
// skip if there is no date
if (!date) {
return undefined
}

// return without conversion if already a gregory date
if (GREGORY_CALENDARS.includes(calendar)) {
return date
Expand Down
2 changes: 1 addition & 1 deletion src/shared/date/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ export {
isDateAGreaterThanDateB,
isDateALessThanDateB,
} from './date-utils.js'
export { DateText } from './date-text.js'
export { DateText } from './date-text.js'

0 comments on commit 1da7887

Please sign in to comment.