/** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; import { SelectControl, TextareaControl, Button, TextControl } from '@wordpress/components'; import { useState, useEffect } from '@wordpress/element'; import { MediaUpload, MediaUploadCheck } from '@wordpress/block-editor'; import LCPDatasetBuilder from './LCPDatasetBuilder'; const DEFAULT_COLORS = [ '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40', '#FF6384', '#C9CBCF', '#4BC0C0', '#FF9F40' ]; /** * LCPDataSelector Component * * @param {Object} props Component properties * @param {Object} props.value Current data value * @param {Function} props.onChange Callback function when data changes * @param {string} props.dataSource Current data source type * @param {Function} props.onDataSourceChange Callback function when data source changes */ const LCPDataSelector = ({ value, onChange, dataSource, onDataSourceChange }) => { const [csvUrl, setCsvUrl] = useState(''); const [jsonData, setJsonData] = useState(''); const [error, setError] = useState(''); // Initialize component state with existing data useEffect(() => { if (value && Object.keys(value).length > 0) { if (dataSource === 'manual_json') { setJsonData(JSON.stringify(value, null, 2)); } else if (dataSource === 'csv_url') { const storedUrl = value[Object.keys(value)[0]]?.[0]?.sourceUrl; if (storedUrl) { setCsvUrl(storedUrl); } } } }, []); const dataSourceOptions = [ { label: __('Manual JSON', 'lcp'), value: 'manual_json' }, { label: __('CSV Upload', 'lcp'), value: 'csv_upload' }, { label: __('CSV URL', 'lcp'), value: 'csv_url' }, { label: __('Dataset Builder', 'lcp'), value: 'dataset_builder' }, ]; const validateJsonData = (jsonString) => { try { const parsed = JSON.parse(jsonString); if (typeof parsed !== 'object' || Array.isArray(parsed)) { throw new Error('Data must be an object with dataset names as keys'); } // Validate each dataset Object.entries(parsed).forEach(([datasetName, dataset]) => { if (!Array.isArray(dataset)) { throw new Error(`Dataset "${datasetName}" must be an array`); } dataset.forEach((item, index) => { if (!item.label || !item.value) { throw new Error(`Item at index ${index} in dataset "${datasetName}" is missing required fields (label or value)`); } // Add default color if not provided if (!item.color) { item.color = DEFAULT_COLORS[index % DEFAULT_COLORS.length]; } }); }); setError(''); return parsed; } catch (e) { setError(e.message); return null; } }; const handleJsonChange = (newJsonData) => { setJsonData(newJsonData); const validData = validateJsonData(newJsonData); if (validData) { onChange(validData); } }; const handleCsvUpload = (media) => { const sourceUrl = media.url; fetch(media.url) .then(response => response.text()) .then(csvText => { const data = parseCsvToJson(csvText, sourceUrl); if (data) { onChange(data); } }) .catch(err => { setError('Error reading CSV file: ' + err.message); }); }; const handleCsvUrlChange = (url) => { setCsvUrl(url); if (url) { fetch(url) .then(response => response.text()) .then(csvText => { const data = parseCsvToJson(csvText, url); if (data) { onChange(data); } }) .catch(err => { setError('Error fetching CSV file: ' + err.message); }); } }; const parseCsvToJson = (csvText, sourceUrl = '') => { try { const lines = csvText.split('\n'); if (lines.length < 2) { throw new Error('CSV must have at least a header row and one data row'); } const headers = lines[0].split(',').map(h => h.trim()); if (!headers.includes('label') || !headers.includes('value')) { throw new Error('CSV must have "label" and "value" columns'); } // Create a single dataset from CSV const dataset = lines.slice(1) .filter(line => line.trim()) .map((line, index) => { const values = line.split(',').map(v => v.trim()); const item = {}; headers.forEach((header, i) => { if (header === 'color' && !values[i]) { item[header] = DEFAULT_COLORS[index % DEFAULT_COLORS.length]; } else { item[header] = values[i]; } }); if (sourceUrl) { item.sourceUrl = sourceUrl; } return item; }); // Create the new data structure const data = { 'Dataset 1': dataset }; setError(''); return data; } catch (e) { setError('Error parsing CSV: ' + e.message); return null; } }; return (
{dataSource === 'dataset_builder' && ( { onChange(newValue); }} /> )} {dataSource === 'manual_json' && ( )} {dataSource === 'csv_upload' && ( (
{value && Object.keys(value).length > 0 && value[Object.keys(value)[0]]?.[0]?.sourceUrl && (
{__('Current file:', 'lcp')} {value[Object.keys(value)[0]][0].sourceUrl.split('/').pop()}
)}
)} />
)} {dataSource === 'csv_url' && ( )} {error && (
{error}
)} {value && Object.keys(value).length > 0 && (

{__('Current Data Preview:', 'lcp')}

{Object.entries(value).map(([datasetName, dataset]) => (
{datasetName}: {dataset.length} {__('data points', 'lcp')}
))}
)}
); }; export default LCPDataSelector;