Skip to content

Commit

Permalink
feat: select a program indicator expression [DHIS2-15645] (#179)
Browse files Browse the repository at this point in the history
* feat: create section component
* feat: android expression validator
* feat: create program tei header component
* feat: handle change tei header
* feat: get expression description
* feat: save in datastore format
* feat: add tests to get expression description
  • Loading branch information
Sharmyn28 committed Jan 27, 2024
1 parent 274a803 commit ef19493
Show file tree
Hide file tree
Showing 16 changed files with 497 additions and 48 deletions.
19 changes: 17 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2023-10-03T11:54:31.751Z\n"
"PO-Revision-Date: 2023-10-03T11:54:31.751Z\n"
"POT-Creation-Date: 2023-10-06T16:23:08.006Z\n"
"PO-Revision-Date: 2023-10-06T16:23:08.006Z\n"

msgid ""
"The initial configuration of the app has been completed and it is now ready "
Expand Down Expand Up @@ -862,6 +862,15 @@ msgstr ""
"apply to all programs a mobile user has access to. Settings specific to "
"individual programs can also be applied."

msgid "TEI Header"
msgstr "TEI Header"

msgid "Advanced options"
msgstr "Advanced options"

msgid "Filter"
msgstr "Filter"

msgid "Enrollment Date"
msgstr "Enrollment Date"

Expand All @@ -877,6 +886,12 @@ msgstr "Event status"
msgid "Follow up"
msgstr "Follow up"

msgid "There are no Program Indicators with valid expressions for Android"
msgstr "There are no Program Indicators with valid expressions for Android"

msgid "Disable elements do not meet Android criteria"
msgstr "Disable elements do not meet Android criteria"

msgid "Enrollment Status"
msgstr "Enrollment Status"

Expand Down
20 changes: 20 additions & 0 deletions src/components/field/Section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { FieldSet, Legend } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './Section.module.css'

export const Section = ({ legend, children }) => (
<div className={styles.container}>
<FieldSet>
<Legend className={styles.legend}>
<span> {legend} </span>
</Legend>
{children}
</FieldSet>
</div>
)

Section.propTypes = {
legend: PropTypes.string,
children: PropTypes.element.isRequired,
}
16 changes: 16 additions & 0 deletions src/components/field/Section.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.legend {
display: inline-block;
padding-bottom: var(--spacers-dp16);
font-size: 15px;
color: var(--colors-grey900);
font-weight: 500;
letter-spacing: 0.2px;
}

.container {
padding: var(--spacers-dp16) 0;
}

.container:not(:last-child) {
margin-bottom: var(--spacers-dp8);
}
1 change: 1 addition & 0 deletions src/components/field/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './OptionalTEISearch'
export * from './PhoneNumberField'
export * from './ProgramCompletionSpinner'
export * from './ReservedValues'
export * from './Section'
export * from './SelectField'
export * from './ShareScreen'
export * from './SmsGateway'
Expand Down
11 changes: 8 additions & 3 deletions src/pages/Appearance/Programs/NewProgramSpecific.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import i18n from '@dhis2/d2-i18n'
import isNil from 'lodash/isNil'
import PropTypes from 'prop-types'
import React, { useState } from 'react'
import { AddNewSetting } from '../../../components/field'
Expand Down Expand Up @@ -49,7 +50,7 @@ const NewProgramSpecific = ({
}

const handleChange = (e, key) => {
if (typeof key === 'string') {
if (key === 'id') {
const states = programHasCategoryCombo(e.selected, programList)
? createInitialSpecificValues('')
: createInitialValues('')
Expand All @@ -67,9 +68,13 @@ const NewProgramSpecific = ({
setTrackerProgram(isTrackerProgram(e.selected, programList))
setDisableSave(false)
} else {
if (isProgramConfiguration(e.name)) {
if (isProgramConfiguration(e.name || key)) {
const spinnerSettings = !isNil(e.name)
? { ...spinner, [e.name]: e.checked }
: { ...spinner, [key]: e.selected }

setSpinner({
...spinner,
...spinnerSettings,
[e.name]: e.checked,
id: specificSettings.id,
name: specificSettings.name,
Expand Down
28 changes: 28 additions & 0 deletions src/pages/Appearance/Programs/ProgramQueries.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useDataQuery } from '@dhis2/app-runtime'

/**
* Query to get program list with attributes and indicators
* */

const programQuery = {
programs: {
resource: 'programs',
params: {
fields: [
'id',
'name',
'programTrackedEntityAttributes[id,trackedEntityAttribute[id,name,valueType]]',
'programIndicators[id,name,expression]',
],
paging: 'false',
},
},
}

export const useGetPrograms = () => {
const { data } = useDataQuery(programQuery)

return {
programs: data && data.programs?.programs,
}
}
3 changes: 2 additions & 1 deletion src/pages/Appearance/Programs/ProgramsAppearance.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
createSpecificValues,
prepareSettingsSaveDataStore,
prepareSpinnerPreviousSpinner,
prepareSpinnerSettingsDataStore,
removeAttributes,
} from './helper'
import ProgramGlobalSettings from './ProgramGlobalSettings'
Expand Down Expand Up @@ -86,7 +87,7 @@ const ProgramsAppearance = () => {
...spinnerGlobal,
},
specificSettings: {
...prepareSettingsSaveDataStore(spinnerSpecific),
...prepareSpinnerSettingsDataStore(spinnerSpecific),
},
},
completionSpinner: {
Expand Down
71 changes: 43 additions & 28 deletions src/pages/Appearance/Programs/SpecificSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {
HideFormSections,
OptionalTEISearch,
ProgramCompletionSpinner,
Section,
} from '../../../components/field'
import { TableHeader } from '../../../components/table'
import Wrapper from '../../../components/Wrapper'
import { TableSettings } from './TableSettings'
import { TeiHeader } from './TeiHeader'

const SpecificSettings = ({
hasCategoryCombo,
Expand All @@ -21,37 +23,50 @@ const SpecificSettings = ({
<>
<Wrapper>
<div>
<ProgramCompletionSpinner
handleChange={handleSettings}
settings={spinnerSettings}
/>
<Section legend={i18n.t('TEI Header')}>
<TeiHeader
handleChange={handleSettings}
settings={spinnerSettings}
program={specificSettings.id}
/>
</Section>

<OptionalTEISearch
isTrackerProgram={isTrackerProgram}
handleChange={handleSettings}
settings={spinnerSettings}
/>
<Section legend={i18n.t('Advanced options')}>
<>
<ProgramCompletionSpinner
handleChange={handleSettings}
settings={spinnerSettings}
/>

<DisableReferral
isTrackerProgram={isTrackerProgram}
handleChange={handleSettings}
settings={spinnerSettings}
/>
<HideFormSections
handleChange={handleSettings}
settings={spinnerSettings}
/>
</div>
</Wrapper>
<OptionalTEISearch
isTrackerProgram={isTrackerProgram}
handleChange={handleSettings}
settings={spinnerSettings}
/>

<Wrapper>
<div>
<TableHeader title={i18n.t('Show Filter')} />
<TableSettings
type={hasCategoryCombo ? 'ProgramCategory' : 'Program'}
states={specificSettings}
handleChange={handleSettings}
/>
<DisableReferral
isTrackerProgram={isTrackerProgram}
handleChange={handleSettings}
settings={spinnerSettings}
/>
<HideFormSections
handleChange={handleSettings}
settings={spinnerSettings}
/>
</>
</Section>
<Section legend={i18n.t('Filter')}>
<>
<TableHeader title={i18n.t('Show Filter')} />
<TableSettings
type={
hasCategoryCombo ? 'ProgramCategory' : 'Program'
}
states={specificSettings}
handleChange={handleSettings}
/>
</>
</Section>
</div>
</Wrapper>
</>
Expand Down
34 changes: 20 additions & 14 deletions src/pages/Appearance/Programs/SpecificTableAction.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import i18n from '@dhis2/d2-i18n'
import isNil from 'lodash/isNil'
import PropTypes from 'prop-types'
import React, { useState } from 'react'
import DialogDelete from '../../../components/dialog/DialogDelete'
Expand Down Expand Up @@ -67,20 +68,25 @@ const SpecificTableAction = ({
handleCloseEdit()
}

const handleChange = (e) => {
isProgramConfiguration(e.name)
? setSpinner({
...spinner,
[e.name]: e.checked,
id: specificSetting.id,
})
: setSpecificSetting({
...specificSetting,
[e.name]: {
filter: e.checked,
sort: e.checked,
},
})
const handleChange = (e, key) => {
if (isProgramConfiguration(e.name || key)) {
const spinnerSettings = !isNil(e.name)
? { ...spinner, [e.name]: e.checked }
: { ...spinner, [key]: e.selected }

setSpinner({
...spinnerSettings,
id: specificSetting.id,
})
} else {
setSpecificSetting({
...specificSetting,
[e.name]: {
filter: e.checked,
sort: e.checked,
},
})
}
}

return (
Expand Down
Loading

0 comments on commit ef19493

Please sign in to comment.