Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Rebuilding getting started component (#687) #782

Merged
merged 7 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
258 changes: 258 additions & 0 deletions components/GettingStarted.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
import React, { useState, useEffect } from 'react';
import { atomOneDark } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import Highlight from 'react-syntax-highlighter';
import JSZip from 'jszip';
import { saveAs } from 'file-saver';

async function fetchData() {
const response = await fetch('/data/getting-started-examples.json');
const data = await response.json();

const defaultSchemaData = data.find((data: any) => data.default === true);

const schemaResp = await fetch(defaultSchemaData.file);
const schemaData = await schemaResp.json();

const defaultInstanceData = defaultSchemaData.instances.find(
(instance: any) => instance.default === true,
);

const instanceResp = await fetch(defaultInstanceData.file);
const instanceData = await instanceResp.json();

return {
data,
schemaData,
instanceData,
initialInstance: defaultSchemaData.instances,
initialDetails: [defaultInstanceData.details, defaultInstanceData.valid],
};
}

interface SchemaOption {
file: string;
instances: InstanceOption[];
}

interface InstanceOption {
file: string;
details: string;
valid: string;
}

const GettingStarted = () => {
useEffect(() => {
fetchData()
.then(
({
data,
schemaData,
instanceData,
initialInstance,
initialDetails,
}) => {
setOptions(data);
setFetchedSchema(schemaData);
setFetchedInstance(instanceData);
setInstances(initialInstance);
setDetails(initialDetails);
},
)
.catch((e) => console.log('Error: ', e));
}, []);

const [options, setOptions] = useState<SchemaOption[]>([]);
const [instances, setInstances] = useState<InstanceOption[]>([]);
const [details, setDetails] = useState<string[]>(['', '']);
const [fetchedSchema, setFetchedSchema] = useState();
const [fetchedInstance, setFetchedInstance] = useState();

const handleSchemaChange = async (
e: React.ChangeEvent<HTMLSelectElement>,
) => {
const selectedSchema = options.find(
(schema) => schema.file === e.target.value,
);

if (selectedSchema) {
const schemaResponse = await fetch(e.target.value);
const schData = await schemaResponse.json();

setFetchedSchema(schData);
setInstances(selectedSchema.instances);

const instResp = await fetch(selectedSchema.instances[0].file);
const instData = await instResp.json();
setFetchedInstance(instData);
} else {
setInstances([]);
setFetchedSchema(null!);
}
};

const handleInstanceChange = async (
e: React.ChangeEvent<HTMLSelectElement>,
) => {
const selectedInstance = instances.find(
(instance) => instance.file === e.target.value,
) as InstanceOption;

if (selectedInstance) {
const instanceResponse = await fetch(e.target.value);
const instanceData = await instanceResponse.json();

setFetchedInstance(instanceData);
setDetails([selectedInstance.details, selectedInstance.valid]);
} else {
setFetchedInstance(undefined);
}
};

const createZip = async () => {
try {
const zip = new JSZip();
zip.file('schema.json', JSON.stringify(fetchedSchema, null, 2));
zip.file('instance.json', JSON.stringify(fetchedInstance, null, 2));

zip.generateAsync({ type: 'blob' }).then((content) => {
saveAs(content, 'getting-started-examples.zip');
});
} catch (e) {
console.log('Error zipping files', e);
}
};

return (
<>
<div className='relative'>
<div className='flex flex-col'>
<div className='flex items-end flex-row justify-between mt-5 mb-3 '>
<h2 className='text-h6 font-semibold mb-1'>JSON Schema</h2>
<div className='select-wrap'>
<label className='mr-2 max-sm:text-[12px]'>
Select a Schema:
</label>
<select
name='Select a JSON Schema Validator'
className='p-2 border dark:border-slate-300 border-slate-800 dark:bg-slate-900 rounded-md max-sm:text-[12px] plausible-event-name==activation-explore-tools'
id='Examples'
onChange={handleSchemaChange}
>
{options.map((option: any, id: number) => (
<option key={id} value={option.file}>
{option.name}
</option>
))}
</select>
</div>
</div>

<div className='overflow-x-auto flex-basis-0 max-w-full min-w-0 shrink lg:max-w-[800px] xl:max-w-[900px]'>
<Highlight
wrapLines={true}
wrapLongLines={true}
customStyle={{
borderRadius: 10,
paddingTop: 15,
paddingBottom: 10,
paddingLeft: 10,
marginBottom: 20,
maxWidth: '100%',
}}
lineNumberStyle={{
marginRight: 10,
}}
style={atomOneDark}
showLineNumbers
startingLineNumber={1}
lineProps={() => {
const isHighlighted = false;
return {
className: `${isHighlighted ? 'bg-code-editor-dark-highlight block ml-10 w-full' : ''} pr-8`,
};
}}
codeTagProps={{
className: 'mr-8',
}}
>
{JSON.stringify(fetchedSchema, null, 2)}
</Highlight>
</div>
</div>

<div className='flex flex-col'>
<div className='flex items-end flex-row justify-between mt-5 mb-3 '>
<h2 className='text-h6 font-semibold mb-1'>JSON Instance</h2>
<div className='select-wrap'>
<label className='mr-2 max-sm:text-[12px]'>
Select an Instance:
</label>
<select
name='Select a JSON Schema Validator'
className='p-2 border dark:border-slate-300 border-slate-800 dark:bg-slate-900 rounded-md max-sm:text-[12px] plausible-event-name==activation-explore-tools'
id='Examples'
onChange={handleInstanceChange}
>
{instances.map((instance: any, id: number) => (
<option key={id} value={instance.file}>
{instance.name}
</option>
))}
</select>
</div>
</div>
<div className='overflow-x-auto flex-basis-0 max-w-full min-w-0 shrink lg:max-w-[800px] xl:max-w-[900px]'>
<Highlight
wrapLines={true}
wrapLongLines={true}
customStyle={{
borderRadius: 10,
paddingTop: 15,
paddingBottom: 10,
paddingLeft: 10,
marginBottom: 20,
maxWidth: '100%',
}}
lineNumberStyle={{
marginRight: 10,
}}
style={atomOneDark}
showLineNumbers
startingLineNumber={1}
lineProps={() => {
const isHighlighted = false;
return {
className: `${isHighlighted ? 'bg-code-editor-dark-highlight block ml-10 w-full' : ''} pr-8`,
};
}}
codeTagProps={{
className: 'mr-8',
}}
>
{JSON.stringify(fetchedInstance, null, 2)}
</Highlight>
</div>
<h2 className='text-h6 font-semibold'>Validation Result</h2>
<div className='flex bg-[#282c34] justify-between items-center text-white font-medium flex-row border p-5 rounded-xl'>
<p>{details[0]}</p>

{details[1] ? (
<img src='/icons/green-tick.svg' alt='green tick' />
) : (
<img src='/icons/red-cross.svg' alt='red cross' />
)}
</div>
</div>

<button
className='absolute right-0 my-4 text-[17px] bg-startBlue text-white px-3 py-1 rounded'
onClick={createZip}
>
Download
</button>
</div>
</>
);
};

export default GettingStarted;
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
"axios": "1.7.2",
"classnames": "^2.3.1",
"feed": "^4.2.2",
"file-saver": "^2.0.5",
"gray-matter": "^4.0.3",
"js-yaml": "^4.1.0",
"jszip": "^3.10.1",
"markdown-to-jsx": "^7.4.7",
"moment": "2.29.4",
"next": "14.2.5",
Expand All @@ -47,6 +49,7 @@
},
"devDependencies": {
"@next/eslint-plugin-next": "^14.0.1",
"@types/file-saver": "^2.0.7",
"@types/js-yaml": "^4.0.5",
"@types/node": "^20.0.0",
"@types/react": "18.3.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ title: Creating your first schema
section: docs
---

JSON Schema is a vocabulary that you can use to annotate and validate JSON documents. This tutorial guides you through the process of creating a JSON Schema document.
JSON Schema is a vocabulary that you can use to annotate and validate JSON documents. This tutorial guides you through the process of creating a JSON Schema.

After you create the JSON Schema document, you can validate the example data against your schema using a validator in a language of your choice. See <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations)</userevent> for a current list of supported validators.
After creating your JSON Schema, you can then validate example data against your schema by using a validator in a language of your choice. Please, visit <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations#validators)</userevent> and select the validator that better suit your needs.

If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations)</userevent> and explore the amazing tooling available in the JSON Schema Ecosystem.

<tableofcontent depth={2} />

Expand Down Expand Up @@ -573,28 +575,11 @@ With the external schema reference, the overall schema looks like this:

## Validate JSON data against the schema

This section describes how to validate JSON data against the product catalog schema.
Now that you have your JSON Schema is time to validate [JSON data](https://json-schema.org/learn/glossary#instance) against it using a <userevent type='plausible-event-name=activation-explore-tools'>[JSON Schema Validator](https://json-schema.org/implementations#validators)</userevent>.

This example JSON data matches the product catalog schema:
A Validator is a tool that implements the JSON Schema specification. All validators works in a similar way: they take a JSON Schema and a JSON Instance as input and they returns the validation result as output.

```json
{
"productId": 1,
"productName": "An ice sculpture",
"price": 12.50,
"tags": [ "cold", "ice" ],
"dimensions": {
"length": 7.0,
"width": 12.0,
"height": 9.5
},
"warehouseLocation": {
"latitude": -78.75,
"longitude": 20.4
}
}
```
![How JSON Schema works](https://json-schema.org/img/json_schema.svg)

To validate this JSON data against the product catalog JSON Schema, you can use any validator of your choice. In addition to command-line and browser tools, validation tools are available in a wide range of languages, including Java, Python, .NET, and many others. To find a validator that’s right for your project, see <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations)</userevent>.
To try it yourself, please visit <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations#validators)</userevent> and select the validator that better suit your needs, our use the editors available below to explore the different Schemas and Instances and see the different validation results.

Use the example JSON data as the input data and the product catalog JSON Schema as the schema. Your validation tool compares the data against the schema, and if the data meets all the requirements defined in the schema, validation is successful.
47 changes: 47 additions & 0 deletions pages/learn/getting-started-step-by-step/index.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react';
import fs from 'fs';

import { getLayout } from '~/components/Sidebar';
import Head from 'next/head';
import { Headline1 } from '~/components/Headlines';
import matter from 'gray-matter';
import StyledMarkdown from '~/components/StyledMarkdown';
import { SectionContext } from '~/context';
import { DocsHelp } from '~/components/DocsHelp';
import GettingStarted from '~/components/GettingStarted';

export async function getStaticProps() {
const block1 = fs.readFileSync(
'pages/learn/getting-started-step-by-step/getting-started-step-by-step.md',
'utf-8',
);
const block2 = fs.readFileSync(
'pages/learn/getting-started-step-by-step/next-steps.md',
'utf-8',
);
const { content: block1Content } = matter(block1);
const { content: block2Content } = matter(block2);
return {
props: {
blocks: [block1Content, block2Content],
},
};
}

export default function StyledValidator({ blocks }: { blocks: any[] }) {
const newTitle = 'Creating your first schema';

return (
<SectionContext.Provider value='docs'>
<Head>
<title>{newTitle}</title>
</Head>
<Headline1>{newTitle}</Headline1>
<StyledMarkdown markdown={blocks[0]} />
<GettingStarted />
<StyledMarkdown markdown={blocks[1]} />
<DocsHelp />
</SectionContext.Provider>
);
}
StyledValidator.getLayout = getLayout;
12 changes: 12 additions & 0 deletions pages/learn/getting-started-step-by-step/next-steps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Getting Started Next Steps
section: docs
---

## What Next?

Now that you know how to create a JSON Schema and use it to validate JSON data, we'd invite you to continue your JSON Schema journey:
* Learn more about JSON Schema by visiting the [reference documentation](../understanding-json-schema).
* Explore the details of the current version of the Spec [2020-12](https://json-schema.org/specification).

If you already know how to create JSON Schemas and you are looking for different JSON Schema use cases like schema generation, code generation, documentation, UI generation or JSON Schema processing or conversion, please visit <userevent type='plausible-event-name=activation-explore-tools'>[Tools](https://json-schema.org/implementations)</userevent> and explore the amazing tooling available in the JSON Schema Ecosystem.
Loading
Loading