Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* SORMAS® - Surveillance Outbreak Response Management & Analysis System
* Copyright © 2016-2026 SORMAS Foundation gGmbH
* This program 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.
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/

package de.symeda.sormas.api.externalmessage;

import java.util.Date;
Expand All @@ -16,6 +31,7 @@ public interface ExternalMessageAdapterFacade {
ExternalMessageResult<List<ExternalMessageDto>> getExternalMessages(Date since);

/**
* The method should return the HTML source to display a structured/simpler view of the message.
*
* @param message
* message to be converted
Expand All @@ -24,6 +40,18 @@ public interface ExternalMessageAdapterFacade {
*/
ExternalMessageResult<String> convertToHTML(ExternalMessageDto message);

/**
* The method should return the HTML source to display a detailed view of the message.
*
* @param message
* message to be converted
* @return An ExternalMessageResult with a String that is a full/raw HTML representation of the message,
* Falls back to {@link #convertToHTML(ExternalMessageDto)} by default.
*/
default ExternalMessageResult<String> convertToDetailedHTML(ExternalMessageDto message) {
return convertToHTML(message);
}

/**
*
* @param message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1979,6 +1979,7 @@ public interface Captions {
String externalMessage_deleteNewlyCreatedCase = "externalMessage.deleteNewlyCreatedCase";
String externalMessage_deleteNewlyCreatedContact = "externalMessage.deleteNewlyCreatedContact";
String externalMessage_deleteNewlyCreatedEventParticipant = "externalMessage.deleteNewlyCreatedEventParticipant";
String externalMessage_detailedView = "externalMessage.detailedView";
String ExternalMessage_disease = "ExternalMessage.disease";
String ExternalMessage_diseaseVariant = "ExternalMessage.diseaseVariant";
String ExternalMessage_diseaseVariantDetails = "ExternalMessage.diseaseVariantDetails";
Expand Down Expand Up @@ -2012,6 +2013,7 @@ public interface Captions {
String ExternalMessage_sampleReceivedDate = "ExternalMessage.sampleReceivedDate";
String ExternalMessage_specimenCondition = "ExternalMessage.specimenCondition";
String ExternalMessage_status = "ExternalMessage.status";
String externalMessage_structuredView = "externalMessage.structuredView";
String ExternalMessage_surveillanceReport = "ExternalMessage.surveillanceReport";
String ExternalMessage_type = "ExternalMessage.type";
String ExternalMessageCriteria_birthDateFrom = "ExternalMessageCriteria.birthDateFrom";
Expand Down
2 changes: 2 additions & 0 deletions sormas-api/src/main/resources/captions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,8 @@ infrastructureImportAllowOverwrite=Overwrite existing entries with imported data
#External Message
ExternalMessage=Message
ExternalMessage.labMessageDetails=Message details
externalMessage.structuredView=Structured view
externalMessage.detailedView=Detailed view
ExternalMessage.labSampleId=Lab sample ID
ExternalMessage.messageDateTime=Message date
ExternalMessage.personBirthDateDD=Day of birth
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
/*
* SORMAS® - Surveillance Outbreak Response Management & Analysis System
* Copyright © 2016-2026 SORMAS Foundation gGmbH
* This program 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.
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/

package de.symeda.sormas.ui.externalmessage;

import static de.symeda.sormas.ui.utils.LayoutUtil.fluidRowLocs;
Expand All @@ -10,26 +25,41 @@
import com.vaadin.ui.CustomLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.v7.data.util.converter.Converter;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.VerticalLayout;

import de.symeda.sormas.api.FacadeProvider;
import de.symeda.sormas.api.externalmessage.ExternalMessageDto;
import de.symeda.sormas.api.externalmessage.ExternalMessageResult;
import de.symeda.sormas.api.i18n.Captions;
import de.symeda.sormas.api.i18n.I18nProperties;
import de.symeda.sormas.ui.utils.AbstractEditForm;
import de.symeda.sormas.ui.utils.VaadinUiUtil;

@SuppressWarnings({
"java:S110", // suppress sonar too many parents warning
"java:S2160" // equals not overridden; value-equality is not needed for Vaadin form components
})
public class ExternalMessageForm extends AbstractEditForm<ExternalMessageDto> {

private static final long serialVersionUID = -3859401780981133265L;

//@formatter:off
private static final String HTML_LAYOUT =
fluidRowLocs(ExternalMessageDto.UUID, ExternalMessageDto.MESSAGE_DATE_TIME) +
fluidRowLocs(ExternalMessageDto.UUID, ExternalMessageDto.MESSAGE_DATE_TIME) +
fluidRowLocs(ExternalMessageDto.EXTERNAL_MESSAGE_DETAILS);
//@formatter:on

private Panel detailsPanel;
private TabSheet detailsTabSheet;
private Panel structuredViewPanel;
@SuppressWarnings("java:S1450") // referenced in addFields, tab listener and setValue - cannot be local
private Panel detailedViewPanel;
private VerticalLayout structuredViewContainer;
private VerticalLayout detailedViewContainer;
private boolean structuredViewLoaded;
private boolean detailedViewLoaded;

@SuppressWarnings("java:S1948") // Logger is effectively serializable via its name
private final Logger logger = LoggerFactory.getLogger(getClass());

public ExternalMessageForm() {
Expand All @@ -40,10 +70,44 @@ public ExternalMessageForm() {
protected void addFields() {
addFields(ExternalMessageDto.UUID, ExternalMessageDto.MESSAGE_DATE_TIME);

detailsPanel = new Panel();
detailsPanel.setHeightFull();
detailsPanel.addStyleName("lab-message-details");
getContent().addComponent(detailsPanel, ExternalMessageDto.EXTERNAL_MESSAGE_DETAILS);
structuredViewContainer = new VerticalLayout();
structuredViewContainer.setMargin(false);
structuredViewContainer.setSizeUndefined();

structuredViewPanel = new Panel();
structuredViewPanel.setSizeFull();
structuredViewPanel.addStyleName("lab-message-structured-view");
structuredViewPanel.setContent(structuredViewContainer);

detailedViewContainer = new VerticalLayout();
detailedViewContainer.setMargin(false);
detailedViewContainer.setSizeUndefined();

detailedViewPanel = new Panel();
detailedViewPanel.setSizeFull();
detailedViewPanel.addStyleName("lab-message-detailed-view");
detailedViewPanel.setContent(detailedViewContainer);

detailsTabSheet = new TabSheet();
detailsTabSheet.setSizeFull();
detailsTabSheet.addStyleName("lab-message-details");
detailsTabSheet.addTab(structuredViewPanel, I18nProperties.getCaption(Captions.externalMessage_structuredView));
detailsTabSheet.addTab(detailedViewPanel, I18nProperties.getCaption(Captions.externalMessage_detailedView));

detailsTabSheet.addSelectedTabChangeListener(event -> {
ExternalMessageDto msg = getValue();
if (msg == null) {
return;
}
Component selected = event.getTabSheet().getSelectedTab();
if (selected == structuredViewPanel) {
loadStructuredView(msg);
} else if (selected == detailedViewPanel) {
loadDetailedView(msg);
}
});

getContent().addComponent(detailsTabSheet, ExternalMessageDto.EXTERNAL_MESSAGE_DETAILS);
}

@Override
Expand All @@ -52,23 +116,57 @@ protected String createHtmlLayout() {
}

@Override
public void setValue(ExternalMessageDto externalMessage) throws ReadOnlyException, Converter.ConversionException {
public void setValue(ExternalMessageDto externalMessage) {
super.setValue(externalMessage);
getFieldGroup().setReadOnly(true);
structuredViewLoaded = false;
detailedViewLoaded = false;
structuredViewContainer.removeAllComponents();
detailedViewContainer.removeAllComponents();
loadStructuredView(externalMessage);
detailsTabSheet.setSelectedTab(structuredViewPanel);
}

private void loadStructuredView(ExternalMessageDto externalMessage) {
if (structuredViewLoaded) {
return;
}
try {
ExternalMessageResult<String> result = FacadeProvider.getExternalLabResultsFacade().convertToHTML(externalMessage);
if (result.isSuccess()) {
CustomLayout layout = new CustomLayout();
layout.setTemplateContents(result.getValue());
structuredViewContainer.addComponent(layout);
} else {
structuredViewContainer.addComponent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
VaadinUiUtil.showWarningPopup(result.getError());
}
} catch (Exception e) {
structuredViewContainer.addComponent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
logger.error(e.getMessage());
}
structuredViewLoaded = true;
}

private void loadDetailedView(ExternalMessageDto externalMessage) {
if (detailedViewLoaded) {
return;
}
try {
ExternalMessageResult<String> htmlConversionResult = FacadeProvider.getExternalLabResultsFacade().convertToHTML(externalMessage);
if (htmlConversionResult.isSuccess()) {
CustomLayout externalMessageDetails = new CustomLayout();
externalMessageDetails.setTemplateContents(htmlConversionResult.getValue());
detailsPanel.setContent(externalMessageDetails);
ExternalMessageResult<String> result = FacadeProvider.getExternalLabResultsFacade().convertToDetailedHTML(externalMessage);
if (result.isSuccess()) {
CustomLayout layout = new CustomLayout();
layout.setTemplateContents(result.getValue());
detailedViewContainer.addComponent(layout);
} else {
detailsPanel.setContent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
VaadinUiUtil.showWarningPopup(htmlConversionResult.getError());
detailedViewContainer.addComponent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
VaadinUiUtil.showWarningPopup(result.getError());
}
} catch (Exception e) {
detailsPanel.setContent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
detailedViewContainer.addComponent(createXmlDisplay(externalMessage.getExternalMessageDetails()));
logger.error(e.getMessage());
}
detailedViewLoaded = true;
}

private Component createXmlDisplay(String xml) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
user-select: text;
}

.lab-message-structured-view .v-customlayout {
min-width: 500px;
}

.lab-message-detailed-view .v-customlayout {
min-width: max-content;
}

.lab-message-processable,
.lab-message-slider {
.lab-message-details {
Expand All @@ -20,6 +28,7 @@
}

.no-required-border {

.v-textfield.v-required,
.v-filterselect.v-required .v-filterselect-input,
.v-customcomponent.v-required .v-datefield-textfield,
Expand Down
Loading