✨ Enhanced Object Editor with fetch data & mobile improvements
🚀 New Features: - Fetch Data functionality with URL input and error handling - Auto-protocol detection (adds https:// if missing) - Smart content-type handling for various JSON APIs - Perfect for Telegram Bot API, GitHub API, JSONPlaceholder, etc. 📱 Mobile Responsiveness: - Desktop: Clean tab interface for view modes - Mobile: Native select dropdown with emoji icons - StructuredEditor: Horizontal scroll for wide JSON structures - Input data field auto-hides on successful fetch 🐛 Critical Fixes: - Fixed StructuredEditor reinitialization loop issue - Fixed deep nested property/array item deletion - Proper array splicing and object property removal - Internal vs external data change tracking 🎨 UX Improvements: - Loading states during fetch operations - Better error messages and validation - Responsive button layouts and spacing - Enhanced usage tips with fetch examples
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Plus, Minus, ChevronDown, ChevronRight, Type, Hash, ToggleLeft, List, Braces } from 'lucide-react';
|
||||
|
||||
const StructuredEditor = ({ onDataChange, initialData = {} }) => {
|
||||
const [data, setData] = useState(initialData);
|
||||
const [expandedNodes, setExpandedNodes] = useState(new Set(['root']));
|
||||
const isInternalUpdate = useRef(false);
|
||||
|
||||
// Update internal data when initialData prop changes
|
||||
// Update internal data when initialData prop changes (but not from internal updates)
|
||||
useEffect(() => {
|
||||
console.log('📥 INITIAL DATA CHANGED:', {
|
||||
// Skip update if this change came from internal editor actions
|
||||
if (isInternalUpdate.current) {
|
||||
isInternalUpdate.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📥 EXTERNAL DATA CHANGED:', {
|
||||
keys: Object.keys(initialData),
|
||||
hasData: Object.keys(initialData).length > 0,
|
||||
data: initialData
|
||||
@@ -20,7 +27,8 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
|
||||
}, [initialData]);
|
||||
|
||||
const updateData = (newData) => {
|
||||
console.log('📊 DATA UPDATE:', { keys: Object.keys(newData), totalProps: JSON.stringify(newData).length });
|
||||
console.log('📊 INTERNAL DATA UPDATE:', { keys: Object.keys(newData), totalProps: JSON.stringify(newData).length });
|
||||
isInternalUpdate.current = true; // Mark as internal update
|
||||
setData(newData);
|
||||
onDataChange(newData);
|
||||
};
|
||||
@@ -78,22 +86,31 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
|
||||
};
|
||||
|
||||
const removeProperty = (key, parentPath) => {
|
||||
console.log('🗑️ REMOVE PROPERTY:', { key, parentPath });
|
||||
|
||||
const pathParts = parentPath.split('.');
|
||||
const newData = { ...data };
|
||||
let current = newData;
|
||||
|
||||
// Navigate to the parent object/array
|
||||
for (let i = 1; i < pathParts.length; i++) {
|
||||
if (i === pathParts.length - 1) {
|
||||
delete current[key];
|
||||
} else {
|
||||
current = current[pathParts[i]];
|
||||
}
|
||||
current = current[pathParts[i]];
|
||||
}
|
||||
|
||||
if (pathParts.length === 1) {
|
||||
delete newData[key];
|
||||
// Delete the property/item from the parent
|
||||
if (Array.isArray(current)) {
|
||||
// For arrays, remove by index and reindex
|
||||
current.splice(parseInt(key), 1);
|
||||
} else {
|
||||
// For objects, delete the property
|
||||
delete current[key];
|
||||
}
|
||||
|
||||
console.log('🗑️ REMOVE PROPERTY - After:', {
|
||||
parentPath,
|
||||
remainingKeys: Array.isArray(current) ? current.length : Object.keys(current)
|
||||
});
|
||||
|
||||
updateData(newData);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user