Added basic support for linking DatasetBuilder datasets to lcp-data-collection CPT, and support for deleting datasets and datapoint in the DatasetBuilder.

This commit is contained in:
Jeremy Rangel
2025-01-16 18:39:08 -08:00
parent 436af3dd29
commit 197c9fd3da
4 changed files with 199 additions and 43 deletions

View File

@ -14,12 +14,13 @@ import {
import { useState, useRef } from '@wordpress/element';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import apiFetch from '@wordpress/api-fetch';
const ItemTypes = {
DATASET_ITEM: 'dataset_item'
};
const DatasetItem = ({ item, datasetKey, moveItem, updateItem, items }) => {
const DatasetItem = ({ item, datasetKey, moveItem, updateItem, items, onDelete }) => {
const [showColorPicker, setShowColorPicker] = useState(false);
const ref = useRef(null);
@ -132,6 +133,18 @@ const DatasetItem = ({ item, datasetKey, moveItem, updateItem, items }) => {
</Popover>
)}
</div>
<Button
variant="secondary"
isDestructive
isSmall
onClick={() => {
if (window.confirm(__('Are you sure you want to delete this item?', 'lcp'))) {
onDelete(item.id);
}
}}
>
{__('Delete', 'lcp')}
</Button>
</div>
</CardBody>
</Card>
@ -145,6 +158,7 @@ const DatasetItem = ({ item, datasetKey, moveItem, updateItem, items }) => {
moveItem={moveItem}
updateItem={updateItem}
items={items}
onDelete={onDelete}
/>
))}
</div>
@ -154,14 +168,25 @@ const DatasetItem = ({ item, datasetKey, moveItem, updateItem, items }) => {
const LCPDatasetBuilder = ({ value, onChange }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const [datasets, setDatasets] = useState(value || {});
const [isSaving, setIsSaving] = useState(false);
const [editingDataset, setEditingDataset] = useState(null);
const addNewDataset = () => {
const newDatasetName = `Dataset ${Object.keys(datasets).length + 1}`;
const defaultName = 'New Dataset';
let newName = defaultName;
let counter = 1;
// Ensure unique name
while (datasets[newName]) {
newName = `${defaultName} ${counter}`;
counter++;
}
const updatedDatasets = {
...datasets,
[newDatasetName]: [{
[newName]: [{
id: `dataset-${Date.now()}`,
label: newDatasetName,
label: 'New Item',
parent: null,
value: 0,
color: '#000000'
@ -169,6 +194,44 @@ const LCPDatasetBuilder = ({ value, onChange }) => {
};
setDatasets(updatedDatasets);
onChange(updatedDatasets);
setEditingDataset(newName);
};
const renameDataset = (oldName, newName) => {
if (oldName === newName || !newName.trim() || datasets[newName]) {
setEditingDataset(null);
return;
}
const updatedDatasets = { ...datasets };
updatedDatasets[newName] = updatedDatasets[oldName];
delete updatedDatasets[oldName];
setDatasets(updatedDatasets);
onChange(updatedDatasets);
setEditingDataset(null);
};
const deleteDataset = (datasetKey) => {
const updatedDatasets = { ...datasets };
delete updatedDatasets[datasetKey];
setDatasets(updatedDatasets);
onChange(updatedDatasets);
};
const deleteItem = (datasetKey, itemId) => {
const updatedDatasets = { ...datasets };
// Remove the item and its children
const removeItemAndChildren = (items, targetId) => {
return items.filter(item => {
if (item.id === targetId) return false;
if (item.parent === targetId) return false;
return true;
});
};
updatedDatasets[datasetKey] = removeItemAndChildren(updatedDatasets[datasetKey], itemId);
setDatasets(updatedDatasets);
onChange(updatedDatasets);
};
const addNewItem = (datasetKey) => {
@ -231,45 +294,127 @@ const LCPDatasetBuilder = ({ value, onChange }) => {
onChange(updatedDatasets);
};
const saveToCollection = async () => {
try {
setIsSaving(true);
console.log('Chart data:', datasets);
const formattedDatasets = Object.entries(datasets).map(([name, data]) => ({
dataset_name: name,
dataset_source: 'json',
dataset_json: data
}));
console.log('Formatted datasets:', formattedDatasets);
// Create the post first
const postResponse = await apiFetch({
path: '/wp/v2/lcp-data-collection',
method: 'POST',
data: {
title: Object.keys(datasets)[0] || 'Dataset Collection',
status: 'publish',
meta: {
lcp_datasets: formattedDatasets
}
}
});
console.log('Post created:', postResponse);
console.log('Meta data in response:', postResponse.meta);
// Double-check the meta was saved by fetching the post
const savedPost = await apiFetch({
path: `/wp/v2/lcp-data-collection/${postResponse.id}`,
method: 'GET'
});
console.log('Saved post data:', savedPost);
console.log('Saved meta data:', savedPost.meta?.lcp_datasets);
} catch (error) {
console.error('Error saving dataset:', error);
console.log('Error details:', {
message: error.message,
code: error.code,
data: error.data
});
} finally {
setIsSaving(false);
}
};
return (
<>
<Button
variant="primary"
onClick={() => {
setIsModalOpen(true);
if (Object.keys(datasets).length === 0) {
addNewDataset();
}
}}
onClick={() => setIsModalOpen(true)}
>
{__('Open Dataset Builder', 'lcp')}
</Button>
{isModalOpen && (
<Modal
title={__('Dataset Builder', 'lcp')}
onRequestClose={() => setIsModalOpen(false)}
style={{ width: '90vw' }}
style={{ width: '100%', maxWidth: '800px' }}
>
<DndProvider backend={HTML5Backend}>
<div style={{ padding: '20px' }}>
{Object.entries(datasets).map(([datasetKey, items]) => (
<div key={datasetKey} style={{ marginBottom: '20px' }}>
<h3>{datasetKey}</h3>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '10px' }}>
{editingDataset === datasetKey ? (
<TextControl
value={datasetKey}
onChange={(newName) => renameDataset(datasetKey, newName)}
onKeyDown={(e) => {
if (e.key === 'Enter') {
renameDataset(datasetKey, e.target.value);
} else if (e.key === 'Escape') {
setEditingDataset(null);
}
}}
autoFocus
/>
) : (
<>
<h3 style={{ margin: 0 }}>{datasetKey}</h3>
<Button
variant="secondary"
isSmall
onClick={() => setEditingDataset(datasetKey)}
>
{__('Rename', 'lcp')}
</Button>
<Button
variant="secondary"
isDestructive
isSmall
onClick={() => {
if (window.confirm(__('Are you sure you want to delete this dataset?', 'lcp'))) {
deleteDataset(datasetKey);
}
}}
>
{__('Delete', 'lcp')}
</Button>
</>
)}
</div>
<div>
{items
.filter(item => !item.parent) // Only render top-level items
.filter(item => !item.parent)
.map(item => (
<DatasetItem
key={item.id}
item={item}
datasetKey={datasetKey}
item={item}
items={items}
moveItem={moveItem}
updateItem={updateItem}
items={items}
onDelete={(itemId) => deleteItem(datasetKey, itemId)}
/>
))
}
))}
</div>
<Button
variant="secondary"
@ -280,13 +425,21 @@ const LCPDatasetBuilder = ({ value, onChange }) => {
</Button>
</div>
))}
<Button
variant="primary"
onClick={addNewDataset}
style={{ marginTop: '20px' }}
>
{__('Add New Dataset', 'lcp')}
</Button>
<div style={{ display: 'flex', gap: '10px', marginTop: '20px' }}>
<Button
variant="primary"
onClick={addNewDataset}
>
{__('Add New Dataset', 'lcp')}
</Button>
<Button
variant="secondary"
onClick={saveToCollection}
disabled={isSaving}
>
{isSaving ? __('Saving...', 'lcp') : __('Save to Collection', 'lcp')}
</Button>
</div>
</div>
</DndProvider>
</Modal>