'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

Hi I'm constantly getting this error:
Uncaught TypeError: Cannot read properties of undefined (reading 'onConstructor')
at new z (Grid.mjs:470:1)
at constructClassInstance (react-dom.development.js:11098:1)
at updateClassComponent (react-dom.development.js:15141:1)
at beginWork (react-dom.development.js:16537:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:3556:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3600:1)
at invokeGuardedCallback (react-dom.development.js:3655:1)
at beginWork$1 (react-dom.development.js:20656:1)
at performUnitOfWork (react-dom.development.js:19667:1)
at workLoopSync (react-dom.development.js:19612:1)
I'm using react 17.0.2 (react 18 does not work as well)
thanks in advance

How do I stop this? I would like for my DropdownList options to be a vertical list.
Hi Team,
In our project, there is a requirement to have a search select in place of the select ("Description" in the below example) as we have multiple columns.
In order to avoid too much scrolling, we are planning to have a search and select option. Is this feature customizable?
Can this be achieved?
Is it possible to remove the OR clause from the GridColumnMenuFilter?
https://www.telerik.com/kendo-react-ui/components/grid/filtering/#toc-column-menu-filter
I'd like it to only AND the two filters together.
Thank you
When I open the following link in iPhone Safari browser
https://www.telerik.com/kendo-react-ui/components/pdfprocessing/
In this link in the example section I am able to download the pdf on iPhone Safari browser but when I open the same example is a new window which uses the same code
then the pdf export doesn't work on iPhone Safari browser.

hi there
im building a gantt chart components right now, and wondering if there is a way to reorder the task it self to up/down?
i noticed there is an API for RowContextMenu which return a level in there which i believed is the one responsible in ordering the task
however there is no such function or api to exactly do the reordering
thank you

I've just upgraded my kendo-react-pdf from 8.0 to 8.1.1
but now the CSS isn't applied anymore. I'm using the CSS library 'Emotion' and this worked fine previously. For example I had a styled component in my PDF template with styling:
However, now the CSS only works if I add it inline:
I can change all the styling, but I'd prefer to keep my styled components as that's what we're using for the rest of the app as well.
Thanks!

I understand that KendoReact is 508 compliant by certain standards, but my agency tests to a different standard.
I'm getting reports that the grid is not associated cells with headers. I've researched different ways to get around this and the solution I've come up with is to add ID to the TH tags and then using the HEADERS attribute to the data cells with the ID in the associated header. Example below:
<table>
<tr>
<th id="colOneHeader">Col One</th>
<th id="colTwoHeader">Col Two</th>
</tr>
<tr>
<td headers="colOneHeader">Col One Data</td>
<td headers="colTwoHeader">Col Two Data</td>
</tr>
</table>My issue is adding the ID attribute to the TH tags in the grid. I've attempted the following:
const HeaderCustomCell = (props: any) => {
return (
<HeaderThElement scope="col" columnId={ props.thProps?.columnId || "" } id={ props.thProps.title + "_Header" } { ...props.thProps }>
{ props.children }
</HeaderThElement>
);
};
<Grid cells={{ headerCell: HeaderCustomCell }} ...The SCOPE and ID attributes are ignored and do not show up in the TH tags in the source code. I also tried just returning a basic <th> node from the HeaderCustomCell method and it did not work.
Is there a different method to add custom attributes to the HeaderThElement?
Thanks in advance
