Skip to content

Commit

Permalink
feat: add dynamic attributes to data & event import page (#68) (DHIS2…
Browse files Browse the repository at this point in the history
…-7495)

Fixes DHIS2-7495
  • Loading branch information
Mohammer5 authored Sep 5, 2019
1 parent f61ee93 commit f9a64bf
Show file tree
Hide file tree
Showing 9 changed files with 288 additions and 58 deletions.
14 changes: 11 additions & 3 deletions src/components/FinalFormComponents/RadioGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,18 @@ const RadioComponent = ({ name, label, value, defaultValue }) => {
)
}

export const RadioGroupContainer = ({ children }) => (
<div className={styles.container}>{children}</div>
)

export const RadioGroupLabel = ({ children }) => (
<span className={styles.label}>{children}</span>
)

export const RadioGroup = ({ label, name, options, defaultValue }) => {
return (
<div className={styles.container}>
<span className={styles.label}>{label}</span>
<RadioGroupContainer>
<RadioGroupLabel>{label}</RadioGroupLabel>

<div className={styles.inputs}>
{options.map(option => (
Expand All @@ -39,7 +47,7 @@ export const RadioGroup = ({ label, name, options, defaultValue }) => {
/>
))}
</div>
</div>
</RadioGroupContainer>
)
}

Expand Down
34 changes: 30 additions & 4 deletions src/components/Inputs/DataElementIdScheme.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,43 @@
import i18n from '@dhis2/d2-i18n'
import React from 'react'
import { RadioGroup } from '../FinalFormComponents/RadioGroup'
import {
RadioGroup,
RadioGroupContainer,
RadioGroupLabel,
} from '../FinalFormComponents/RadioGroup'

export const OPTION_UID = { value: 'UID', label: i18n.t('Uid') }
export const OPTION_CODE = { value: 'CODE', label: i18n.t('Code') }
export const OPTION_NAME = { value: 'NAME', label: i18n.t('Name') }

export const DATA_ELEMENT_ID_SCHEME_DEFAULT_OPTIONS = [
OPTION_UID,
OPTION_CODE,
OPTION_NAME,
]
export const DATA_ELEMENT_ID_SCHEME_KEY = 'dataElementIdScheme'
export const DATA_ELEMENT_ID_SCHEME_DEFAULT_VALUE = OPTION_UID.value

export const DataElementIdScheme = () => (
const dataElementIdSchemeLabel = i18n.t('Data element id scheme')
export const DataElementIdScheme = ({ options }) => (
<RadioGroup
name={DATA_ELEMENT_ID_SCHEME_KEY}
label={i18n.t('Data element id scheme')}
options={[OPTION_UID, OPTION_CODE, OPTION_NAME]}
label={dataElementIdSchemeLabel}
options={options}
/>
)

DataElementIdScheme.propTypes = {
options: RadioGroup.propTypes.options,
}

DataElementIdScheme.defaultProps = {
options: DATA_ELEMENT_ID_SCHEME_DEFAULT_OPTIONS,
}

export const DataElementIdSchemeLoading = () => (
<RadioGroupContainer>
<RadioGroupLabel>{dataElementIdSchemeLabel}</RadioGroupLabel>
{i18n.t('Loading data element id scheme options...')}
</RadioGroupContainer>
)
38 changes: 30 additions & 8 deletions src/components/Inputs/OrgUnitIdScheme.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
import i18n from '@dhis2/d2-i18n'
import React from 'react'
import { RadioGroup } from '../FinalFormComponents/RadioGroup'
import {
RadioGroup,
RadioGroupContainer,
RadioGroupLabel,
} from '../FinalFormComponents/RadioGroup'

export const OPTION_UID = { value: 'UID', label: i18n.t('Uid') }
export const OPTION_CODE = { value: 'CODE', label: i18n.t('Code') }
export const OPTION_NAME = { value: 'NAME', label: i18n.t('Name') }
export const OPTION_HR_IDENTIFIER = {
value: 'ATTRIBUTE:UKNKz1H10EE',
label: i18n.t('HR Identifier'),
}

export const ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS = [
OPTION_UID,
OPTION_CODE,
OPTION_NAME,
]
export const ORG_UNIT_ID_SCHEME_KEY = 'orgUnitIdScheme'
export const ORG_UNIT_ID_SCHEME_DEFAULT_VALUE = OPTION_UID.value

export const OrgUnitIdScheme = () => (
const orgUnitIdSchemeLabel = i18n.t('Org unit id scheme')
export const OrgUnitIdScheme = ({ options }) => (
<RadioGroup
name={ORG_UNIT_ID_SCHEME_KEY}
label={i18n.t('Org unit id scheme')}
options={[OPTION_UID, OPTION_CODE, OPTION_NAME]}
label={orgUnitIdSchemeLabel}
options={options}
/>
)

OrgUnitIdScheme.propTypes = {
options: RadioGroup.propTypes.options,
}

OrgUnitIdScheme.defaultProps = {
options: ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS,
}

export const OrgUnitIdSchemeLoading = () => (
<RadioGroupContainer>
<RadioGroupLabel>{orgUnitIdSchemeLabel}</RadioGroupLabel>
{i18n.t('Loading organisation unit id scheme options...')}
</RadioGroupContainer>
)
8 changes: 5 additions & 3 deletions src/pages/export/Data.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,11 @@ class DataExport extends FormBase {

const ConnectedDataExport = connect(
state => ({
loadingAttributes: state.attributes.loading,
dataElementAttributes: state.attributes.dataElement,
orgUnitAttributes: state.attributes.organisationUnit,
loadingAttributes:
state.attributes.dataElement.loading ||
state.attributes.organisationUnit.loading,
dataElementAttributes: state.attributes.dataElement.data,
orgUnitAttributes: state.attributes.organisationUnit.data,
}),
dispatch => ({
fetchDataElementAttributes: () =>
Expand Down
104 changes: 96 additions & 8 deletions src/pages/import/Data.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Button } from '@dhis2/ui-core'
import { Form } from 'react-final-form'
import React, { useState } from 'react'
import { connect } from 'react-redux'
import React, { useEffect, useState } from 'react'
import cx from 'classnames'
import i18n from '@dhis2/d2-i18n'

import { TaskSummary } from '../../components/TaskSummary'
import { DataElementIdScheme } from '../../components/Inputs/DataElementIdScheme'
import {
DATA_ELEMENT_ID_SCHEME_DEFAULT_OPTIONS,
DataElementIdScheme,
DataElementIdSchemeLoading,
} from '../../components/Inputs/DataElementIdScheme'
import { DataIcon } from '../../components/Icon'
import { DryRun } from '../../components/Inputs/DryRun'
import { Error } from '../../components/Error'
Expand All @@ -16,7 +20,11 @@ import { FormFooter } from '../../components/FormSections/FormFooter'
import { FormHeader } from '../../components/FormSections/FormHeader'
import { IdScheme } from '../../components/Inputs/idScheme'
import { MoreOptions } from '../../components/FormSections/MoreOptions'
import { OrgUnitIdScheme } from '../../components/Inputs/OrgUnitIdScheme'
import {
ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS,
OrgUnitIdScheme,
OrgUnitIdSchemeLoading,
} from '../../components/Inputs/OrgUnitIdScheme'
import { PreheatCache } from '../../components/Inputs/PreheatCache'
import { Progress } from '../../components/Loading/Progress'
import {
Expand All @@ -25,14 +33,43 @@ import {
} from '../../components/Inputs/SkipAudit'
import { SkipExistingCheck } from '../../components/Inputs/SkipExistingCheck'
import { Strategy } from '../../components/Inputs/Strategy'
import { WithAuthority } from '../../components/WithAuthority'
import { TaskSummary } from '../../components/TaskSummary'
import { Upload } from '../../components/Inputs/Upload'
import { WithAuthority } from '../../components/WithAuthority'
import { defaultValues, supportedFormats, onSubmit } from './Data/helper'
import {
fetchUniqueDataElementAttributes,
fetchUniqueOrgUnitAttributes,
} from '../../reducers/attributes/thunks'
import { useErrorHandler } from '../../helpers/useErrorHandler'
import stylesForm from '../../components/Form/styles.module.css'
import stylesFormBase from '../../components/FormBase/styles.module.css'

export const DataImport = () => {
const DataImport = ({
dataElementAttributes,
dataElementAttributesLoaded,
loadingDataElementAttributes,
orgUnitAttributes,
orgUnitAttributesLoaded,
loadingOrgUnitAttributes,
fetchDataElementAttributes,
fetchOrganisationUnitAttributes,
}) => {
useEffect(
() => {
if (!dataElementAttributesLoaded) {
fetchDataElementAttributes()
}

if (!orgUnitAttributesLoaded) {
fetchOrganisationUnitAttributes()
}
},

// load attributes on componentDidMount
[] // eslint-disable-line react-hooks/exhaustive-deps
)

const [loading, setLoading] = useState(false)
const [error, setError] = useErrorHandler()
const onSubmitHandler = onSubmit(setLoading, setError)
Expand All @@ -48,6 +85,22 @@ export const DataImport = () => {
/>
)

const dataElementIdSchemeOptions = [
...DATA_ELEMENT_ID_SCHEME_DEFAULT_OPTIONS,
...dataElementAttributes.map(({ id, displayName: label }) => ({
value: `ATTRIBUTE:${id}`,
label,
})),
]

const orgUnitIdSchemeOptions = [
...ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS,
...orgUnitAttributes.map(({ id, displayName: label }) => ({
value: `ATTRIBUTE:${id}`,
label,
})),
]

return (
<Form onSubmit={onSubmitHandler} initialValues={defaultValues}>
{({ handleSubmit, values }) => (
Expand Down Expand Up @@ -80,8 +133,22 @@ export const DataImport = () => {
</WithAuthority>

<MoreOptions>
<DataElementIdScheme />
<OrgUnitIdScheme />
{loadingDataElementAttributes ? (
<DataElementIdSchemeLoading />
) : (
<DataElementIdScheme
options={dataElementIdSchemeOptions}
/>
)}

{loadingOrgUnitAttributes ? (
<OrgUnitIdSchemeLoading />
) : (
<OrgUnitIdScheme
options={orgUnitIdSchemeOptions}
/>
)}

<IdScheme />
<SkipExistingCheck />
</MoreOptions>
Expand All @@ -105,3 +172,24 @@ DataImport.menuIcon = <DataIcon />
DataImport.desc = i18n.t(
'Import data values on the DXF 2 XML, JSON, CSV and PDF formatrant s. DXF 2 is the standard exchange format for DHIS 2.'
)

const ConnectedDataImport = connect(
state => ({
dataElementAttributes: state.attributes.dataElement.data,
dataElementAttributesLoaded: state.attributes.dataElement.loaded,
loadingDataElementAttributes: state.attributes.dataElement.loading,

orgUnitAttributes: state.attributes.organisationUnit.data,
orgUnitAttributesLoaded: state.attributes.organisationUnit.loaded,
loadingOrgUnitAttributes: state.attributes.organisationUnit.loading,
}),
dispatch => ({
fetchDataElementAttributes: () =>
dispatch(fetchUniqueDataElementAttributes()),

fetchOrganisationUnitAttributes: () =>
dispatch(fetchUniqueOrgUnitAttributes()),
})
)(DataImport)

export { ConnectedDataImport as DataImport }
63 changes: 57 additions & 6 deletions src/pages/import/Event.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,63 @@
import { Button } from '@dhis2/ui-core'
import { Form } from 'react-final-form'
import React, { useState } from 'react'
import { connect } from 'react-redux'
import React, { useEffect, useState } from 'react'
import cx from 'classnames'
import i18n from '@dhis2/d2-i18n'

import { TaskSummary } from '../../components/TaskSummary'
import { DryRun } from '../../components/Inputs/DryRun'
import { Error } from '../../components/Error'
import { EventIcon } from '../../components/Icon'
import { EventIdScheme } from '../../components/Inputs/EventIdScheme'
import { FormContent } from '../../components/FormSections/FormContent'
import { FormFooter } from '../../components/FormSections/FormFooter'
import { FormHeader } from '../../components/FormSections/FormHeader'
import { EventIdScheme } from '../../components/Inputs/EventIdScheme'
import { Format } from '../../components/Inputs/Format'
import { OrgUnitIdScheme } from '../../components/Inputs/OrgUnitIdScheme'
import {
ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS,
OrgUnitIdSchemeLoading,
OrgUnitIdScheme,
} from '../../components/Inputs/OrgUnitIdScheme'
import { Progress } from '../../components/Loading/Progress'
import { TaskSummary } from '../../components/TaskSummary'
import { Upload } from '../../components/Inputs/Upload'
import { fetchUniqueOrgUnitAttributes } from '../../reducers/attributes/thunks'
import { supportedFormats, defaultValues, onSubmit } from './Event/helper'
import stylesForm from '../../components/Form/styles.module.css'
import stylesFormBase from '../../components/FormBase/styles.module.css'

export const EventImport = () => {
const EventImport = ({
orgUnitAttributes,
orgUnitAttributesLoaded,
loadingOrgUnitAttributes,
fetchOrganisationUnitAttributes,
}) => {
useEffect(
() => {
if (!orgUnitAttributesLoaded) {
fetchOrganisationUnitAttributes()
}
},

// load attributes on componentDidMount
[] // eslint-disable-line react-hooks/exhaustive-deps
)

const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const onSubmitHandler = onSubmit(setLoading, setError)

if (error) return <Error message={error} onClear={() => setError('')} />
if (loading) return <Progress />

const orgUnitIdSchemeOptions = [
...ORG_UNIT_ID_SCHEME_DEFAULT_OPTIONS,
...orgUnitAttributes.map(({ id, displayName: label }) => ({
value: `ATTRIBUTE:${id}`,
label,
})),
]

return (
<Form onSubmit={onSubmitHandler} initialValues={defaultValues}>
{({ handleSubmit, values }) => (
Expand All @@ -48,7 +78,14 @@ export const EventImport = () => {
<Format options={supportedFormats} />
<DryRun />
<EventIdScheme />
<OrgUnitIdScheme />

{loadingOrgUnitAttributes ? (
<OrgUnitIdSchemeLoading />
) : (
<OrgUnitIdScheme
options={orgUnitIdSchemeOptions}
/>
)}
</FormContent>

<FormFooter>
Expand All @@ -69,3 +106,17 @@ EventImport.desc = i18n.t(
)

EventImport.menuIcon = <EventIcon />

const ConnectedEventImport = connect(
state => ({
orgUnitAttributes: state.attributes.organisationUnit.data,
orgUnitAttributesLoaded: state.attributes.organisationUnit.loaded,
loadingOrgUnitAttributes: state.attributes.organisationUnit.loading,
}),
dispatch => ({
fetchOrganisationUnitAttributes: () =>
dispatch(fetchUniqueOrgUnitAttributes()),
})
)(EventImport)

export { ConnectedEventImport as EventImport }
Loading

0 comments on commit f9a64bf

Please sign in to comment.