diff --git a/builder-api/src/main/java/org/acme/controller/DecisionResource.java b/builder-api/src/main/java/org/acme/controller/DecisionResource.java index 8b020580..d008c226 100644 --- a/builder-api/src/main/java/org/acme/controller/DecisionResource.java +++ b/builder-api/src/main/java/org/acme/controller/DecisionResource.java @@ -136,9 +136,9 @@ private Map evaluateBenefit(Benefit benefit, Map String dmnFilepath = storageService.getCheckDmnModelPath(checkConfig.getCheckId()); EvaluationResult evaluationResult; if (isLibraryCheck(checkConfig)){ - EligibilityCheck check = libraryApi.getById(checkConfig.getCheckId()); - String path = check.getPath(); - evaluationResult = libraryApi.evaluateCheck(checkConfig, path, formData); + + String evaluationUrl = checkConfig.getEvaluationUrl(); + evaluationResult = libraryApi.evaluateCheck(checkConfig, evaluationUrl, formData); } else { Map customFormValues = (Map) formData.get("custom"); if (customFormValues == null) { diff --git a/builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java b/builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java index e12b8709..6b5146fc 100644 --- a/builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java +++ b/builder-api/src/main/java/org/acme/controller/EligibilityCheckResource.java @@ -185,7 +185,9 @@ public Response createCustomCheck(@Context SecurityIdentity identity, //TODO: Add validations for user provided data newCheck.setOwnerId(userId); newCheck.setPublic(false); - newCheck.setVersion(0); + if (newCheck.getVersion().isEmpty()){ + newCheck.setVersion("1.0.0"); + } try { eligibilityCheckRepository.saveNewWorkingCustomCheck(newCheck); return Response.ok(newCheck, MediaType.APPLICATION_JSON).build(); @@ -242,7 +244,7 @@ public Response publishCustomCheck(@Context SecurityIdentity identity, @PathPara } // Update workingCheck so that the incremented version number is saved - check.setVersion(check.getVersion() + 1); + check.setVersion(incrementMajorVersion(check.getVersion())); try { eligibilityCheckRepository.updateWorkingCustomCheck(check); } catch (Exception e){ @@ -272,6 +274,24 @@ public Response publishCustomCheck(@Context SecurityIdentity identity, @PathPara return Response.ok(check, MediaType.APPLICATION_JSON).build(); } + private String incrementMajorVersion(String version) { + int[] v = normalize(version); + v[0]++; // increment major + v[1] = 0; // reset minor + v[2] = 0; // reset patch + return v[0] + "." + v[1] + "." + v[2]; + } + + private int[] normalize(String version) { + String[] parts = version.split("\\."); + int[] nums = new int[]{0, 0, 0}; + + for (int i = 0; i < parts.length && i < 3; i++) { + nums[i] = Integer.parseInt(parts[i]); + } + return nums; + } + /* Endpoint for returning all Published Check Versions related to a given Working Eligibility Check */ @GET @Path("/custom-checks/{checkId}/published-check-versions") @@ -290,7 +310,7 @@ public Response getPublishedVersionsOfWorkingCheck(@Context SecurityIdentity ide } // Update workingCheck so that the incremented version number is saved - check.setVersion(check.getVersion() + 1); + check.setVersion(incrementMajorVersion(check.getVersion())); try { List publishedChecks = eligibilityCheckRepository.getPublishedCheckVersions(check); diff --git a/builder-api/src/main/java/org/acme/model/domain/CheckConfig.java b/builder-api/src/main/java/org/acme/model/domain/CheckConfig.java index c941bdc0..0011bb7d 100644 --- a/builder-api/src/main/java/org/acme/model/domain/CheckConfig.java +++ b/builder-api/src/main/java/org/acme/model/domain/CheckConfig.java @@ -1,14 +1,22 @@ package org.acme.model.domain; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.JsonNode; +import java.util.List; import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) public class CheckConfig { private String checkId; private String checkName; + private String checkVersion; + private String checkModule; private Map parameters; + // evaluation endpoint url for library checks + private String evaluationUrl; + private JsonNode inputDefinition; + private List parameterDefinitions; public String getCheckId() { return checkId; @@ -33,4 +41,44 @@ public String getCheckName() { public void setCheckName(String checkName) { this.checkName = checkName; } + + public String getEvaluationUrl() { + return evaluationUrl; + } + + public void setEvaluationUrl(String libraryCheckEvaluationUrl) { + this.evaluationUrl = libraryCheckEvaluationUrl; + } + + public JsonNode getInputDefinition() { + return inputDefinition; + } + + public void setInputDefinition(JsonNode inputDefinition) { + this.inputDefinition = inputDefinition; + } + + public List getParameterDefinitions() { + return parameterDefinitions; + } + + public void setParameterDefinitions(List parameterDefinitions) { + this.parameterDefinitions = parameterDefinitions; + } + + public String getCheckVersion() { + return checkVersion; + } + + public void setCheckVersion(String checkVersion) { + this.checkVersion = checkVersion; + } + + public String getCheckModule() { + return checkModule; + } + + public void setCheckModule(String checkModule) { + this.checkModule = checkModule; + } } diff --git a/builder-api/src/main/java/org/acme/model/domain/EligibilityCheck.java b/builder-api/src/main/java/org/acme/model/domain/EligibilityCheck.java index 6c8bafe8..7177b3ae 100644 --- a/builder-api/src/main/java/org/acme/model/domain/EligibilityCheck.java +++ b/builder-api/src/main/java/org/acme/model/domain/EligibilityCheck.java @@ -12,12 +12,11 @@ public class EligibilityCheck { private String name; private String module; private String description; - private Integer version; + private String version; private boolean isActive; private String dmnModel; - private List inputs; - private JsonNode situation; - private List parameters; + private JsonNode inputDefinition; + private List parameterDefinitions; private String ownerId; @JsonProperty("isPublic") private Boolean isPublic; @@ -64,11 +63,11 @@ public void setDescription(String description) { this.description = description; } - public Integer getVersion() { + public String getVersion() { return version; } - public void setVersion(Integer version) { + public void setVersion(String version) { this.version = version; } @@ -80,20 +79,12 @@ public void setActive(boolean active) { isActive = active; } - public List getInputs() { - return inputs; + public List getParameterDefinitions() { + return parameterDefinitions; } - public void setInputs(List inputDefinitions) { - this.inputs = inputDefinitions; - } - - public List getParameters() { - return parameters; - } - - public void setParameters(List parameters) { - this.parameters = parameters; + public void setParameterDefinitions(List parameterDefinitions) { + this.parameterDefinitions = parameterDefinitions; } public String getOwnerId() { @@ -112,12 +103,12 @@ public void setPublic(Boolean aPublic) { isPublic = aPublic; } - public JsonNode getSituation() { - return situation; + public JsonNode getInputDefinition() { + return inputDefinition; } - public void setSituation(JsonNode situation) { - this.situation = situation; + public void setInputDefinition(JsonNode inputDefinition) { + this.inputDefinition = inputDefinition; } public String getPath() { diff --git a/builder-api/src/main/java/org/acme/model/domain/InputDefinition.java b/builder-api/src/main/java/org/acme/model/domain/InputDefinition.java deleted file mode 100644 index 4adc35e6..00000000 --- a/builder-api/src/main/java/org/acme/model/domain/InputDefinition.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.acme.model.domain; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -import java.util.Map; - - -@JsonIgnoreProperties(ignoreUnknown = true) -public class InputDefinition { - private String key; - private String label; - private String prompt; - private String type; - private String options; - private Map validation; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - public String getPrompt() { - return prompt; - } - - public void setPrompt(String prompt) { - this.prompt = prompt; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public Map getValidation() { - return validation; - } - - public void setValidation(Map validation) { - this.validation = validation; - } - - public String getOptions() { - return options; - } - - public void setOptions(String options) { - this.options = options; - } -} diff --git a/builder-api/src/main/java/org/acme/persistence/impl/EligibilityCheckRepositoryImpl.java b/builder-api/src/main/java/org/acme/persistence/impl/EligibilityCheckRepositoryImpl.java index efa67b4e..ce0ad1f7 100644 --- a/builder-api/src/main/java/org/acme/persistence/impl/EligibilityCheckRepositoryImpl.java +++ b/builder-api/src/main/java/org/acme/persistence/impl/EligibilityCheckRepositoryImpl.java @@ -87,11 +87,33 @@ public List getLatestVersionPublishedCustomChecks(String userI .collect(java.util.stream.Collectors.toMap( check -> getPublishedPrefix(check), check -> check, - (check1, check2) -> check1.getVersion() > check2.getVersion() ? check1 : check2 + (check1, check2) -> compareVersions(check1.getVersion(), check2.getVersion()) > 0 ? check1 : check2 )); return new ArrayList<>(latestVersionMap.values()); } + private static int compareVersions(String v1, String v2) { + int[] a = normalize(v1); + int[] b = normalize(v2); + + for (int i = 0; i < 3; i++) { + if (a[i] != b[i]) { + return a[i] - b[i]; + } + } + return 0; + } + + private static int[] normalize(String version) { + String[] parts = version.split("\\."); + int[] nums = new int[] {0, 0, 0}; + + for (int i = 0; i < parts.length && i < 3; i++) { + nums[i] = Integer.parseInt(parts[i]); + } + return nums; + } + public List getPublishedCheckVersions(EligibilityCheck workingCustomCheck){ Map fieldValues = Map.of( "ownerId", workingCustomCheck.getOwnerId(), diff --git a/builder-api/src/main/java/org/acme/service/LibraryApiService.java b/builder-api/src/main/java/org/acme/service/LibraryApiService.java index fd5ba589..93e21cf7 100644 --- a/builder-api/src/main/java/org/acme/service/LibraryApiService.java +++ b/builder-api/src/main/java/org/acme/service/LibraryApiService.java @@ -27,7 +27,6 @@ public class LibraryApiService { @PostConstruct void init() { try { - // Get path of most recent library schema json document Optional> configOpt = FirestoreUtils.getFirestoreDocById("system", "config"); if (configOpt.isEmpty()){ @@ -71,7 +70,7 @@ public EligibilityCheck getById(String id) { return matches.getFirst(); } - public EvaluationResult evaluateCheck(CheckConfig checkConfig, String path, Map inputs){ + public EvaluationResult evaluateCheck(CheckConfig checkConfig, String evaluationUrl, Map inputs){ return EvaluationResult.TRUE; } } diff --git a/builder-frontend/src/api/benefit.ts b/builder-frontend/src/api/benefit.ts index b8d5cc17..37e33c27 100644 --- a/builder-frontend/src/api/benefit.ts +++ b/builder-frontend/src/api/benefit.ts @@ -1,10 +1,14 @@ import { authFetch } from "@/api/auth"; +import BenefitList from "@/components/project/manageBenefits/benefitList/BenefitList"; import { Benefit } from "@/types"; const apiUrl = import.meta.env.VITE_API_URL; -export const fetchScreenerBenefit = async (srceenerId: string, benefitId: string): Promise => { +export const fetchScreenerBenefit = async ( + srceenerId: string, + benefitId: string +): Promise => { const url = apiUrl + "/screener/" + srceenerId + "/benefit/" + benefitId; try { const response = await authFetch(url, { @@ -25,7 +29,10 @@ export const fetchScreenerBenefit = async (srceenerId: string, benefitId: string } }; -export const updateScreenerBenefit = async (screenerId: string, benefitData: Benefit): Promise => { +export const updateScreenerBenefit = async ( + screenerId: string, + benefitData: Benefit +): Promise => { const url = apiUrl + "/screener/" + screenerId + "/benefit"; try { const response = await authFetch(url, { @@ -48,7 +55,6 @@ export const updateScreenerBenefit = async (screenerId: string, benefitData: Ben } }; - export const fetchPublicBenefits = async (): Promise => { const url = apiUrl + "/benefit"; try { diff --git a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/ParametersConfiguration.tsx b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/ParametersConfiguration.tsx index 0a4a6111..d8e19080 100644 --- a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/ParametersConfiguration.tsx +++ b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/ParametersConfiguration.tsx @@ -5,7 +5,6 @@ import ParameterModal from "./modals/ParameterModal"; import ConfirmationModal from "@/components/shared/ConfirmationModal"; import type { EligibilityCheck, ParameterDefinition } from "@/types"; - const ParametersConfiguration = ({ eligibilityCheck, addParameter, @@ -21,8 +20,12 @@ const ParametersConfiguration = ({ removeParameter: (parameterIndex: number) => Promise; }) => { const [addingParameter, setAddingParameter] = createSignal(false); - const [parameterIndexToEdit, setParameterIndexToEdit] = createSignal(null); - const [parameterIndexToRemove, setParameterIndexToRemove] = createSignal(null); + const [parameterIndexToEdit, setParameterIndexToEdit] = createSignal< + null | number + >(null); + const [parameterIndexToRemove, setParameterIndexToRemove] = createSignal< + null | number + >(null); const handleProjectMenuClicked = (e, parameterIndex: number) => { e.stopPropagation(); @@ -46,11 +49,15 @@ const ParametersConfiguration = ({ Create New Parameter 0} + when={ + eligibilityCheck() && + eligibilityCheck().parameterDefinitions && + eligibilityCheck().parameterDefinitions.length > 0 + } fallback={

No parameters defined.

} >
- + {(param, parameterIndex) => (
)} diff --git a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/PublishCheck.tsx b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/PublishCheck.tsx index 357f5b5c..8b3d83ce 100644 --- a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/PublishCheck.tsx +++ b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/PublishCheck.tsx @@ -4,22 +4,52 @@ import { EligibilityCheck } from "@/types"; import { getRelatedPublishedChecks } from "@/api/check"; const PublishCheck = ({ - eligibilityCheck, publishCheck, + eligibilityCheck, + publishCheck, }: { eligibilityCheck: Accessor; publishCheck: (checkId: string) => Promise; }) => { const [relatedPublishedChecks] = createResource( - () => eligibilityCheck().id, getRelatedPublishedChecks + () => eligibilityCheck().id, + getRelatedPublishedChecks ); const sortedPublishedChecks = () => { /* Sort published checks by version in descending order */ const checks = relatedPublishedChecks(); if (!checks) return []; - return checks.slice().sort((check1, check2) => check2.version - check1.version); + return checks + .slice() + .sort((check1, check2) => + reverseCompareVersions(check1.version, check2.version) + ); }; + // Called reverse compare because we are sorting the largest version number first + function reverseCompareVersions(a: string, b: string): number { + const aValues = normalize(a); + const bValues = normalize(b); + + for (let i = 0; i < 3; i++) { + if (aValues[i] !== bValues[i]) { + // The order of this subtraction is what reverses the sort order + return bValues[i] - aValues[i]; + } + } + return 0; + } + + function normalize(version: string): [number, number, number] { + const parts = version.split(".").map(Number); + + while (parts.length < 3) { + parts.push(0); + } + + return [parts[0], parts[1], parts[2]]; + } + return (
@@ -40,17 +70,18 @@ const PublishCheck = ({ >
- {(checkVersion) => ( + {(check) => (
- {checkVersion.name} - v{checkVersion.version} + {check.name} - {check.version}
- Module: {checkVersion.module} + Module: {check.module}
- Number of Parameters: {checkVersion.parameters.length} + Number of Parameters:{" "} + {check.parameterDefinitions.length}
Date Published: -- @@ -64,6 +95,6 @@ const PublishCheck = ({
); -} +}; export default PublishCheck; diff --git a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/checkTesting/EligibilityCheckTest.tsx b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/checkTesting/EligibilityCheckTest.tsx index 949a2547..5d05733c 100644 --- a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/checkTesting/EligibilityCheckTest.tsx +++ b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/checkTesting/EligibilityCheckTest.tsx @@ -1,6 +1,11 @@ import { Accessor, createSignal, Match, Switch } from "solid-js"; -import { CheckConfig, EligibilityCheck, OptionalBoolean, ParameterValues } from "@/types"; +import { + CheckConfig, + EligibilityCheck, + OptionalBoolean, + ParameterValues, +} from "@/types"; import SelectedEligibilityCheck from "@/components/project/manageBenefits/configureBenefit/SelectedEligibilityCheck"; import CheckJsonEditor from "./CheckJsonEditor"; import { JSONContent } from "vanilla-jsoneditor"; @@ -10,26 +15,41 @@ interface TestRun { result: OptionalBoolean; } -const EligibilityCheckTest = ( - { eligibilityCheck, testEligibility }: - { - eligibilityCheck: Accessor, - testEligibility: (checkConfg: CheckConfig, inputData: Record) => Promise; - } -) => { - const [checkConfig, setCheckConfig] = createSignal( - { checkId: eligibilityCheck().id, checkName: eligibilityCheck().name, parameters: {} } - ); +const EligibilityCheckTest = ({ + eligibilityCheck, + testEligibility, +}: { + eligibilityCheck: Accessor; + testEligibility: ( + checkConfg: CheckConfig, + inputData: Record + ) => Promise; +}) => { + const [checkConfig, setCheckConfig] = createSignal({ + checkId: eligibilityCheck().id, + checkName: eligibilityCheck().name, + checkVersion: eligibilityCheck().version, + checkModule: eligibilityCheck().module, + checkDescription: eligibilityCheck().description, + parameterDefinitions: eligibilityCheck().parameterDefinitions, + inputDefinition: eligibilityCheck().inputDefinition, + evaluationUrl: eligibilityCheck().evaluationUrl, + parameters: {}, + }); const [lastTestResult, setLastTestResult] = createSignal(null); - const [initialJsonContent, setInitialJsonContent] = ( - createSignal<{ json: Record }>({ json: { example: "data" } }) - ); - const [currentJsonContent, setCurrentJsonContent] = createSignal<{ json: Record }>({ json: { example: "data" } }); + const [initialJsonContent, setInitialJsonContent] = createSignal<{ + json: Record; + }>({ json: { example: "data" } }); + const [currentJsonContent, setCurrentJsonContent] = createSignal<{ + json: Record; + }>({ json: { example: "data" } }); return (
-
{eligibilityCheck().name}
+
+ {eligibilityCheck().name} +

{eligibilityCheck().description}

@@ -52,7 +72,10 @@ const EligibilityCheckTest = ( {lastTestResult() !== null && ( <>
- Latest Test Data: {JSON.stringify(lastTestResult().inputData)} + Latest Test Data:{" "} + + {JSON.stringify(lastTestResult().inputData)} +
Latest Test Result: @@ -81,8 +104,8 @@ const EligibilityCheckTest = ( { - setCurrentJsonContent(content); } - } + setCurrentJsonContent(content); + }} />
@@ -98,6 +121,6 @@ const EligibilityCheckTest = (
- ) + ); }; export default EligibilityCheckTest; diff --git a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/eligibilityCheckDetailResource.ts b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/eligibilityCheckDetailResource.ts index 145ee5dc..d3cd68b1 100644 --- a/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/eligibilityCheckDetailResource.ts +++ b/builder-frontend/src/components/homeScreen/eligibilityCheckList/eligibilityCheckDetail/eligibilityCheckDetailResource.ts @@ -70,7 +70,10 @@ const eligibilityCheckDetailResource = ( const addParameter = async (parameterDef: ParameterDefinition) => { const updatedCheck: EligibilityCheckDetail = { ...eligibilityCheck, - parameters: [...eligibilityCheck.parameters, parameterDef], + parameterDefinitions: [ + ...eligibilityCheck.parameterDefinitions, + parameterDef, + ], }; setActionInProgress(true); try { @@ -86,12 +89,12 @@ const eligibilityCheckDetailResource = ( parameterIndex: number, parameterDef: ParameterDefinition ) => { - const updatedParameters = [...eligibilityCheck.parameters]; + const updatedParameters = [...eligibilityCheck.parameterDefinitions]; updatedParameters[parameterIndex] = parameterDef; console.log("updatedParameters", updatedParameters); const updatedCheck: EligibilityCheckDetail = { ...eligibilityCheck, - parameters: updatedParameters, + parameterDefinitions: updatedParameters, }; setActionInProgress(true); @@ -105,11 +108,11 @@ const eligibilityCheckDetailResource = ( }; const removeParameter = async (parameterIndex: number) => { - const updatedParameters = [...eligibilityCheck.parameters]; + const updatedParameters = [...eligibilityCheck.parameterDefinitions]; updatedParameters.splice(parameterIndex, 1); const updatedCheck: EligibilityCheckDetail = { ...eligibilityCheck, - parameters: updatedParameters, + parameterDefinitions: updatedParameters, }; setActionInProgress(true); diff --git a/builder-frontend/src/components/homeScreen/eligibilityCheckList/modals/CheckModal.tsx b/builder-frontend/src/components/homeScreen/eligibilityCheckList/modals/CheckModal.tsx index 7da2e4ad..054d834e 100644 --- a/builder-frontend/src/components/homeScreen/eligibilityCheckList/modals/CheckModal.tsx +++ b/builder-frontend/src/components/homeScreen/eligibilityCheckList/modals/CheckModal.tsx @@ -1,18 +1,24 @@ -import { createStore } from "solid-js/store" +import { createStore } from "solid-js/store"; import type { EligibilityCheck } from "@/types"; - type CheckValues = { name: string; module: string; description: string; -} -const EditCheckModal = ( - { modalAction, closeModal }: - { modalAction: (check: EligibilityCheck) => Promise; closeModal: () => void } -) => { - const [newCheck, setNewCheck] = createStore({ name: "", module: "", description: "" }); +}; +const EditCheckModal = ({ + modalAction, + closeModal, +}: { + modalAction: (check: EligibilityCheck) => Promise; + closeModal: () => void; +}) => { + const [newCheck, setNewCheck] = createStore({ + name: "", + module: "", + description: "", + }); // Styling for the Add button based on whether fields are filled const isAddDisabled = () => { @@ -21,10 +27,12 @@ const EditCheckModal = ( newCheck.description.trim() === "" || newCheck.module.trim() === "" ); - } + }; const addButtonClasses = () => { - return isAddDisabled() ? "opacity-50 cursor-not-allowed" : "hover:bg-sky-700"; - } + return isAddDisabled() + ? "opacity-50 cursor-not-allowed" + : "hover:bg-sky-700"; + }; return (
@@ -63,7 +71,9 @@ const EditCheckModal = (
{ closeModal(); }} + onClick={() => { + closeModal(); + }} > Cancel
@@ -75,12 +85,17 @@ const EditCheckModal = ( return; } const check: EligibilityCheck = { - id: newCheck.module.toLowerCase() + "-" + newCheck.name.toLowerCase().replace(/\s+/g, "_"), + id: + newCheck.module.toLowerCase() + + "-" + + newCheck.name.toLowerCase().replace(/\s+/g, "_"), name: newCheck.name, + version: "1.0.0", + module: newCheck.module, description: newCheck.description, - inputs: [], - parameters: [], + inputDefinition: {}, + parameterDefinitions: [], }; await modalAction(check); closeModal(); @@ -92,5 +107,5 @@ const EditCheckModal = (
); -} +}; export default EditCheckModal; diff --git a/builder-frontend/src/components/project/manageBenefits/configureBenefit/ConfigureBenefit.tsx b/builder-frontend/src/components/project/manageBenefits/configureBenefit/ConfigureBenefit.tsx index bc5e942d..b3cc645c 100644 --- a/builder-frontend/src/components/project/manageBenefits/configureBenefit/ConfigureBenefit.tsx +++ b/builder-frontend/src/components/project/manageBenefits/configureBenefit/ConfigureBenefit.tsx @@ -19,26 +19,16 @@ const ConfigureBenefit = ({ benefitId: Accessor; setBenefitId: (benefitId: string | null) => void; }) => { - const { benefit, actions, actionInProgress, initialLoadStatus } = BenefitResource( - screenerId, - benefitId - ); + const { benefit, actions, actionInProgress, initialLoadStatus } = + BenefitResource(screenerId, benefitId); const [checkListMode, setCheckListMode] = createSignal("public"); const [publicChecks] = createResource(fetchPublicChecks); - const [userDefinedChecks] = createResource( - () => fetchUserDefinedChecks(false) + const [userDefinedChecks] = createResource(() => + fetchUserDefinedChecks(false) ); - const getSelectedCheck = (checkId: string) => { - const allChecks = [ - ...(publicChecks() || []), - ...(userDefinedChecks() || []), - ]; - return allChecks.find((check) => check.id === checkId); - }; - const onRemoveEligibilityCheck = (checkIndexToRemove: number) => { actions.removeCheck(checkIndexToRemove); }; @@ -102,11 +92,14 @@ const ConfigureBenefit = ({ onRemove={() => onRemoveEligibilityCheck(checkIndex()) } - updateCheckConfigParams={ - (newCheckData: ParameterValues) => { - actions.updateCheckConfigParams(checkIndex(), newCheckData); - } - } + updateCheckConfigParams={( + newCheckData: ParameterValues + ) => { + actions.updateCheckConfigParams( + checkIndex(), + newCheckData + ); + }} /> ); }} diff --git a/builder-frontend/src/components/project/manageBenefits/configureBenefit/EligibilityCheckListView.tsx b/builder-frontend/src/components/project/manageBenefits/configureBenefit/EligibilityCheckListView.tsx index 693e1f9b..f1e6c959 100644 --- a/builder-frontend/src/components/project/manageBenefits/configureBenefit/EligibilityCheckListView.tsx +++ b/builder-frontend/src/components/project/manageBenefits/configureBenefit/EligibilityCheckListView.tsx @@ -56,7 +56,13 @@ const EligibilityCheckListView = ({ const checkConfig: CheckConfig = { checkId: check.id, checkName: check.name, + checkVersion: check.version, + checkModule: check.module, + checkDescription: check.description, + evaluationUrl: check.evaluationUrl, parameters: {}, + parameterDefinitions: check.parameterDefinitions, + inputDefinition: check.inputDefinition, }; addCheck(checkConfig); }; @@ -146,7 +152,7 @@ const EligibilityCheckRow = ({ {check.description} - v{check.version} + {check.version} ); }; diff --git a/builder-frontend/src/components/project/manageBenefits/configureBenefit/SelectedEligibilityCheck.tsx b/builder-frontend/src/components/project/manageBenefits/configureBenefit/SelectedEligibilityCheck.tsx index b07967bb..7fa68da9 100644 --- a/builder-frontend/src/components/project/manageBenefits/configureBenefit/SelectedEligibilityCheck.tsx +++ b/builder-frontend/src/components/project/manageBenefits/configureBenefit/SelectedEligibilityCheck.tsx @@ -1,8 +1,7 @@ -import { Accessor, createResource, createSignal, For, Show } from "solid-js"; +import { Accessor, createSignal, For, Show } from "solid-js"; import ConfigureCheckModal from "./modals/ConfigureCheckModal"; -import { fetchCheck } from "@/api/check"; import { titleCase } from "@/utils/title_case"; import type { @@ -10,7 +9,6 @@ import type { ParameterDefinition, ParameterValues, } from "@/types"; -import Loading from "@/components/Loading"; interface ParameterWithConfiguredValue { parameter: ParameterDefinition; @@ -28,69 +26,51 @@ const SelectedEligibilityCheck = ({ updateCheckConfigParams: (newCheckData: ParameterValues) => void; onRemove: () => void | null; }) => { - const [check] = createResource(() => checkId(), fetchCheck); const [configuringCheckModalOpen, setConfiguringCheckModalOpen] = createSignal(false); - const checkParameters: Accessor = () => - check().parameters.map((param) => { - return { parameter: param, value: checkConfig().parameters[param.key]! }; - }); - const unfilledRequiredParameters = () => { return []; }; return ( <> - - - - - -
{ - setConfiguringCheckModalOpen(true); - }} - class=" +
{ + setConfiguringCheckModalOpen(true); + }} + class=" mb-4 p-4 cursor-pointer select-none relative border-2 border-gray-200 rounded-lg hover:bg-gray-200" - > - -
{ - e.stopPropagation(); - onRemove(); - }} - > - X -
-
-
- {titleCase(check().name)} - v{check().version} + > + +
{ + e.stopPropagation(); + onRemove(); + }} + > + X
-
{check().description}
- - {check().inputs && check().inputs.length > 0 && ( -
-
Inputs
- - {(input) => ( -
-
{titleCase(input.key)}:
-
"{input.prompt}"
-
- )} -
-
- )} - {checkParameters().length > 0 && ( +
+
+ {titleCase(checkConfig().checkName)} - {checkConfig().checkVersion} +
+
+ {checkConfig().checkDescription} +
+ { + // Place to display information about expected inputs for check + } + {checkConfig().parameterDefinitions && + checkConfig().parameterDefinitions.length > 0 && (
Parameters
- - {({ parameter, value }: ParameterWithConfiguredValue) => { + + {(parameter: ParameterDefinition) => { const getLabel = () => { + let value = checkConfig().parameters[parameter.key]; return value !== undefined ? ( value.toString() ) : ( @@ -107,25 +87,23 @@ const SelectedEligibilityCheck = ({
)} - {unfilledRequiredParameters().length > 0 && ( -
- Warning: This check has required parameter(s) that are not - configured. Click here to edit. -
- )} -
- - {configuringCheckModalOpen() && ( - { - setConfiguringCheckModalOpen(false); - }} - /> + {unfilledRequiredParameters().length > 0 && ( +
+ Warning: This check has required parameter(s) that are not + configured. Click here to edit. +
)} - +
+ + {configuringCheckModalOpen() && ( + { + setConfiguringCheckModalOpen(false); + }} + /> + )} ); }; diff --git a/builder-frontend/src/components/project/manageBenefits/configureBenefit/benefitResource.ts b/builder-frontend/src/components/project/manageBenefits/configureBenefit/benefitResource.ts index f22b129f..09bed222 100644 --- a/builder-frontend/src/components/project/manageBenefits/configureBenefit/benefitResource.ts +++ b/builder-frontend/src/components/project/manageBenefits/configureBenefit/benefitResource.ts @@ -5,13 +5,15 @@ import { fetchScreenerBenefit, updateScreenerBenefit } from "@/api/benefit"; import type { Benefit, CheckConfig, ParameterValues } from "@/types"; - interface ScreenerBenefitsResource { benefit: Accessor; actions: { addCheck: (newCheck: CheckConfig) => void; removeCheck: (indexToRemove: number) => void; - updateCheckConfigParams: (indexToUpdate: number, parameters: ParameterValues) => void; + updateCheckConfigParams: ( + indexToUpdate: number, + parameters: ParameterValues + ) => void; }; actionInProgress: Accessor; initialLoadStatus: { @@ -20,7 +22,10 @@ interface ScreenerBenefitsResource { }; } -const createScreenerBenefits = (screenerId: Accessor, benefitId: Accessor): ScreenerBenefitsResource => { +const createScreenerBenefits = ( + screenerId: Accessor, + benefitId: Accessor +): ScreenerBenefitsResource => { const [benefitResource, { refetch }] = createResource( () => [screenerId(), benefitId()], ([sId, bId]) => fetchScreenerBenefit(sId, bId) @@ -30,7 +35,7 @@ const createScreenerBenefits = (screenerId: Accessor, benefitId: Accesso const [benefit, setBenefit] = createStore(null); const [actionInProgress, setActionInProgress] = createSignal(false); - + // When resource resolves, sync it into the store createEffect(() => { if (benefitResource()) { @@ -50,47 +55,48 @@ const createScreenerBenefits = (screenerId: Accessor, benefitId: Accesso console.error("Failed to update Benefit", e); } setActionInProgress(false); - }; // Actions const addCheck = (newCheck: CheckConfig) => { if (!benefit) return; - - const updatedChecks: CheckConfig[] = [...benefit.checks, newCheck] + const updatedChecks: CheckConfig[] = [...benefit.checks, newCheck]; const updatedBenefit: Benefit = { ...benefit, checks: updatedChecks }; updateBenefit(updatedBenefit); - } + }; const removeCheck = (indexToRemove: number) => { if (!benefit) return; - const updatedChecks: CheckConfig[] = ( - benefit.checks.filter((_, checkIndex) => checkIndex !== indexToRemove) + const updatedChecks: CheckConfig[] = benefit.checks.filter( + (_, checkIndex) => checkIndex !== indexToRemove ); const updatedBenefit: Benefit = { ...benefit, checks: updatedChecks }; updateBenefit(updatedBenefit); - } - const updateCheckConfigParams = (indexToUpdate: number, parameters: ParameterValues) => { + }; + const updateCheckConfigParams = ( + indexToUpdate: number, + parameters: ParameterValues + ) => { if (!benefit) return; const updatedCheckConfigs: CheckConfig[] = benefit.checks.map( (check, checkIndex) => { if (checkIndex === indexToUpdate) { - return { ...check, parameters: parameters}; + return { ...check, parameters: parameters }; } return check; } ); const updatedBenefit: Benefit = { ...benefit, checks: updatedCheckConfigs }; updateBenefit(updatedBenefit); - } + }; return { benefit: () => benefit, actions: { addCheck, removeCheck, - updateCheckConfigParams + updateCheckConfigParams, }, actionInProgress, initialLoadStatus: { diff --git a/builder-frontend/src/components/project/manageBenefits/configureBenefit/modals/ConfigureCheckModal.tsx b/builder-frontend/src/components/project/manageBenefits/configureBenefit/modals/ConfigureCheckModal.tsx index b18ae669..a1cd5c50 100644 --- a/builder-frontend/src/components/project/manageBenefits/configureBenefit/modals/ConfigureCheckModal.tsx +++ b/builder-frontend/src/components/project/manageBenefits/configureBenefit/modals/ConfigureCheckModal.tsx @@ -13,19 +13,24 @@ import type { StringParameter, } from "@/types"; - -const ConfigureCheckModal = ( - { checkConfig, check, updateCheckConfigParams, closeModal }: - { - checkConfig: Accessor; - check: Accessor; - updateCheckConfigParams: (newCheckData: ParameterValues) => void; - closeModal: () => void - } -) => { +const ConfigureCheckModal = ({ + checkConfig, + updateCheckConfigParams, + closeModal, +}: { + checkConfig: Accessor; + updateCheckConfigParams: (newCheckData: ParameterValues) => void; + closeModal: () => void; +}) => { const [tempCheck, setTempCheck] = createStore({ checkId: checkConfig().checkId, checkName: checkConfig().checkName, + checkVersion: checkConfig().checkVersion, + checkModule: checkConfig().checkModule, + checkDescription: checkConfig().checkDescription, + evaluationUrl: checkConfig().evaluationUrl, + parameterDefinitions: checkConfig().parameterDefinitions, + inputDefinition: checkConfig().inputDefinition, parameters: { ...checkConfig().parameters }, }); @@ -41,14 +46,14 @@ const ConfigureCheckModal = ( Configure Check: {titleCase(checkConfig().checkName)}
- {check().parameters.length === 0 && ( + {checkConfig().parameterDefinitions.length === 0 && (
This check has no configurable parameters.
)} - {check().parameters.length > 0 && ( + {checkConfig().parameterDefinitions.length > 0 && (
Parameters
- + {(parameter) => { return (