import { HTMLEditor, ObservableMarkdownEditor } from "@hpcc-js/codemirror";
import { Button, SelectDropDown, Spacer, TitleBar, ToggleButton, Utility } from "@hpcc-js/common";
import { Table } from "@hpcc-js/dgrid";
import { Border2 } from "@hpcc-js/layout";
import { Observable, OJSRuntimeError } from "@hpcc-js/observable-md";
import { SplitPanel, TabPanel } from "@hpcc-js/phosphor";
import { html } from "./html";
import { samples, SampleT } from "./samples";
const sampleKeys = {};
for (const key in samples) {
sampleKeys[key] = key;
}
export class App extends Border2 {
_buttonGenerate = new Button().faChar("fa-arrow-right").tooltip("Render (Ctrl+S)")
.on("click", () => {
this.generate();
});
_buttonDownload = new Button().faChar("fa-download").tooltip("Download as Web Page")
.on("click", () => {
const omd = this._mdEditor.text();
Utility.downloadString("TEXT", html(omd, this.mode()), `${this._selectSample.selected() || "omd"}.html`);
});
_toggleValues = new ToggleButton().faChar("fa-bug").tooltip("Show Developer Info")
.selected(false)
.on("click", () => {
this.updateAddress();
this._omd
.showValues(this._toggleValues.selected())
.lazyRender()
;
});
_sample: SampleT;
_selectSample = new SelectDropDown()
.values(sampleKeys)
.on("click", key => {
this._sample = samples[key];
this.updateAddress();
this._mdEditor
.text(this._sample.content)
.lazyRender()
;
this.generate();
})
;
_buttonGithub = new Button().faChar("fa-github").tooltip("GitHub Repository")
.on("click", () => {
const win = window.open("https://github.com/hpcc-systems/Visualization/tree/trunk/packages/observable-md", "_blank");
win.focus();
})
;
_titleBar = new TitleBar().buttons([this._buttonGenerate, new Spacer(), this._buttonDownload, this._toggleValues, new Spacer(), this._selectSample, new Spacer(), this._buttonGithub])
.title("Observable Markdown Demo")
;
_mdEditor: ObservableMarkdownEditor = new ObservableMarkdownEditor()
.on("changes", () => {
this.updateToolbar();
})
;
_mdErrors = new Table()
.columns(["Type", "Message", "Row", "Col"])
.sortable(true)
.renderHtml(true)
.on("click", (row, col, sel) => {
if (sel) {
this._mdEditor.setCursor(row.Row, row.Col);
}
})
;
_lhsSplit = new SplitPanel("vertical")
.addWidget(this._mdEditor)
.addWidget(this._mdErrors)
;
_omd = new Observable()
.on("runtimeUpdated", () => {
this.updateErrors(this._omd.errors());
})
;
_html = new HTMLEditor()
;
_rhsTab = new TabPanel()
.addWidget(this._omd, "Markdown", { overflowY: "auto" })
.addWidget(this._html, "HTML")
;
_split = new SplitPanel("horizontal")
.addWidget(this._lhsSplit)
.addWidget(this._rhsTab)
;
constructor(defaultSelection?: string, debug = false) {
super();
if (!samples[defaultSelection]) {
defaultSelection = "Hello World (.omd)";
}
this._selectSample.selected(defaultSelection);
this._toggleValues.selected(debug);
}
updateAddress() {
const newUrl = document.location.origin + document.location.pathname + encodeURI(`?${this._selectSample.selected()}${this._toggleValues.selected() === true ? "&debug" : ""}`);
try {
window.history.pushState("", "", newUrl);
} catch (e) {
// Local files do not have history...
}
}
mode(): "ojs" | "omd" {
return this._selectSample.selected().indexOf("(.ojs)") >= 0 ? "ojs" : "omd";
}
generate() {
this.clearErrors();
const mode = this.mode();
const text = this._mdEditor.text();
this._omd
.mode(mode)
.text(text)
.lazyRender()
;
this._html
.text(html(text, mode))
.lazyRender()
;
this.updateToolbar();
}
updateToolbar() {
this._buttonGenerate.enabled(this._mdEditor.text() !== this._omd.text()).lazyRender();
}
clearErrors() {
this._mdEditor.removeAllHighlight();
this._mdErrors
.data([])
.lazyRender()
;
}
updateErrors(errors: OJSRuntimeError[]) {
this._mdEditor.removeAllHighlight();
const tableErrors = [];
errors.forEach(e => {
const startPos = this._mdEditor.positionAt(e.start);
const endPos = this._mdEditor.positionAt(e.end - 1);
if (e.severity === "rejected") {
this._mdEditor.highlightError(startPos, endPos);
}
tableErrors.push([e.severity, e.message, startPos.line, startPos.ch, e.start, e.end]);
});
this._mdErrors
.data(tableErrors)
.lazyRender()
;
}
enter(domNode, element) {
super.enter(domNode, element);
this.top(this._titleBar);
this.center(this._split);
this._sample = samples[this._selectSample.selected()];
this._mdEditor
.text(this._sample ? this._sample.content : "")
;
this._omd
.showValues(this._toggleValues.selected())
;
this.generate();
}
update(domNode, element) {
super.update(domNode, element);
this.updateToolbar();
}
}