Big refactoring with properties + Implement Property

This commit is contained in:
Siklos 2022-08-01 16:16:31 +02:00
parent 43fb019e05
commit d2492520b4
5 changed files with 133 additions and 28 deletions

View file

@ -43,16 +43,16 @@ class App extends React.Component<IAppProps> {
const MainContainer = new Container(
{
parent: null,
properties: {
id: 'main',
x: 0,
y: 0,
width: configuration.MainContainer.Width,
height: configuration.MainContainer.Height,
children: [],
style: {
fillOpacity: 0,
stroke: 'black'
} as React.CSSProperties
},
children: []
}
);
this.setState(prevState => ({
@ -82,6 +82,46 @@ class App extends React.Component<IAppProps> {
} as IAppProps);
}
public OnPropertyChange(key: string, value: string) {
if (this.state.SelectedContainer === null ||
this.state.SelectedContainer === undefined) {
throw new Error('Property was changed before selecting a Container');
}
if (this.state.MainContainer === null ||
this.state.MainContainer === undefined) {
throw new Error('Property was changed before the main container was added');
}
const pair = {} as Record<string, string>;
pair[key] = value;
const properties = Object.assign(this.state.SelectedContainer.props.properties, pair);
const props = {
...this.state.SelectedContainer.props,
properties
};
const newSelectedContainer = new Container(props);
const parent = this.state.SelectedContainer.props.parent;
if (parent === null) {
this.setState({
SelectedContainer: newSelectedContainer,
MainContainer: newSelectedContainer
});
return;
}
const index = parent.props.children.indexOf(this.state.SelectedContainer);
parent.props.children[index] = newSelectedContainer;
const newMainContainer = new Container(Object.assign({}, this.state.MainContainer.props));
this.setState({
SelectedContainer: newSelectedContainer,
MainContainer: newMainContainer
});
}
public AddContainer(type: string): void {
if (this.state.SelectedContainer === null ||
this.state.SelectedContainer === undefined) {
@ -111,13 +151,15 @@ class App extends React.Component<IAppProps> {
const count = newCounters[type];
const container = new Container({
parent,
properties: {
id: `${type}-${count}`,
x: 0,
y: 0,
width: properties?.Width,
height: parent.props.height,
height: parent.props.properties.height,
...properties.Style
},
children: [],
style: properties.Style,
userData: {
type
}
@ -148,6 +190,7 @@ class App extends React.Component<IAppProps> {
SelectedContainer={this.state.SelectedContainer}
isOpen={this.state.isSVGSidebarOpen}
onClick={() => this.ToggleSVGSidebar()}
onPropertyChange={(key: string, value: string) => this.OnPropertyChange(key, value)}
selectContainer={(container: Container) => this.SelectContainer(container)}
/>
<button className='fixed z-10 top-4 right-12 text-lg bg-slate-200 hover:bg-slate-300 transition-all drop-shadow-md hover:drop-shadow-lg py-2 px-3 rounded-lg' onClick={() => this.ToggleSVGSidebar()}>&#9776; Menu</button>

View file

@ -1,4 +1,5 @@
import * as React from 'react';
import { Properties } from '../Properties/Properties';
import { Container } from '../SVG/Elements/Container';
interface IElementsSidebarProps {
@ -6,6 +7,7 @@ interface IElementsSidebarProps {
isOpen: boolean,
SelectedContainer: Container | null,
onClick: () => void,
onPropertyChange: (key: string, value: string) => void,
selectContainer: (container: Container) => void
}
@ -39,10 +41,10 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
const containerRows: React.ReactNode[] = [];
this.iterateChilds((container: Container) => {
const depth: number = Container.getDepth(container);
const key = container.props.id.toString();
const key = container.props.properties.id.toString();
const text = '|\t'.repeat(depth) + key;
const selectedClass: string = this.props.SelectedContainer !== null &&
this.props.SelectedContainer.props.id === container.props.id
this.props.SelectedContainer.props.properties.id === container.props.properties.id
? 'bg-blue-500 hover:bg-blue-600'
: 'bg-slate-400 hover:bg-slate-600';
containerRows.push(
@ -53,7 +55,7 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
});
return (
<div className={`fixed bg-slate-400 text-white transition-all h-screen w-64 overflow-y-auto z-20 ${isOpenClasses}`}>
<div className={`fixed flex flex-col bg-slate-400 text-white transition-all h-screen w-64 overflow-y-auto z-20 ${isOpenClasses}`}>
<button className='close-button hover:bg-slate-600 justify-start' onClick={this.props.onClick}>
&times; Close
</button>
@ -63,6 +65,7 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
<div className='overflow-auto divide-y divide-solid divide-slate-500'>
{ containerRows }
</div>
<Properties properties={this.props.SelectedContainer?.GetProperties()} onChange={this.props.onPropertyChange}></Properties>
</div>
);
}

View file

@ -0,0 +1,48 @@
import * as React from 'react';
import ContainerProperties from '../../Interfaces/Properties';
interface IPropertiesProps {
properties?: ContainerProperties,
onChange: (key: string, value: string) => void
}
interface IPropertiesState {
hasUpdate: boolean
}
export class Properties extends React.Component<IPropertiesProps, IPropertiesState> {
public state: IPropertiesState;
constructor(props: IPropertiesProps) {
super(props);
this.state = {
hasUpdate: false
};
}
public render() {
if (this.props.properties === undefined) {
return <div></div>;
}
const groupInput: React.ReactNode[] = [];
Object.entries(this.props.properties).forEach((pair) => this.handleProperties(pair, groupInput));
return (
<div>
{ groupInput }
</div>
);
}
public handleProperties = ([key, value]: [string, string | number], groupInput: React.ReactNode[]) => {
const id = `property-${key}`;
const type = typeof value === 'number' ? 'number' : 'text';
groupInput.push(
<div key={id}>
<label className='' htmlFor={id}>{key}</label>
<input className='text-black' type={type} id={id} value={value} onChange={(event) => this.props.onChange(key, event.target.value)} />
</div>
);
};
}

View file

@ -1,16 +1,12 @@
import * as React from 'react';
import Properties from '../../../Interfaces/Properties';
interface IContainerProps {
// eslint-disable-next-line no-use-before-define
parent: Container | null,
id: string,
// eslint-disable-next-line no-use-before-define
children: Container[],
x: number,
y: number,
width: number,
height: number,
style?: React.CSSProperties,
properties: Properties,
userData?: Record<string, string | number>
}
@ -18,17 +14,25 @@ export class Container extends React.Component<IContainerProps> {
componentWillUnMount() {
}
public GetProperties(): Properties {
const properties : Properties = {
...this.props.properties
};
return properties;
}
public render(): React.ReactNode {
const containersElements = this.props.children.map(child => child.render());
const style = Object.assign({}, this.props.properties);
style.x = 0;
style.y = 0;
return (
<g
transform={`translate(${this.props.x}, ${this.props.y})`}
key={`container-${this.props.id}`}
transform={`translate(${this.props.properties.x}, ${this.props.properties.y})`}
key={`container-${this.props.properties.id}`}
>
<rect
width={this.props.width}
height={this.props.height}
style={this.props.style}
style={style}
>
</rect>
{ containersElements }

View file

@ -0,0 +1,7 @@
import * as React from 'react';
export default interface Properties extends React.CSSProperties {
id: string,
x: number,
y: number,
}