Skip to content

Commit

Permalink
HTML-705: New <condition/> tag (from Core 2.2).
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmale authored and mks-d committed Jul 25, 2019
1 parent f2d2f63 commit 1b60268
Show file tree
Hide file tree
Showing 10 changed files with 446 additions and 0 deletions.
82 changes: 82 additions & 0 deletions api-2.2/pom.xml
@@ -0,0 +1,82 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openmrs.module</groupId>
<artifactId>htmlformentry</artifactId>
<version>3.10.0-SNAPSHOT</version>
</parent>

<artifactId>htmlformentry-api-2.2</artifactId>
<packaging>jar</packaging>
<name>htmlformentry Module api 2.2</name>
<description>2.2 api project for htmlformentry</description>

<properties>
<openMRSVersion>2.2.0</openMRSVersion>
</properties>

<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>${project.parent.artifactId}-api</artifactId>
<version>${project.parent.version}</version>
</dependency>

<dependency>
<groupId>org.openmrs.api</groupId>
<artifactId>openmrs-api</artifactId>
<version>${openMRSVersion}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.openmrs.test</groupId>
<artifactId>openmrs-test</artifactId>
<type>pom</type>
<version>${openMRSVersion}</version>
</dependency>

<dependency>
<groupId>org.openmrs.web</groupId>
<artifactId>openmrs-web</artifactId>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>

<testResources>
<testResource>
<directory>src/test/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</testResource>
<testResource>
<directory>src/test/resources</directory>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.xml</exclude>
</excludes>
<filtering>false</filtering>
</testResource>
</testResources>
</build>

</project>
@@ -0,0 +1,272 @@
package org.openmrs.module.htmlformentry;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.openmrs.CodedOrFreeText;
import org.openmrs.Concept;
import org.openmrs.ConceptClass;
import org.openmrs.Condition;
import org.openmrs.ConditionClinicalStatus;
import org.openmrs.api.ConditionService;
import org.openmrs.api.context.Context;
import org.openmrs.messagesource.MessageSourceService;
import org.openmrs.module.htmlformentry.FormEntryContext.Mode;
import org.openmrs.module.htmlformentry.action.FormSubmissionControllerAction;
import org.openmrs.module.htmlformentry.element.HtmlGeneratorElement;
import org.openmrs.module.htmlformentry.widget.DateWidget;
import org.openmrs.module.htmlformentry.widget.ErrorWidget;
import org.openmrs.module.htmlformentry.widget.Option;
import org.openmrs.module.htmlformentry.widget.RadioButtonsWidget;
import org.openmrs.module.htmlformentry.widget.Widget;
import org.openmrs.module.htmlformentry.widget.ConceptSearchAutocompleteWidget;

public class ConditionElement implements HtmlGeneratorElement, FormSubmissionControllerAction {

private MessageSourceService mss;
private ConditionService conditionService;
private boolean required;
private final String CONDITION_LIST_CONCEPT_CLASS_NAME = "Diagnosis";

// widgets
private Widget conditionSearchWidget;
private DateWidget onSetDateWidget;
private DateWidget endDateWidget;
private RadioButtonsWidget conditionStatusesWidget;
private ErrorWidget endDateErrorWidget;
private ErrorWidget conditionSearchErrorWidget;
private ErrorWidget conditionStatusesErrorWidget;

@Override
public void handleSubmission(FormEntrySession session, HttpServletRequest submission) {
FormEntryContext context = session.getContext();
if (context.getMode() != Mode.VIEW) {
Condition condition = new Condition();
CodedOrFreeText conditionConcept = new CodedOrFreeText();
try {
int conceptId = Integer.parseInt((String) conditionSearchWidget.getValue(session.getContext(), submission));
conditionConcept.setCoded(new Concept(conceptId));

} catch(NumberFormatException e) {
String nonCodedConcept = submission.getParameter(context.getFieldName(conditionSearchWidget));
conditionConcept.setNonCoded(nonCodedConcept);
}
condition.setCondition(conditionConcept);
condition.setClinicalStatus(getStatus(context, submission));
condition.setOnsetDate(onSetDateWidget.getValue(context, submission));
if (ConditionClinicalStatus.INACTIVE == getStatus(context, submission)) {
condition.setEndDate(endDateWidget.getValue(context, submission));
}
condition.setPatient(session.getPatient());
conditionService = Context.getConditionService();
conditionService.saveCondition(condition);
}
}

@Override
public Collection<FormSubmissionError> validateSubmission(FormEntryContext context, HttpServletRequest submission) {
List<FormSubmissionError> ret = new ArrayList<FormSubmissionError>();
Date givenOnsetDate = onSetDateWidget.getValue(context, submission);
Date givenEndDate = endDateWidget.getValue(context, submission);
String condition = StringUtils.isNotBlank((String) conditionSearchWidget.getValue(context, submission)) ?
(String) conditionSearchWidget.getValue(context, submission) : submission.getParameter(context.getFieldName(conditionSearchWidget));
ConditionClinicalStatus status = getStatus(context, submission);

if (context.getMode() != Mode.VIEW) {
if (StringUtils.isBlank(condition) && required) {
ret.add(new FormSubmissionError(context.getFieldName(conditionSearchWidget),
Context.getMessageSourceService().getMessage("htmlformentry.conditionui.condition.required")));
}
if (givenOnsetDate != null && givenEndDate != null) {
if (givenOnsetDate.after(givenEndDate)) {
ret.add(new FormSubmissionError(context.getFieldName(endDateWidget),
Context.getMessageSourceService().getMessage("htmlformentry.conditionui.endDate.before.onsetDate.error")));
}
}
if (status == null && required) {
ret.add(new FormSubmissionError(context.getFieldName(conditionStatusesWidget),
Context.getMessageSourceService().getMessage("htmlformentry.conditionui.status.required")));
}
}
return ret;
}

@Override
public String generateHtml(FormEntryContext context) {
StringBuilder ret = new StringBuilder();
ret.append("<div id=\"htmlformentry-condition\">");
ret.append(htmlForConditionSearchWidget(context));
ret.append(htmlForConditionStatusesWidgets(context));
ret.append(htmlForConditionDatesWidget(context));
ret.append("</div>");
return ret.toString();
}

private String htmlForConditionSearchWidget(FormEntryContext context) {
Set<Concept> initialConcepts = new HashSet<Concept>();
if (mss == null) {
mss = Context.getMessageSourceService();
}
ConceptClass conceptClass = Context.getConceptService().getConceptClassByName(CONDITION_LIST_CONCEPT_CLASS_NAME);
initialConcepts.addAll(Context.getConceptService().getConceptsByClass(conceptClass));
conditionSearchWidget = new ConceptSearchAutocompleteWidget(new ArrayList<Concept>(initialConcepts), Arrays.asList(conceptClass));
String conditionNameTextInputId = context.registerWidget(conditionSearchWidget);
conditionSearchErrorWidget = new ErrorWidget();
context.registerErrorWidget(conditionSearchWidget, conditionSearchErrorWidget);

StringBuilder ret = new StringBuilder();
ret.append(conditionSearchWidget.generateHtml(context));
if (context.getMode() != Mode.VIEW) {
ret.append(conditionSearchErrorWidget.generateHtml(context));
}
ret.append("\n<script>jq('#" + conditionNameTextInputId + "').attr('placeholder',");
ret.append(" '" + mss.getMessage("coreapps.conditionui.condition") + "');\n");
ret.append(" jq('#" + conditionNameTextInputId + "').css('min-width', '46.4%');\n");

// Add support for non-coded concept values.
// This a hack to let the autocomplete widget accept values that aren't part of the concept list.
ret.append("jq('#" + conditionNameTextInputId + "').blur(function(e){\n");
ret.append(" var valueAttr = jq('#" + conditionNameTextInputId + "_hid" + "').attr('value');\n");
ret.append(" if(valueAttr === \"ERROR\"){\n");
ret.append(" jq('#" + conditionNameTextInputId + "_hid" + "').attr('value', '');\n");
ret.append(" }\n");
ret.append("});\n");
ret.append("</script>\n");
return ret.toString();
}

private String htmlForConditionStatusesWidgets(FormEntryContext context) {
if (mss == null) {
mss = Context.getMessageSourceService();
}
Option active = new Option(mss.getMessage("coreapps.conditionui.active.label"), "active", false);
Option inactive = new Option(mss.getMessage("coreapps.conditionui.inactive.label"), "inactive", false);
Option historyOf = new Option(mss.getMessage("htmlformentry.conditionui.historyOf.label"), "history-of", false);
conditionStatusesWidget = new RadioButtonsWidget();
conditionStatusesErrorWidget = new ErrorWidget();
conditionStatusesWidget.addOption(active);
conditionStatusesWidget.addOption(inactive);
conditionStatusesWidget.addOption(historyOf);
String radioGroupName = context.registerWidget(conditionStatusesWidget);
context.registerErrorWidget(conditionStatusesWidget, conditionStatusesErrorWidget);

StringBuilder sb = new StringBuilder();
sb.append("<div id=\"condition-status\">");
sb.append(conditionStatusesErrorWidget.generateHtml(context));
sb.append(conditionStatusesWidget.generateHtml(context));
sb.append("<script>");
sb.append("jq(\"input[name='" + radioGroupName + "']\").change(function(e){\n" +
" if($(this).val() == 'active') {\n" +
" document.getElementById('endDatePicker').style.visibility=\"hidden\"; \n" +
" } else {\n" +
" document.getElementById('endDatePicker').style.visibility=\"visible\";\n" +
" }\n" +
"\n" +
"});");
sb.append("</script>");
sb.append("<style>");
sb.append("#condition-status input {\n" +
" display: inline;\n" +
" float: none;\n" +
"}\n" +
"#condition-status label {\n" +
" display: inline;\n" +
"}");
sb.append("#condition-status {\n" +
" padding:10px 0px;\n" +
" }");
sb.append("</style>");
sb.append("</div>");
return sb.toString();
}

private String htmlForConditionDatesWidget(FormEntryContext context) {
onSetDateWidget = new DateWidget();
if (mss == null) {
mss = Context.getMessageSourceService();
}
String onsetDateTextInputId = context.registerWidget(onSetDateWidget) + "-display";
endDateWidget = new DateWidget();
endDateErrorWidget = new ErrorWidget();
String endDateTextInputId = context.registerWidget(endDateWidget) + "-display";
context.registerErrorWidget(endDateWidget, endDateErrorWidget);

StringBuilder ret = new StringBuilder();
ret.append("<ul>");
ret.append("<li>");
ret.append(onSetDateWidget.generateHtml(context));
ret.append("</li> <li>");
ret.append("<span id=\"endDatePicker\">");
ret.append(endDateWidget.generateHtml(context));
ret.append("</span>");
ret.append("</li>");
if (context.getMode() != Mode.VIEW) {
ret.append(endDateErrorWidget.generateHtml(context));
}
ret.append("</ul> <br/>");
ret.append("<script> jq('#" + onsetDateTextInputId + "').attr('placeholder',");
ret.append(" '" + mss.getMessage("coreapps.conditionui.onsetdate") + "');");
ret.append("jq('#" + endDateTextInputId + "').attr('placeholder',");
ret.append(" '" + mss.getMessage("coreapps.stopDate.label") + "');");
ret.append("</script>");
ret.append("<style>");
ret.append("#htmlformentry-condition li {\n" +
" width:30%;\n" +
" float: left;\n" +
"}");
ret.append("#htmlformentry-condition ul {\n" +
" display:flow-root;\n" +
" width:85%" +
"}");
ret.append("</style>");
return ret.toString();
}

private ConditionClinicalStatus getStatus(FormEntryContext context, HttpServletRequest request) {
if (conditionStatusesWidget == null) {
return null;
}
Object status = conditionStatusesWidget.getValue(context, request);
if (status != null) {
if (((String)status).equals("active")) {
return ConditionClinicalStatus.ACTIVE;
}
if (((String)status).equals("inactive")) {
return ConditionClinicalStatus.INACTIVE;
}
if (((String)status).equals("history-of")) {
return ConditionClinicalStatus.HISTORY_OF;
}
}
return null;
}

public void setConditionSearchWidget(Widget conditionSearchWidget) {
this.conditionSearchWidget = conditionSearchWidget;
}

public void setOnSetDateWidget(DateWidget onSetDateWidget) {
this.onSetDateWidget = onSetDateWidget;
}

public void setEndDateWidget(DateWidget endDateWidget) {
this.endDateWidget = endDateWidget;
}

public void setConditionStatusesWidget(RadioButtonsWidget conditionStatusesWidget) {
this.conditionStatusesWidget = conditionStatusesWidget;
}

public void setRequired(boolean required) {
this.required = required;
}

}
@@ -0,0 +1,24 @@
package org.openmrs.module.htmlformentry.handler;

import java.util.Map;

import org.openmrs.annotation.OpenmrsProfile;
import org.openmrs.module.htmlformentry.ConditionElement;
import org.openmrs.module.htmlformentry.FormEntrySession;
import org.openmrs.module.htmlformentry.FormSubmissionController;

@OpenmrsProfile(openmrsPlatformVersion = "2.2.*")
public class ConditionTagHandlerSupport2_2 implements ConditionTagHandlerSupport {

@Override
public String getSubstitution(FormEntrySession session, FormSubmissionController controller, Map<String, String> attributes) {
ConditionElement element = new ConditionElement();
String required = attributes.get("required");
if (required != null) {
element.setRequired(required.equalsIgnoreCase("true"));
}
session.getSubmissionController().addAction(element);
return element.generateHtml(session.getContext());
}

}

0 comments on commit 1b60268

Please sign in to comment.