Skip to content

Commit

Permalink
Feat: Rebuilding getting started component (#687)
Browse files Browse the repository at this point in the history
* adding componet

* adding data

* connecting with data

* Pushed data changes

* Fix:getting started data fetching problem

* updating component rendering

* adjusting layout

* update: changing interating logics

* update: changing file location

* fix: minor fixes

* schema data fetching

* fixing workflow

* adding fetch testing

* replacing code editor

* feat: enabling instnaces and moving to new component

* fix: state rendering problem solved

* feat:adding text and icons

* fix: instances fix

* fixing text alignment

* fix: instances fix

* Refactoring and improvements

* removing some codes

* Refactoring component and bug fixes

* Add plausible events

* Update package.json

* adding better messaging

---------

Co-authored-by: Benjamin Granados <[email protected]>
  • Loading branch information
DhairyaMajmudar and benjagm authored Jun 24, 2024
1 parent e796a69 commit 6b7e5e7
Show file tree
Hide file tree
Showing 12 changed files with 453 additions and 23 deletions.
221 changes: 221 additions & 0 deletions components/GettingStarted.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import React, { useState, useEffect } from 'react';
import { atomOneDark } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import Highlight from 'react-syntax-highlighter';

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,
);

console.log(defaultInstanceData);

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);
},
);
}, []);

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 schemaData = await schemaResponse.json();
setFetchedSchema(schemaData);
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,
);

if (selectedInstance) {
const instanceResponse = await fetch(e.target.value);
const instanceData = await instanceResponse.json();
setFetchedInstance(instanceData);
setDetails([selectedInstance.details, selectedInstance.valid]);
} else {
setFetchedInstance(null!);
}
};

return (
<>
<div className='flex flex-col'>
<div className='flex items-end flex-row justify-between mt-5 mb-3 '>
<h2 className='text-h5 font-semibold mb-1'>JSON Schema</h2>
<div className='select-wrap'>
<label className='mr-2'>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-h5 font-semibold mb-1'>JSON Instance</h2>
<div className='select-wrap'>
<label className='mr-2'>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-h5 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>
</>
);
};

export default GettingStarted;
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 and select 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.
38 changes: 38 additions & 0 deletions public/data/getting-started-examples.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[
{
"name": "Getting started basic schema",
"default": true,
"file": "/data/getting-started-examples/schemas/default.json",
"instances": [
{
"name": "Valid instance",
"default": true,
"valid": true,
"file": "/data/getting-started-examples/instances/default-ok.json",
"details": "This is a valid JSON instance for the provided JSON Schema"
},
{
"name": "Invalid instance",
"default": false,
"valid": false,
"file": "/data/getting-started-examples/instances/default-ko.json",
"details": "Invalid: The value of 'price' property must be a number"
}
]
},

{
"name": "Getting started extended schema",
"default": false,
"file": "/data/getting-started-examples/schemas/default-extended.json",
"instances": [
{
"name": "Valid instance",
"default": true,
"valid": true,
"file": "/data/getting-started-examples/instances/default-extended-ok.json",
"details": "This is a valid JSON instance for the provided JSON Schema"
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"productId": 1,
"productName": "An ice sculpture",
"price": 12.5,
"tags": ["cold", "ice"],
"dimensions": {
"length": 7.0,
"width": 12.0,
"height": 9.5
},
"warehouseLocation": {
"latitude": -78.75,
"longitude": 20.4
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"productId": 1,
"product": "An ice sculpture",
"price": "100"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"productId": 1,
"productName": "An ice sculpture",
"price": 12.5,
"tags": ["cold", "ice"]
}
Loading

0 comments on commit 6b7e5e7

Please sign in to comment.