From 4ee776b6a5328c9c6a1264067649815ccfa7ccb1 Mon Sep 17 00:00:00 2001 From: Alexander Elguezabal Date: Thu, 1 Aug 2024 14:58:14 -0700 Subject: [PATCH 1/2] Implemented DateTime edit control type. --- src/libs/editablegrid/addrowpanel.tsx | 116 +- src/libs/editablegrid/columnupdatedialog.tsx | 129 +- src/libs/editablegrid/editablegrid.tsx | 1432 ++++++++++-------- src/libs/editablegrid/editpanel.tsx | 107 +- 4 files changed, 1027 insertions(+), 757 deletions(-) diff --git a/src/libs/editablegrid/addrowpanel.tsx b/src/libs/editablegrid/addrowpanel.tsx index 6a7955c3..ce5ba98e 100644 --- a/src/libs/editablegrid/addrowpanel.tsx +++ b/src/libs/editablegrid/addrowpanel.tsx @@ -1,4 +1,4 @@ -import { ConstrainMode, DatePicker, Dropdown, IDropdownOption, IStackStyles, IStackTokens, ITag, ITextFieldStyles, mergeStyleSets, Position, PrimaryButton, SpinButton, Stack, TextField } from "office-ui-fabric-react"; +import { ConstrainMode, DatePicker, Dropdown, IComboBox, IDropdownOption, IStackStyles, IStackTokens, ITag, ITextFieldStyles, mergeStyleSets, Position, PrimaryButton, SpinButton, Stack, TextField } from "office-ui-fabric-react"; import React, { useEffect, useState } from "react"; import { IColumnConfig } from "../types/columnconfigtype"; import { EditControlType } from "../types/editcontroltype"; @@ -6,6 +6,7 @@ import { DayPickerStrings } from "./datepickerconfig"; import { controlClass, horizontalGapStackTokens, stackStyles, textFieldStyles, verticalGapStackTokens } from "./editablegridstyles"; import { GetDefault, IsValidDataType, ParseType } from "./helper"; import PickerControl from "./pickercontrol/picker"; +import { TimePicker } from "@fluentui/react"; interface Props { onChange: any; @@ -16,38 +17,38 @@ interface Props { const AddRowPanel = (props: Props) => { let AddSpinRef: any = React.createRef(); - const updateObj : any = {}; + const updateObj: any = {}; const [columnValuesObj, setColumnValuesObj] = useState(null); useEffect(() => { - let tmpColumnValuesObj : any = {}; + let tmpColumnValuesObj: any = {}; props.columnConfigurationData.forEach((item, index) => { - tmpColumnValuesObj[item.key] = { 'value' : GetDefault(item.dataType), 'isChanged' : false, 'error': null }; + tmpColumnValuesObj[item.key] = { 'value': GetDefault(item.dataType), 'isChanged': false, 'error': null }; }) setColumnValuesObj(tmpColumnValuesObj); }, [props.columnConfigurationData]); - const SetObjValues = (key: string, value: any, isChanged: boolean = true, errorMessage: string | null = null) : void => { - setColumnValuesObj({...columnValuesObj, [key]: { 'value' : value, 'isChanged' : isChanged, 'error': errorMessage }}) + const SetObjValues = (key: string, value: any, isChanged: boolean = true, errorMessage: string | null = null): void => { + setColumnValuesObj({ ...columnValuesObj, [key]: { 'value': value, 'isChanged': isChanged, 'error': errorMessage } }) } - const onDropDownChange = (event: React.FormEvent, selectedDropdownItem: IDropdownOption | undefined, item : any): void => { + const onDropDownChange = (event: React.FormEvent, selectedDropdownItem: IDropdownOption | undefined, item: any): void => { SetObjValues(item.key, selectedDropdownItem?.text); } - const onTextUpdate = (ev: React.FormEvent, text: string, column : IColumnConfig): void => { - if(!IsValidDataType(column.dataType, text)){ + const onTextUpdate = (ev: React.FormEvent, text: string, column: IColumnConfig): void => { + if (!IsValidDataType(column.dataType, text)) { SetObjValues((ev.target as Element).id, text, false, `Data should be of type '${column.dataType}'`); return; } - + SetObjValues((ev.target as Element).id, ParseType(column.dataType, text)); }; const onPanelSubmit = (): void => { var objectKeys = Object.keys(columnValuesObj); objectKeys.forEach((objKey) => { - if(columnValuesObj[objKey]['isChanged']){ + if (columnValuesObj[objKey]['isChanged']) { updateObj[objKey] = columnValuesObj[objKey]['value'] } }); @@ -55,21 +56,50 @@ const AddRowPanel = (props: Props) => { props.onChange(updateObj, props.enableRowsCounterField ? AddSpinRef.current.value : 1); }; - const onCellPickerTagListChanged = (cellPickerTagList: ITag[] | undefined, item : any) : void => { - if(cellPickerTagList && cellPickerTagList[0] && cellPickerTagList[0].name) + const onCellPickerTagListChanged = (cellPickerTagList: ITag[] | undefined, item: any): void => { + if (cellPickerTagList && cellPickerTagList[0] && cellPickerTagList[0].name) SetObjValues(item.key, cellPickerTagList[0].name); else SetObjValues(item.key, ''); } - const onCellDateChange = (date: Date | null | undefined, item : any): void => { - SetObjValues(item.key, date); + const onCellDateChange = (date: Date | null | undefined, item: IColumnConfig): void => { + let currentDate = getColumnValue(item); + + if (currentDate === undefined || currentDate === null) { + currentDate = date; + } else if (date !== null && date !== undefined) { + currentDate.setFullYear(date.getFullYear()); + currentDate.setMonth(date.getMonth()); + currentDate.setDate(date.getDate()); + } + + SetObjValues(item.key, currentDate); + }; + + const onCellTimeChange = (dateTime: Date | null | undefined, item: IColumnConfig): void => { + let currentDate = getColumnValue(item); + + if (currentDate === undefined || currentDate === null) { + currentDate = dateTime; + } else if (dateTime !== null && dateTime !== undefined) { + currentDate.setHours(dateTime.getHours()); + currentDate.setMinutes(dateTime.getMinutes()); + currentDate.setSeconds(dateTime.getSeconds()); + currentDate.setMilliseconds(dateTime.getMilliseconds()); + } + + SetObjValues(item.key, currentDate); }; - const createTextFields = () : any[] => { - let tmpRenderObj : any[] = []; + const getColumnValue = (item: IColumnConfig) => { + return columnValuesObj[item.key].value; + }; + + const createTextFields = (): any[] => { + let tmpRenderObj: any[] = []; props.columnConfigurationData.forEach((item, index) => { - switch(item.inputType){ + switch (item.inputType) { case EditControlType.Date: tmpRenderObj.push( { case EditControlType.Picker: tmpRenderObj.push(
{item.text} - onCellPickerTagListChanged(selectedItem, item)} pickerDescriptionOptions={item.pickerOptions?.pickerDescriptionOptions} - />
); + />); break; case EditControlType.MultilineTextField: tmpRenderObj.push( { styles={textFieldStyles} onChange={(ev, text) => onTextUpdate(ev, text!, item)} value={columnValuesObj[item.key].value || ''} - />); + />); break; case EditControlType.Password: tmpRenderObj.push( { value={columnValuesObj[item.key].value || ''} type="password" canRevealPassword - />); + />); + break; + case EditControlType.DateTime: + tmpRenderObj.push( + + onCellDateChange(date, item)} + /> + { onCellTimeChange(time, item) }} + /> + + ); break; default: tmpRenderObj.push( { styles={textFieldStyles} onChange={(ev, text) => onTextUpdate(ev, text!, item)} value={columnValuesObj[item.key].value || ''} - />); + />); break; } }); - if(props.enableRowsCounterField){ + if (props.enableRowsCounterField) { tmpRenderObj.push( { /> ); } - + return tmpRenderObj; } @@ -168,13 +218,13 @@ const AddRowPanel = (props: Props) => { {columnValuesObj && createTextFields()} - columnValuesObj[k] && columnValuesObj[k].error && columnValuesObj[k].error.length > 0) || false} - /> + columnValuesObj[k] && columnValuesObj[k].error && columnValuesObj[k].error.length > 0) || false} + /> ); diff --git a/src/libs/editablegrid/columnupdatedialog.tsx b/src/libs/editablegrid/columnupdatedialog.tsx index f5c76c57..b40d1261 100644 --- a/src/libs/editablegrid/columnupdatedialog.tsx +++ b/src/libs/editablegrid/columnupdatedialog.tsx @@ -8,6 +8,7 @@ import { EditControlType } from "../types/editcontroltype"; import { DayPickerStrings } from "./datepickerconfig"; import { GetDefault, IsValidDataType, ParseType } from "./helper"; import PickerControl from "./pickercontrol/picker"; +import { TimePicker } from "@fluentui/react"; interface Props { columnConfigurationData: IColumnConfig[]; @@ -15,9 +16,9 @@ interface Props { onDialogSave?: any; } -const ColumnUpdateDialog = (props : Props) => { +const ColumnUpdateDialog = (props: Props) => { const controlClass = mergeStyleSets({ - inputClass:{ + inputClass: { display: 'block', width: '100%' }, @@ -27,7 +28,7 @@ const ColumnUpdateDialog = (props : Props) => { }); const textFieldStyles: Partial = { fieldGroup: {} }; - + const [gridColumn, setGridColumn] = useState(''); const [inputValue, setInputValue] = useState(null); @@ -37,29 +38,29 @@ const ColumnUpdateDialog = (props : Props) => { }; useEffect(() => { - let tmpColumnValuesObj : any = {}; + let tmpColumnValuesObj: any = {}; props.columnConfigurationData.filter(x => x.editable == true).forEach((item, index) => { - tmpColumnValuesObj[item.key] = { 'value' : GetDefault(item.dataType), 'isChanged' : false, 'error': null }; + tmpColumnValuesObj[item.key] = { 'value': GetDefault(item.dataType), 'isChanged': false, 'error': null }; }) setInputValue(tmpColumnValuesObj); }, [props.columnConfigurationData]); - const SetObjValues = (key: string, value: any, isChanged: boolean = true, errorMessage: string | null = null) : void => { - var inputValueTmp : any = { ...inputValue }; + const SetObjValues = (key: string, value: any, isChanged: boolean = true, errorMessage: string | null = null): void => { + var inputValueTmp: any = { ...inputValue }; var objectKeys = Object.keys(inputValueTmp); objectKeys.forEach((objKey) => { inputValueTmp[objKey]['isChanged'] = false; }); - inputValueTmp[key] = { 'value' : value, 'isChanged' : isChanged, 'error': errorMessage }; + inputValueTmp[key] = { 'value': value, 'isChanged': isChanged, 'error': errorMessage }; setInputValue(inputValueTmp); } - const onTextUpdate = (ev: React.FormEvent, text: string, column : IColumnConfig): void => { - if(!IsValidDataType(column?.dataType, text)){ + const onTextUpdate = (ev: React.FormEvent, text: string, column: IColumnConfig): void => { + if (!IsValidDataType(column?.dataType, text)) { SetObjValues((ev.target as Element).id, text, false, `Data should be of type '${column.dataType}'`) return; } - + SetObjValues((ev.target as Element).id, ParseType(column.dataType, text)); }; @@ -67,18 +68,53 @@ const ColumnUpdateDialog = (props : Props) => { <> ); - const onSelectDate = (date: Date | null | undefined, item : any): void => { + const onSelectDate = (date: Date | null | undefined, item: any): void => { SetObjValues(item.key, date); }; - const onCellPickerTagListChanged = (cellPickerTagList: ITag[] | undefined, item : any) : void => { - if(cellPickerTagList && cellPickerTagList[0] && cellPickerTagList[0].name) + const onCellDateChange = (date: Date | null | undefined, item: IColumnConfig): void => { + let currentDate = getColumnValue(item); + + if (currentDate === undefined || currentDate === null) { + currentDate = date; + } else if (date !== null && date !== undefined) { + currentDate.setFullYear(date.getFullYear()); + currentDate.setMonth(date.getMonth()); + currentDate.setDate(date.getDate()); + } + + SetObjValues(item.key, currentDate); + }; + + const onCellTimeChange = (dateTime: Date | null | undefined, item: IColumnConfig): void => { + let currentDate = getColumnValue(item); + + if (currentDate === undefined || currentDate === null) { + currentDate = dateTime; + } else if (dateTime !== null && dateTime !== undefined) { + currentDate.setHours(dateTime.getHours()); + currentDate.setMinutes(dateTime.getMinutes()); + currentDate.setSeconds(dateTime.getSeconds()); + currentDate.setMilliseconds(dateTime.getMilliseconds()); + } + + SetObjValues(item.key, currentDate); + }; + + + const getColumnValue = (item: IColumnConfig) => { + return inputValue[item.key].value; + }; + + + const onCellPickerTagListChanged = (cellPickerTagList: ITag[] | undefined, item: any): void => { + if (cellPickerTagList && cellPickerTagList[0] && cellPickerTagList[0].name) SetObjValues(item.key, cellPickerTagList[0].name); else SetObjValues(item.key, ''); } - const onDropDownChange = (event: React.FormEvent, selectedDropdownItem: IDropdownOption | undefined, item : any): void => { + const onDropDownChange = (event: React.FormEvent, selectedDropdownItem: IDropdownOption | undefined, item: any): void => { SetObjValues(item.key, selectedDropdownItem?.text); } @@ -87,21 +123,21 @@ const ColumnUpdateDialog = (props : Props) => { }; const closeDialog = React.useCallback((): void => { - if(props.onDialogCancel){ + if (props.onDialogCancel) { props.onDialogCancel(); } - + setInputFieldContent(undefined) }, []); const saveDialog = (): void => { - if(props.onDialogSave){ - var inputValueTmp : any = {}; + if (props.onDialogSave) { + var inputValueTmp: any = {}; var objectKeys = Object.keys(inputValue); var BreakException = {}; - try{ + try { objectKeys.forEach((objKey) => { - if(inputValue[objKey]['isChanged']){ + if (inputValue[objKey]['isChanged']) { inputValueTmp[objKey] = inputValue[objKey]['value']; throw BreakException; } @@ -116,11 +152,11 @@ const ColumnUpdateDialog = (props : Props) => { setInputFieldContent(undefined); }; - const createDropDownOptions = () : IDropdownOption[] => { + const createDropDownOptions = (): IDropdownOption[] => { let dropdownOptions: IDropdownOption[] = []; props.columnConfigurationData.forEach((item, index) => { - if(item.editable == true){ - dropdownOptions.push({ key: item.key, text: item.text}); + if (item.editable == true) { + dropdownOptions.push({ key: item.key, text: item.text }); } }); @@ -129,10 +165,10 @@ const ColumnUpdateDialog = (props : Props) => { const options = createDropDownOptions(); - const GetInputFieldContent = () : JSX.Element => { + const GetInputFieldContent = (): JSX.Element => { var column = props.columnConfigurationData.filter(x => x.key == gridColumn); - if(column.length > 0){ - switch(column[0].inputType){ + if (column.length > 0) { + switch (column[0].inputType) { case EditControlType.Date: return ( { ariaLabel="Select a date" className={controlClass.inputClass} onSelectDate={(date) => onSelectDate(date, column[0])} - //value={new Date()} + //value={new Date()} />); + case EditControlType.DateTime: + return ( + + onCellDateChange(date, column[0])} + /> + { onCellTimeChange(time, column[0]) }} + /> + ) case EditControlType.Picker: return (
- onCellPickerTagListChanged(selectedItem, column[0])} pickerDescriptionOptions={column[0].pickerOptions?.pickerDescriptionOptions} - />
); + />); case EditControlType.DropDown: return ( { styles={textFieldStyles} onChange={(ev, text) => onTextUpdate(ev, text!, column[0])} value={inputValue[column[0].key].value || ''} - />); + />); default: return ( onTextUpdate(ev, text!,column[0])} + onChange={(ev, text) => onTextUpdate(ev, text!, column[0])} styles={textFieldStyles} id={column[0].key} value={inputValue[column[0].key].value || ''} @@ -189,8 +242,8 @@ const ColumnUpdateDialog = (props : Props) => { return (<>); } - - return( + + return (