Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* [schema] Add a new way to traverse/prepare schema and basic validation infrastructure * [base] Expose validation groups on result of createSchema * [default-layout] Go into 'failure mode' and display schema errors if any * [test-studio] Remove object without fields test case as its now a hard error * [code-input] Fix schema warning * [default-layout] Styling the schema error screen * [schema] Clean up help ids * [schema] Error message improvements + reserve a few more type names * [schema] More help-id cleanup * [schema] Register reference validator
- Loading branch information
Showing
78 changed files
with
1,060 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import MdError from 'react-icons/lib/md/error' | ||
|
||
export default MdError |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import MdWarning from 'react-icons/lib/md/warning' | ||
|
||
export default MdWarning |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
packages/@sanity/default-layout/src/components/SchemaErrorReporter.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import schema from 'part:@sanity/base/schema' | ||
import {SchemaErrors} from './SchemaErrors' | ||
|
||
function renderPath(path) { | ||
return path.map(segment => { | ||
if (segment.kind === 'type') { | ||
return `${segment.name || '<unnamed>'}(${segment.type})` | ||
} | ||
if (segment.kind === 'property') { | ||
return segment.name | ||
} | ||
if (segment.kind === 'type') { | ||
return `${segment.type}(${segment.name || '<unnamed>'})` | ||
} | ||
return null | ||
}) | ||
.filter(Boolean) | ||
.join(' > ') | ||
} | ||
|
||
function reportWarnings() { | ||
if (!__DEV__) { | ||
return | ||
} | ||
/* eslint-disable no-console */ | ||
const problemGroups = schema._validation | ||
|
||
const groupsWithWarnings = problemGroups | ||
.filter(group => group.problems | ||
.some(problem => problem.severity === 'warning')) | ||
if (groupsWithWarnings.length === 0) { | ||
return | ||
} | ||
console.groupCollapsed(`⚠️ Schema has ${groupsWithWarnings.length} warnings`) | ||
groupsWithWarnings.forEach((group, i) => { | ||
const path = renderPath(group.path) | ||
console.group(`%cAt ${path}`, 'color: #FF7636') | ||
group.problems.forEach((problem, j) => { | ||
console.log(problem.message) | ||
}) | ||
console.groupEnd(`At ${path}`) | ||
}) | ||
console.groupEnd('Schema warnings') | ||
/* eslint-enable no-console */ | ||
} | ||
|
||
export class SchemaErrorReporter extends React.Component { | ||
componentDidMount = reportWarnings | ||
render() { | ||
const problemGroups = schema._validation | ||
|
||
const groupsWithErrors = problemGroups | ||
.filter(group => group.problems | ||
.some(problem => problem.severity === 'error')) | ||
|
||
if (groupsWithErrors.length > 0) { | ||
return ( | ||
<SchemaErrors problemGroups={groupsWithErrors} /> | ||
) | ||
} | ||
|
||
return this.props.children() | ||
} | ||
} | ||
|
||
SchemaErrorReporter.propTypes = { | ||
children: PropTypes.func | ||
} |
86 changes: 86 additions & 0 deletions
86
packages/@sanity/default-layout/src/components/SchemaErrors.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import React from 'react' | ||
import styles from './styles/SchemaErrors.css' | ||
import ErrorIcon from 'part:@sanity/base/error-icon' | ||
import WarningIcon from 'part:@sanity/base/warning-icon' | ||
import generateHelpUrl from '../../../generate-help-url' | ||
|
||
function renderPath(path) { | ||
return path.map(segment => { | ||
if (segment.kind === 'type') { | ||
return ( | ||
<span className={styles.segment}> | ||
<span key="name" className={styles.pathSegmentTypeName}>{segment.name}</span> | ||
 <span key="type" className={styles.pathSegmentTypeType}>{segment.type}</span> | ||
</span> | ||
) | ||
} | ||
if (segment.kind === 'property') { | ||
return ( | ||
<span className={styles.segment}> | ||
<span className={styles.pathSegmentProperty}>{segment.name}</span> | ||
</span> | ||
) | ||
} | ||
if (segment.kind === 'type') { | ||
return ( | ||
<span className={styles.segment}> | ||
<span key="name" className={styles.pathSegmentTypeName}>{segment.name}</span> | ||
<span key="type" className={styles.pathSegmentTypeType}>{segment.type}</span> | ||
</span> | ||
) | ||
} | ||
return null | ||
}) | ||
.filter(Boolean) | ||
} | ||
|
||
|
||
export function SchemaErrors(props) { | ||
const {problemGroups} = props | ||
return ( | ||
<div className={styles.root}> | ||
<h2 className={styles.title}>Uh oh… found errors in schema</h2> | ||
<ul className={styles.list}> | ||
{problemGroups.map((group, i) => { | ||
return ( | ||
<li key={i} className={styles.listItem}> | ||
<h2 className={styles.path}> | ||
{renderPath(group.path)} | ||
</h2> | ||
<ul className={styles.problems}> | ||
{group.problems.map((problem, j) => ( | ||
<li key={j} className={styles[`problem_${problem.severity}`]}> | ||
<div className={styles.problemSeverity}> | ||
<span className={styles.problemSeverityIcon}> | ||
{problem.severity === 'error' && <ErrorIcon />} | ||
{problem.severity === 'warning' && <WarningIcon />} | ||
</span> | ||
<span className={styles.problemSeverityText}> | ||
{problem.severity} | ||
</span> | ||
</div> | ||
<div className={styles.problemContent}> | ||
<div className={styles.problemMessage}> | ||
{problem.message} | ||
</div> | ||
{problem.helpId && ( | ||
<a | ||
className={styles.problemLink} | ||
href={generateHelpUrl(problem.helpId)} | ||
target="_blank" | ||
> | ||
View documentation | ||
</a> | ||
)} | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
</li> | ||
) | ||
})} | ||
</ul> | ||
</div> | ||
|
||
) | ||
} |
128 changes: 128 additions & 0 deletions
128
packages/@sanity/default-layout/src/components/styles/SchemaErrors.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
@import "part:@sanity/base/theme/variables-style"; | ||
|
||
.root { | ||
display: block; | ||
height: 100vh; | ||
width: 100vw; | ||
overflow-y: auto; | ||
color: var(--body-text); | ||
} | ||
|
||
.title { | ||
margin: 0; | ||
background-color: var(--state-danger-color); | ||
font-size: var(--font-size-large); | ||
padding: var(--large-padding); | ||
color: var(--state-danger-color--text); | ||
} | ||
|
||
.list { | ||
display: block; | ||
margin: 0; | ||
padding: 0; | ||
padding: var(--large-padding); | ||
} | ||
|
||
.path { | ||
font-size: var(--font-size-large); | ||
word-spacing: -0.25em; | ||
} | ||
|
||
.segment { | ||
@nest &:not(:last-child)::after { | ||
padding: 0 0.5em; | ||
content: '➝'; | ||
} | ||
} | ||
|
||
.problems { | ||
display: block; | ||
margin: 0; | ||
padding: 0; | ||
} | ||
|
||
.problem { | ||
display: flex; | ||
margin: 0; | ||
padding: 0; | ||
color: var(--body-text); | ||
font-size: var(--font-size-xsmall); | ||
margin-bottom: var(--medium-padding); | ||
} | ||
|
||
.problemSeverity { | ||
padding: 1em; | ||
margin-right: 1em; | ||
min-width: 4em; | ||
text-align: center; | ||
} | ||
|
||
.problemSeverityIcon { | ||
display: block; | ||
font-size: 2em; | ||
} | ||
|
||
.problemSeverityText { | ||
display: block; | ||
font-size: var(--font-size-tiny); | ||
margin: 1em 0; | ||
font-weight: 700; | ||
text-transform: uppercase; | ||
} | ||
|
||
.problemLink { | ||
clear: both; | ||
margin: 1em 0; | ||
display: inline-block; | ||
color: var(--body-text); | ||
|
||
@nest &:hover { | ||
color: var(--brand-primary); | ||
} | ||
} | ||
|
||
.problemMessage { | ||
padding-top: 0.5em; | ||
font-family: var(--font-family-monospace); | ||
} | ||
|
||
.problem_error { | ||
composes: problem; | ||
color: var(--state-danger-color); | ||
|
||
@nest & .problemSeverity { | ||
color: var(--state-danger-color); | ||
border-right: 2px solid var(--state-danger-color); | ||
} | ||
} | ||
|
||
.problem_warning { | ||
composes: problem; | ||
|
||
@nest & .problemSeverity { | ||
color: var(--state-warning-color); | ||
border-right: 2px solid var(--state-warning-color); | ||
} | ||
} | ||
|
||
.listItem { | ||
display: block; | ||
padding: 0.5em 0; | ||
} | ||
|
||
.arrow { | ||
padding: 0 0.5em; | ||
} | ||
|
||
.pathSegmentTypeName { | ||
font-weight: 700; | ||
} | ||
|
||
.pathSegmentTypeType { | ||
font-weight: 300; | ||
font-size: var(--font-size-small); | ||
} | ||
|
||
.pathSegmentProperty { | ||
font-weight: 300; | ||
} |
Oops, something went wrong.