Improves lazy loading.
This commit is contained in:
@@ -1,29 +1,30 @@
|
||||
import * as React from "react";
|
||||
import { observable, runInAction } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { Loadable } from "./Loadable";
|
||||
|
||||
export function makeLazyLoadable<TProps>(
|
||||
selector: () => Promise<React.ComponentClass<TProps>>
|
||||
): React.ComponentClass<TProps> {
|
||||
): React.ComponentClass<TProps> & { preload(): Promise<void> } {
|
||||
const loader = new Loadable(selector);
|
||||
|
||||
@observer
|
||||
class MyComponent extends React.Component<TProps> {
|
||||
@observable
|
||||
component: React.ComponentClass<TProps> | undefined;
|
||||
|
||||
async componentDidMount() {
|
||||
const result = await selector();
|
||||
runInAction("Set Lazily Loaded Component", () => {
|
||||
this.component = result;
|
||||
});
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
loader.load();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.component) {
|
||||
if (!loader.result) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
const C = this.component;
|
||||
const C = loader.result;
|
||||
return <C {...this.props} />;
|
||||
}
|
||||
|
||||
static async preload(): Promise<void> {
|
||||
await loader.load();
|
||||
}
|
||||
}
|
||||
|
||||
return MyComponent;
|
||||
|
||||
22
visualization-bundle/src/utils/Loadable.tsx
Normal file
22
visualization-bundle/src/utils/Loadable.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { observable, runInAction } from "mobx";
|
||||
|
||||
export class Loadable<T> {
|
||||
@observable.ref
|
||||
public result: T | undefined;
|
||||
|
||||
private operation?: Promise<void> = undefined;
|
||||
|
||||
constructor(private readonly _load: () => Promise<T>) {}
|
||||
|
||||
public load(): Promise<void> {
|
||||
if (!this.operation) {
|
||||
this.operation = (async () => {
|
||||
const r = await this._load();
|
||||
runInAction(() => {
|
||||
this.result = r;
|
||||
});
|
||||
})();
|
||||
}
|
||||
return this.operation;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import * as React from "react";
|
||||
import { observer, disposeOnUnmount } from "mobx-react";
|
||||
import { observable, autorun, trace, computed } from "mobx";
|
||||
import * as monacoTypes from "monaco-editor";
|
||||
import { getLanguageId } from "../monaco-text-visualizer/MonacoEditor";
|
||||
import { getLanguageId } from "../monaco-text-visualizer/getLanguageId";
|
||||
import {
|
||||
TreeWithPathView,
|
||||
TreeViewModel,
|
||||
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
import { visualizationNs } from "../../consts";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { createTreeViewModelFromTreeNodeData } from "../tree-visualizer";
|
||||
import { AstTree, NodeInfo } from "./AstVisualizer";
|
||||
@@ -81,7 +81,7 @@ export const astVisualizer = createVisualizer({
|
||||
name: "AST",
|
||||
serializer: sAstTree,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1500 }, theme => {
|
||||
createReactVisualization(self, { priority: 1500 }, ({ theme }) => {
|
||||
const m = createTreeViewModelFromTreeNodeData(
|
||||
data.root,
|
||||
node => node.span
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observer, disposeOnUnmount } from "mobx-react";
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { observable, autorun, runInAction } from "mobx";
|
||||
import { SvgViewer } from "../../svg-visualizer/SvgViewer";
|
||||
import { Loadable } from "../../../utils/Loadable";
|
||||
|
||||
class VisLoader {
|
||||
private result: any | undefined;
|
||||
@@ -24,26 +24,29 @@ class VisLoader {
|
||||
|
||||
const vizLoader = new VisLoader();
|
||||
|
||||
export function getSvgFromDotCode(dotCode: string): Loadable<string> {
|
||||
return new Loadable(async () => {
|
||||
const viz = await vizLoader.getViz();
|
||||
return await viz.renderString(dotCode);
|
||||
});
|
||||
}
|
||||
|
||||
@observer
|
||||
export class GraphvizDotViewer extends React.Component<{
|
||||
dotCode: string;
|
||||
svgSource: Loadable<string>;
|
||||
svgRef?: (element: SVGSVGElement | null) => void;
|
||||
}> {
|
||||
@observable private svg: string | null = null;
|
||||
|
||||
@disposeOnUnmount
|
||||
// @ts-ignore
|
||||
private readonly _updateSvgAutorun = autorun(async () => {
|
||||
const dotCode = this.props.dotCode; // to trigger mobx dependency
|
||||
const viz = await vizLoader.getViz();
|
||||
const svg = await viz.renderString(dotCode);
|
||||
runInAction("Update svg", () => (this.svg = svg));
|
||||
});
|
||||
|
||||
render() {
|
||||
if (!this.svg) {
|
||||
const { svgSource } = this.props;
|
||||
svgSource.load();
|
||||
if (!svgSource.result) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
return <SvgViewer svgRef={this.props.svgRef} svgContent={this.svg} />;
|
||||
return (
|
||||
<SvgViewer
|
||||
svgRef={this.props.svgRef}
|
||||
svgContent={svgSource.result}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import * as React from "react";
|
||||
import { sOpenObject, sLiteral, sString } from "@hediet/semantic-json";
|
||||
import { GraphvizDotViewer } from "./GraphvizDotVisualizer";
|
||||
import { getSvgFromDotCode, GraphvizDotViewer } from "./GraphvizDotVisualizer";
|
||||
import {
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createVisualizer,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../../consts";
|
||||
|
||||
@@ -17,10 +17,17 @@ export const graphvizDotVisualizer = createVisualizer({
|
||||
}),
|
||||
text: sString(),
|
||||
}).defineAs(visualizationNs("GraphvizDotVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1500 }, () => (
|
||||
<GraphvizDotViewer dotCode={data.text} />
|
||||
)),
|
||||
getVisualization: (data, self) => {
|
||||
const svgSource = getSvgFromDotCode(data.text);
|
||||
return createReactVisualization(
|
||||
self,
|
||||
{
|
||||
priority: 1500,
|
||||
preload: () => svgSource.load(),
|
||||
},
|
||||
() => <GraphvizDotViewer svgSource={svgSource} />
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(graphvizDotVisualizer);
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { GraphvizDotViewer } from "../dot-graphviz-visualizer/GraphvizDotVisualizer";
|
||||
|
||||
@observer
|
||||
export class GraphvizGraphViewer extends React.Component<{
|
||||
nodes: { id: string; label?: string }[];
|
||||
edges: { from: string; to: string; label?: string; style: string }[];
|
||||
}> {
|
||||
render() {
|
||||
const { nodes, edges } = this.props;
|
||||
const dotContent = `
|
||||
digraph MyGraph {
|
||||
${nodes
|
||||
.map(
|
||||
n =>
|
||||
`"${n.id}" [ label = ${JSON.stringify(
|
||||
n.label !== undefined ? n.label : n.id
|
||||
)} ];`
|
||||
)
|
||||
.join("\n ")}
|
||||
${edges
|
||||
.map(
|
||||
e =>
|
||||
`"${e.from}" -> "${
|
||||
e.to
|
||||
}" [ label = ${JSON.stringify(
|
||||
e.label !== undefined ? e.label : ""
|
||||
)} style = ${JSON.stringify(e.style || "")} ];`
|
||||
)
|
||||
.join("\n")}
|
||||
}
|
||||
`;
|
||||
return <GraphvizDotViewer dotCode={dotContent} />;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Loadable } from "../../../utils/Loadable";
|
||||
import { getSvgFromDotCode } from "../dot-graphviz-visualizer/GraphvizDotVisualizer";
|
||||
|
||||
export function getSvgFromGraphData(
|
||||
nodes: { id: string; label?: string }[],
|
||||
edges: {
|
||||
from: string;
|
||||
to: string;
|
||||
label?: string;
|
||||
style?: string;
|
||||
}[]
|
||||
): Loadable<string> {
|
||||
const dotContent = `
|
||||
digraph MyGraph {
|
||||
${nodes
|
||||
.map(
|
||||
n =>
|
||||
`"${n.id}" [ label = ${JSON.stringify(
|
||||
n.label !== undefined ? n.label : n.id
|
||||
)} ];`
|
||||
)
|
||||
.join("\n ")}
|
||||
${edges
|
||||
.map(
|
||||
e =>
|
||||
`"${e.from}" -> "${e.to}" [ label = ${JSON.stringify(
|
||||
e.label !== undefined ? e.label : ""
|
||||
)} style = ${JSON.stringify(e.style || "")} ];`
|
||||
)
|
||||
.join("\n")}
|
||||
}
|
||||
`;
|
||||
return getSvgFromDotCode(dotContent);
|
||||
}
|
||||
@@ -1,20 +1,25 @@
|
||||
import * as React from "react";
|
||||
import { GraphvizGraphViewer } from "./GraphvizGraphVisualizer";
|
||||
import { sGraph } from "../sGraph";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { GraphvizDotViewer } from "../dot-graphviz-visualizer/GraphvizDotVisualizer";
|
||||
import { getSvgFromGraphData } from "./getGraphVizData";
|
||||
|
||||
export const graphvizGraphVisualizer = createVisualizer({
|
||||
id: "graphviz-graph",
|
||||
name: "Graphviz",
|
||||
serializer: sGraph,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1000 }, () => (
|
||||
<GraphvizGraphViewer edges={data.edges} nodes={data.nodes} />
|
||||
)),
|
||||
getVisualization: (data, self) => {
|
||||
const svgSource = getSvgFromGraphData(data.nodes, data.edges);
|
||||
return createReactVisualization(
|
||||
self,
|
||||
{ priority: 1000, preload: () => svgSource.load() },
|
||||
() => <GraphvizDotViewer svgSource={svgSource} />
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(graphvizGraphVisualizer);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "react";
|
||||
import { makeLazyLoadable } from "../../../utils/LazyLoadable";
|
||||
import {
|
||||
createReactVisualization,
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
} from "@hediet/visualization-core";
|
||||
import { sGraph } from "../sGraph";
|
||||
@@ -16,12 +16,19 @@ export const visJsGraphVisualizer = createVisualizer({
|
||||
name: "vis.js",
|
||||
serializer: sGraph,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1500 }, () => (
|
||||
<VisJsGraphViewerLazyLoadable
|
||||
edges={data.edges}
|
||||
nodes={data.nodes}
|
||||
/>
|
||||
)),
|
||||
createReactVisualization(
|
||||
self,
|
||||
{
|
||||
priority: 1500,
|
||||
preload: VisJsGraphViewerLazyLoadable.preload,
|
||||
},
|
||||
() => (
|
||||
<VisJsGraphViewerLazyLoadable
|
||||
edges={data.edges}
|
||||
nodes={data.nodes}
|
||||
/>
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(visJsGraphVisualizer);
|
||||
|
||||
@@ -4,15 +4,14 @@ import {
|
||||
sLiteral,
|
||||
sString,
|
||||
sArrayOf,
|
||||
sObject,
|
||||
sOptionalProp,
|
||||
sNumber,
|
||||
} from "@hediet/semantic-json";
|
||||
import { DecoratedGridComponent } from "./GridVisualizer";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
|
||||
@@ -65,7 +64,7 @@ export const gridVisualizer = createVisualizer({
|
||||
name: "Grid",
|
||||
serializer: sGrid,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1000 }, () => (
|
||||
createReactVisualization(self, { priority: 1000 }, () => (
|
||||
<DecoratedGridComponent data={data} />
|
||||
)),
|
||||
});
|
||||
|
||||
@@ -2,8 +2,8 @@ import { sOpenObject, sLiteral, sString, sProp } from "@hediet/semantic-json";
|
||||
import * as React from "react";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { SvgViewer } from "../svg-visualizer/SvgViewer";
|
||||
import { Observer, observer, disposeOnUnmount } from "mobx-react";
|
||||
@@ -22,7 +22,7 @@ export const imageVisualizer = createVisualizer({
|
||||
}),
|
||||
}).defineAs(visualizationNs("ImageVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1000 }, () => {
|
||||
createReactVisualization(self, { priority: 1000 }, () => {
|
||||
return <ImageViewer base64Data={data.base64Data} />;
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -33,10 +33,10 @@ export function getLanguageId(fileName: string): string {
|
||||
}
|
||||
|
||||
@observer
|
||||
export class MonacoEditor extends React.Component<{
|
||||
export class MonacoDiffEditor extends React.Component<{
|
||||
originalText: string;
|
||||
modifiedText: string;
|
||||
languageId: string;
|
||||
fileName?: string;
|
||||
theme: Theme;
|
||||
}> {
|
||||
@observable private editor:
|
||||
@@ -49,6 +49,13 @@ export class MonacoEditor extends React.Component<{
|
||||
}
|
||||
}
|
||||
|
||||
get languageId(): string {
|
||||
if (!this.props.fileName) {
|
||||
return "text";
|
||||
}
|
||||
return getLanguageId(this.props.fileName);
|
||||
}
|
||||
|
||||
private originalModel:
|
||||
| monacoTypes.editor.ITextModel
|
||||
| undefined = undefined;
|
||||
@@ -61,12 +68,12 @@ export class MonacoEditor extends React.Component<{
|
||||
if (this.editor) {
|
||||
const originalModel = getLoadedMonaco().editor.createModel(
|
||||
this.props.originalText,
|
||||
this.props.languageId,
|
||||
this.languageId,
|
||||
undefined
|
||||
);
|
||||
const modifiedModel = getLoadedMonaco().editor.createModel(
|
||||
this.props.modifiedText,
|
||||
this.props.languageId,
|
||||
this.languageId,
|
||||
undefined
|
||||
);
|
||||
|
||||
|
||||
@@ -7,15 +7,16 @@ import {
|
||||
} from "@hediet/semantic-json";
|
||||
import * as React from "react";
|
||||
import {
|
||||
getLanguageId,
|
||||
MonacoEditor as MonacoDiffEditor,
|
||||
} from "./MonacoEditor";
|
||||
import {
|
||||
createReactVisualization,
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
import { makeLazyLoadable } from "../../utils/LazyLoadable";
|
||||
|
||||
const MonacoDiffEditorLazyLoadable = makeLazyLoadable(
|
||||
async () => (await import("./MonacoEditor")).MonacoDiffEditor
|
||||
);
|
||||
|
||||
export const monacoTextDiffVisualizer = createVisualizer({
|
||||
id: "monaco-text-diff",
|
||||
@@ -34,20 +35,18 @@ export const monacoTextDiffVisualizer = createVisualizer({
|
||||
}),
|
||||
}).defineAs(visualizationNs("MonacoTextDiffVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 900 }, theme => {
|
||||
let id = "text";
|
||||
if (data.fileName) {
|
||||
id = getLanguageId(data.fileName);
|
||||
}
|
||||
return (
|
||||
<MonacoDiffEditor
|
||||
createReactVisualization(
|
||||
self,
|
||||
{ priority: 900, preload: MonacoDiffEditorLazyLoadable.preload },
|
||||
({ theme }) => (
|
||||
<MonacoDiffEditorLazyLoadable
|
||||
originalText={data.otherText}
|
||||
modifiedText={data.text}
|
||||
languageId={id}
|
||||
fileName={data.fileName}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(monacoTextDiffVisualizer);
|
||||
|
||||
@@ -4,39 +4,13 @@ import { observable, autorun } from "mobx";
|
||||
import * as monacoTypes from "monaco-editor";
|
||||
import { Theme } from "@hediet/visualization-core";
|
||||
import { getLoadedMonaco } from "@hediet/monaco-editor-react";
|
||||
|
||||
export function getLanguageId(fileName: string): string {
|
||||
const l = getLoadedMonaco().languages.getLanguages();
|
||||
const result = l.find(l => {
|
||||
if (l.filenamePatterns) {
|
||||
for (const p of l.filenamePatterns) {
|
||||
if (new RegExp(p).test(fileName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (l.extensions) {
|
||||
for (const p of l.extensions) {
|
||||
if (fileName.endsWith(p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (result) {
|
||||
return result.id;
|
||||
}
|
||||
return "text";
|
||||
}
|
||||
import { getLanguageId } from "./getLanguageId";
|
||||
|
||||
@observer
|
||||
export class MonacoEditor extends React.Component<{
|
||||
text: string;
|
||||
languageId: string;
|
||||
theme: Theme;
|
||||
fileName?: string;
|
||||
}> {
|
||||
@observable private editor:
|
||||
| monacoTypes.editor.IStandaloneCodeEditor
|
||||
@@ -48,6 +22,13 @@ export class MonacoEditor extends React.Component<{
|
||||
}
|
||||
}
|
||||
|
||||
get languageId(): string {
|
||||
if (!this.props.fileName) {
|
||||
return "text";
|
||||
}
|
||||
return getLanguageId(this.props.fileName);
|
||||
}
|
||||
|
||||
private model: monacoTypes.editor.ITextModel | undefined = undefined;
|
||||
|
||||
@disposeOnUnmount
|
||||
@@ -55,7 +36,7 @@ export class MonacoEditor extends React.Component<{
|
||||
if (this.editor) {
|
||||
const model = getLoadedMonaco().editor.createModel(
|
||||
this.props.text,
|
||||
this.props.languageId,
|
||||
this.languageId,
|
||||
undefined
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { getLoadedMonaco } from "@hediet/monaco-editor-react";
|
||||
|
||||
export function getLanguageId(fileName: string): string {
|
||||
const l = getLoadedMonaco().languages.getLanguages();
|
||||
const result = l.find(l => {
|
||||
if (l.filenamePatterns) {
|
||||
for (const p of l.filenamePatterns) {
|
||||
if (new RegExp(p).test(fileName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (l.extensions) {
|
||||
for (const p of l.extensions) {
|
||||
if (fileName.endsWith(p)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (result) {
|
||||
return result.id;
|
||||
}
|
||||
return "text";
|
||||
}
|
||||
@@ -6,13 +6,17 @@ import {
|
||||
sProp,
|
||||
} from "@hediet/semantic-json";
|
||||
import * as React from "react";
|
||||
import { getLanguageId, MonacoEditor } from "./MonacoEditor";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
import { makeLazyLoadable } from "../../utils/LazyLoadable";
|
||||
|
||||
export const MonacoEditorLazyLoadable = makeLazyLoadable(
|
||||
async () => (await import("./MonacoEditor")).MonacoEditor
|
||||
);
|
||||
|
||||
export const monacoTextVisualizer = createVisualizer({
|
||||
id: "monaco-text",
|
||||
@@ -28,15 +32,17 @@ export const monacoTextVisualizer = createVisualizer({
|
||||
}),
|
||||
}).defineAs(visualizationNs("MonacoTextVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 500 }, theme => {
|
||||
let id = "text";
|
||||
if (data.fileName) {
|
||||
id = getLanguageId(data.fileName);
|
||||
}
|
||||
return (
|
||||
<MonacoEditor text={data.text} languageId={id} theme={theme} />
|
||||
);
|
||||
}),
|
||||
createReactVisualization(
|
||||
self,
|
||||
{ priority: 500, preload: MonacoEditorLazyLoadable.preload },
|
||||
({ theme }) => (
|
||||
<MonacoEditorLazyLoadable
|
||||
text={data.text}
|
||||
fileName={data.fileName}
|
||||
theme={theme}
|
||||
/>
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(monacoTextVisualizer);
|
||||
|
||||
@@ -3,8 +3,8 @@ import { sOpenObject, sLiteral, sArrayOf, sProp } from "@hediet/semantic-json";
|
||||
import { toJS } from "mobx";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { makeLazyLoadable } from "../../utils/LazyLoadable";
|
||||
import { visualizationNs } from "../../consts";
|
||||
@@ -28,21 +28,28 @@ export const perspectiveTableVisualizer = createVisualizer({
|
||||
name: "Perspective Table",
|
||||
serializer: sTable,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1000 }, theme => (
|
||||
<PerspectiveDataViewerLazyLoadable
|
||||
className={
|
||||
{
|
||||
light: "perspective-viewer-material",
|
||||
dark: "perspective-viewer-material-dark",
|
||||
}[theme.kind]
|
||||
}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
data={toJS(data.rows)}
|
||||
/>
|
||||
)),
|
||||
createReactVisualization(
|
||||
self,
|
||||
{
|
||||
priority: 1000,
|
||||
preload: PerspectiveDataViewerLazyLoadable.preload,
|
||||
},
|
||||
({ theme }) => (
|
||||
<PerspectiveDataViewerLazyLoadable
|
||||
className={
|
||||
{
|
||||
light: "perspective-viewer-material",
|
||||
dark: "perspective-viewer-material-dark",
|
||||
}[theme.kind]
|
||||
}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
data={toJS(data.rows)}
|
||||
/>
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(perspectiveTableVisualizer);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Theme } from "@hediet/visualization-core";
|
||||
import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import Plot from "react-plotly.js";
|
||||
@@ -6,13 +7,14 @@ import Plot from "react-plotly.js";
|
||||
export class PlotlyViewer extends React.Component<{
|
||||
data: Plotly.Data[];
|
||||
layout?: Partial<Plotly.Layout>;
|
||||
theme: "light" | "dark";
|
||||
theme: Theme;
|
||||
onReady: () => void;
|
||||
}> {
|
||||
render() {
|
||||
const { theme, data, layout } = this.props;
|
||||
const computedLayout = Object.assign(
|
||||
{},
|
||||
theme === "dark" ? darkLayout : {},
|
||||
theme.id === "dark" ? getLayout(theme) : {},
|
||||
layout || {}
|
||||
);
|
||||
|
||||
@@ -39,11 +41,108 @@ export class PlotlyViewer extends React.Component<{
|
||||
data={data}
|
||||
layout={computedLayout}
|
||||
config={{ responsive: true }}
|
||||
onInitialized={this.props.onReady}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getLayout(theme: Theme): Partial<Plotly.Layout> {
|
||||
return {
|
||||
colorway: [
|
||||
"#636efa",
|
||||
"#EF553B",
|
||||
"#00cc96",
|
||||
"#ab63fa",
|
||||
"#19d3f3",
|
||||
"#e763fa",
|
||||
"#fecb52",
|
||||
"#ffa15a",
|
||||
"#ff6692",
|
||||
"#b6e880",
|
||||
],
|
||||
autosize: true,
|
||||
font: { color: "#f2f5fa" },
|
||||
title: { x: 0.05 },
|
||||
paper_bgcolor: theme.resolveVarToColor("--visualizer-background"), // "rgb(17,17,17)",
|
||||
plot_bgcolor: theme.resolveVarToColor("--visualizer-background"), // "rgb(17,17,17)",
|
||||
hovermode: "closest",
|
||||
polar: {
|
||||
bgcolor: theme.resolveVarToColor("--visualizer-background"),
|
||||
angularaxis: {
|
||||
gridcolor: "#506784",
|
||||
linecolor: "#506784",
|
||||
ticks: "",
|
||||
},
|
||||
radialaxis: {
|
||||
gridcolor: "#506784",
|
||||
linecolor: "#506784",
|
||||
ticks: "",
|
||||
},
|
||||
},
|
||||
ternary: {
|
||||
bgcolor: theme.resolveVarToColor("--visualizer-background"),
|
||||
aaxis: { gridcolor: "#506784", linecolor: "#506784", ticks: "" },
|
||||
baxis: { gridcolor: "#506784", linecolor: "#506784", ticks: "" },
|
||||
caxis: { gridcolor: "#506784", linecolor: "#506784", ticks: "" },
|
||||
},
|
||||
xaxis: {
|
||||
gridcolor: "#283442",
|
||||
linecolor: "#506784",
|
||||
ticks: "",
|
||||
zerolinecolor: "#283442",
|
||||
zerolinewidth: 2,
|
||||
automargin: true,
|
||||
},
|
||||
yaxis: {
|
||||
gridcolor: "#283442",
|
||||
linecolor: "#506784",
|
||||
ticks: "",
|
||||
zerolinecolor: "#283442",
|
||||
zerolinewidth: 2,
|
||||
automargin: true,
|
||||
},
|
||||
scene: {
|
||||
xaxis: {
|
||||
gridcolor: "#506784",
|
||||
linecolor: "#506784",
|
||||
showbackground: false,
|
||||
ticks: "",
|
||||
zerolinecolor: "#C8D4E3",
|
||||
gridwidth: 2,
|
||||
},
|
||||
yaxis: {
|
||||
gridcolor: "#506784",
|
||||
linecolor: "#506784",
|
||||
showbackground: false,
|
||||
ticks: "",
|
||||
zerolinecolor: "#C8D4E3",
|
||||
gridwidth: 2,
|
||||
},
|
||||
zaxis: {
|
||||
gridcolor: "#506784",
|
||||
linecolor: "#506784",
|
||||
showbackground: false,
|
||||
ticks: "",
|
||||
zerolinecolor: "#C8D4E3",
|
||||
gridwidth: 2,
|
||||
},
|
||||
},
|
||||
geo: {
|
||||
bgcolor: theme.resolveVarToColor("--visualizer-plotly-background"),
|
||||
landcolor: theme.resolveVarToColor(
|
||||
"--visualizer-plotly-background"
|
||||
),
|
||||
subunitcolor: "#506784",
|
||||
showland: true,
|
||||
showlakes: true,
|
||||
lakecolor: theme.resolveVarToColor(
|
||||
"--visualizer-plotly-background"
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// extracted from the plotly website
|
||||
const darkLayout: Partial<Plotly.Layout> = {
|
||||
colorway: [
|
||||
@@ -59,53 +158,6 @@ const darkLayout: Partial<Plotly.Layout> = {
|
||||
"#b6e880",
|
||||
],
|
||||
autosize: true,
|
||||
//margin: { b: 0, t: 0, pad: 0 },
|
||||
//height: 300,
|
||||
/*colorscale: {
|
||||
sequential: [
|
||||
[0, "#0508b8"],
|
||||
[0.0893854748603352, "#1910d8"],
|
||||
[0.1787709497206704, "#3c19f0"],
|
||||
[0.2681564245810056, "#6b1cfb"],
|
||||
[0.3575418994413408, "#981cfd"],
|
||||
[0.44692737430167595, "#bf1cfd"],
|
||||
[0.5363128491620112, "#dd2bfd"],
|
||||
[0.6256983240223464, "#f246fe"],
|
||||
[0.7150837988826816, "#fc67fd"],
|
||||
[0.8044692737430168, "#fe88fc"],
|
||||
[0.8938547486033519, "#fea5fd"],
|
||||
[0.9832402234636871, "#febefe"],
|
||||
[1, "#fec3fe"],
|
||||
],
|
||||
sequentialminus: [
|
||||
[0, "#0508b8"],
|
||||
[0.0893854748603352, "#1910d8"],
|
||||
[0.1787709497206704, "#3c19f0"],
|
||||
[0.2681564245810056, "#6b1cfb"],
|
||||
[0.3575418994413408, "#981cfd"],
|
||||
[0.44692737430167595, "#bf1cfd"],
|
||||
[0.5363128491620112, "#dd2bfd"],
|
||||
[0.6256983240223464, "#f246fe"],
|
||||
[0.7150837988826816, "#fc67fd"],
|
||||
[0.8044692737430168, "#fe88fc"],
|
||||
[0.8938547486033519, "#fea5fd"],
|
||||
[0.9832402234636871, "#febefe"],
|
||||
[1, "#fec3fe"],
|
||||
],
|
||||
diverging: [
|
||||
[0, "#8e0152"],
|
||||
[0.1, "#c51b7d"],
|
||||
[0.2, "#de77ae"],
|
||||
[0.3, "#f1b6da"],
|
||||
[0.4, "#fde0ef"],
|
||||
[0.5, "#f7f7f7"],
|
||||
[0.6, "#e6f5d0"],
|
||||
[0.7, "#b8e186"],
|
||||
[0.8, "#7fbc41"],
|
||||
[0.9, "#4d9221"],
|
||||
[1, "#276419"],
|
||||
],
|
||||
},*/
|
||||
font: { color: "#f2f5fa" },
|
||||
title: { x: 0.05 },
|
||||
paper_bgcolor: "rgb(17,17,17)",
|
||||
@@ -175,17 +227,6 @@ const darkLayout: Partial<Plotly.Layout> = {
|
||||
gridwidth: 2,
|
||||
},
|
||||
},
|
||||
/*
|
||||
shapedefaults: {
|
||||
fillcolor: "#f2f5fa",
|
||||
line: { width: 0 },
|
||||
opacity: 0.4,
|
||||
},
|
||||
annotationdefaults: {
|
||||
arrowcolor: "#f2f5fa",
|
||||
arrowhead: 0,
|
||||
arrowwidth: 1,
|
||||
},*/
|
||||
geo: {
|
||||
bgcolor: "rgb(17,17,17)",
|
||||
landcolor: "rgb(17,17,17)",
|
||||
@@ -194,13 +235,4 @@ const darkLayout: Partial<Plotly.Layout> = {
|
||||
showlakes: true,
|
||||
lakecolor: "rgb(17,17,17)",
|
||||
},
|
||||
/*
|
||||
updatemenudefaults: { bgcolor: "#506784", borderwidth: 0 },
|
||||
sliderdefaults: {
|
||||
bgcolor: "#C8D4E3",
|
||||
borderwidth: 1,
|
||||
bordercolor: "rgb(17,17,17)",
|
||||
tickwidth: 0,
|
||||
},
|
||||
*/
|
||||
};
|
||||
|
||||
@@ -14,8 +14,9 @@ import {
|
||||
import { makeLazyLoadable } from "../../utils/LazyLoadable";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
createLazyReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
|
||||
@@ -111,13 +112,21 @@ export const plotlyVisualizer = createVisualizer({
|
||||
),
|
||||
}).defineAs(visualizationNs("PlotlyVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1000 }, theme => (
|
||||
<PlotlyViewerLazyLoadable
|
||||
data={data.data}
|
||||
layout={data.layout}
|
||||
theme={theme.kind}
|
||||
/>
|
||||
)),
|
||||
createLazyReactVisualization(
|
||||
self,
|
||||
{
|
||||
priority: 1000,
|
||||
preload: PlotlyViewerLazyLoadable.preload,
|
||||
},
|
||||
({ theme, readyCallback }) => (
|
||||
<PlotlyViewerLazyLoadable
|
||||
data={data.data}
|
||||
layout={data.layout}
|
||||
theme={theme}
|
||||
onReady={readyCallback}
|
||||
/>
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
globalVisualizationFactory.addVisualizer(plotlyVisualizer);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.themeable {
|
||||
--visualizer-plotly-background: var(--visualizer-background);
|
||||
}
|
||||
@@ -2,8 +2,8 @@ import { sOpenObject, sLiteral, sString } from "@hediet/semantic-json";
|
||||
import * as React from "react";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
|
||||
@@ -30,7 +30,7 @@ export const simpleTextVisualizer = createVisualizer({
|
||||
) =>
|
||||
// If you want to use react, this is the way to go.
|
||||
// Return your own implementation if you want to render directly to the DOM.
|
||||
new ReactVisualization(
|
||||
createReactVisualization(
|
||||
self,
|
||||
{
|
||||
// The priority is used for automatically selecting the best visualization
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { sAny, sOpenObject } from "@hediet/semantic-json";
|
||||
import { sOpenObject } from "@hediet/semantic-json";
|
||||
import * as React from "react";
|
||||
import {
|
||||
createReactVisualization,
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
} from "@hediet/visualization-core";
|
||||
import { MonacoEditor } from "../monaco-text-visualizer/MonacoEditor";
|
||||
import { visualizationNs } from "../../consts";
|
||||
import { MonacoEditorLazyLoadable } from "../monaco-text-visualizer";
|
||||
|
||||
export const sourceVisualizer = createVisualizer({
|
||||
id: "source",
|
||||
@@ -15,10 +15,10 @@ export const sourceVisualizer = createVisualizer({
|
||||
kind: sOpenObject({}),
|
||||
}).defineAs(visualizationNs("SourceVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: -100 }, theme => (
|
||||
<MonacoEditor
|
||||
createReactVisualization(self, { priority: -100 }, ({ theme }) => (
|
||||
<MonacoEditorLazyLoadable
|
||||
text={JSON.stringify(data, undefined, 4)}
|
||||
languageId={"json"}
|
||||
fileName={"main.json"}
|
||||
theme={theme}
|
||||
/>
|
||||
)),
|
||||
|
||||
@@ -3,8 +3,8 @@ import { sOpenObject, sLiteral, sString, sProp } from "@hediet/semantic-json";
|
||||
import { SvgViewer } from "./SvgViewer";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
|
||||
@@ -18,7 +18,7 @@ export const svgVisualizer = createVisualizer({
|
||||
text: sProp(sString(), { description: "The svg content" }),
|
||||
}).defineAs(visualizationNs("SvgVisualizationData")),
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1500 }, () => (
|
||||
createReactVisualization(self, { priority: 1500 }, () => (
|
||||
<SvgViewer svgContent={data.text} />
|
||||
)),
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@ import {
|
||||
} from "@hediet/semantic-json";
|
||||
import {
|
||||
createVisualizer,
|
||||
ReactVisualization,
|
||||
globalVisualizationFactory,
|
||||
createReactVisualization,
|
||||
} from "@hediet/visualization-core";
|
||||
import { visualizationNs } from "../../consts";
|
||||
|
||||
@@ -86,7 +86,7 @@ export const treeVisualizer = createVisualizer({
|
||||
name: "Tree",
|
||||
serializer: sTree,
|
||||
getVisualization: (data, self) =>
|
||||
new ReactVisualization(self, { priority: 1200 }, () => {
|
||||
createReactVisualization(self, { priority: 1200 }, () => {
|
||||
const m = createTreeViewModelFromTreeNodeData(
|
||||
data.root,
|
||||
() => undefined
|
||||
|
||||
Reference in New Issue
Block a user