Skip to content

Commit b59aa28

Browse files
committed
fix: clamp number decimal precision
Signed-off-by: xhon-pelushi <xhon@pelushi.com>
1 parent aec7e1f commit b59aa28

4 files changed

Lines changed: 59 additions & 9 deletions

File tree

cypress/component/TableCellNumber.cy.js

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import { setLocale } from '@nextcloud/l10n'
66

77
import TableCellNumber from '../../src/shared/components/ncTable/partials/TableCellNumber.vue'
8+
import NumberForm from '../../src/shared/components/ncTable/partials/rowTypePartials/NumberForm.vue'
89

910
describe('TableCellNumber', () => {
1011
beforeEach(() => {
@@ -26,9 +27,23 @@ describe('TableCellNumber', () => {
2627
})
2728

2829
it('clamps out-of-range decimal counts for Intl.NumberFormat', () => {
29-
mountNumberCell(1.234567, { numberDecimals: 50 })
30+
mountNumberCell(1.2, { numberDecimals: 101 })
3031

31-
cy.get('.number-display').should('contain.text', '1.234567')
32+
cy.get('.number-display').invoke('text').should((text) => {
33+
expect(text).to.match(/^1\.20+$/)
34+
expect(text.trim().split('.')[1]).to.have.length(100)
35+
})
36+
})
37+
38+
it('clamps out-of-range decimal counts when editing row values', () => {
39+
mountRowNumberForm(1.2, { numberDecimals: 101 }).then(({ wrapper }) => {
40+
expect(wrapper.vm.numberFractionDigits).to.equal(100)
41+
expect(wrapper.vm.parseValue('1.234')).to.equal(1.234)
42+
expect(wrapper.vm.getStep).to.match(/^\.0+1$/)
43+
44+
const step = wrapper.vm.getStep
45+
expect(step.slice(1, -1)).to.have.length(99)
46+
})
3247
})
3348
})
3449

@@ -49,3 +64,32 @@ function mountNumberCell(value, columnOverrides = {}) {
4964
},
5065
})
5166
}
67+
68+
function mountRowNumberForm(value, columnOverrides = {}) {
69+
return cy.mount(NumberForm, {
70+
props: {
71+
column: {
72+
id: 1,
73+
title: 'Amount',
74+
description: '',
75+
mandatory: false,
76+
numberDecimals: 0,
77+
numberDefault: undefined,
78+
numberMax: null,
79+
numberMin: null,
80+
numberPrefix: '',
81+
numberSuffix: '',
82+
viewColumnInformation: {},
83+
...columnOverrides,
84+
},
85+
value,
86+
},
87+
global: {
88+
components: {
89+
RowFormWrapper: {
90+
template: '<div><slot /></div>',
91+
},
92+
},
93+
},
94+
})
95+
}

src/shared/components/ncTable/partials/TableCellNumber.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ export default {
4343
if (this.value === null) {
4444
return null
4545
}
46-
// Intl.NumberFormat only accepts 0..20 fraction digits
46+
// Intl.NumberFormat only accepts 0..100 fraction digits
4747
const raw = Number(this.column?.numberDecimals ?? 0)
4848
const fractionDigits = Number.isFinite(raw)
49-
? Math.min(20, Math.max(0, Math.trunc(raw)))
49+
? Math.min(100, Math.max(0, Math.trunc(raw)))
5050
: 0
5151
return new Intl.NumberFormat(getCanonicalLocale(), {
5252
maximumFractionDigits: fractionDigits,

src/shared/components/ncTable/partials/columnTypePartials/forms/NumberForm.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
{{ t('tables', 'Decimals') }}
2020
</div>
2121
<div class="fix-col-4">
22-
<input v-model="mutableColumn.numberDecimals" type="number">
22+
<input v-model="mutableColumn.numberDecimals" type="number" min="0" max="100" step="1">
2323
</div>
2424
</div>
2525
<div v-if="defaultValueErrorHint !== ''" class="col-4">

src/shared/components/ncTable/partials/rowTypePartials/NumberForm.vue

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,17 @@ export default {
4343
'update:value',
4444
],
4545
computed: {
46+
numberFractionDigits() {
47+
const raw = Number(this.column?.numberDecimals ?? 0)
48+
return Number.isFinite(raw)
49+
? Math.min(100, Math.max(0, Math.trunc(raw)))
50+
: 0
51+
},
4652
getStep() {
47-
if (this.column?.numberDecimals === 0) {
53+
if (this.numberFractionDigits === 0) {
4854
return '1'
49-
} else if (this.column?.numberDecimals > 0) {
50-
return '.' + '0'.repeat(this.column.numberDecimals - 1) + '1'
55+
} else if (this.numberFractionDigits > 0) {
56+
return '.' + '0'.repeat(this.numberFractionDigits - 1) + '1'
5157
} else {
5258
return 'any'
5359
}
@@ -95,7 +101,7 @@ export default {
95101
} else {
96102
parsedValue = inputValue
97103
}
98-
const roundedValue = parsedValue.toFixed(this.column?.numberDecimals)
104+
const roundedValue = parsedValue.toFixed(this.numberFractionDigits)
99105
let value = parseFloat(roundedValue)
100106
if ((this.column?.numberMin !== null && this.column?.numberMin !== undefined) && value < this.column?.numberMin) {
101107
value = this.column.numberMin

0 commit comments

Comments
 (0)