diff --git a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx
index 8811a3e0bd..689ac4379f 100644
--- a/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx
+++ b/plugins/config-schema/src/components/ConfigSchemaPage/ConfigSchemaPage.tsx
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import React, { useMemo } from 'react';
-import { Grid } from '@material-ui/core';
import {
Header,
Page,
@@ -36,19 +35,15 @@ export const ConfigSchemaPage = () => {
return (
-
+
-
+
A description of your plugin goes here.
-
-
- {schema ? : 'No schema available'}
-
-
+ {schema ? : 'No schema available'}
);
diff --git a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx
index 5e6c1ec94c..874fea03a9 100644
--- a/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx
+++ b/plugins/config-schema/src/components/SchemaViewer/SchemaViewer.tsx
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import React from 'react';
+import React, { ReactNode, useMemo } from 'react';
import { Schema } from 'jsonschema';
import {
Box,
Chip,
+ createStyles,
Divider,
+ fade,
makeStyles,
Paper,
Table,
@@ -26,8 +28,12 @@ import {
TableCell,
TableRow,
Typography,
+ withStyles,
} from '@material-ui/core';
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
+import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import { JsonValue } from '@backstage/config';
+import { TreeItem, TreeItemProps, TreeView } from '@material-ui/lab';
interface SchemaViewProps {
path: string;
@@ -414,6 +420,183 @@ export interface SchemaViewerProps {
schema: Schema;
}
+const StyledTreeItem = withStyles(theme =>
+ createStyles({
+ label: {
+ userSelect: 'none',
+ },
+ group: {
+ marginLeft: 7,
+ paddingLeft: theme.spacing(1),
+ borderLeft: `1px solid ${fade(theme.palette.text.primary, 0.15)}`,
+ },
+ }),
+)((props: TreeItemProps) => );
+
+export function createSchemaBrowserItems(
+ expanded: string[],
+ schema: Schema,
+ path: string = '',
+ depth: number = 0,
+): ReactNode {
+ let matchArr;
+ if (schema.anyOf) {
+ matchArr = schema.anyOf;
+ } else if (schema.oneOf) {
+ matchArr = schema.oneOf;
+ } else if (schema.allOf) {
+ matchArr = schema.allOf;
+ }
+ if (matchArr) {
+ return matchArr.map((childSchema, index) => {
+ const childPath = `${path}/${index}`;
+ if (depth > 0) expanded.push(childPath);
+ return (
+ `}
+ >
+ {createSchemaBrowserItems(
+ expanded,
+ childSchema,
+ childPath,
+ depth + 1,
+ )}
+
+ );
+ });
+ }
+
+ switch (schema.type) {
+ case 'array': {
+ const childPath = `${path}[]`;
+ if (depth > 0) expanded.push(childPath);
+ return (
+
+ {schema.items &&
+ createSchemaBrowserItems(
+ expanded,
+ schema.items as Schema,
+ childPath,
+ depth + 1,
+ )}
+
+ );
+ }
+ case 'object':
+ case undefined: {
+ const children = [];
+
+ if (schema.properties) {
+ children.push(
+ ...Object.entries(schema.properties).map(([name, childSchema]) => {
+ const childPath = path ? `${path}/${name}` : name;
+ if (depth > 0) expanded.push(childPath);
+ return (
+
+ {createSchemaBrowserItems(
+ expanded,
+ childSchema,
+ childPath,
+ depth + 1,
+ )}
+
+ );
+ }),
+ );
+ }
+
+ if (schema.patternProperties) {
+ children.push(
+ ...Object.entries(schema.patternProperties).map(
+ ([name, childSchema]) => {
+ const childPath = `${path}/<${name}>`;
+ if (depth > 0) expanded.push(childPath);
+ return (
+ `}
+ >
+ {createSchemaBrowserItems(
+ expanded,
+ childSchema,
+ childPath,
+ depth + 1,
+ )}
+
+ );
+ },
+ ),
+ );
+ }
+
+ if (schema.additionalProperties && schema.additionalProperties !== true) {
+ const childPath = `${path}/*`;
+ if (depth > 0) expanded.push(childPath);
+ children.push(
+
+ {createSchemaBrowserItems(
+ expanded,
+ schema.additionalProperties,
+ childPath,
+ depth + 1,
+ )}
+ ,
+ );
+ }
+
+ return <>{children}>;
+ }
+
+ default:
+ return null;
+ }
+}
+
+export function SchemaBrowser({ schema }: { schema: Schema }) {
+ const data = useMemo(() => {
+ const expanded = new Array();
+
+ const items = createSchemaBrowserItems(expanded, schema);
+
+ return { items, expanded };
+ }, [schema]);
+
+ return (
+ }
+ defaultExpandIcon={}
+ >
+ {data.items}
+
+ );
+}
+
export const SchemaViewer = ({ schema }: SchemaViewerProps) => {
- return ;
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};