From 1e1bd4058ad1189a83ad225c8aa166f27a9f917d Mon Sep 17 00:00:00 2001 From: Max <m.giller@tu-bs.de> Date: Wed, 27 Apr 2022 10:31:53 +0200 Subject: [PATCH] Connected first components to editor backend, but still WIP --- src/backend.js | 2 + src/backend.tsx | 8 ++ src/editor/editor.php | 119 +----------------- src/editor/js/components/editor.tsx | 52 ++++++++ src/editor/js/components/toolbar.tsx | 12 ++ src/editor/js/components/toolitem.tsx | 44 +++++++ src/editor/js/graph.js | 34 ----- src/editor/js/structures/editor/tools/tool.ts | 7 ++ src/editor/js/structures/graph/graph.ts | 24 ++++ webpack.common.js | 2 +- 10 files changed, 151 insertions(+), 153 deletions(-) create mode 100644 src/backend.tsx create mode 100644 src/editor/js/components/editor.tsx create mode 100644 src/editor/js/components/toolbar.tsx create mode 100644 src/editor/js/components/toolitem.tsx create mode 100644 src/editor/js/structures/editor/tools/tool.ts diff --git a/src/backend.js b/src/backend.js index fe9e170..3aefed2 100644 --- a/src/backend.js +++ b/src/backend.js @@ -3,3 +3,5 @@ import "./editor/css/editor.css"; import "./display/display"; import "./editor/js/editor"; + +// TODO: Is this file deprecated? diff --git a/src/backend.tsx b/src/backend.tsx new file mode 100644 index 0000000..8df5b72 --- /dev/null +++ b/src/backend.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import ReactDOM from "react-dom"; + +import "./editor/css/editor.css"; +import "./editor/js/editor"; +import { Editor } from "./editor/js/components/editor"; + +ReactDOM.render(<Editor />, document.getElementById("ks-editor")); diff --git a/src/editor/editor.php b/src/editor/editor.php index cf25e16..944183b 100644 --- a/src/editor/editor.php +++ b/src/editor/editor.php @@ -1,118 +1 @@ -<div id="ks-editor"> - <!--The id "ks-editor" indicates, that the javascript associated with this should automatically be executed--> - <h1>Interface</h1> - <div id="box-select-layer"><div id="2d-graph"></div></div> - <section id="toolbar"></section> - <section id="tool-menu"> - <div id="delete-menu" class="hidden"> - <p>Drag and drop while pressing SHIFT to delete all the nodes that are being selected.</p> - </div> - <div id="collect-menu" class="hidden"> - <h3>Collected items</h3> - <button id="clear-collection">Clear</button> - <ul id="selected-items"></ul> - </div> - <div id="select-menu" class=""> - <p id="nothing-selected">Nothing selected</p> - <div id="node-selected" class="hidden"> - <label for="node-name" hidden>Name</label> - </br> - <input type="text" id="node-name" name="node-name" placeholder="Enter name" class="bottom-space"></input> - - </br> - - <label for="node-description">Description</label> - </br> - <textarea id="node-description" name="node-description" class="bottom-space"></textarea> - - </br> - <label for="node-image">Node Image</label> - </br> - <img id="node-image-preview" style="color:red" class="preview-image" src="" /> - </br> - <input type="text" id="node-image" name="node-image" placeholder="Enter file name or URL" class="bottom-space" /> - - </br> - <label for="node-detail-image">Info Image</label> - </br> - <img id="node-detail-image-preview" style="color:red" class="preview-image" src="" /> - </br> - <input type="text" id="node-detail-image" name="node-detail-image" placeholder="Enter file name or URL" class="bottom-space" /> - - </br> - <label for="node-type">Type</label> - </br> - <select id="node-type" name="node-type" class="bottom-space"> - <option value="Vorlesung">Vorlesung</option> - <option value="Algorithmus">Algorithmus</option> - <option value="Definition">Definition</option> - <option value="Beispiel">Beispiel</option> - <option value="Ãœbung">Ãœbung</option> - <option value="Kapitel">Kapitel</option> - </select> - - </br> - <label for="node-video">Video</label> - </br> - <input type="text" placeholder="Video URL" id="node-video" name="node-video"></input> - - </br> - <label for="node-references">References</label> <small>One URL per line</small> - </br> - <textarea id="node-references" name="node-references" class="bottom-space"></textarea> - </div> - <div id="link-selected" class="hidden"> - <h3 id="link-name"></h3> - </div> - </div> - <div id="settings-menu" class="hidden" checked> - <label for="label-toggle" class="bottom-space"> - <input type="checkbox" checked id="label-toggle" name="label-toggle"></input> - Show labels in graph - </label> - </br> - </br> - - - <h3>Space</h3> - <label for="space-id-select">Currently open</label> - </br> - <select id="space-id-select" name="space-id-select" class="bottom-space"> - </select> - - </br> - </br> - - <h3>Physics Simulation</h3> - - <button id="reanimate-button" name="reanimate-button" class="bottom-space">Re-simulate</button> - - </br> - - <label for="stop-physics-delay">Amount of time [in seconds] after which the physics simulation is stopped</label> - </br> - <input type="number" onkeypress="return (event.charCode !=8 && event.charCode ==0 || (event.charCode >= 48 && event.charCode <= 57))" value="5" id="stop-physics-delay" name="stop-physics-delay" class="small-width"> - </input> - </br> - </br> - - - <h3>Import Space</h3> - <label for="import-space-area">Space JSON</label> - </br> - <textarea id="import-space-area" name="import-space-area" class="bottom-space"> - </textarea> - </br> - <label for="import-space-name-text">Space Name</label> - </br> - <input type="text" id="import-space-name-text" name="import-space-name-text" class="bottom-space"> - </input> - </br> - <button id="import-space-btn" name="import-space-btn" class="bottom-space">Import</button> - - </br> - </br> - - </div> - </section> -</div> \ No newline at end of file +<div id="ks-editor"></div> \ No newline at end of file diff --git a/src/editor/js/components/editor.tsx b/src/editor/js/components/editor.tsx new file mode 100644 index 0000000..7e52996 --- /dev/null +++ b/src/editor/js/components/editor.tsx @@ -0,0 +1,52 @@ +import React from "react"; +import { Tool } from "../structures/editor/tools/tool"; +import { ToolBar } from "./toolbar"; + +export class Editor extends React.Component { + state: { + currentTool: Tool; + previousTool: Tool; + }; + + constructor(props: any) { + super(props); + } + + /** + * Sets current tool. Select events not triggered if already selected. + * @param tool New tool to select. + */ + public setTool(tool: Tool) { + if (this.state.currentTool == tool) { + return; + } + + this.setState({ currentTool: tool }); + } + + /** + * If exists, sets previously selected tool as current tool. + */ + public setPreviousTool() { + if (this.state.previousTool === undefined) { + return; + } + + this.setTool(this.state.previousTool); + } + + /** + * @returns Tool that is currently selected. + */ + public getCurrentTool(): Tool { + return this.state.currentTool; + } + + render(): React.ReactNode { + return ( + <div id="ks-editor"> + <ToolBar editor={this}></ToolBar> + </div> + ); + } +} diff --git a/src/editor/js/components/toolbar.tsx b/src/editor/js/components/toolbar.tsx new file mode 100644 index 0000000..ad08e59 --- /dev/null +++ b/src/editor/js/components/toolbar.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import { Editor } from "./editor"; + +type ToolBarProps = { editor: Editor }; + +export class ToolBar extends React.Component { + props: ToolBarProps; + + constructor(props: ToolBarProps) { + super(props); + } +} diff --git a/src/editor/js/components/toolitem.tsx b/src/editor/js/components/toolitem.tsx new file mode 100644 index 0000000..b590060 --- /dev/null +++ b/src/editor/js/components/toolitem.tsx @@ -0,0 +1,44 @@ +import React from "react"; +import { Tool } from "../structures/editor/tools/tool"; +import { Editor } from "./editor"; + +type ToolItemProps = { tool: Tool; editor: Editor }; + +class ToolItem extends React.Component { + state = {}; + props: ToolItemProps; + + constructor(props: ToolItemProps) { + super(props); + } + + /** + * Handles the click-on-tool-icon event. + */ + private handleClick() { + if (this.props.editor.getCurrentTool() !== this.props.tool) { + // Not selected, so select + this.props.editor.setTool(this.props.tool); + return; + } + + // Is already set, so only unset, if tool is toggleable + if (!this.props.tool.isToggleable) { + return; + } + + this.props.editor.setPreviousTool(); + } + + public render() { + return ( + <button + id={this.props.tool.id} + title={this.props.tool.name} + onClick={this.handleClick} + > + <img src={this.props.tool.icon} /> + </button> + ); + } +} diff --git a/src/editor/js/graph.js b/src/editor/js/graph.js index 68e52e8..81c1e42 100644 --- a/src/editor/js/graph.js +++ b/src/editor/js/graph.js @@ -86,40 +86,6 @@ export class PREVIOUSGraph extends ManagedData { return cleanLink; } - existsNodeId(nodeId) { - var nodes = this.data[GRAPH_NODES]; - for (var i = 0; i < nodes.length; i++) { - if (nodes[i][NODE_ID] === nodeId) { - return true; - } - } - return false; - } - - getUnusedNodeId() { - var id; - do { - id = this.getRandomString(); - } while (this.existsNodeId(id)); - return id; - } - - getRandomString(length = 8) { - // Move to global helpers - // Based on: https://stackoverflow.com/a/1349426/7376120 - var characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - var charactersLength = characters.length; - - var result = ""; - for (var i = 0; i < length; i++) { - result += characters.charAt( - Math.floor(Math.random() * charactersLength) - ); - } - return result; - } - static toStr(item) { if (item === undefined) { return "UNDEFINED"; diff --git a/src/editor/js/structures/editor/tools/tool.ts b/src/editor/js/structures/editor/tools/tool.ts new file mode 100644 index 0000000..c379e8f --- /dev/null +++ b/src/editor/js/structures/editor/tools/tool.ts @@ -0,0 +1,7 @@ +export class Tool { + public id: string; + public name: string; + public icon: string; + + public isToggleable: boolean = false; +} \ No newline at end of file diff --git a/src/editor/js/structures/graph/graph.ts b/src/editor/js/structures/graph/graph.ts index ccadd99..91b4648 100644 --- a/src/editor/js/structures/graph/graph.ts +++ b/src/editor/js/structures/graph/graph.ts @@ -26,6 +26,30 @@ export class Graph extends ManagedData { this.prepareIds(data); } + + /** + * Intuitive getter for links. + * @returns All links associated with the graph. + */ + public get links(): Link[] { + return this.data.links; + } + + /** + * Intuitive getter for nodes. + * @returns All nodes associated with the graph. + */ + public get nodes(): Node[] { + return this.data.nodes; + } + + /** + * Intuitive getter for node types. + * @returns All node types associated with the graph. + */ + public get types(): NodeType[] { + return this.data.types; + } /** * Determines the highest, used ids for GraphElements in data for later use. diff --git a/webpack.common.js b/webpack.common.js index 543a79e..00a8982 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -9,7 +9,7 @@ const babelOptions = { module.exports = { entry: { frontend: "./src/frontend.tsx", - backend: "./src/backend.js", + backend: "./src/backend.tsx", }, output: { filename: "[name].js", -- GitLab