Adding property validators
This commit is contained in:
parent
b7a14ac838
commit
6383d79ecf
4 changed files with 51 additions and 5 deletions
|
@ -29,6 +29,24 @@ const PropertyValueElement = (props:Props): JSX.Element => {
|
||||||
const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, propertyTemplate)
|
const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, propertyTemplate)
|
||||||
const finalDisplayValue = displayValue || emptyDisplayValue
|
const finalDisplayValue = displayValue || emptyDisplayValue
|
||||||
|
|
||||||
|
const validateProp = (propType: string, val: string): boolean => {
|
||||||
|
if (val === '') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
switch (propType) {
|
||||||
|
case 'number':
|
||||||
|
return !isNaN(parseInt(val, 10))
|
||||||
|
case 'email': {
|
||||||
|
const emailRegexp = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||||
|
return emailRegexp.test(val.toLowerCase())
|
||||||
|
}
|
||||||
|
case 'text':
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (propertyTemplate.type === 'select') {
|
if (propertyTemplate.type === 'select') {
|
||||||
let propertyColorCssClassName = ''
|
let propertyColorCssClassName = ''
|
||||||
const cardPropertyValue = propertyTemplate.options.find((o) => o.id === propertyValue)
|
const cardPropertyValue = propertyTemplate.options.find((o) => o.id === propertyValue)
|
||||||
|
@ -85,6 +103,7 @@ const PropertyValueElement = (props:Props): JSX.Element => {
|
||||||
onChange={setValue}
|
onChange={setValue}
|
||||||
onSave={() => mutator.changePropertyValue(card, propertyTemplate.id, value)}
|
onSave={() => mutator.changePropertyValue(card, propertyTemplate.id, value)}
|
||||||
onCancel={() => setValue(propertyValue)}
|
onCancel={() => setValue(propertyValue)}
|
||||||
|
validator={(value) => validateProp(propertyTemplate.type, value)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
--button-bg: 22, 109, 204;
|
--button-bg: 22, 109, 204;
|
||||||
--link-color: 35, 137, 215;
|
--link-color: 35, 137, 215;
|
||||||
--link-visited-color: #551a8b;
|
--link-visited-color: #551a8b;
|
||||||
|
--error-color: #ffa9a9;
|
||||||
|
|
||||||
// Label Colors
|
// Label Colors
|
||||||
--prop-default: #fff;
|
--prop-default: #fff;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
border: 0;
|
border: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
border: 1px solid transparent;
|
||||||
&.active {
|
&.active {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
@ -10,4 +11,8 @@
|
||||||
color: rgba(var(--body-color), 0.4);
|
color: rgba(var(--body-color), 0.4);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
&.error {
|
||||||
|
border: 1px solid var(--error-color);
|
||||||
|
border-radius: var(--default-rad);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ type Props = {
|
||||||
saveOnEsc?: boolean
|
saveOnEsc?: boolean
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
|
|
||||||
|
validator?: (value: string) => boolean
|
||||||
onCancel?: () => void
|
onCancel?: () => void
|
||||||
onSave?: (saveType: 'onEnter'|'onEsc'|'onBlur') => void
|
onSave?: (saveType: 'onEnter'|'onEsc'|'onBlur') => void
|
||||||
}
|
}
|
||||||
|
@ -24,6 +25,22 @@ export default class Editable extends React.Component<Props> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
save = (saveType: 'onEnter'|'onEsc'|'onBlur'): void => {
|
||||||
|
if (this.props.validator && !this.props.validator(this.props.value || '')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!this.props.onSave) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (saveType === 'onBlur' && !this.saveOnBlur) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (saveType === 'onEsc' && !this.props.saveOnEsc) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.props.onSave(saveType)
|
||||||
|
}
|
||||||
|
|
||||||
public focus(selectAll = false): void {
|
public focus(selectAll = false): void {
|
||||||
if (this.elementRef.current) {
|
if (this.elementRef.current) {
|
||||||
const valueLength = this.elementRef.current.value.length
|
const valueLength = this.elementRef.current.value.length
|
||||||
|
@ -44,30 +61,34 @@ export default class Editable extends React.Component<Props> {
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
const {value, onChange, className, placeholderText} = this.props
|
const {value, onChange, className, placeholderText} = this.props
|
||||||
|
let error = false
|
||||||
|
if (this.props.validator) {
|
||||||
|
error = !this.props.validator(value || '')
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
ref={this.elementRef}
|
ref={this.elementRef}
|
||||||
className={'Editable ' + className}
|
className={'Editable ' + (error ? 'error ' : '') + className}
|
||||||
placeholder={placeholderText}
|
placeholder={placeholderText}
|
||||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
onChange(e.target.value)
|
onChange(e.target.value)
|
||||||
}}
|
}}
|
||||||
value={value}
|
value={value}
|
||||||
title={value}
|
title={value}
|
||||||
onBlur={() => this.saveOnBlur && this.props.onSave && this.props.onSave('onBlur')}
|
onBlur={() => this.save('onBlur')}
|
||||||
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>): void => {
|
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>): void => {
|
||||||
if (e.keyCode === 27 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // ESC
|
if (e.keyCode === 27 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // ESC
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
if (this.props.saveOnEsc) {
|
if (this.props.saveOnEsc) {
|
||||||
this.props.onSave?.('onEsc')
|
this.save('onEsc')
|
||||||
} else {
|
} else {
|
||||||
this.props.onCancel?.()
|
this.props.onCancel?.()
|
||||||
}
|
}
|
||||||
this.blur()
|
this.blur()
|
||||||
} else if (e.keyCode === 13 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // Return
|
} else if (e.keyCode === 13 && !(e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey) { // Return
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
this.props.onSave?.('onEnter')
|
this.save('onEnter')
|
||||||
this.blur()
|
this.blur()
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
Loading…
Reference in a new issue