Initial commit
This commit is contained in:
188
website/src/Validated/Validator.js
Normal file
188
website/src/Validated/Validator.js
Normal file
@@ -0,0 +1,188 @@
|
||||
import EventEmitter from 'eventemitter3'
|
||||
|
||||
const any = function(obj, pred) {
|
||||
for (let name in obj) {
|
||||
if (pred(obj[name])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export class Validator extends EventEmitter {
|
||||
constructor(originalObj, validations, onModifiedChanged) {
|
||||
super()
|
||||
this.updateValue = this.updateValue.bind(this)
|
||||
|
||||
this._id = originalObj._id
|
||||
this.onModifiedChanged = onModifiedChanged
|
||||
this.fields = {}
|
||||
this.nonValueFields = {}
|
||||
|
||||
for (let name in validations) {
|
||||
let validation = validations[name]
|
||||
let field = {
|
||||
isDisabled: this.normalize(validation.isDisabled, false),
|
||||
isReadOnly: this.normalize(validation.isReadOnly, false),
|
||||
isVisible: this.normalize(validation.isVisible, true),
|
||||
nonValue: validation.nonValue || false
|
||||
}
|
||||
|
||||
if (field.nonValue) {
|
||||
field.disabled = field.isDisabled(this)
|
||||
field.readOnly = field.isReadOnly(this)
|
||||
field.visible = field.isVisible(this)
|
||||
this.nonValueFields[name] = field
|
||||
} else {
|
||||
field.alwaysGet = validation.alwaysGet
|
||||
field.isValid = this.normalize(validation.isValid, true)
|
||||
field.initValue = (validation.initValue === undefined ? '' : validation.initValue)
|
||||
field.originalValue = Validator.getObjectValue(originalObj, name)
|
||||
this.updateFieldValue(field, field.originalValue || field.initValue)
|
||||
this.fields[name] = field
|
||||
}
|
||||
}
|
||||
|
||||
this.updateNonValueFields()
|
||||
}
|
||||
|
||||
normalize(obj, def) {
|
||||
return obj ? ((obj.constructor === Function) ? obj : () => (!!obj)) : () => (def)
|
||||
}
|
||||
|
||||
static stateSafeField(field) {
|
||||
return {
|
||||
value: field.value,
|
||||
modified: field.modified,
|
||||
valid: field.valid,
|
||||
disabled: field.disabled,
|
||||
readOnly: field.readOnly,
|
||||
visible: field.visible
|
||||
}
|
||||
}
|
||||
|
||||
updateValue(name, newValue) {
|
||||
let lastAnyModified = this.anyModified
|
||||
let field = this.fields[name]
|
||||
|
||||
if (field) {
|
||||
this.updateFieldValue(field, newValue)
|
||||
this.updateNonValueFields()
|
||||
if (lastAnyModified !== this.anyModified && this.onModifiedChanged) {
|
||||
this.onModifiedChanged(this.anyModified)
|
||||
}
|
||||
}
|
||||
|
||||
return Validator.stateSafeField(field)
|
||||
}
|
||||
|
||||
updateFieldValue(field, newValue) {
|
||||
field.value = newValue
|
||||
field.disabled = field.isDisabled(this)
|
||||
field.readOnly = field.isReadOnly(this)
|
||||
field.visible = field.isVisible(this)
|
||||
field.valid = field.isValid(this, newValue)
|
||||
field.modified =
|
||||
field.originalValue !== undefined ? (field.originalValue !== newValue) : (newValue !== field.initValue)
|
||||
|
||||
this.anyModified = field.modified || any(this.fields, (field) => (field.modified))
|
||||
this.allValid = !field.valid ? false : !any(this.fields, (field) => (!field.valid))
|
||||
}
|
||||
|
||||
updateNonValueFields() {
|
||||
for (let name in this.nonValueFields) {
|
||||
let field = this.nonValueFields[name]
|
||||
let disabled = field.isDisabled(this)
|
||||
let readOnly = field.isReadOnly(this)
|
||||
let visible = field.isVisible(this)
|
||||
let b = (disabled !== field.disabled || readOnly !== field.readOnly || visible !== field.visible)
|
||||
|
||||
field.disabled = disabled
|
||||
field.readOnly = readOnly
|
||||
field.visible = visible
|
||||
|
||||
if (b) {
|
||||
this.emit(name, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getField(name) {
|
||||
let field = this.fields[name] || this.nonValueFields[name]
|
||||
|
||||
if (!field) {
|
||||
throw new Error(`Field '${name}' does not have a validation entry`)
|
||||
}
|
||||
|
||||
return Validator.stateSafeField(field)
|
||||
}
|
||||
|
||||
getValues() {
|
||||
// Generate an object that has the modified and alwaysGet fields
|
||||
let obj = {}
|
||||
|
||||
if (!this.anyModified && !this.allValid) {
|
||||
return obj
|
||||
}
|
||||
|
||||
// Will have an _id if updating
|
||||
if (this._id) {
|
||||
obj._id = this._id
|
||||
}
|
||||
|
||||
for (let name in this.fields) {
|
||||
let field = this.fields[name]
|
||||
|
||||
if (field.alwaysGet || (!field.nonValue && field.modified)) {
|
||||
let value = field.value
|
||||
if (value && value.constructor === 'String') {
|
||||
value = value.trim()
|
||||
}
|
||||
Validator.setObjectValue(obj, name, value)
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
getOriginalValues() {
|
||||
// Generate an object that has the original values of all fields
|
||||
let obj = {}
|
||||
|
||||
if (this._id) {
|
||||
obj._id = this._id
|
||||
}
|
||||
|
||||
for (let name in this.fields) {
|
||||
let field = this.fields[name]
|
||||
|
||||
if (field.originalValue !== undefined) {
|
||||
Validator.setObjectValue(obj, name, field.originalValue)
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
static getObjectValue(obj, name) {
|
||||
name.split('.').forEach((namePart) => {
|
||||
if (obj) {
|
||||
obj = obj[namePart]
|
||||
}
|
||||
})
|
||||
return obj
|
||||
}
|
||||
|
||||
static setObjectValue(obj, name, value) {
|
||||
name.split('.').forEach((namePart, i, nameParts) => {
|
||||
if (i < nameParts.length - 1) {
|
||||
if (!obj[namePart]) {
|
||||
obj[namePart] = {}
|
||||
}
|
||||
obj = obj[namePart]
|
||||
} else {
|
||||
obj[namePart] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user