Big refactoring with properties + Implement Property
This commit is contained in:
parent
43fb019e05
commit
d2492520b4
5 changed files with 133 additions and 28 deletions
71
src/App.tsx
71
src/App.tsx
|
@ -43,16 +43,16 @@ class App extends React.Component<IAppProps> {
|
||||||
const MainContainer = new Container(
|
const MainContainer = new Container(
|
||||||
{
|
{
|
||||||
parent: null,
|
parent: null,
|
||||||
id: 'main',
|
properties: {
|
||||||
x: 0,
|
id: 'main',
|
||||||
y: 0,
|
x: 0,
|
||||||
width: configuration.MainContainer.Width,
|
y: 0,
|
||||||
height: configuration.MainContainer.Height,
|
width: configuration.MainContainer.Width,
|
||||||
children: [],
|
height: configuration.MainContainer.Height,
|
||||||
style: {
|
|
||||||
fillOpacity: 0,
|
fillOpacity: 0,
|
||||||
stroke: 'black'
|
stroke: 'black'
|
||||||
} as React.CSSProperties
|
},
|
||||||
|
children: []
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.setState(prevState => ({
|
this.setState(prevState => ({
|
||||||
|
@ -82,6 +82,46 @@ class App extends React.Component<IAppProps> {
|
||||||
} as 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 {
|
public AddContainer(type: string): void {
|
||||||
if (this.state.SelectedContainer === null ||
|
if (this.state.SelectedContainer === null ||
|
||||||
this.state.SelectedContainer === undefined) {
|
this.state.SelectedContainer === undefined) {
|
||||||
|
@ -111,13 +151,15 @@ class App extends React.Component<IAppProps> {
|
||||||
const count = newCounters[type];
|
const count = newCounters[type];
|
||||||
const container = new Container({
|
const container = new Container({
|
||||||
parent,
|
parent,
|
||||||
id: `${type}-${count}`,
|
properties: {
|
||||||
x: 0,
|
id: `${type}-${count}`,
|
||||||
y: 0,
|
x: 0,
|
||||||
width: properties?.Width,
|
y: 0,
|
||||||
height: parent.props.height,
|
width: properties?.Width,
|
||||||
|
height: parent.props.properties.height,
|
||||||
|
...properties.Style
|
||||||
|
},
|
||||||
children: [],
|
children: [],
|
||||||
style: properties.Style,
|
|
||||||
userData: {
|
userData: {
|
||||||
type
|
type
|
||||||
}
|
}
|
||||||
|
@ -148,6 +190,7 @@ class App extends React.Component<IAppProps> {
|
||||||
SelectedContainer={this.state.SelectedContainer}
|
SelectedContainer={this.state.SelectedContainer}
|
||||||
isOpen={this.state.isSVGSidebarOpen}
|
isOpen={this.state.isSVGSidebarOpen}
|
||||||
onClick={() => this.ToggleSVGSidebar()}
|
onClick={() => this.ToggleSVGSidebar()}
|
||||||
|
onPropertyChange={(key: string, value: string) => this.OnPropertyChange(key, value)}
|
||||||
selectContainer={(container: Container) => this.SelectContainer(container)}
|
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()}>☰ Menu</button>
|
<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()}>☰ Menu</button>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { Properties } from '../Properties/Properties';
|
||||||
import { Container } from '../SVG/Elements/Container';
|
import { Container } from '../SVG/Elements/Container';
|
||||||
|
|
||||||
interface IElementsSidebarProps {
|
interface IElementsSidebarProps {
|
||||||
|
@ -6,6 +7,7 @@ interface IElementsSidebarProps {
|
||||||
isOpen: boolean,
|
isOpen: boolean,
|
||||||
SelectedContainer: Container | null,
|
SelectedContainer: Container | null,
|
||||||
onClick: () => void,
|
onClick: () => void,
|
||||||
|
onPropertyChange: (key: string, value: string) => void,
|
||||||
selectContainer: (container: Container) => void
|
selectContainer: (container: Container) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,10 +41,10 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
|
||||||
const containerRows: React.ReactNode[] = [];
|
const containerRows: React.ReactNode[] = [];
|
||||||
this.iterateChilds((container: Container) => {
|
this.iterateChilds((container: Container) => {
|
||||||
const depth: number = Container.getDepth(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 text = '|\t'.repeat(depth) + key;
|
||||||
const selectedClass: string = this.props.SelectedContainer !== null &&
|
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-blue-500 hover:bg-blue-600'
|
||||||
: 'bg-slate-400 hover:bg-slate-600';
|
: 'bg-slate-400 hover:bg-slate-600';
|
||||||
containerRows.push(
|
containerRows.push(
|
||||||
|
@ -53,7 +55,7 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
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}>
|
<button className='close-button hover:bg-slate-600 justify-start' onClick={this.props.onClick}>
|
||||||
× Close
|
× Close
|
||||||
</button>
|
</button>
|
||||||
|
@ -63,6 +65,7 @@ export class ElementsSidebar extends React.Component<IElementsSidebarProps> {
|
||||||
<div className='overflow-auto divide-y divide-solid divide-slate-500'>
|
<div className='overflow-auto divide-y divide-solid divide-slate-500'>
|
||||||
{ containerRows }
|
{ containerRows }
|
||||||
</div>
|
</div>
|
||||||
|
<Properties properties={this.props.SelectedContainer?.GetProperties()} onChange={this.props.onPropertyChange}></Properties>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
48
src/Components/Properties/Properties.tsx
Normal file
48
src/Components/Properties/Properties.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,16 +1,12 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import Properties from '../../../Interfaces/Properties';
|
||||||
|
|
||||||
interface IContainerProps {
|
interface IContainerProps {
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
parent: Container | null,
|
parent: Container | null,
|
||||||
id: string,
|
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
children: Container[],
|
children: Container[],
|
||||||
x: number,
|
properties: Properties,
|
||||||
y: number,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
style?: React.CSSProperties,
|
|
||||||
userData?: Record<string, string | number>
|
userData?: Record<string, string | number>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,17 +14,25 @@ export class Container extends React.Component<IContainerProps> {
|
||||||
componentWillUnMount() {
|
componentWillUnMount() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GetProperties(): Properties {
|
||||||
|
const properties : Properties = {
|
||||||
|
...this.props.properties
|
||||||
|
};
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const containersElements = this.props.children.map(child => child.render());
|
const containersElements = this.props.children.map(child => child.render());
|
||||||
|
const style = Object.assign({}, this.props.properties);
|
||||||
|
style.x = 0;
|
||||||
|
style.y = 0;
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
transform={`translate(${this.props.x}, ${this.props.y})`}
|
transform={`translate(${this.props.properties.x}, ${this.props.properties.y})`}
|
||||||
key={`container-${this.props.id}`}
|
key={`container-${this.props.properties.id}`}
|
||||||
>
|
>
|
||||||
<rect
|
<rect
|
||||||
width={this.props.width}
|
style={style}
|
||||||
height={this.props.height}
|
|
||||||
style={this.props.style}
|
|
||||||
>
|
>
|
||||||
</rect>
|
</rect>
|
||||||
{ containersElements }
|
{ containersElements }
|
||||||
|
|
7
src/Interfaces/Properties.ts
Normal file
7
src/Interfaces/Properties.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export default interface Properties extends React.CSSProperties {
|
||||||
|
id: string,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue