From 79647884ac5e3e1d4dfcb27a5a0a71ee97b13a4b Mon Sep 17 00:00:00 2001 From: siddheshraze <81591724+siddheshraze@users.noreply.github.com> Date: Fri, 7 Feb 2025 14:05:59 -0500 Subject: [PATCH] Editing interface repaired. trailing zeros issue during editing should be resolved. --- .../components/client/datagridcolumns.tsx | 33 ++++++++---- .../datagrids/measurementscommons.tsx | 54 +++++++++++++------ frontend/config/datamapper.ts | 13 +++++ 3 files changed, 76 insertions(+), 24 deletions(-) diff --git a/frontend/components/client/datagridcolumns.tsx b/frontend/components/client/datagridcolumns.tsx index 36130a82..5ef72c23 100644 --- a/frontend/components/client/datagridcolumns.tsx +++ b/frontend/components/client/datagridcolumns.tsx @@ -1,6 +1,6 @@ import { HEADER_ALIGN } from '@/config/macros'; import { Autocomplete, Box, Chip, IconButton, Stack, Typography } from '@mui/joy'; -import { GridColDef, GridRenderEditCellParams } from '@mui/x-data-grid'; +import { GridColDef, GridPreProcessEditCellProps, GridRenderEditCellParams } from '@mui/x-data-grid'; import React, { Dispatch, SetStateAction, useState } from 'react'; import { AttributeStatusOptions } from '@/config/sqlrdsdefinitions/core'; import { standardizeGridColumns } from '@/components/client/clientmacros'; @@ -369,6 +369,20 @@ export function InputChip({ ); } +function preprocessor(params: GridPreProcessEditCellProps) { + const { props } = params; + let newValue = props.value; + + if (typeof newValue === 'string' && newValue.trim() !== '') { + const parsedValue = parseFloat(newValue); + if (!isNaN(parsedValue)) { + newValue = parseFloat(parsedValue.toFixed(2)); + } + } + + return { ...props, value: newValue }; +} + export const MeasurementsSummaryViewGridColumns: GridColDef[] = standardizeGridColumns([ { field: 'id', @@ -432,13 +446,13 @@ export const MeasurementsSummaryViewGridColumns: GridColDef[] = standardizeGridC headerName: 'X', renderHeader: () => formatHeader('X', 'Stem'), flex: 0.7, - type: 'number', valueFormatter: (value: any) => { return Number(value).toFixed(2); }, maxWidth: 100, editable: true, - filterOperators: customNumericOperators + filterOperators: customNumericOperators, + preProcessEditCellProps: params => preprocessor(params) }, { field: 'stemLocalY', @@ -451,17 +465,17 @@ export const MeasurementsSummaryViewGridColumns: GridColDef[] = standardizeGridC return Number(value).toFixed(2); }, editable: true, - filterOperators: customNumericOperators + filterOperators: customNumericOperators, + preProcessEditCellProps: params => preprocessor(params) }, { field: 'measuredDBH', headerName: 'DBH', flex: 0.5, editable: true, - valueFormatter: (value: any) => { - return Number(value).toFixed(2); - }, - filterOperators: customNumericOperators + valueFormatter: (value: any) => parseFloat(Number(value).toFixed(2)), + filterOperators: customNumericOperators, + preProcessEditCellProps: params => preprocessor(params) }, { field: 'measuredHOM', @@ -471,7 +485,8 @@ export const MeasurementsSummaryViewGridColumns: GridColDef[] = standardizeGridC valueFormatter: (value: any) => { return Number(value).toFixed(2); }, - filterOperators: customNumericOperators + filterOperators: customNumericOperators, + preProcessEditCellProps: params => preprocessor(params) }, { field: 'description', diff --git a/frontend/components/datagrids/measurementscommons.tsx b/frontend/components/datagrids/measurementscommons.tsx index c53f5671..6c64179c 100644 --- a/frontend/components/datagrids/measurementscommons.tsx +++ b/frontend/components/datagrids/measurementscommons.tsx @@ -41,6 +41,7 @@ import { Dropdown, FormLabel, IconButton, + Input, Menu, MenuButton, MenuItem, @@ -473,6 +474,26 @@ const EditToolbar = (props: EditToolbarProps) => { ); }; +function EditMeasurements({ params }: { params: GridRenderEditCellParams }) { + const initialValue = params.value ? Number(params.value).toFixed(2) : '0.00'; + const [value, setValue] = useState(initialValue); + + const handleChange = (event: React.ChangeEvent) => { + const newValue = event.target.value; + + if (/^\d*\.?\d{0,2}$/.test(newValue) || newValue === '') { + setValue(newValue); + } + }; + + const handleBlur = () => { + const formattedValue = parseFloat(value).toFixed(2); + params.api.setEditCellValue({ id: params.id, field: params.field, value: parseFloat(formattedValue) }); + }; + + return ; +} + export default function MeasurementsCommons(props: Readonly) { const { addNewRowToGrid, @@ -1273,6 +1294,20 @@ export default function MeasurementsCommons(props: Readonly { const commonColumns = gridColumns.map(column => { + if (column.field === 'attributes') { + column = { + ...column, + renderEditCell: (params: GridRenderEditCellParams) => ( + + ) + }; + } + if (['measuredDBH', 'measuredHOM', 'stemLocalX', 'stemLocalY'].includes(column.field)) { + column = { + ...column, + renderEditCell: (params: GridRenderEditCellParams) => + }; + } return { ...column, renderCell: (params: GridCellParams) => { @@ -1281,21 +1316,14 @@ export default function MeasurementsCommons(props: Readonly - {column.field === 'measuredDBH' - ? params.row.measuredDBH - ? Number(params.row.measuredDBH).toFixed(2) - : 'null' - : params.row.measuredHOM - ? Number(params.row.measuredHOM).toFixed(2) - : 'null'} - + {isMeasurementField && params.row[column.field] ? Number(params.row[column.field]).toFixed(2) : 'null'} ); } @@ -1342,11 +1370,7 @@ export default function MeasurementsCommons(props: Readonly ); - }, - renderEditCell: (params: GridRenderEditCellParams) => - column.field === 'attributes' && selectableAttributes.length > 0 ? ( - - ) : undefined + } }; }); if (locked || (session?.user.userStatus !== 'global' && session?.user.userStatus !== 'db admin')) { diff --git a/frontend/config/datamapper.ts b/frontend/config/datamapper.ts index 2b6130e9..24347286 100644 --- a/frontend/config/datamapper.ts +++ b/frontend/config/datamapper.ts @@ -177,6 +177,10 @@ export class GenericMapper implements IDataMapper { else if (Buffer.isBuffer(value) || value instanceof Uint8Array) { return bitToBoolean(value); } + // dynamically detect if values are decimal and provide handling + else if (this.isDecimal(value)) { + return parseFloat(value.toFixed(2)); + } // Now process date-like fields more carefully else if (this.isDateKey(key) && value !== null) { return parseDate(value); @@ -193,6 +197,15 @@ export class GenericMapper implements IDataMapper { // Add other specific date-related keys as needed return ['measurementdate', 'createddate', 'updateddate'].includes(lowerKey); } + + private isDecimal(value: any): boolean { + if (typeof value !== 'number') return false; + + // Check if the number has more than 2 decimal places + const decimalPlaces = (value.toString().split('.')[1] || '').length; + + return decimalPlaces > 2; // If more than 2 decimal places, it's likely a DECIMAL type + } } class MapperFactory {