import React from 'react' ; import { types } from 'mobx-state-tree' ; import { observer } from 'mobx-react' ; import { MenuItem , Select , TextField , makeStyles } from '@material-ui/core' ; import MakeSpreadsheetColumnType from './MakeSpreadsheetColumnType' ; const OPERATIONS = [ 'equals' , 'greater than' , 'less than' , 'between' , 'not between' , ] ; const OPERATION_PREDICATES = { equals : ( numberInCell , firstNumber ) => { return numberInCell === firstNumber ; } , 'greater than' : ( numberInCell , firstNumber ) => { return numberInCell > firstNumber ; } , 'less than' : ( numberInCell , firstNumber ) => { return numberInCell < firstNumber ; } , between : ( numberInCell , firstNumber , secondNumber ) => { return numberInCell > firstNumber && numberInCell < secondNumber ; } , } ; OPERATION_PREDICATES [ 'not between' ] = ( numberInCell , firstNumber , secondNumber ) => { return ! OPERATION_PREDICATES . between ( numberInCell , firstNumber , secondNumber ) ; } ; const useStyles = makeStyles ( ( ) => { return { textFilterControlAdornment : { marginRight : '-18px' } , textFilterControl : { margin : [ [ 0 , 0 , 0 , '0.4rem' ] ] , '& .MuiInput-formControl' : { marginTop : 8 , } , '& .MuiInputLabel-formControl' : { top : '-7px' , '&.MuiInputLabel-shrink' : { top : '-3px' , } , } , } , } ; } ) ; const FilterReactComponent = observer ( ( { filterModel } ) => { const classes = useStyles ( ) ; const operationChoices = OPERATIONS ; return ( < > < Select value = { filterModel . operation } onChange = { event => { filterModel . setOperation ( String ( event . target . value ) ) ; } } > { operationChoices . map ( name => ( < MenuItem key = { name } value = { name } > { name } < /MenuItem>))} < /Select>{' '} < TextField label = "number" placeholder = "123" type = "number" error = { filterModel . firstNumberIsInvalid } defaultValue = { filterModel . firstNumber } onChange = { evt => { filterModel . setFirstNumber ( parseFloat ( evt . target . value ) ) ; } } className = { classes . textFilterControl } / > { filterModel . operation !== 'between' && filterModel . operation !== 'not between' ? null : ( < > { ' and ' } < TextField label = "number" placeholder = "456" type = "number" error = { filterModel . secondNumberIsInvalid } defaultValue = { filterModel . secondNumber } onChange = { evt => filterModel . setSecondNumber ( parseFloat ( evt . target . value ) ) } className = { classes . textFilterControl } / > < />)} < />); } ) ; const FilterModelType = types . model ( 'ColumnNumberFilter' , { type : types . literal ( 'Number' ) , columnNumber : types . integer , firstNumber : types . maybe ( types . number ) , secondNumber : types . maybe ( types . number ) , operation : types . optional ( types . enumeration ( OPERATIONS ) , OPERATIONS [ 0 ] ) , } ) . views ( self => ( { get predicate ( ) { if ( typeof self . firstNumber !== 'number' ) { return function alwaysTrue ( ) { return true ; } ; } const { firstNumber , secondNumber , operation , columnNumber } = self ; return function stringPredicate ( sheet , row ) { const { cellsWithDerived } = row ; const cell = cellsWithDerived [ columnNumber ] ; if ( ! cell || ! cell . text ) { return false ; } const parsedCellText = parseFloat ( cell . text ) ; if ( typeof parsedCellText !== 'number' ) { return false ; } const predicate = OPERATION_PREDICATES [ operation ] ; if ( ! predicate ) { throw new Error ( `"${ operation }" not implemented in location filter` ) ; } return predicate ( parsedCellText , firstNumber , secondNumber ) ; } ; } , } ) ) . actions ( self => ( { setFirstNumber ( n ) { if ( Number . isNaN ( n ) || typeof n !== 'number' ) { self . firstNumber = undefined ; } else { self . firstNumber = n ; } } , setSecondNumber ( n ) { if ( Number . isNaN ( n ) || typeof n !== 'number' ) { self . secondNumber = undefined ; } else { self . secondNumber = n ; } } , setOperation ( op ) { self . operation = op ; } , } ) ) . volatile ( ( ) => ( { ReactComponent : FilterReactComponent } ) ) ; const NumberColumn = MakeSpreadsheetColumnType ( 'Number' , { compare ( cellA , cellB ) { return parseFloat ( cellA . text ) - parseFloat ( cellB . text ) ; } , FilterModelType , } ) ; export { NumberColumn , FilterModelType } ;