From cb8c136673b0fbcadf797d20ea5d68eeed2692e7 Mon Sep 17 00:00:00 2001 From: SergiuPacurariu Date: Tue, 3 Dec 2024 16:31:35 +0200 Subject: [PATCH 1/3] #13181 - Enhance National Health ID Search Functionality Across Modules and Address Duplication Issues - v3 --- .../de/symeda/sormas/api/i18n/Strings.java | 1 + .../api/person/PersonSimilarityCriteria.java | 18 ++++- .../src/main/resources/strings.properties | 1 + .../ExternalMessageService.java | 2 + .../AutomaticLabMessageProcessor.java | 2 +- .../sormas/backend/person/PersonService.java | 22 +++--- .../sormas/backend/sample/SampleService.java | 1 + .../backend/person/PersonFacadeEjbTest.java | 2 +- .../symeda/sormas/ui/caze/CaseController.java | 79 ++++++++++++++++--- .../symeda/sormas/ui/caze/CaseCreateForm.java | 12 +++ .../sormas/ui/person/PersonController.java | 9 ++- .../sormas/ui/person/PersonCreateForm.java | 19 ++++- .../sormas/ui/person/PersonEditForm.java | 23 +++++- .../sormas/ui/person/PersonFormHelper.java | 54 +++++++++++++ .../ui/person/PersonSelectionField.java | 2 +- .../sormas/ui/person/PersonSelectionGrid.java | 7 ++ .../sormas/ui/utils/AbstractEditForm.java | 12 +++ .../utils/SormasFieldGroupFieldFactory.java | 3 + .../ui/utils/components/TextFieldCustom.java | 61 ++++++++++++++ 19 files changed, 299 insertions(+), 31 deletions(-) create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFormHelper.java create mode 100644 sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java index ec0559d766b..484d972c404 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java @@ -825,6 +825,7 @@ public interface Strings { String headingShowExternalMessage = "headingShowExternalMessage"; String headingSignsAndSymptoms = "headingSignsAndSymptoms"; String headingSimilarImmunization = "headingSimilarImmunization"; + String headingSimilarPerson = "headingSimilarPerson"; String headingSomeCasesAlreadyInEvent = "headingSomeCasesAlreadyInEvent"; String headingSomeCasesNotRestored = "headingSomeCasesNotRestored"; String headingSomeContactsAlreadyInEvent = "headingSomeContactsAlreadyInEvent"; diff --git a/sormas-api/src/main/java/de/symeda/sormas/api/person/PersonSimilarityCriteria.java b/sormas-api/src/main/java/de/symeda/sormas/api/person/PersonSimilarityCriteria.java index fd0ca37565c..e782b271914 100644 --- a/sormas-api/src/main/java/de/symeda/sormas/api/person/PersonSimilarityCriteria.java +++ b/sormas-api/src/main/java/de/symeda/sormas/api/person/PersonSimilarityCriteria.java @@ -20,6 +20,7 @@ public class PersonSimilarityCriteria extends BaseCriteria implements Cloneable private String passportNumber; private String nationalHealthId; private String nameUuidExternalIdExternalTokenLike; + private boolean checkOnlyForNationalHealthId; /** * If true, compare the name of the person only to the first and last name fields of the database; if false, compare the * name of the person to other fields like UUID and external ID as well. @@ -106,6 +107,14 @@ public PersonSimilarityCriteria nationalHealthId(String nationalHealthId) { return this; } + public boolean isCheckOnlyForNationalHealthId() { + return checkOnlyForNationalHealthId; + } + + public void setCheckOnlyForNationalHealthId(boolean checkOnlyForNationalHealthId) { + this.checkOnlyForNationalHealthId = checkOnlyForNationalHealthId; + } + public String getNameUuidExternalIdExternalTokenLike() { return nameUuidExternalIdExternalTokenLike; } @@ -140,7 +149,11 @@ public void setBirthdateDD(Integer birthdateDD) { } public static PersonSimilarityCriteria forPerson(PersonDto person) { - return forPerson(person, false); + return forPerson(person, false, false); + } + + public static PersonSimilarityCriteria forPerson(PersonDto person, boolean checkOnlyForNationalHealthId){ + return forPerson(person, false, checkOnlyForNationalHealthId); } /** @@ -148,7 +161,7 @@ public static PersonSimilarityCriteria forPerson(PersonDto person) { * If true, compares the name of the person only to the first and last name fields of the database; if false, compares the * name of the person to other fields like UUID and external ID as well. */ - public static PersonSimilarityCriteria forPerson(PersonDto person, boolean strictNameComparison) { + public static PersonSimilarityCriteria forPerson(PersonDto person, boolean strictNameComparison, boolean checkOnlyForNationalHealthId) { PersonSimilarityCriteria personSimilarityCriteria = new PersonSimilarityCriteria().sex(person.getSex()) .birthdateDD(person.getBirthdateDD()) @@ -156,6 +169,7 @@ public static PersonSimilarityCriteria forPerson(PersonDto person, boolean stric .birthdateYYYY(person.getBirthdateYYYY()) .passportNumber(person.getPassportNumber()) .nationalHealthId(person.getNationalHealthId()); + personSimilarityCriteria.setCheckOnlyForNationalHealthId(checkOnlyForNationalHealthId); if (strictNameComparison) { personSimilarityCriteria.firstName(person.getFirstName()).lastName(person.getLastName()).strictNameComparison(Boolean.TRUE); } else { diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index aa9c0c3ea24..7f03cdf3778 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -697,6 +697,7 @@ headingShowExternalMessage = Message headingSelfReportSideComponent = Self reports headingSignsAndSymptoms = Clinical Signs and Symptoms headingSimilarImmunization = Similar immunizaton +headingSimilarPerson = Similar persons found based on person introduced data headingSyncUsers = Sync Users headingTasksDeleted = Tasks deleted headingTasksNotDeleted = None of the tasks were deleted diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageService.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageService.java index d163cb10330..9ce612c32cd 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageService.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/ExternalMessageService.java @@ -18,6 +18,7 @@ import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import de.symeda.sormas.backend.person.Person; import org.apache.commons.lang3.StringUtils; import de.symeda.sormas.api.ReferenceDto; @@ -123,6 +124,7 @@ public Predicate buildCriteriaFilter(CriteriaBuilder cb, Root l CriteriaBuilderHelper.ilike(cb, labMessage.get(ExternalMessage.UUID), textFilter), CriteriaBuilderHelper.unaccentedIlike(cb, labMessage.get(ExternalMessage.PERSON_FIRST_NAME), textFilter), CriteriaBuilderHelper.unaccentedIlike(cb, labMessage.get(ExternalMessage.PERSON_LAST_NAME), textFilter), + CriteriaBuilderHelper.ilike(cb, labMessage.get(ExternalMessage.PERSON_NATIONAL_HEALTH_ID), textFilter), CriteriaBuilderHelper.ilike(cb, labMessage.get(ExternalMessage.PERSON_POSTAL_CODE), textFilter), CriteriaBuilderHelper.unaccentedIlike(cb, labMessage.get(ExternalMessage.REPORTER_NAME), textFilter), CriteriaBuilderHelper.ilike(cb, labMessage.get(ExternalMessage.REPORTER_POSTAL_CODE), textFilter)); diff --git a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/AutomaticLabMessageProcessor.java b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/AutomaticLabMessageProcessor.java index 74f141f2b50..f660bce1805 100644 --- a/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/AutomaticLabMessageProcessor.java +++ b/sormas-backend/src/main/java/de/symeda/sormas/backend/externalmessage/labmessage/AutomaticLabMessageProcessor.java @@ -149,7 +149,7 @@ protected void handlePickOrCreatePerson(PersonDto person, HandlerCallback caseCreateComponent; + public CaseController() { } @@ -187,7 +192,7 @@ public void registerViews(Navigator navigator) { } public void create() { - CommitDiscardWrapperComponent caseCreateComponent = getCaseCreateComponent(null, null, null, null, null, false); + caseCreateComponent = getCaseCreateComponent(null, null, null, null, null, false); VaadinUiUtil.showModalPopupWindow(caseCreateComponent, I18nProperties.getString(Strings.headingCreateNewCase)); } @@ -740,6 +745,12 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( dto.getSymptoms().setOnsetDate(createForm.getOnsetDate()); dto.setWasInQuarantineBeforeIsolation(YesNoUnknown.YES); +// if (StringUtils.isNotEmpty(person.getNationalHealthId())) { +// PersonFormHelper.warningSimilarPersons(person.getNationalHealthId(), null, () -> { +// transferDataToPerson(createForm, person); +// FacadeProvider.getPersonFacade().save(person); +// }); +// } transferDataToPerson(createForm, person); FacadeProvider.getPersonFacade().save(person); @@ -835,18 +846,60 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( } else { // look for potential duplicate final PersonDto duplicatePerson = PersonDto.build(); - transferDataToPerson(createForm, duplicatePerson); - ControllerProvider.getPersonController() - .selectOrCreatePerson( - duplicatePerson, - I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), - selectedPerson -> { - if (selectedPerson != null) { - dto.setPerson(selectedPerson); - selectOrCreateCase(createForm, dto, selectedPerson); - } - }, - true); + + if (createForm.getWarningSimilarPersons() != null) { + CommitDiscardWrapperComponent warningPopUpDuplicatePerson = + (CommitDiscardWrapperComponent) editView.getWrappedComponent() + .getWarningSimilarPersons() + .getContent(); + + warningPopUpDuplicatePerson.getDiscardButton().setVisible(true); + warningPopUpDuplicatePerson.getCommitButton().setCaption("Continue to save"); + warningPopUpDuplicatePerson.addDoneListener(()-> { + VaadinUiUtil.showModalPopupWindow(caseCreateComponent, I18nProperties.getString(Strings.headingCreateNewCase)); + }); + warningPopUpDuplicatePerson.addCommitListener(() -> { + + transferDataToPerson(createForm, duplicatePerson); + ControllerProvider.getPersonController() + .selectOrCreatePerson( + duplicatePerson, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), + selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + selectOrCreateCase(createForm, dto, selectedPerson); + } + }, + true); + }); + } else { + transferDataToPerson(createForm, duplicatePerson); + ControllerProvider.getPersonController() + .selectOrCreatePerson( + duplicatePerson, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), + selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + selectOrCreateCase(createForm, dto, selectedPerson); + } + }, + true); + + } +// transferDataToPerson(createForm, duplicatePerson); +// ControllerProvider.getPersonController() +// .selectOrCreatePerson( +// duplicatePerson, +// I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), +// selectedPerson -> { +// if (selectedPerson != null) { +// dto.setPerson(selectedPerson); +// selectOrCreateCase(createForm, dto, selectedPerson); +// } +// }, +// true); } } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java index 5554342567e..6283b61ea39 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java @@ -31,6 +31,8 @@ import java.util.Date; import java.util.List; +import com.vaadin.ui.Window; +import de.symeda.sormas.ui.person.PersonFormHelper; import org.apache.commons.collections4.CollectionUtils; import com.google.common.collect.Sets; @@ -111,6 +113,7 @@ public class CaseCreateForm extends AbstractEditForm { private NullableOptionGroup ogCaseOrigin; private PersonCreateForm personCreateForm; + private Window warningSimilarPersons; private final boolean showHomeAddressForm; private final boolean showPersonSearchButton; @@ -209,6 +212,11 @@ protected void addFields() { personCreateForm.setWidth(100, Unit.PERCENTAGE); getContent().addComponent(personCreateForm, CaseDataDto.PERSON); + personCreateForm.getNationalHealthIdField().addTextFieldValueChangeListener(e -> { + warningSimilarPersons = PersonFormHelper + .warningSimilarPersons(personCreateForm.getNationalHealthIdField().getValue(), null, () -> warningSimilarPersons = null); + }); + // Jurisdiction fields Label jurisdictionHeadingLabel = new Label(I18nProperties.getString(Strings.headingCaseResponsibleJurisidction)); jurisdictionHeadingLabel.addStyleName(H3); @@ -730,4 +738,8 @@ public void setValue(CaseDataDto caseDataDto) throws com.vaadin.v7.data.Property public void setSearchedPerson(PersonDto searchedPerson) { personCreateForm.setSearchedPerson(searchedPerson); } + + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java index 03e117f37fa..88f53a0b9e9 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonController.java @@ -474,7 +474,14 @@ public CommitDiscardWrapperComponent getPersonEditComponent( editView.addCommitListener(() -> { if (!editForm.getFieldGroup().isModified()) { PersonDto dto = editForm.getValue(); - savePerson(dto); + if (editForm.getWarningSimilarPersons() != null) { + CommitDiscardWrapperComponent content = + (CommitDiscardWrapperComponent) editView.getWrappedComponent().getWarningSimilarPersons().getContent(); + content.getDiscardButton().setVisible(true); + content.addCommitListener(() -> savePerson(dto)); + } else { + savePerson(dto); + } } }); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java index 9f6cab9751c..02311ca226e 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java @@ -28,6 +28,8 @@ import java.util.List; import java.util.stream.Collectors; +import com.vaadin.ui.Window; +import de.symeda.sormas.ui.utils.components.TextFieldCustom; import org.apache.commons.lang3.StringUtils; import com.vaadin.icons.VaadinIcons; @@ -86,6 +88,8 @@ public class PersonCreateForm extends AbstractEditForm { private final boolean showPresentCondition; private final boolean showSymptomsOnsetDate; private final boolean showPersonSearchButton; + private TextFieldCustom nationalHealthIdField; + private Window warningSimilarPersons; private static final String HTML_LAYOUT = "%s" + fluidRow(fluidRowLocs(PersonDto.BIRTH_DATE_YYYY, PersonDto.BIRTH_DATE_MM, PersonDto.BIRTH_DATE_DD), fluidRowLocs(PersonDto.SEX)) @@ -186,7 +190,12 @@ protected void addFields() { ComboBox sex = addField(PersonDto.SEX, ComboBox.class); addField(PersonDto.PASSPORT_NUMBER, TextField.class); - addField(PersonDto.NATIONAL_HEALTH_ID, TextField.class); + + nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); +// nationalHealthIdField.addTextFieldValueChangeListener(e -> { +// warningSimilarPersons = +// PersonFormHelper.warningSimilarPersons(nationalHealthIdField.getValue(), null, () -> getContent()); +// }); ComboBox presentCondition = addField(PersonDto.PRESENT_CONDITION, ComboBox.class); presentCondition.setVisible(showPresentCondition); @@ -498,4 +507,12 @@ public PersonDto getSearchedPerson() { public void setSearchedPerson(PersonDto searchedPerson) { this.person = searchedPerson; } + + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } + + public TextFieldCustom getNationalHealthIdField() { + return nationalHealthIdField; + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java index 283d00c1d3c..6be5d4f0e0b 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java @@ -33,8 +33,12 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; +import com.vaadin.shared.Registration; +import com.vaadin.ui.Window; +import de.symeda.sormas.ui.utils.components.TextFieldCustom; import org.apache.commons.lang3.StringUtils; import com.vaadin.shared.ui.ErrorLevel; @@ -184,6 +188,8 @@ public class PersonEditForm extends AbstractEditForm { private boolean isPseudonymized; private LocationEditForm addressForm; private PresentConditionChangeListener presentConditionChangeListener; + private TextFieldCustom nationalHealthIdField; + private Window warningSimilarPersons; //@formatter:on public PersonEditForm( @@ -367,7 +373,7 @@ protected void addFields() { addField(PersonDto.PASSPORT_NUMBER); - TextField nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID); + nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); Label nationalHealthIdWarningLabel = new Label(I18nProperties.getString(Strings.messagePersonNationalHealthIdInvalid)); nationalHealthIdWarningLabel.addStyleNames(VSPACE_3, LABEL_WHITE_SPACE_NORMAL); nationalHealthIdWarningLabel.setVisible(false); @@ -383,6 +389,17 @@ protected void addFields() { getContent().addComponent(externalTokenWarningLabel, EXTERNAL_TOKEN_WARNING_LOC); addField(PersonDto.INTERNAL_TOKEN); + AtomicBoolean nationalHealthIdFirstLoading = new AtomicBoolean(true); + nationalHealthIdField.addTextFieldValueChangeListener(e -> { + String currentPersonUuid = this.getValue().getUuid(); + if (nationalHealthIdFirstLoading.get()) { + nationalHealthIdFirstLoading.set(false); + } else { + warningSimilarPersons = + PersonFormHelper.warningSimilarPersons(nationalHealthIdField.getValue(), currentPersonUuid, () -> warningSimilarPersons = null); + } + }); + addField(PersonDto.HAS_COVID_APP).addStyleName(CssStyles.FORCE_CAPTION_CHECKBOX); addField(PersonDto.COVID_CODE_DELIVERED).addStyleName(CssStyles.FORCE_CAPTION_CHECKBOX); @@ -905,6 +922,10 @@ public Field getLastNameField() { return lastNameField; } + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } + @Override protected F addFieldToLayout(CustomLayout layout, String propertyId, F field) { field.addValueChangeListener(e -> fireValueChange(false)); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFormHelper.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFormHelper.java new file mode 100644 index 00000000000..21afff244d3 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonFormHelper.java @@ -0,0 +1,54 @@ +package de.symeda.sormas.ui.person; + +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; + +import com.vaadin.server.Sizeable; +import com.vaadin.ui.Window; + +import de.symeda.sormas.api.FacadeProvider; +import de.symeda.sormas.api.i18n.Captions; +import de.symeda.sormas.api.i18n.I18nProperties; +import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.person.PersonSimilarityCriteria; +import de.symeda.sormas.api.person.SimilarPersonDto; +import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; +import de.symeda.sormas.ui.utils.VaadinUiUtil; + +public class PersonFormHelper { + + public static Window warningSimilarPersons(String nationalHealthId, String currentPersonUuid, Runnable callback) { + if (StringUtils.isNoneBlank(nationalHealthId)) { + PersonDto currentPerson = new PersonDto(); + currentPerson.setNationalHealthId(nationalHealthId); + List similarPersonDtos = + FacadeProvider.getPersonFacade().getSimilarPersonDtos(PersonSimilarityCriteria.forPerson(currentPerson, true)); + List filteredSimilarPersons = similarPersonDtos.stream() + .filter(similarPersonDto -> !similarPersonDto.getUuid().equals(currentPersonUuid)) + .collect(Collectors.toList()); + + if (!filteredSimilarPersons.isEmpty()) { + PersonSelectionGrid similarPersonGrid = new PersonSelectionGrid(); + similarPersonGrid.loadData(filteredSimilarPersons); + + final CommitDiscardWrapperComponent component = new CommitDiscardWrapperComponent<>(similarPersonGrid); + component.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionDone)); + component.getDiscardButton().setVisible(false); + component.getWrappedComponent().setWidth(800, Sizeable.Unit.PIXELS); + + Window popupWindow = VaadinUiUtil.showPopupWindow(component); + component.addDoneListener(() -> { + popupWindow.close(); + callback.run(); + }); + popupWindow.setCaption(I18nProperties.getString(Strings.headingSimilarPerson)); + popupWindow.setWidth(900, Sizeable.Unit.PIXELS); + return popupWindow; + } + } + return null; + } +} diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionField.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionField.java index 3cfdbf8d70f..8640ddf7df2 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionField.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionField.java @@ -269,7 +269,7 @@ protected void addFilterForm() { * Load a grid of all persons similar to the given reference person. */ protected void initializeGrid() { - defaultCriteria = PersonSimilarityCriteria.forPerson(referencePerson, true); + defaultCriteria = PersonSimilarityCriteria.forPerson(referencePerson, true, false); personGrid = new PersonSelectionGrid(); personGrid.addSelectionListener(e -> { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionGrid.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionGrid.java index 0762c264e40..e4fe4f63b59 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionGrid.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonSelectionGrid.java @@ -104,4 +104,11 @@ public void loadData(PersonSimilarityCriteria criteria) { getContainer().addAll(similarPersons); setHeightByRows(similarPersons.size() > 0 ? (Math.min(similarPersons.size(), 10)) : 1); } + + public void loadData(List similarPersons) { + getContainer().removeAllItems(); + getContainer().addAll(similarPersons); + setHeightByRows(similarPersons.size() > 0 ? (Math.min(similarPersons.size(), 10)) : 1); + } + } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java index fb3e4203bac..dba76e34844 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java @@ -21,9 +21,12 @@ import java.util.Collection; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.vaadin.navigator.ViewLeaveAction; +import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Validator; @@ -45,10 +48,17 @@ import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; +import de.symeda.sormas.api.person.PersonDto; +import de.symeda.sormas.api.person.PersonSimilarityCriteria; +import de.symeda.sormas.api.person.Sex; +import de.symeda.sormas.api.person.SimilarPersonDto; import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; +import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.utils.components.NotBlankTextValidator; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; public abstract class AbstractEditForm extends AbstractForm implements FieldGroup.CommitHandler {// implements DtoEditForm { @@ -613,4 +623,6 @@ protected boolean isEditableAllowed(String propertyId) { public void setHeading(String heading) { throw new RuntimeException("setHeading should be implemented in " + getClass().getSimpleName()); } + + } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java index f23d145988d..d7cd5d95382 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java @@ -43,6 +43,7 @@ import de.symeda.sormas.ui.utils.components.JsonForm; import de.symeda.sormas.ui.utils.components.MultiSelect; import de.symeda.sormas.ui.utils.components.MultiSelectFiles; +import de.symeda.sormas.ui.utils.components.TextFieldCustom; import de.symeda.sormas.ui.vaccination.VaccinationsField; public class SormasFieldGroupFieldFactory extends DefaultFieldGroupFieldFactory { @@ -191,6 +192,8 @@ public T createField(Class type, Class fieldType) { return (T) new CheckBoxTree<>(); } else if (RichTextArea.class.isAssignableFrom(fieldType)) { return (T) new RichTextArea(); + }else if (TextFieldCustom.class.isAssignableFrom(fieldType)) { + return (T) new TextFieldCustom(); } return super.createField(type, fieldType); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java new file mode 100644 index 00000000000..4371c0716d2 --- /dev/null +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java @@ -0,0 +1,61 @@ +package de.symeda.sormas.ui.utils.components; + +import java.lang.reflect.Method; + +import com.vaadin.event.SerializableEventListener; +import com.vaadin.shared.Registration; +import com.vaadin.ui.Component; +import com.vaadin.util.ReflectTools; +import com.vaadin.v7.data.Property; +import com.vaadin.v7.ui.AbstractField; +import com.vaadin.v7.ui.TextField; + +public class TextFieldCustom extends TextField { + + /* Value change events */ + + private static final Method VALUE_CHANGE_METHOD; + + static { + try { + VALUE_CHANGE_METHOD = Property.ValueChangeListener.class + .getDeclaredMethod("valueChange", + new Class[] { Property.ValueChangeEvent.class }); + } catch (final NoSuchMethodException e) { + // This should never happen + throw new RuntimeException( + "Internal error finding methods in AbstractField"); + } + } + + public Registration addTextFieldValueChangeListener(Property.ValueChangeListener listener) { + Registration registration = addListener(ValueChangeEvent.class, listener, + VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); + return registration; + } + + public interface TextFieldValueChangeListener extends SerializableEventListener { + + Method TEXTFIELD_CHANGE_METHOD = + ReflectTools.findMethod(TextFieldValueChangeListener.class, "textFieldValueChange", TextFieldValueChangeEvent.class); + + void textFieldValueChange(TextFieldValueChangeEvent event); + + } + + public static final class TextFieldValueChangeEvent extends Component.Event { + + private static final long serialVersionUID = 7689979222604215471L; + + public TextFieldValueChangeEvent(TextField source) { + super(source); + } + + public TextField getTextField() { + return (TextField) getComponent(); + } + } + +} From 89685ea58313afe6e4f6bf331f94d641d0992c8e Mon Sep 17 00:00:00 2001 From: SergiuPacurariu Date: Thu, 5 Dec 2024 12:10:54 +0200 Subject: [PATCH 2/3] #13181 - Enhance National Health ID Search Functionality Across Modules and Address Duplication Issues --- .../java/de/symeda/sormas/ui/MainScreen.java | 2 +- .../symeda/sormas/ui/caze/CaseController.java | 34 ++----- .../symeda/sormas/ui/caze/CaseCreateForm.java | 4 +- .../sormas/ui/contact/ContactController.java | 90 ++++++++++++++----- .../sormas/ui/contact/ContactCreateForm.java | 11 +++ .../immunization/ImmunizationController.java | 55 +++++++++--- .../form/ImmunizationCreationForm.java | 12 +++ .../sormas/ui/person/PersonCreateForm.java | 9 +- .../sormas/ui/person/PersonEditForm.java | 6 +- .../ui/travelentry/TravelEntryController.java | 46 ++++++++-- .../components/TravelEntryCreateForm.java | 11 +++ .../ui/utils/components/TextFieldCustom.java | 62 ++++--------- 12 files changed, 220 insertions(+), 122 deletions(-) diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java index 260e045d60f..00ecea96b08 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/MainScreen.java @@ -315,7 +315,7 @@ && permitted(FeatureType.ADVERSE_EVENTS_FOLLOWING_IMMUNIZATION_MANAGEMENT, UserR } if (permitted(FeatureType.TRAVEL_ENTRIES, UserRight.TRAVEL_ENTRY_MANAGEMENT_ACCESS) - && FacadeProvider.getConfigFacade().isConfiguredCountry(CountryHelper.COUNTRY_CODE_LUXEMBOURG)) { + && FacadeProvider.getConfigFacade().isConfiguredCountry(CountryHelper.COUNTRY_CODE_GERMANY)) { ControllerProvider.getTravelEntryController().registerViews(navigator); menu.addView( TravelEntriesView.class, diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java index 1e83418c063..c30af8de040 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java @@ -26,7 +26,6 @@ import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.StringUtils; import com.vaadin.navigator.Navigator; import com.vaadin.server.ExternalResource; @@ -131,7 +130,6 @@ import de.symeda.sormas.ui.externalsurveillanceservice.ExternalSurveillanceServiceGateway; import de.symeda.sormas.ui.hospitalization.HospitalizationForm; import de.symeda.sormas.ui.hospitalization.HospitalizationView; -import de.symeda.sormas.ui.person.PersonFormHelper; import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.symptoms.SymptomsForm; import de.symeda.sormas.ui.therapy.TherapyView; @@ -155,6 +153,7 @@ public class CaseController { CommitDiscardWrapperComponent caseCreateComponent; + boolean caseSaveTriggered; public CaseController() { @@ -723,6 +722,7 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( editView.addFieldGroups(createForm.getHomeAddressForm().getFieldGroup()); } + caseSaveTriggered = false; editView.addCommitListener(() -> { if (!createForm.getFieldGroup().isModified()) { final CaseDataDto dto = createForm.getValue(); @@ -745,12 +745,6 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( dto.getSymptoms().setOnsetDate(createForm.getOnsetDate()); dto.setWasInQuarantineBeforeIsolation(YesNoUnknown.YES); -// if (StringUtils.isNotEmpty(person.getNationalHealthId())) { -// PersonFormHelper.warningSimilarPersons(person.getNationalHealthId(), null, () -> { -// transferDataToPerson(createForm, person); -// FacadeProvider.getPersonFacade().save(person); -// }); -// } transferDataToPerson(createForm, person); FacadeProvider.getPersonFacade().save(person); @@ -854,12 +848,14 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( .getContent(); warningPopUpDuplicatePerson.getDiscardButton().setVisible(true); - warningPopUpDuplicatePerson.getCommitButton().setCaption("Continue to save"); - warningPopUpDuplicatePerson.addDoneListener(()-> { - VaadinUiUtil.showModalPopupWindow(caseCreateComponent, I18nProperties.getString(Strings.headingCreateNewCase)); + warningPopUpDuplicatePerson.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionContinue)); + warningPopUpDuplicatePerson.addDoneListener(() -> { + if (!caseSaveTriggered) { + VaadinUiUtil.showModalPopupWindow(caseCreateComponent, I18nProperties.getString(Strings.headingCreateNewCase)); + } }); warningPopUpDuplicatePerson.addCommitListener(() -> { - + caseSaveTriggered = true; transferDataToPerson(createForm, duplicatePerson); ControllerProvider.getPersonController() .selectOrCreatePerson( @@ -886,27 +882,13 @@ public CommitDiscardWrapperComponent getCaseCreateComponent( } }, true); - } -// transferDataToPerson(createForm, duplicatePerson); -// ControllerProvider.getPersonController() -// .selectOrCreatePerson( -// duplicatePerson, -// I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), -// selectedPerson -> { -// if (selectedPerson != null) { -// dto.setPerson(selectedPerson); -// selectOrCreateCase(createForm, dto, selectedPerson); -// } -// }, -// true); } } } }); return editView; - } private void selectOrCreateCase(CaseCreateForm createForm, CaseDataDto dto, PersonReferenceDto selectedPerson) { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java index 6283b61ea39..7c2b71d69a5 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseCreateForm.java @@ -31,12 +31,11 @@ import java.util.Date; import java.util.List; -import com.vaadin.ui.Window; -import de.symeda.sormas.ui.person.PersonFormHelper; import org.apache.commons.collections4.CollectionUtils; import com.google.common.collect.Sets; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.data.util.converter.Converter; import com.vaadin.v7.ui.AbstractSelect.ItemCaptionMode; @@ -74,6 +73,7 @@ import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.location.LocationEditForm; import de.symeda.sormas.ui.person.PersonCreateForm; +import de.symeda.sormas.ui.person.PersonFormHelper; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ComboBoxHelper; import de.symeda.sormas.ui.utils.CssStyles; diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java index 926e6d61662..5b0754a3562 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java @@ -93,6 +93,7 @@ import de.symeda.sormas.ui.contact.components.linelisting.layout.LineListingLayout; import de.symeda.sormas.ui.epidata.ContactEpiDataView; import de.symeda.sormas.ui.epidata.EpiDataForm; +import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.utils.AbstractView; import de.symeda.sormas.ui.utils.ArchiveHandlers; import de.symeda.sormas.ui.utils.BulkOperationHandler; @@ -110,6 +111,8 @@ public class ContactController { protected final Logger logger = LoggerFactory.getLogger(getClass()); + boolean contactSaveTriggered; + CommitDiscardWrapperComponent createComponent; public ContactController() { @@ -270,8 +273,7 @@ public void create(CaseReferenceDto caseRef, boolean asResultingCase, Runnable a if (caseRef != null) { caze = FacadeProvider.getCaseFacade().getCaseDataByUuid(caseRef.getUuid()); } - CommitDiscardWrapperComponent createComponent = - getContactCreateComponent(caze, asResultingCase, alternativeCallback, false); + createComponent = getContactCreateComponent(caze, asResultingCase, alternativeCallback, false); VaadinUiUtil.showModalPopupWindow(createComponent, I18nProperties.getString(Strings.headingCreateNewContact)); } @@ -452,6 +454,7 @@ public CommitDiscardWrapperComponent getContactCreateComponen final CommitDiscardWrapperComponent createComponent = new CommitDiscardWrapperComponent(createForm, UiUtil.permitted(UserRight.CONTACT_CREATE), createForm.getFieldGroup()); + contactSaveTriggered = false; createComponent.addCommitListener(() -> { if (!createForm.getFieldGroup().isModified()) { final ContactDto dto = createForm.getValue(); @@ -504,26 +507,73 @@ public CommitDiscardWrapperComponent getContactCreateComponen } else { final PersonDto person = PersonDto.build(); - transferDataToPerson(createForm, person); - ControllerProvider.getPersonController() - .selectOrCreatePerson(person, I18nProperties.getString(Strings.infoSelectOrCreatePersonForContact), selectedPerson -> { - if (selectedPerson != null) { - dto.setPerson(selectedPerson); - - selectOrCreateContact(dto, selectedPerson, selectedContactUuid -> { - if (selectedContactUuid != null) { - editData(selectedContactUuid); - } - }); - } - if (createForm.adoptAddressLayout.isAdoptAddress()) { - FacadeProvider.getPersonFacade() - .copyHomeAddress( - FacadeProvider.getCaseFacade().getByUuid(dto.getCaze().getUuid()).getPerson(), - dto.getPerson()); + if (createForm.getWarningSimilarPersons() != null) { + CommitDiscardWrapperComponent warningPopUpDuplicatePerson = + (CommitDiscardWrapperComponent) createComponent.getWrappedComponent() + .getWarningSimilarPersons() + .getContent(); + warningPopUpDuplicatePerson.getDiscardButton().setVisible(true); + warningPopUpDuplicatePerson.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionContinue)); + warningPopUpDuplicatePerson.addDoneListener(() -> { + if (!contactSaveTriggered) { + VaadinUiUtil.showModalPopupWindow(createComponent, I18nProperties.getString(Strings.headingCreateNewContact)); } - }, true); + }); + + warningPopUpDuplicatePerson.addCommitListener(() -> { + contactSaveTriggered = true; + transferDataToPerson(createForm, person); + + ControllerProvider.getPersonController() + .selectOrCreatePerson( + person, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForContact), + selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + + selectOrCreateContact(dto, selectedPerson, selectedContactUuid -> { + if (selectedContactUuid != null) { + editData(selectedContactUuid); + } + }); + } + if (createForm.adoptAddressLayout.isAdoptAddress()) { + FacadeProvider.getPersonFacade() + .copyHomeAddress( + FacadeProvider.getCaseFacade().getByUuid(dto.getCaze().getUuid()).getPerson(), + dto.getPerson()); + } + }, + true); + }); + } else { + transferDataToPerson(createForm, person); + + ControllerProvider.getPersonController() + .selectOrCreatePerson( + person, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForContact), + selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + + selectOrCreateContact(dto, selectedPerson, selectedContactUuid -> { + if (selectedContactUuid != null) { + editData(selectedContactUuid); + } + }); + } + if (createForm.adoptAddressLayout.isAdoptAddress()) { + FacadeProvider.getPersonFacade() + .copyHomeAddress( + FacadeProvider.getCaseFacade().getByUuid(dto.getCaze().getUuid()).getPerson(), + dto.getPerson()); + } + }, + true); + } } } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java index 715ea4072f3..e7c57c7d226 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactCreateForm.java @@ -27,6 +27,7 @@ import com.vaadin.shared.ui.ContentMode; import com.vaadin.ui.Button; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.ui.AbstractField; import com.vaadin.v7.ui.CheckBox; @@ -55,6 +56,7 @@ import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.person.PersonCreateForm; +import de.symeda.sormas.ui.person.PersonFormHelper; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ButtonHelper; import de.symeda.sormas.ui.utils.CssStyles; @@ -119,6 +121,7 @@ public class ContactCreateForm extends AbstractEditForm { ComboBox community; private final boolean showPersonSearchButton; + private Window warningSimilarPersons; /** * TODO use disease and case relation information given in ContactDto @@ -159,6 +162,11 @@ protected void addFields() { personCreateForm.setValue(new PersonDto()); getContent().addComponent(personCreateForm, ContactDto.PERSON); + personCreateForm.getNationalHealthIdField().addTextFieldValueChangeListener(e -> { + warningSimilarPersons = PersonFormHelper + .warningSimilarPersons(personCreateForm.getNationalHealthIdField().getValue(), null, () -> warningSimilarPersons = null); + }); + addField(ContactDto.RETURNING_TRAVELER, NullableOptionGroup.class); region = addInfrastructureField(ContactDto.REGION); district = addInfrastructureField(ContactDto.DISTRICT); @@ -430,4 +438,7 @@ private void updateDateComparison() { } } + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java index e39ccc96b84..6288c273cb2 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java @@ -30,6 +30,7 @@ import de.symeda.sormas.ui.immunization.components.fields.popup.SimilarImmunizationPopup; import de.symeda.sormas.ui.immunization.components.form.ImmunizationCreationForm; import de.symeda.sormas.ui.immunization.components.form.ImmunizationDataForm; +import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.utils.ArchiveHandlers; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; import de.symeda.sormas.ui.utils.NotificationHelper; @@ -40,6 +41,9 @@ public class ImmunizationController { + boolean immunizationSaveTriggered; + CommitDiscardWrapperComponent immunizationCreateComponent; + public void registerViews(Navigator navigator) { navigator.addView(ImmunizationsView.VIEW_NAME, ImmunizationsView.class); navigator.addView(ImmunizationDataView.VIEW_NAME, ImmunizationDataView.class); @@ -47,7 +51,7 @@ public void registerViews(Navigator navigator) { } public void create() { - CommitDiscardWrapperComponent immunizationCreateComponent = getImmunizationCreateComponent(); + immunizationCreateComponent = getImmunizationCreateComponent(); if (immunizationCreateComponent != null) { VaadinUiUtil.showModalPopupWindow(immunizationCreateComponent, I18nProperties.getString(Strings.headingCreateNewImmunization)); } @@ -81,6 +85,7 @@ private CommitDiscardWrapperComponent getImmunizationC currentUserProvider.hasUserRight(UserRight.IMMUNIZATION_CREATE), createForm.getFieldGroup()); + immunizationSaveTriggered = false; viewComponent.addCommitListener(() -> { if (!createForm.getFieldGroup().isModified()) { final ImmunizationDto dto = createForm.getValue(); @@ -90,16 +95,44 @@ private CommitDiscardWrapperComponent getImmunizationC selectOrCreateimmunizationForPerson(dto, searchedPerson.toReference()); } else { final PersonDto person = createForm.getPerson(); - ControllerProvider.getPersonController() - .selectOrCreatePerson( - person, - I18nProperties.getString(Strings.infoSelectOrCreatePersonForImmunization), - selectedPerson -> { - if (selectedPerson != null) { - selectOrCreateimmunizationForPerson(dto, selectedPerson); - } - }, - true); + if (createForm.getWarningSimilarPersons() != null) { + CommitDiscardWrapperComponent warningPopUpDuplicatePerson = + (CommitDiscardWrapperComponent) viewComponent.getWrappedComponent() + .getWarningSimilarPersons() + .getContent(); + warningPopUpDuplicatePerson.getDiscardButton().setVisible(true); + warningPopUpDuplicatePerson.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionContinue)); + warningPopUpDuplicatePerson.addDoneListener(() -> { + if (!immunizationSaveTriggered) { + VaadinUiUtil.showModalPopupWindow(viewComponent, I18nProperties.getString(Strings.headingCreateNewImmunization)); + } + }); + + warningPopUpDuplicatePerson.addCommitListener(() -> { + immunizationSaveTriggered = true; + ControllerProvider.getPersonController() + .selectOrCreatePerson( + person, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForImmunization), + selectedPerson -> { + if (selectedPerson != null) { + selectOrCreateimmunizationForPerson(dto, selectedPerson); + } + }, + true); + }); + } else { + ControllerProvider.getPersonController() + .selectOrCreatePerson( + person, + I18nProperties.getString(Strings.infoSelectOrCreatePersonForImmunization), + selectedPerson -> { + if (selectedPerson != null) { + selectOrCreateimmunizationForPerson(dto, selectedPerson); + } + }, + true); + } } } }); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java index d71f82c6f1f..87265176ea6 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/components/form/ImmunizationCreationForm.java @@ -27,6 +27,7 @@ import java.util.Collections; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.v7.ui.CheckBox; import com.vaadin.v7.ui.ComboBox; import com.vaadin.v7.ui.DateField; @@ -56,6 +57,7 @@ import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.person.PersonCreateForm; +import de.symeda.sormas.ui.person.PersonFormHelper; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.ComboBoxHelper; import de.symeda.sormas.ui.utils.DateComparisonValidator; @@ -96,6 +98,7 @@ public class ImmunizationCreationForm extends AbstractEditForm private ComboBox responsibleRegion; private ComboBox responsibleDistrict; private ComboBox responsibleCommunity; + private Window warningSimilarPersons; public ImmunizationCreationForm() { this(null, null); @@ -191,6 +194,11 @@ protected void addFields() { personCreateForm = new PersonCreateForm(false, true, false); personCreateForm.setWidth(100, Unit.PERCENTAGE); personCreateForm.setValue(new PersonDto()); + personCreateForm.getNationalHealthIdField().addTextFieldValueChangeListener(e -> { + warningSimilarPersons = PersonFormHelper + .warningSimilarPersons(personCreateForm.getNationalHealthIdField().getValue(), null, () -> warningSimilarPersons = null); + }); + diseaseField.addValueChangeListener( (ValueChangeListener) valueChangeEvent -> personCreateForm .updatePresentConditionEnum((Disease) valueChangeEvent.getProperty().getValue())); @@ -406,4 +414,8 @@ protected void setInternalValue(ImmunizationDto newValue) { hideAndFillJurisdictionFields(); } } + + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java index 02311ca226e..a1e9d757967 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java @@ -28,13 +28,12 @@ import java.util.List; import java.util.stream.Collectors; -import com.vaadin.ui.Window; -import de.symeda.sormas.ui.utils.components.TextFieldCustom; import org.apache.commons.lang3.StringUtils; import com.vaadin.icons.VaadinIcons; import com.vaadin.ui.Button; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.v7.data.validator.EmailValidator; import com.vaadin.v7.ui.AbstractSelect; import com.vaadin.v7.ui.AbstractSelect.ItemCaptionMode; @@ -67,6 +66,7 @@ import de.symeda.sormas.ui.utils.FieldHelper; import de.symeda.sormas.ui.utils.PhoneNumberValidator; import de.symeda.sormas.ui.utils.VaadinUiUtil; +import de.symeda.sormas.ui.utils.components.TextFieldCustom; public class PersonCreateForm extends AbstractEditForm { @@ -192,10 +192,7 @@ protected void addFields() { addField(PersonDto.PASSPORT_NUMBER, TextField.class); nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); -// nationalHealthIdField.addTextFieldValueChangeListener(e -> { -// warningSimilarPersons = -// PersonFormHelper.warningSimilarPersons(nationalHealthIdField.getValue(), null, () -> getContent()); -// }); + nationalHealthIdField.setNullRepresentation(""); ComboBox presentCondition = addField(PersonDto.PRESENT_CONDITION, ComboBox.class); presentCondition.setVisible(showPresentCondition); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java index 6be5d4f0e0b..ec3427adb6f 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java @@ -36,14 +36,12 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import com.vaadin.shared.Registration; -import com.vaadin.ui.Window; -import de.symeda.sormas.ui.utils.components.TextFieldCustom; import org.apache.commons.lang3.StringUtils; import com.vaadin.shared.ui.ErrorLevel; import com.vaadin.ui.CustomLayout; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Property; import com.vaadin.v7.ui.AbstractSelect; @@ -98,6 +96,7 @@ import de.symeda.sormas.ui.utils.SormasFieldGroupFieldFactory; import de.symeda.sormas.ui.utils.ValidationUtils; import de.symeda.sormas.ui.utils.ViewMode; +import de.symeda.sormas.ui.utils.components.TextFieldCustom; public class PersonEditForm extends AbstractEditForm { @@ -374,6 +373,7 @@ protected void addFields() { addField(PersonDto.PASSPORT_NUMBER); nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); + nationalHealthIdField.setNullRepresentation(""); Label nationalHealthIdWarningLabel = new Label(I18nProperties.getString(Strings.messagePersonNationalHealthIdInvalid)); nationalHealthIdWarningLabel.addStyleNames(VSPACE_3, LABEL_WHITE_SPACE_NORMAL); nationalHealthIdWarningLabel.setVisible(false); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java index 8432275a15c..78507946a95 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java @@ -20,6 +20,7 @@ import de.symeda.sormas.api.docgeneneration.DocumentWorkflow; import de.symeda.sormas.api.docgeneneration.RootEntityType; import de.symeda.sormas.api.document.DocumentRelatedEntityType; +import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; import de.symeda.sormas.api.person.PersonDto; @@ -32,6 +33,7 @@ import de.symeda.sormas.ui.ControllerProvider; import de.symeda.sormas.ui.SormasUI; import de.symeda.sormas.ui.UiUtil; +import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.travelentry.components.TravelEntryCreateForm; import de.symeda.sormas.ui.utils.ArchiveHandlers; import de.symeda.sormas.ui.utils.CommitDiscardWrapperComponent; @@ -43,6 +45,9 @@ public class TravelEntryController { + boolean travelEntrySaveTriggered; + CommitDiscardWrapperComponent travelEntryCreateComponent; + public void registerViews(Navigator navigator) { navigator.addView(TravelEntriesView.VIEW_NAME, TravelEntriesView.class); navigator.addView(TravelEntryDataView.VIEW_NAME, TravelEntryDataView.class); @@ -50,7 +55,7 @@ public void registerViews(Navigator navigator) { } public void create() { - CommitDiscardWrapperComponent travelEntryCreateComponent = getTravelEntryCreateComponent(null, null); + travelEntryCreateComponent = getTravelEntryCreateComponent(null, null); VaadinUiUtil.showModalPopupWindow(travelEntryCreateComponent, I18nProperties.getString(Strings.headingCreateNewTravelEntry)); } @@ -106,14 +111,39 @@ private CommitDiscardWrapperComponent getTravelEntryCreat if (dto.getPerson() == null) { final PersonDto person = createForm.getPerson(); - ControllerProvider.getPersonController() - .selectOrCreatePerson(person, I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), selectedPerson -> { - if (selectedPerson != null) { - dto.setPerson(selectedPerson); - FacadeProvider.getTravelEntryFacade().save(dto); - navigateToTravelEntry(dto.getUuid()); + if (createForm.getWarningSimilarPersons() != null) { + CommitDiscardWrapperComponent warningPopUpDuplicatePerson = + (CommitDiscardWrapperComponent) editView.getWrappedComponent() + .getWarningSimilarPersons() + .getContent(); + warningPopUpDuplicatePerson.getDiscardButton().setVisible(true); + warningPopUpDuplicatePerson.getCommitButton().setCaption(I18nProperties.getCaption(Captions.actionContinue)); + warningPopUpDuplicatePerson.addDoneListener(() -> { + if (!travelEntrySaveTriggered) { + VaadinUiUtil.showModalPopupWindow(editView, I18nProperties.getString(Strings.headingCreateNewImmunization)); } - }, true); + }); + warningPopUpDuplicatePerson.addCommitListener(() -> { + travelEntrySaveTriggered = true; + ControllerProvider.getPersonController() + .selectOrCreatePerson(person, I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + FacadeProvider.getTravelEntryFacade().save(dto); + navigateToTravelEntry(dto.getUuid()); + } + }, true); + }); + } else { + ControllerProvider.getPersonController() + .selectOrCreatePerson(person, I18nProperties.getString(Strings.infoSelectOrCreatePersonForCase), selectedPerson -> { + if (selectedPerson != null) { + dto.setPerson(selectedPerson); + FacadeProvider.getTravelEntryFacade().save(dto); + navigateToTravelEntry(dto.getUuid()); + } + }, true); + } } else { FacadeProvider.getTravelEntryFacade().save(dto); navigateToTravelEntry(dto.getUuid()); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/components/TravelEntryCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/components/TravelEntryCreateForm.java index f515eba3dfd..0e8e974759a 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/components/TravelEntryCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/components/TravelEntryCreateForm.java @@ -17,6 +17,7 @@ import org.apache.commons.collections4.CollectionUtils; import com.vaadin.ui.Label; +import com.vaadin.ui.Window; import com.vaadin.v7.data.util.converter.Converter; import com.vaadin.v7.ui.CheckBox; import com.vaadin.v7.ui.ComboBox; @@ -44,6 +45,7 @@ import de.symeda.sormas.ui.UiUtil; import de.symeda.sormas.ui.UserProvider; import de.symeda.sormas.ui.person.PersonCreateForm; +import de.symeda.sormas.ui.person.PersonFormHelper; import de.symeda.sormas.ui.travelentry.DEAFormBuilder; import de.symeda.sormas.ui.utils.AbstractEditForm; import de.symeda.sormas.ui.utils.FieldHelper; @@ -86,6 +88,7 @@ public class TravelEntryCreateForm extends AbstractEditForm { private PersonCreateForm personCreateForm; private final PersonReferenceDto personDto; + private Window warningSimilarPersons; public TravelEntryCreateForm() { this(null); @@ -156,6 +159,10 @@ protected void addFields() { personCreateForm.setWidth(100, Unit.PERCENTAGE); personCreateForm.setValue(new PersonDto()); getContent().addComponent(personCreateForm, TravelEntryDto.PERSON); + personCreateForm.getNationalHealthIdField().addTextFieldValueChangeListener(e -> { + warningSimilarPersons = PersonFormHelper + .warningSimilarPersons(personCreateForm.getNationalHealthIdField().getValue(), null, () -> warningSimilarPersons = null); + }); regionCombo.addItems(FacadeProvider.getRegionFacade().getAllActiveByServerCountry()); regionCombo.addValueChangeListener(e -> { @@ -315,4 +322,8 @@ public void setValue(TravelEntryDto newFieldValue) throws ReadOnlyException, Con responsibleCommunity.setReadOnly(true); } } + + public Window getWarningSimilarPersons() { + return warningSimilarPersons; + } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java index 4371c0716d2..49d41d45e09 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java @@ -2,60 +2,32 @@ import java.lang.reflect.Method; -import com.vaadin.event.SerializableEventListener; import com.vaadin.shared.Registration; -import com.vaadin.ui.Component; -import com.vaadin.util.ReflectTools; import com.vaadin.v7.data.Property; -import com.vaadin.v7.ui.AbstractField; import com.vaadin.v7.ui.TextField; public class TextFieldCustom extends TextField { - /* Value change events */ + /* Value change events */ - private static final Method VALUE_CHANGE_METHOD; + private static final Method VALUE_CHANGE_METHOD; - static { - try { - VALUE_CHANGE_METHOD = Property.ValueChangeListener.class - .getDeclaredMethod("valueChange", - new Class[] { Property.ValueChangeEvent.class }); - } catch (final NoSuchMethodException e) { - // This should never happen - throw new RuntimeException( - "Internal error finding methods in AbstractField"); - } - } - - public Registration addTextFieldValueChangeListener(Property.ValueChangeListener listener) { - Registration registration = addListener(ValueChangeEvent.class, listener, - VALUE_CHANGE_METHOD); - // ensure "automatic immediate handling" works - markAsDirty(); - return registration; - } - - public interface TextFieldValueChangeListener extends SerializableEventListener { - - Method TEXTFIELD_CHANGE_METHOD = - ReflectTools.findMethod(TextFieldValueChangeListener.class, "textFieldValueChange", TextFieldValueChangeEvent.class); - - void textFieldValueChange(TextFieldValueChangeEvent event); - - } - - public static final class TextFieldValueChangeEvent extends Component.Event { - - private static final long serialVersionUID = 7689979222604215471L; - - public TextFieldValueChangeEvent(TextField source) { - super(source); - } - - public TextField getTextField() { - return (TextField) getComponent(); + static { + try { + VALUE_CHANGE_METHOD = Property.ValueChangeListener.class.getDeclaredMethod( + "valueChange", + new Class[] { + Property.ValueChangeEvent.class }); + } catch (final NoSuchMethodException e) { + // This should never happen + throw new RuntimeException("Internal error finding methods in AbstractField"); } } + public Registration addTextFieldValueChangeListener(Property.ValueChangeListener listener) { + Registration registration = addListener(ValueChangeEvent.class, listener, VALUE_CHANGE_METHOD); + // ensure "automatic immediate handling" works + markAsDirty(); + return registration; + } } From 6c9f438f81839e772f055633aa3a33c806f4ee87 Mon Sep 17 00:00:00 2001 From: SergiuPacurariu Date: Fri, 6 Dec 2024 13:55:22 +0200 Subject: [PATCH 3/3] #13181 - Enhance National Health ID Search Functionality Across Modules and Address Duplication Issues - changes after review --- sormas-api/src/main/resources/strings.properties | 2 +- .../de/symeda/sormas/ui/caze/CaseController.java | 4 ++-- .../symeda/sormas/ui/contact/ContactController.java | 4 ++-- .../ui/immunization/ImmunizationController.java | 4 ++-- .../de/symeda/sormas/ui/person/PersonCreateForm.java | 8 ++++---- .../de/symeda/sormas/ui/person/PersonEditForm.java | 6 +++--- .../sormas/ui/travelentry/TravelEntryController.java | 4 ++-- .../de/symeda/sormas/ui/utils/AbstractEditForm.java | 12 ------------ .../ui/utils/SormasFieldGroupFieldFactory.java | 6 +++--- .../{TextFieldCustom.java => SormasTextField.java} | 2 +- 10 files changed, 20 insertions(+), 32 deletions(-) rename sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/{TextFieldCustom.java => SormasTextField.java} (94%) diff --git a/sormas-api/src/main/resources/strings.properties b/sormas-api/src/main/resources/strings.properties index 7f03cdf3778..2e9723c6cf6 100644 --- a/sormas-api/src/main/resources/strings.properties +++ b/sormas-api/src/main/resources/strings.properties @@ -697,7 +697,7 @@ headingShowExternalMessage = Message headingSelfReportSideComponent = Self reports headingSignsAndSymptoms = Clinical Signs and Symptoms headingSimilarImmunization = Similar immunizaton -headingSimilarPerson = Similar persons found based on person introduced data +headingSimilarPerson = There are other persons with similar national health Id headingSyncUsers = Sync Users headingTasksDeleted = Tasks deleted headingTasksNotDeleted = None of the tasks were deleted diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java index c30af8de040..2c0b8db9493 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/caze/CaseController.java @@ -152,8 +152,8 @@ public class CaseController { - CommitDiscardWrapperComponent caseCreateComponent; - boolean caseSaveTriggered; + private CommitDiscardWrapperComponent caseCreateComponent; + private boolean caseSaveTriggered; public CaseController() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java index 5b0754a3562..24a49fb16e7 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java @@ -111,8 +111,8 @@ public class ContactController { protected final Logger logger = LoggerFactory.getLogger(getClass()); - boolean contactSaveTriggered; - CommitDiscardWrapperComponent createComponent; + private boolean contactSaveTriggered; + private CommitDiscardWrapperComponent createComponent; public ContactController() { diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java index 6288c273cb2..7e535b5e0cd 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/immunization/ImmunizationController.java @@ -41,8 +41,8 @@ public class ImmunizationController { - boolean immunizationSaveTriggered; - CommitDiscardWrapperComponent immunizationCreateComponent; + private boolean immunizationSaveTriggered; + private CommitDiscardWrapperComponent immunizationCreateComponent; public void registerViews(Navigator navigator) { navigator.addView(ImmunizationsView.VIEW_NAME, ImmunizationsView.class); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java index a1e9d757967..0827f474a00 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonCreateForm.java @@ -66,7 +66,7 @@ import de.symeda.sormas.ui.utils.FieldHelper; import de.symeda.sormas.ui.utils.PhoneNumberValidator; import de.symeda.sormas.ui.utils.VaadinUiUtil; -import de.symeda.sormas.ui.utils.components.TextFieldCustom; +import de.symeda.sormas.ui.utils.components.SormasTextField; public class PersonCreateForm extends AbstractEditForm { @@ -88,7 +88,7 @@ public class PersonCreateForm extends AbstractEditForm { private final boolean showPresentCondition; private final boolean showSymptomsOnsetDate; private final boolean showPersonSearchButton; - private TextFieldCustom nationalHealthIdField; + private SormasTextField nationalHealthIdField; private Window warningSimilarPersons; private static final String HTML_LAYOUT = @@ -191,7 +191,7 @@ protected void addFields() { addField(PersonDto.PASSPORT_NUMBER, TextField.class); - nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); + nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, SormasTextField.class); nationalHealthIdField.setNullRepresentation(""); ComboBox presentCondition = addField(PersonDto.PRESENT_CONDITION, ComboBox.class); @@ -509,7 +509,7 @@ public Window getWarningSimilarPersons() { return warningSimilarPersons; } - public TextFieldCustom getNationalHealthIdField() { + public SormasTextField getNationalHealthIdField() { return nationalHealthIdField; } } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java index ec3427adb6f..c1d2af88566 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/person/PersonEditForm.java @@ -96,7 +96,7 @@ import de.symeda.sormas.ui.utils.SormasFieldGroupFieldFactory; import de.symeda.sormas.ui.utils.ValidationUtils; import de.symeda.sormas.ui.utils.ViewMode; -import de.symeda.sormas.ui.utils.components.TextFieldCustom; +import de.symeda.sormas.ui.utils.components.SormasTextField; public class PersonEditForm extends AbstractEditForm { @@ -187,7 +187,7 @@ public class PersonEditForm extends AbstractEditForm { private boolean isPseudonymized; private LocationEditForm addressForm; private PresentConditionChangeListener presentConditionChangeListener; - private TextFieldCustom nationalHealthIdField; + private SormasTextField nationalHealthIdField; private Window warningSimilarPersons; //@formatter:on @@ -372,7 +372,7 @@ protected void addFields() { addField(PersonDto.PASSPORT_NUMBER); - nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, TextFieldCustom.class); + nationalHealthIdField = addField(PersonDto.NATIONAL_HEALTH_ID, SormasTextField.class); nationalHealthIdField.setNullRepresentation(""); Label nationalHealthIdWarningLabel = new Label(I18nProperties.getString(Strings.messagePersonNationalHealthIdInvalid)); nationalHealthIdWarningLabel.addStyleNames(VSPACE_3, LABEL_WHITE_SPACE_NORMAL); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java index 78507946a95..579d7702030 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/travelentry/TravelEntryController.java @@ -45,8 +45,8 @@ public class TravelEntryController { - boolean travelEntrySaveTriggered; - CommitDiscardWrapperComponent travelEntryCreateComponent; + private boolean travelEntrySaveTriggered; + private CommitDiscardWrapperComponent travelEntryCreateComponent; public void registerViews(Navigator navigator) { navigator.addView(TravelEntriesView.VIEW_NAME, TravelEntriesView.class); diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java index dba76e34844..fb3e4203bac 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/AbstractEditForm.java @@ -21,12 +21,9 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import com.vaadin.navigator.ViewLeaveAction; -import com.vaadin.ui.Window; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Validator; @@ -48,17 +45,10 @@ import de.symeda.sormas.api.i18n.Captions; import de.symeda.sormas.api.i18n.I18nProperties; import de.symeda.sormas.api.i18n.Strings; -import de.symeda.sormas.api.person.PersonDto; -import de.symeda.sormas.api.person.PersonSimilarityCriteria; -import de.symeda.sormas.api.person.Sex; -import de.symeda.sormas.api.person.SimilarPersonDto; import de.symeda.sormas.api.utils.fieldaccess.UiFieldAccessCheckers; import de.symeda.sormas.api.utils.fieldvisibility.FieldVisibilityCheckers; import de.symeda.sormas.ui.clinicalcourse.HealthConditionsForm; -import de.symeda.sormas.ui.person.PersonSelectionGrid; import de.symeda.sormas.ui.utils.components.NotBlankTextValidator; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.StringUtils; public abstract class AbstractEditForm extends AbstractForm implements FieldGroup.CommitHandler {// implements DtoEditForm { @@ -623,6 +613,4 @@ protected boolean isEditableAllowed(String propertyId) { public void setHeading(String heading) { throw new RuntimeException("setHeading should be implemented in " + getClass().getSimpleName()); } - - } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java index d7cd5d95382..11d08a40b3d 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/SormasFieldGroupFieldFactory.java @@ -43,7 +43,7 @@ import de.symeda.sormas.ui.utils.components.JsonForm; import de.symeda.sormas.ui.utils.components.MultiSelect; import de.symeda.sormas.ui.utils.components.MultiSelectFiles; -import de.symeda.sormas.ui.utils.components.TextFieldCustom; +import de.symeda.sormas.ui.utils.components.SormasTextField; import de.symeda.sormas.ui.vaccination.VaccinationsField; public class SormasFieldGroupFieldFactory extends DefaultFieldGroupFieldFactory { @@ -192,8 +192,8 @@ public T createField(Class type, Class fieldType) { return (T) new CheckBoxTree<>(); } else if (RichTextArea.class.isAssignableFrom(fieldType)) { return (T) new RichTextArea(); - }else if (TextFieldCustom.class.isAssignableFrom(fieldType)) { - return (T) new TextFieldCustom(); + }else if (SormasTextField.class.isAssignableFrom(fieldType)) { + return (T) new SormasTextField(); } return super.createField(type, fieldType); } diff --git a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/SormasTextField.java similarity index 94% rename from sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java rename to sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/SormasTextField.java index 49d41d45e09..7245a6c9b8b 100644 --- a/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/TextFieldCustom.java +++ b/sormas-ui/src/main/java/de/symeda/sormas/ui/utils/components/SormasTextField.java @@ -6,7 +6,7 @@ import com.vaadin.v7.data.Property; import com.vaadin.v7.ui.TextField; -public class TextFieldCustom extends TextField { +public class SormasTextField extends TextField { /* Value change events */