Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
911f57c
refactor: add TimeZone enum instead of simple string
Jonathan-Zollinger Mar 10, 2026
a9102f5
refactor: add TimeZone enum instead of simple string
Jonathan-Zollinger Mar 10, 2026
62ab06e
refactor(wip): create dynamic query builder
Jonathan-Zollinger Mar 10, 2026
7023a5d
refactor(wip): build mutation query
Jonathan-Zollinger Mar 10, 2026
a59bcab
refactor(wip): build mutation query
Jonathan-Zollinger Mar 10, 2026
7913c42
feat: add working test for createEvent()
Jonathan-Zollinger Mar 11, 2026
cdfda63
refactor: rename CreateEventFields
Jonathan-Zollinger Mar 11, 2026
82d8654
refactor: remove unused pojo
Jonathan-Zollinger Mar 11, 2026
5ddbcc8
test(wip): add controlled chaos
Jonathan-Zollinger Mar 11, 2026
62c0db8
test: lean into providing fake data
Jonathan-Zollinger Mar 11, 2026
b240dfd
fix: write custom ProjectStatus Enum
Jonathan-Zollinger Mar 12, 2026
00d7ac1
test(wip): drop me
Jonathan-Zollinger Mar 12, 2026
a07709e
refactor: rename ProjectEvent. describe use cases in comments
Jonathan-Zollinger Mar 12, 2026
a156da1
fix: add missing CreateEventVariables
Jonathan-Zollinger Mar 12, 2026
fae7d27
refactor(docs): correct punctuation
Jonathan-Zollinger Mar 13, 2026
36bbcce
fix: set timezone field as pojo
Jonathan-Zollinger Mar 13, 2026
402cc5b
fix: set query value as json value
Jonathan-Zollinger Mar 13, 2026
d626d80
test(wip): split createEvent into tests against individual fields
Jonathan-Zollinger Mar 13, 2026
4f506c5
feat: add tests for ongoing events
Jonathan-Zollinger Mar 15, 2026
876c10f
refactor: ignore leftshift incompatibility
Jonathan-Zollinger Mar 15, 2026
99565d5
refactor: remove custom linebreaks
Jonathan-Zollinger Mar 15, 2026
c979b24
docs: flesh out javadocs
Jonathan-Zollinger Mar 15, 2026
5230b5d
refactor: move model classes to model dir
Jonathan-Zollinger Mar 15, 2026
968b885
fix: update properties allowed in different projectTypes
Jonathan-Zollinger Mar 15, 2026
8a887f1
docs: add javadocs
Jonathan-Zollinger Mar 15, 2026
978f1c9
build: remove edits to test heap size
Jonathan-Zollinger Mar 15, 2026
f889cd5
refactor: skip test which needs investigating
Jonathan-Zollinger Mar 15, 2026
0f14e58
refactor: remove deprecated methods
Jonathan-Zollinger Mar 15, 2026
849e25e
refactor: rename to GraphQuery to GraphMutation
Jonathan-Zollinger Mar 17, 2026
2af0bcc
feat: add CreateEvents
Jonathan-Zollinger Mar 17, 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
4 changes: 4 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ micronaut {
importMapping.put("EventType", "org.justserve.model.EventType")
schemaMapping.put("ProjectLocationType", "org.justserve.model.ProjectLocationType")
importMapping.put("ProjectLocationType", "org.justserve.model.ProjectLocationType")
schemaMapping.put("ProjectStatus", "org.justserve.model.ProjectStatus")
importMapping.put("ProjectStatus", "org.justserve.model.ProjectStatus")
schemaMapping.put("TimeZone", "org.justserve.model.TimeZone")
importMapping.put("TimeZone", "org.justserve.model.TimeZone")
}
}
processing {
Expand Down
39 changes: 26 additions & 13 deletions core/src/main/java/org/justserve/client/GraphQLClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@
import io.micronaut.http.client.annotation.Client;
import io.micronaut.retry.annotation.Retryable;
import org.justserve.model.*;
import org.justserve.model.graph.*;

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

@Produces("application/json")
@Consumes("application/graphql-response+json; charset=utf-8")
@Retryable
@Client(id = "justserve", path = "/graphql")
public interface GraphQLClient {

@Post
GraphQLResponse<ProjectEvent> createEvent(@Body CreateEventMutation request);

@Post
GraphQLResponse<CreateEventsData> createEvents(@Body CreateEventsMutation request);

@Post
GraphQLResponse<CreateRecurringEventsData> createRecurringEvents(@Body CreateRecurringEventsMutation request);

@Post
GraphQLResponse<GraphQLAddProjectAttachmentData> executeAddProjectAttachment(@Body GraphQLAddProjectAttachmentRequest request);

Expand All @@ -23,9 +36,6 @@ public interface GraphQLClient {
@Post
GraphQLResponse<GraphQLCombinedMutationUpdateProjectAddProjectTagData> executeCombinedMutationUpdateProjectAddProjectTag(@Body GraphQLCombinedMutationUpdateProjectAddProjectTagRequest request);

@Post
GraphQLResponse<GraphQLCreateEventData> executeCreateEvent(@Body GraphQLCreateEventRequest request);

@Post
GraphQLResponse<GraphQLCreateProjectData> executeCreateProject(@Body GraphQLCreateProjectRequest request);

Expand Down Expand Up @@ -71,14 +81,6 @@ default GraphQLResponse<GraphQLCombinedMutationUpdateProjectAddProjectTagData> c
return this.executeCombinedMutationUpdateProjectAddProjectTag(request);
}

default GraphQLResponse<GraphQLCreateEventData> createEvent(GraphQLCreateEventVariables variables) {
String fixedQuery = "mutation createEvent($projectId: ID!, $projectEvent: UpdateProjectEventInput!) {\n createEvent(\n projectId: $projectId\n projectEvent: $projectEvent\n ) {\n id\n projectId\n contactEmail\n contactName\n contactPhone\n start\n end\n groupCap\n groupLimit\n timezone\n totalVolunteersNeeded\n volunteerCap\n }\n }";
GraphQLCreateEventRequest request = new GraphQLCreateEventRequest();
request.setQuery(fixedQuery);
request.setVariables(variables);
return this.executeCreateEvent(request);
}

default GraphQLResponse<GraphQLCreateProjectData> createProject(GraphQLCreateProjectVariables variables) {
String fixedQuery = "mutation createProject($title: String!, $eventType: ProjectType!, $locationType: ProjectLocationType!, $redirect: String) {\n createProject(\n title: $title\n eventType: $eventType\n locationType: $locationType\n redirect: $redirect\n ) {\n id\n title\n typeId\n locationTypeId\n externalVolunteerUrl\n statusId\n }\n }";
GraphQLCreateProjectRequest request = new GraphQLCreateProjectRequest();
Expand Down Expand Up @@ -128,9 +130,20 @@ default GraphQLResponse<GraphQLUpdateProjectListingData> updateProjectListing(Gr
}

default GraphQLResponse<GraphQLUpdateProjectData> updateProject(GraphQLUpdateProjectVariables variables) {
String fixedQuery = "mutation ($projectId: ID!, $logo: String!) {\n updateProject(id: $projectId, modify: { logo: $logo }) {\n id\n logo\n }\n }";
String mutationFormat = "mutation ($projectId: ID!, $logo: String!) {\n updateProject(id: $projectId, modify: { logo: $logo }) {\n %s\n }\n }";

List<String> responseFields = new ArrayList<>();
responseFields.add("id");

if (variables.getLogo() != null) {
responseFields.add("logo");
}

String fieldsString = String.join("\n", responseFields);
String dynamicQuery = String.format(mutationFormat, fieldsString);

GraphQLUpdateProjectRequest request = new GraphQLUpdateProjectRequest();
request.setQuery(fixedQuery);
request.setQuery(dynamicQuery);
request.setVariables(variables);
return this.executeUpdateProject(request);
}
Expand Down
17 changes: 17 additions & 0 deletions core/src/main/java/org/justserve/model/CivicGeography.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.justserve.model;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.serde.annotation.Serdeable;
import lombok.Data;
import lombok.experimental.Accessors;

/**
* This class is currently a placeholder for a future work.
* This class does nothing.
*/
@Data
@Accessors(chain = true)
@Serdeable
@Introspected
public class CivicGeography {
}
43 changes: 36 additions & 7 deletions core/src/main/java/org/justserve/model/EventType.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import io.micronaut.serde.annotation.Serdeable;
import jakarta.annotation.Generated;
import lombok.Generated;
import lombok.RequiredArgsConstructor;

import java.util.Arrays;
Expand All @@ -12,16 +12,40 @@
import java.util.stream.Collectors;

/**
* Gets or Sets EventType
* Defines the scheduling model for a JustServe project, determining how its
* {@link ProjectEvent}s are structured and displayed.
*
* @author Jonathan Zollinger
* @since 0.1.0
*/
@RequiredArgsConstructor
@Serdeable
@Generated("io.micronaut.openapi.generator.JavaMicronautClientCodegen")
public enum EventType {
// None(0, "None"),
/**
* <h4>Date, Time, and Location</h4>
* A standard event that occurs at a specific time and place.
*/
DTL(1, "DTL"),

/**
* <h4>Ongoing</h4>
* An event with no specific time. The start and end dates determine visibility on JustServe
*/
Ongoing(2, "ONGOING"),

/**
* <h4>Recurring</h4>
* An event that repeats on a regular schedule, such as weekly or monthly.
* <p><b>Example:</b> An evening opportunity that occurs every Monday, Wednesday,
* and Friday for three months.
*/
Recurring(3, "RECURRING"),

/**
* <h4>Multiple Date, Time, and Location</h4>
* A complex event that has multiple, distinct shifts or occurrences.
* <p><b>Example:</b> A project with multiple shifts on each Saturday for several weeks.
*/
MultipleDTL(4, "MULTIPLE_DTL");

public static final Map<Integer, EventType> VALUE_MAPPING = Map.copyOf(Arrays.stream(values())
Expand All @@ -40,8 +64,13 @@ public String getStringValue() {
return stringValue;
}

// 2. RECEIVING (Response): This catches the incoming data.
// It can handle the Integer '1' from GraphQL, or even a String if a REST endpoint sends one.
/**
* Parses the incoming value to either the string or integer value, whichever the server is using.
*
* @param value the incoming value from the server
* @return the event type that matches the incoming value
*/
@Generated //manually placed annotation to tell jacoco coverage report to ignore this
@JsonCreator
public static EventType fromValue(Object value) {
if (value instanceof Number) {
Expand All @@ -56,4 +85,4 @@ public static EventType fromValue(Object value) {
}
throw new IllegalArgumentException("Unexpected value '" + value + "' for EventType");
}
}
}
18 changes: 0 additions & 18 deletions core/src/main/java/org/justserve/model/GraphQLRequest.java

This file was deleted.

Loading
Loading