UNPKG

@triply/yasr

Version:

Yet Another SPARQL Resultset GUI

171 lines (158 loc) 6.08 kB
/** * Make sure not to include any deps from our main index file. That way, we can easily publish the publin as standalone build */ import { Plugin } from "../"; import Yasr from "../../"; require("./index.scss"); const CodeMirror = require("codemirror"); require("codemirror/addon/fold/foldcode.js"); require("codemirror/addon/fold/foldgutter.js"); require("codemirror/addon/fold/xml-fold.js"); require("codemirror/addon/fold/brace-fold.js"); require("codemirror/addon/edit/matchbrackets.js"); require("codemirror/mode/xml/xml.js"); require("codemirror/mode/javascript/javascript.js"); require("codemirror/lib/codemirror.css"); import { drawSvgStringAsElement, addClass, removeClass, drawFontAwesomeIconAsSvg } from "@triply/yasgui-utils"; import * as faAlignIcon from "@fortawesome/free-solid-svg-icons/faAlignLeft"; import { DeepReadonly } from "ts-essentials"; import * as imgs from "../../imgs"; export interface PluginConfig { maxLines: number; } export default class Response implements Plugin<PluginConfig> { private yasr: Yasr; label = "Response"; priority = 2; helpReference = "https://triply.cc/docs/yasgui#response"; private config: DeepReadonly<PluginConfig>; private overLay: HTMLDivElement | undefined; private cm: CodeMirror.Editor | undefined; constructor(yasr: Yasr) { this.yasr = yasr; this.config = Response.defaults; if (yasr.config.plugins["response"] && yasr.config.plugins["response"].dynamicConfig) { this.config = { ...this.config, ...yasr.config.plugins["response"].dynamicConfig, }; } } // getDownloadInfo: getDownloadInfo canHandleResults() { if (!this.yasr.results) return false; if (!this.yasr.results.getOriginalResponseAsString) return false; var response = this.yasr.results.getOriginalResponseAsString(); if ((!response || response.length == 0) && this.yasr.results.getError()) return false; //in this case, show exception instead, as we have nothing to show anyway return true; } public getIcon() { return drawSvgStringAsElement(drawFontAwesomeIconAsSvg(faAlignIcon)); } download(filename?: string) { if (!this.yasr.results) return; const contentType = this.yasr.results.getContentType(); const type = this.yasr.results.getType(); const extension = type === "xml" ? "rdf" : type; return { getData: () => { return this.yasr.results?.getOriginalResponseAsString() || ""; }, filename: `${filename || "queryResults"}${extension ? "." + extension : ""}`, contentType: contentType ? contentType : "text/plain", title: "Download result", }; } draw(persistentConfig: PluginConfig) { const config: DeepReadonly<PluginConfig> = { ...this.config, ...persistentConfig, }; // When the original response is empty, use an empty string let value = this.yasr.results?.getOriginalResponseAsString() || ""; const lines = value.split("\n"); if (lines.length > config.maxLines) { value = lines.slice(0, config.maxLines).join("\n"); } const codemirrorOpts: Partial<CodeMirror.EditorConfiguration> = { readOnly: true, lineNumbers: true, lineWrapping: true, foldGutter: true, gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], value: value, extraKeys: { Tab: false }, }; const mode = this.yasr.results?.getType(); if (mode === "json") { codemirrorOpts.mode = { name: "javascript", json: true }; } this.cm = CodeMirror(this.yasr.resultsEl, codemirrorOpts); // Don't show less originally we've already set the value in the codemirrorOpts if (lines.length > config.maxLines) this.showLess(false); } private limitData(value: string) { const lines = value.split("\n"); if (lines.length > this.config.maxLines) { value = lines.slice(0, this.config.maxLines).join("\n"); } return value; } /** * * @param setValue Optional, if set to false the string will not update */ showLess(setValue = true) { if (!this.cm) return; // Add overflow addClass(this.cm.getWrapperElement(), "overflow"); // Remove old instance if (this.overLay) { this.overLay.remove(); this.overLay = undefined; } // Wrapper this.overLay = document.createElement("div"); addClass(this.overLay, "overlay"); // overlay content const overlayContent = document.createElement("div"); addClass(overlayContent, "overlay_content"); const showMoreButton = document.createElement("button"); showMoreButton.title = "Show all"; addClass(showMoreButton, "yasr_btn", "overlay_btn"); showMoreButton.textContent = "Show all"; showMoreButton.addEventListener("click", () => this.showMore()); overlayContent.append(showMoreButton); const downloadButton = document.createElement("button"); downloadButton.title = "Download result"; addClass(downloadButton, "yasr_btn", "overlay_btn"); const text = document.createElement("span"); text.innerText = "Download result"; downloadButton.appendChild(text); downloadButton.appendChild(drawSvgStringAsElement(imgs.download)); downloadButton.addEventListener("click", () => this.yasr.download()); downloadButton.addEventListener("keydown", (event) => { if (event.code === "Space" || event.code === "Enter") this.yasr.download(); }); overlayContent.appendChild(downloadButton); this.overLay.appendChild(overlayContent); this.cm.getWrapperElement().appendChild(this.overLay); if (setValue) { this.cm.setValue(this.limitData(this.yasr.results?.getOriginalResponseAsString() || "")); } } /** * Render the raw response full length */ showMore() { if (!this.cm) return; removeClass(this.cm.getWrapperElement(), "overflow"); this.overLay?.remove(); this.overLay = undefined; this.cm.setValue(this.yasr.results?.getOriginalResponseAsString() || ""); this.cm.refresh(); } public static defaults: PluginConfig = { maxLines: 30, }; }