From a5397242abd89b28b4388476dfb3cbf533490c13 Mon Sep 17 00:00:00 2001
From: Joe Bottigliero <694253+jbottigliero@users.noreply.github.com>
Date: Tue, 23 Apr 2024 10:31:56 -0500
Subject: [PATCH] feat: adds 'table' field type and scaffold for JSONTree
component
---
src/components/Field.tsx | 9 ++-
src/components/Fields/FallbackField.tsx | 18 ++---
src/components/Fields/TableField.tsx | 50 +++++++++++++
src/components/JSONTree.tsx | 10 +++
src/components/Result.tsx | 5 +-
src/components/ResultListing.tsx | 97 +++++++++++++------------
6 files changed, 128 insertions(+), 61 deletions(-)
create mode 100644 src/components/Fields/TableField.tsx
create mode 100644 src/components/JSONTree.tsx
diff --git a/src/components/Field.tsx b/src/components/Field.tsx
index 23feb5e..006a8ad 100644
--- a/src/components/Field.tsx
+++ b/src/components/Field.tsx
@@ -5,6 +5,7 @@ import jsonata from "jsonata";
import RgbaField from "./Fields/RgbaField";
import ImageField from "./Fields/ImageField";
+import TableField from "./Fields/TableField";
import FallbackField from "./Fields/FallbackField";
import type { GMetaResult } from "../globus/search";
@@ -69,7 +70,13 @@ export const FieldValue = ({
if (type === "image") {
return ;
}
- return ; // fallback
+ if (type === "table") {
+ return ;
+ }
+ /**
+ * If no `type` is provided, or the `type` is not recognized, use the fallback field.
+ */
+ return ;
};
export const Field = ({
diff --git a/src/components/Fields/FallbackField.tsx b/src/components/Fields/FallbackField.tsx
index 508eb38..58dc403 100644
--- a/src/components/Fields/FallbackField.tsx
+++ b/src/components/Fields/FallbackField.tsx
@@ -1,22 +1,22 @@
import React from "react";
-import { Box, Code, Text } from "@chakra-ui/react";
+import { Box, Text } from "@chakra-ui/react";
+import { JSONTree } from "../JSONTree";
type Value = unknown;
-// function isValidValue(value: unknown): value is Value {
-// return true;
-// }
-
/**
* A fallback field that will introspect the value and render it as best as it can.
*/
export default function FallbackField({ value }: { value: Value }) {
+ if (value === null || value === undefined) {
+ return —;
+ }
if (
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean"
) {
- return {value};
+ return {value};
}
if (Array.isArray(value)) {
return value.map((v, i) => (
@@ -25,9 +25,5 @@ export default function FallbackField({ value }: { value: Value }) {
));
}
- return (
-
- {JSON.stringify(value, null, 2)}
-
- );
+ return ;
}
diff --git a/src/components/Fields/TableField.tsx b/src/components/Fields/TableField.tsx
new file mode 100644
index 0000000..7364030
--- /dev/null
+++ b/src/components/Fields/TableField.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import {
+ Table,
+ Tbody,
+ Tr,
+ Thead,
+ Th,
+ Td,
+ TableContainer,
+} from "@chakra-ui/react";
+import { FieldValue } from "../Field";
+
+type Value = Record;
+
+function isValidValue(value: unknown): value is Value {
+ return typeof value === "object" && value !== null;
+}
+
+/**
+ * Render a field as an RGBA color.
+ */
+export default function TableField({ value }: { value: unknown }) {
+ if (!isValidValue(value)) {
+ return;
+ }
+ return (
+
+
+
+
+ Property |
+ Value |
+
+
+
+ {Object.entries(value).map(([key, value]) => {
+ return (
+
+ {key} |
+
+
+ |
+
+ );
+ })}
+
+
+
+ );
+}
diff --git a/src/components/JSONTree.tsx b/src/components/JSONTree.tsx
new file mode 100644
index 0000000..763806e
--- /dev/null
+++ b/src/components/JSONTree.tsx
@@ -0,0 +1,10 @@
+import React from "react";
+
+import { Code } from "@chakra-ui/react";
+
+/**
+ * @todo
+ */
+export const JSONTree = ({ data }: { data: unknown }) => {
+ return {JSON.stringify(data, null, 2)}
;
+};
diff --git a/src/components/Result.tsx b/src/components/Result.tsx
index 4069deb..f452bc5 100644
--- a/src/components/Result.tsx
+++ b/src/components/Result.tsx
@@ -5,7 +5,6 @@ import {
Heading,
Text,
Box,
- Code,
Flex,
Button,
Drawer,
@@ -22,8 +21,8 @@ import {
import { getAttribute, getAttributeFrom } from "../../static";
import { Error } from "./Error";
import { isGError, type GError, type GMetaResult } from "@/globus/search";
-
import { Field, type FieldDefinition } from "./Field";
+import { JSONTree } from "./JSONTree";
export type ResultComponentOptions = {
/**
@@ -104,7 +103,7 @@ export default function Result({ result }: { result?: GMetaResult | GError }) {
- {JSON.stringify(result, null, 2)}
+
diff --git a/src/components/ResultListing.tsx b/src/components/ResultListing.tsx
index 00d5755..cf2223b 100644
--- a/src/components/ResultListing.tsx
+++ b/src/components/ResultListing.tsx
@@ -13,6 +13,7 @@ import {
Tr,
Td,
HStack,
+ Link,
} from "@chakra-ui/react";
import { getAttributeFrom, getAttribute } from "../../static";
@@ -125,60 +126,64 @@ export default function ResultListing({ gmeta }: { gmeta: GMetaResult }) {
src: string;
alt?: string;
}>();
- getAttributeFrom(gmeta, "components.ResultListing.heading").then(
- (result) => {
- setHeading(result);
- },
- );
- getAttributeFrom(gmeta, "components.ResultListing.summary").then(
- (result) => {
- setSummary(result);
- },
- );
+ useEffect(() => {
+ async function resolveAttributes() {
+ const heading = await getAttributeFrom(
+ gmeta,
+ "components.ResultListing.heading",
+ );
+ const summary = await getAttributeFrom(
+ gmeta,
+ "components.ResultListing.summary",
+ );
+ let image = await getAttributeFrom<
+ | string
+ | {
+ src: string;
+ alt?: string;
+ }
+ >(gmeta, "components.ResultListing.image");
- getAttributeFrom<
- | string
- | {
- src: string;
- alt?: string;
+ setHeading(heading);
+ setSummary(summary);
+
+ if (typeof image === "string") {
+ image = { src: image };
}
- >(gmeta, "components.ResultListing.image").then((result) => {
- let image = result;
- if (typeof image === "string") {
- image = { src: image };
+ setImage(image);
}
- setImage(image);
- });
+ resolveAttributes();
+ }, [gmeta]);
const fields = getAttribute("components.ResultListing.fields");
return (
-
-
-
-
+
+
+
+
{heading}
-
-
-
-
- {image && (
-
- )}
- {summary && {summary}}
-
-
-
-
-
+
+
+
+
+
+ {image && (
+
+ )}
+ {summary && {summary}}
+
+
+
+
);
}