Skip to content

Commit

Permalink
Merge pull request #466 from 3YOURMIND/465-fix-kt-field-number-floati…
Browse files Browse the repository at this point in the history
…ng-point

fix(#465): KtFieldNumber Floating Point
  • Loading branch information
carsoli authored Jul 14, 2021
2 parents 65ed39a + 9259a83 commit 3612a41
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/documentation/pages/usage/components/filters.vue
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export default defineComponent({
Kotti.Filters.Operation.Float.LESS_THAN_OR_EQUAL,
Kotti.Filters.Operation.Float.IS_EMPTY,
],
step: 0.1,
step: 0.001,
type: Kotti.Filters.FilterType.FLOAT,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@
/>
<KtFieldNumber
formKey="step"
:minimum="0"
isOptional
label="step"
size="small"
Expand Down
2 changes: 2 additions & 0 deletions packages/kotti-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"@3yourmind/vue-use-tippy": "1.x",
"@3yourmind/yoco": "^2.1.1",
"@popperjs/core": "2.0.6",
"@types/big.js": "^6.1.1",
"big.js": "^6.1.1",
"color": "3.x",
"deep-eql": "^4.0.0",
"deepmerge": "^4.2.2",
Expand Down
24 changes: 13 additions & 11 deletions packages/kotti-ui/source/kotti-field-number/KtFieldNumber.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<script lang="ts">
import { Yoco } from '@3yourmind/yoco'
import { defineComponent, computed, ref, watch } from '@vue/composition-api'
import Big from 'big.js'
import { KtField } from '../kotti-field'
import { KOTTI_FIELD_PROPS } from '../kotti-field/constants'
Expand Down Expand Up @@ -91,10 +92,12 @@ export default defineComponent({
() =>
!field.isDisabled &&
isInRange({
maximum: null,
maximum: props.maximum,
minimum: props.minimum,
offset: -props.step,
value: field.currentValue,
value:
field.currentValue === null
? null
: Big(field.currentValue).minus(props.step).toNumber(),
}),
)
Expand All @@ -103,9 +106,11 @@ export default defineComponent({
!field.isDisabled &&
isInRange({
maximum: props.maximum,
minimum: null,
offset: props.step,
value: field.currentValue,
minimum: props.minimum,
value:
field.currentValue === null
? null
: Big(field.currentValue).add(props.step).toNumber(),
}),
)
Expand All @@ -125,7 +130,6 @@ export default defineComponent({
!isInRange({
maximum: props.maximum,
minimum: props.minimum,
offset: 0,
value: truncatedNumber,
})
)
Expand Down Expand Up @@ -181,7 +185,6 @@ export default defineComponent({
isInRange({
maximum: props.maximum,
minimum: props.minimum,
offset: 0,
value: 0,
}),
)
Expand All @@ -198,7 +201,7 @@ export default defineComponent({
? canFallbackToZero.value
? 0
: props.minimum ?? props.maximum ?? 0
: field.currentValue - props.step,
: Big(field.currentValue).minus(props.step).toNumber(),
)
},
field,
Expand All @@ -216,7 +219,7 @@ export default defineComponent({
? canFallbackToZero.value
? 0
: props.minimum ?? props.maximum ?? 0
: field.currentValue + props.step,
: Big(field.currentValue).add(props.step).toNumber(),
)
},
internalStringValue,
Expand Down Expand Up @@ -258,7 +261,6 @@ export default defineComponent({
isInRange({
maximum,
minimum,
offset: 0,
value: nextNumber,
})
Expand Down
9 changes: 8 additions & 1 deletion packages/kotti-ui/source/kotti-field-number/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { KottiField } from '../kotti-field/types'

import { isNumber } from './utilities'

export const KOTTI_FIELD_NUMBER_SUPPORTS: KottiField.Supports = {
clear: false,
decoration: true,
Expand All @@ -12,7 +14,12 @@ export const KOTTI_FIELD_NUMBER_PROPS = {
maximum: { default: null, type: Number },
minimum: { default: null, type: Number },
placeholder: { default: null, type: String },
step: { default: 1, type: Number },
step: {
default: 1,
type: Number,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
validator: (value: any): value is number => isNumber(value) && value > 0,
},
value: { default: null, type: Number },
}

Expand Down
25 changes: 15 additions & 10 deletions packages/kotti-ui/source/kotti-field-number/utilities.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import Big from 'big.js'

import { Kotti } from '../types'

import {
STRINGS_THAT_ARE_TREATED_AS_NULL,
DECIMAL_SEPARATOR,
Expand All @@ -16,18 +20,16 @@ export const isNumber = (value: unknown): boolean =>
export const isInRange = ({
maximum,
minimum,
offset,
value,
}: {
maximum: number | null
minimum: number | null
offset: number
value: number | null
maximum: Kotti.FieldNumber.Props['maximum']
minimum: Kotti.FieldNumber.Props['minimum']
value: Kotti.FieldNumber.Value
}) => {
if (value === null) return true

const fitsMinimum = minimum === null || value + offset >= minimum
const fitsMaximum = maximum === null || value + offset <= maximum
const fitsMinimum = minimum === null || value >= minimum
const fitsMaximum = maximum === null || value <= maximum

return fitsMinimum && fitsMaximum
}
Expand All @@ -42,9 +44,12 @@ export const isStepMultiple = ({
value: number | null
}) => {
if (minimum === null || value === null) return true
const k = (value - minimum) / step
const epsilon = 10e-10
return Math.abs(k - Math.round(k)) < epsilon

// (value - minimum) / step
const stepFactor = Big(value).minus(minimum).div(step)

// is integer?
return stepFactor.eq(stepFactor.round())
}

export const toNumber = (string: string) =>
Expand Down
16 changes: 2 additions & 14 deletions packages/kotti-ui/source/kotti-filters/components/FilterRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ export default defineComponent<{
case Kotti.Filters.FilterType.FLOAT:
return props.column.step
case Kotti.Filters.FilterType.INTEGER:
return 1
// fall through
default:
return null
return 1
}
})
const isOperationSelectDisabled = computed<boolean>(
Expand Down Expand Up @@ -195,18 +195,6 @@ export default defineComponent<{
return
}
// FIXME: Remove after issue https://github.com/3YOURMIND/kotti/issues/461 is fixed
if (props.column?.type === Kotti.Filters.FilterType.INTEGER) {
emit('input', {
...newFilter,
value:
typeof newFilter.value === 'number'
? Math.trunc(newFilter.value)
: null,
})
return
}
emit('input', newFilter)
}
return {
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3532,6 +3532,11 @@
dependencies:
"@types/babel-types" "*"

"@types/big.js@^6.1.1":
version "6.1.1"
resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-6.1.1.tgz#c2be5e81e0cf0c1c31704e3b12f750712f647414"
integrity sha512-Zns+nT0hj96ie+GDbL5NeHxhL4wNz8QMxCHqBvxgc4x0hhgQ/o92rPwqxvPBhY3ZYnH8TJGw/8oCkjhOy2Rfzw==

"@types/body-parser@*":
version "1.19.0"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f"
Expand Down Expand Up @@ -5693,6 +5698,11 @@ big.js@^5.2.2:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==

big.js@^6.1.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.1.1.tgz#63b35b19dc9775c94991ee5db7694880655d5537"
integrity sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg==

binary-extensions@^1.0.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
Expand Down

0 comments on commit 3612a41

Please sign in to comment.