From 8b559c6bc4289d1f16ba80d4625e9f927c5ae8b5 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Wed, 26 Nov 2025 15:39:39 +0100 Subject: [PATCH 1/3] feat: add "isInReviewState" to API responses about dataset versions --- .../java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java index 654154c5b64..0f8042cc021 100644 --- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java +++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java @@ -533,6 +533,7 @@ public static JsonObjectBuilder json(DatasetVersion dsv, List anonymized .add("internalVersionNumber", dsv.getVersion()) .add("versionMinorNumber", dsv.getMinorVersionNumber()) .add("versionState", dsv.getVersionState().name()) + .add("isInReviewState", dsv.isInReview()) .add("latestVersionPublishingState", dataset.getLatestVersion().getVersionState().name()) .add("deaccessionNote", dsv.getDeaccessionNote()) .add("deaccessionLink", dsv.getDeaccessionLink()) From 046d9698955a213b2fd909399a6ec032fe74d97a Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Thu, 27 Nov 2025 16:36:02 +0100 Subject: [PATCH 2/3] test: add "isInReviewState" to API responses about dataset versions --- .../harvard/iq/dataverse/api/DatasetsIT.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java index 39c66f9888f..91e5f436d7b 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java @@ -1176,6 +1176,7 @@ public void testDatasetVersionsAPI() { datasetVersion.then().assertThat() .statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.latestVersionPublishingState", equalTo("RELEASED")); // Upload another file: @@ -1189,6 +1190,7 @@ public void testDatasetVersionsAPI() { datasetVersion.then().assertThat() .statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.latestVersionPublishingState", equalTo("DRAFT")); datasetVersion = UtilIT.getDatasetVersion(datasetPid, DS_VERSION_LATEST, apiTokenNoPerms, excludeFiles, includeDeaccessioned); @@ -1196,6 +1198,7 @@ public void testDatasetVersionsAPI() { datasetVersion.then().assertThat() .statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.latestVersionPublishingState", equalTo("DRAFT")); // We should now have a published version, and a draft. @@ -1222,6 +1225,7 @@ public void testDatasetVersionsAPI() { .statusCode(OK.getStatusCode()) .body("data.size()", equalTo(1)) .body("data.versionState[0]", equalTo("DRAFT")) + .body("data[0].isInReviewState", equalTo(false)) .body("data[0].files.size()", equalTo(2)); // And now call it with an un-privileged token, to make sure only one @@ -1231,6 +1235,7 @@ public void testDatasetVersionsAPI() { versionsResponse.then().assertThat() .statusCode(OK.getStatusCode()) .body("data.versionState[0]", not("DRAFT")) + .body("data[0].isInReviewState", equalTo(false)) .body("data.size()", equalTo(1)); // And now call the "short", no-files version of the same api @@ -1253,6 +1258,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest published unauthorized token @@ -1261,6 +1267,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest authorized token @@ -1269,6 +1276,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest unauthorized token @@ -1277,6 +1285,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Specific version authorized token @@ -1285,6 +1294,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Specific version unauthorized token @@ -1293,6 +1303,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); excludeFiles = false; @@ -1303,6 +1314,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Latest published unauthorized token @@ -1311,6 +1323,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Latest authorized token, user is authenticated should get the Draft version @@ -1319,6 +1332,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(2)); //Latest unauthorized token, user has no permissions should get the latest Published version @@ -1327,6 +1341,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Specific version authorized token @@ -1335,6 +1350,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Specific version unauthorized token @@ -1343,6 +1359,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("RELEASED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //We deaccession the dataset @@ -1359,6 +1376,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Latest published requesting files, one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets @@ -1371,6 +1389,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(2)); //Latest unauthorized token requesting files, one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets @@ -1383,6 +1402,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(1)); //Specific version unauthorized token requesting files, one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets. @@ -1398,6 +1418,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest published exclude files, should get the DEACCESSIONED version @@ -1406,6 +1427,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest authorized token should get the DRAFT version with no files @@ -1414,6 +1436,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest unauthorized token excluding files, one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets @@ -1422,6 +1445,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Specific version authorized token @@ -1430,6 +1454,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Specific version unauthorized token requesting files, one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets. @@ -1438,6 +1463,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DEACCESSIONED")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Set of test when we have a deaccessioned dataset but we don't include deaccessioned @@ -1460,6 +1486,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files.size()", equalTo(2)); //Latest unauthorized token one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets @@ -1494,6 +1521,7 @@ public void testDatasetVersionsAPI() { datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(OK.getStatusCode()) .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(false)) .body("data.files", equalTo(null)); //Latest unauthorized token one version is DEACCESSIONED the second is DRAFT so shouldn't get any datasets @@ -1510,6 +1538,28 @@ public void testDatasetVersionsAPI() { datasetVersion = UtilIT.getDatasetVersion(datasetPid, specificVersion, apiTokenNoPerms, excludeFiles, includeDeaccessioned); datasetVersion.prettyPrint(); datasetVersion.then().assertThat().statusCode(NOT_FOUND.getStatusCode()); + + // Now we request review for the dataset, and check that this is reflected in the API responses + + Response submitForReview = UtilIT.submitDatasetForReview(datasetPid, apiToken); + submitForReview.prettyPrint(); + submitForReview.then().assertThat() + .statusCode(OK.getStatusCode()); + + datasetVersion = UtilIT.getDatasetVersion(datasetPid, DS_VERSION_LATEST, apiToken); + datasetVersion.prettyPrint(); + datasetVersion.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.versionState", equalTo("DRAFT")) + .body("data.isInReviewState", equalTo(true)) + .body("data.latestVersionPublishingState", equalTo("DRAFT")); + + versionsResponse = UtilIT.getDatasetVersions(datasetPid, apiToken); + versionsResponse.prettyPrint(); + versionsResponse.then().assertThat() + .statusCode(OK.getStatusCode()) + .body("data.versionState[0]", equalTo("DRAFT")) + .body("data[0].isInReviewState", equalTo(true)); } From 76026b1bf328a5777a0b801e45b5b5fd081325a1 Mon Sep 17 00:00:00 2001 From: Vera Clemens Date: Thu, 27 Nov 2025 16:41:07 +0100 Subject: [PATCH 3/3] docs: add "isInReviewState" to API responses about dataset versions --- doc/release-notes/12008-is-in-review-state.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/release-notes/12008-is-in-review-state.md diff --git a/doc/release-notes/12008-is-in-review-state.md b/doc/release-notes/12008-is-in-review-state.md new file mode 100644 index 00000000000..f0162c328c4 --- /dev/null +++ b/doc/release-notes/12008-is-in-review-state.md @@ -0,0 +1 @@ +The APIs returning information about dataset versions (`/api/datasets/{id}/versions` and `/api/datasets/{id}/versions/{vid}`) now include an `isInReviewState` field indicating whether a specific version is currently under review. \ No newline at end of file