'use client'
import { ReactElement, useMemo, useRef, useState } from "react"
import dynamic from "next/dynamic"
import { GridColumn as Column, GridCellProps, GridItemChangeEvent, GridRowProps, GridToolbar } from "@progress/kendo-react-grid"
import { CompositeFilterDescriptor } from "@progress/kendo-data-query"
import { filterBy } from "@progress/kendo-react-data-tools"
import { CellRender, RowRender } from "../../Other/renderers"
const Grid: any = dynamic(() => import("@progress/kendo-react-grid").then(module => module.Grid as any), { ssr: false })
import { process } from '@progress/kendo-data-query'
import useCdpGridFunctions from "./localHooks/useCdpGridFunctions"
import addIdProperty from './helpers/addIdProperty' // Helpers
import formatDates from './helpers/formatDates'
import './CDPGrid.css'
import fillComboDynamic from "../../fillComboDynamic"
const EDIT_FIELD = 'inEdit'; const GridColumns = [{ field: '' }]
const CDPExampleComponent = ({ cdpData, data, setData, selectedGrid, selectedFilter, basicGridName, tableHmy, databasePackage, gridProps }) => {
// console.log('basicGridName', basicGridName)
async function getDbGridConfig() {
// const controlsUrl = `/api/storedProcedures/${paramSelectedGrid}/controls`
const controlsUrl = `/api/storedProcedures/rofoGridConfig?grid=${basicGridName}`
// return await (await fetch(controlsUrl)).json()
const columns = await fetch(controlsUrl)
return columns
}
const [reactiveGridColumns, setReactiveGridColumns] = useState()
useMemo(() => {
const gridColumns = getDbGridConfig()
.then((response) => {return response.json()})
.then((data) => {
console.log('columns', data)
setReactiveGridColumns(data)
})
}, [])
// console.log('data', data)
// const result = filterBy(data, { filter: selectedFilter })
const filteredData = process(data, { filter: selectedFilter })
// console.log('filteredData', filteredData)
data = addIdProperty(filteredData.data) // Data that's sent to the Grid
data = formatDates(data)
const [changes, setChanges] = useState<boolean>(false)
const [columns, setColumns] = useState(GridColumns)
useCdpGridFunctions(cdpData, setColumns)
const itemChange = (event: GridItemChangeEvent) => {
let field = event.field || ''
event.dataItem[field] = event.value
let newData = data.map((item: any) => {
if (item.Id === event.dataItem.Id) {
item[field] = event.value
}
return item
})
setData(newData)
setChanges(true)
}
const editedDataItem = useRef()
// enterEdit ////////////////////////////////////////////////////////////////////
const enterEdit: any = (dataItem: any, field: string) => {
// console.log('dataItem', dataItem)
// console.log('field', field)
const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: item.Id === dataItem.Id ? field : undefined }))
// console.log('newData', newData)
setData(newData)
newData['field'] = field
editedDataItem.current = newData[dataItem.Id]
// console.log("enterEdit | newData")
// console.log('editedDataItem.current', editedDataItem.current)
// console.log(`Row: ${dataItem.Id}, Field: ${field}`, dataItem)
}
// exitEdit /////////////////////////////////////////////////////////////////////
const exitEdit: any = () => {
// console.log('exitEdit')
// const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: undefined }))
const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: undefined }))
// console.log('EDIT_FIELD', newData.EDIT_FIELD)
setData(newData)
// console.log("exitEdit | newData", newData)
// console.log('editedDataItem', editedDataItem.current)
}
// TODO: I need the title here
const saveChanges = () => {
// console.log('Save Changes')
const dataSegment = data.splice(0, data.length, ...data) // Giant Array
setChanges(false)
// console.log('Updating the database'); // TODO: Update the database correctly
updateDatabase(databasePackage, editedDataItem.current)
}
const updateDatabase = async (databasePackage: any, edits: any) => { // TODO: Get the stored procedure to work correctly
const storedProcedureParameters = {
tableHmy: edits[databasePackage.current.tableHmy],
amendmentid: edits.AmendmentID,
fieldToUpdate: edits.inEdit,
fieldValue: edits[edits.inEdit],
domainUser: databasePackage.current.domainUser,
grid: databasePackage.current.basicGridName
}
fetch('/api/storedProcedures/[storedProcedure]', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(storedProcedureParameters),
})
.then((response) => {
// console.log('response', response)
return response.json()
})
.then((data) => {
// console.log('data', data)
})
}
const cancelChanges = () => {
setData(data)
setChanges(false)
}
const customCellRender: any = (td: ReactElement<HTMLTableCellElement>, props: GridCellProps) => {
return <CellRender originalProps={props} td={td} enterEdit={enterEdit} editField={EDIT_FIELD} />
} // Error, until it returns the correct type, an empty render function returns no data
const customRowRender: any = (tr: ReactElement<HTMLTableRowElement>, props: GridRowProps) => {
return <RowRender originalProps={props} tr={tr} exitEdit={exitEdit} editField={EDIT_FIELD} />
} // Error, until it returns the correct type, an empty render function returns no data; params display column-names
function dontDisplay(column, value) {
let displayStatus = true
value.map((hiddenElement: any) => {
if (column === hiddenElement) {
// console.log(`column: ${column} | hiddenElement: ${hiddenElement}`)
displayStatus = false
}
})
return displayStatus
}
function permitEdits(column:any, fields:any) {
const permittedFields = fields.filter((field:any, index:number) => {
if (field.ReadOnly !== true) {
// console.log('field.ReadOnly', field.Name, field.ReadOnly)
return fields[index]
}
})
try {
let permitStatus = true
permittedFields.map((permittedElement: any) => {
if (column === permittedElement.Name) {
permitStatus = false
}
})
return permitStatus
}
catch (error) {
return false
}
}
return (
<>
{/* <h1>CDP Grid (E2) {selectedGrid}</h1> */}
<Grid
id='mainGrid'
// ref={gridRef}
style={{ height: '82vh' }} // Grid Height, up from 70vh
data={data}
dataItemKey={'Id'}
// dataItemKey={`${tableHmy}`}
rowHeight={50}
resizable={true}
reorderable={true}
onItemChange={itemChange} cellRender={customCellRender} rowRender={customRowRender} editField={EDIT_FIELD}>
{/* {
gridProps.columnProps.map((column:any, index:any) => {
if (!dontDisplay(column.field, ['inEdit', 'Id'])) { }
else if (column.ReadOnly) { // Enable Editables
return <Column key={index} {...column} format="{0:d}" editable={false} field={column.FieldName} width={column.Width} title={column.HeaderText} />
}
else {
return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.FieldName} width={column.Width} title={column.HeaderText} />
}
})
} */}
{
reactiveGridColumns?.map((column:any, index:any) => {
// console.log('column', column)
if (column.IsHidden === 1) {}
else if (column.DropDownProc !== null) {
// fillComboDynamic(column)
// How do I replace the field={column.DBName} text with a DropDownList?
return <Column key={index} {...column} editable={true} className={'fillableDropdown'} field={column.DBName} width={column.Width} title={column.FriendlyName} />
}
else if (column.IsEditable !== 0) {
return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} />
}
else {
return <Column key={index} {...column} format="{0:d}" editable={false} field={column.DBName} width={column.Width} title={column.FriendlyName} />
}
// return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} />
})
}
<GridToolbar>
<button
title='Save Changes'
className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base'
onClick={saveChanges}
disabled={!changes}>Save Changes</button>
<button
title='Cancel Changes'
className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base'
// onClick={cancelChanges}
disabled={!changes}>Cancel Changes</button>
</GridToolbar>
</Grid>
</>
)
}
export default CDPExampleComponent
I've made some progress! The custom cell renderer contains a "dataItem" property that need to work with...
The dataItem must be replaced with my DropDownList - but how?
'use client' import { ReactElement, useMemo, useRef, useState } from "react" import dynamic from "next/dynamic" import { GridColumn as Column, GridCellProps, GridItemChangeEvent, GridRowProps, GridToolbar } from "@progress/kendo-react-grid" import { CompositeFilterDescriptor } from "@progress/kendo-data-query" import { filterBy } from "@progress/kendo-react-data-tools" import { CellRender, RowRender } from "../../Other/renderers" const Grid: any = dynamic(() => import("@progress/kendo-react-grid").then(module => module.Grid as any), { ssr: false }) import { process } from '@progress/kendo-data-query' import useCdpGridFunctions from "./localHooks/useCdpGridFunctions" import addIdProperty from './helpers/addIdProperty' // Helpers import formatDates from './helpers/formatDates' import './CDPGrid.css' const EDIT_FIELD = 'inEdit'; const GridColumns = [{ field: '' }] const CDPExampleComponent = ({ cdpData, data, setData, selectedGrid, selectedFilter, basicGridName, tableHmy, databasePackage, gridProps }) => { async function getDbGridConfig() { const controlsUrl = `/api/storedProcedures/rofoGridConfig?grid=${basicGridName}` const columns = await fetch(controlsUrl) return columns } const [reactiveGridColumns, setReactiveGridColumns] = useState() useMemo(() => { const gridColumns = getDbGridConfig() .then((response) => {return response.json()}) .then((data) => { console.log('columns', data) setReactiveGridColumns(data) }) }, []) const filteredData = process(data, { filter: selectedFilter }) data = addIdProperty(filteredData.data) // Data that's sent to the Grid data = formatDates(data) const [changes, setChanges] = useState<boolean>(false) const [columns, setColumns] = useState(GridColumns) useCdpGridFunctions(cdpData, setColumns) const itemChange = (event: GridItemChangeEvent) => { let field = event.field || '' event.dataItem[field] = event.value let newData = data.map((item: any) => { if (item.Id === event.dataItem.Id) { item[field] = event.value } return item }) setData(newData) setChanges(true) } const editedDataItem = useRef() // enterEdit //////////////////////////////////////////////////////////////////// const enterEdit: any = (dataItem: any, field: string) => { const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: item.Id === dataItem.Id ? field : undefined })) setData(newData) newData['field'] = field editedDataItem.current = newData[dataItem.Id] } // exitEdit ///////////////////////////////////////////////////////////////////// const exitEdit: any = () => { const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: undefined })) setData(newData) } const saveChanges = () => { // TODO: I need the title here const dataSegment = data.splice(0, data.length, ...data) // Giant Array setChanges(false) updateDatabase(databasePackage, editedDataItem.current) } const updateDatabase = async (databasePackage: any, edits: any) => { // TODO: Get the stored procedure to work correctly const storedProcedureParameters = { tableHmy: edits[databasePackage.current.tableHmy], amendmentid: edits.AmendmentID, fieldToUpdate: edits.inEdit, fieldValue: edits[edits.inEdit], domainUser: databasePackage.current.domainUser, grid: databasePackage.current.basicGridName } fetch('/api/storedProcedures/[stored_procedure]', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(storedProcedureParameters), }) .then((response) => { return response.json() }) .then((data) => { }) } const cancelChanges = () => { setData(data) setChanges(false) } const customCellRender: any = (td: ReactElement<HTMLTableCellElement>, props: GridCellProps) => { // Cell Data // TODO: Current Development: Get the DaysType column key (data) and replace it with a DropDownList // console.log('dataItem', props.dataItem) console.log('dataItem', props.dataItem.DaysType) return <CellRender originalProps={props} td={td} enterEdit={enterEdit} editField={EDIT_FIELD} /> } // Error, until it returns the correct type, an empty render function returns no data const customRowRender: any = (tr: ReactElement<HTMLTableRowElement>, props: GridRowProps) => { return <RowRender originalProps={props} tr={tr} exitEdit={exitEdit} editField={EDIT_FIELD} /> } // Error, until it returns the correct type, an empty render function returns no data; params display column-names return ( <> <Grid id='mainGrid' style={{ height: '82vh' }} // Grid Height, up from 70vh data={data} dataItemKey={'Id'} rowHeight={50} resizable={true} reorderable={true} onItemChange={itemChange} cellRender={customCellRender} rowRender={customRowRender} editField={EDIT_FIELD}> { reactiveGridColumns?.map((column:any, index:any) => { // console.log('column', column) if (column.IsHidden === 1) {} else if (column.DropDownProc !== null) { return <Column key={index} {...column} editable={true} className={'fillableDropdown'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } else if (column.IsEditable !== 0) { return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } else { return <Column key={index} {...column} format="{0:d}" editable={false} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } // return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> }) } <GridToolbar> <button title='Save Changes' className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base' onClick={saveChanges} disabled={!changes}>Save Changes</button> <button title='Cancel Changes' className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base' // onClick={cancelChanges} disabled={!changes}>Cancel Changes</button> </GridToolbar> </Grid> </> ) } export default CDPExampleComponent
How do I separate the Dropdowns?
The "Days Type" column contains the ROFO controls, which belong in the "ROFO/ROFR" column instead.
'use client' import { ReactElement, useMemo, useRef, useState } from "react" import dynamic from "next/dynamic" import { GridColumn as Column, GridCellProps, GridItemChangeEvent, GridRowProps, GridToolbar } from "@progress/kendo-react-grid" import { CompositeFilterDescriptor } from "@progress/kendo-data-query" import { filterBy } from "@progress/kendo-react-data-tools" import { CellRender, RowRender } from "../../Other/renderers" const Grid: any = dynamic(() => import("@progress/kendo-react-grid").then(module => module.Grid as any), { ssr: false }) import { process } from '@progress/kendo-data-query' import useCdpGridFunctions from "./localHooks/useCdpGridFunctions" import addIdProperty from './helpers/addIdProperty' // Helpers import formatDates from './helpers/formatDates' import './CDPGrid.css' import { DropDownList } from "@progress/kendo-react-dropdowns" const EDIT_FIELD = 'inEdit'; const GridColumns = [{ field: '' }] const CDPExampleComponent = ({ cdpData, data, setData, selectedGrid, selectedFilter, basicGridName, tableHmy, databasePackage, gridProps }) => { async function getDbGridConfig() { const controlsUrl = `/api/storedProcedures/rofoGridConfig?grid=${basicGridName}` const columns = await fetch(controlsUrl) return columns } const [reactiveGridColumns, setReactiveGridColumns] = useState() useMemo(() => { const gridColumns = getDbGridConfig() .then((response) => {return response.json()}) .then((data) => { console.log('columns', data) setReactiveGridColumns(data) }) }, []) const filteredData = process(data, { filter: selectedFilter }) data = addIdProperty(filteredData.data) // Data that's sent to the Grid data = formatDates(data) const [changes, setChanges] = useState<boolean>(false) const [columns, setColumns] = useState(GridColumns) useCdpGridFunctions(cdpData, setColumns) const itemChange = (event: GridItemChangeEvent) => { let field = event.field || '' event.dataItem[field] = event.value let newData = data.map((item: any) => { if (item.Id === event.dataItem.Id) { item[field] = event.value } return item }) setData(newData) setChanges(true) } const editedDataItem = useRef() // enterEdit //////////////////////////////////////////////////////////////////// const enterEdit: any = (dataItem: any, field: string) => { const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: item.Id === dataItem.Id ? field : undefined })) setData(newData) newData['field'] = field editedDataItem.current = newData[dataItem.Id] } // exitEdit ///////////////////////////////////////////////////////////////////// const exitEdit: any = () => { const newData = data.map((item: any) => ({ ...item, [EDIT_FIELD]: undefined })) setData(newData) } const saveChanges = () => { // TODO: I need the title here const dataSegment = data.splice(0, data.length, ...data) // Giant Array setChanges(false) updateDatabase(databasePackage, editedDataItem.current) } const updateDatabase = async (databasePackage: any, edits: any) => { // TODO: Get the stored procedure to work correctly const storedProcedureParameters = { tableHmy: edits[databasePackage.current.tableHmy], amendmentid: edits.AmendmentID, fieldToUpdate: edits.inEdit, fieldValue: edits[edits.inEdit], domainUser: databasePackage.current.domainUser, grid: databasePackage.current.basicGridName } fetch('/api/storedProcedures/[storedProcedure]', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(storedProcedureParameters), }) .then((response) => { return response.json() }) .then((data) => { }) } const cancelChanges = () => { setData(data) setChanges(false) } function presentCustomCellData(props:any, td:any) { const bridgeIndex = props.columnIndex + 1 const customCellBridge = { column: reactiveGridColumns[bridgeIndex].DBName, // State variable from line 32 dropdownStatus: reactiveGridColumns[bridgeIndex].DropDownProc, cellProps: props, colmProps: reactiveGridColumns } console.log('customCellBridge', customCellBridge) if (customCellBridge.dropdownStatus !== null && customCellBridge.column == 'DaysType') { return (<DropDownList value={customCellBridge.cellProps.dataItem[customCellBridge.column]}></DropDownList>) } if (customCellBridge.dropdownStatus !== null && customCellBridge.column == 'ROFOROFRType') { return (<DropDownList value={customCellBridge.cellProps.dataItem[customCellBridge.column]}></DropDownList>) } return <CellRender originalProps={props} td={td} enterEdit={enterEdit} editField={EDIT_FIELD} /> } const customCellRender: any = (td: ReactElement<HTMLTableCellElement>, props: GridCellProps) => { // Cell Data return presentCustomCellData(props, td) } // Error, until it returns the correct type, an empty render function returns no data const customRowRender: any = (tr: ReactElement<HTMLTableRowElement>, props: GridRowProps) => { return <RowRender originalProps={props} tr={tr} exitEdit={exitEdit} editField={EDIT_FIELD} /> } // Error, until it returns the correct type, an empty render function returns no data; params display column-names return ( <> <Grid id='mainGrid' style={{ height: '82vh' }} // Grid Height, up from 70vh data={data} dataItemKey={'Id'} rowHeight={50} resizable={true} reorderable={true} onItemChange={itemChange} cellRender={customCellRender} rowRender={customRowRender} editField={EDIT_FIELD}> { reactiveGridColumns?.map((column:any, index:any) => { console.log('column', column) if (column.IsHidden === 1) {} else if (column.DropDownProc !== null) { return <Column key={index} {...column} editable={true} className={'fillableDropdown'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } else if (column.IsEditable !== 0) { return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } else { return <Column key={index} {...column} format="{0:d}" editable={false} field={column.DBName} width={column.Width} title={column.FriendlyName} /> } // return <Column key={index} {...column} editable={true} className={'azureColor'} field={column.DBName} width={column.Width} title={column.FriendlyName} /> }) } <GridToolbar> <button title='Save Changes' className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base' onClick={saveChanges} disabled={!changes}>Save Changes</button> <button title='Cancel Changes' className='k-button k-button-md k-rounded-md k-button-solid k-button-solid-base' // onClick={cancelChanges} disabled={!changes}>Cancel Changes</button> </GridToolbar> </Grid> </> ) } export default CDPExampleComponent