Skip to content

Commit 4f8dec4

Browse files
committed
feat(sdf): add basic support for sdf without a schema
1 parent e624325 commit 4f8dec4

File tree

4 files changed

+97
-39
lines changed

4 files changed

+97
-39
lines changed

src/features/SDFViewer/ConfigEditor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { Alert, Box, Button, Checkbox, MenuItem, TextField, Typography } from "@
66
import { type SDFViewerConfig } from "../../utils/api/sdfViewer";
77
import { type JSON_SCHEMA_TYPE, JSON_SCHEMA_TYPES } from "../../utils/app/jsonSchema";
88

9-
type Field = {
9+
export type Field = {
1010
type: JSON_SCHEMA_TYPE;
1111
description: string;
1212
};
1313

14-
interface Schema {
14+
export interface Schema {
1515
$schema: string;
1616
$id: string;
1717
title: string;

src/features/SDFViewer/SDFViewer.tsx

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,25 @@
11
import { type PropsWithChildren, useState } from "react";
22

3-
import { useGetProjectFile } from "@squonk/data-manager-client/project";
4-
53
import { Button, Typography } from "@mui/material";
64

75
import { CenterLoader } from "../../components/CenterLoader";
86
import { type SDFViewerConfig } from "../../utils/api/sdfViewer";
97
import { ConfigEditor } from "./ConfigEditor";
108
import { SDFViewerData } from "./SDFViewerData";
9+
import { useGetSDFSchema } from "./useGetSDFSchema";
1110

1211
export interface SDFViewerProps {
1312
project: string;
1413
path: string;
1514
file: string;
1615
}
1716

18-
const getSchemaFileNameFromSDFFileName = (fname: string) => fname.slice(0, -4) + ".schema.json";
19-
2017
export const SDFViewer = ({ project, path, file }: SDFViewerProps) => {
21-
const schemaFilename = getSchemaFileNameFromSDFFileName(file);
22-
const {
23-
data: schema,
24-
error,
25-
isLoading,
26-
} = useGetProjectFile<any>(
27-
project,
28-
{
29-
path,
30-
file: schemaFilename,
31-
},
32-
{
33-
query: {
34-
retry: 0,
35-
},
36-
},
37-
);
18+
const { schema, isLoading } = useGetSDFSchema(project, path, file);
3819

3920
const [isEditingConfig, setIsEditingConfig] = useState(true);
4021
const [config, setConfig] = useState<SDFViewerConfig | undefined>(undefined);
4122

42-
if (error) {
43-
// handle error
44-
// SDF schema might not exist
45-
if (error.status === 404) {
46-
return (
47-
<Header title={file}>
48-
<Typography color="error" variant="body1">
49-
No schema found for this SDF
50-
</Typography>
51-
</Header>
52-
);
53-
}
54-
return null;
55-
}
56-
5723
if (isLoading) {
5824
// TODO: add loading page
5925
return (
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { useGetProjectFile } from "@squonk/data-manager-client/project";
2+
import { createSDFTransformer } from "@squonk/sdf-parser";
3+
4+
import { useQuery } from "@tanstack/react-query";
5+
6+
import { API_ROUTES } from "../../utils/app/routes";
7+
import { type Field, type Schema } from "./ConfigEditor";
8+
9+
const getSchemaFileNameFromSDFFileName = (fname: string) => fname.slice(0, -4) + ".schema.json";
10+
11+
const getSDFFields = async (project: string, path: string, file: string) => {
12+
const response = await fetch(API_ROUTES.projectFile(project, path, file, "/api/dm-api"));
13+
14+
if (!response.ok) {
15+
throw new Error(`Failed to fetch SDF file: ${response.statusText}`);
16+
}
17+
18+
const properties = new Set<string>();
19+
await response.body
20+
?.pipeThrough(new TextDecoderStream())
21+
.pipeThrough(createSDFTransformer())
22+
.pipeTo(
23+
new WritableStream({
24+
write(record) {
25+
// Get all field keys from the record and add to Set
26+
Object.keys(record.properties).forEach((key) => properties.add(key));
27+
},
28+
}),
29+
);
30+
31+
const fields = [...properties].reduce<Record<string, Field>>((acc, property) => {
32+
acc[property] = {
33+
type: "string",
34+
description: "",
35+
};
36+
return acc;
37+
}, {});
38+
39+
return fields;
40+
};
41+
42+
const stubSchema = (fields: Record<string, Field> | undefined): Schema | undefined => {
43+
if (fields) {
44+
return {
45+
$schema: "",
46+
$id: "",
47+
title: "",
48+
description: "",
49+
version: 0,
50+
type: "object",
51+
fields,
52+
required: [],
53+
labels: {},
54+
};
55+
}
56+
};
57+
58+
const useGetSDFSchema = (project: string, path: string, file: string) => {
59+
const schemaFilename = getSchemaFileNameFromSDFFileName(file);
60+
const {
61+
data: schemaFile,
62+
error,
63+
isLoading,
64+
} = useGetProjectFile<any>(
65+
project,
66+
{ path, file: schemaFilename },
67+
{
68+
query: { retry: 0, enabled: true, refetchOnWindowFocus: false },
69+
},
70+
);
71+
72+
const {
73+
data: fields,
74+
isLoading: isSdfLoading,
75+
error: sdfError,
76+
} = useQuery({
77+
queryKey: ["sdf-fields", project, path, file],
78+
queryFn: () => getSDFFields(project, path, file),
79+
enabled: error?.status === 404,
80+
refetchOnWindowFocus: false,
81+
});
82+
83+
const fallbackSchema = stubSchema(fields);
84+
85+
return {
86+
schema: schemaFile ?? fallbackSchema,
87+
isLoading: isLoading || isSdfLoading,
88+
error: error ?? sdfError,
89+
};
90+
};
91+
92+
export { useGetSDFSchema };

src/pages/viewer/sdf.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const SDF = () => {
1616
const { project, path, file } = query;
1717

1818
if (typeof project !== "string" || typeof path !== "string" || typeof file !== "string") {
19-
return <Error statusCode={404} title="File not found" />;
19+
return <Error statusCode={404} title="URL is Malformed" />;
2020
}
2121

2222
return (

0 commit comments

Comments
 (0)