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

Commit a08bcce

Browse files
authored
Merge pull request SORMAS-Foundation#2885 from hzi-braunschweig/feature-2527-CampaignDashboard
Feature 2527 campaign dashboard
2 parents 9d47c76 + a5f9e3a commit a08bcce

15 files changed

Lines changed: 697 additions & 64 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/campaign/CampaignFacade.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.symeda.sormas.api.campaign;
22

3+
import de.symeda.sormas.api.campaign.diagram.CampaignDashboardElement;
34
import de.symeda.sormas.api.utils.SortProperty;
45

56
import javax.ejb.Remote;
@@ -12,16 +13,19 @@ public interface CampaignFacade {
1213

1314
List<CampaignReferenceDto> getAllCampaignsAsReference();
1415

16+
CampaignReferenceDto getLastStartedCampaign();
17+
1518
long count(CampaignCriteria campaignCriteria);
1619

1720
CampaignDto saveCampaign(CampaignDto dto);
1821

1922
CampaignDto getByUuid(String uuid);
2023

24+
List<CampaignDashboardElement> getCampaignDashboardElements(String campaignUuid);
25+
2126
boolean isArchived(String uuid);
2227

2328
void deleteCampaign(String uuid);
2429

2530
void archiveOrDearchiveCampaign(String campaignUuid, boolean archive);
26-
2731
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package de.symeda.sormas.api.campaign.diagram;
2+
3+
import java.io.Serializable;
4+
5+
public class CampaignDashboardElement implements Serializable {
6+
7+
private String diagramId;
8+
private String tabId;
9+
private Integer order;
10+
private Integer width;
11+
private Integer height;
12+
13+
public CampaignDashboardElement() {
14+
}
15+
16+
public CampaignDashboardElement(String diagramId, String tabId, Integer order, Integer width, Integer height) {
17+
this.diagramId = diagramId;
18+
this.tabId = tabId;
19+
this.order = order;
20+
this.width = width;
21+
this.height = height;
22+
}
23+
24+
public String getDiagramId() {
25+
return diagramId;
26+
}
27+
28+
public void setDiagramId(String diagramId) {
29+
this.diagramId = diagramId;
30+
}
31+
32+
public String getTabId() {
33+
return tabId;
34+
}
35+
36+
public void setTabId(String tabId) {
37+
this.tabId = tabId;
38+
}
39+
40+
public Integer getOrder() {
41+
return order;
42+
}
43+
44+
public void setOrder(Integer order) {
45+
this.order = order;
46+
}
47+
48+
public Integer getWidth() {
49+
return width;
50+
}
51+
52+
public void setWidth(Integer width) {
53+
this.width = width;
54+
}
55+
56+
public Integer getHeight() {
57+
return height;
58+
}
59+
60+
public void setHeight(Integer height) {
61+
this.height = height;
62+
}
63+
}

sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/Campaign.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package de.symeda.sormas.backend.campaign;
22

33
import de.symeda.auditlog.api.Audited;
4+
import de.symeda.auditlog.api.AuditedIgnore;
5+
import de.symeda.sormas.api.campaign.diagram.CampaignDashboardElement;
46
import de.symeda.sormas.backend.common.CoreAdo;
57
import de.symeda.sormas.backend.user.User;
8+
import org.hibernate.annotations.Type;
69

710
import javax.persistence.Column;
811
import javax.persistence.Entity;
@@ -11,6 +14,7 @@
1114
import javax.persistence.Temporal;
1215
import javax.persistence.TemporalType;
1316
import java.util.Date;
17+
import java.util.List;
1418

1519
@Entity(name = "campaigns")
1620
@Audited
@@ -33,6 +37,7 @@ public class Campaign extends CoreAdo {
3337
private Date endDate;
3438
private User creatingUser;
3539
private boolean archived;
40+
private List<CampaignDashboardElement> dashboardElements;
3641

3742
@Column(length = 255)
3843
public String getName() {
@@ -93,4 +98,15 @@ public void setArchived(boolean archived) {
9398
public String toString() {
9499
return name;
95100
}
101+
102+
@AuditedIgnore
103+
@Type(type = "json")
104+
@Column(columnDefinition = "json")
105+
public List<CampaignDashboardElement> getDashboardElements() {
106+
return dashboardElements;
107+
}
108+
109+
public void setDashboardElements(List<CampaignDashboardElement> dashboardElements) {
110+
this.dashboardElements = dashboardElements;
111+
}
96112
}

sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/CampaignFacadeEjb.java

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
11
package de.symeda.sormas.backend.campaign;
22

3+
import java.sql.Timestamp;
4+
import java.util.ArrayList;
5+
import java.util.Date;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
import javax.ejb.EJB;
10+
import javax.ejb.LocalBean;
11+
import javax.ejb.Stateless;
12+
import javax.persistence.EntityManager;
13+
import javax.persistence.PersistenceContext;
14+
import javax.persistence.TypedQuery;
15+
import javax.persistence.criteria.CriteriaBuilder;
16+
import javax.persistence.criteria.CriteriaQuery;
17+
import javax.persistence.criteria.Expression;
18+
import javax.persistence.criteria.Order;
19+
import javax.persistence.criteria.Predicate;
20+
import javax.persistence.criteria.Root;
21+
import javax.validation.constraints.NotNull;
22+
323
import de.symeda.sormas.api.campaign.CampaignCriteria;
424
import de.symeda.sormas.api.campaign.CampaignDto;
525
import de.symeda.sormas.api.campaign.CampaignFacade;
626
import de.symeda.sormas.api.campaign.CampaignIndexDto;
727
import de.symeda.sormas.api.campaign.CampaignReferenceDto;
28+
import de.symeda.sormas.api.campaign.diagram.CampaignDashboardElement;
829
import de.symeda.sormas.api.i18n.I18nProperties;
930
import de.symeda.sormas.api.i18n.Strings;
1031
import de.symeda.sormas.api.user.UserRight;
@@ -19,23 +40,6 @@
1940
import de.symeda.sormas.backend.util.DtoHelper;
2041
import de.symeda.sormas.backend.util.ModelConstants;
2142

22-
import javax.ejb.EJB;
23-
import javax.ejb.LocalBean;
24-
import javax.ejb.Stateless;
25-
import javax.persistence.EntityManager;
26-
import javax.persistence.PersistenceContext;
27-
import javax.persistence.criteria.CriteriaBuilder;
28-
import javax.persistence.criteria.CriteriaQuery;
29-
import javax.persistence.criteria.Expression;
30-
import javax.persistence.criteria.Order;
31-
import javax.persistence.criteria.Predicate;
32-
import javax.persistence.criteria.Root;
33-
import javax.validation.constraints.NotNull;
34-
import java.sql.Timestamp;
35-
import java.util.ArrayList;
36-
import java.util.List;
37-
import java.util.stream.Collectors;
38-
3943
@Stateless(name = "CampaignFacade")
4044
public class CampaignFacadeEjb implements CampaignFacade {
4145

@@ -100,6 +104,22 @@ public List<CampaignReferenceDto> getAllCampaignsAsReference() {
100104
return campaignService.getAll().stream().map(c -> toReferenceDto(c)).collect(Collectors.toList());
101105
}
102106

107+
@Override
108+
public CampaignReferenceDto getLastStartedCampaign() {
109+
110+
final CriteriaBuilder cb = em.getCriteriaBuilder();
111+
final CriteriaQuery<Campaign> query = cb.createQuery(Campaign.class);
112+
final Root<Campaign> from = query.from(Campaign.class);
113+
query.select(from);
114+
query.where(cb.lessThanOrEqualTo(from.get(Campaign.START_DATE), new Date()));
115+
query.orderBy(cb.desc(from.get(Campaign.START_DATE)));
116+
117+
final TypedQuery<Campaign> q = em.createQuery(query);
118+
final Campaign lastStartedCampaign = q.getResultList().stream().findFirst().orElse(null);
119+
120+
return toReferenceDto(lastStartedCampaign);
121+
}
122+
103123
@Override
104124
public long count(CampaignCriteria campaignCriteria) {
105125

@@ -171,6 +191,24 @@ public CampaignDto getByUuid(String uuid) {
171191
return toDto(campaignService.getByUuid(uuid));
172192
}
173193

194+
@Override
195+
public List<CampaignDashboardElement> getCampaignDashboardElements(String campaignUuid) {
196+
final List<CampaignDashboardElement> result = new ArrayList<>();
197+
if (campaignUuid != null) {
198+
List<CampaignDashboardElement> dashboardElements = campaignService.getByUuid(campaignUuid).getDashboardElements();
199+
if (dashboardElements != null) {
200+
result.addAll(dashboardElements);
201+
}
202+
} else {
203+
campaignService.getAll().forEach(campaign -> {
204+
if (campaign.getDashboardElements() != null) {
205+
result.addAll(campaign.getDashboardElements());
206+
}
207+
});
208+
}
209+
return result;
210+
}
211+
174212
@Override
175213
public boolean isArchived(String uuid) {
176214

sormas-backend/src/main/java/de/symeda/sormas/backend/campaign/data/CampaignFormDataFacadeEjb.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public List<CampaignDiagramDataDto> getDiagramData(
315315
+ ", jsonData->>'" + CampaignFormDataEntry.ID + "' as fieldId"
316316
+ ", jsonMeta->>'" + CampaignFormElement.CAPTION + "' as fieldCaption"
317317
+ ", CASE"
318-
+ " WHEN (jsonMeta ->> '" + CampaignFormElement.TYPE + "') = '" + CampaignFormElementType.NUMBER.toString() + "' THEN sum((jsonData->>'" + CampaignFormDataEntry.VALUE + "')\\:\\:int)"
318+
+ " WHEN (jsonMeta ->> '" + CampaignFormElement.TYPE + "') = '" + CampaignFormElementType.NUMBER.toString() + "' THEN sum(cast_to_int(jsonData->>'" + CampaignFormDataEntry.VALUE + "', 0))"
319319
+ " ELSE count((jsonData->>'" + CampaignFormDataEntry.VALUE + "') = '" + diagramSeries.getFieldValue() + "')"
320320
+ " END as sumValue"
321321
+ ", " + Region.TABLE_NAME + "." + Region.UUID

sormas-backend/src/main/resources/sql/sormas_schema.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5269,4 +5269,19 @@ ALTER TABLE campaignformmeta_history ADD COLUMN campaignformtranslations json;
52695269

52705270
INSERT INTO schema_version (version_number, comment) VALUES (250, 'Campaign diagram visualization refinement #2753');
52715271

5272+
-- 2020-09-07 Campaign dashboard element
5273+
5274+
ALTER TABLE campaigns ADD COLUMN dashboardElements json;
5275+
ALTER TABLE campaigns_history ADD COLUMN dashboardElements json;
5276+
5277+
create or replace function cast_to_int(text, integer) returns integer as $$
5278+
begin
5279+
return cast($1 as integer);
5280+
exception
5281+
when invalid_text_representation then
5282+
return $2;
5283+
end;
5284+
$$ language plpgsql immutable;
5285+
5286+
INSERT INTO schema_version (version_number, comment) VALUES (251, 'Campaign dashboard element #2527');
52725287
-- *** Insert new sql commands BEFORE this line ***
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package de.symeda.sormas.backend.campaign;
2+
3+
import java.util.Date;
4+
5+
import org.junit.Assert;
6+
import org.junit.Test;
7+
8+
import de.symeda.sormas.api.campaign.CampaignDto;
9+
import de.symeda.sormas.api.campaign.CampaignReferenceDto;
10+
import de.symeda.sormas.api.user.UserDto;
11+
import de.symeda.sormas.api.user.UserRole;
12+
import de.symeda.sormas.backend.AbstractBeanTest;
13+
import de.symeda.sormas.backend.TestDataCreator;
14+
15+
public class CampaignFacadeEjbTest extends AbstractBeanTest {
16+
17+
public static final int ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000;
18+
19+
@Test
20+
public void testGetLastStartedCampaign() {
21+
22+
final TestDataCreator.RDCF rdcf = creator.createRDCF("Region", "District", "Community", "Facility");
23+
final UserDto user = creator.createUser(rdcf, UserRole.SURVEILLANCE_SUPERVISOR);
24+
final CampaignDto campaign1 = creator.createCampaign(user);
25+
campaign1.setStartDate(new Date(System.currentTimeMillis() - 7 * ONE_DAY_IN_MILLIS)); // last week
26+
getCampaignFacade().saveCampaign(campaign1);
27+
final CampaignDto campaign2 = creator.createCampaign(user);
28+
campaign2.setStartDate(new Date(System.currentTimeMillis() - ONE_DAY_IN_MILLIS)); // yesterday
29+
getCampaignFacade().saveCampaign(campaign2);
30+
final CampaignDto campaign3 = creator.createCampaign(user);
31+
campaign3.setStartDate(new Date(System.currentTimeMillis() + ONE_DAY_IN_MILLIS)); // tomorrow
32+
getCampaignFacade().saveCampaign(campaign3);
33+
34+
CampaignReferenceDto lastStartedCampaign = getCampaignFacade().getLastStartedCampaign();
35+
Assert.assertEquals(campaign2.getUuid(), lastStartedCampaign.getUuid());
36+
}
37+
38+
}

sormas-ui/src/main/java/de/symeda/sormas/ui/campaign/campaigndata/CampaignDataView.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ private void createImportanceFilterSwitch() {
167167
campaignFormElementImportance
168168
.setItemCaption(CampaignFormElementImportance.ALL, I18nProperties.getEnumCaption(CampaignFormElementImportance.ALL));
169169

170-
campaignFormElementImportance.setValue(CampaignFormElementImportance.IMPORTANT);
170+
campaignFormElementImportance.setValue(CampaignFormElementImportance.ALL);
171171
campaignFormElementImportance.setVisible(false);
172172
}
173173

sormas-ui/src/main/java/de/symeda/sormas/ui/dashboard/campaigns/CampaignDashboardDataProvider.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package de.symeda.sormas.ui.dashboard.campaigns;
22

3+
import java.util.ArrayList;
4+
import java.util.Comparator;
35
import java.util.HashMap;
46
import java.util.List;
57
import java.util.Map;
8+
import java.util.Optional;
69

710
import de.symeda.sormas.api.FacadeProvider;
811
import de.symeda.sormas.api.campaign.CampaignReferenceDto;
12+
import de.symeda.sormas.api.campaign.diagram.CampaignDashboardElement;
913
import de.symeda.sormas.api.campaign.diagram.CampaignDiagramCriteria;
1014
import de.symeda.sormas.api.campaign.diagram.CampaignDiagramDataDto;
1115
import de.symeda.sormas.api.campaign.diagram.CampaignDiagramDefinitionDto;
@@ -20,21 +24,40 @@ public class CampaignDashboardDataProvider {
2024
private RegionReferenceDto region;
2125
private DistrictReferenceDto district;
2226

23-
private final Map<CampaignDiagramDefinitionDto, List<CampaignDiagramDataDto>> campaignFormDataMap =
24-
new HashMap<CampaignDiagramDefinitionDto, List<CampaignDiagramDataDto>>();
27+
private final Map<CampaignDashboardDiagramDto, List<CampaignDiagramDataDto>> campaignFormDataMap = new HashMap<>();
2528

2629
public void refreshData() {
2730
campaignFormDataMap.clear();
28-
List<CampaignDiagramDefinitionDto> campaignDiagramDefinitions = FacadeProvider.getCampaignDiagramDefinitionFacade().getAll();
29-
campaignDiagramDefinitions.forEach(campaignDiagramDefinitionDto -> {
31+
32+
final List<CampaignDashboardElement> campaignDashboardElements =
33+
FacadeProvider.getCampaignFacade().getCampaignDashboardElements(campaign != null ? campaign.getUuid() : null);
34+
final List<CampaignDiagramDefinitionDto> campaignDiagramDefinitions = FacadeProvider.getCampaignDiagramDefinitionFacade().getAll();
35+
36+
final List<CampaignDashboardDiagramDto> campaignDashboardDiagramDtos = new ArrayList<>();
37+
38+
campaignDashboardElements.stream().sorted(Comparator.comparingInt(CampaignDashboardElement::getOrder)).forEach(campaignDashboardElement -> {
39+
final Optional<CampaignDiagramDefinitionDto> first = campaignDiagramDefinitions.stream()
40+
.filter(campaignDiagramDefinitionDto -> campaignDiagramDefinitionDto.getDiagramId().equals(campaignDashboardElement.getDiagramId()))
41+
.findFirst();
42+
if (first.isPresent()) {
43+
CampaignDiagramDefinitionDto campaignDiagramDefinitionDto = first.get();
44+
campaignDashboardDiagramDtos.add(new CampaignDashboardDiagramDto(campaignDashboardElement, campaignDiagramDefinitionDto));
45+
}
46+
});
47+
48+
campaignDashboardDiagramDtos.forEach(campaignDashboardDiagramDto -> {
3049
List<CampaignDiagramDataDto> diagramData = FacadeProvider.getCampaignFormDataFacade()
3150
.getDiagramData(
32-
campaignDiagramDefinitionDto.getCampaignDiagramSeriesList(),
51+
campaignDashboardDiagramDto.getCampaignDiagramDefinitionDto().getCampaignDiagramSeriesList(),
3352
new CampaignDiagramCriteria(campaign, area, region, district));
34-
campaignFormDataMap.put(campaignDiagramDefinitionDto, diagramData);
53+
campaignFormDataMap.put(campaignDashboardDiagramDto, diagramData);
3554
});
3655
}
3756

57+
public CampaignReferenceDto getLastStartedCampaign() {
58+
return FacadeProvider.getCampaignFacade().getLastStartedCampaign();
59+
}
60+
3861
public CampaignReferenceDto getCampaign() {
3962
return campaign;
4063
}
@@ -67,7 +90,7 @@ public void setDistrict(DistrictReferenceDto district) {
6790
this.district = district;
6891
}
6992

70-
public Map<CampaignDiagramDefinitionDto, List<CampaignDiagramDataDto>> getCampaignFormDataMap() {
93+
public Map<CampaignDashboardDiagramDto, List<CampaignDiagramDataDto>> getCampaignFormDataMap() {
7194
return campaignFormDataMap;
7295
}
7396
}

0 commit comments

Comments
 (0)