Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Enhancement of Visual Json Schema Editor #1065

Merged
merged 39 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
06a2f4e
changed type of property function
Gmin2 Apr 5, 2024
d5104da
added ability to delete properties and added property function for ca…
Gmin2 Apr 5, 2024
3d33502
added toggle property for nested and non nested objects
Gmin2 Apr 8, 2024
c530d52
modified the UI
Gmin2 Apr 10, 2024
fa72fc6
improve the UI
Gmin2 Apr 10, 2024
3e567cb
cleanup
Gmin2 Apr 10, 2024
284832a
modified the delete property
Gmin2 Apr 10, 2024
d81d930
array of type is visible
Gmin2 Apr 12, 2024
2ceb3c6
fix for adding property type to `array<object>`
Gmin2 Apr 12, 2024
dadc00d
added all the changes requested
Gmin2 Apr 12, 2024
4334c14
cleanup
Gmin2 Apr 12, 2024
04648c8
added option to `add property` to the `array<object>` type, in the UI…
Gmin2 Apr 15, 2024
1b1fd96
cleanup
Gmin2 Apr 15, 2024
b821555
Merge branch 'master' into test-editor
princerajpoot20 Apr 16, 2024
f5329d9
Merge branch 'master' of https://github.com/utnim2/studio into test-e…
Gmin2 May 7, 2024
88694a2
Merge branch 'test-editor' of https://github.com/utnim2/studio into t…
Gmin2 May 7, 2024
9983711
added ability to change array items
Gmin2 May 13, 2024
ccd6ea3
chnage color function
Gmin2 May 13, 2024
f75170c
enter
Gmin2 May 13, 2024
3b9320d
Revert "enter"
Gmin2 May 13, 2024
a9a5c0e
enter
Gmin2 May 13, 2024
f3d2278
added the remaining changes
Gmin2 May 18, 2024
398711b
Merge branch 'master' into test-editor
KhudaDad414 May 20, 2024
d05bf8a
added some changes
Gmin2 May 21, 2024
5e9c28f
added collapsable icon for object & array
Gmin2 May 22, 2024
13bc7c8
Merge branch 'master' into test-editor
princerajpoot20 May 22, 2024
562c640
added pnpm lock file
Gmin2 May 22, 2024
a3b9654
removed unused prop in Dropdown
Gmin2 May 24, 2024
e18dedd
cleanup
Gmin2 May 24, 2024
472ae06
fixed sonarcloud error
Gmin2 May 24, 2024
b616a30
cleannnn
Gmin2 May 24, 2024
33e0b9f
added some reviewed change
Gmin2 May 27, 2024
2be5cb0
removed unused props in dropdownEditor
Gmin2 May 29, 2024
67d41dd
Revert "removed unused props in dropdownEditor"
Gmin2 May 29, 2024
7b4fb9d
added three more examples and resolved some bugs
Gmin2 May 30, 2024
a08b46d
corrected all the changes
Gmin2 Jun 2, 2024
3648dc0
required array is removed when changing types and removing a property
Gmin2 Jun 4, 2024
cf87bb9
cleanup
Gmin2 Jun 5, 2024
7707e06
when changing type the root properties is removed
Gmin2 Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions packages/ui/components/VisualEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react';
import SchemaObject from './VisualEditor/SchemaObject';
import _ from 'lodash';
import { getColorForType } from './VisualEditor/SchemaProperty';

interface VisualEditorProps {
schema: string;
Expand All @@ -15,14 +16,7 @@ interface SchemaObjectInterface {
}

export const VisualEditor: React.FC<VisualEditorProps> = ({ schema, onSchemaChange }) => {
const selectStyle = {
backgroundColor: '#0F172A',
color: 'white',
borderRadius: '3px',
fontSize: '12px',
fontFamily: 'Inter, sans-serif'
};


const [schemaObject, setSchemaObject] = useState<SchemaObjectInterface>({});

useEffect(() => {
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -43,6 +37,14 @@ export const VisualEditor: React.FC<VisualEditorProps> = ({ schema, onSchemaChan
onSchemaChange(newSchemaString);
};

const selectStyle = {
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
backgroundColor: '#0F172A',
color: getColorForType(schemaObject.type || 'white', schemaObject.items?.type || 'red'),
borderRadius: '3px',
fontSize: '12px',
fontFamily: 'Inter, sans-serif'
};

const renderRootTypeSelector = () => (
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
<div>
<select
Expand Down
104 changes: 71 additions & 33 deletions packages/ui/components/VisualEditor/PropertyControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ interface PropertyControlsProps {
const PropertyControls: React.FC<PropertyControlsProps> = ({ onAdd, schemaPath, level }) => {
const inputAndSelectStyle = {
backgroundColor: '#0F172A',
color: 'white',
borderRadius: '3px',
padding: '2px',
fontSize: '14px',
fontFamily: 'Inter, Helvetica'
fontFamily: 'Inter, Helvetica',
};

const [key, setKey] = useState('');
const [type, setType] = useState('');
const [error, setError] = useState('');
const [itemType, setItemType] = useState('');
const [showInputs, setShowInputs] = useState(false);

const handleAddProperty = () => {
if (_.isEmpty(key) || _.isEmpty(type)) {
Expand All @@ -31,58 +31,96 @@ const PropertyControls: React.FC<PropertyControlsProps> = ({ onAdd, schemaPath,
const fullPath = schemaPath ? `${schemaPath}.properties.${key}` : `properties.${key}`;
console.log('Full Full Path :)', fullPath);
console.log(`Adding new property at: ${fullPath}`);

onAdd(fullPath, {
type,
...(type === 'object' && { properties: {} }),
...(type === 'array' && { items: { type: itemType } })
...(type === 'array' && {
items: (itemType !== 'object')
? { type: itemType }
: {
type: 'object',
properties: {},
}
})
} as any);

setKey('');
setType('');
setItemType('');
setError('');
setShowInputs(false);
};

const handleCancel = () => {
setKey('');
setType('');
setItemType('');
setError('');
setShowInputs(false);
};

return (
<div style={{
marginLeft: `${level === 0 ? 20 : level * 20}px`,
color: '#CBD5E1',
fontFamily: 'Inter, sans-serif',
borderLeft: '1px solid grey',
paddingLeft: '10px',
marginTop: '-1px',
}}>
<div className="flex gap-[6px] items-center mt-[6px] mb-[6px]">
<input
type="text"
value={key}
onChange={(e) => setKey(e.target.value)}
placeholder="Property name"
style={inputAndSelectStyle}
<div className="">
<div style={{
display: 'flex',
alignItems: 'center',
marginLeft: `${level === 0 ? 20 : level * 20}px`,
color: '#CBD5E1',
fontFamily: 'Inter, sans-serif',
borderLeft: '1px solid grey',
marginTop: '-1px',
}}>
<div
style={{
borderTop: '1px solid grey',
width: `${level === 0 ? 20 : level * 20}px`,
}}
/>
<select value={type} onChange={(e) => setType(e.target.value)} style={inputAndSelectStyle}>
<option value="">Select type</option>
<option value="string">String</option>
<option value="number">Number</option>
<option value="boolean">Boolean</option>
<option value="object">Object</option>
<option value="array">Array</option>
</select>
{type === 'array' && (
<select value={itemType} onChange={(e) => setItemType(e.target.value)} style={inputAndSelectStyle}>
<option value="">Select item type</option>
{!showInputs && (
<button onClick={() => setShowInputs(true)} className='text-[#808080] px-2 py-2 rounded-md flex items-center gap-2 font-inter text-sm'>
<div className="text-[#808080] border-2 border-[#808080] h-5 w-5 rounded-full flex items-center justify-center">
<span>&#43;</span>
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
</div>
Add Property
</button>
)}
{showInputs && (
<div className='flex gap-[6px] items-center mt-[6px] mb-[6px]'>
<input
type="text"
value={key}
onChange={(e) => setKey(e.target.value)}
placeholder="Property name"
style={inputAndSelectStyle}
/>
<select value={type} onChange={(e) => setType(e.target.value)} style={inputAndSelectStyle}>
<option value="">Select type</option>
<option value="string">String</option>
<option value="number">Number</option>
<option value="boolean">Boolean</option>
<option value="object">Object</option>
<option value="array">Array</option>
</select>
{type === 'array' && (
<select value={itemType} onChange={(e) => setItemType(e.target.value)} style={inputAndSelectStyle}>
<option value="">Select item type</option>
<option value="string">String</option>
<option value="number">Number</option>
<option value="boolean">Boolean</option>
<option value="object">Object</option>
</select>
)}
<button onClick={handleAddProperty} className='inline-flex items-center justify-center px-2 py-1 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500'>Add</button>
<button onClick={handleCancel} className="inline-flex items-center justify-center px-2 py-1 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-red-500 hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500">Cancel</button>
</div>
)}
<button onClick={handleAddProperty}>Add Property</button>
</div>
{error && <p style={{ color: '#DB2777' }}>{error}</p>}
<div className="">
{error && <p style={{ color: '#DB2777' }}>{error}</p>}
</div>
</div>
);
);
};

export default PropertyControls;
62 changes: 52 additions & 10 deletions packages/ui/components/VisualEditor/SchemaObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,68 @@ const SchemaObject: React.FC<SchemaObjectProps> = ({
const normalizedPath = fullPath.startsWith('.') ? fullPath.slice(1) : fullPath;
console.log('Normalised path',normalizedPath);
_.set(updatedSchema, normalizedPath, propertySchema);

console.log(`Property added at ${normalizedPath}`, updatedSchema);
onSchemaChange(updatedSchema);
};

const handleRemoveProperty = (propertyPath: string) => {
const currentSchema = _.cloneDeep(schema);
_.unset(currentSchema, propertyPath);
console.log(`Removed property at ${propertyPath}`);
onSchemaChange(currentSchema);
const updatedSchema = _.cloneDeep(schema);
const normalizedPath = propertyPath.startsWith('.') ? propertyPath.slice(1) : propertyPath;
console.log("normalizedPath: ",normalizedPath)
console.log("propertyPath: ",propertyPath)
_.unset(updatedSchema, normalizedPath);
onSchemaChange(updatedSchema);
};

const handleTypeChange = (propertyPath: string, newSchema: any) => { // Added types to resolve TS7006
console.log(`handleTypeChange called with path: ${propertyPath}, newType: ${newSchema}`);
const handleTypeChange = (propertyPath: string, newSchema: any, newType: any) => { // Added types to resolve TS7006
console.log(`handleTypeChange called with path: ${propertyPath}, newType: ${newType}`);
const normalizedPath = propertyPath.startsWith('.') ? propertyPath.slice(1) : propertyPath;
const typePath = `${normalizedPath}.type`;
const newTypeValue = newType.type;
const currentSchema = _.cloneDeep(schema);
_.set(currentSchema, propertyPath, newSchema);
_.set(currentSchema, typePath , newTypeValue);
console.log(`Type changed at ${propertyPath}`, newSchema);
onSchemaChange(currentSchema);
};

const handleToggleRequired = (path:string, name: string) => {
const updatedSchema = _.cloneDeep(schema);
const existingRequired = _.get(updatedSchema, `required`, []);
const isRequirePresent = existingRequired.includes(name);
console.log("isRequired",isRequirePresent);
if(!isRequirePresent) {
const newRequired = _.uniq([...existingRequired, name]);
_.set(updatedSchema, `required`, newRequired);
} else {
const newRequired = existingRequired.filter((item: string) => item !== name);
_.set(updatedSchema, `required`, newRequired);
}

onSchemaChange(updatedSchema);
}

const handleToggleNestedRequired = (path: string, name: string) => {
const updatedSchema = _.cloneDeep(schema);
const normalizedPath = path.startsWith('.') ? path.slice(1) : path;
const schemaPath = normalizedPath.split('.properties');
console.log("schemaPath",schemaPath)
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
const requiredPath = schemaPath.slice(0, -1).join('.properties') + '.required';
console.log("requiredPath",requiredPath)

const existingRequired = _.get(updatedSchema, requiredPath, []);
const isRequirePresent = existingRequired.includes(name);

if (!isRequirePresent) {
const newRequired = _.uniq([...existingRequired, name]);
_.set(updatedSchema, requiredPath, newRequired);
} else {
const newRequired = existingRequired.filter((item: string) => item !== name);
_.set(updatedSchema, requiredPath, newRequired);
}

onSchemaChange(updatedSchema);
};

return (
<div style={{ margin: '10px 0' }}>
Gmin2 marked this conversation as resolved.
Show resolved Hide resolved
{_.map(schema.properties, (propertySchema, propertyName) => (
Expand All @@ -51,12 +93,12 @@ const SchemaObject: React.FC<SchemaObjectProps> = ({
name={propertyName}
schema={propertySchema}
onRemove={handleRemoveProperty}
onToggleRequired={() => console.log('Toggling required')}
onToggleRequired={handleToggleRequired}
isRequired={_.includes(schema.required, propertyName)}
onTypeChange={handleTypeChange}
onAddNestedProperty={handleAddProperty}
onRemoveNestedProperty={handleRemoveProperty}
onToggleNestedRequired={() => console.log('Toggling nested required')}
onToggleNestedRequired={handleToggleNestedRequired}
path={`${path}.properties.${propertyName}`}
level={level + 1}
/>
Expand Down
Loading
Loading