Updates visualization playground.

This commit is contained in:
Henning Dieterichs
2020-03-22 14:17:54 +01:00
parent 546d79ae6d
commit 927b5bbc45
13 changed files with 453 additions and 79 deletions

View File

@@ -5,34 +5,41 @@ import { observer } from "mobx-react";
import { Model } from "../model/Model";
import classnames = require("classnames");
import { knownVisualizations } from "@hediet/visualization";
import {
ExtractedData,
CommonDataType,
} from "@hediet/debug-visualizer-data-extraction";
import { CommonDataType } from "@hediet/debug-visualizer-data-extraction";
import { LightExpressionInput } from "./LightExpressionInput";
@observer
export class GUI extends React.Component<{ model: Model }> {
render() {
const m = this.props.model;
const e: CommonDataType = {
kind: { graph: true },
nodes: [
{ id: "1", label: "1" },
{ id: "2", label: "2" },
],
edges: [
{
from: "1",
to: "2",
},
],
};
const result = knownVisualizations.getBestVisualization(e, undefined);
return (
<div className="component-GUI">
{result.visualization!.render()}
<div
className="component-GUI"
style={{ display: "flex", flexDirection: "column" }}
>
<div className="part-header">
<LightExpressionInput model={m.jsonExpression} />
</div>
<div
className="part-visualization"
style={{ minHeight: 0, flex: 1 }}
>
{this.renderVisualization()}
</div>
</div>
);
}
renderVisualization() {
const m = this.props.model;
if (!m.visualizations) {
return <div>No/Invalid Data</div>;
}
if (!m.visualizations.visualization) {
return <div>Data cannot be visualized</div>;
}
return m.visualizations.visualization.render();
}
}

View File

@@ -0,0 +1,76 @@
import * as React from "react";
import { observer } from "mobx-react";
import { observable, action } from "mobx";
import TextareaAutosize from "react-autosize-textarea";
export class ExpressionModel {
@observable
private _value: string;
constructor(initialValue: string) {
this._value = initialValue;
}
public get value(): string {
return this._value;
}
public setValue(newValue: string): void {
this._value = newValue;
}
}
@observer
export class LightExpressionInput extends React.Component<{
model: ExpressionModel;
}> {
@observable localText: string | undefined = undefined;
get text(): string {
if (this.localText !== undefined) {
return this.localText;
}
return this.props.model.value;
}
render() {
return (
<div>
<TextareaAutosize
value={this.text}
spellCheck={false}
onChange={e => (this.localText = e.currentTarget.value)}
onKeyDown={e => {
if (e.keyCode == 9 || e.which == 9) {
// enable tab
const target = e.currentTarget;
e.preventDefault();
var s = target.selectionStart;
target.value =
target.value.substring(
0,
target.selectionStart
) +
"\t" +
target.value.substring(target.selectionEnd);
target.selectionEnd = s + 1;
}
}}
style={{
width: "100%",
resize: "none",
}}
onBlur={this.handleBlur}
/>
</div>
);
}
@action.bound
private handleBlur() {
if (this.localText !== undefined) {
this.props.model.setValue(this.localText);
}
this.localText = undefined;
}
}

View File

@@ -5,6 +5,9 @@ import {
knownVisualizations,
} from "@hediet/visualization";
import { Disposable } from "@hediet/std/disposable";
import { ExpressionModel } from "../components/LightExpressionInput";
import { ExtractedData } from "@hediet/debug-visualizer-data-extraction";
import { QueryController } from "./QueryController";
export class Model {
public readonly dispose = Disposable.fn();
@@ -21,24 +24,64 @@ export class Model {
this.preferredVisualizationId = id;
}
public jsonExpression = new ExpressionModel(
JSON.stringify(
{
kind: { graph: true },
nodes: [
{ id: "1", label: "1" },
{ id: "2", label: "2" },
],
edges: [
{
from: "1",
to: "2",
},
],
},
undefined,
4
)
);
get state():
| { kind: "data"; data: ExtractedData }
| { kind: "parseError" } {
const json = this.jsonExpression.value;
let data: ExtractedData;
try {
data = JSON.parse(json);
} catch (e) {
return {
kind: "parseError",
};
}
return {
kind: "data",
data,
};
}
@computed get visualizations():
| {
visualization: Visualization | undefined;
allVisualizations: Visualization[];
}
| undefined {
return undefined;
/*if (this.state.kind === "data") {
if (this.state.kind === "data") {
const vis = knownVisualizations.getBestVisualization(
this.state.result.data,
this.state.data,
this.preferredVisualizationId
);
return vis;
} else {
return undefined;
}*/
}
}
private readonly q = new QueryController(this);
constructor() {
const url = new URL(window.location.href);

View File

@@ -0,0 +1,26 @@
import { Model } from "./Model";
import { autorun } from "mobx";
export class QueryController {
constructor(private readonly model: Model) {
this.loadFromQuery();
autorun(() => {
this.updateQuery();
});
}
loadFromQuery() {
const url = new URL(window.location.href);
const val = url.searchParams.get("value");
if (val) {
this.model.jsonExpression.setValue(val);
}
}
updateQuery() {
const url = new URL(window.location.href);
url.searchParams.set("value", this.model.jsonExpression.value);
history.replaceState(null, document.title, url.toString());
}
}

View File

@@ -36,8 +36,8 @@ body {
.component-GUI {
height: 100%;
& > .part-Header {
padding: 6px 20px 6px 0;
background-color: var(--vscode-sideBar-background);
//padding: 6px 20px 6px 0;
//background-color: var(--vscode-sideBar-background);
// border-top: solid 1px var(--vscode-button-background);
// rgba(128, 128, 128, 0.15)
@@ -66,13 +66,6 @@ body {
}
}
.svgViewer {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.bp3-transition-container {
z-index: 100000;
}