import { last } from 'lodash' ; import { i18n } from '@osd/i18n' ; import { htmlIdGenerator } from '@elastic/eui' ; import { parseRange , NumberListRange } from './range' ; import { NumberRowModel } from './number_row' ; const EMPTY_STRING = '' ; const defaultRange = parseRange ( '[0,Infinity)' ) ; const generateId = htmlIdGenerator ( ) ; const defaultModel = { value : 0 , id : generateId ( ) , isInvalid : false } ; function parse ( value ) { const parsedValue = parseFloat ( value ) ; return isNaN ( parsedValue ) ? EMPTY_STRING : parsedValue ; } function getRange ( range ? ) { try { return range ? parseRange ( range ) : defaultRange ; } catch ( e ) { throw new TypeError ( 'Unable to parse range: ' + e . message ) ; } } function validateValue ( value , numberRange ) { const result = { isInvalid : false , } ; if ( value === EMPTY_STRING ) { result . isInvalid = true ; result . error = EMPTY_STRING ; } else if ( ! numberRange . within ( value ) ) { result . isInvalid = true ; result . error = i18n . translate ( 'visDefaultEditor.controls.numberList.invalidRangeErrorMessage' , { defaultMessage : 'The value should be in the range of {min} to {max}.' , values : { min : numberRange . min , max : numberRange . max } , } ) ; } return result ; } function validateValueAscending ( inputValue , index , list ) { const result = { isInvalidOrder : false , } ; const previousModel = list [ index - 1 ] ; if ( previousModel !== undefined && inputValue !== undefined && inputValue <= previousModel ) { result . isInvalidOrder = true ; result . error = i18n . translate ( 'visDefaultEditor.controls.numberList.invalidAscOrderErrorMessage' , { defaultMessage : 'Value is not in ascending order.' , } ) ; } return result ; } function validateValueUnique ( inputValue , index , list ) { const result = { isDuplicate : false , } ; if ( inputValue !== EMPTY_STRING && list . indexOf ( inputValue ) !== index ) { result . isDuplicate = true ; result . error = i18n . translate ( 'visDefaultEditor.controls.numberList.duplicateValueErrorMessage' , { defaultMessage : 'Duplicate value.' , } ) ; } return result ; } function getNextModel ( list , range ) { const lastValue = ( last ( list ) as NumberRowModel ) . value ; let next = Number ( lastValue ) ? Number ( lastValue ) + 1 : 1 ; if ( next >= range . max ) { next = range . max - 1 ; } return { id : generateId ( ) , value : next , isInvalid : false , } ; } function getInitModelList ( list ) { return list . length ? list . map ( ( num ) => ( { value : ( num === undefined ? EMPTY_STRING : num ) as NumberRowModel [ 'value' ] , id : generateId ( ) , isInvalid : false , } ) ) : [ defaultModel ] ; } function getValidatedModels ( numberList , modelList , numberRange , validateAscendingOrder = false , disallowDuplicates = false ) { if ( ! numberList . length ) { return [ defaultModel ] ; } return numberList . map ( ( number , index ) => { const model = modelList [ index ] || { id : generateId ( ) } ; const newValue = number === undefined ? EMPTY_STRING : number ; const valueResult = numberRange ? validateValue ( newValue , numberRange ) : { isInvalid : false } ; const ascendingResult = validateAscendingOrder ? validateValueAscending ( newValue , index , numberList ) : { isInvalidOrder : false } ; const duplicationResult = disallowDuplicates ? validateValueUnique ( newValue , index , numberList ) : { isDuplicate : false } ; const allErrors = [ valueResult . error , ascendingResult . error , duplicationResult . error ] . filter ( Boolean ) . join ( ' ' ) ; return { ... model , value : newValue , isInvalid : valueResult . isInvalid || ascendingResult . isInvalidOrder || duplicationResult . isDuplicate , error : allErrors === EMPTY_STRING ? undefined : allErrors , } ; } ) ; } function hasInvalidValues ( modelList ) { return ! ! modelList . find ( ( { isInvalid } ) => isInvalid ) ; } export { EMPTY_STRING , parse , getRange , validateValue , getNextModel , getInitModelList , getValidatedModels , hasInvalidValues , } ;