From 9acc0b81af109f9ee0d676046b73e936016eaea4 Mon Sep 17 00:00:00 2001 From: NimeshaKahingala Date: Tue, 25 Nov 2025 14:32:09 -0600 Subject: [PATCH 1/6] supply tree match mock api created --- packages/mock-api/index.js | 32 ++++++++++ packages/mock-api/mock-data.js | 107 +++++++++++++++++++++++++++++++++ packages/mock-api/package.json | 18 ++++++ 3 files changed, 157 insertions(+) create mode 100644 packages/mock-api/index.js create mode 100644 packages/mock-api/mock-data.js create mode 100644 packages/mock-api/package.json diff --git a/packages/mock-api/index.js b/packages/mock-api/index.js new file mode 100644 index 0000000..9b86df8 --- /dev/null +++ b/packages/mock-api/index.js @@ -0,0 +1,32 @@ +import express from "express"; +import morgan from "morgan"; +import { supplyTreeMockResponse } from "./mock-data.js"; + +const app = express(); + +const PORT = 8081; + +// Middleware to parse JSON +app.use(express.json()); + +//middleware for logging +app.use(morgan('tiny')); + +// Basic route +app.get("/", (req, res) => { + res.send("Hello from your first Node.js backend!"); +}); + +app.post("/v1/match", (req, res) => { + console.log("Received data:", req.body); + res.status(200).json({ status: "OK", data: supplyTreeMockResponse }); +}); + +app.get("/health", (req, res) => { + res.status(200).json({ status: "OK", message: "Server is healthy!" }); +}); + +// Start the server +app.listen(PORT, () => { + console.log(`Server is running on http://localhost:${PORT}`); +}); diff --git a/packages/mock-api/mock-data.js b/packages/mock-api/mock-data.js new file mode 100644 index 0000000..0922884 --- /dev/null +++ b/packages/mock-api/mock-data.js @@ -0,0 +1,107 @@ +export const supplyTreeMockResponse = { + "product": { + "id": "Q15026", + "desc": "chair" + }, + "type": "made", + "party": "Devhawk Engineering", + "design": "Funky Chair Design", + "bom": [ + { + "product": { + "id": "QH100", + "desc": "chair leg" + }, + "type": "supplied", + "party": "Robert's Chair Parts" + }, + { + "product": { + "id": "QH108", + "desc": "nails" + }, + "type": "supplied", + "party": "raw supplies" + }, + { + "product": { + "id": "QH102", + "desc": "chair back" + }, + "type": "supplied", + "party": "Robert's Chair Parts" + }, + { + "product": { + "id": "QH100", + "desc": "chair leg" + }, + "type": "made", + "party": "Devhawk Engineering", + "design": "Leg Design", + "bom": [ + { + "product": { + "id": "QH104", + "desc": "wood" + }, + "type": "supplied", + "party": "raw supplies" + } + ] + }, + { + "product": { + "id": "QH101", + "desc": "chair seat" + }, + "type": "made", + "party": "James Maker Space", + "design": "Seat Design 2", + "bom": [ + { + "product": { + "id": "QH107", + "desc": "frame" + }, + "type": "supplied", + "party": "raw supplies" + }, + { + "product": { + "id": "QH106", + "desc": "upholstery" + }, + "type": "supplied", + "party": "raw supplies" + }, + { + "product": { + "id": "QH105", + "desc": "stuffing" + }, + "type": "missing" + } + ] + }, + { + "product": { + "id": "QH101", + "desc": "chair seat" + }, + "type": "made", + "party": "Devhawk Engineering", + "design": "Seat Design 1", + "bom": [ + { + "product": { + "id": "QH103", + "desc": "fabric" + }, + "type": "supplied", + "party": "raw supplies" + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/mock-api/package.json b/packages/mock-api/package.json new file mode 100644 index 0000000..b02fcd8 --- /dev/null +++ b/packages/mock-api/package.json @@ -0,0 +1,18 @@ +{ + "name": "mock-api", + "version": "1.0.0", + "description": "", + "type": "module", + "main": "index.js", + "scripts": { + "dev": "nodemon index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^5.1.0", + "morgan": "^1.10.1" + } +} From 21ab3b72719967a0054d5877d2392f2c22a965b8 Mon Sep 17 00:00:00 2001 From: NimeshaKahingala Date: Tue, 25 Nov 2025 14:32:29 -0600 Subject: [PATCH 2/6] readme file added --- packages/mock-api/README.md | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/mock-api/README.md diff --git a/packages/mock-api/README.md b/packages/mock-api/README.md new file mode 100644 index 0000000..9036378 --- /dev/null +++ b/packages/mock-api/README.md @@ -0,0 +1,68 @@ +# Mock API (project-data-platform-ts) + +Lightweight Express mock API used for local development and for testing integration with the frontend and supply-graph services. + +- Port: 8081 (default) +- Purpose: return deterministic mock supply-tree responses and basic health checks. + +## Quick start + +1. Install dependencies + +```powershell +npm install +``` + +2. Start dev server + +```powershell +npm run dev +``` + +3. Server will be listening on: + +``` +http://localhost:8081 +``` + +(If you want to run without nodemon, use `node index.js`.) + +## Available endpoints + +- GET / + - Basic welcome text. + +- POST /v1/match + - Accepts a JSON body and returns a mock supply-tree response. + - Useful for testing supply-graph AI integration. + +- GET /health + - Returns a simple health JSON: `{ "status": "OK", "message": "Server is healthy!" }`. + +## Example cURL + +POST to the match endpoint: + +```bash +curl -X POST http://localhost:8081/v1/match \ + -H "Content-Type: application/json" \ + -d '{"product": {"id":"Q15026","desc":"chair"}}' +``` + +Response will be the mock supply-tree JSON defined in `mock-data.js`. + +## Files + +- `index.js` — Express server and endpoints. +- `mock-data.js` — Contains the mock response object(s) including `supplyTreeMockResponse`. +- `package.json` — Scripts and dependencies. + +## Notes + +- This mock API is intentionally simple and synchronous to make frontend integration straightforward. +- Replace or extend the mock response in `mock-data.js` to suit tests or demos. +- The repo uses `type: "module"`, so Node should be v14+ (prefer v18+). + +## License + +Project license follows the parent repository. See top-level LICENSE for details. From c7d0650b6d7653f483ab26a45f3c4954b94649ba Mon Sep 17 00:00:00 2001 From: NimeshaKahingala Date: Tue, 13 Jan 2026 01:57:26 -0600 Subject: [PATCH 3/6] icons added --- packages/front-end/public/OKP_icon.png | Bin 0 -> 12813 bytes packages/front-end/public/okh.png | Bin 0 -> 13358 bytes packages/front-end/public/okw_maker.png | Bin 0 -> 19728 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/front-end/public/OKP_icon.png create mode 100644 packages/front-end/public/okh.png create mode 100644 packages/front-end/public/okw_maker.png diff --git a/packages/front-end/public/OKP_icon.png b/packages/front-end/public/OKP_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..59ce796ce77e66a868489bc342fa7db05098acb4 GIT binary patch literal 12813 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 literal 0 HcmV?d00001 diff --git a/packages/front-end/public/okh.png b/packages/front-end/public/okh.png new file mode 100644 index 0000000000000000000000000000000000000000..5dfbc638add96388261426b38d8b927e6dd63dd1 GIT binary patch literal 13358 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 literal 0 HcmV?d00001 diff --git a/packages/front-end/public/okw_maker.png b/packages/front-end/public/okw_maker.png new file mode 100644 index 0000000000000000000000000000000000000000..375b40c7c16e10d0a68a6afb0165a0b1784baf4a GIT binary patch literal 19728 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 literal 0 HcmV?d00001 From 32f13b01c0cd03b0dd9fad75ba7439d83f77c675 Mon Sep 17 00:00:00 2001 From: NimeshaKahingala Date: Tue, 13 Jan 2026 01:59:26 -0600 Subject: [PATCH 4/6] supply tree visualization --- packages/front-end/components/D3Tree.vue | 8 + packages/front-end/nuxt.config.ts | 2 +- .../pages/products/[id]/supplyTree.vue | 150 ++++++------------ packages/front-end/pages/supply-graph-api.vue | 40 ++--- packages/mock-api/index.js | 2 +- packages/mock-api/package.json | 1 + 6 files changed, 80 insertions(+), 123 deletions(-) diff --git a/packages/front-end/components/D3Tree.vue b/packages/front-end/components/D3Tree.vue index 3f12342..c6afb81 100644 --- a/packages/front-end/components/D3Tree.vue +++ b/packages/front-end/components/D3Tree.vue @@ -25,6 +25,14 @@ export default { default: 40, // Default size of the image node }, }, + watch: { + data: { + handler() { + this.drawTree(); + }, + deep: true, // Watch nested properties for changes + }, + }, mounted() { this.drawTree(); }, diff --git a/packages/front-end/nuxt.config.ts b/packages/front-end/nuxt.config.ts index 4dc8303..739f529 100644 --- a/packages/front-end/nuxt.config.ts +++ b/packages/front-end/nuxt.config.ts @@ -14,7 +14,7 @@ export default defineNuxtConfig({ public: { baseUrl: process.env.BACKEND_URL ? process.env.BACKEND_URL : globalBaseUrl, // Supply Graph AI configuration - supplyGraphAiUrl: process.env.SUPPLY_GRAPH_AI_URL || 'http://localhost:8081' + supplyGraphAiUrl: process.env.SUPPLY_GRAPH_AI_URL || 'http://localhost:8001' // apiBase: '/api' } }, diff --git a/packages/front-end/pages/products/[id]/supplyTree.vue b/packages/front-end/pages/products/[id]/supplyTree.vue index d1cf251..c828ca1 100644 --- a/packages/front-end/pages/products/[id]/supplyTree.vue +++ b/packages/front-end/pages/products/[id]/supplyTree.vue @@ -22,9 +22,10 @@ const apiBaseUrl = ref( ); // Updated to use port 8001 as requested const supplyGraphApiUrl = ref( - import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || "http://localhost:8001" + import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || "http://localhost:8000" ); -const supplyGraphApiEndpoint = ref("/v1/match"); // Path to the versioned supply tree creation endpoint +const supplyGraphApiEndpoint = ref("/v1/api/match"); // Path to the versioned supply tree creation endpoint + const sendToSupplyGraphAI = async (o: any) => { if (!o) { @@ -54,37 +55,10 @@ const sendToSupplyGraphAI = async (o: any) => { try { const originalData = okhItem.originalData || okhItem; + console.log("Preparing to send OKH item to Supply Graph AI:", okhItem); + const payload = { - okh_reference: - okhItem.id?.toString() || - originalData.fname || - originalData.id || - "unknown", - required_quantity: 1, - deadline: null, - metadata: { - name: okhItem.name || originalData.name || originalData.title, - shortDescription: - okhItem.shortDescription || - originalData.description || - originalData.summary, - keywords: - okhItem.keywords || originalData.keywords || originalData.tags || [], - maker: - okhItem.maker || - originalData.maker || - originalData.author || - originalData.creator, - whereToFind: - okhItem.whereToFind || - originalData.whereToFind || - originalData.source, - source: "project-data-platform-ts", - image: okhItem.image || originalData.image || originalData.imageUrl, - originalId: originalData.id || originalData.fname, - dataSource: originalData.dataSource || "project-data-platform", - ...originalData, - }, + recipe_id: "8f14e3c4-09f2-4a5e-8bd9-4b5bb5d0a9cd", }; console.log("Enhanced payload for Supply Graph AI (port 8001):", payload); @@ -134,87 +108,57 @@ const sendToSupplyGraphAI = async (o: any) => { // Parse the response from supply graph AI const supplyTreeResponse = await response.json(); - console.log("Supply Graph AI Response:", supplyTreeResponse); - - // Enhanced response processing to handle various response formats - supplyTreeData.value = { - rootItem: selectedOkh.value, - relatedComponents: - supplyTreeResponse.components || - supplyTreeResponse.related_items || - supplyTreeResponse.dependencies || - [], - supplyChainDepth: - supplyTreeResponse.depth || supplyTreeResponse.chain_depth || 1, - analysisTimestamp: - supplyTreeResponse.creation_time || - supplyTreeResponse.timestamp || - new Date().toISOString(), - analysisMethod: "supply-graph-ai-port-8001", - apiResponse: supplyTreeResponse, // Keep full response for debugging - requestPayload: payload, // Keep request for debugging - }; - console.log("Final Supply Tree Data:", supplyTreeData.value); + + console.log("Supply Graph AI Response2:", supplyTreeResponse); + + // Clear previous solutions + const formattedSolutions: any[] = []; + + supplyTreeResponse.data.solutions.forEach((solution: any) => { + + const children = solution.tree.capabilities_used.map((capability: string) => ({ + name: capability, + image: "/OKP_icon.png", + })); + + + const formattedSolution = { + name: solution.facility_name, + image: "/okw_maker.png", + class: "test", + children: children, + }; + + formattedSolutions.push(formattedSolution); + }); + + console.log("formattedSolutions:", formattedSolutions); + + // Update treeData.value to trigger re-render in D3Tree component + treeData.value = { + name: selectedOkh.value?.name || "Supply Tree", + children: [ + { + image: "/okh.png", + children: formattedSolutions, + }, + ], + }; } catch (err) { console.error("Error generating supply tree:", err); - error.value = `Failed to generate supply tree: ${err.message}`; + error.value = `Failed to generate supply tree: ${err instanceof Error ? err.message : String(err)}`; } finally { loading.value = false; } }; -const treeData = reactive({ - name: "Oatmeal raisin cookie", - +const treeData = ref({ + name: "Chocolate Chip Cookies", children: [ { - // name: "OKW", - image: "/okw.png", - children: [ - { - name: "cinnamon", - class: "test", - children: [ - { - image: "/okw.png", - children: [ - { - name: "testA", - children: [ - { - image: "/okw.png", - children: [ - { - name: "test1", - }, - ], - }, - { image: "/okw.png" }, - { image: "/okw.png" }, - { image: "/okw.png" }, - ], - }, - ], - }, - { image: "/okw.png", children: [{ name: "testB" }] }, - { image: "/okw.png" }, - { image: "/okw.png" }, - ], - }, - { name: "vanilla extract", children: [{ image: "/okw.png" }] }, - { name: "white sugar", children: [{ image: "/okw.png" }] }, - { name: "raisin", children: [{ image: "/okw.png" }] }, - { name: "egg", children: [{ image: "/okw.png" }] }, - { name: "shipping supply", children: [{ image: "/okw.png" }] }, - { name: "butter", children: [{ image: "/okw.png" }] }, - { name: "oats", children: [{ image: "/okw.png" }] }, - { - name: "all purpose flour", - children: [{ image: "/okw.png" }], - }, - { name: "brown sugar", children: [{ image: "/okw.png" }] }, - ], + image: "/okh.png", + children: [], }, ], }); diff --git a/packages/front-end/pages/supply-graph-api.vue b/packages/front-end/pages/supply-graph-api.vue index 1066d21..e4000e3 100644 --- a/packages/front-end/pages/supply-graph-api.vue +++ b/packages/front-end/pages/supply-graph-api.vue @@ -11,7 +11,7 @@ const selectedOkh = ref(null); // API configuration const apiBaseUrl = ref(import.meta.env.VITE_API_BASE_URL || 'http://localhost:7071/api'); // Updated to use port 8001 as requested -const supplyGraphApiUrl = ref(import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || 'http://localhost:8001'); +const supplyGraphApiUrl = ref(import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || 'http://localhost:8000'); const supplyGraphApiEndpoint = ref('/v1/match'); // Path to the versioned match endpoint // Removed fetchData function - no mock data needed @@ -94,23 +94,27 @@ const sendToSupplyGraphAI = async (okhItem) => { console.log('Processing OKH item for Supply Graph AI:', okhItem); const originalData = okhItem.originalData || okhItem; - const payload = { - okh_reference: okhItem.id?.toString() || originalData.fname || originalData.id || 'unknown', - required_quantity: 1, - deadline: null, - metadata: { - name: okhItem.name || originalData.name || originalData.title, - shortDescription: okhItem.shortDescription || originalData.description || originalData.summary, - keywords: okhItem.keywords || originalData.keywords || originalData.tags || [], - maker: okhItem.maker || originalData.maker || originalData.author || originalData.creator, - whereToFind: okhItem.whereToFind || originalData.whereToFind || originalData.source, - source: "project-data-platform-ts", - image: okhItem.image || originalData.image || originalData.imageUrl, - originalId: originalData.id || originalData.fname, - dataSource: originalData.dataSource || 'project-data-platform', - ...originalData - } - }; + // const payload = { + // okh_reference: okhItem.id?.toString() || originalData.fname || originalData.id || 'unknown', + // required_quantity: 1, + // deadline: null, + // metadata: { + // name: okhItem.name || originalData.name || originalData.title, + // shortDescription: okhItem.shortDescription || originalData.description || originalData.summary, + // keywords: okhItem.keywords || originalData.keywords || originalData.tags || [], + // maker: okhItem.maker || originalData.maker || originalData.author || originalData.creator, + // whereToFind: okhItem.whereToFind || originalData.whereToFind || originalData.source, + // source: "project-data-platform-ts", + // image: okhItem.image || originalData.image || originalData.imageUrl, + // originalId: originalData.id || originalData.fname, + // dataSource: originalData.dataSource || 'project-data-platform', + // ...originalData + // } + // }; + + const payload = { + "recipe_id": "8f14e3c4-09f2-4a5e-8bd9-4b5bb5d0a9cd" +} console.log('Enhanced payload for Supply Graph AI (port 8001):', payload); console.log(`Sending request to: ${supplyGraphApiUrl.value}${supplyGraphApiEndpoint.value}`); diff --git a/packages/mock-api/index.js b/packages/mock-api/index.js index 9b86df8..f18a583 100644 --- a/packages/mock-api/index.js +++ b/packages/mock-api/index.js @@ -4,7 +4,7 @@ import { supplyTreeMockResponse } from "./mock-data.js"; const app = express(); -const PORT = 8081; +const PORT = 8001; // Middleware to parse JSON app.use(express.json()); diff --git a/packages/mock-api/package.json b/packages/mock-api/package.json index b02fcd8..5ee7218 100644 --- a/packages/mock-api/package.json +++ b/packages/mock-api/package.json @@ -6,6 +6,7 @@ "main": "index.js", "scripts": { "dev": "nodemon index.js", + "start" : "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], From 905ce2568d07ff9252930b0554b112bbfa00644b Mon Sep 17 00:00:00 2001 From: "Robert L. Read" Date: Thu, 22 Jan 2026 17:08:20 -0600 Subject: [PATCH 5/6] changing port to 8001 --- packages/front-end/pages/products/[id]/supplyTree.vue | 2 +- packages/front-end/pages/supply-graph-api.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/front-end/pages/products/[id]/supplyTree.vue b/packages/front-end/pages/products/[id]/supplyTree.vue index c828ca1..483cf3f 100644 --- a/packages/front-end/pages/products/[id]/supplyTree.vue +++ b/packages/front-end/pages/products/[id]/supplyTree.vue @@ -22,7 +22,7 @@ const apiBaseUrl = ref( ); // Updated to use port 8001 as requested const supplyGraphApiUrl = ref( - import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || "http://localhost:8000" + import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || "http://localhost:8001" ); const supplyGraphApiEndpoint = ref("/v1/api/match"); // Path to the versioned supply tree creation endpoint diff --git a/packages/front-end/pages/supply-graph-api.vue b/packages/front-end/pages/supply-graph-api.vue index e4000e3..b42babf 100644 --- a/packages/front-end/pages/supply-graph-api.vue +++ b/packages/front-end/pages/supply-graph-api.vue @@ -11,7 +11,7 @@ const selectedOkh = ref(null); // API configuration const apiBaseUrl = ref(import.meta.env.VITE_API_BASE_URL || 'http://localhost:7071/api'); // Updated to use port 8001 as requested -const supplyGraphApiUrl = ref(import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || 'http://localhost:8000'); +const supplyGraphApiUrl = ref(import.meta.env.VITE_SUPPLY_GRAPH_AI_URL || 'http://localhost:8001'); const supplyGraphApiEndpoint = ref('/v1/match'); // Path to the versioned match endpoint // Removed fetchData function - no mock data needed From 0075e999f5f9715a86ba8ecdfc75716fe61c8d9a Mon Sep 17 00:00:00 2001 From: "Robert L. Read" Date: Thu, 12 Feb 2026 16:52:39 -0600 Subject: [PATCH 6/6] marking problematic line --- packages/front-end/pages/products/[id]/supplyTree.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/front-end/pages/products/[id]/supplyTree.vue b/packages/front-end/pages/products/[id]/supplyTree.vue index 483cf3f..accc50d 100644 --- a/packages/front-end/pages/products/[id]/supplyTree.vue +++ b/packages/front-end/pages/products/[id]/supplyTree.vue @@ -57,6 +57,7 @@ const sendToSupplyGraphAI = async (o: any) => { console.log("Preparing to send OKH item to Supply Graph AI:", okhItem); + // WARNING! TODO: This is hard coding a recipe. We instatn want this to be the OKH! const payload = { recipe_id: "8f14e3c4-09f2-4a5e-8bd9-4b5bb5d0a9cd", };