Skip to content

Commit

Permalink
Improved support and flow for getting rules added to the rules reposi…
Browse files Browse the repository at this point in the history
…tory also in the db
  • Loading branch information
timwekkenbc committed Jun 11, 2024
1 parent e7e0eab commit 8aba5f1
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 59 deletions.
31 changes: 21 additions & 10 deletions app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Link from "next/link";
import { Table, Input, Button, Flex } from "antd";
import { ColumnsType } from "antd/es/table";
import { RuleInfo } from "../types/ruleInfo";
import { getAllRuleData, postRuleData, updateRuleData, deleteRuleData } from "../utils/api";
import { getAllRuleData, getAllRuleDocuments, postRuleData, updateRuleData, deleteRuleData } from "../utils/api";

enum ACTION_STATUS {
NEW = "new",
Expand All @@ -18,9 +18,18 @@ export default function Admin() {
const [rules, setRules] = useState<RuleInfo[]>([]);

const getOrRefreshRuleList = async () => {
const data = await getAllRuleData();
setInitialRules(data);
setRules(JSON.parse(JSON.stringify(data))); // JSON.parse(JSON.stringify(data)) is a hacky way to deep copy the data - needed for comparison later
// Get rules that are already defined in the DB
const existingRules = await getAllRuleData();
setInitialRules(existingRules);
// Get rules that exist in the rules repository, but aren't yet defined in the DB
const existingRuleDocuments = await getAllRuleDocuments();
const undefinedRules = existingRuleDocuments
.filter((ruleJSON: string) => {
return !existingRules.find((rule: RuleInfo) => rule.goRulesJSONFilename === ruleJSON);
})
.map((ruleJSON: string) => ({ goRulesJSONFilename: ruleJSON }));
const ruleData = [...existingRules, ...undefinedRules];
setRules(JSON.parse(JSON.stringify(ruleData))); // JSON.parse(JSON.stringify(data)) is a hacky way to deep copy the data - needed for comparison later
setIsLoading(false);
};

Expand Down Expand Up @@ -82,19 +91,19 @@ export default function Admin() {
const entriesToUpdate = getRulesToUpdate();
await Promise.all(
entriesToUpdate.map(async ({ rule, action }) => {
if (rule?._id) {
try {
if (action === ACTION_STATUS.NEW) {
await postRuleData(rule);
} else if (action === ACTION_STATUS.UPDATE) {
await updateRuleData(rule._id, rule);
} else if (action === ACTION_STATUS.DELETE) {
await deleteRuleData(rule._id);
} else if (rule?._id) {
if (action === ACTION_STATUS.UPDATE) {
await updateRuleData(rule._id, rule);
} else if (action === ACTION_STATUS.DELETE) {
await deleteRuleData(rule._id);
}
}
} catch (error) {
console.error(`Error performing action ${action} on rule ${rule._id}: ${error}`);
}
}
})
);
getOrRefreshRuleList();
Expand All @@ -113,6 +122,7 @@ export default function Admin() {
title: "Title",
dataIndex: "title",
render: renderInputField("title"),
width: "220px"
},
{
title: "GoRules Id",
Expand All @@ -123,6 +133,7 @@ export default function Admin() {
title: "GoRules JSON Filename",
dataIndex: "goRulesJSONFilename",
render: renderInputField("goRulesJSONFilename"),
width: "260px"
},
{
title: "CHEFS Form Id",
Expand Down
1 change: 0 additions & 1 deletion app/components/RulesDecisionGraph/RulesDecisionGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import styles from "./RulesDecisionGraph.module.css";

interface RulesViewerProps {
jsonFile: string;
docId: string;
contextToSimulate?: SubmissionData | null;
setResultsOfSimulation: (results: Record<string, any>) => void;
}
Expand Down
4 changes: 1 addition & 3 deletions app/components/SimulationViewer/SimulationViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ const RulesDecisionGraph = dynamic(() => import("../RulesDecisionGraph"), { ssr:

interface SimulationViewerProps {
jsonFile: string;
docId: string;
chefsFormId: string;
}

export default function SimulationViewer({ jsonFile, docId, chefsFormId }: SimulationViewerProps) {
export default function SimulationViewer({ jsonFile, chefsFormId }: SimulationViewerProps) {
const [selectedSubmissionInputs, setSelectedSubmissionInputs] = useState<SubmissionData>();
const [contextToSimulate, setContextToSimulate] = useState<SubmissionData | null>();
const [resultsOfSimulation, setResultsOfSimulation] = useState<Record<string, any> | null>();
Expand All @@ -43,7 +42,6 @@ export default function SimulationViewer({ jsonFile, docId, chefsFormId }: Simul
<div className={styles.rulesWrapper}>
<RulesDecisionGraph
jsonFile={jsonFile}
docId={docId}
contextToSimulate={contextToSimulate}
setResultsOfSimulation={setResultsOfSimulation}
/>
Expand Down
2 changes: 1 addition & 1 deletion app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default function Home() {
key: _id,
titleLink: (
<b>
<Link href={`/rule/${_id}`}>{title}</Link>
<Link href={`/rule/${_id}`}>{title || goRulesJSONFilename}</Link>
</b>
),
downloadRule: (
Expand Down
2 changes: 1 addition & 1 deletion app/rule/[ruleId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default async function Rule({ params: { ruleId } }: { params: { ruleId: s
<Link href="/">
<HomeOutlined />
</Link>
<h1>{title}</h1>
<h1>{title || goRulesJSONFilename}</h1>
</Flex>
<SimulationViewer jsonFile={goRulesJSONFilename} chefsFormId={chefsFormId} />
</>
Expand Down
101 changes: 58 additions & 43 deletions app/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,66 @@ const axiosAPIInstance = axios.create({
});

/**
* Retrieves a document from the API based on the provided document ID.
* @param docId The ID of the document to retrieve.
* @returns The content of the document.
* @throws If an error occurs while retrieving the document.
* Retrieves a rule data from the API based on the provided rule ID.
* @param ruleId The ID of the rule data to retrieve.
* @returns The rule data.
* @throws If an error occurs while retrieving the rule data.
*/
export const getDocument = async (jsonFile: string): Promise<DecisionGraphType> => {
export const getRuleDataById = async (ruleId: string): Promise<RuleInfo> => {
try {
const { data } = await axiosAPIInstance.get(`/documents/${jsonFile}`);
if (!data || !data.nodes || !data.edges) {
throw new Error("Unexpected format of the returned data");
}
const { data } = await axiosAPIInstance.get(`/ruleData/${ruleId}`);
return data;
} catch (error) {
console.error(`Error getting the gorules document: ${error}`);
console.error(`Error getting rule data: ${error}`);
throw error;
}
};

/**
* Posts a decision to the API for evaluation.
* @param jsonFile The JSON file to use for the decision.
* @param decisionGraph The decision graph to evaluate.
* @param context The context for the decision evaluation.
* @returns The result of the decision evaluation.
* @throws If an error occurs while simulating the decision.
* Retrieves all rules data from the API.
* @returns The rule data list.
* @throws If an error occurs while fetching the rule data.
*/
export const postDecision = async (jsonFile: string, context: unknown) => {
export const getAllRuleData = async (): Promise<RuleInfo[]> => {
try {
const { data } = await axiosAPIInstance.post(`/decisions/evaluate/${jsonFile}`, {
context,
trace: true,
});
const { data } = await axiosAPIInstance.get("/ruleData/list");
return data;
} catch (error) {
console.error(`Error simulating decision: ${error}`);
console.error(`Error fetching rule data: ${error}`);
throw error;
}
};

/**
* Retrieves submissions from the CHEFS API.
* @returns The submissions data.
* @throws If an error occurs while fetching the submissions.
* Gets list of all rule documents
* @returns The rule documents list.
* @throws If an error occurs while fetching the rule documents list.
*/
export const getSubmissionsFromCHEFS = async (formId: string) => {
export const getAllRuleDocuments = async (): Promise<string[]> => {
try {
const { data } = await axiosAPIInstance.get(`/submissions/list/${formId}`);
const { data } = await axiosAPIInstance.get("/documents");
return data;
} catch (error) {
console.error(`Error fetching submissions: ${error}`);
console.error(`Error fetching rule data: ${error}`);
throw error;
}
};

/**
* Retrieves a document from the API based on the provided document ID.
* @param docId The ID of the document to retrieve.
* @returns The content of the document.
* @throws If an error occurs while retrieving the document.
*/
export const getDocument = async (jsonFilePath: string): Promise<DecisionGraphType> => {
try {
const { data } = await axiosAPIInstance.get(`/documents/${encodeURIComponent(jsonFilePath)}`);
if (!data || !data.nodes || !data.edges) {
throw new Error("Unexpected format of the returned data");
}
return data;
} catch (error) {
console.error(`Error getting the gorules document: ${error}`);
throw error;
}
};
Expand All @@ -70,9 +80,9 @@ export const getSubmissionsFromCHEFS = async (formId: string) => {
* @returns The submissions data.
* @throws If an error occurs while fetching the submissions.
*/
export const getSubmissionFromCHEFSById = async (formId: string, id: string) => {
export const getSubmissionsFromCHEFS = async (formId: string) => {
try {
const { data } = await axiosAPIInstance.get(`/submissions/${formId}/${id}`);
const { data } = await axiosAPIInstance.get(`/submissions/list/${formId}`);
return data;
} catch (error) {
console.error(`Error fetching submissions: ${error}`);
Expand All @@ -81,32 +91,37 @@ export const getSubmissionFromCHEFSById = async (formId: string, id: string) =>
};

/**
* Retrieves a rule data from the API based on the provided rule ID.
* @param ruleId The ID of the rule data to retrieve.
* @returns The rule data.
* @throws If an error occurs while retrieving the rule data.
* Retrieves submissions from the CHEFS API.
* @returns The submissions data.
* @throws If an error occurs while fetching the submissions.
*/
export const getRuleDataById = async (ruleId: string): Promise<RuleInfo> => {
export const getSubmissionFromCHEFSById = async (formId: string, id: string) => {
try {
const { data } = await axiosAPIInstance.get(`/ruleData/${ruleId}`);
const { data } = await axiosAPIInstance.get(`/submissions/${formId}/${id}`);
return data;
} catch (error) {
console.error(`Error getting rule data: ${error}`);
console.error(`Error fetching submissions: ${error}`);
throw error;
}
};

/**
* Retrieves all rules data from the API.
* @returns The rule data list.
* @throws If an error occurs while fetching the rule data.
* Posts a decision to the API for evaluation.
* @param jsonFile The JSON file to use for the decision.
* @param decisionGraph The decision graph to evaluate.
* @param context The context for the decision evaluation.
* @returns The result of the decision evaluation.
* @throws If an error occurs while simulating the decision.
*/
export const getAllRuleData = async (): Promise<RuleInfo[]> => {
export const postDecision = async (jsonFile: string, context: unknown) => {
try {
const { data } = await axiosAPIInstance.get(`/ruleData/list`);
const { data } = await axiosAPIInstance.post(`/decisions/evaluate/${jsonFile}`, {
context,
trace: true,
});
return data;
} catch (error) {
console.error(`Error fetching rule data: ${error}`);
console.error(`Error simulating decision: ${error}`);
throw error;
}
};
Expand Down

0 comments on commit 8aba5f1

Please sign in to comment.