Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
b8d24ad
#13828 - Add customizable field metadata and values infrastructure
raulbob Mar 19, 2026
f993c23
add enums, modify entities, dtos required for exposure form redesign
obinna-h-n Mar 22, 2026
7d13524
Updated action versions
raulbob Apr 1, 2026
1044843
Added manual trigger
raulbob Apr 1, 2026
da91663
Added manual trigger
raulbob Apr 1, 2026
5a776bb
Fixed sormas app barcodescanner version
raulbob Apr 1, 2026
33b1639
Removed manual trigger, corrected gradle validate version
raulbob Apr 1, 2026
03ef509
Disabled linter, fixed maven ci
raulbob Apr 1, 2026
58ac29b
Disabled codeql
raulbob Apr 1, 2026
c34ef21
Disabled codeql
raulbob Apr 1, 2026
c5c71e3
Fixing codeql
raulbob Apr 1, 2026
b96fc53
Re-added build step
raulbob Apr 1, 2026
1a2d5e4
Enabled maven tests
raulbob Apr 1, 2026
2e7923d
Temporarily disabled open canary
raulbob Apr 1, 2026
c7ab067
Merge pull request #13893 from SORMAS-Foundation/task-update_github_a…
raulbob Apr 1, 2026
5db41c6
Summary: Malaria and Dengue Sample and Pathogentestform changes.
KarnaiahPesula Mar 25, 2026
70d2d77
Fixed the possible issues
KarnaiahPesula Mar 26, 2026
6d2ddbe
Review fixes for exposure dates
KarnaiahPesula Mar 27, 2026
40ae639
Review fixes for exposure dates
KarnaiahPesula Mar 27, 2026
23e9c83
fix for possible script failure
KarnaiahPesula Mar 31, 2026
67899d6
#13711 - Update Android app to support multiple contact proximities.
roldy Apr 1, 2026
e9fcb67
Resolve PR comments in-line with the initial commit
roldy Apr 1, 2026
00cd76b
Resolve PR comments in-line with the initial commit
roldy Apr 1, 2026
ebb192b
Avoid silent drift between the transient set and persisted JSON & Add…
roldy Apr 1, 2026
0d7ec2c
Fix missing import
roldy Apr 1, 2026
906c3a1
Prevents NPE when Gson deserializes unknown enum values as null entri…
roldy Apr 1, 2026
115da06
Changed OpenAPI Canary to fail on incompatible
raulbob Apr 1, 2026
a179d89
Changed image to ubuntu-latest for app ci action
raulbob Apr 2, 2026
19453ba
Resolved test failures
KarnaiahPesula Apr 2, 2026
f675c3b
corrected the latest case
KarnaiahPesula Apr 2, 2026
cdbd1bb
Updated Jacoco tool version to 0.8.14 to avoid bytecode failures
raulbob Apr 2, 2026
02f494b
Corrected coderabit suggestion
raulbob Apr 2, 2026
132aa73
[GitHub Actions] Update openAPI spec files
SORMAS-Robot Apr 7, 2026
80a4047
Dengue review comments
KarnaiahPesula Apr 2, 2026
4d4fa60
Updated app ci action
raulbob Apr 7, 2026
5ece351
[GitHub Actions] Update openAPI spec files
SORMAS-Robot Apr 7, 2026
15651a1
Update sql schema with TestReport renamed columns (#13901)
raulbob Apr 7, 2026
78a8e45
Updated java ci to avoid unnecessary commits for swagger files
raulbob Apr 7, 2026
239d8c3
#13883 - Fixed IGRA inputs value change listeners
raulbob Mar 16, 2026
75ccd8c
Added guards against number conversion errors
raulbob Mar 17, 2026
b6b733b
Removed full type reference
raulbob Mar 17, 2026
26bf66c
implement ui for new exposure form exposures changes
obinna-h-n Apr 7, 2026
9655302
implement ui for disease specific configuration of exposure user inte…
obinna-h-n Apr 8, 2026
198fd3a
remove schema name from alter table statements
obinna-h-n Apr 8, 2026
6c138a5
#13828 - Add customizable field metadata and values infrastructure
raulbob Mar 19, 2026
f8a52c2
Fixed sormas_schema
raulbob Apr 13, 2026
da5d38d
Merge branch 'development' into task-13886-customizable_fields_metada…
raulbob Apr 13, 2026
9a178ee
Improved UI Group handling and fixed other issues
raulbob Apr 14, 2026
508f0c3
Added better handling for customizable field deletionconfiguration
raulbob Apr 16, 2026
87374b7
Modified field value metadata uuid to strong typed
raulbob Apr 16, 2026
67d390e
Tweeked enum handling, added CustomizableFieldValue table partitions
raulbob Apr 17, 2026
8cd5609
Hide customizable field group on UI when no fields
raulbob Apr 17, 2026
f1f9653
Added customizable field admin UI and Case Form integration
raulbob Apr 20, 2026
29b506b
Fixed EJB local inject causing test failures
raulbob Apr 20, 2026
9f94409
Removed customizable field value table partitioning, not supported by…
raulbob Apr 20, 2026
c841d1b
Fixed history tables
raulbob Apr 20, 2026
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
10 changes: 10 additions & 0 deletions sormas-api/src/main/java/de/symeda/sormas/api/FacadeProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import de.symeda.sormas.api.clinicalcourse.ClinicalVisitFacade;
import de.symeda.sormas.api.contact.ContactFacade;
import de.symeda.sormas.api.customizableenum.CustomizableEnumFacade;
import de.symeda.sormas.api.customizablefield.CustomizableFieldMetadataFacade;
import de.symeda.sormas.api.customizablefield.CustomizableFieldValueFacade;
import de.symeda.sormas.api.dashboard.DashboardFacade;
import de.symeda.sormas.api.dashboard.adverseeventsfollowingimmunization.AefiDashboardFacade;
import de.symeda.sormas.api.dashboard.sample.SampleDashboardFacade;
Expand Down Expand Up @@ -508,6 +510,14 @@ public static CustomizableEnumFacade getCustomizableEnumFacade() {
return get().lookupEjbRemote(CustomizableEnumFacade.class);
}

public static CustomizableFieldMetadataFacade getCustomizableFieldMetadataFacade() {
return get().lookupEjbRemote(CustomizableFieldMetadataFacade.class);
}

public static CustomizableFieldValueFacade getCustomizableFieldValueFacade() {
return get().lookupEjbRemote(CustomizableFieldValueFacade.class);
}

public static InfoFacade getInfoFacade() {
return get().lookupEjbRemote(InfoFacade.class);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ public enum DeletableEntityType {
PATHOGEN_TEST,
ENVIRONMENT,
ENVIRONMENT_SAMPLE,
SELF_REPORT;
SELF_REPORT,
CUSTOMIZABLE_FIELD_METADATA,
CUSTOMIZABLE_FIELD_VALUE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.customizablefield;

import de.symeda.sormas.api.EntityDto;
import de.symeda.sormas.api.caze.CaseDataDto;
import de.symeda.sormas.api.epidata.EpiDataDto;
import de.symeda.sormas.api.exposure.ExposureDto;

/**
* Defines supported customizable field contexts and links them to existing
* SORMAS DTO classes. Contexts must reference real DTOs; defining a custom
* field for a non-existent DTO does not make sense.
*/
public enum CustomizableFieldContext {

CASE(CaseDataDto.class),
EPIDATA(EpiDataDto.class),
EXPOSURE(ExposureDto.class);

// add other contexts here

private final String contextClassName;

CustomizableFieldContext(Class<? extends EntityDto> dtoClass) {
this.contextClassName = dtoClass.getName();
}

public String getContextClassName() {
return contextClassName;
}

public static CustomizableFieldContext fromDtoClass(Class<? extends EntityDto> dtoClass) {
return fromDtoClassName(dtoClass.getName());
}

public static CustomizableFieldContext fromDtoClassName(String dtoClassName) {
Class<?> rawClass;
try {
rawClass = Class.forName(dtoClassName);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unknown context DTO: " + dtoClassName, e);
}
if (!EntityDto.class.isAssignableFrom(rawClass)) {
throw new IllegalArgumentException("Context class is not an EntityDto: " + dtoClassName);
}
for (CustomizableFieldContext context : values()) {
if (context.contextClassName.equals(dtoClassName)) {
return context;
}
}
throw new IllegalArgumentException("Unknown context DTO: " + dtoClassName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.customizablefield;

import java.io.Serializable;
import java.util.List;

/**
* Typed representation of the {@code customProperties} JSON column on
* {@link CustomizableFieldMetadataDto}.
* <p>
* Field-type-specific configuration lives here:
* <ul>
* <li><b>options</b> – selectable string values used by
* {@link CustomizableFieldType#COMBOBOX},
* {@link CustomizableFieldType#CHECKBOX_LIST}, and
* {@link CustomizableFieldType#RADIO_BUTTON_LIST}.</li>
* </ul>
* Additional properties can be added here as the feature grows without
* touching the database schema (the whole object is stored as a single
* {@code jsonb} column).
*/
public class CustomizableFieldCustomProperties implements Serializable {

private static final long serialVersionUID = 1L;

/**
* The list of selectable option values for list-type fields
* ({@code COMBOBOX}, {@code CHECKBOX_LIST}, {@code RADIO_BUTTON_LIST}).
* Each entry is the raw stored string value (not a display label).
*/
private List<String> options;

public CustomizableFieldCustomProperties() {
// Required for JSON deserialization.
}

public List<String> getOptions() {
return options;
}

public void setOptions(List<String> options) {
this.options = options;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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.customizablefield;

import java.util.ArrayList;
import java.util.List;

/**
* Defines UI groups for customizable fields, scoped to a specific {@link CustomizableFieldContext}.
* <p>
* Each group has a stable string {@link #key} that is used as:
* <ul>
* <li>the value stored in the database;</li>
* <li>the Vaadin layout location ID when embedding a {@code CustomizableFieldsGroup} component.</li>
* </ul>
* <p>
* To add a new group, append an enum value with the owning context and a unique, stable key.
* The key must not be changed after data has been stored against it.
*/
public enum CustomizableFieldGroup {

// ---- CASE groups --------------------------------------------------------
CASE_DATA_GENERAL(CustomizableFieldContext.CASE, "caseDataGeneral"),
CASE_DATA_CLASSIFICATION(CustomizableFieldContext.CASE, "caseDataClassification"),
CASE_DATA_INVESTIGATION(CustomizableFieldContext.CASE, "caseDataInvestigation"),
CASE_DATA_IDENTIFIERS(CustomizableFieldContext.CASE, "caseDataIdentifiers"),
CASE_DATA_DISEASE(CustomizableFieldContext.CASE, "caseDataDisease"),
CASE_DATA_REINFECTION(CustomizableFieldContext.CASE, "caseDataReinfection"),
CASE_DATA_OUTCOME(CustomizableFieldContext.CASE, "caseDataOutcome"),
CASE_DATA_SEQUELAE(CustomizableFieldContext.CASE, "caseDataSequelae"),
CASE_DATA_JURISDICTION(CustomizableFieldContext.CASE, "caseDataJurisdiction"),
CASE_DATA_PLACE_OF_STAY(CustomizableFieldContext.CASE, "caseDataPlaceOfStay"),
CASE_DATA_QUARANTINE(CustomizableFieldContext.CASE, "caseDataQuarantine"),
CASE_DATA_REPORT_GEO(CustomizableFieldContext.CASE, "caseDataReportGeo"),
CASE_DATA_HEALTH_CONDITIONS(CustomizableFieldContext.CASE, "caseDataHealthConditions"),
CASE_DATA_DIAGNOSTIC(CustomizableFieldContext.CASE, "caseDataDiagnostic"),
CASE_DATA_MEDICAL_INFORMATION(CustomizableFieldContext.CASE, "caseDataMedicalInformation"),
CASE_DATA_VACCINATION(CustomizableFieldContext.CASE, "caseDataVaccination"),
CASE_DATA_CLINICIAN_NOTIFICATION(CustomizableFieldContext.CASE, "caseDataClinicianNotification"),
CASE_DATA_CONTACT_TRACING(CustomizableFieldContext.CASE, "caseDataContactTracing"),

// ---- EPIDATA groups -----------------------------------------------------
EPIDATA_EXPOSURE_INVESTIGATION(CustomizableFieldContext.EPIDATA, "exposureInvestigation"),
EPIDATA_ACTIVITY_AS_CASE(CustomizableFieldContext.EPIDATA, "activityAsCase"),
EPIDATA_CONTACT_WITH_SOURCE_CASE(CustomizableFieldContext.EPIDATA, "contactWithSourceCase"),

// ---- EXPOSURE groups ----------------------------------------------------
EXPOSURE_DETAILS(CustomizableFieldContext.EXPOSURE, "exposureDetails"),
EXPOSURES_GENERAL(CustomizableFieldContext.EXPOSURE, "exposuresGeneral"),
LOCATION_GENERAL(CustomizableFieldContext.EXPOSURE, "locationGeneral");

private final CustomizableFieldContext context;
/**
* Stable key stored in the database and used as the Vaadin layout location ID.
*/
private final String key;

CustomizableFieldGroup(CustomizableFieldContext context, String key) {
this.context = context;
this.key = key;
}

/**
* The {@link CustomizableFieldContext} this group belongs to.
*/
public CustomizableFieldContext getContext() {
return context;
}

/**
* Stable string key used as the database-stored value and as the Vaadin layout location ID.
*/
public String getKey() {
return key;
}

/**
* Returns all groups that belong to the given context.
*/
public static List<CustomizableFieldGroup> getGroupsForContext(CustomizableFieldContext context) {
List<CustomizableFieldGroup> result = new ArrayList<>();
for (CustomizableFieldGroup group : values()) {
if (group.context == context) {
result.add(group);
}
}
return result;
}

/**
* Looks up a group by its stable {@link #key}, returning {@code null} if not found.
*/
public static CustomizableFieldGroup fromKey(String key) {
if (key == null) {
return null;
}
for (CustomizableFieldGroup group : values()) {
if (group.key.equals(key)) {
return group;
}
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.customizablefield;

import de.symeda.sormas.api.utils.IgnoreForUrl;
import de.symeda.sormas.api.utils.criteria.BaseCriteria;

/**
* Criteria for filtering customizable field metadata in admin views.
*/
public class CustomizableFieldMetadataCriteria extends BaseCriteria {

private static final long serialVersionUID = 1L;

private String freeTextFilter;
private CustomizableFieldContext contextClass;
private CustomizableFieldType fieldType;
private Boolean active;

public String getFreeTextFilter() {
return freeTextFilter;
}

public CustomizableFieldMetadataCriteria freeTextFilter(String freeTextFilter) {
this.freeTextFilter = freeTextFilter;
return this;
}

@IgnoreForUrl
public CustomizableFieldContext getContextClass() {
return contextClass;
}

public void setContextClass(CustomizableFieldContext contextClass) {
this.contextClass = contextClass;
}

@IgnoreForUrl
public CustomizableFieldType getFieldType() {
return fieldType;
}

public void setFieldType(CustomizableFieldType fieldType) {
this.fieldType = fieldType;
}

@IgnoreForUrl
public Boolean getActive() {
return active;
}

public void setActive(Boolean active) {
this.active = active;
}
}
Loading
Loading