From 992c867c60786f3afa72d3e188ffd0aa45d2acf0 Mon Sep 17 00:00:00 2001 From: Jo Humphrey <31373245+jamdelion@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:33:27 +0000 Subject: [PATCH] feat: toggle hardcoded schema versions (#5) --- api/useQuerySchemas.ts | 18 ++++-- package.json | 1 + pnpm-lock.yaml | 43 +++++++++++++ src/App.tsx | 128 +++++++++++++++++++++++++------------- src/components/Header.tsx | 39 ++++++++++++ 5 files changed, 180 insertions(+), 49 deletions(-) create mode 100644 src/components/Header.tsx diff --git a/api/useQuerySchemas.ts b/api/useQuerySchemas.ts index 932fda5..10ff0f2 100644 --- a/api/useQuerySchemas.ts +++ b/api/useQuerySchemas.ts @@ -1,19 +1,27 @@ -import { useQuery } from "@tanstack/react-query"; +import { useQuery, UseQueryOptions } from "@tanstack/react-query"; import axios from "axios"; const DIGITAL_PLANNING_DATA_SCHEMAS_JSON_URL = - "https://theopensystemslab.github.io/digital-planning-data-schemas/v0.7.0/schema.json"; + "https://theopensystemslab.github.io/digital-planning-data-schemas"; -const useQuerySchemas = () => { +// TODO: type the version more strictly +const useQuerySchemas = ( + version: string, + options?: Readonly, "queryKey" | "queryFn">> +) => { const fetchFn = async (url: string) => { const response = await axios.get(url); return response.data; }; return useQuery({ - queryKey: ["schemas"], - queryFn: () => fetchFn(DIGITAL_PLANNING_DATA_SCHEMAS_JSON_URL), + queryKey: ["schemas", version], + queryFn: () => + fetchFn( + `${DIGITAL_PLANNING_DATA_SCHEMAS_JSON_URL}/${version}/schema.json` + ), staleTime: 1000 * 60 * 10, // cache for 10 minutes + ...options, }); }; diff --git a/package.json b/package.json index f16b9ca..cb9f8f1 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@tanstack/react-query": "^5.59.15", "@types/prismjs": "^1.26.4", "axios": "^1.7.7", + "formik": "^2.4.6", "prismjs": "^1.29.0", "react": "^18.3.1", "react-dom": "^18.3.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25903f3..25e186e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: axios: specifier: ^1.7.7 version: 1.7.7 + formik: + specifier: ^2.4.6 + version: 2.4.6(react@18.3.1) prismjs: specifier: ^1.29.0 version: 1.29.0 @@ -1535,6 +1538,13 @@ packages: '@types/unist': 2.0.11 dev: false + /@types/hoist-non-react-statics@3.3.5: + resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==} + dependencies: + '@types/react': 18.3.3 + hoist-non-react-statics: 3.3.2 + dev: false + /@types/js-cookie@2.2.7: resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} dev: false @@ -2050,6 +2060,11 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /deepmerge@2.2.1: + resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} + engines: {node: '>=0.10.0'} + dev: false + /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -2366,6 +2381,22 @@ packages: engines: {node: '>=0.4.x'} dev: false + /formik@2.4.6(react@18.3.1): + resolution: {integrity: sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==} + peerDependencies: + react: '>=16.8.0' + dependencies: + '@types/hoist-non-react-statics': 3.3.5 + deepmerge: 2.2.1 + hoist-non-react-statics: 3.3.2 + lodash: 4.17.21 + lodash-es: 4.17.21 + react: 18.3.1 + react-fast-compare: 2.0.4 + tiny-warning: 1.0.3 + tslib: 2.7.0 + dev: false + /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2749,6 +2780,10 @@ packages: p-locate: 5.0.0 dev: true + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} dev: false @@ -3208,6 +3243,10 @@ packages: scheduler: 0.23.2 dev: false + /react-fast-compare@2.0.4: + resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} + dev: false + /react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} dev: false @@ -3540,6 +3579,10 @@ packages: engines: {node: '>=10'} dev: false + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} diff --git a/src/App.tsx b/src/App.tsx index 12ca705..065ed04 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,58 +1,98 @@ -import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; +import { useQueryClient } from "@tanstack/react-query"; import { JsonSchemaViewer } from "@stoplight/json-schema-viewer"; -import { Provider as MosaicProvider, injectStyles } from "@stoplight/mosaic"; +import { injectStyles } from "@stoplight/mosaic"; +import { useFormik } from "formik"; import useQuerySchemas from "./../api/useQuerySchemas"; +import InputLabel from "@mui/material/InputLabel"; +import MenuItem from "@mui/material/MenuItem"; +import Select from "@mui/material/Select"; +import { useState } from "react"; +import Header from "./components/Header"; + +// TODO: grab this programatically instead of hard-coding +const LATEST_WORKING_VERSION = "v0.7.0"; + const App = () => { injectStyles(); + const queryClient = useQueryClient(); + const [selectedVersion, setSelectedVersion] = useState( + LATEST_WORKING_VERSION + ); - const { data: schema, isLoading, isError } = useQuerySchemas(); + const { + data: schema, + isLoading, + isError, + } = useQuerySchemas(selectedVersion, { retry: false }); + + const formik = useFormik({ + initialValues: { + version: selectedVersion, + }, + onSubmit: (values) => setSelectedVersion(values.version), + }); return ( - - - Digital planning data schemas - - - Digital Planning Data schemas aim to encourage more interoperability and - consistency between systems by offering a central, version controlled - specification for documenting and validating planning data. - - - - {isLoading ? ( - Loading... - ) : ( - <> - {schema.$id} - - - )} - {isError && ( - Sorry, please try again later. +
+ {isLoading ? ( + Loading... + ) : ( + <> +
+ + Version + + +
+ {!isError && ( + )} - - - + + )} + {isError && ( + Sorry, please try again later. + )} +
); }; diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..b0c5f4b --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,39 @@ +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; + +import { Provider as MosaicProvider, injectStyles } from "@stoplight/mosaic"; + +import { ComponentProps } from "react"; + +const Header = ({ children }: ComponentProps<"header">) => { + injectStyles(); + + return ( + + + Digital planning data schemas + + + Digital Planning Data schemas aim to encourage more interoperability and + consistency between systems by offering a central, version controlled + specification for documenting and validating planning data. + + + + {children} + + + + ); +}; + +export default Header;