Bugfix for data parser and data formatter
This commit is contained in:
@ -3,9 +3,27 @@ import { AgGridReact } from 'ag-grid-react';
|
||||
import 'ag-grid-community/styles/ag-grid.css';
|
||||
import 'ag-grid-community/styles/ag-theme-alpine.css';
|
||||
|
||||
import LCPGridColorRender from './LCPGridColorRender';
|
||||
|
||||
const LCPDataGrid = ({dataset}) => {
|
||||
|
||||
|
||||
// lcpCellRenderer to dynamically assign the right cellRenderer
|
||||
function lcpCellRenderer(params) {
|
||||
const value = params.value;
|
||||
|
||||
// First, check if the value is a Date object
|
||||
if (value instanceof Date) {
|
||||
return value.toLocaleString(); // Return a formatted string (you can format it however you want)
|
||||
}
|
||||
|
||||
// Check if the value is a valid CSS color (this works for string values like '#232323' or 'red')
|
||||
if (isValidCSSColor(value)) {
|
||||
return <LCPGridColorRender value={value} />; // Use the color renderer
|
||||
}
|
||||
|
||||
// Default rendering for other types of data (like text, number, etc.)
|
||||
return value;
|
||||
}
|
||||
const [rowsToAdd, setRowsToAdd] = useState(1); // Number of rows the user wants to add
|
||||
|
||||
const [currentRowCount, setCurrentRowCount] = useState(dataset.length); // Track the current row count
|
||||
@ -43,11 +61,85 @@ const LCPDataGrid = ({dataset}) => {
|
||||
return 'text'; // Defaults to 'text' for strings and others
|
||||
};
|
||||
|
||||
// Helper function to detect if a value is a valid CSS color
|
||||
const isValidCSSColor = (value) => {
|
||||
const cssColorRegex = /^(#([0-9a-fA-F]{3}){1,2}|[a-zA-Z]+|rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)|rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0(\.\d+)?|1(\.0+)?)\)|hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)|hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(0(\.\d+)?|1(\.0+)?)\))$/i;
|
||||
return cssColorRegex.test(value);
|
||||
};
|
||||
|
||||
// Helper function to detect if a value is a valid CSS color
|
||||
const isValidCSSColor = (value) => {
|
||||
// Ensure the value is a string before trimming
|
||||
value = String(value).trim(); // Convert to string if it's not already
|
||||
|
||||
// Regex to match valid CSS color formats (hex, rgb, rgba, hsl, hsla, named colors)
|
||||
const cssColorRegex = /^(#([0-9a-fA-F]{3}){1,2}|[a-zA-Z]+|rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)|rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0(\.\d+)?|1(\.0+)?)\)|hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)|hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(0(\.\d+)?|1(\.0+)?)\))$/i;
|
||||
|
||||
// First check if the value matches the general color regex
|
||||
if (!cssColorRegex.test(value)) {
|
||||
return false; // If it doesn't match any known color format, it's not valid
|
||||
}
|
||||
|
||||
// Now, we'll do more detailed checks for RGB, RGBA, HSL, and HSLA formats
|
||||
|
||||
// Check if it's a valid RGB format (rgb(r, g, b))
|
||||
const rgbMatch = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/i.exec(value);
|
||||
if (rgbMatch) {
|
||||
const r = parseInt(rgbMatch[1], 10);
|
||||
const g = parseInt(rgbMatch[2], 10);
|
||||
const b = parseInt(rgbMatch[3], 10);
|
||||
// RGB values should be in the range 0-255
|
||||
return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255;
|
||||
}
|
||||
|
||||
// Check if it's a valid RGBA format (rgba(r, g, b, a))
|
||||
const rgbaMatch = /^rgba\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3}),\s*(0(\.\d+)?|1(\.0+)?)\)$/i.exec(value);
|
||||
if (rgbaMatch) {
|
||||
const r = parseInt(rgbaMatch[1], 10);
|
||||
const g = parseInt(rgbaMatch[2], 10);
|
||||
const b = parseInt(rgbaMatch[3], 10);
|
||||
const a = parseFloat(rgbaMatch[4]);
|
||||
// RGBA values should be in the range 0-255 for RGB and 0-1 for alpha
|
||||
return r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1;
|
||||
}
|
||||
|
||||
// Check if it's a valid HSL format (hsl(h, s%, l%))
|
||||
const hslMatch = /^hsl\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%\)$/i.exec(value);
|
||||
if (hslMatch) {
|
||||
const h = parseInt(hslMatch[1], 10);
|
||||
const s = parseInt(hslMatch[2], 10);
|
||||
const l = parseInt(hslMatch[3], 10);
|
||||
// Hue should be 0-360, saturation and lightness should be 0-100
|
||||
return h >= 0 && h <= 360 && s >= 0 && s <= 100 && l >= 0 && l <= 100;
|
||||
}
|
||||
|
||||
// Check if it's a valid HSLA format (hsla(h, s%, l%, a))
|
||||
const hslaMatch = /^hsla\((\d{1,3}),\s*(\d{1,3})%,\s*(\d{1,3})%,\s*(0(\.\d+)?|1(\.0+)?)\)$/i.exec(value);
|
||||
if (hslaMatch) {
|
||||
const h = parseInt(hslaMatch[1], 10);
|
||||
const s = parseInt(hslaMatch[2], 10);
|
||||
const l = parseInt(hslaMatch[3], 10);
|
||||
const a = parseFloat(hslaMatch[4]);
|
||||
// Hue should be 0-360, saturation and lightness should be 0-100, alpha should be 0-1
|
||||
return h >= 0 && h <= 360 && s >= 0 && s <= 100 && l >= 0 && l <= 100 && a >= 0 && a <= 1;
|
||||
}
|
||||
|
||||
// If it's a valid named color (like "red", "blue", etc.)
|
||||
const namedColors = [
|
||||
"red", "green", "blue", "yellow", "black", "white", "gray", "purple", "orange", "brown", "pink", "cyan", "magenta",
|
||||
// Add more CSS named colors as necessary
|
||||
];
|
||||
if (namedColors.includes(value.toLowerCase())) {
|
||||
return true; // It's a valid named color
|
||||
}
|
||||
|
||||
// If it's a valid hex color (hex format should be valid)
|
||||
const hexMatch = /^#([0-9a-fA-F]{3}){1,2}$/i.exec(value);
|
||||
if (hexMatch) {
|
||||
return true; // It's a valid hex color
|
||||
}
|
||||
|
||||
// If it passed regex but didn't pass the detailed checks, it's invalid
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// Helper function to detect if a value contains HTML tags
|
||||
const isHTML = (value) => {
|
||||
@ -115,11 +207,10 @@ const LCPDataGrid = ({dataset}) => {
|
||||
return label;
|
||||
};
|
||||
|
||||
// Data parser for Ag Grid based on detected data types
|
||||
function lcpDataTypeParser(params) {
|
||||
const columnName = params.colDef.field; // Get the column field name (e.g., 'Budget', 'MeetAt')
|
||||
const dataType = gridDataTypes[columnName]; // Get the data type for this column from gridDataTypes
|
||||
|
||||
|
||||
if (params.node.rowPinned) {
|
||||
// If it's the pinned top row, return the value as-is
|
||||
return params.newValue;
|
||||
@ -130,11 +221,30 @@ const LCPDataGrid = ({dataset}) => {
|
||||
// If it's a number, return the number or NaN
|
||||
return Number(params.newValue);
|
||||
case 'date':
|
||||
// If it's a date, try to parse the value as a Date
|
||||
const parsedDate = new Date(params.newValue);
|
||||
return !isNaN(parsedDate.getTime()) ? parsedDate : params.newValue; // Return parsed date or original value if invalid
|
||||
const dateStr = params.newValue;
|
||||
|
||||
// Check if the value is an empty string or undefined
|
||||
if (!dateStr || dateStr.trim() === '') {
|
||||
return null; // If empty, return null or any default value you prefer
|
||||
}
|
||||
|
||||
let parsedDate;
|
||||
// Check if the date is in the format "MM/DD/YYYY"
|
||||
const isValidMMDDYYYY = /^\d{2}\/\d{2}\/\d{4}$/.test(dateStr);
|
||||
|
||||
if (isValidMMDDYYYY) {
|
||||
const [month, day, year] = dateStr.split('/');
|
||||
const isoDateStr = `${year}-${month}-${day}`;
|
||||
parsedDate = new Date(isoDateStr);
|
||||
} else {
|
||||
// For other formats, try using the default Date parser
|
||||
parsedDate = new Date(dateStr);
|
||||
}
|
||||
|
||||
// Return parsed date if valid, otherwise return the original string
|
||||
return !isNaN(parsedDate.getTime()) ? parsedDate : dateStr;
|
||||
case 'color':
|
||||
// If it's a color, we don't need to change the value (it's already a valid color)
|
||||
// If it's a color, return the value as-is
|
||||
return params.newValue;
|
||||
case 'html':
|
||||
// If it's HTML, we can either sanitize or leave the value as is (for now, leaving it as is)
|
||||
@ -145,6 +255,9 @@ const LCPDataGrid = ({dataset}) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Create columnDefs dynamically
|
||||
const [columnDefs, setColumnDefs] = useState([]);
|
||||
@ -161,6 +274,9 @@ const LCPDataGrid = ({dataset}) => {
|
||||
headerName: getColumnLabel(index), // 'A', 'B', 'C', ...
|
||||
field: key, // Field will match the key (Department2, Budget, etc.)
|
||||
valueParser: lcpDataTypeParser,
|
||||
cellRenderer: lcpCellRenderer, // Reference the custom cell renderer
|
||||
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
28
blocks/components/LCPGridColorRender.js
Normal file
28
blocks/components/LCPGridColorRender.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
// AG-Grid Cell Renderer Component
|
||||
const LCPGridColorRender = (props) => {
|
||||
const [color, setColor] = useState(props.value || ''); // Get the color value from the cell data
|
||||
|
||||
useEffect(() => {
|
||||
// Update color if the value from AG-Grid changes
|
||||
if (props.value !== color) {
|
||||
setColor(props.value);
|
||||
}
|
||||
}, [props.value]); // Dependency on props.value so it updates when the cell value changes
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '30px',
|
||||
height: '30px',
|
||||
backgroundColor: color,
|
||||
border: '1px solid #000',
|
||||
margin: '0 auto'
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default LCPGridColorRender;
|
||||
|
||||
Reference in New Issue
Block a user