Added basics of LCPLegend and more controls for blocks. Added boilerplate for lcp/line-graph
This commit is contained in:
@ -379,37 +379,51 @@ const LCPDataGrid = ({
|
||||
event.preventDefault();
|
||||
const target = event.target;
|
||||
const rowCell = target.closest('.ag-cell');
|
||||
const headerCell = target.closest('.ag-header-cell');
|
||||
|
||||
if (!rowCell) return;
|
||||
|
||||
const rect = rowCell.getBoundingClientRect();
|
||||
const rowNode = gridRef.current.api.getRowNode(rowCell.parentElement.getAttribute('row-index'));
|
||||
if (!rowNode || !rowNode.data || !rowNode.data.ID) return;
|
||||
|
||||
setContextMenu({
|
||||
type: 'row',
|
||||
position: { top: rect.bottom, left: rect.left },
|
||||
rowIndex: rowNode.rowIndex,
|
||||
totalRows: gridRef.current.api.getDisplayedRowCount()
|
||||
});
|
||||
if (rowCell) {
|
||||
const rect = rowCell.getBoundingClientRect();
|
||||
const rowNode = gridRef.current.api.getRowNode(rowCell.parentElement.getAttribute('row-index'));
|
||||
if (!rowNode || !rowNode.data || !rowNode.data.ID) return;
|
||||
|
||||
setContextMenu({
|
||||
type: 'row',
|
||||
position: {
|
||||
top: event.clientY,
|
||||
left: event.clientX,
|
||||
},
|
||||
rowIndex: rowNode.rowIndex,
|
||||
totalRows: gridRef.current.api.getDisplayedRowCount()
|
||||
});
|
||||
} else if (headerCell) {
|
||||
const rect = headerCell.getBoundingClientRect();
|
||||
const colId = headerCell.getAttribute('col-id');
|
||||
if (!colId) return;
|
||||
|
||||
setContextMenu({
|
||||
type: 'column',
|
||||
position: {
|
||||
top: event.clientY,
|
||||
left: event.clientX,
|
||||
},
|
||||
colId: colId
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleRowAction = useCallback((action, rowIndex) => {
|
||||
const handleRowAction = useCallback((action) => {
|
||||
const newData = [...chartData];
|
||||
const rowIndex = contextMenu.rowIndex;
|
||||
|
||||
// Create empty row with all existing columns
|
||||
const emptyRow = { ID: generateId() };
|
||||
if (chartData.length > 0) {
|
||||
// Get all columns from existing data
|
||||
const columns = Array.from(new Set(
|
||||
chartData.flatMap(item => Object.keys(item))
|
||||
));
|
||||
|
||||
// Initialize each column with an appropriate empty value
|
||||
columns.forEach(col => {
|
||||
if (col === 'ID') return; // Skip Id as it's already set
|
||||
|
||||
// Get a sample value to determine appropriate empty value
|
||||
if (col === 'ID') return;
|
||||
const sampleValue = chartData.find(item => item[col] !== undefined)?.[col];
|
||||
|
||||
switch (typeof sampleValue) {
|
||||
@ -427,19 +441,59 @@ const LCPDataGrid = ({
|
||||
|
||||
switch (action) {
|
||||
case 'add-above':
|
||||
newData.splice(rowIndex - 1, 0, emptyRow);
|
||||
break;
|
||||
case 'add-below':
|
||||
newData.splice(rowIndex, 0, emptyRow);
|
||||
break;
|
||||
case 'add-below':
|
||||
newData.splice(rowIndex + 1, 0, emptyRow);
|
||||
break;
|
||||
case 'delete':
|
||||
newData.splice(rowIndex - 1, 1);
|
||||
newData.splice(rowIndex, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
onDataChange(newData);
|
||||
setContextMenu(null);
|
||||
}, [chartData, onDataChange]);
|
||||
}, [chartData, onDataChange, contextMenu]);
|
||||
|
||||
const handleColumnAction = useCallback((action) => {
|
||||
if (!contextMenu || !contextMenu.colId) return;
|
||||
|
||||
const newData = [...chartData];
|
||||
const colId = contextMenu.colId;
|
||||
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
// Remove the column from all rows
|
||||
newData.forEach(row => {
|
||||
const { [colId]: removed, ...rest } = row;
|
||||
Object.assign(row, rest);
|
||||
});
|
||||
break;
|
||||
case 'add-left':
|
||||
case 'add-right':
|
||||
// Get all existing column names
|
||||
const existingColumns = Object.keys(chartData[0] || {});
|
||||
|
||||
// Find the next available column number
|
||||
let nextNumber = 1;
|
||||
while (existingColumns.includes(`Column${nextNumber}`)) {
|
||||
nextNumber++;
|
||||
}
|
||||
|
||||
const newColId = `Column${nextNumber}`;
|
||||
const insertIndex = columnDefs.findIndex(col => col.field === colId);
|
||||
const finalIndex = action === 'add-right' ? insertIndex + 1 : insertIndex;
|
||||
|
||||
// Add the new column to all rows
|
||||
newData.forEach(row => {
|
||||
row[newColId] = '';
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
onDataChange(newData);
|
||||
setContextMenu(null);
|
||||
}, [chartData, onDataChange, contextMenu, columnDefs]);
|
||||
|
||||
const handleCellValueChanged = useCallback((params) => {
|
||||
if (!params.data || !params.data.ID) return;
|
||||
@ -451,8 +505,15 @@ const LCPDataGrid = ({
|
||||
onDataChange(newData);
|
||||
}, [chartData, onDataChange]);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="ag-theme-alpine" style={{ height: '400px', width: '100%' }}>
|
||||
<div
|
||||
className="ag-theme-alpine"
|
||||
style={{ height: '400px', width: '100%' }}
|
||||
onContextMenu={handleContextMenu}
|
||||
>
|
||||
|
||||
<AgGridReact
|
||||
ref={gridRef}
|
||||
rowData={rowData}
|
||||
@ -472,24 +533,57 @@ const LCPDataGrid = ({
|
||||
position="bottom left"
|
||||
onClose={() => setContextMenu(null)}
|
||||
anchorRect={{
|
||||
top: contextMenu.mouseEvent.clientY,
|
||||
left: contextMenu.mouseEvent.clientX,
|
||||
top: contextMenu.position.top,
|
||||
left: contextMenu.position.left,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}}
|
||||
>
|
||||
<div style={{ padding: '8px' }}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
const selectedRows = gridRef.current.api.getSelectedRows();
|
||||
const newData = chartData.filter(row => !selectedRows.includes(row));
|
||||
onDataChange(newData);
|
||||
setContextMenu(null);
|
||||
}}
|
||||
>
|
||||
{__('Delete Selected Rows', 'lcp-visualize')}
|
||||
</Button>
|
||||
<div style={{ padding: '8px', display: 'flex', flexDirection: 'column', gap: '4px' }}>
|
||||
{contextMenu.type === 'row' && (
|
||||
<>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleRowAction('add-above')}
|
||||
>
|
||||
{__('Add Row Above', 'lcp-visualize')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleRowAction('add-below')}
|
||||
>
|
||||
{__('Add Row Below', 'lcp-visualize')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleRowAction('delete')}
|
||||
>
|
||||
{__('Delete Row', 'lcp-visualize')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
{contextMenu.type === 'column' && (
|
||||
<>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleColumnAction('add-left')}
|
||||
>
|
||||
{__('Add Column Left', 'lcp-visualize')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleColumnAction('add-right')}
|
||||
>
|
||||
{__('Add Column Right', 'lcp-visualize')}
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => handleColumnAction('delete')}
|
||||
>
|
||||
{__('Delete Column', 'lcp-visualize')}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user