mirror of
https://github.com/bendtherules/piktochart-create-editor.git
synced 2026-08-18 22:02:56 +00:00
Add node delete + server url constant
This commit is contained in:
@@ -8,14 +8,47 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 600px;
|
height: 600px;
|
||||||
|
|
||||||
border: 1px solid;
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-area .image-node {
|
.canvas-area .image-node img{
|
||||||
max-width: 150px;
|
max-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.canvas-area .text-node {
|
.canvas-area .text-node .value{
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.canvas-area .image-node, .canvas-area .text-node {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-area .image-node .delete, .canvas-area .text-node .delete{
|
||||||
|
position: absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
|
||||||
|
right: -.75em;
|
||||||
|
top: -.75em;
|
||||||
|
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid black;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.canvas-area .image-node:hover .delete, .canvas-area .text-node:hover .delete{
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-area .delete-text {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
@@ -14,6 +14,8 @@ interface CanvasAreaProps {
|
|||||||
[nodeId: string]: CanvasImageNode;
|
[nodeId: string]: CanvasImageNode;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
deleteNode(type: 'text' | 'image', nodeId: string): void;
|
||||||
}
|
}
|
||||||
interface CanvasAreaState {
|
interface CanvasAreaState {
|
||||||
}
|
}
|
||||||
@@ -27,14 +29,27 @@ export class CanvasArea extends React.Component<CanvasAreaProps, CanvasAreaState
|
|||||||
this.containerId = 'container-' + uuid();
|
this.containerId = 'container-' + uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderDeleteNode(type: 'text' | 'image', nodeId: string) {
|
||||||
|
return (
|
||||||
|
<div className="delete" onClick={() => { this.props.deleteNode(type, nodeId); }}>
|
||||||
|
<div className="delete-text">
|
||||||
|
X
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderTextNodes() {
|
renderTextNodes() {
|
||||||
return Object.keys(this.props.nodes.text).map((nodeId) => {
|
return Object.keys(this.props.nodes.text).map((nodeId) => {
|
||||||
const tmpTextNode = this.props.nodes.text[nodeId];
|
const tmpTextNode = this.props.nodes.text[nodeId];
|
||||||
return (
|
return (
|
||||||
<DraggableNode key={nodeId} id={nodeId} containerId={this.containerId}>
|
<DraggableNode key={nodeId} id={nodeId} containerId={this.containerId}>
|
||||||
<div className="text-node">
|
<div className="text-node">
|
||||||
|
{this.renderDeleteNode('text', nodeId)}
|
||||||
|
<div className="value">
|
||||||
{tmpTextNode.value}
|
{tmpTextNode.value}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</DraggableNode>
|
</DraggableNode>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -45,7 +60,10 @@ export class CanvasArea extends React.Component<CanvasAreaProps, CanvasAreaState
|
|||||||
const tmpImageNode = this.props.nodes.image[nodeId];
|
const tmpImageNode = this.props.nodes.image[nodeId];
|
||||||
return (
|
return (
|
||||||
<DraggableNode key={nodeId} id={nodeId} containerId={this.containerId}>
|
<DraggableNode key={nodeId} id={nodeId} containerId={this.containerId}>
|
||||||
<img className="image-node" draggable={false} src={tmpImageNode.url} />
|
<div className="image-node">
|
||||||
|
{this.renderDeleteNode('image', nodeId)}
|
||||||
|
<img draggable={false} src={tmpImageNode.url} />
|
||||||
|
</div>
|
||||||
</DraggableNode>
|
</DraggableNode>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|||||||
import './CreateEditorApp.css';
|
import './CreateEditorApp.css';
|
||||||
import { Sidebar } from '../Sidebar';
|
import { Sidebar } from '../Sidebar';
|
||||||
import { CanvasArea } from '../CanvasArea';
|
import { CanvasArea } from '../CanvasArea';
|
||||||
import { deppCloneNaive, CanvasTextNode, CanvasImageNode } from '../../Helpers';
|
import { deepCloneNaive, CanvasTextNode, CanvasImageNode, serverURL } from '../../Helpers';
|
||||||
|
|
||||||
interface CreateEditorAppState {
|
interface CreateEditorAppState {
|
||||||
imageURLs: string[];
|
imageURLs: string[];
|
||||||
@@ -31,6 +31,7 @@ export class CreateEditorApp extends React.Component<{}, CreateEditorAppState> {
|
|||||||
this.addOrUpdateTextNode = this.addOrUpdateTextNode.bind(this);
|
this.addOrUpdateTextNode = this.addOrUpdateTextNode.bind(this);
|
||||||
this.addOrUpdateImageNode = this.addOrUpdateImageNode.bind(this);
|
this.addOrUpdateImageNode = this.addOrUpdateImageNode.bind(this);
|
||||||
this.onImageUploadSuccess = this.onImageUploadSuccess.bind(this);
|
this.onImageUploadSuccess = this.onImageUploadSuccess.bind(this);
|
||||||
|
this.deleteNode = this.deleteNode.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -43,7 +44,7 @@ export class CreateEditorApp extends React.Component<{}, CreateEditorAppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchImages() {
|
fetchImages() {
|
||||||
fetch('http://localhost:8000/images/')
|
fetch(`${serverURL}/images/`)
|
||||||
.then((response: Response) => {
|
.then((response: Response) => {
|
||||||
return response.json();
|
return response.json();
|
||||||
}).then((responseJSON: string[]) => {
|
}).then((responseJSON: string[]) => {
|
||||||
@@ -77,7 +78,7 @@ export class CreateEditorApp extends React.Component<{}, CreateEditorAppState> {
|
|||||||
|
|
||||||
addOrUpdateTextNode(nodeId: string, textNode: CanvasTextNode): void {
|
addOrUpdateTextNode(nodeId: string, textNode: CanvasTextNode): void {
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
const newState = deppCloneNaive(prevState as CreateEditorAppState);
|
const newState = deepCloneNaive(prevState as CreateEditorAppState);
|
||||||
newState.text[nodeId] = textNode;
|
newState.text[nodeId] = textNode;
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
@@ -86,13 +87,28 @@ export class CreateEditorApp extends React.Component<{}, CreateEditorAppState> {
|
|||||||
|
|
||||||
addOrUpdateImageNode(nodeId: string, imageNode: CanvasImageNode): void {
|
addOrUpdateImageNode(nodeId: string, imageNode: CanvasImageNode): void {
|
||||||
this.setState((prevState) => {
|
this.setState((prevState) => {
|
||||||
const newState = deppCloneNaive(prevState as CreateEditorAppState);
|
const newState = deepCloneNaive(prevState as CreateEditorAppState);
|
||||||
newState.image[nodeId] = imageNode;
|
newState.image[nodeId] = imageNode;
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteNode(type: 'text' | 'image', nodeId: string): void {
|
||||||
|
this.setState((prevState) => {
|
||||||
|
const newState = deepCloneNaive(prevState as CreateEditorAppState);
|
||||||
|
|
||||||
|
if (type === 'text') {
|
||||||
|
delete newState.text[nodeId];
|
||||||
|
}
|
||||||
|
if (type === 'image') {
|
||||||
|
delete newState.image[nodeId];
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="create-editor-app">
|
<div className="create-editor-app">
|
||||||
@@ -102,7 +118,7 @@ export class CreateEditorApp extends React.Component<{}, CreateEditorAppState> {
|
|||||||
addTextNode={this.addOrUpdateTextNode}
|
addTextNode={this.addOrUpdateTextNode}
|
||||||
addImageNode={this.addOrUpdateImageNode}
|
addImageNode={this.addOrUpdateImageNode}
|
||||||
/>
|
/>
|
||||||
<CanvasArea nodes={this.state} />
|
<CanvasArea nodes={this.state} deleteNode={this.deleteNode} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import './UploadResourcesInput.css';
|
import './UploadResourcesInput.css';
|
||||||
|
import { serverURL } from '../../Helpers';
|
||||||
|
|
||||||
interface UploadResourcesInputProps {
|
interface UploadResourcesInputProps {
|
||||||
notifyImageUploadSuccess(): void;
|
notifyImageUploadSuccess(): void;
|
||||||
@@ -29,7 +30,7 @@ export class UploadResourcesInput extends React.Component<UploadResourcesInputPr
|
|||||||
|
|
||||||
onFileSubmit(ev: React.MouseEvent<HTMLButtonElement>) {
|
onFileSubmit(ev: React.MouseEvent<HTMLButtonElement>) {
|
||||||
if (this.state.file !== undefined) {
|
if (this.state.file !== undefined) {
|
||||||
const url = 'http://localhost:8000/uploads';
|
const url = `${serverURL}/uploads`;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('upload', this.state.file);
|
formData.append('upload', this.state.file);
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
export { DragContextProvider, DragStartFn, DragSharedInfo } from './DragContextProvider';
|
export { DragContextProvider, DragStartFn, DragSharedInfo } from './DragContextProvider';
|
||||||
export { XYPair, deppCloneNaive, CanvasTextNode, CanvasImageNode } from './utils';
|
export { XYPair, deepCloneNaive, CanvasTextNode, CanvasImageNode } from './utils';
|
||||||
|
export {serverURL} from './urls';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const serverURL = 'http://localhost:8000';
|
||||||
@@ -3,7 +3,7 @@ export interface XYPair {
|
|||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deppCloneNaive<T>(originalObject: T): T {
|
export function deepCloneNaive<T>(originalObject: T): T {
|
||||||
return JSON.parse(JSON.stringify(originalObject));
|
return JSON.parse(JSON.stringify(originalObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user