Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit f99a5a5

Browse files
SORMAS-Foundation#2476 apply date filters and warn the user if there are too many contacts to display on the network diagram dashboard widget (SORMAS-Foundation#2857)
* SORMAS-Foundation#2476 apply date filters and warn the user if there are too many contacts to display on the network diagram dashboard widget
1 parent 4f9da71 commit f99a5a5

8 files changed

Lines changed: 135 additions & 68 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Strings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public interface Strings {
106106
String confirmationReduceQuarantine = "confirmationReduceQuarantine";
107107
String confirmationRemoveUserAsOfficer = "confirmationRemoveUserAsOfficer";
108108
String confirmationUpdateCompleteness = "confirmationUpdateCompleteness";
109+
String confirmNetworkDiagramTooManyContacts = "confirmNetworkDiagramTooManyContacts";
109110
String day = "day";
110111
String DiseaseNetworkDiagram_Classification_HEALTHY = "DiseaseNetworkDiagram.Classification.HEALTHY";
111112
String DiseaseNetworkDiagram_heading = "DiseaseNetworkDiagram.heading";
@@ -308,6 +309,7 @@ public interface Strings {
308309
String headingMissingDateFilter = "headingMissingDateFilter";
309310
String headingMissingEpiWeekFilter = "headingMissingEpiWeekFilter";
310311
String headingMyTasks = "headingMyTasks";
312+
String headingNetworkDiagramTooManyContacts = "headingNetworkDiagramTooManyContacts";
311313
String headingNewCases = "headingNewCases";
312314
String headingNewEvents = "headingNewEvents";
313315
String headingNewPassword = "headingNewPassword";
@@ -756,6 +758,7 @@ public interface Strings {
756758
String unsavedChanges_warningMessage = "unsavedChanges.warningMessage";
757759
String unsavedChanges_warningTitle = "unsavedChanges.warningTitle";
758760
String until = "until";
761+
String warningNetworkDiagramTooManyContacts = "warningNetworkDiagramTooManyContacts";
759762
String week = "week";
760763
String weekShort = "weekShort";
761764
String year = "year";

sormas-api/src/main/java/de/symeda/sormas/api/visualization/VisualizationFacade.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package de.symeda.sormas.api.visualization;
1919

2020
import java.util.Collection;
21+
import java.util.Date;
2122

2223
import javax.ejb.Remote;
2324

@@ -29,5 +30,13 @@
2930
@Remote
3031
public interface VisualizationFacade {
3132

32-
String buildTransmissionChainJson(RegionReferenceDto region, DistrictReferenceDto district, Collection<Disease> diseases, Language language);
33+
String buildTransmissionChainJson(
34+
Date fromDate,
35+
Date toDate,
36+
RegionReferenceDto region,
37+
DistrictReferenceDto district,
38+
Collection<Disease> diseases,
39+
Language language);
40+
41+
Long getContactCount(Date fromDate, Date toDate, RegionReferenceDto region, DistrictReferenceDto district, Collection<Disease> diseases);
3342
}

sormas-api/src/main/resources/strings.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,3 +804,7 @@ unsavedChanges.warningTitle = Confirm navigation
804804
unsavedChanges.warningMessage = You have unsaved changes on this form.
805805
unsavedChanges.discard = Discard changes
806806
unsavedChanges.save = Save changes
807+
808+
headingNetworkDiagramTooManyContacts = Too many contacts
809+
warningNetworkDiagramTooManyContacts = There are %d contacts and it is possible that your browser will freeze while displaying the diagram.<br/>Please choose a smaller time window.
810+
confirmNetworkDiagramTooManyContacts = Do you really want to update the diagram?

sormas-backend/src/main/java/de/symeda/sormas/backend/visualization/VisualizationFacadeEjb.java

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.Arrays;
3030
import java.util.Collection;
3131
import java.util.Collections;
32+
import java.util.Date;
3233
import java.util.HashMap;
3334
import java.util.Map;
3435
import java.util.Optional;
@@ -46,6 +47,7 @@
4647
import javax.persistence.criteria.CriteriaQuery;
4748
import javax.persistence.criteria.Join;
4849
import javax.persistence.criteria.JoinType;
50+
import javax.persistence.criteria.Predicate;
4951
import javax.persistence.criteria.Root;
5052

5153
import org.apache.commons.io.FileUtils;
@@ -79,7 +81,7 @@
7981
public class VisualizationFacadeEjb implements VisualizationFacade {
8082

8183
static final String SORMAS_DATA_POOL_JNDI = "jdbc/sormasDataPool";
82-
84+
8385
// private static final String TRANSMISSION_CHAIN_SCRIPT = "transmission_chain.r";
8486
private static final String TRANSMISSION_CHAIN_SCRIPT = "transform_contact.R";
8587
private static final String[] REQUIRED_SCRIPTS = {
@@ -98,6 +100,8 @@ public class VisualizationFacadeEjb implements VisualizationFacade {
98100

99101
@Override
100102
public String buildTransmissionChainJson(
103+
Date fromDate,
104+
Date toDate,
101105
RegionReferenceDto region,
102106
DistrictReferenceDto district,
103107
Collection<Disease> diseases,
@@ -109,7 +113,7 @@ public String buildTransmissionChainJson(
109113
}
110114
Path tempBasePath = new File(configFacade.getTempFilesPath()).toPath();
111115

112-
Collection<Long> contactIds = getContactIds(region, district, diseases);
116+
Collection<Long> contactIds = getContactIds(fromDate, toDate, region, district, diseases);
113117

114118
if (contactIds.isEmpty()) {
115119
return null;
@@ -121,31 +125,65 @@ public String buildTransmissionChainJson(
121125
return buildTransmissionChainJson(rExecutable, tempBasePath, domainXmlPath, contactIds, language);
122126
}
123127

124-
private Collection<Long> getContactIds(RegionReferenceDto region, DistrictReferenceDto district, Collection<Disease> diseases) {
128+
@Override
129+
public Long getContactCount(Date fromDate, Date toDate, RegionReferenceDto region, DistrictReferenceDto district, Collection<Disease> diseases) {
125130

126131
CriteriaBuilder cb = em.getCriteriaBuilder();
127132
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
128133
Root<Contact> root = cq.from(Contact.class);
129-
Join<Contact, Case> caze = root.join(Contact.CAZE, JoinType.LEFT);
130134

131-
cq.where(
132-
AbstractAdoService.and(
133-
cb,
134-
contactService.createUserFilter(cb, cq, root),
135-
contactService.createActiveContactsFilter(cb, root),
136-
contactService.createDefaultFilter(cb, root),
137-
cb.notEqual(root.get(Contact.CONTACT_CLASSIFICATION), ContactClassification.NO_CONTACT),
138-
cb.or(
139-
cb.isNull(caze),
140-
cb.and(caseService.createDefaultFilter(cb, caze), cb.notEqual(caze.get(Case.CASE_CLASSIFICATION), CaseClassification.NO_CASE))),
141-
root.get(Contact.DISEASE).in(diseases),
142-
region == null ? null : cb.equal(root.join(Contact.REGION).get(Region.UUID), region.getUuid()),
143-
district == null ? null : cb.equal(root.join(Contact.DISTRICT).get(District.UUID), district.getUuid())));
135+
cq.where(buildContactFilters(cb, cq, root, fromDate, toDate, region, district, diseases));
136+
137+
cq.select(cb.count(root.get(AbstractDomainObject.ID)));
138+
139+
return em.createQuery(cq).getSingleResult();
140+
}
141+
142+
private Collection<Long> getContactIds(
143+
Date fromDate,
144+
Date toDate,
145+
RegionReferenceDto region,
146+
DistrictReferenceDto district,
147+
Collection<Disease> diseases) {
148+
149+
CriteriaBuilder cb = em.getCriteriaBuilder();
150+
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
151+
Root<Contact> root = cq.from(Contact.class);
152+
153+
cq.where(buildContactFilters(cb, cq, root, fromDate, toDate, region, district, diseases));
144154

145155
cq.select(root.get(AbstractDomainObject.ID));
156+
146157
return em.createQuery(cq).getResultList();
147158
}
148159

160+
private Predicate buildContactFilters(
161+
CriteriaBuilder cb,
162+
CriteriaQuery<Long> cq,
163+
Root<Contact> root,
164+
Date fromDate,
165+
Date toDate,
166+
RegionReferenceDto region,
167+
DistrictReferenceDto district,
168+
Collection<Disease> diseases) {
169+
Join<Contact, Case> caze = root.join(Contact.CAZE, JoinType.LEFT);
170+
171+
return AbstractAdoService.and(
172+
cb,
173+
contactService.createUserFilter(cb, cq, root),
174+
contactService.createActiveContactsFilter(cb, root),
175+
contactService.createDefaultFilter(cb, root),
176+
cb.notEqual(root.get(Contact.CONTACT_CLASSIFICATION), ContactClassification.NO_CONTACT),
177+
cb.or(
178+
cb.isNull(caze),
179+
cb.and(caseService.createDefaultFilter(cb, caze), cb.notEqual(caze.get(Case.CASE_CLASSIFICATION), CaseClassification.NO_CASE))),
180+
fromDate == null ? null : cb.greaterThanOrEqualTo(root.get(Contact.REPORT_DATE_TIME), fromDate),
181+
toDate == null ? null : cb.lessThanOrEqualTo(root.get(Contact.REPORT_DATE_TIME), toDate),
182+
root.get(Contact.DISEASE).in(diseases),
183+
region == null ? null : cb.equal(root.join(Contact.REGION).get(Region.UUID), region.getUuid()),
184+
district == null ? null : cb.equal(root.join(Contact.DISTRICT).get(District.UUID), district.getUuid()));
185+
}
186+
149187
enum EnvParam {
150188

151189
DB_USER("user"),

sormas-backend/src/main/resources/visualisation/transform_contact.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ if (idContString == "") idContString = "NULL"
6565
#query all relevant contacts
6666
sql_edge = "select distinct cs.person_id case_pid, ct.person_id contact_pid,
6767
'ContactProximity.' || ct.contactproximity as contactproximity, 'ContactStatus.' || ct.contactstatus as contactstatus
68-
from public.contact ct
68+
from public.contact ct
6969
join public.cases cs on ct.caze_id = cs.id
7070
where ct.id in (%s)"
7171

@@ -80,7 +80,7 @@ sql_node = "with clean_ct as (
8080
clean_cs as (
8181
select *
8282
from public.cases
83-
where deleted = FALSE
83+
where deleted = FALSE
8484
and caseclassification != 'NO_CASE'
8585
),
8686
node as (
@@ -92,7 +92,7 @@ node as (
9292
union
9393
--caze
9494
select distinct p.id, cs.reportdate, cs.uuid, cs.caseclassification
95-
from clean_ct ct
95+
from clean_ct ct
9696
join public.cases cs on ct.caze_id = cs.id
9797
join public.person p on cs.person_id = p.id
9898
)

sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/DashboardFilterLayout.java

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,10 @@
2020
import java.util.Date;
2121
import java.util.HashSet;
2222
import java.util.Set;
23-
import java.util.function.Consumer;
24-
import java.util.stream.Stream;
2523

26-
import com.vaadin.event.ShortcutAction;
27-
import com.vaadin.ui.CustomLayout;
28-
import com.vaadin.v7.ui.Field;
29-
import de.symeda.sormas.ui.utils.FieldHelper;
3024
import org.vaadin.hene.popupbutton.PopupButton;
3125

26+
import com.vaadin.event.ShortcutAction;
3227
import com.vaadin.icons.VaadinIcons;
3328
import com.vaadin.server.Page;
3429
import com.vaadin.shared.ui.ContentMode;
@@ -95,7 +90,6 @@ public class DashboardFilterLayout extends HorizontalLayout {
9590
private HorizontalLayout customDateFilterLayout;
9691

9792
private Runnable dateFilterChangeCallback;
98-
private Consumer<Boolean> diseaseFilterChangeCallback;
9993

10094
public DashboardFilterLayout(AbstractDashboardView dashboardView, DashboardDataProvider dashboardDataProvider) {
10195
this.dashboardView = dashboardView;
@@ -159,9 +153,6 @@ private void createDiseaseFilter() {
159153
diseaseFilter.addItems(FacadeProvider.getDiseaseConfigurationFacade().getAllDiseases(true, true, true).toArray());
160154
}
161155
diseaseFilter.addValueChangeListener(e -> {
162-
if (diseaseFilterChangeCallback != null) {
163-
diseaseFilterChangeCallback.accept(diseaseFilter.getValue() != null);
164-
}
165156
dashboardDataProvider.setDisease((Disease) diseaseFilter.getValue());
166157
});
167158
addComponent(diseaseFilter);
@@ -552,14 +543,6 @@ public void setDateFilterChangeCallback(Runnable dateFilterChangeCallback) {
552543
this.dateFilterChangeCallback = dateFilterChangeCallback;
553544
}
554545

555-
public Consumer<Boolean> getDiseaseFilterChangeCallback() {
556-
return diseaseFilterChangeCallback;
557-
}
558-
559-
public void setDiseaseFilterChangeCallback(Consumer<Boolean> diseaseFilterChangeCallback) {
560-
this.diseaseFilterChangeCallback = diseaseFilterChangeCallback;
561-
}
562-
563546
public boolean hasDiseaseSelected() {
564547
return diseaseFilter.getValue() != null;
565548
}

sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/contacts/ContactsDashboardView.java

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
import java.util.List;
2121
import java.util.Optional;
22-
import java.util.function.Consumer;
2322
import java.util.stream.Collectors;
2423

2524
import com.vaadin.icons.VaadinIcons;
@@ -139,15 +138,6 @@ public ContactsDashboardView() {
139138

140139
networkDiagramRowLayout = createNetworkDiagramRowLayout();
141140
rowsLayout.addComponent(networkDiagramRowLayout);
142-
143-
networkDiagramLayout.ifPresent(l -> {
144-
Consumer<Boolean> diseaseFilterChangeCallback = (diseaseSelected) -> {
145-
networkDiagramLayout.get().setVisible(diseaseSelected);
146-
noNetworkDiagramLayout.setVisible(!diseaseSelected);
147-
};
148-
filterLayout.setDiseaseFilterChangeCallback(diseaseFilterChangeCallback);
149-
diseaseFilterChangeCallback.accept(null != dashboardDataProvider.getDisease());
150-
});
151141
}
152142
}
153143

@@ -481,7 +471,11 @@ public void refreshDashboard() {
481471
}
482472

483473
// Update cases and contacts shown on the map
484-
if (UserProvider.getCurrent().hasUserRight(UserRight.DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS)) {
474+
if (UserProvider.getCurrent().hasUserRight(UserRight.DASHBOARD_CONTACT_VIEW_TRANSMISSION_CHAINS) && networkDiagramLayout.isPresent()) {
475+
boolean diseaseSelected = dashboardDataProvider.getDisease() != null;
476+
477+
networkDiagramLayout.get().setVisible(diseaseSelected);
478+
noNetworkDiagramLayout.setVisible(!diseaseSelected);
485479
networkDiagramComponent.filter(c -> c.getParent().isVisible()).ifPresent(DashboardNetworkComponent::refreshDiagram);
486480
}
487481

0 commit comments

Comments
 (0)