Skip to content
Snippets Groups Projects
Commit c75774c2 authored by Maximilian Giller's avatar Maximilian Giller :squid:
Browse files

Implemented working history navigation and extended parsing of objects for greater compatibility

parent a3076071
No related branches found
No related tags found
1 merge request!2Implemented editor in the react framework
Pipeline #56625 failed
import React from "react";
import { State } from "../state";
import * as Interactions from "../interactions";
import { Graph } from "../structures/graph/graph";
import { Graph, GraphData } from "../structures/graph/graph";
import { loadGraphJson } from "../../../datasets";
import { ToolPool } from "./toolpool";
import { ToolDetails } from "./tooldetails";
......@@ -29,6 +29,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
this.loadGraph = this.loadGraph.bind(this);
this.loadSpace = this.loadSpace.bind(this);
this.handleNodeClick = this.handleNodeClick.bind(this);
this.onHistoryChange = this.onHistoryChange.bind(this);
// Set as new state
this.state = {
......@@ -134,6 +135,8 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
graph: newGraph,
});
this.state.graph.onChangeCallbacks.push(this.onHistoryChange);
// Subscribe to global key-press events
document.onkeydown = newState.onKeyDown;
document.onkeyup = newState.onKeyUp;
......@@ -141,6 +144,13 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
return true;
}
/**
* Propagates the changed state of the graph.
*/
private onHistoryChange() {
this.forceUpdate();
}
/**
* Calculates the corresponding coordinates for a click event for easier further processing.
* @param event The corresponding click event.
......@@ -175,6 +185,7 @@ export class Editor extends React.PureComponent<propTypes, stateTypes> {
<HistoryNavigator
spaceId="space"
historyObject={this.state.graph}
onChange={this.onHistoryChange}
/>
<hr />
......
......@@ -6,6 +6,7 @@ import "./historynavigator.css";
type propTypes = {
historyObject: ManagedData;
spaceId: string;
onChange: { (): void };
};
export class HistoryNavigator extends React.Component<propTypes> {
......@@ -50,6 +51,8 @@ export class HistoryNavigator extends React.Component<propTypes> {
handleSelectSavepoint(e: ChangeEvent<HTMLSelectElement>) {
if (!this.props.historyObject.goToSavePoint(Number(e.target.value))) {
alert("Something went wrong, could not load savepoint.");
} else {
this.props.onChange();
}
}
......@@ -58,18 +61,20 @@ export class HistoryNavigator extends React.Component<propTypes> {
<div id="history-navigator">
<button onClick={this.handleUndo}>Undo</button>
<button onClick={this.handleRedo}>Redo</button>
<select onChange={this.handleSelectSavepoint}>
<select
onChange={this.handleSelectSavepoint}
value={
this.props.historyObject
? this.props.historyObject.currentSavePoint.id
: 0
}
>
{this.props.historyObject
? this.props.historyObject.history.map((savepoint) => {
return (
<option
key={savepoint.id}
value={savepoint.id}
selected={
savepoint.id ===
this.props.historyObject
.currentSavePoint.id
}
>
{savepoint.description}
</option>
......
......@@ -18,27 +18,30 @@ export class Graph extends ManagedData {
private nextTypeId = 0;
// Callbacks
public onChangeCallbacks: { (data: any): void }[];
public onChangeCallbacks: { (data: GraphData): void }[];
constructor(data: GraphData) {
super(data);
this.onChangeCallbacks = [];
this.connectElementsToGraph();
this.connectElementsToGraph(this.data);
this.prepareIds(data);
this.storeCurrentData("Initial state", false);
}
/**
* Sets the correct graph object for all the graph elements in data.
* @param data Datastructure to connect.
*/
connectElementsToGraph() {
this.data.nodes.forEach((n) => (n.graph = this));
this.data.links.forEach((l) => {
connectElementsToGraph(data: GraphData) {
data.nodes.forEach((n) => (n.graph = this));
data.links.forEach((l) => {
l.graph = this;
l.source = this.getNode(l.sourceId);
l.target = this.getNode(l.targetId);
l.source = data.nodes.find((node) => node.id === l.sourceId);
l.target = data.nodes.find((node) => node.id === l.targetId);
});
this.data.types.forEach((t) => (t.graph = this));
data.types.forEach((t) => (t.graph = this));
}
/**
......@@ -132,6 +135,24 @@ export class Graph extends ManagedData {
return clean;
}
protected restoreData(data: GraphData): any {
const parsedData = Graph.parseData(data);
this.connectElementsToGraph(parsedData);
// TODO: Remove. Just testing for missing nodes
parsedData.links.forEach((link) => {
const sourceNode = link.source;
const targetNode = link.target;
if (sourceNode === undefined || targetNode === undefined) {
console.log(link);
}
});
return parsedData;
}
serialize(): any {
return this.serializeData(this.data);
}
......@@ -255,6 +276,10 @@ export class Graph extends ManagedData {
}
public static parse(raw: any): Graph {
return new Graph(this.parseData(raw));
}
public static parseData(raw: any): GraphData {
const data: GraphData = {
nodes: [],
links: [],
......@@ -299,6 +324,6 @@ export class Graph extends ManagedData {
data.types.push(node.type);
});
return new Graph(data);
return data;
}
}
......@@ -96,8 +96,23 @@ export class Link extends GraphElement {
public static parse(raw: any): Link {
const link: Link = new Link();
link.sourceId = Number(raw.source);
link.targetId = Number(raw.target);
if (isNaN(Number(raw.source))) {
// Source not given as id, but probably as node object
link.sourceId = raw.source.id;
link.targetId = raw.target.id;
} else {
link.sourceId = Number(raw.source);
link.targetId = Number(raw.target);
}
// Try to parse simulation parameters
LINK_SIM_PARAMS.forEach((param) => {
if (raw[param] === undefined) {
return;
}
(link as any)[param] = raw[param];
});
return link;
}
......@@ -110,7 +125,7 @@ export class Link extends GraphElement {
source = this.sourceId;
target = this.targetId;
}
return source.toString() + " -> " + target.toString();
}
}
......@@ -94,11 +94,25 @@ export class Node extends GraphElement {
public static parse(raw: any): Node {
const node: Node = new Node();
if (raw.label !== undefined) {
node.label = raw.label;
} else {
node.label = raw.name;
}
node.id = Number(raw.id);
node.label = raw.name;
node.description = raw.description;
node.type = NodeType.parse(raw.type);
// Try to parse simulation parameters
NODE_SIM_PARAMS.forEach((param) => {
if (raw[param] === undefined) {
return;
}
(node as any)[param] = raw[param];
});
return node;
}
......
......@@ -29,8 +29,13 @@ export class NodeType extends GraphElement {
public static parse(raw: any): NodeType {
const type: NodeType = new NodeType();
type.name = raw;
type.color = "#ff0000"
if (typeof raw === "string" || raw instanceof String) {
type.name = raw as string;
type.color = "#ff0000";
} else {
type.name = raw.name;
type.color = raw.color;
}
return type;
}
......
......@@ -30,8 +30,6 @@ export default class ManagedData extends SerializableItem {
this.historyPosition = 0;
this.savedHistoryId = 0;
this.storingEnabled = true;
this.storeCurrentData("Initial state", false);
}
/**
......@@ -184,7 +182,10 @@ export default class ManagedData extends SerializableItem {
}
this.historyPosition = position;
this.data = JSON.parse(this.history[this.historyPosition].data);
const savePointData = JSON.parse(
this.history[this.historyPosition].data
);
this.data = this.restoreData(savePointData);
return true;
}
......@@ -198,6 +199,15 @@ export default class ManagedData extends SerializableItem {
return data;
}
/**
* Restores proper format of data.
* @param data New data to restore.
* @returns Formatted data ready to use.
*/
protected restoreData(data: any): any {
return data;
}
/**
* Creates a save point.
* @param description Description of the current save point. Could describe the difference to the previous save point.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment