Merged PR 16: Transform every single class components into functional component
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This improve greatly the performance and the code cleaning.
It allows us to separate the inseparable class methods into modules functions
This commit is contained in:
Eric Nguyen 2022-08-09 15:15:56 +00:00
parent 1fc11adbaa
commit d9e06537e8
33 changed files with 1298 additions and 1261 deletions

View file

@ -9,70 +9,68 @@ export interface IContainerProps {
const GAP = 50;
export class Container extends React.PureComponent<IContainerProps> {
/**
* Render the container
* @returns Render the container
*/
public render(): React.ReactNode {
const containersElements = this.props.model.children.map(child => <Container key={`container-${child.properties.id}`} model={child} />);
const xText = Number(this.props.model.properties.width) / 2;
const yText = Number(this.props.model.properties.height) / 2;
const transform = `translate(${Number(this.props.model.properties.x)}, ${Number(this.props.model.properties.y)})`;
/**
* Render the container
* @returns Render the container
*/
export const Container: React.FC<IContainerProps> = (props: IContainerProps) => {
const containersElements = props.model.children.map(child => <Container key={`container-${child.properties.id}`} model={child} />);
const xText = Number(props.model.properties.width) / 2;
const yText = Number(props.model.properties.height) / 2;
const transform = `translate(${Number(props.model.properties.x)}, ${Number(props.model.properties.y)})`;
// g style
const defaultStyle: React.CSSProperties = {
transitionProperty: 'all',
transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
transitionDuration: '150ms'
};
// g style
const defaultStyle: React.CSSProperties = {
transitionProperty: 'all',
transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
transitionDuration: '150ms'
};
// Rect style
const style = Object.assign(
JSON.parse(JSON.stringify(defaultStyle)),
this.props.model.properties
);
style.x = 0;
style.y = 0;
delete style.height;
delete style.width;
// Rect style
const style = Object.assign(
JSON.parse(JSON.stringify(defaultStyle)),
props.model.properties
);
style.x = 0;
style.y = 0;
delete style.height;
delete style.width;
// Dimension props
const id = `dim-${this.props.model.properties.id}`;
const xStart: number = 0;
const xEnd = Number(this.props.model.properties.width);
const y = -(GAP * (getDepth(this.props.model) + 1));
const strokeWidth = 1;
const text = (this.props.model.properties.width ?? 0).toString();
// Dimension props
const id = `dim-${props.model.properties.id}`;
const xStart: number = 0;
const xEnd = Number(props.model.properties.width);
const y = -(GAP * (getDepth(props.model) + 1));
const strokeWidth = 1;
const text = (props.model.properties.width ?? 0).toString();
return (
<g
style={defaultStyle}
transform={transform}
key={`container-${this.props.model.properties.id}`}
return (
<g
style={defaultStyle}
transform={transform}
key={`container-${props.model.properties.id}`}
>
<Dimension
id={id}
xStart={xStart}
xEnd={xEnd}
y={y}
strokeWidth={strokeWidth}
text={text}
/>
<rect
width={props.model.properties.width}
height={props.model.properties.height}
style={style}
>
<Dimension
id={id}
xStart={xStart}
xEnd={xEnd}
y={y}
strokeWidth={strokeWidth}
text={text}
/>
<rect
width={this.props.model.properties.width}
height={this.props.model.properties.height}
style={style}
>
</rect>
<text
x={xText}
y={yText}
>
{this.props.model.properties.id}
</text>
{ containersElements }
</g>
);
}
}
</rect>
<text
x={xText}
y={yText}
>
{props.model.properties.id}
</text>
{ containersElements }
</g>
);
};

View file

@ -9,44 +9,42 @@ interface IDimensionProps {
strokeWidth: number
}
export class Dimension extends React.PureComponent<IDimensionProps> {
public render(): JSX.Element {
const style: React.CSSProperties = {
stroke: 'black'
};
return (
<g key={this.props.id}>
<line
x1={this.props.xStart}
y1={this.props.y - 4 * this.props.strokeWidth}
x2={this.props.xStart}
y2={this.props.y + 4 * this.props.strokeWidth}
strokeWidth={this.props.strokeWidth}
style={style}
/>
<line
x1={this.props.xStart}
y1={this.props.y}
x2={this.props.xEnd}
y2={this.props.y}
strokeWidth={this.props.strokeWidth}
style={style}
/>
<line
x1={this.props.xEnd}
y1={this.props.y - 4 * this.props.strokeWidth}
x2={this.props.xEnd}
y2={this.props.y + 4 * this.props.strokeWidth}
strokeWidth={this.props.strokeWidth}
style={style}
/>
<text
x={(this.props.xStart + this.props.xEnd) / 2}
y={this.props.y}
>
{this.props.text}
</text>
</g>
);
}
}
export const Dimension: React.FC<IDimensionProps> = (props: IDimensionProps) => {
const style: React.CSSProperties = {
stroke: 'black'
};
return (
<g key={props.id}>
<line
x1={props.xStart}
y1={props.y - 4 * props.strokeWidth}
x2={props.xStart}
y2={props.y + 4 * props.strokeWidth}
strokeWidth={props.strokeWidth}
style={style}
/>
<line
x1={props.xStart}
y1={props.y}
x2={props.xEnd}
y2={props.y}
strokeWidth={props.strokeWidth}
style={style}
/>
<line
x1={props.xEnd}
y1={props.y - 4 * props.strokeWidth}
x2={props.xEnd}
y2={props.y + 4 * props.strokeWidth}
strokeWidth={props.strokeWidth}
style={style}
/>
<text
x={(props.xStart + props.xEnd) / 2}
y={props.y}
>
{props.text}
</text>
</g>
);
};

View file

@ -12,74 +12,69 @@ interface ISVGProps {
selected: ContainerModel | null
}
interface ISVGState {
interface Viewer {
viewerWidth: number
viewerHeight: number
}
export class SVG extends React.PureComponent<ISVGProps> {
public static ID = 'svg';
public state: ISVGState;
export const ID = 'svg';
constructor(props: ISVGProps) {
super(props);
this.state = {
viewerWidth: window.innerWidth - BAR_WIDTH,
viewerHeight: window.innerHeight
};
}
resizeViewBox(): void {
this.setState({
viewerWidth: window.innerWidth - BAR_WIDTH,
viewerHeight: window.innerHeight
});
}
componentDidMount(): void {
window.addEventListener('resize', () => this.resizeViewBox());
}
componentWillUnmount(): void {
window.removeEventListener('resize', () => this.resizeViewBox());
}
render(): JSX.Element {
const xmlns = '<http://www.w3.org/2000/svg>';
const properties = {
width: this.props.width,
height: this.props.height,
xmlns
};
let children: React.ReactNode | React.ReactNode[] = [];
if (Array.isArray(this.props.children)) {
children = this.props.children.map(child => <Container key={`container-${child.properties.id}`} model={child}/>);
} else if (this.props.children !== null) {
children = <Container key={`container-${this.props.children.properties.id}`} model={this.props.children}/>;
}
return (
<div id={SVG.ID} className='ml-16'>
<UncontrolledReactSVGPanZoom
width={this.state.viewerWidth}
height={this.state.viewerHeight}
background={'#ffffff'}
defaultTool='pan'
miniatureProps={{
position: 'left',
background: '#616264',
width: window.innerWidth - 12 - BAR_WIDTH,
height: 120
}}
>
<svg {...properties}>
{ children }
<Selector selected={this.props.selected} />
</svg>
</UncontrolledReactSVGPanZoom>
</div>
);
};
function resizeViewBox(
setViewer: React.Dispatch<React.SetStateAction<Viewer>>
): void {
setViewer({
viewerWidth: window.innerWidth - BAR_WIDTH,
viewerHeight: window.innerHeight
});
}
export const SVG: React.FC<ISVGProps> = (props: ISVGProps) => {
const [viewer, setViewer] = React.useState<Viewer>({
viewerWidth: window.innerWidth,
viewerHeight: window.innerHeight
});
React.useEffect(() => {
window.addEventListener('resize', () => resizeViewBox(setViewer));
return () => {
window.addEventListener('resize', () => resizeViewBox(setViewer));
};
});
const xmlns = '<http://www.w3.org/2000/svg>';
const properties = {
width: props.width,
height: props.height,
xmlns
};
let children: React.ReactNode | React.ReactNode[] = [];
if (Array.isArray(props.children)) {
children = props.children.map(child => <Container key={`container-${child.properties.id}`} model={child}/>);
} else if (props.children !== null) {
children = <Container key={`container-${props.children.properties.id}`} model={props.children}/>;
}
return (
<div id={ID} className='ml-16'>
<UncontrolledReactSVGPanZoom
width={viewer.viewerWidth}
height={viewer.viewerHeight}
background={'#ffffff'}
defaultTool='pan'
miniatureProps={{
position: 'left',
background: '#616264',
width: window.innerWidth - 12 - BAR_WIDTH,
height: 120
}}
>
<svg {...properties}>
{ children }
<Selector selected={props.selected} />
</svg>
</UncontrolledReactSVGPanZoom>
</div>
);
};