Skip to content

Commit

Permalink
refactor: move validator logic to utils
Browse files Browse the repository at this point in the history
  • Loading branch information
Aidosmf committed Sep 18, 2024
1 parent a41b1f3 commit 632f665
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 117 deletions.
209 changes: 92 additions & 117 deletions src/pages/validator.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import * as React from "react"
import { useState, useRef } from "react"

import Ajv from "ajv/dist/2020"

import Container from "react-bootstrap/Container"
import Row from "react-bootstrap/Row"
import Col from "react-bootstrap/Col"
Expand All @@ -19,8 +17,8 @@ import Alert from "react-bootstrap/Alert"
import Layout from "../components/layout"
import Seo from "../components/seo"

import lottieSchema from "../assets/lottie.schema.json"
import { isValidUrl } from "../utils/helpers"
import { validateLottieString } from "../utils/validator"

const content = {
title: "Lottie Validator",
Expand Down Expand Up @@ -53,91 +51,72 @@ const ValidatorPage = () => {
const [warningProperty, setWarningProperty] = useState(false)
const [warningType, setWarningType] = useState(false)

// validator

const ajv = new Ajv({
keywords: [{ keyword: "$version" }],
})

const validateLottieString = lottieStr => {
if (!lottieStr) {
setErrorMessage("Lottie cannot be empty")
return
}

if (typeof lottieStr !== "string") {
setErrorMessage("Lottie must be a string")
return
}
// handlers

const validateLottie = lottieStr => {
setLoading(true)
setLottie(lottieStr)

try {
const validate = ajv.compile(lottieSchema)
const lottieJSON = JSON.parse(lottieStr)
const isValid = validate(lottieJSON)

if (!isValid) setValidationErrors(validate.errors)
const result = validateLottieString(lottieStr)
setValidationErrors(result)
} catch (e) {
setErrorMessage(`Could not validate Lottie JSON: ${e.message}`)
setErrorMessage(e.message)
}

setLoading(false)
}

// handlers

const validateLottieUrl = url => {
if (!url) {
const validateLottieUrl = () => {
if (!lottieUrl) {
setErrorMessage("Lottie URL cannot be empty")
return
}

if (!isValidUrl(url)) {
if (!isValidUrl(lottieUrl)) {
setErrorMessage("Invalid Lottie URL")
return
}

setLoading(true)

fetch(url)
fetch(lottieUrl)
.then(result => result.text())
.then(validateLottieString)
.then(validateLottie)
.catch(e =>
setErrorMessage(`Could not load Lottie file from URL: ${e.message}`)
)
.finally(() => setLoading(false))
}

const validateLottieFile = file => {
if (!file) {
const validateLottieFile = () => {
if (!lottieFile) {
setErrorMessage("Lottie File cannot be empty")
return
}

setLoading(true)

const reader = new FileReader()
reader.onload = e => validateLottieString(e.target.result)
reader.onload = e => validateLottie(e.target.result)
reader.onerror = _e => setErrorMessage("Could not load file")
reader.readAsText(file)
reader.readAsText(lottieFile)

setLoading(false)
}

const validateLottieText = text => {
if (!text) {
const validateLottieText = () => {
if (!lottieText) {
setErrorMessage("Lottie text cannot be empty")
return
}

if (typeof text !== "string") {
if (typeof lottieText !== "string") {
setErrorMessage("Lottie text must be a string")
return
}

validateLottieString(text)
validateLottie(lottieText)
}

// ui handlers
Expand All @@ -159,13 +138,13 @@ const ValidatorPage = () => {
const onValidateBtnClick = () => {
switch (currentTab) {
case "url":
validateLottieUrl(lottieUrl)
validateLottieUrl()
break
case "file":
validateLottieFile(lottieFile)
validateLottieFile()
break
case "text":
validateLottieText(lottieText)
validateLottieText()
break
default:
break
Expand All @@ -185,83 +164,79 @@ const ValidatorPage = () => {
</Container>
</section>
<Container className="py-5 mb-5 position-relative">
{lottieSchema && (
<Row>
<Col md={8} className="mb-3">
<Tabs
defaultActiveKey={currentTab}
id="justify-tab-example"
justify
onSelect={onTabsSelect}
>
<Tab eventKey="url" title="URL" className={tabCssClass}>
<Row>
<Col md={8} className="mb-3">
<Tabs
defaultActiveKey={currentTab}
id="justify-tab-example"
justify
onSelect={onTabsSelect}
>
<Tab eventKey="url" title="URL" className={tabCssClass}>
<Form.Control
aria-label="Example text with button addon"
aria-describedby="basic-addon1"
placeholder="Paste Lottie JSON URL"
onChange={e => setLottieUrl(e.target.value)}
/>
</Tab>
<Tab eventKey="file" title="File" className={tabCssClass}>
<Form.Group controlId="formFileLg">
<Form.Control
aria-label="Example text with button addon"
aria-describedby="basic-addon1"
placeholder="Paste Lottie JSON URL"
onChange={e => setLottieUrl(e.target.value)}
type="file"
accept="application/JSON"
ref={lottieFileInputRef}
onChange={e => setLottieFile(e.target.files[0])}
/>
</Tab>
<Tab eventKey="file" title="File" className={tabCssClass}>
<Form.Group controlId="formFileLg">
<Form.Control
type="file"
accept="application/JSON"
ref={lottieFileInputRef}
onChange={e => setLottieFile(e.target.files[0])}
/>
</Form.Group>
</Tab>
<Tab eventKey="text" title="Text" className={tabCssClass}>
<FloatingLabel
controlId="floatingTextarea"
label="Lottie JSON text"
>
<Form.Control
as="textarea"
placeholder="Paste Lottie JSON text"
style={{ height: "100px" }}
onChange={e => setLottieText(e.target.value)}
/>
</FloatingLabel>
</Tab>
</Tabs>
</Col>
<Col md={4} className="mb-3">
<h6 className="pt-2">Options</h6>
<div className="mb-2">
<Form.Check
inline
label="Warn about unknown object types"
name="check-warning-type"
type="checkbox"
id="check-warning-type"
onChange={e => onWarningTypeChange(e.currentTarget.checked)}
/>
<Form.Check
inline
label="Warn about unknown properties"
name="check-warning-property"
type="checkbox"
id="check-warning-property"
onChange={e =>
onWarningPropertyChange(e.currentTarget.checked)
}
/>
</div>
<ButtonGroup aria-label="valiate buttons" size="sm">
<Button onClick={onValidateBtnClick}>validate</Button>
<Button
variant="outline-primary"
onClick={resetStates}
disabled={!validationErrors && !errorMessage}
</Form.Group>
</Tab>
<Tab eventKey="text" title="Text" className={tabCssClass}>
<FloatingLabel
controlId="floatingTextarea"
label="Lottie JSON text"
>
reset
</Button>
</ButtonGroup>
</Col>
</Row>
)}
<Form.Control
as="textarea"
placeholder="Paste Lottie JSON text"
style={{ height: "100px" }}
onChange={e => setLottieText(e.target.value)}
/>
</FloatingLabel>
</Tab>
</Tabs>
</Col>
<Col md={4} className="mb-3">
<h6 className="pt-2">Options</h6>
<div className="mb-2">
<Form.Check
inline
label="Warn about unknown object types"
name="check-warning-type"
type="checkbox"
id="check-warning-type"
onChange={e => onWarningTypeChange(e.currentTarget.checked)}
/>
<Form.Check
inline
label="Warn about unknown properties"
name="check-warning-property"
type="checkbox"
id="check-warning-property"
onChange={e => onWarningPropertyChange(e.currentTarget.checked)}
/>
</div>
<ButtonGroup aria-label="valiate buttons" size="sm">
<Button onClick={onValidateBtnClick}>validate</Button>
<Button
variant="outline-primary"
onClick={resetStates}
disabled={!validationErrors && !errorMessage}
>
reset
</Button>
</ButtonGroup>
</Col>
</Row>
<Row>
<Col>
{loading && (
Expand Down
30 changes: 30 additions & 0 deletions src/utils/validator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Ajv from "ajv/dist/2020"
import lottieSchema from "../assets/lottie.schema.json"

const ajv = new Ajv({
keywords: [{ keyword: "$version" }],
})

export const validateLottieString = lottieStr => {
if (!lottieStr) {
throw new Error("Lottie cannot be empty")
}

if (typeof lottieStr !== "string") {
throw new Error("Lottie must be a string")
}

try {
const validate = ajv.compile(lottieSchema)
const lottieJSON = JSON.parse(lottieStr)
const isValid = validate(lottieJSON)

if (isValid) {
return []
} else {
return validate.errors
}
} catch (e) {
throw new Error(`Could not validate Lottie JSON: ${e.message}`)
}
}

0 comments on commit 632f665

Please sign in to comment.