Skip to content

Commit

Permalink
feat: Improves JSON rendering via react-json-view (#260)
Browse files Browse the repository at this point in the history
- Improved rendering of raw JSON objects when referenced as field
values.
- Improved raw search result rendering.
- Improved GCS error rendering.
  • Loading branch information
jbottigliero authored Nov 14, 2024
1 parent 31a592b commit 59b6fc1
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 30 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@tanstack/react-query": "^5.59.20",
"@types/d3-fetch": "^3.0.7",
"@types/mdx": "^2.0.13",
"@uiw/react-json-view": "^2.0.0-alpha.30",
"d3-fetch": "^3.0.1",
"framer-motion": "^11.11.11",
"lodash": "^4.17.21",
Expand Down
89 changes: 64 additions & 25 deletions src/components/Fields/GlobusEmbedField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React, { PropsWithChildren } from "react";
import {
Accordion,
AccordionButton,
AccordionItem,
AccordionPanel,
Alert,
AlertDescription,
AlertIcon,
Expand All @@ -10,6 +14,7 @@ import {
Code,
Flex,
HStack,
Spacer,
Spinner,
Text,
} from "@chakra-ui/react";
Expand All @@ -23,6 +28,7 @@ import { useLogin } from "@/hooks/useOAuth";
import { PlotlyRenderer } from "./Renderer/Plotly";
import { ObjectRenderer } from "./Renderer/Object";
import { useGCSAsset, useGCSAssetMetadata } from "@/hooks/useGlobusAPI";
import { JSONTree } from "../JSONTree";

type Renderers = "plotly" | "editor" | undefined;

Expand Down Expand Up @@ -207,11 +213,13 @@ function GlobusEmbed({ config, field }: GlobusEmbedProps) {
<AlertIcon />
<AlertTitle>Authentication Required</AlertTitle>
<AlertDescription>
To view this asset, you must{" "}
<Button variant="link" onClick={login}>
Sign In
</Button>
.
<Text>
In order to view this embedded resource, you must{" "}
<Button variant="link" onClick={login} color="yellow.800">
Sign In
</Button>
.
</Text>
</AlertDescription>
</Alert>
)}
Expand Down Expand Up @@ -260,6 +268,19 @@ function EmbedError({ error }: { error: unknown }) {
const pathname = usePathname();
const search = useSearchParams();
let handler;
/**
* Attempt to extract a `message` from the error.
*/
const message =
error &&
typeof error === "object" &&
"message" in error &&
typeof error.message === "string"
? error.message
: "An error occurred.";

let description = <Text>{message}</Text>;

if (isAuthorizationRequirementsError(error)) {
const requiredScopes = error.authorization_parameters?.required_scopes;
handler = async () => {
Expand All @@ -274,28 +295,46 @@ function EmbedError({ error }: { error: unknown }) {
},
});
};

description = (
<>
<Text>
Your current session does not meet the requirements to view this
resource – you must{" "}
<Button onClick={handler} variant="link" color="red.800">
address requirements
</Button>
.
</Text>
</>
);
}
/**
* Attempt to extract a `message` from the error.
*/
const message =
error &&
typeof error === "object" &&
"message" in error &&
typeof error.message === "string"
? error.message
: "An error occurred.";
return (
<Alert status="error">
<AlertIcon />
{message}
<AlertDescription>
{handler && (
<Button onClick={handler} size="xs" colorScheme="red" ml={2}>
Address Error
</Button>
)}
</AlertDescription>
<Alert status="error" flexDirection="column" alignItems="flex-start">
<Flex>
<AlertIcon />
<AlertTitle>Unable to render resource.</AlertTitle>
</Flex>
<AlertDescription mt={1}>{description}</AlertDescription>
{typeof error === "object" && error && (
<Accordion allowToggle w="100%">
<AccordionItem border={0}>
<Flex>
<Spacer />
<AccordionButton w="auto">
<Button variant="link" colorScheme="black" size="xs">
View Error
</Button>
</AccordionButton>
</Flex>
<AccordionPanel>
<Box bg="white" p={2} rounded={5}>
<JSONTree data={error} />
</Box>
</AccordionPanel>
</AccordionItem>
</Accordion>
)}
</Alert>
);
}
9 changes: 4 additions & 5 deletions src/components/JSONTree.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from "react";

import JsonView from "@uiw/react-json-view";
import { Code } from "@chakra-ui/react";

/**
* @todo
*/
export const JSONTree = ({ data }: { data: unknown }) => {
return (
return typeof data === "object" && data !== null ? (
<JsonView value={data} />
) : (
<Code as="pre" overflow="scroll" maxW="100%">
{JSON.stringify(data, null, 2)}
</Code>
Expand Down

0 comments on commit 59b6fc1

Please sign in to comment.