Updates visualization playground.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
26
visualization-playground/src/model/QueryController.ts
Normal file
26
visualization-playground/src/model/QueryController.ts
Normal 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());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user