diff --git a/dashx/src/main/java/com/dashx/DashX.java b/dashx/src/main/java/com/dashx/DashX.java index 0d6c91e..b531e11 100644 --- a/dashx/src/main/java/com/dashx/DashX.java +++ b/dashx/src/main/java/com/dashx/DashX.java @@ -12,6 +12,7 @@ import org.springframework.util.MultiValueMap; import com.dashx.graphql.generated.types.Account; +import com.dashx.graphql.generated.types.AggregateResponse; import com.dashx.graphql.generated.types.Asset; import com.dashx.graphql.generated.types.Issue; import com.dashx.graphql.generated.types.Broadcast; @@ -411,6 +412,68 @@ public CompletableFuture upsertIssue(UpsertIssueInput input) { return issueService.upsertIssue(input).toFuture(); } + /** + * Lists issues with optional filtering, ordering, and pagination. + * + * @param filter Optional filter criteria + * @param order Optional ordering criteria + * @param limit Optional maximum number of results + * @param page Optional page number for pagination + * @param targetEnvironment Optional target environment identifier to scope the query + * @return A CompletableFuture that will be completed with the list of issues or completed + * exceptionally if there are GraphQL errors or execution errors. + */ + public CompletableFuture> listIssues(Map filter, + List> order, Integer limit, Integer page, String targetEnvironment) { + ensureConfigured(); + + logger.debug("Listing issues with filter: {}, limit: {}, page: {}", filter, limit, page); + return issueService.listIssues(filter, order, limit, page, targetEnvironment).toFuture(); + } + + public CompletableFuture> listIssues(Map filter, + List> order, Integer limit, Integer page) { + return listIssues(filter, order, limit, page, null); + } + + public CompletableFuture> listIssues(Map filter, + List> order) { + return listIssues(filter, order, null, null, null); + } + + public CompletableFuture> listIssues(Map filter) { + return listIssues(filter, null, null, null, null); + } + + public CompletableFuture> listIssues() { + return listIssues(null, null, null, null, null); + } + + /** + * Counts issues matching the provided filter. + * + * @param filter Optional filter criteria + * @param targetEnvironment Optional target environment identifier to scope the query + * @return A CompletableFuture that will be completed with the aggregate response containing + * the count of matching issues, or completed exceptionally if there are GraphQL errors + * or execution errors. + */ + public CompletableFuture aggregateIssues(Map filter, + String targetEnvironment) { + ensureConfigured(); + + logger.debug("Aggregating issues with filter: {}", filter); + return issueService.aggregateIssues(filter, targetEnvironment).toFuture(); + } + + public CompletableFuture aggregateIssues(Map filter) { + return aggregateIssues(filter, null); + } + + public CompletableFuture aggregateIssues() { + return aggregateIssues(null, null); + } + /** * Creates a new broadcast using the CreateBroadcast mutation. * diff --git a/dashx/src/main/java/com/dashx/graphql/IssueService.java b/dashx/src/main/java/com/dashx/graphql/IssueService.java index 85b4b1e..5df157a 100644 --- a/dashx/src/main/java/com/dashx/graphql/IssueService.java +++ b/dashx/src/main/java/com/dashx/graphql/IssueService.java @@ -1,9 +1,12 @@ package com.dashx.graphql; import com.dashx.DashXGraphQLClient; +import com.dashx.graphql.generated.types.AggregateResponse; import com.dashx.graphql.generated.types.CreateIssueInput; import com.dashx.graphql.generated.types.Issue; import com.dashx.graphql.generated.types.UpsertIssueInput; +import java.util.HashMap; +import java.util.List; import java.util.Map; import reactor.core.publisher.Mono; @@ -30,6 +33,7 @@ public IssueService(DashXGraphQLClient client) { issueStatusId createdById environmentId + requestedById spaceId parentId assigneeId @@ -83,4 +87,53 @@ public Mono upsertIssue(UpsertIssueInput input) { return client.execute(query, variables) .map(response -> response.extractValueAsObject("upsertIssue", Issue.class)); } + + /** + * Lists issues with optional filtering, ordering, and pagination. + * + * @param filter optional filter criteria to narrow down results + * @param order optional ordering criteria to sort the results + * @param limit optional maximum number of results to return per page + * @param page optional page number for pagination + * @param targetEnvironment optional target environment identifier to scope the query + * @return a Mono that emits a list of Issue objects matching the criteria + */ + public Mono> listIssues(Map filter, + List> order, Integer limit, Integer page, String targetEnvironment) { + String query = + "query ListIssues($filter: JSON, $order: [JSON!], $limit: Int, $page: Int, $targetEnvironment: String) { issuesList(filter: $filter, order: $order, limit: $limit, page: $page, targetEnvironment: $targetEnvironment) " + + this.fullIssueProjection + " }"; + + Map variables = new HashMap<>(); + if (filter != null) variables.put("filter", filter); + if (order != null) variables.put("order", order); + if (limit != null) variables.put("limit", limit); + if (page != null) variables.put("page", page); + if (targetEnvironment != null) variables.put("targetEnvironment", targetEnvironment); + + return client.execute(query, variables).map(response -> { + Issue[] issuesArray = response.extractValueAsObject("issuesList", Issue[].class); + return issuesArray != null ? List.of(issuesArray) : List.of(); + }); + } + + /** + * Counts issues matching the provided filter. + * + * @param filter optional filter criteria to narrow down the count + * @param targetEnvironment optional target environment identifier to scope the query + * @return a Mono that emits an AggregateResponse containing the count of matching issues + */ + public Mono aggregateIssues(Map filter, + String targetEnvironment) { + String query = + "query AggregateIssues($filter: JSON, $targetEnvironment: String) { issuesAggregate(filter: $filter, targetEnvironment: $targetEnvironment) { count } }"; + + Map variables = new HashMap<>(); + if (filter != null) variables.put("filter", filter); + if (targetEnvironment != null) variables.put("targetEnvironment", targetEnvironment); + + return client.execute(query, variables).map(response -> response + .extractValueAsObject("issuesAggregate", AggregateResponse.class)); + } } diff --git a/dashx/src/main/resources/schema/dashx.graphql b/dashx/src/main/resources/schema/dashx.graphql index 98aa3ac..d3a2ba7 100644 --- a/dashx/src/main/resources/schema/dashx.graphql +++ b/dashx/src/main/resources/schema/dashx.graphql @@ -6,6 +6,8 @@ type Query { asset(id: UUID!): Asset! issue(id: UUID!): Issue! assetsList(filter: JSON, order: [JSON!], limit: Int, page: Int): [Asset!]! + issuesList(filter: JSON, order: [JSON!], limit: Int, page: Int, targetEnvironment: String): [Issue!]! + issuesAggregate(filter: JSON, targetEnvironment: String): AggregateResponse! searchRecords(input: SearchRecordsInput!): [JSON!]! } @@ -84,6 +86,10 @@ type TrackEventResponse { success: Boolean! } +type AggregateResponse { + count: Int +} + type Broadcast { id: UUID! templateSubkind: TemplateSubkind! diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c432452..2799e5c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format [versions] -dashx = "1.4.1" +dashx = "1.4.2" group = "com.dashx" junit-jupiter = "5.11.3"