/* * PatientView * * Copyright (c) Worth Solutions Limited 2004-2013 * * This file is part of PatientView. * * PatientView is free software: you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * PatientView is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with PatientView in a file * titled COPYING. If not, see <http://www.gnu.org/licenses/>. * * @package PatientView * @link http://www.patientview.org * @author PatientView <info@patientview.org> * @copyright Copyright (c) 2004-2013, Worth Solutions Limited * @license http://www.gnu.org/licenses/gpl-3.0.html The GNU General Public License V3.0 */ package org.patientview.radar.web.panels; import org.apache.commons.lang.StringUtils; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.form.ChoiceRenderer; import org.apache.wicket.markup.html.form.DropDownChoice; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.markup.html.form.TextField; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.panel.Panel; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.CompoundPropertyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.spring.injection.annot.SpringBean; import org.apache.wicket.validation.validator.PatternValidator; import org.patientview.model.Centre; import org.patientview.model.Ethnicity; import org.patientview.model.Patient; import org.patientview.model.Sex; import org.patientview.model.Status; import org.patientview.model.generic.DiseaseGroup; import org.patientview.radar.exception.RegisterException; import org.patientview.radar.model.Diagnosis; import org.patientview.radar.model.DiagnosisCode; import org.patientview.radar.model.user.User; import org.patientview.radar.service.ClinicalDataManager; import org.patientview.radar.service.DemographicsManager; import org.patientview.radar.service.DiagnosisManager; import org.patientview.radar.service.LabDataManager; import org.patientview.radar.service.TherapyManager; import org.patientview.radar.service.UnitManager; import org.patientview.radar.service.UserManager; import org.patientview.radar.service.UtilityManager; import org.patientview.radar.service.generic.DiseaseGroupManager; import org.patientview.radar.web.RadarApplication; import org.patientview.radar.web.RadarSecuredSession; import org.patientview.radar.web.components.ClinicianDropDown; import org.patientview.radar.web.components.PatientCentreDropDown; import org.patientview.radar.web.components.RadarComponentFactory; import org.patientview.radar.web.components.RadarRequiredCheckBox; import org.patientview.radar.web.components.RadarRequiredDateTextField; import org.patientview.radar.web.components.RadarRequiredDropdownChoice; import org.patientview.radar.web.components.RadarRequiredTextField; import org.patientview.radar.web.components.RadarTextFieldWithValidation; import org.patientview.radar.web.models.RadarModelFactory; import org.patientview.radar.web.pages.patient.srns.PatientCallBack; import org.patientview.radar.web.pages.patient.srns.SrnsPatientPage; import org.patientview.util.CommonUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Date; import java.util.List; public class DemographicsPanel extends Panel { @SpringBean private DemographicsManager demographicsManager; @SpringBean private DiseaseGroupManager diseaseGroupManager; @SpringBean private DiagnosisManager diagnosisManager; @SpringBean private ClinicalDataManager clinicalDataManager; @SpringBean private LabDataManager labDataManager; @SpringBean private TherapyManager therapyManager; @SpringBean private UtilityManager utilityManager; @SpringBean private UnitManager unitManager; @SpringBean private UserManager userManager; private static final Logger LOGGER = LoggerFactory.getLogger(DemographicsPanel.class); public DemographicsPanel(String id, final IModel<Patient> patientModel, final PatientCallBack patientCallBack) { super(id); List<Component> nonEditableComponents = new ArrayList<Component>(); setOutputMarkupId(true); setOutputMarkupPlaceholderTag(true); final User user = RadarSecuredSession.get().getUser(); // Set up model - if given radar number loadable detachable getting demographics by radar number final CompoundPropertyModel<Patient> model = new CompoundPropertyModel<Patient>(patientModel.getObject()); final IModel<Date> registrationHeaderModel = new Model<Date>(); if (patientModel.getObject().getDateReg() != null) { registrationHeaderModel.setObject(patientModel.getObject().getDateReg()); } else { registrationHeaderModel.setObject(new Date()); } final IModel<Long> radarHeaderModel = new Model<Long>(patientModel.getObject().getRadarNo()); final IModel<String> forenameHeaderModel = new Model<String>(patientModel.getObject().getForename()); final IModel<String> surnameHeaderModel = new Model<String>(patientModel.getObject().getSurname()); final IModel<Date> dobHeaderModel = new Model<Date>(patientModel.getObject().getDob()); // Set up form final Form<Patient> form = new Form<Patient>("form", model) { @Override protected void onSubmit() { Patient patient = getModelObject(); patient.setRadarConsentConfirmedByUserId(user.getUserId()); try { patientModel.setObject(patient); patientModel.getObject().setDateReg(new Date()); userManager.addPatientUserOrUpdatePatient(patient); patientCallBack.updateModel(patient.getRadarNo()); // Update the header with the saved record forenameHeaderModel.setObject(patientModel.getObject().getForename()); surnameHeaderModel.setObject(patientModel.getObject().getSurname()); dobHeaderModel.setObject(patientModel.getObject().getDob()); registrationHeaderModel.setObject(patientModel.getObject().getDateReg()); radarHeaderModel.setObject(patient.getRadarNo()); } catch (RegisterException re) { LOGGER.error("Registration Exception {} ", re.getMessage()); error("Could not register patient" + re.getMessage()); } catch (Exception e) { String message = "Error registering new patient to accompany this demographic"; LOGGER.error("{}, message {}", message, e.getMessage()); error(message); } // create new diagnosis if it doesnt exist becuase diagnosis code is set in demographics tab if (patient.hasValidId()) { Diagnosis diagnosis = diagnosisManager.getDiagnosisByRadarNumber(patient.getRadarNo()); if (diagnosis == null) { Diagnosis diagnosisNew = new Diagnosis(); diagnosisNew.setRadarNumber(patient.getRadarNo()); DiagnosisCode diagnosisCode = (DiagnosisCode) ((DropDownChoice) get("diagnosis")) .getModelObject(); diagnosisNew.setDiagnosisCode(diagnosisCode); diagnosisManager.saveDiagnosis(diagnosisNew); } } } }; // More info Label nhsNumber = new Label("nhsno"); WebMarkupContainer nhsNumberContainer = new WebMarkupContainer("nhsNumberContainer"); nhsNumberContainer.add(nhsNumber); Label chiNumber = new Label("chiNumber"); WebMarkupContainer chiNumberContainer = new WebMarkupContainer("chiNumberContainer") { @Override public boolean isVisible() { return false; } }; chiNumberContainer.add(chiNumber); form.add(nhsNumberContainer, chiNumberContainer); form.setOutputMarkupId(true); form.setOutputMarkupPlaceholderTag(true); add(form); final List<Component> componentsToUpdateList = new ArrayList<Component>(); form.add(new Label("addNewPatientLabel", "Add a New Patient") { @Override public boolean isVisible() { return patientModel.getObject().hasValidId(); } }); final TextField radarNumberField = new TextField("radarNo", radarHeaderModel); radarNumberField.setEnabled(false); radarNumberField.setOutputMarkupId(true); radarNumberField.setOutputMarkupPlaceholderTag(true); form.add(radarNumberField); componentsToUpdateList.add(radarNumberField); final TextField dateRegistered = new org.apache.wicket.extensions.markup.html.form.DateTextField("dateReg", registrationHeaderModel, CommonUtils.UK_DATE_FORMAT); dateRegistered.setOutputMarkupId(true); dateRegistered.setOutputMarkupPlaceholderTag(true); form.add(dateRegistered); componentsToUpdateList.add(dateRegistered); RadarRequiredDropdownChoice diagnosis = new RadarRequiredDropdownChoice("diagnosis", RadarModelFactory.getDiagnosisCodeModel( new Model<Long>(patientModel.getObject().getRadarNo()), diagnosisManager), diagnosisManager.getDiagnosisCodes(), new ChoiceRenderer("abbreviation", "id"), form, componentsToUpdateList) { @Override public boolean isEnabled() { RadarSecuredSession securedSession = RadarSecuredSession.get(); if (securedSession.getRoles().hasRole(User.ROLE_PATIENT)) { return false; } return getModelObject() == null; } }; String diseaseGroup = patientModel.getObject().getDiseaseGroup().getId(); DiagnosisCode diagnosisCode = new DiagnosisCode(); // WARNING - This doesn't make sense, you cannot equate a disease group with a diagnosis code, // but works because these groups do not have specific diagnosis if (diseaseGroup.equals(DiseaseGroup.SRNS_DISEASE_GROUP_ID)) { diagnosisCode.setId(DiagnosisCode.SRNS_ID); } else if (diseaseGroup.equals(DiseaseGroup.MPGN_DISEASEGROUP_ID)) { diagnosisCode.setId(DiagnosisCode.MPGN_ID); } diagnosis.setModel(new Model(diagnosisCode)); /** * Basic fields */ RadarRequiredTextField surname = new RadarRequiredTextField("surname", form, componentsToUpdateList); RadarRequiredTextField forename = new RadarRequiredTextField("forename", form, componentsToUpdateList); RadarRequiredDateTextField dateOfBirth = new RadarRequiredDateTextField("dob", form, componentsToUpdateList); dateOfBirth.setRequired(true); form.add(diagnosis, surname, forename, dateOfBirth); nonEditableComponents.add(surname); nonEditableComponents.add(forename); nonEditableComponents.add(dateOfBirth); /** * Add basic fields for header too... apparently we can't render same component twice in wicket!.. * * As we cant set demographicsModelObject as final outside isVisible() implementations there's a bunch of * code duplication */ // forename final Label nameLabel = new Label("nameLabel", "Name") { @Override public boolean isVisible() { return StringUtils.isNotBlank(patientModel.getObject().getForename()); } }; nameLabel.setOutputMarkupId(true); nameLabel.setOutputMarkupPlaceholderTag(true); form.add(nameLabel); final TextField forenameForHeader = new TextField("forenameForHeader", forenameHeaderModel) { @Override public boolean isVisible() { return StringUtils.isNotBlank(patientModel.getObject().getForename()); } }; forenameForHeader.setOutputMarkupId(true); forenameForHeader.setOutputMarkupPlaceholderTag(true); componentsToUpdateList.add(forenameForHeader); componentsToUpdateList.add(nameLabel); // surname final TextField surnameForHeader = new TextField("surnameForHeader", surnameHeaderModel) { @Override public boolean isVisible() { return StringUtils.isNotBlank(patientModel.getObject().getSurname()); } }; surnameForHeader.setOutputMarkupId(true); surnameForHeader.setOutputMarkupPlaceholderTag(true); componentsToUpdateList.add(surnameForHeader); // date of birth final Label dobLabel = new Label("dobLabel", "DoB") { @Override public boolean isVisible() { return patientModel.getObject().getDob() != null; } }; dobLabel.setOutputMarkupId(true); dobLabel.setOutputMarkupPlaceholderTag(true); form.add(dobLabel); final TextField dateOfBirthForHeader = new org.apache.wicket.extensions.markup.html.form.DateTextField( "dateOfBirthForHeader", dobHeaderModel, CommonUtils.UK_DATE_FORMAT) { @Override public boolean isVisible() { return patientModel.getObject().getDob() != null; } }; dateOfBirthForHeader.setOutputMarkupId(true); dateOfBirthForHeader.setOutputMarkupPlaceholderTag(true); componentsToUpdateList.add(dateOfBirthForHeader); componentsToUpdateList.add(dobLabel); form.add(diagnosis, surnameForHeader, forenameForHeader, dateOfBirthForHeader); // Sex RadarRequiredDropdownChoice sex = new RadarRequiredDropdownChoice("sexModel", demographicsManager.getSexes(), new ChoiceRenderer<Sex>("type", "id"), form, componentsToUpdateList); // Ethnicity DropDownChoice<Ethnicity> ethnicity = new DropDownChoice<Ethnicity>("ethnicity", utilityManager. getEthnicities(), new ChoiceRenderer<Ethnicity>("name", "id")); form.add(sex, ethnicity); // Address fields TextField address1 = new TextField("address1"); TextField address2 = new TextField("address2"); TextField address3 = new TextField("address3"); TextField address4 = new TextField("address4"); RadarTextFieldWithValidation postcode = new RadarTextFieldWithValidation("postcode", new PatternValidator("[a-zA-Z]{1,2}[0-9][0-9A-Za-z]{0,1} {0,1}[0-9][A-Za-z]{2}$"), form, componentsToUpdateList); form.add(address1, address2, address3, address4, postcode); nonEditableComponents.add(address1); nonEditableComponents.add(address2); nonEditableComponents.add(address3); nonEditableComponents.add(address4); nonEditableComponents.add(postcode); // Archive fields TextField surnameAlias = new TextField("surnameAlias"); TextField previousPostcode = new TextField("postcodeOld"); form.add(surnameAlias, previousPostcode); // More info RadarRequiredTextField hospitalNumber = new RadarRequiredTextField("hospitalnumber", form, componentsToUpdateList); TextField renalRegistryNumber = new TextField("rrNo"); TextField ukTransplantNumber = new TextField("uktNo"); form.add(hospitalNumber, renalRegistryNumber, ukTransplantNumber); nonEditableComponents.add(hospitalNumber); // Status, consultants and centres drop down boxes form.add(new DropDownChoice<Status>("statusModel", demographicsManager.getStatuses(), new ChoiceRenderer<Status>("abbreviation", "id"))); // Consultant and renal unit Label sourceUnitCodeLabel = new Label("sourceUnitCodeLabel", "Linked to") { @Override public boolean isVisible() { return model.getObject().isLinked(); } }; String sourceUnitNameLabelValue = model.getObject().getPatientLinkUnitCode() != null ? utilityManager.getCentre(model.getObject().getPatientLinkUnitCode()).getName() : ""; Label sourceUnitCode = new Label("sourceUnitCode", sourceUnitNameLabelValue) { @Override public boolean isVisible() { return model.getObject().isLinked(); } }; form.add(sourceUnitCodeLabel, sourceUnitCode); final ClinicianDropDown clinician = new ClinicianDropDown("clinician", user, form.getModelObject()); form.add(clinician); DropDownChoice<Centre> renalUnit = new PatientCentreDropDown("renalUnit", user, form.getModelObject()); renalUnit.add(new AjaxFormComponentUpdatingBehavior("onchange") { @Override protected void onUpdate(AjaxRequestTarget target) { Patient patient = model.getObject(); if (patient != null) { clinician.updateCentre(patient.getRenalUnit() != null ? patient.getRenalUnit().getUnitCode() : null); } clinician.clearInput(); target.add(clinician); } }); form.add(renalUnit); final IModel<String> consentUserModel = new Model<String>(utilityManager.getUserName( patientModel.getObject().getRadarConsentConfirmedByUserId())); form.add(new ExternalLink("consentFormsLink", "http://www.rarerenal.org/join/criteria-and-consent/")); final Label tickConsentUser = new Label("radarConsentConfirmedByUserId", consentUserModel) { @Override public boolean isVisible() { return StringUtils.isNotEmpty(consentUserModel.getObject()); } }; tickConsentUser.setOutputMarkupId(true); tickConsentUser.setOutputMarkupPlaceholderTag(true); form.add(tickConsentUser); final RadarRequiredCheckBox consent = new RadarRequiredCheckBox("consent", form, componentsToUpdateList); consent.add(new AjaxFormComponentUpdatingBehavior("onclick") { @Override protected void onUpdate(AjaxRequestTarget target) { target.add(tickConsentUser); if (consent.getModel().getObject().equals(Boolean.TRUE)) { model.getObject().setRadarConsentConfirmedByUserId(RadarSecuredSession.get().getUser().getUserId()); consentUserModel.setObject(RadarSecuredSession.get().getUser().getName()); tickConsentUser.setVisible(true); } else { tickConsentUser.setVisible(false); } } }); form.add(consent); final Label successMessageTop = RadarComponentFactory.getSuccessMessageLabel("successMessageTop", form, componentsToUpdateList); final Label successMessageBottom = RadarComponentFactory.getSuccessMessageLabel("successMessageBottom", form, componentsToUpdateList); Label errorMessage = RadarComponentFactory.getErrorMessageLabel("errorMessage", form, componentsToUpdateList); AjaxSubmitLink ajaxSubmitLinkTop = new AjaxSubmitLink("saveTop") { @Override protected void onSubmit(AjaxRequestTarget ajaxRequestTarget, Form<?> form) { ajaxRequestTarget.add(componentsToUpdateList.toArray(new Component[componentsToUpdateList.size()])); successMessageTop.setVisible(true); successMessageBottom.setVisible(true); ajaxRequestTarget.add(successMessageTop); ajaxRequestTarget.add(successMessageBottom); ajaxRequestTarget.appendJavaScript(RadarApplication.FORM_IS_DIRTY_FALSE_SCRIPT); } @Override protected void onError(AjaxRequestTarget ajaxRequestTarget, Form<?> form) { ajaxRequestTarget.add(componentsToUpdateList.toArray(new Component[componentsToUpdateList.size()])); successMessageTop.setVisible(false); successMessageBottom.setVisible(false); ajaxRequestTarget.add(successMessageTop); ajaxRequestTarget.add(successMessageBottom); } }; ajaxSubmitLinkTop.add(new AttributeModifier("value", new AbstractReadOnlyModel() { @Override public Object getObject() { return patientModel.getObject() == null ? "Add this patient" : "Update"; } })); form.add(ajaxSubmitLinkTop); AjaxSubmitLink ajaxSubmitLinkBottom = new AjaxSubmitLink("saveBottom") { @Override protected void onSubmit(AjaxRequestTarget ajaxRequestTarget, Form<?> form) { ajaxRequestTarget.add(componentsToUpdateList.toArray(new Component[componentsToUpdateList.size()])); successMessageTop.setVisible(true); successMessageBottom.setVisible(true); ajaxRequestTarget.add(successMessageTop); ajaxRequestTarget.add(successMessageBottom); ajaxRequestTarget.appendJavaScript(RadarApplication.FORM_IS_DIRTY_FALSE_SCRIPT); } @Override protected void onError(AjaxRequestTarget ajaxRequestTarget, Form<?> form) { ajaxRequestTarget.add(componentsToUpdateList.toArray(new Component[componentsToUpdateList.size()])); successMessageTop.setVisible(false); successMessageBottom.setVisible(false); ajaxRequestTarget.add(successMessageTop); ajaxRequestTarget.add(successMessageBottom); } }; ajaxSubmitLinkBottom.add(new AttributeModifier("value", new AbstractReadOnlyModel() { @Override public Object getObject() { return patientModel.getObject() == null ? "Add this patient" : "Update"; } })); form.add(ajaxSubmitLinkBottom); if (model.getObject().isLinked()) { for (Component component : nonEditableComponents) { component.setEnabled(false); } } } @Override public boolean isVisible() { return ((SrnsPatientPage) getPage()).getCurrentTab().equals(SrnsPatientPage.CurrentTab.DEMOGRAPHICS); } }