From e7e0eab16e75ab3aa111a813ef0866131dc5d451 Mon Sep 17 00:00:00 2001 From: timwekkenbc Date: Mon, 10 Jun 2024 13:34:59 -0700 Subject: [PATCH 1/7] Updated to use our own backend for getting/evaluating goRules, Updated editing of a rule to be downloading the json instead --- .github/workflows/build-and-deploy.yml | 3 -- Dockerfile | 6 --- .../RulesDecisionGraph/RulesDecisionGraph.tsx | 10 ++--- app/page.tsx | 12 +++--- app/rule/[ruleId]/embedded/page.tsx | 2 +- app/rule/[ruleId]/page.tsx | 2 +- app/utils/api.ts | 42 ++++++++----------- 7 files changed, 31 insertions(+), 46 deletions(-) diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 5bb3a0a..54f5fa2 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -40,9 +40,6 @@ jobs: labels: ${{ steps.meta.outputs.labels }} build-args: | "NEXT_PUBLIC_API_URL=${{ github.ref == 'refs/heads/main' && secrets.NEXT_PUBLIC_API_URL_PROD || secrets.NEXT_PUBLIC_API_URL_DEV }}" - "NEXT_PUBLIC_GO_RULES_PROJECT_ID=${{ secrets.NEXT_PUBLIC_GO_RULES_PROJECT_ID }}" - "NEXT_PUBLIC_GO_RULES_BEARER_PAT=${{ secrets.NEXT_PUBLIC_GO_RULES_BEARER_PAT }}" - "NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN=${{ secrets.NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN }}" outputs: image_tag: ${{ steps.meta.outputs.tags }} diff --git a/Dockerfile b/Dockerfile index 7152704..0191ec2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,12 +4,6 @@ FROM registry.access.redhat.com/ubi9/nodejs-20:latest # Set the environment variables ARG NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} -ARG NEXT_PUBLIC_GO_RULES_PROJECT_ID -ENV NEXT_PUBLIC_GO_RULES_PROJECT_ID=${NEXT_PUBLIC_GO_RULES_PROJECT_ID} -ARG NEXT_PUBLIC_GO_RULES_BEARER_PAT -ENV NEXT_PUBLIC_GO_RULES_BEARER_PAT=${NEXT_PUBLIC_GO_RULES_BEARER_PAT} -ARG NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN -ENV NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN=${NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN} # Set the working directory WORKDIR /opt/app-root/src diff --git a/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx b/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx index b75d1ca..477a750 100644 --- a/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx +++ b/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx @@ -18,24 +18,24 @@ interface RulesViewerProps { export default function RulesDecisionGraph({ jsonFile, - docId, contextToSimulate, setResultsOfSimulation, }: RulesViewerProps) { const decisionGraphRef: any = useRef(); const [graphJSON, setGraphJSON] = useState(); + useEffect(() => { const fetchData = async () => { try { - const data = await getDocument(docId); + const data = await getDocument(jsonFile); setGraphJSON(data); } catch (error) { console.error("Error fetching JSON:", error); } }; fetchData(); - }, [docId]); + }, [jsonFile]); // Can set additional react flow options here if we need to change how graph looks when it's loaded in const reactFlowInit = (reactFlow: ReactFlowInstance) => { @@ -47,10 +47,10 @@ export default function RulesDecisionGraph({ decisionGraphRef?.current?.runSimulator(contextToSimulate); }, [contextToSimulate]); - const simulateRun = async ({ decisionGraph, context }: { decisionGraph: DecisionGraphType; context: unknown }) => { + const simulateRun = async ({ context }: { context: unknown }) => { if (contextToSimulate) { console.info("Simulate:", context); - const data = await postDecision(jsonFile, decisionGraph, context); + const data = await postDecision(jsonFile, context); console.info("Simulation Results:", data, data?.result); setResultsOfSimulation(data?.result); return { result: data }; diff --git a/app/page.tsx b/app/page.tsx index 7a58144..0d60245 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -22,7 +22,7 @@ export default function Home() { getRules(); }, []); - const mappedRules = rules.map(({ _id, title, chefsFormId }) => { + const mappedRules = rules.map(({ _id, title, goRulesJSONFilename, chefsFormId }) => { return { key: _id, titleLink: ( @@ -30,9 +30,9 @@ export default function Home() { {title} ), - editRule: ( - - Edit + downloadRule: ( + + Download JSON ), submissionFormLink: Submission, @@ -45,8 +45,8 @@ export default function Home() { dataIndex: "titleLink", }, { - title: "Edit Rule", - dataIndex: "editRule", + title: "Download Rule", + dataIndex: "downloadRule", }, { title: "Submission Form", diff --git a/app/rule/[ruleId]/embedded/page.tsx b/app/rule/[ruleId]/embedded/page.tsx index cda1cb7..3cfcea5 100644 --- a/app/rule/[ruleId]/embedded/page.tsx +++ b/app/rule/[ruleId]/embedded/page.tsx @@ -8,5 +8,5 @@ export default async function RuleEmbedded({ params: { ruleId } }: { params: { r return

Rule not found

; } - return ; + return ; } diff --git a/app/rule/[ruleId]/page.tsx b/app/rule/[ruleId]/page.tsx index 3738c53..c9abdd2 100644 --- a/app/rule/[ruleId]/page.tsx +++ b/app/rule/[ruleId]/page.tsx @@ -19,7 +19,7 @@ export default async function Rule({ params: { ruleId } }: { params: { ruleId: s

{title}

- + ); } diff --git a/app/utils/api.ts b/app/utils/api.ts index 8acdd3d..aa07867 100644 --- a/app/utils/api.ts +++ b/app/utils/api.ts @@ -2,32 +2,27 @@ import { DecisionGraphType } from "@gorules/jdm-editor/dist/components/decision- import axios from "axios"; import { RuleInfo } from "../types/ruleInfo"; -// For server side calls, need full URL, otherwise can just use /api -const API_URI = typeof window === "undefined" ? process.env.NEXT_PUBLIC_API_URL : "/api"; - -const GO_RULES_ROOT_PROJECT_URL = `https://sdpr.gorules.io/api/projects/${process.env.NEXT_PUBLIC_GO_RULES_PROJECT_ID}`; - -const goRulesAxiosInstance = axios.create({ +const axiosAPIInstance = axios.create({ + // For server side calls, need full URL, otherwise can just use /api + baseURL: typeof window === "undefined" ? process.env.NEXT_PUBLIC_API_URL : "/api", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${process.env.NEXT_PUBLIC_GO_RULES_BEARER_PAT}`, - "x-access-token": process.env.NEXT_PUBLIC_GO_RULES_ACCESS_TOKEN, }, }); /** - * Retrieves a document from the GoRules API based on the provided document ID. + * 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 (docId: string): Promise => { +export const getDocument = async (jsonFile: string): Promise => { try { - const { data } = await goRulesAxiosInstance.get(`${GO_RULES_ROOT_PROJECT_URL}/documents/${docId}`); - if (!data.versions || !data.versions[0] || !data.versions[0].content) { + const { data } = await axiosAPIInstance.get(`/documents/${jsonFile}`); + if (!data || !data.nodes || !data.edges) { throw new Error("Unexpected format of the returned data"); } - return data.versions[0].content; + return data; } catch (error) { console.error(`Error getting the gorules document: ${error}`); throw error; @@ -35,19 +30,18 @@ export const getDocument = async (docId: string): Promise => }; /** - * Posts a decision to the GoRules API for evaluation. + * 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 postDecision = async (jsonFile: string, decisionGraph: DecisionGraphType, context: unknown) => { +export const postDecision = async (jsonFile: string, context: unknown) => { try { - const { data } = await goRulesAxiosInstance.post(`${GO_RULES_ROOT_PROJECT_URL}/evaluate/${jsonFile}`, { + const { data } = await axiosAPIInstance.post(`/decisions/evaluate/${jsonFile}`, { context, trace: true, - content: decisionGraph, }); return data; } catch (error) { @@ -63,7 +57,7 @@ export const postDecision = async (jsonFile: string, decisionGraph: DecisionGrap */ export const getSubmissionsFromCHEFS = async (formId: string) => { try { - const { data } = await axios.get(`${API_URI}/submissions/list/${formId}`); + const { data } = await axiosAPIInstance.get(`/submissions/list/${formId}`); return data; } catch (error) { console.error(`Error fetching submissions: ${error}`); @@ -78,7 +72,7 @@ export const getSubmissionsFromCHEFS = async (formId: string) => { */ export const getSubmissionFromCHEFSById = async (formId: string, id: string) => { try { - const { data } = await axios.get(`${API_URI}/submissions/${formId}/${id}`); + const { data } = await axiosAPIInstance.get(`/submissions/${formId}/${id}`); return data; } catch (error) { console.error(`Error fetching submissions: ${error}`); @@ -94,7 +88,7 @@ export const getSubmissionFromCHEFSById = async (formId: string, id: string) => */ export const getRuleDataById = async (ruleId: string): Promise => { try { - const { data } = await axios.get(`${API_URI}/ruleData/${ruleId}`); + const { data } = await axiosAPIInstance.get(`/ruleData/${ruleId}`); return data; } catch (error) { console.error(`Error getting rule data: ${error}`); @@ -109,7 +103,7 @@ export const getRuleDataById = async (ruleId: string): Promise => { */ export const getAllRuleData = async (): Promise => { try { - const { data } = await axios.get(`${API_URI}/ruleData/list`); + const { data } = await axiosAPIInstance.get(`/ruleData/list`); return data; } catch (error) { console.error(`Error fetching rule data: ${error}`); @@ -125,7 +119,7 @@ export const getAllRuleData = async (): Promise => { */ export const postRuleData = async (newRuleData: unknown) => { try { - const { data } = await axios.post(`${API_URI}/ruleData`, newRuleData); + const { data } = await axiosAPIInstance.post(`/ruleData`, newRuleData); return data; } catch (error) { console.error(`Error posting rule data: ${error}`); @@ -142,7 +136,7 @@ export const postRuleData = async (newRuleData: unknown) => { */ export const updateRuleData = async (ruleId: string, updatedRuleData: unknown) => { try { - const { data } = await axios.put(`${API_URI}/ruleData/${ruleId}`, updatedRuleData); + const { data } = await axiosAPIInstance.put(`/ruleData/${ruleId}`, updatedRuleData); return data; } catch (error) { console.error(`Error updating rule: ${error}`); @@ -158,7 +152,7 @@ export const updateRuleData = async (ruleId: string, updatedRuleData: unknown) = */ export const deleteRuleData = async (ruleId: string) => { try { - const { data } = await axios.delete(`${API_URI}/ruleData/${ruleId}`); + const { data } = await axiosAPIInstance.delete(`/ruleData/${ruleId}`); return data; } catch (error) { console.error(`Error deleting rule: ${error}`); From 8aba5f16b0d80e4f127a38421a7a36b1d0ff894f Mon Sep 17 00:00:00 2001 From: timwekkenbc Date: Tue, 11 Jun 2024 11:48:36 -0700 Subject: [PATCH 2/7] Improved support and flow for getting rules added to the rules repository also in the db --- app/admin/page.tsx | 31 ++++-- .../RulesDecisionGraph/RulesDecisionGraph.tsx | 1 - .../SimulationViewer/SimulationViewer.tsx | 4 +- app/page.tsx | 2 +- app/rule/[ruleId]/page.tsx | 2 +- app/utils/api.ts | 101 ++++++++++-------- 6 files changed, 82 insertions(+), 59 deletions(-) diff --git a/app/admin/page.tsx b/app/admin/page.tsx index db2371e..e5c7732 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -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", @@ -18,9 +18,18 @@ export default function Admin() { const [rules, setRules] = useState([]); 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); }; @@ -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(); @@ -113,6 +122,7 @@ export default function Admin() { title: "Title", dataIndex: "title", render: renderInputField("title"), + width: "220px" }, { title: "GoRules Id", @@ -123,6 +133,7 @@ export default function Admin() { title: "GoRules JSON Filename", dataIndex: "goRulesJSONFilename", render: renderInputField("goRulesJSONFilename"), + width: "260px" }, { title: "CHEFS Form Id", diff --git a/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx b/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx index 477a750..0ea98be 100644 --- a/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx +++ b/app/components/RulesDecisionGraph/RulesDecisionGraph.tsx @@ -11,7 +11,6 @@ import styles from "./RulesDecisionGraph.module.css"; interface RulesViewerProps { jsonFile: string; - docId: string; contextToSimulate?: SubmissionData | null; setResultsOfSimulation: (results: Record) => void; } diff --git a/app/components/SimulationViewer/SimulationViewer.tsx b/app/components/SimulationViewer/SimulationViewer.tsx index 5cfdcbe..0dfeb33 100644 --- a/app/components/SimulationViewer/SimulationViewer.tsx +++ b/app/components/SimulationViewer/SimulationViewer.tsx @@ -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(); const [contextToSimulate, setContextToSimulate] = useState(); const [resultsOfSimulation, setResultsOfSimulation] = useState | null>(); @@ -43,7 +42,6 @@ export default function SimulationViewer({ jsonFile, docId, chefsFormId }: Simul
diff --git a/app/page.tsx b/app/page.tsx index 0d60245..db52f81 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -27,7 +27,7 @@ export default function Home() { key: _id, titleLink: ( - {title} + {title || goRulesJSONFilename} ), downloadRule: ( diff --git a/app/rule/[ruleId]/page.tsx b/app/rule/[ruleId]/page.tsx index c9abdd2..74b1d6b 100644 --- a/app/rule/[ruleId]/page.tsx +++ b/app/rule/[ruleId]/page.tsx @@ -17,7 +17,7 @@ export default async function Rule({ params: { ruleId } }: { params: { ruleId: s -

{title}

+

{title || goRulesJSONFilename}

diff --git a/app/utils/api.ts b/app/utils/api.ts index aa07867..5cda18e 100644 --- a/app/utils/api.ts +++ b/app/utils/api.ts @@ -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 => { +export const getRuleDataById = async (ruleId: string): Promise => { 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 => { 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 => { 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 => { + 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; } }; @@ -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}`); @@ -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 => { +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 => { +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; } }; From d97970458e649eccef74291f0d26cd1209426fbd Mon Sep 17 00:00:00 2001 From: timwekkenbc Date: Mon, 17 Jun 2024 11:01:26 -0700 Subject: [PATCH 3/7] Updated API to match backend document changes --- app/utils/api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/utils/api.ts b/app/utils/api.ts index 5cda18e..45ed512 100644 --- a/app/utils/api.ts +++ b/app/utils/api.ts @@ -48,7 +48,7 @@ export const getAllRuleData = async (): Promise => { */ export const getAllRuleDocuments = async (): Promise => { try { - const { data } = await axiosAPIInstance.get("/documents"); + const { data } = await axiosAPIInstance.get("/documents/all"); return data; } catch (error) { console.error(`Error fetching rule data: ${error}`); @@ -64,7 +64,7 @@ export const getAllRuleDocuments = async (): Promise => { */ export const getDocument = async (jsonFilePath: string): Promise => { try { - const { data } = await axiosAPIInstance.get(`/documents/${encodeURIComponent(jsonFilePath)}`); + const { data } = await axiosAPIInstance.get(`/documents?ruleFileName=${jsonFilePath}`); if (!data || !data.nodes || !data.edges) { throw new Error("Unexpected format of the returned data"); } From 0c2b168254a71ff07c059706494717e9a4b02593 Mon Sep 17 00:00:00 2001 From: timwekkenbc Date: Mon, 17 Jun 2024 16:45:47 -0700 Subject: [PATCH 4/7] Fixed download json link and added home button to admin page --- app/admin/page.tsx | 4 ++++ app/page.tsx | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/admin/page.tsx b/app/admin/page.tsx index e5c7732..8dbaf41 100644 --- a/app/admin/page.tsx +++ b/app/admin/page.tsx @@ -3,6 +3,7 @@ import { useState, useEffect } from "react"; import Link from "next/link"; import { Table, Input, Button, Flex } from "antd"; import { ColumnsType } from "antd/es/table"; +import { HomeOutlined } from "@ant-design/icons"; import { RuleInfo } from "../types/ruleInfo"; import { getAllRuleData, getAllRuleDocuments, postRuleData, updateRuleData, deleteRuleData } from "../utils/api"; @@ -166,6 +167,9 @@ export default function Admin() { return ( <> + + +

Admin

{!isLoading && (