Skip to content

Commit

Permalink
[components] Refactor and improve validation components
Browse files Browse the repository at this point in the history
  • Loading branch information
mariuslundgard authored and rexxars committed Oct 6, 2020
1 parent 352d6f1 commit 5ec8e03
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 308 deletions.
142 changes: 69 additions & 73 deletions packages/@sanity/components/src/validation/ValidationList.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,90 @@
import React from 'react'
import {Path} from '@sanity/types'
import React, {useCallback} from 'react'
import {ObjectSchemaType, Path} from '@sanity/types'
import {Marker} from '../types'
import ValidationListItem from './ValidationListItem'

import styles from './ValidationList.css'

type Props = {
kind?: string
interface ValidationListProps {
documentType?: ObjectSchemaType
kind?: 'simple'
markers: Marker[]
onFocus?: (path: Path) => void
onClose?: () => void
showLink?: boolean
// showLink?: boolean
truncate?: boolean
documentType?: {
fields: {
name: string
type: {
title: string
}
}[]
}
markers: Marker[]
}

// @todo: refactor to functional component
export default class ValidationList extends React.PureComponent<Props> {
static defaultProps = {
markers: [],
documentType: null,
onClose: () => undefined,
showLink: false,
onFocus: () => undefined
}
function ValidationList(props: ValidationListProps) {
const {
documentType,
kind,
markers,
onFocus,
onClose,
truncate
// showLink,
} = props

handleClick = (path: Path = []) => {
const {onFocus, onClose} = this.props
const validation = markers.filter(marker => marker.type === 'validation')
const errors = validation.filter(marker => marker.level === 'error')
const warnings = validation.filter(marker => marker.level === 'warning')

if (onFocus) onFocus(path)
if (onClose) onClose()
}
const handleClick = useCallback(
(path: Path = []) => {
if (onFocus) onFocus(path)
if (onClose) onClose()
},
[onFocus, onClose]
)

resolvePathTitle(path: Path) {
const type = this.props.documentType
const fields = type && type.fields
const resolvePathTitle = (path: Path) => {
const fields = documentType && documentType.fields
const field = fields && fields.find(curr => curr.name === path[0])

return field ? field.type.title : ''
return (field && field.type.title) || ''
}

render() {
const {kind, markers, showLink, truncate} = this.props
const validation = markers.filter(marker => marker.type === 'validation')
const errors = validation.filter(marker => marker.level === 'error')
const warnings = validation.filter(marker => marker.level === 'warning')
const hasErrors = errors.length > 0
const hasWarnings = warnings.length > 0

if (errors.length === 0 && warnings.length === 0) {
return <div />
}
if (!hasErrors && !hasWarnings) {
return null
}

return (
<ul className={styles.root} data-kind={kind}>
{errors.length > 0 &&
errors.map((error, i) => (
// eslint-disable-next-line react/no-array-index-key
<li className={styles.item} key={i}>
<ValidationListItem
kind={kind}
truncate={truncate}
path={this.resolvePathTitle(error.path)}
marker={error}
onClick={this.handleClick}
showLink={showLink}
/>
</li>
))}
return (
<ul className={styles.root} data-kind={kind}>
{hasErrors &&
errors.map((error, i) => (
// eslint-disable-next-line react/no-array-index-key
<li className={styles.item} key={i}>
<ValidationListItem
kind={kind}
truncate={truncate}
path={resolvePathTitle(error.path)}
marker={error}
onClick={handleClick}
// showLink={showLink}
/>
</li>
))}

{warnings.length > 0 &&
warnings.map((warning, i) => (
// eslint-disable-next-line react/no-array-index-key
<li className={styles.item} key={i}>
<ValidationListItem
kind={kind}
truncate={truncate}
path={this.resolvePathTitle(warning.path)}
marker={warning}
onClick={this.handleClick}
showLink={showLink}
/>
</li>
))}
</ul>
)
}
{hasWarnings &&
warnings.map((warning, i) => (
// eslint-disable-next-line react/no-array-index-key
<li className={styles.item} key={i}>
<ValidationListItem
kind={kind}
truncate={truncate}
path={resolvePathTitle(warning.path)}
marker={warning}
onClick={handleClick}
// showLink={showLink}
/>
</li>
))}
</ul>
)
}

export default ValidationList
37 changes: 17 additions & 20 deletions packages/@sanity/components/src/validation/ValidationListItem.css
Original file line number Diff line number Diff line change
@@ -1,49 +1,46 @@
@import 'part:@sanity/base/theme/variables-style';

.item {
.root {
display: flex;
margin: 0;
flex-grow: 1;
width: 100%;
cursor: pointer;
box-sizing: border-box;
outline: none;
color: inherit;
padding: var(--medium-padding);
line-height: 0;
}

.item[data-item-type='simple'] {
.root[data-item-type='simple'] {
user-select: none;
cursor: unset;
padding: var(--extra-small-padding) var(--medium-padding);
border: 0;

@nest & .message {
color: var(--text-color);
}
}

.item.error {
.root.error {
@nest & .icon {
color: var(--state-danger-color);
}
}

.item.warning {
.root.warning {
@nest & .icon {
color: var(--state-warning-color);
}
}

.interactiveItem {
composes: item;
.interactive {
composes: root;
cursor: pointer;

@nest &.error:not([data-item-type='simple']):hover {
@nest &.error:not([data-item-type='simple']):hover, &.error:not([data-item-type='simple']):focus {
background-color: color(var(--state-danger-color) a(10%));
}

@nest &.warning:not([data-item-type='simple']):hover, &:focus {
@nest &.warning:not([data-item-type='simple']):hover,
&.warning:not([data-item-type='simple']):focus {
background-color: color(var(--state-warning-color) a(10%));
}
}
Expand All @@ -64,15 +61,9 @@

.content {
flex-grow: 1;
min-width: 0;
padding-left: var(--small-padding);
margin: -3px 0 -2px;

@nest .truncate & {
padding-top: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

.path {
Expand All @@ -89,4 +80,10 @@
@nest .path + & {
margin-top: calc(var(--extra-small-padding) / 2);
}

@nest .truncate & {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}

0 comments on commit 5ec8e03

Please sign in to comment.