Skip to content

Commit

Permalink
feedbackWidget, infoWidget
Browse files Browse the repository at this point in the history
  • Loading branch information
zepto5 committed Jul 25, 2018
1 parent 36014b9 commit b863946
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 69 deletions.
Binary file added .vs/slnx.sqlite
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export default {
SHOW_WARNING_ONCOMPLETE: 'WARNINGONCOMPLETE',
HIDE_SECTION: 'HIDESECTION',
MAKE_COMPULSORY: 'SETMANDATORYFIELD',
DISPLAY_TEXT: 'DISPLAYTEXT',
};
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ export default function getRulesEffectsProcessor(
};
}

function processDisplayText(effect: ProgramRuleEffect): ?any {
return {
type: actions.DISPLAY_TEXT,
id: effect.location,
message: `${effect.content} ${effect.data ? effect.data : ''}`,
};
}

const mapActionsToProcessor = {
[actions.ASSIGN_VALUE]: processAssignValue,
[actions.HIDE_FIELD]: processHideField,
Expand All @@ -159,6 +167,7 @@ export default function getRulesEffectsProcessor(
[actions.SHOW_WARNING_ONCOMPLETE]: processShowWarningOnComplete,
[actions.HIDE_SECTION]: processHideSection,
[actions.MAKE_COMPULSORY]: processMakeCompulsory,
[actions.DISPLAY_TEXT]: processDisplayText,
};

function processRulesEffects(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,34 @@ const styles = theme => ({
button: {
paddingRight: theme.spacing.unit * 2,
},
horizontalContainer: {
horizontalFormContainer: {
display: 'flex',
flexWrap: 'wrap',
alignItems: 'flex-start',
},
verticalDataEntryContainer: {
flexGrow: 1,
},
verticalContainer: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
},
});

type FieldContainer = {
field: React.Element<any>,
placement: $Values<typeof placements>,
};

type DirectionClasses = {
container?: ?string,
dataEntryContainer?: ?string,
infoWidgetsContainer?: ?string,
infoWidgetsInnerContainer?: ?string,
formContainer?: ?string,
}

type Props = {
id: string,
itemId: string,
Expand All @@ -35,6 +51,7 @@ type Props = {
saveButton?: ?React.Element<any>,
cancelButton?: ?React.Element<any>,
fields?: ?Array<FieldContainer>,
infoWidgets?: ?Array<any>,
completionAttempted?: ?boolean,
saveAttempted?: ?boolean,
classes: Object,
Expand Down Expand Up @@ -73,16 +90,18 @@ class DataEntry extends React.Component<Props> {
this.props.onUpdateFieldInner(...args, this.props.id, this.props.itemId, this.props.onUpdateFormField);
}

getClasses = () => {
getClasses = (): DirectionClasses => {
const { classes, formHorizontal } = this.props;
if (formHorizontal) {
return {
ContainerClass: classes.horizontalContainer,
edgeFieldsClass: classes.horizontalEdgeFields,
formClass: classes.horizontalForm,
formContainer: classes.horizontalFormContainer,
infoWidgetsContainer: classes.horizontalWidgetsContainer,
};
}
return {};
return {
container: classes.verticalContainer,
dataEntryContainer: classes.verticalDataEntryContainer,
};
}

handleUpdateFieldAsync = (...args) => {
Expand Down Expand Up @@ -130,74 +149,81 @@ class DataEntry extends React.Component<Props> {
{DataEntry.errorMessages.FORM_FOUNDATION_MISSING}
</div>
);
}
}
const directionClasses = this.getClasses();

const topFields = this.getFieldWithPlacement(placements.TOP);
const bottomFields = this.getFieldWithPlacement(placements.BOTTOM);

const infoWidgets = this.props.infoWidgets;
return (
<div>
<div className={directionClasses.ContainerClass}>
{topFields}
<D2Form
innerRef={(formInstance) => { this.formInstance = formInstance; }}
formFoundation={formFoundation}
id={getDataEntryKey(id, itemId)}
validationAttempted={completionAttempted || saveAttempted}
onUpdateField={this.handleUpdateField}
onUpdateFieldAsync={this.handleUpdateFieldAsync}
{...passOnProps}
/>
{bottomFields}
<div className={directionClasses.container}>
<div className={directionClasses.dataEntryContainer}>
<div className={directionClasses.formContainer}>
{topFields}
<D2Form
innerRef={(formInstance) => { this.formInstance = formInstance; }}
formFoundation={formFoundation}
id={getDataEntryKey(id, itemId)}
validationAttempted={completionAttempted || saveAttempted}
onUpdateField={this.handleUpdateField}
onUpdateFieldAsync={this.handleUpdateFieldAsync}
{...passOnProps}
/>
{bottomFields}
</div>
<div
className={classes.footerBar}
>
{
(() => {
if (completeButton) {
return (
<div
className={classes.button}
>
{ completeButton }
</div>
);
}
return null;
})()
}

{
(() => {
if (saveButton) {
return (
<div
className={classes.button}
>
{ saveButton }
</div>
);
}
return null;
})()
}

{
(() => {
if (cancelButton) {
return (
<div
className={classes.button}
>
{ cancelButton }
</div>
);
}
return null;
})()
}
</div>
</div>
<div
className={classes.footerBar}
>
{
(() => {
if (completeButton) {
return (
<div
className={classes.button}
>
{ completeButton }
</div>
);
}
return null;
})()
}

{
(() => {
if (saveButton) {
return (
<div
className={classes.button}
>
{ saveButton }
</div>
);
}
return null;
})()
}

{
(() => {
if (cancelButton) {
return (
<div
className={classes.button}
>
{ cancelButton }
</div>
);
}
return null;
})()
}
<div className={directionClasses.infoWidgetsContainer}>
<div className={directionClasses.infoWidgetsInnerContainer}>
{infoWidgets}
</div>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// @flow
import * as React from 'react';
import { connect } from 'react-redux';
import getDataEntryKey from '../common/getDataEntryKey';
import withInfoWidget from './withInfoWidget';

type Props = {
feedbackItems: Array<any>,

};

const getFeedbackWidget = () =>
class FeedbackWidgetBuilder extends React.Component<Props> {
renderFeedbackItems = (feedbackItems: any) =>
(<div>
{feedbackItems.displayTexts &&
feedbackItems.displayTexts.map(item => (<div key={item}>{item}</div>))}
</div>)

render = () => {
const { feedbackItems } = this.props;
return (
<div>
{feedbackItems && this.renderFeedbackItems(feedbackItems)}
</div>
);
}
};


const mapStateToProps = (state: ReduxState, props: any) => {
const itemId = state.dataEntries[props.id].itemId;
const key = getDataEntryKey(props.id, itemId);
return {
feedbackItems: state.rulesEffectsFeedback && state.rulesEffectsFeedback[key] ?
state.rulesEffectsFeedback[key] : null,
};
};

const mapDispatchToProps = () => ({});

export default () =>
(InnerComponent: React.ComponentType<any>) =>
// $FlowSuppress
withInfoWidget()(InnerComponent, connect(mapStateToProps, mapDispatchToProps, null, { withRef: true })(getFeedbackWidget()));
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// @flow

import * as React from 'react';

type Props = {
infoWidgets: Array<React.Component<any>>
};

const getInfoWidget = (InnerComponent: React.ComponentType<any>, Widget: React.ComponentType<any>) =>
class InfoWidgetBuilder extends React.Component<Props> {
innerInstance: ?any;
getInfoWidgets = () => {
const infoWidgets = this.props.infoWidgets;
const widget = this.getWidget(infoWidgets ? infoWidgets.length : 0);
return infoWidgets ? [...infoWidgets, widget] : [widget];
};
getWidget = (key: any) =>
(
<Widget
key={key}
{...this.props}
/>)
render = () => {
const { infoWidgets, ...passOnProps } = this.props;

return (
<div>
<InnerComponent
ref={(innerInstance) => { this.innerInstance = innerInstance; }}
infoWidgets={this.getInfoWidgets()}
{...passOnProps}
/>
</div>
);
}
};

export default () =>
(InnerComponent: React.ComponentType<any>, Widget: React.ComponentType<any>) =>
getInfoWidget(InnerComponent, Widget);
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,21 @@ const getSaveButton = (InnerComponent: React.ComponentType<any>, optionFn?: ?Opt
return dataEntryFields;
}

getErrorInstance() {
let currentInstance = this.innerInstance;
let done;
const dataEntryFields = [];
while (!done) {
currentInstance = currentInstance.getWrappedInstance && currentInstance.getWrappedInstance();
if (!currentInstance || currentInstance instanceof DataEntry) {
done = true;
} else if (currentInstance.constructor.name === 'ErrorWidgetBuilder') {
dataEntryFields.push(currentInstance);
}
}
return dataEntryFields;
}

validateDataEntryFields() {
const fieldInstance = this.getDataEntryFieldInstances();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import D2TrueOnly from '../../../../components/FormFields/Generic/D2TrueOnly.com
import withDefaultMessages from '../../../../components/DataEntry/dataEntryField/withDefaultMessages';
import withDefaultFieldContainer from '../../../../components/DataEntry/dataEntryField/withDefaultFieldContainer';
import withDefaultChangeHandler from '../../../../components/DataEntry/dataEntryField/withDefaultChangeHandler';
import withFeedbackWidget from '../../../../components/DataEntry/dataEntryInfoWidgets/withFeedbackWidget';
import withDefaultShouldUpdateInterface from
'../../../../components/DataEntry/dataEntryField/withDefaultShouldUpdateInterface';

Expand Down Expand Up @@ -105,7 +106,8 @@ const buildCompleteFieldSettingsFn = () => {

const ReportDateField = withDataEntryField(buildReportDateSettingsFn())(DataEntry);
const CompleteField = withDataEntryField(buildCompleteFieldSettingsFn())(ReportDateField);
const SaveableDataEntry = withSaveButton(getSaveOptions)(CompleteField);
const FeedbackWidget = withFeedbackWidget()(CompleteField);
const SaveableDataEntry = withSaveButton(getSaveOptions)(FeedbackWidget);
const CancelableDataEntry = withCancelButton(getCancelOptions)(SaveableDataEntry);

type Props = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,16 @@ export const rulesEffectsErrorMessagesDesc = createReducerDescription({
return newState;
},
}, 'rulesEffectsMessages');

export const rulesEffectsFeedbackDesc = createReducerDescription({
[actionTypes.UPDATE_RULES_EFFECTS_EVENT]: (state, action) => {
const newState = { ...state };

const displayTextEffects: { [id: string]: Array<OutputEffect> } = action.payload.rulesEffects && action.payload.rulesEffects[effectActions.DISPLAY_TEXT];
newState[action.payload.formId] = {
displayTexts: displayTextEffects && displayTextEffects.feedback ? displayTextEffects.feedback.map(e => e.message) : null,
};

return newState;
},
}, 'rulesEffectsFeedback', {});
Loading

0 comments on commit b863946

Please sign in to comment.