UNPKG

@discoveryjs/discovery

Version:

Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards

135 lines (134 loc) 4.04 kB
import { createElement } from "../../core/utils/dom.js"; import { copyText } from "../../core/utils/copy-text.js"; import { getParamsFromContext } from "./params.js"; function quote(str) { return str.replace(/\\/g, "\\\\").replace(/\t/g, "\\t").replace(/\r/g, "\\r").replace(/\n/g, "\\n").replace(/'/g, "\\'"); } function exportStateAsJson(pageParams) { const { title, query, view } = pageParams; const res = { title, query, view }; return `{ ${Object.keys(res).reduce( (props, k) => typeof res[k] === "string" ? props.concat(` ${k}: '${quote(res[k])}'`) : props, [] ).join(",\n")} }`; } function toDate(value) { if (value && (typeof value === "number" || typeof value === "string")) { const date = new Date(value); return !isNaN(Number(date)) ? date : null; } return value instanceof Date ? value : null; } function formatDate(value) { const date = toDate(value); if (date) { return date.toISOString().replace(/^(\d{4})-(\d{2})-(\d{2})T([\d:]+).*/, "$3/$2/$1 $4 UTC"); } return null; } export default function(host, updateParams) { let titleInputEl; let dataDateTimeEl; let viewDateTimeEl; let noeditToggleEl; const shareOptionsPopup = new host.view.Popup({ render: (popupEl, _, hide) => host.view.render(popupEl, { view: "menu", data: () => [ { text: "Copy page permalink", disabled: !host.action.has("permalink"), action: async () => copyText(await host.action.call("permalink", host.pageHash)) }, { text: "Copy page hash", action: () => copyText(host.pageHash) }, { text: "Copy page as JSON", action: () => copyText(exportStateAsJson(host.pageParams)) } ], onClick(item) { hide(); item.action(); } }) }); const actionsPanel = createElement("div", "discovery-actions", [ noeditToggleEl = createElement("button", { class: "edit-mode discovery-hidden-in-dzen", title: "Toggle edit mode", onclick() { this.blur(); updateParams({ noedit: !host.pageParams.noedit }); } }), createElement("button", { class: "share", title: "Sharing", onclick() { this.blur(); shareOptionsPopup.show(this); } }), createElement("button", { class: "toggle-fullscreen", title: "Toggle full page mode", onclick() { this.blur(); updateParams({ dzen: !host.pageParams.dzen }); } }) ]); const updateHeaderTitle = (target) => { target.parentNode.dataset.title = target.value || target.placeholder; }; const headerEl = createElement("div", "discovery-header", [ createElement("div", { class: "discovery-header-text", "data-title": "\xA0" }, [ titleInputEl = createElement("input", { class: "discovery-hidden-in-dzen", placeholder: "Untitled discovery", oninput() { updateHeaderTitle(this); }, onchange() { updateHeaderTitle(this); updateParams({ title: this.value }, true); }, onkeypress(e) { if (e.key === "Enter") { this.blur(); } } }), createElement("span", "timestamp", [ dataDateTimeEl = createElement("span", null, " "), viewDateTimeEl = createElement("span") ]) ]) ]); return { el: [ actionsPanel, headerEl ], render(data, context) { const { title, noedit } = getParamsFromContext(context); const createdAt = formatDate(context?.datasets?.[0]?.resource?.createdAt); titleInputEl.value = title || ""; updateHeaderTitle(titleInputEl); noeditToggleEl.classList.toggle("disabled", noedit); dataDateTimeEl.innerText = createdAt ? "Data collected at " + createdAt + " | " : ""; viewDateTimeEl.innerText = "Rendered at " + formatDate(/* @__PURE__ */ new Date()); } }; }