From 60a4483446c21e14a70068ee88751b900d2e7e93 Mon Sep 17 00:00:00 2001 From: cstarcher Date: Fri, 22 May 2026 13:16:37 -0500 Subject: [PATCH 1/3] fixed order in submission and admin view --- .../java/org/tdl/vireo/model/CustomActionDefinition.java | 9 +++++++++ src/main/webapp/app/views/admin/list.html | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java b/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java index cccc219540..39c24abc40 100644 --- a/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java +++ b/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java @@ -34,6 +34,15 @@ public CustomActionDefinition(String label, Boolean isStudentVisible) { isStudentVisible(isStudentVisible); } + /** + * @return the label + */ + @Override + @JsonView(Views.SubmissionList.class) + public Long getPosition() { + return super.getPosition(); + } + /** * @return the label */ diff --git a/src/main/webapp/app/views/admin/list.html b/src/main/webapp/app/views/admin/list.html index d2d958b97d..34767103bf 100644 --- a/src/main/webapp/app/views/admin/list.html +++ b/src/main/webapp/app/views/admin/list.html @@ -36,7 +36,7 @@

List ETDs

{{displaySubmissionProperty(row, col)}} - + {{getCustomActionLabelById(ca.definition.id)}}
From 50ee5ab2bfc1eed11ba7d757fa452cf51bc1b9b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 22 May 2026 18:58:05 +0000 Subject: [PATCH 2/3] Fix incorrect Javadoc for getPosition() in CustomActionDefinition Agent-Logs-Url: https://github.com/TexasDigitalLibrary/Vireo/sessions/f0a08f30-1f9f-400b-ad8d-b923231196a5 Co-authored-by: cstarcher <5767401+cstarcher@users.noreply.github.com> --- src/main/java/org/tdl/vireo/model/CustomActionDefinition.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java b/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java index 39c24abc40..0479921ac7 100644 --- a/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java +++ b/src/main/java/org/tdl/vireo/model/CustomActionDefinition.java @@ -35,7 +35,7 @@ public CustomActionDefinition(String label, Boolean isStudentVisible) { } /** - * @return the label + * @return the position */ @Override @JsonView(Views.SubmissionList.class) From bfdc6c66048f63a5f2b45fccd4c80283b40ac8c5 Mon Sep 17 00:00:00 2001 From: cstarcher Date: Fri, 22 May 2026 14:06:12 -0500 Subject: [PATCH 3/3] fixed test --- .../model/CustomActionDefinitionTest.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/test/java/org/tdl/vireo/model/CustomActionDefinitionTest.java b/src/test/java/org/tdl/vireo/model/CustomActionDefinitionTest.java index 1799089637..94f7f5eb67 100644 --- a/src/test/java/org/tdl/vireo/model/CustomActionDefinitionTest.java +++ b/src/test/java/org/tdl/vireo/model/CustomActionDefinitionTest.java @@ -1,8 +1,19 @@ package org.tdl.vireo.model; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.util.stream.Stream; + +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.provider.Arguments; import org.mockito.InjectMocks; +import org.tdl.vireo.model.response.Views; + +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; public class CustomActionDefinitionTest extends AbstractModelCustomMethodTest { @@ -43,4 +54,62 @@ private static Stream getParameterMethodStream() { ); } + /** + * Regression test for GitHub issue #2104. + * + * Verifies that {@code CustomActionDefinition.position} is included in the + * JSON output when serialized under {@link Views.SubmissionList} (and its + * sub-views such as {@link Views.SubmissionIndividualActionLogs}). + * + * The application sets {@code jackson.mapper.default-view-inclusion: false}, + * so any field without a matching {@code @JsonView} annotation is silently + * excluded when a view is active. The fix overrides {@code getPosition()} in + * {@code CustomActionDefinition} with {@code @JsonView(Views.SubmissionList.class)}. + * Removing that annotation will cause this test to fail. + */ + @Test + public void testPositionSerializedInSubmissionListView() throws Exception { + // Configure ObjectMapper to match application.yml: default-view-inclusion: false + ObjectMapper mapper = JsonMapper.builder() + .disable(MapperFeature.DEFAULT_VIEW_INCLUSION) + .build(); + + CustomActionDefinition definition = new CustomActionDefinition("Test action", true); + definition.setPosition(3L); + + // Serialize under Views.SubmissionList — the view used by /submission/query + String json = mapper.writerWithView(Views.SubmissionList.class).writeValueAsString(definition); + ObjectNode node = (ObjectNode) mapper.readTree(json); + + assertNotNull(node.get("position"), + "position must be present in SubmissionList view JSON; " + + "ensure getPosition() in CustomActionDefinition is annotated with @JsonView(Views.SubmissionList.class)"); + assertTrue(node.get("position").isNumber(), + "position must be a numeric value in SubmissionList view JSON"); + } + + /** + * Verifies that {@code position} is also included when serialized under the + * {@link Views.SubmissionIndividualActionLogs} view used by the admin + * {@code GET /submission/get-one/{id}} endpoint, since that view extends + * {@link Views.SubmissionList}. + */ + @Test + public void testPositionSerializedInSubmissionIndividualActionLogsView() throws Exception { + ObjectMapper mapper = JsonMapper.builder() + .disable(MapperFeature.DEFAULT_VIEW_INCLUSION) + .build(); + + CustomActionDefinition definition = new CustomActionDefinition("Test action", true); + definition.setPosition(5L); + + String json = mapper.writerWithView(Views.SubmissionIndividualActionLogs.class).writeValueAsString(definition); + ObjectNode node = (ObjectNode) mapper.readTree(json); + + assertNotNull(node.get("position"), + "position must be present in SubmissionIndividualActionLogs view JSON"); + assertTrue(node.get("position").isNumber(), + "position must be a numeric value in SubmissionIndividualActionLogs view JSON"); + } + }