Skip to content

Commit

Permalink
feat: add orgunit selector to schedule form
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikmv committed Dec 7, 2024
1 parent 5056f96 commit c93d7b6
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 128 deletions.
13 changes: 8 additions & 5 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: 2024-12-06T11:29:57.874Z\n"
"PO-Revision-Date: 2024-12-06T11:29:57.874Z\n"
"POT-Creation-Date: 2024-12-07T11:18:04.373Z\n"
"PO-Revision-Date: 2024-12-07T11:18:04.373Z\n"

msgid "Choose one or more dates..."
msgstr "Choose one or more dates..."
Expand Down Expand Up @@ -1346,21 +1346,24 @@ msgid_plural "There are {{count}} scheduled event in {{orgUnitName}} on this day
msgstr[0] "There are {{count}} scheduled event in {{orgUnitName}} on this day."
msgstr[1] "There are {{count}} scheduled events in {{orgUnitName}} on this day."

msgid "Schedule date / Due date"
msgstr "Schedule date / Due date"

msgid "Scheduling an event in {{stageName}} for {{programName}} in {{orgUnitName}}"
msgstr "Scheduling an event in {{stageName}} for {{programName}} in {{orgUnitName}}"

msgid "Schedule info"
msgstr "Schedule info"

msgid "Schedule date / Due date"
msgstr "Schedule date / Due date"

msgid "Event notes"
msgstr "Event notes"

msgid "Write a note about this scheduled event"
msgstr "Write a note about this scheduled event"

msgid "Program or stage is invalid"
msgstr "Program or stage is invalid"

msgid "Save note"
msgstr "Save note"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,52 @@
// @flow
import React, { type ComponentType } from 'react';
import { spacersNum } from '@dhis2/ui';
import withStyles from '@material-ui/core/styles/withStyles';
import { DateField } from 'capture-core/components/FormFields/New';
import { InfoBox } from '../InfoBox';
import type { Props } from './scheduleDate.types';
import React from 'react';
import i18n from '@dhis2/d2-i18n';
import { DateField,
withDefaultFieldContainer,
withLabel,
withDisplayMessages,
withInternalChangeHandler,
} from 'capture-core/components/FormFields/New';
import labelTypeClasses from './dataEntryFieldLabels.module.css';
import { convertStringToDateFormat } from '../../../utils/converters/date';


const styles = {
container: {
display: 'flex',
marginTop: spacersNum.dp4,
},
button: {
paddingRight: spacersNum.dp16,
},
const LabelledRequiredDateField = withDefaultFieldContainer()(
withLabel({
onGetCustomFieldLabeClass: () => labelTypeClasses.dateLabel,
})(
withDisplayMessages()(
withInternalChangeHandler()(
DateField,
),
),
),
);

type Props = {
scheduleDate: ?string,
setScheduleDate: (dateString: ?string) => void,
hideDueDate?: boolean,
};

const ScheduleDatePlain = ({
export const ScheduleDate = ({
scheduleDate,
serverScheduleDate,
setScheduleDate,
orgUnit,
serverSuggestedScheduleDate,
eventCountInOrgUnit,
classes,
hideDueDate,
}: Props) => (<>
{!hideDueDate && <div className={classes.container}>
<DateField
value={scheduleDate}
width="100%"
calendarWidth={350}
onSetFocus={() => {}}
onFocus={() => { }}
onRemoveFocus={() => { }}
onBlur={(e) => { setScheduleDate(convertStringToDateFormat(e)); }}
/>
</div>}
<InfoBox
scheduleDate={serverScheduleDate}
suggestedScheduleDate={serverSuggestedScheduleDate}
eventCountInOrgUnit={eventCountInOrgUnit}
orgUnitName={orgUnit?.name}
hideDueDate={hideDueDate}
/>
</>);

export const ScheduleDate: ComponentType<$Diff<Props, CssClasses>> = (withStyles(styles)(ScheduleDatePlain));
}: Props) => (
<>
{!hideDueDate && (
<LabelledRequiredDateField
label={i18n.t('Schedule date / Due date')}
required
value={scheduleDate}
width="100%"
calendarWidth={350}
onSetFocus={() => { }}
onFocus={() => { }}
onRemoveFocus={() => { }}
onBlur={(e) => { setScheduleDate(convertStringToDateFormat(e)); }}
/>
)}
</>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dateLabel {
padding-top: 13px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// @flow
import React from 'react';
import i18n from '@dhis2/d2-i18n';
import {
SingleOrgUnitSelectField,
withDefaultFieldContainer,
withDisplayMessages,
withInternalChangeHandler,
withLabel,
} from '../../FormFields/New';
import labelTypeClasses from './dataEntryFieldLabels.module.css';
import { baseInputStyles } from './commonProps';

type OrgUnitValue = {|
checked: boolean,
id: string,
children: number,
displayName: string,
path: string,
selected: string[],
|}

type Props = {
onSelectOrgUnit: (orgUnit: OrgUnitValue) => void,
onDeselectOrgUnit: () => void,
orgUnit: OrgUnitValue,
};

const OrgUnitFieldForForm = withDefaultFieldContainer()(
withLabel({
onGetCustomFieldLabeClass: () => labelTypeClasses.dateLabel,
})(
withDisplayMessages()(
withInternalChangeHandler()(
SingleOrgUnitSelectField,
),
),
),
);

export const ScheduleOrgUnit = ({
onSelectOrgUnit,
onDeselectOrgUnit,
orgUnit,
}: Props) => {
const handleSelect = (event) => {
onSelectOrgUnit(event);
};

const handleDeselect = () => {
onDeselectOrgUnit();
};

return (
<OrgUnitFieldForForm
label={i18n.t('Organisation unit')}
value={orgUnit}
required
onSelectClick={handleSelect}
onBlur={handleDeselect}
styles={baseInputStyles}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @flow

export const baseInputStyles = {
inputContainerStyle: { flexBasis: 150 },
labelContainerStyle: { flexBasis: 200 },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dateLabel {
padding-top: 13px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { NoteSection } from '../WidgetNote';
import type { Props } from './widgetEventSchedule.types';
import { CategoryOptions } from './CategoryOptions/CategoryOptions.component';
import { Assignee } from './Assignee';
import { ScheduleOrgUnit } from './ScheduleOrgUnit/ScheduleOrgUnit.component';

const styles = () => ({
wrapper: {
Expand Down Expand Up @@ -64,6 +65,7 @@ const WidgetEventSchedulePlain = ({
classes,
scheduleDate,
suggestedScheduleDate,
setScheduledOrgUnit,
serverSuggestedScheduleDate,
notes,
programCategory,
Expand All @@ -75,70 +77,84 @@ const WidgetEventSchedulePlain = ({
assignee,
categoryOptionsError,
...passOnProps
}: Props) => (
<div className={classes.wrapper}>
<DataSection
dataTest="schedule-section"
sectionName={i18n.t('Schedule info')}
>
<div className={classes.fieldWrapper}>
<div className={classes.fieldLabel}>
{displayDueDateLabel ?? i18n.t('Schedule date / Due date', {
interpolation: { escapeValue: false } },
)}
</div>
<div className={classes.fieldContent}>
<ScheduleDate
programId={programId}
stageId={stageId}
orgUnit={orgUnit}
scheduleDate={scheduleDate}
serverSuggestedScheduleDate={serverSuggestedScheduleDate}
{...passOnProps}
/>
</div>
</div>
</DataSection>
{programCategory && <DataSection
dataTest="category-options-section"
sectionName={programCategory.displayName}
>
<CategoryOptions
categories={programCategory.categories}
selectedOrgUnitId={orgUnit?.id}
selectedCategories={selectedCategories}
categoryOptionsError={categoryOptionsError}
onClickCategoryOption={onClickCategoryOption}
onResetCategoryOption={onResetCategoryOption}
required
}: Props) => {
const onSelectOrgUnit = (e: { id: string, displayName: string, path: string }) => {
setScheduledOrgUnit({
id: e.id,
name: e.displayName,
path: e.path,
});
};

const onDeselectOrgUnit = () => {
setScheduledOrgUnit(undefined);
};


return (

<div className={classes.wrapper}>
<DataSection
dataTest="schedule-section"
sectionName={i18n.t('Schedule info')}
>

<ScheduleDate
programId={programId}
stageId={stageId}
scheduleDate={scheduleDate}
serverSuggestedScheduleDate={serverSuggestedScheduleDate}
{...passOnProps}
/>

<ScheduleOrgUnit
orgUnit={orgUnit}
onSelectOrgUnit={onSelectOrgUnit}
onDeselectOrgUnit={onDeselectOrgUnit}
{...passOnProps}
/>
</DataSection>
{programCategory && <DataSection
dataTest="category-options-section"
sectionName={programCategory.displayName}
>
<CategoryOptions
categories={programCategory.categories}
selectedOrgUnitId={orgUnit?.id}
selectedCategories={selectedCategories}
categoryOptionsError={categoryOptionsError}
onClickCategoryOption={onClickCategoryOption}
onResetCategoryOption={onResetCategoryOption}
required
/>
</DataSection>}
<DataSection
dataTest="note-section"
sectionName={i18n.t('Event notes')}
>
<NoteSection
notes={notes}
placeholder={i18n.t('Write a note about this scheduled event')}
handleAddNote={onAddNote}
/>
</DataSection>
{enableUserAssignment && (
<DataSection dataTest="assignee-section" sectionName={i18n.t('Assignee')}>
<Assignee onSet={onSetAssignee} assignee={assignee} />
</DataSection>
)}
<ScheduleButtons
hasChanges={scheduleDate !== suggestedScheduleDate}
onCancel={onCancel}
onSchedule={onSchedule}
/>
</DataSection>}
<DataSection
dataTest="note-section"
sectionName={i18n.t('Event notes')}
>
<NoteSection
notes={notes}
placeholder={i18n.t('Write a note about this scheduled event')}
handleAddNote={onAddNote}
<ScheduleText
programName={programName}
stageName={stageName}
orgUnitName={orgUnit?.name || ''}
/>
</DataSection>
{enableUserAssignment && (
<DataSection dataTest="assignee-section" sectionName={i18n.t('Assignee')}>
<Assignee onSet={onSetAssignee} assignee={assignee} />
</DataSection>
)}
<ScheduleButtons
hasChanges={scheduleDate !== suggestedScheduleDate}
onCancel={onCancel}
onSchedule={onSchedule}
/>
<ScheduleText
programName={programName}
stageName={stageName}
orgUnitName={orgUnit?.name || ''}
/>
</div>
);
</div>
);
};

export const WidgetEventScheduleComponent: ComponentType<$Diff<Props, CssClasses>> = withStyles(styles)(WidgetEventSchedulePlain);
Loading

0 comments on commit c93d7b6

Please sign in to comment.