diff --git a/openbb_terminal/core/plots/assets/icon.png b/openbb_terminal/core/plots/assets/icon.png deleted file mode 100644 index 1d77bc133cc7..000000000000 Binary files a/openbb_terminal/core/plots/assets/icon.png and /dev/null differ diff --git a/openbb_terminal/core/plots/old_table.html b/openbb_terminal/core/plots/old_table.html deleted file mode 100644 index 4aefb6e015ed..000000000000 --- a/openbb_terminal/core/plots/old_table.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - -
- - - diff --git a/openbb_terminal/core/plots/web/bar_menus.js b/openbb_terminal/core/plots/web/bar_menus.js deleted file mode 100644 index 455e96326f8d..000000000000 --- a/openbb_terminal/core/plots/web/bar_menus.js +++ /dev/null @@ -1,460 +0,0 @@ -// Custom Menu functions for Plotly charts - -async function autoScaling(eventdata, graphs) { - try { - if (eventdata["xaxis.range[0]"] != undefined) { - const x_min = eventdata["xaxis.range[0]"]; - const x_max = eventdata["xaxis.range[1]"]; - let to_update = {}; - let y_min, y_max; - - const YaxisData = graphs.data.filter((trace) => trace.yaxis != undefined); - const yaxis_unique = [ - ...new Set( - YaxisData.map( - (trace) => - trace.yaxis || trace.y != undefined || trace.type == "candlestick" - ) - ), - ]; - - const get_all_yaxis_traces = (yaxis) => { - return graphs.data.filter( - (trace) => - trace.yaxis == yaxis && (trace.y || trace.type == "candlestick") - ); - }; - - yaxis_unique.forEach((unique) => { - if (typeof unique != "string") { - return; - } - let yaxis = "yaxis" + unique.replace("y", ""); - let y_candle = []; - let y_values = []; - let log_scale = graphs.layout[yaxis].type == "log"; - - get_all_yaxis_traces(unique).forEach((trace2) => { - let x = trace2.x; - log_scale = graphs.layout[yaxis].type == "log"; - - let y = trace2.y != undefined ? trace2.y : []; - let y_low = trace2.type == "candlestick" ? trace2.low : []; - let y_high = trace2.type == "candlestick" ? trace2.high : []; - - if (log_scale) { - y = y.map(Math.log10); - if (trace2.type == "candlestick") { - y_low = trace2.low.map(Math.log10); - y_high = trace2.high.map(Math.log10); - } - } - - let yx_values = x.map((x, i) => { - let out = null; - if (x >= x_min && x <= x_max) { - if (trace2.y != undefined) { - console.log(trace2.name, trace2.type, trace2.yaxis); - out = y[i]; - } - if (trace2.type == "candlestick") { - y_candle.push(y_low[i]); - y_candle.push(y_high[i]); - } - } - return out; - }); - - y_values = y_values.concat(yx_values); - }); - - y_values = y_values.filter((y2) => y2 != undefined && y2 != null); - y_min = Math.min(...y_values); - y_max = Math.max(...y_values); - - if (y_candle.length > 0) { - y_candle = y_candle.filter((y2) => y2 != undefined && y2 != null); - y_min = Math.min(...y_candle); - y_max = Math.max(...y_candle); - } - - let org_y_max = y_max; - let is_volume = - graphs.layout[yaxis].fixedrange != undefined && - graphs.layout[yaxis].fixedrange == true; - - if (y_min != undefined && y_max != undefined) { - let y_range = y_max - y_min; - let y_mult = 0.15; - if (y_candle.length > 0) { - y_mult = 0.3; - } - - y_min -= y_range * y_mult; - y_max += y_range * y_mult; - - if (is_volume) { - if (graphs.layout[yaxis].tickvals != undefined) { - const range_x = 7; - let volume_ticks = org_y_max; - let round_digits = -3; - let first_val = Math.round(volume_ticks * 0.2, round_digits); - let x_zipped = [2, 5, 6, 7, 8, 9, 10]; - let y_zipped = [1, 4, 5, 6, 7, 8, 9]; - - for (let i = 0; i < x_zipped.length; i++) { - if (String(volume_ticks).length > x_zipped[i]) { - round_digits = -y_zipped[i]; - first_val = Math.round(volume_ticks * 0.2, round_digits); - } - } - let tickvals = [ - Math.floor(first_val), - Math.floor(first_val * 2), - Math.floor(first_val * 3), - Math.floor(first_val * 4), - ]; - let volume_range = [0, Math.floor(volume_ticks * range_x)]; - - to_update[yaxis + ".tickvals"] = tickvals; - to_update[yaxis + ".range"] = volume_range; - to_update[yaxis + ".tickformat"] = ".2s"; - return; - } - y_min = 0; - y_max = graphs.layout[yaxis].range[1]; - } - to_update[yaxis + ".range"] = [y_min, y_max]; - } - }); - Plotly.update(graphs, {}, to_update); - } - } catch (e) { - console.log(`Error in AutoScaling: ${e}`); - } -} - -function changeColor() { - if (!globals.color_picker) { - let color_picker = document.getElementById("changecolor"); - globals.color_picker = color_picker; - - color_picker.style.display = "block"; - color_picker.style.width = null; - dragElement(color_picker); - - function dragElement(elmnt) { - let pos1 = 0, - pos2 = 0, - pos3 = 0, - pos4 = 0; - if (document.getElementById(elmnt.id + "_header")) { - // if present, the header is where you move the DIV from: - document.getElementById(elmnt.id + "_header").onmousedown = - dragMouseDown; - } else { - // otherwise, move the DIV from anywhere inside the DIV: - elmnt.onmousedown = dragMouseDown; - } - - function dragMouseDown(e) { - e = e || window.event; - e.preventDefault(); - // get the mouse cursor position at startup: - pos3 = e.clientX; - pos4 = e.clientY; - document.onmouseup = closeDragElement; - // call a function whenever the cursor moves: - document.onmousemove = elementDrag; - } - - function elementDrag(e) { - e = e || window.event; - e.preventDefault(); - // calculate the new cursor position: - pos1 = pos3 - e.clientX; - pos2 = pos4 - e.clientY; - pos3 = e.clientX; - pos4 = e.clientY; - // set the element's new position: - elmnt.style.top = elmnt.offsetTop - pos2 + "px"; - elmnt.style.left = elmnt.offsetLeft - pos1 + "px"; - } - - function closeDragElement() { - // stop moving when mouse button is released: - document.onmouseup = null; - document.onmousemove = null; - } - } - } else { - globals.color_picker.style.display = "none"; - globals.color_picker = null; - } -} - -function uploadImage() { - const loader = document.getElementById("loader"); - loader.classList.add("show"); - Plotly.toImage(globals.CHART_DIV, { - format: "png", - height: 627, - width: 1200, - }) - .then(function (url) { - let data = { - image: url, - title: globals.title, - description: "Check out this chart from OpenBB", - }; - - fetch("https://uppy-self.vercel.app/api/upload-image", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(data), - }) - .then(function (response) { - return response.json(); - }) - .then(function (data) { - const { url, id } = data; - loader.classList.remove("show"); - openPopup("popup_upload", { url }); - }) - .catch(function (err) { - console.log(err); - loader.classList.remove("show"); - }); - }) - .catch(function (err) { - console.log(err); - loader.classList.remove("show"); - }); -} - -const openbb_watermark = { - yref: "paper", - xref: "paper", - x: 1, - y: 0, - text: "OpenBB Terminal", - font_size: 17, - font_color: "gray", - opacity: 0.5, - xanchor: "right", - yanchor: "bottom", - yshift: -80, - xshift: 40, -}; - -async function setWatermarks(margin, old_index, init = false) { - if (init) { - globals.CHART_DIV.layout.annotations.push(openbb_watermark); - if (globals.cmd_idx && globals.cmd_src) { - globals.CHART_DIV.layout.annotations[globals.cmd_idx].text = - globals.cmd_src; - } - - Plotly.relayout(globals.CHART_DIV, { - "title.text": globals.title, - margin: globals.old_margin, - }); - } - - if (!init) { - if (globals.cmd_idx && globals.cmd_src) { - globals.CHART_DIV.layout.annotations[globals.cmd_idx].text = ""; - } - globals.CHART_DIV.layout.annotations.splice(old_index, 1); - - Plotly.relayout(globals.CHART_DIV, { - "title.text": "", - margin: margin, - }); - } -} - -async function downloadImage(filename, extension, writable = undefined) { - const loader = document.getElementById("loader"); - loader.classList.add("show"); - - let imageDownload = undefined; - - if (extension == "png") { - imageDownload = domtoimage.toPng; - } else if (extension == "jpeg") { - imageDownload = domtoimage.toJpeg; - // } else if (extension == "svg") { - // imageDownload = domtoimage.toSvg; - } else if (["svg", "pdf"].includes(extension)) { - const margin = globals.CHART_DIV.layout.margin; - const old_index = globals.CHART_DIV.layout.annotations.length; - - await setWatermarks(margin, old_index, true); - - if (window.showSaveFilePicker && writable) { - await Plotly.toImage(globals.CHART_DIV, { - format: "svg", - height: globals.CHART_DIV.clientHeight, - width: globals.CHART_DIV.clientWidth, - }).then(async function (dataUrl) { - const blob = await fetch(dataUrl).then((r) => r.blob()); - await writable.write(blob); - await writable.close(); - }); - } else { - Plotly.downloadImage(globals.CHART_DIV, { - format: "svg", - height: globals.CHART_DIV.clientHeight, - width: globals.CHART_DIV.clientWidth, - filename: filename, - }); - } - - await setWatermarks(margin, old_index, false); - - return; - } else { - console.log("Invalid extension"); - return; - } - - imageDownload(document.getElementById("openbb_container")) - .then(async function (dataUrl) { - if (window.showSaveFilePicker && writable) { - const blob = await fetch(dataUrl).then((r) => r.blob()); - await writable.write(blob); - await writable.close(); - } else { - downloadURI(dataUrl, filename + "." + extension); - } - loader.classList.remove("show"); - }) - .catch(function (error) { - console.error("oops, something went wrong!", error); - loader.classList.remove("show"); - hideModebar(); - }); -} - -function downloadURI(uri, name) { - let link = document.createElement("a"); - link.download = name; - link.href = uri; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); -} - -async function downloadData(gd, filename, writable = undefined) { - let data = gd.data; - let candlestick = false; - let csv = undefined; - - data.forEach(function (trace) { - // check if candlestick - if (trace.type == "candlestick") { - candlestick = true; - return; - } - }); - - let xaxis = - "title" in gd.layout["xaxis"] && - gd.layout["xaxis"]["title"]["text"] != undefined - ? gd.layout["xaxis"]["title"]["text"] - : "x"; - - let yaxis = - "title" in gd.layout["yaxis"] && - gd.layout["yaxis"]["title"]["text"] != undefined - ? gd.layout["yaxis"]["title"]["text"] - : "y"; - - if (candlestick) { - csv = "Date,Open,High,Low,Close\n"; - data.forEach(function (trace) { - if (trace.type == "candlestick") { - let x = trace.x; - let open = trace.open; - let high = trace.high; - let low = trace.low; - let close = trace.close; - - for (let i = 0; i < x.length; i++) { - csv += `${x[i]},${open[i]},${high[i]},${low[i]},${close[i]}\n`; - } - } - }); - } else { - let traces = 0; - data.forEach(function (trace) { - if (trace.type == "scatter") { - traces++; - } - }); - - if (traces == 1) { - csv = `${data[0].name},${xaxis},${yaxis}\n`; - data.forEach(function (trace) { - if (trace.type == "scatter") { - let x = trace.x; - let y = trace.y; - - for (let i = 0; i < x.length; i++) { - csv += `${x[i]},${y[i]}\n`; - } - } - }); - } else if (traces > 1) { - csv = `${xaxis}`; - data.forEach(function (trace) { - if (trace.type == "scatter") { - csv += `,${trace.name}`; - } - }); - csv += "\n"; - - let x = data[0].x; - for (let i = 0; i < x.length; i++) { - csv += `${x[i]}`; - data.forEach(function (trace) { - if (trace.type == "scatter") { - csv += `,${trace.y[i]}`; - } - }); - csv += "\n"; - } - } else { - return; - } - } - - const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" }); - if (navigator.msSaveBlob) { - // IE 10+ - navigator.msSaveBlob(blob, filename); - } else { - // feature detection - // Browsers that support showSaveFilePicker or HTML5 download attribute - if (window.showSaveFilePicker && writable) { - await writable.write(blob); - await writable.close(); - } else { - let link = window.document.createElement("a"); - if (link.download !== undefined) { - // feature detection - // Browsers that support HTML5 download attribute - let url = URL.createObjectURL(blob); - link.setAttribute("href", url); - link.setAttribute("download", filename); - link.style.visibility = "hidden"; - window.document.body.appendChild(link); - link.click(); - window.document.body.removeChild(link); - } - } - } -} diff --git a/openbb_terminal/core/plots/web/css/fonts/FiraCode-Regular.ttf b/openbb_terminal/core/plots/web/css/fonts/FiraCode-Regular.ttf deleted file mode 100644 index bd736851948d..000000000000 Binary files a/openbb_terminal/core/plots/web/css/fonts/FiraCode-Regular.ttf and /dev/null differ diff --git a/openbb_terminal/core/plots/web/css/fonts/FiraCode-VF.ttf b/openbb_terminal/core/plots/web/css/fonts/FiraCode-VF.ttf deleted file mode 100644 index c05ac827c584..000000000000 Binary files a/openbb_terminal/core/plots/web/css/fonts/FiraCode-VF.ttf and /dev/null differ diff --git a/openbb_terminal/core/plots/web/css/style.css b/openbb_terminal/core/plots/web/css/style.css deleted file mode 100644 index ad5e6454b368..000000000000 --- a/openbb_terminal/core/plots/web/css/style.css +++ /dev/null @@ -1,1351 +0,0 @@ -/* local Fira Code font */ -@font-face { - font-family: "Fira Code"; - src: url("fonts/FiraCode-VF.ttf") format("truetype"); - /* fix Fire Code font width issue that makes Text get cut off in Plotly.js */ - font-weight: 400 700; - font-stretch: 50%; -} - -html { - font-size: 62.5%; - font-family: "Fira Code", monospace, "Arial Black"; -} - -body { - font-family: "Fira Code", monospace, "Arial Black"; - font-size: 12px; - font-size: 1.2rem; - color: #ffffff; - background-color: #000000; - font-stretch: 50%; - overflow: hidden; -} - -.saving { - position: absolute; - z-index: 9999999; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - height: 100px; - width: 200px; - display: none; - justify-content: center; - align-items: center; - background-color: rgba(0, 0, 0, 0.7); - color: white; - box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.5); - border: 4px solid rgba(250, 250, 250, 0.5); - font-size: 1.5em; - border-radius: 20px; - animation: popup 0.3s ease-in-out; -} - -.saving.show { - display: flex; -} - -.openbb_container { - align-items: center; - width: 100%; - height: 100%; - background-color: #000000; - position: absolute; - top: 0; - left: 0; -} - -.openbb_header { - position: relative; - z-index: 99999999999; - text-align: center; - top: 0; - background-color: transparent; - box-sizing: border-box; -} - -.plotly-graph-div { - width: 100%; - height: 89.6%; - position: relative; - font-size: 12px; - font-size: 1.2rem; - font-family: "Fira Code", monospace, "Arial Black"; - visibility: visible; -} - -#changecolor { - position: absolute; - z-index: 9; - text-align: center; - top: 50%; - left: 50%; - width: 100px; - height: 60px; - background-color: transparent; - padding: 10px; - box-sizing: border-box; - display: none; -} - -#changecolor_header:hover { - margin-top: 0px !important; - margin-bottom: 0px !important; - border: 1px solid gold; - box-shadow: 0 0 5px gold; -} - -#changecolor_header { - padding: 10px; - cursor: move; - z-index: 10; - color: #fff; -} - -#changecolor_header input[type="color"] { - width: 100%; - height: 40px; - border: none; - border-radius: 5px; - margin-bottom: 20px !important; - cursor: pointer; - border: 1px solid #7d7d7d; - padding: 5px; - background-color: #131313; - color: #ffffff; - margin-right: 50px !important; -} - -@keyframes popup { - 0% { - -webkit-transition: all 0.3s ease-in-out; - transform: translate(-50%, -50%) scale(0.2); - } - - 40% { - transform: translate(-50%, -50%) scale(1.1); - } - - 80% { - transform: translate(-50%, -50%) scale(1.05); - } - - 100% { - transform: translate(-50%, -50%) scale(1); - } -} - -.popup_overlay { - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 420px; - background: #070707; - border: 1px solid #dcdcdc; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 4px; - padding: 40px; - box-sizing: border-box; - display: none; - font-family: "Fira Code", monospace, "Arial Black"; - animation: popup 0.3s ease-in-out; - box-shadow: 0 3px 10px rgb(0 0 0 / 0.2); - z-index: 2; -} - -.popup_content { - position: relative; - background-color: transparent; - padding: 0px; - width: 100%; - height: 100%; - z-index: 3; -} - -.popup_warning { - color: #ff0000; - font-size: 12px; - font-size: 1.2rem; - font-family: "Fira Code", monospace, "Arial Black"; - display: none; - font-weight: bold; - margin-top: -15px; - margin-left: 135px; -} - -.csv_column_container { - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 10px; - margin-top: 10px; - margin-bottom: 10px; -} - -.plotly-graph-div .modebar--hover .modebar-group { - border: 2px solid #5a5a5a !important; - border-radius: 4px; - padding: 2px 2px 2px !important; -} - -.modebar-group { - display: flex !important; - background-color: transparent !important; -} - -.modebar { - z-index: 5000 !important; - position: fixed !important; - bottom: 10px !important; - top: auto !important; - left: 50% !important; - right: auto !important; - align-items: center; - transform: translate(-50%, 10%) !important; -} - -@media screen and (max-width: 600px) { - .modebar-group { - display: block !important; - background-color: transparent !important; - } - - .modebar { - bottom: 20px !important; - } -} - -.modebar-group { - margin-left: 10px; - margin-right: 10px; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; -} - - -.modebar-group:nth-of-type(1):after { - content: "Panning Tools"; - height: fit-content; - width: fit-content; - position: absolute; - display: none; -} - -.modebar-group:nth-of-type(1):hover:after { - padding: 10px; - display: block; - font-size: 10px; - color: white; - cursor: pointer; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - top: -40px; - left: 50%; - transform: translateX(-50%); -} - -.modebar-group:nth-of-type(2):after { - content: "Indicator Tools"; - height: fit-content; - width: fit-content; - position: absolute; - display: none; -} - -.modebar-group:nth-of-type(2):hover:after { - padding: 10px; - display: block; - font-size: 10px; - color: white; - cursor: pointer; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - top: -40px; - left: 50%; - transform: translateX(-50%); -} - -.modebar-group:nth-of-type(3):after { - content: "Chart Tools"; - height: fit-content; - width: fit-content; - position: absolute; - display: none; -} - -.modebar-group:nth-of-type(3):hover:after { - padding: 10px; - display: block; - font-size: 10px; - color: white; - cursor: pointer; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - top: -40px; - left: 50%; - transform: translateX(-50%); -} - -.modebar-group:nth-of-type(4):after { - content: "Drawing Tools"; - height: fit-content; - width: fit-content; - position: absolute; - display: none; -} - -.modebar-group:nth-of-type(4):hover:after { - padding: 10px; - display: block; - font-size: 10px; - color: white; - cursor: pointer; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - top: -40px; - left: 50%; - transform: translateX(-50%); -} - -.modebar-group:nth-of-type(5):after { - content: "Export Tools"; - height: fit-content; - width: fit-content; - position: absolute; - display: none; -} - -.modebar-group:nth-of-type(5):hover:after { - padding: 10px; - display: block; - font-size: 10px; - color: white; - cursor: pointer; - background: #0f0f0f !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - top: -40px; - left: 50%; - transform: translateX(-50%); -} - -.modebar.vertical { - flex-direction: row !important; - flex-flow: initial !important; - gap: 6px !important; -} - -.js-plotly-plot .plotly .modebar.vertical .modebar-group { - padding-bottom: 0px !important; -} - -.modebar-container { - position: initial !important; -} - -.modebar-btn:hover .icon path { - fill: #00acff !important; -} - -.modebar-btn.active .icon path { - fill: #00acff !important; -} - -.menulayer { - background: #0f0f0f; - padding-right: 10px !important; - padding-left: 10px !important; - padding-top: 5px !important; - padding-bottom: 5px !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; -} - -.modebar-btn { - padding: 4px !important; - margin-left: 4px !important; - margin-right: 4px !important; - margin-top: 4px !important; - margin-bottom: 4px !important; -} - -.rangeselector { - background: #0f0f0f; - padding: 10px !important; - border: 1px solid #404040; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border-radius: 8px; - height: 33px !important; -} - -.modebar-btn:hover { - background-color: #1f1f1f !important; - border-radius: 8px; -} - -.updatemenu-item-rect { - fill-opacity: 0.5 !important; -} - -.updatemenu-item-rect:hover { - background-color: #1f1f1f !important; -} - -.selector-text { - text-transform: uppercase; -} - -button { - all: unset; - cursor: pointer; -} - -._btn { - display: inline-flex; - width: 100%; - align-items: center; - justify-content: center; - gap: 0.5rem; - border-radius: 4px; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1.5rem; - padding-right: 1.5rem; - text-align: center; - -webkit-text-decoration-line: none !important; - text-decoration-line: none !important; - transition-property: color, background-color, border-color, fill, stroke, - opacity, box-shadow, transform, filter, -webkit-text-decoration-color, - -webkit-backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - transition-timing-function: cubic-bezier(0, 0, 0.2, 1); -} - -@media (min-width: 768px) { - ._btn { - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - } -} - -._btn { - background-color: #eaeaeaff; - color: #2a2a2aff; -} - -._btn:hover { - background-color: #ffffffff; -} - -._btn:focus { - outline-style: solid; - outline-width: 2px; - outline-color: #808080ff; -} - -._btn:active { - background-color: #dcdcdcff; -} - -._btn:active:hover { - color: #070707ff; -} - -._btn:disabled { - background-color: #c8c8c8ff; - color: #808080ff; -} - -._btn:disabled:active { - background-color: #c8c8c8ff; - color: #808080ff; -} - -._btn-secondary { - display: inline-flex; - width: 100%; - align-items: center; - justify-content: center; - gap: 0.5rem; - border-radius: 4px; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1.5rem; - padding-right: 1.5rem; - text-align: center; - -webkit-text-decoration-line: none !important; - text-decoration-line: none !important; - transition-property: color, background-color, border-color, fill, stroke, - opacity, box-shadow, transform, filter, -webkit-text-decoration-color, - -webkit-backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - transition-timing-function: cubic-bezier(0, 0, 0.2, 1); -} - -@media (min-width: 768px) { - ._btn-secondary { - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - } -} - -._btn-secondary { - border-width: 1px; - border-color: #c8c8c8ff; - color: #c8c8c8ff; - outline-offset: 0px; -} - -._btn-secondary:hover { - border-color: #ffffffff; - color: #ffffffff; -} - -._btn-secondary:focus { - outline-style: solid; - outline-width: 2px; - outline-color: #808080ff; -} - -._btn-secondary:active { - border-color: #ffffffff; - background-color: #2a2a2aff; - color: #ffffffff; -} - -._btn-secondary:disabled { - border-color: #808080ff; - background-color: transparent; - color: #808080ff; -} - -._btn-tertiary { - display: inline-flex; - width: 100%; - align-items: center; - justify-content: center; - gap: 0.5rem; - border-radius: 4px; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1.5rem; - padding-right: 1.5rem; - text-align: center; - -webkit-text-decoration-line: none !important; - text-decoration-line: none !important; - transition-property: color, background-color, border-color, fill, stroke, - opacity, box-shadow, transform, filter, -webkit-text-decoration-color, - -webkit-backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter; - transition-property: color, background-color, border-color, - text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, - backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - transition-timing-function: cubic-bezier(0, 0, 0.2, 1); -} - -@media (min-width: 768px) { - ._btn-tertiary { - width: -webkit-fit-content; - width: -moz-fit-content; - width: fit-content; - } -} - -._btn-tertiary { - background-color: #070707ff; - color: #f6f6f6ff; -} - -._btn-tertiary:hover { - background-color: #2a2a2aff; - color: #ffffffff; -} - -._btn-tertiary:focus { - background-color: #070707ff; - outline-style: solid; - outline-width: 2px; - outline-color: #808080ff; -} - -._btn-tertiary:active { - background-color: #474747ff; - color: #ffffffff; -} - -._btn-tertiary:disabled { - background-color: #808080ff; - color: #474747ff; -} - -.loader { - position: relative; - bottom: 0px; - right: -5px; - border: 4px solid #f3f3f3; - border-radius: 50%; - border-top: 4px solid #00acff; - width: 20px; - height: 20px; - animation: spin 1.5s linear infinite; - opacity: 1; -} - -@keyframes spin { - 0% { - transform: rotate(0deg); - } - - 100% { - transform: rotate(360deg); - } -} - -ul { - margin: 0; - padding: 0; - list-style: none; - width: 150px; - border-bottom: 1px solid #404040; - background: #0f0f0f; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - display: flex; - flex-direction: row; -} - -ul li { - position: relative; -} - -li ul { - position: relative; - left: 0px; - top: 0; - display: none; -} - -ul li a { - display: block; - text-decoration: none; - color: #777; - background: #0f0f0f; - padding: 5px; - box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.06); - border: 1px solid #404040; - border-bottom: 0; -} - -/* Fix IE. Hide from IE Mac */ -* html ul li { - float: none; -} - -* html ul li a { - height: 1%; -} - -/* End */ - -li:hover ul { - display: block; -} - -li:hover { - max-height: 1%; -} - -#openbb_menu { - position: relative; - top: 0; - left: 0; - height: 3%; - z-index: 1 !important; -} - -/* ! tailwindcss v3.2.7 | MIT License | https://tailwindcss.com */ - -/* -1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) -2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) -*/ - -*, -::before, -::after { - box-sizing: border-box; - /* 1 */ - border-width: 0; - /* 2 */ - border-style: solid; - /* 2 */ - border-color: #e5e7eb; - /* 2 */ -} - -::before, -::after { - --tw-content: ""; -} - -/* -1. Use a consistent sensible line-height in all browsers. -2. Prevent adjustments of font size after orientation changes in iOS. -3. Use a more readable tab size. -4. Use the user's configured `sans` font-family by default. -5. Use the user's configured `sans` font-feature-settings by default. -*/ - -html { - line-height: 1.5; - /* 1 */ - -webkit-text-size-adjust: 100%; - /* 2 */ - -moz-tab-size: 4; - /* 3 */ - tab-size: 4; - /* 3 */ - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, - "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - /* 4 */ - font-feature-settings: normal; - /* 5 */ -} - -/* -1. Remove the margin in all browsers. -2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. -*/ - -body { - margin: 0; - /* 1 */ - line-height: inherit; - /* 2 */ -} - -/* -1. Add the correct height in Firefox. -2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) -3. Ensure horizontal rules are visible by default. -*/ - -hr { - height: 0; - /* 1 */ - color: inherit; - /* 2 */ - border-top-width: 1px; - /* 3 */ -} - -/* -Add the correct text decoration in Chrome, Edge, and Safari. -*/ - -abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; -} - -/* -Remove the default font size and weight for headings. -*/ - -h1, -h2, -h3, -h4, -h5, -h6 { - font-size: inherit; - font-weight: inherit; -} - -/* -Reset links to optimize for opt-in styling instead of opt-out. -*/ - -a { - color: inherit; - text-decoration: inherit; -} - -/* -Add the correct font weight in Edge and Safari. -*/ - -b, -strong { - font-weight: bolder; -} - -/* -1. Use the user's configured `mono` font family by default. -2. Correct the odd `em` font sizing in all browsers. -*/ - -code, -kbd, -samp, -pre { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, - "Liberation Mono", "Courier New", monospace; - /* 1 */ - font-size: 1em; - /* 2 */ -} - -/* -Add the correct font size in all browsers. -*/ - -small { - font-size: 80%; -} - -/* -Prevent `sub` and `sup` elements from affecting the line height in all browsers. -*/ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* -1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) -2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) -3. Remove gaps between table borders by default. -*/ - -table { - text-indent: 0; - /* 1 */ - border-color: inherit; - /* 2 */ - border-collapse: collapse; - /* 3 */ -} - -/* -1. Change the font styles in all browsers. -2. Remove the margin in Firefox and Safari. -3. Remove default padding in all browsers. -*/ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; - /* 1 */ - font-size: 100%; - /* 1 */ - font-weight: inherit; - /* 1 */ - line-height: inherit; - /* 1 */ - color: inherit; - /* 1 */ - margin: 0; - /* 2 */ - padding: 0; - /* 3 */ -} - -/* -Remove the inheritance of text transform in Edge and Firefox. -*/ - -button, -select { - text-transform: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Remove default button styles. -*/ - -button, -[type="button"], -[type="reset"], -[type="submit"] { - -webkit-appearance: button; - /* 1 */ - background-color: transparent; - /* 2 */ - background-image: none; - /* 2 */ -} - -/* -Use the modern Firefox focus style for all focusable elements. -*/ - -:-moz-focusring { - outline: auto; -} - -/* -Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) -*/ - -:-moz-ui-invalid { - box-shadow: none; -} - -/* -Add the correct vertical alignment in Chrome and Firefox. -*/ - -progress { - vertical-align: baseline; -} - -/* -Correct the cursor style of increment and decrement buttons in Safari. -*/ - -::-webkit-inner-spin-button, -::-webkit-outer-spin-button { - height: auto; -} - -/* -1. Correct the odd appearance in Chrome and Safari. -2. Correct the outline style in Safari. -*/ - -[type="search"] { - -webkit-appearance: textfield; - /* 1 */ - outline-offset: -2px; - /* 2 */ -} - -/* -Remove the inner padding in Chrome and Safari on macOS. -*/ - -::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* -1. Correct the inability to style clickable types in iOS and Safari. -2. Change font properties to `inherit` in Safari. -*/ - -::-webkit-file-upload-button { - -webkit-appearance: button; - /* 1 */ - font: inherit; - /* 2 */ -} - -/* -Add the correct display in Chrome and Safari. -*/ - -summary { - display: list-item; -} - -/* -Removes the default spacing and border for appropriate elements. -*/ - -blockquote, -dl, -dd, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -figure, -p, -pre { - margin: 0; -} - -fieldset { - margin: 0; - padding: 0; -} - -legend { - padding: 0; -} - -ol, -ul, -menu { - list-style: none; - margin: 0; - padding: 0; -} - -/* -Prevent resizing textareas horizontally by default. -*/ - -textarea { - resize: vertical; -} - -/* -1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) -2. Set the default placeholder color to the user's configured gray 400 color. -*/ - -input::placeholder, -textarea::placeholder { - opacity: 1; - /* 1 */ - color: #9ca3af; - /* 2 */ -} - -/* -Set the default cursor for buttons. -*/ - -button, -[role="button"] { - cursor: pointer; -} - -/* -Make sure disabled buttons don't get the pointer cursor. -*/ - -:disabled { - cursor: default; -} - -/* -1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) -2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) - This can trigger a poorly considered lint error in some tools but is included by design. -*/ - -img, -svg, -video, -canvas, -audio, -iframe, -embed, -object { - display: block; - /* 1 */ - vertical-align: middle; - /* 2 */ -} - -/* -Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) -*/ - -img, -video { - max-width: 100%; - height: auto; -} - -/* Make elements with the HTML hidden attribute stay hidden by default */ - -[hidden] { - display: none; -} - -*, -::before, -::after { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; -} - -::backdrop { - --tw-border-spacing-x: 0; - --tw-border-spacing-y: 0; - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-rotate: 0; - --tw-skew-x: 0; - --tw-skew-y: 0; - --tw-scale-x: 1; - --tw-scale-y: 1; - --tw-pan-x: ; - --tw-pan-y: ; - --tw-pinch-zoom: ; - --tw-scroll-snap-strictness: proximity; - --tw-ordinal: ; - --tw-slashed-zero: ; - --tw-numeric-figure: ; - --tw-numeric-spacing: ; - --tw-numeric-fraction: ; - --tw-ring-inset: ; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-color: rgb(59 130 246 / 0.5); - --tw-ring-offset-shadow: 0 0 #0000; - --tw-ring-shadow: 0 0 #0000; - --tw-shadow: 0 0 #0000; - --tw-shadow-colored: 0 0 #0000; - --tw-blur: ; - --tw-brightness: ; - --tw-contrast: ; - --tw-grayscale: ; - --tw-hue-rotate: ; - --tw-invert: ; - --tw-saturate: ; - --tw-sepia: ; - --tw-drop-shadow: ; - --tw-backdrop-blur: ; - --tw-backdrop-brightness: ; - --tw-backdrop-contrast: ; - --tw-backdrop-grayscale: ; - --tw-backdrop-hue-rotate: ; - --tw-backdrop-invert: ; - --tw-backdrop-opacity: ; - --tw-backdrop-saturate: ; - --tw-backdrop-sepia: ; -} - -.absolute { - position: absolute; -} - -.relative { - position: relative; -} - -.-inset-1 { - top: -0.25rem; - right: -0.25rem; - bottom: -0.25rem; - left: -0.25rem; -} - -.z-20 { - z-index: 20; -} - -.flex { - display: flex; -} - -.w-1\/3 { - width: 33.333333%; -} - -.items-center { - align-items: center; -} - -.justify-between { - justify-content: space-between; -} - -.gap-4 { - gap: 1rem; -} - -.overflow-hidden { - overflow: hidden; -} - -.rounded { - border-radius: 0.25rem; -} - -.rounded-md { - border-radius: 0.375rem; -} - -.border { - border-width: 1px; -} - -.border-grey-200\/60 { - border-color: rgb(220 220 220 / 0.6); -} - -.bg-grey-900 { - background-color: #070707ff; -} - -.bg-gradient-to-br { - background-image: linear-gradient(to bottom right, var(--tw-gradient-stops)); -} - -.from-\[\#072e49\]\/20 { - --tw-gradient-from: rgb(7 46 73 / 0.2); - --tw-gradient-to: rgb(7 46 73 / 0); - --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); -} - -.via-\[\#0d345f\]\/20 { - --tw-gradient-to: rgb(13 52 95 / 0); - --tw-gradient-stops: var(--tw-gradient-from), rgb(13 52 95 / 0.2), - var(--tw-gradient-to); -} - -.to-\[\#0d3362\]\/20 { - --tw-gradient-to: rgb(13 51 98 / 0.2); -} - -.px-4 { - padding-left: 1rem; - padding-right: 1rem; -} - -.py-2 { - padding-top: 0.5rem; - padding-bottom: 0.5rem; -} - -.text-center { - text-align: center; -} - -.text-right { - text-align: right; -} - -.text-xs { - font-size: 0.75rem; - line-height: 1rem; -} - -.font-bold { - font-weight: 700; -} - -.text-white { - --tw-text-opacity: 1; - color: rgb(255 255 255 / var(--tw-text-opacity)); -} - -.blur-md { - --tw-blur: blur(12px); - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - -._header { - background: #062d48; - background: linear-gradient(90deg, - #062d48, - #0b3054 15%, - #0e386c 45%, - #0b203d 64%, - #06101a 82%, - #060709); -} - - -@media screen and (max-height: 1000px) and (max-width: 1100px) { - ._header strong { - font-size: 1.1rem !important; - } - ._header p { - font-size: 1.0rem !important; - } - - ._header span { - font-size: 0.9rem !important; - } -} diff --git a/openbb_terminal/core/plots/web/css/table.css b/openbb_terminal/core/plots/web/css/table.css deleted file mode 100644 index fcb4c86cfc2b..000000000000 --- a/openbb_terminal/core/plots/web/css/table.css +++ /dev/null @@ -1,7 +0,0 @@ -body { - font-family: "Fira Code", monospace, "Arial Black"; - font-size: 1.2rem; - color: #ffffff; - background-color: #000000; - overflow: hidden; -} diff --git a/openbb_terminal/core/plots/web/helpers.js b/openbb_terminal/core/plots/web/helpers.js deleted file mode 100644 index d032ff946021..000000000000 --- a/openbb_terminal/core/plots/web/helpers.js +++ /dev/null @@ -1,1080 +0,0 @@ -const ICONS = { - sunIcon: { - viewBox: "0 0 16 16", - width: 16, - height: 16, - path: "M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z", - }, - moonIcon: { - viewBox: "0 0 25 25", - width: 25, - height: 25, - path: "M21.752 15.002A9.718 9.718 0 0118 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 003 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 009.002-5.998z", - }, - plotCsv: { - width: 900, - height: 900, - path: "M170.666667 106.666667l0.192 736H906.666667v64H149.546667c-23.552 0-42.666667-19.093333-42.666667-42.666667L106.666667 106.666667h64z m686.506666 454.144l13.653334 16.362666a21.333333 21.333333 0 0 1-2.666667 30.058667l-171.157333 143.146667a21.333333 21.333333 0 0 1-21.546667 3.477333l-229.973333-91.285333-113.834667 94.997333a21.333333 21.333333 0 0 1-30.037333-2.709333l-13.653334-16.362667a21.333333 21.333333 0 0 1 2.688-30.058667l133.312-111.274666a21.333333 21.333333 0 0 1 21.546667-3.456l229.930667 91.264 151.68-126.826667a21.333333 21.333333 0 0 1 30.037333 2.666667z m-1.621333-417.962667l16.896 13.013333a21.333333 21.333333 0 0 1 3.925333 29.888L685.802667 433.706667a21.333333 21.333333 0 0 1-20.202667 8.085333l-226.794667-35.413333-150.186666 222.357333a21.333333 21.333333 0 0 1-27.477334 7.018667l-2.133333-1.28-17.685333-11.946667a21.333333 21.333333 0 0 1-5.738667-29.610667l165.354667-244.821333a21.333333 21.333333 0 0 1 20.992-9.130667L650.453333 374.613333l175.146667-227.882666a21.333333 21.333333 0 0 1 29.930667-3.904z", - }, - addText: { - path: "M896 928H128a32 32 0 0 1-32-32V128a32 32 0 0 1 32-32h768a32 32 0 0 1 32 32v768a32 32 0 0 1-32 32z m-736-64h704v-704h-704z M704 352H320a32 32 0 0 1 0-64h384a32 32 0 0 1 0 64z M512 736a32 32 0 0 1-32-32V320a32 32 0 0 1 64 0v384a32 32 0 0 1-32 32z", - width: 950, - height: 950, - }, - changeTitle: { - path: "M122.368 165.888h778.24c-9.216 0-16.384-7.168-16.384-16.384v713.728c0-9.216 7.168-16.384 16.384-16.384h-778.24c9.216 0 16.384 7.168 16.384 16.384V150.016c0 8.192-6.656 15.872-16.384 15.872z m-32.768 684.544c0 26.112 20.992 47.104 47.104 47.104h750.08c26.112 0 47.104-20.992 47.104-47.104V162.304c0-26.112-20.992-47.104-47.104-47.104H136.704c-26.112 0-47.104 20.992-47.104 47.104v688.128z M244.736 656.896h534.016v62.464H244.736z M373.76 358.4H307.2v219.136h-45.568V358.4H192v-41.472H373.76V358.4zM403.968 316.928h44.032v50.176h-44.032v-50.176z m0 67.072h44.032v194.048h-44.032V384zM576.512 541.184l8.704 31.744c-13.312 5.12-26.624 8.192-38.912 8.704-32.768 1.024-48.64-15.36-48.128-48.128V422.912h-26.624V384h26.624v-46.592l44.032-21.504V384h36.352v38.912h-36.352V532.48c-1.024 10.24 3.072 14.848 11.264 13.824 5.12 0 12.8-1.536 23.04-5.12zM619.008 316.928h44.032v260.608h-44.032V316.928zM813.056 509.952l41.472 12.8c-11.776 40.96-37.888 61.44-78.336 60.416-52.736-1.536-80.384-34.304-81.92-98.304 2.56-67.072 29.696-102.4 81.92-105.984 52.224 1.536 78.336 36.864 79.36 105.984v13.824h-117.248c3.584 30.208 15.872 45.568 37.888 46.592 19.968 0.512 32.256-11.264 36.864-35.328z m-72.704-51.712h70.656c-1.024-25.088-12.288-38.4-33.792-38.912-21.504 0.512-33.792 13.824-36.864 38.912z", - width: 920, - height: 900, - }, - changeColor: { - path: "M8 3C5.79 3 4 4.79 4 7V14C4 15.1 4.9 16 6 16H9V20C9 21.1 9.9 22 11 22H13C14.1 22 15 21.1 15 20V16H18C19.1 16 20 15.1 20 14V3H8M8 5H12V7H14V5H15V9H17V5H18V10H6V7C6 5.9 6.9 5 8 5M6 14V12H18V14H6Z", - width: 22, - height: 22, - }, - uploadImage: { - path: "M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5", - width: 1024, - height: 1024, - }, - downloadCsv: { - path: `M486.2,196.121h-13.164V132.59c0-0.399-0.064-0.795-0.116-1.2c-0.021-2.52-0.824-5-2.551-6.96L364.656,3.677 - c-0.031-0.034-0.064-0.044-0.085-0.075c-0.629-0.707-1.364-1.292-2.141-1.796c-0.231-0.157-0.462-0.286-0.704-0.419 - c-0.672-0.365-1.386-0.672-2.121-0.893c-0.199-0.052-0.377-0.134-0.576-0.188C358.229,0.118,357.4,0,356.562,0H96.757 - C84.893,0,75.256,9.649,75.256,21.502v174.613H62.093c-16.972,0-30.733,13.756-30.733,30.73v159.81 - c0,16.966,13.761,30.736,30.733,30.736h13.163V526.79c0,11.854,9.637,21.501,21.501,21.501h354.777 - c11.853,0,21.502-9.647,21.502-21.501V417.392H486.2c16.966,0,30.729-13.764,30.729-30.731v-159.81 - C516.93,209.872,503.166,196.121,486.2,196.121z M96.757,21.502h249.053v110.006c0,5.94,4.818,10.751,10.751,10.751h94.973v53.861 - H96.757V21.502z M258.618,313.18c-26.68-9.291-44.063-24.053-44.063-47.389c0-27.404,22.861-48.368,60.733-48.368 - c18.107,0,31.447,3.811,40.968,8.107l-8.09,29.3c-6.43-3.107-17.862-7.632-33.59-7.632c-15.717,0-23.339,7.149-23.339,15.485 - c0,10.247,9.047,14.769,29.78,22.632c28.341,10.479,41.681,25.239,41.681,47.874c0,26.909-20.721,49.786-64.792,49.786 - c-18.338,0-36.449-4.776-45.497-9.77l7.38-30.016c9.772,5.014,24.775,10.006,40.264,10.006c16.671,0,25.488-6.908,25.488-17.396 - C285.536,325.789,277.909,320.078,258.618,313.18z M69.474,302.692c0-54.781,39.074-85.269,87.654-85.269 - c18.822,0,33.113,3.811,39.549,7.149l-7.392,28.816c-7.38-3.084-17.632-5.939-30.491-5.939c-28.822,0-51.206,17.375-51.206,53.099 - c0,32.158,19.051,52.4,51.456,52.4c10.947,0,23.097-2.378,30.241-5.238l5.483,28.346c-6.672,3.34-21.674,6.919-41.208,6.919 - C98.06,382.976,69.474,348.424,69.474,302.692z M451.534,520.962H96.757v-103.57h354.777V520.962z M427.518,380.583h-42.399 - l-51.45-160.536h39.787l19.526,67.894c5.479,19.046,10.479,37.386,14.299,57.397h0.709c4.048-19.298,9.045-38.352,14.526-56.693 - l20.487-68.598h38.599L427.518,380.583z`, - width: 550, - height: 550, - transform: "translate(4, 0)", - }, - downloadImage: { - path: "M22.71,6.29a1,1,0,0,0-1.42,0L20,7.59V2a1,1,0,0,0-2,0V7.59l-1.29-1.3a1,1,0,0,0-1.42,1.42l3,3a1,1,0,0,0,.33.21.94.94,0,0,0,.76,0,1,1,0,0,0,.33-.21l3-3A1,1,0,0,0,22.71,6.29ZM19,13a1,1,0,0,0-1,1v.38L16.52,12.9a2.79,2.79,0,0,0-3.93,0l-.7.7L9.41,11.12a2.85,2.85,0,0,0-3.93,0L4,12.6V7A1,1,0,0,1,5,6h8a1,1,0,0,0,0-2H5A3,3,0,0,0,2,7V19a3,3,0,0,0,3,3H17a3,3,0,0,0,3-3V14A1,1,0,0,0,19,13ZM5,20a1,1,0,0,1-1-1V15.43l2.9-2.9a.79.79,0,0,1,1.09,0l3.17,3.17,0,0L15.46,20Zm13-1a.89.89,0,0,1-.18.53L13.31,15l.7-.7a.77.77,0,0,1,1.1,0L18,17.21Z", - width: 21, - height: 21, - transform: "translate(-2, -2)", - }, -}; - -function onlyOne(checkbox) { - var checkboxes = document.getElementsByName("csv_plot_yaxis_check"); - checkboxes.forEach((item) => { - if (item !== checkbox) item.checked = false; - }); -} - -function add_annotation(data, yshift, popup_data, current_text = null) { - let gd = globals.CHART_DIV; - let x = data.x; - let y = data.y; - let yref = data.yref; - let annotations = gd.layout.annotations; - let index = -1; - - for (let i = 0; i < annotations.length; i++) { - if ( - annotations[i].x == x && - annotations[i].y == y && - annotations[i].text == current_text - ) { - index = i; - break; - } - } - if (index == -1) { - let annotation = { - x: x, - y: y, - xref: "x", - yref: yref, - xanchor: "center", - text: popup_data.text, - showarrow: true, - arrowhead: 2, - arrowsize: 1, - arrowwidth: 2, - ax: x, - ay: y + yshift, - ayref: yref, - axref: "x", - bordercolor: popup_data.bordercolor, - bgcolor: "#000000", - borderwidth: 2, - borderpad: 4, - opacity: 0.8, - font: { - color: popup_data.color, - size: popup_data.size, - }, - clicktoshow: "onoff", - captureevents: true, - }; - annotations.push(annotation); - } else { - annotations[index].text = popup_data.text; - annotations[index].font.color = popup_data.color; - annotations[index].font.size = popup_data.size; - annotations[index].ay = y + yshift; - annotations[index].bordercolor = popup_data.bordercolor; - } - return annotations; -} - -function checkFile(popup, type = false) { - console.log("checkFile"); - let csv_file = popup.querySelector("#csv_file"); - let csv_name = popup.querySelector("#csv_name"); - let csv_type = popup.querySelector("#csv_trace_type"); - let csv_columns = popup.querySelector("#csv_columns"); - let csv_colors = popup.querySelector("#csv_colors"); - let csv_plot_yaxis_options = popup.querySelector("#csv_plot_yaxis_options"); - let csv_bar_orientation = popup.querySelector("#csv_bar_orientation"); - csv_plot_yaxis_options.style.display = "none"; - csv_bar_orientation.style.display = "none"; - csv_plot_yaxis_options.querySelector( - "#csv_percent_change_div" - ).style.display = "inline-block"; - - if (csv_file.files.length > 0) { - console.log("file selected"); - let file = csv_file.files[0]; - let reader = new FileReader(); - - reader.onload = function (e) { - let headers = e.target.result.split("\n")[0].split(","); - headers = headers.map((x) => x.replace(/\r/g, "")); - let headers_lower = headers.map((x) => x.trim().toLowerCase()); - let candle_cols = ["open", "high", "low", "close"]; - - let options = ""; - for (let i = 0; i < headers.length; i++) { - options += ``; - } - - // we try to guess the type of the data from the headers - if (type == false) { - if ( - headers_lower - .map(function (x) { - return candle_cols.includes(x); - }) - .includes(true) - ) { - csv_type.value = "candlestick"; - } else { - csv_type.value = "scatter"; - } - } - let option_ids = ["csv_x", "csv_y"]; - - csv_columns.innerHTML = "Columns:
"; - if (csv_type.value == "candlestick") { - option_ids = ["x", "open", "high", "low", "close"]; - let options_select = ""; - - for (let i = 0; i < option_ids.length; i++) { - let header_name = option_ids[i].replace(/\b[a-z]/g, (x) => - x.toUpperCase() - ); - - options_select += ` -
- - -
- `; - } - csv_columns.innerHTML += ` -
${options_select}
- `; - - csv_colors.innerHTML = ` - Candlestick colors:
- - - - - - `; - - for (let i = 0; i < option_ids.length; i++) { - if (headers_lower.includes(option_ids[i])) { - csv_columns.querySelector("#csv_" + option_ids[i]).value = - headers[headers_lower.indexOf(option_ids[i])]; - } else if (option_ids[i] == "x" && headers_lower.includes("date")) { - csv_columns.querySelector("#csv_x").value = - headers[headers_lower.indexOf("date")]; - } - } - globals.CSV_DIV.querySelector("#csv_percent_change_div").style.display = - "none"; - } else { - let color_text = csv_type.value == "bar" ? "Bar color" : "Line color"; - csv_columns.innerHTML = ` - Columns:
-
- - -
-
- - -
- `; - csv_colors.innerHTML = ` - - - `; - - if (headers_lower.includes("x")) { - csv_columns.querySelector("#csv_x").value = - headers[headers_lower.indexOf("x")]; - } else if (headers_lower.includes("date")) { - csv_columns.querySelector("#csv_x").value = - headers[headers_lower.indexOf("date")]; - } - - if (headers_lower.includes("y")) { - csv_columns.querySelector("#csv_y").value = - headers[headers_lower.indexOf("y")]; - } else if (headers_lower.includes("close")) { - csv_columns.querySelector("#csv_y").value = - headers[headers_lower.indexOf("close")]; - } - } - if (csv_type.value == "bar") { - csv_bar_orientation.style.display = "inline-block"; - globals.CSV_DIV.querySelector("#csv_percent_change_div").style.display = - "none"; - } - - csv_plot_yaxis_options.style.display = "inline-block"; - - // we try to guess the date and time to remove from the name of the file - // if "_" in the name of the file, - // we assume the first 2 parts or the last 2 parts are date and time - let filename = file.name.split(".")[0]; - csv_name.value = filename; - - try { - if (filename.includes("_")) { - let name_parts = filename.split("_"); - let date_regex = new RegExp("^[0-9]{8}$"); - - if (name_parts.length > 2) { - // we check if the first 2 parts are date and time - if (date_regex.test(name_parts[0])) { - name_parts.splice(0, 2); - } - // we check if the last 2 parts are date and time - else if (date_regex.test(name_parts[name_parts.length - 2])) { - name_parts.splice(name_parts.length - 2, 2); - } - csv_name.value = name_parts.join("_").replace(/openbb_/g, ""); - } - } - } catch (e) { - console.log(e); - } - }; - - reader.readAsText(file); - } -} - -function openbbFilename(data, csv = false) { - let title = csv ? "data" : "plots"; - - if (data.layout.title != undefined) { - title = (csv ? "data_" : "") + data.layout.title.text; - } - - globals.title = title; - - let filename = "openbb_" + title.replace(/|<\/b>/g, "").replace(/ /g, "_"); - - let date = new Date().toISOString().slice(0, 10).replace(/-/g, ""); - let time = new Date().toISOString().slice(11, 19).replace(/:/g, ""); - - return filename + "_" + date + "_" + time; -} - -function plot_text(data, popup_data, current_text = null) { - // Plots text on the chart based on the popup_data - // If current_text is not null, it will be replaced with the new text - // If current_text is null, a new annotation will be added - // popup_data is the data from the popup - // data is the data from the chart - - console.log("plot_text"); - let gd = globals.CHART_DIV; - let annotations = undefined; - let yaxis = data.yref.replace("y", "yaxis"); - let yrange = gd.layout[yaxis].range; - let yshift = (yrange[1] - yrange[0]) * 0.2; - - if (popup_data.yanchor == "below") { - yshift = -yshift; - } - - if (current_text == null) { - annotations = add_annotation(data, yshift, popup_data); - } else { - annotations = add_annotation(data, yshift, popup_data, current_text); - } - let to_update = { annotations: annotations, dragmode: "pan" }; - to_update[yaxis + ".type"] = "linear"; - - Plotly.update(gd, {}, to_update); - gd.removeAllListeners("plotly_click"); - - globals.TEXT_DIV = document.getElementById("popup_text"); - globals.TEXT_DIV.querySelectorAll("input").forEach(function (input) { - if (!input.name in ["addtext_color", "addtext_border"]) { - input.value = ""; - } - }); - closePopup(); -} - -function update_color() { - // updates the color of the last added shape - // this function is called when the color picker is used - let color = globals.color_picker.querySelector("#picked_color").value; - let gd = globals.CHART_DIV; - - // if there are no shapes, we remove the color picker - let shapes = gd.layout.shapes; - if (!shapes || shapes.length == 0) { - globals.color_picker.remove(); - return; - } - // we change last added shape color - let last_shape = shapes[shapes.length - 1]; - last_shape.line.color = color; - Plotly.update(gd, {}, { shapes: shapes }); -} - -function button_pressed(title, active = false) { - // changes the style of the button when it is pressed - // title is the title of the button - // active is true if the button is active, false otherwise - - let button = globals.barButtons[title]; - - if (!active) { - button.style.border = "1px solid rgba(0, 151, 222, 1.0)"; - button.style.borderRadius = "5px"; - button.style.borderpadding = "5px"; - button.style.boxShadow = "0 0 5px rgba(0, 151, 222, 1.0)"; - } else { - button.style.border = "transparent"; - button.style.boxShadow = "none"; - } -} - -const DARK_CHARTS_TEMPLATE = { - data: { - candlestick: [ - { - decreasing: { - fillcolor: "#e4003a", - line: { - color: "#e4003a", - }, - }, - increasing: { - fillcolor: "#00ACFF", - line: { - color: "#00ACFF", - }, - }, - type: "candlestick", - }, - ], - }, - layout: { - annotationdefaults: { - showarrow: false, - }, - autotypenumbers: "strict", - colorway: [ - "#ffed00", - "#ef7d00", - "#e4003a", - "#c13246", - "#822661", - "#48277c", - "#005ca9", - "#00aaff", - "#9b30d9", - "#af005f", - "#5f00af", - "#af87ff", - ], - dragmode: "pan", - font: { - family: "Fira Code", - size: 18, - }, - hoverlabel: { - align: "left", - }, - mapbox: { - style: "dark", - }, - hovermode: "x", - legend: { - bgcolor: "rgba(0, 0, 0, 0)", - x: 0.01, - xanchor: "left", - y: 0.99, - yanchor: "top", - font: { - size: 15, - }, - }, - paper_bgcolor: "#000000", - plot_bgcolor: "#000000", - xaxis: { - automargin: true, - autorange: true, - rangeslider: { - visible: false, - }, - showgrid: true, - showline: true, - tickfont: { - size: 14, - }, - zeroline: false, - tick0: 1, - title: { - standoff: 20, - }, - linecolor: "#F5EFF3", - mirror: true, - ticks: "outside", - }, - yaxis: { - anchor: "x", - automargin: true, - fixedrange: false, - zeroline: false, - showgrid: true, - showline: true, - side: "right", - tick0: 0.5, - title: { - standoff: 20, - }, - gridcolor: "#283442", - linecolor: "#F5EFF3", - mirror: true, - ticks: "outside", - }, - }, -}; - -const LIGHT_CHARTS_TEMPLATE = { - data: { - barpolar: [ - { - marker: { - line: { - color: "white", - width: 0.5, - }, - pattern: { - fillmode: "overlay", - size: 10, - solidity: 0.2, - }, - }, - type: "barpolar", - }, - ], - bar: [ - { - error_x: { - color: "#2a3f5f", - }, - error_y: { - color: "#2a3f5f", - }, - marker: { - line: { - color: "white", - width: 0.5, - }, - pattern: { - fillmode: "overlay", - size: 10, - solidity: 0.2, - }, - }, - type: "bar", - }, - ], - carpet: [ - { - aaxis: { - endlinecolor: "#2a3f5f", - gridcolor: "#C8D4E3", - linecolor: "#C8D4E3", - minorgridcolor: "#C8D4E3", - startlinecolor: "#2a3f5f", - }, - baxis: { - endlinecolor: "#2a3f5f", - gridcolor: "#C8D4E3", - linecolor: "#C8D4E3", - minorgridcolor: "#C8D4E3", - startlinecolor: "#2a3f5f", - }, - type: "carpet", - }, - ], - choropleth: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - type: "choropleth", - }, - ], - contourcarpet: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - type: "contourcarpet", - }, - ], - contour: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "contour", - }, - ], - heatmapgl: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "heatmapgl", - }, - ], - heatmap: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "heatmap", - }, - ], - histogram2dcontour: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "histogram2dcontour", - }, - ], - histogram2d: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "histogram2d", - }, - ], - histogram: [ - { - marker: { - pattern: { - fillmode: "overlay", - size: 10, - solidity: 0.2, - }, - }, - type: "histogram", - }, - ], - mesh3d: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - type: "mesh3d", - }, - ], - parcoords: [ - { - line: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "parcoords", - }, - ], - pie: [ - { - automargin: true, - type: "pie", - }, - ], - scatter3d: [ - { - line: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scatter3d", - }, - ], - scattercarpet: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scattercarpet", - }, - ], - scattergeo: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scattergeo", - }, - ], - scattergl: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scattergl", - }, - ], - scattermapbox: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scattermapbox", - }, - ], - scatterpolargl: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scatterpolargl", - }, - ], - scatterpolar: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scatterpolar", - }, - ], - scatter: [ - { - fillpattern: { - fillmode: "overlay", - size: 10, - solidity: 0.2, - }, - type: "scatter", - }, - ], - scatterternary: [ - { - marker: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - type: "scatterternary", - }, - ], - surface: [ - { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - colorscale: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - type: "surface", - }, - ], - table: [ - { - cells: { - fill: { - color: "#EBF0F8", - }, - line: { - color: "white", - }, - }, - header: { - fill: { - color: "#C8D4E3", - }, - line: { - color: "white", - }, - }, - type: "table", - }, - ], - candlestick: [ - { - decreasing: { - fillcolor: "#c80000", - line: { - color: "#990000", - }, - }, - increasing: { - fillcolor: "#009600", - line: { - color: "#007500", - }, - }, - type: "candlestick", - }, - ], - }, - layout: { - annotationdefaults: { - arrowcolor: "#2a3f5f", - arrowhead: 0, - arrowwidth: 1, - showarrow: false, - }, - autotypenumbers: "strict", - coloraxis: { - colorbar: { - outlinewidth: 0, - ticks: "", - }, - }, - colorscale: { - 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"], - ], - sequential: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - sequentialminus: [ - [0.0, "#0d0887"], - [0.1111111111111111, "#46039f"], - [0.2222222222222222, "#7201a8"], - [0.3333333333333333, "#9c179e"], - [0.4444444444444444, "#bd3786"], - [0.5555555555555556, "#d8576b"], - [0.6666666666666666, "#ed7953"], - [0.7777777777777778, "#fb9f3a"], - [0.8888888888888888, "#fdca26"], - [1.0, "#f0f921"], - ], - }, - colorway: [ - "#254495", - "#c13246", - "#48277c", - "#e4003a", - "#ef7d00", - "#822661", - "#ffed00", - "#00aaff", - "#9b30d9", - "#af005f", - "#5f00af", - "#af87ff", - ], - font: { - color: "#2a3f5f", - }, - geo: { - bgcolor: "white", - lakecolor: "white", - landcolor: "white", - showlakes: true, - showland: true, - subunitcolor: "#C8D4E3", - }, - hoverlabel: { - align: "left", - }, - hovermode: "x", - mapbox: { - style: "light", - }, - paper_bgcolor: "white", - plot_bgcolor: "white", - polar: { - angularaxis: { - gridcolor: "#EBF0F8", - linecolor: "#EBF0F8", - ticks: "", - }, - bgcolor: "white", - radialaxis: { - gridcolor: "#EBF0F8", - linecolor: "#EBF0F8", - ticks: "", - }, - }, - scene: { - xaxis: { - backgroundcolor: "white", - gridcolor: "#DFE8F3", - gridwidth: 2, - linecolor: "#EBF0F8", - showbackground: true, - ticks: "", - zerolinecolor: "#EBF0F8", - }, - yaxis: { - backgroundcolor: "white", - gridcolor: "#DFE8F3", - gridwidth: 2, - linecolor: "#EBF0F8", - showbackground: true, - ticks: "", - zerolinecolor: "#EBF0F8", - }, - zaxis: { - backgroundcolor: "white", - gridcolor: "#DFE8F3", - gridwidth: 2, - linecolor: "#EBF0F8", - showbackground: true, - ticks: "", - zerolinecolor: "#EBF0F8", - }, - }, - shapedefaults: { - line: { - color: "#2a3f5f", - }, - }, - ternary: { - aaxis: { - gridcolor: "#DFE8F3", - linecolor: "#A2B1C6", - ticks: "", - }, - baxis: { - gridcolor: "#DFE8F3", - linecolor: "#A2B1C6", - ticks: "", - }, - bgcolor: "white", - caxis: { - gridcolor: "#DFE8F3", - linecolor: "#A2B1C6", - ticks: "", - }, - }, - title: { - x: 0.05, - }, - xaxis: { - automargin: true, - ticks: "outside", - zerolinewidth: 2, - rangeslider: { - visible: false, - }, - showgrid: true, - showline: true, - tickfont: { - size: 15, - }, - title: { - standoff: 20, - }, - mirror: true, - zeroline: false, - }, - yaxis: { - automargin: true, - ticks: "outside", - tickfont: { - size: 15, - }, - zerolinewidth: 2, - fixedrange: false, - title: { - standoff: 20, - }, - nticks: 8, - showgrid: true, - showline: true, - side: "right", - mirror: true, - zeroline: false, - }, - dragmode: "pan", - legend: { - bgcolor: "rgba(0, 0, 0, 0)", - x: 1.03, - xanchor: "left", - y: 0.99, - yanchor: "top", - }, - }, -}; diff --git a/openbb_terminal/core/plots/web/main.js b/openbb_terminal/core/plots/web/main.js deleted file mode 100644 index 352d9c264ac8..000000000000 --- a/openbb_terminal/core/plots/web/main.js +++ /dev/null @@ -1,646 +0,0 @@ -let globals = { - dark_mode: false, - modebarHidden: false, - volume: {}, - added_traces: [], - old_nticks: {}, - csv_yaxis_id: null, - cmd_src_idx: null, -}; - -function loadingOverlay(message) { - const loading = document.getElementById("loading"); - const loading_text = document.getElementById("loading_text"); - - loading_text.innerHTML = message; - loading.classList.add("show"); - - let is_loaded = setInterval(function () { - if (loading.classList.contains("show")) { - clearInterval(is_loaded); - } - }, 10); -} - -const non_blocking = (func, delay) => { - let timeout; - return function () { - const context = this; - const args = arguments; - clearTimeout(timeout); - timeout = setTimeout(() => func.apply(context, args), delay); - }; -}; - -function OpenBBMain( - plotly_figure, - chartdiv, - csvdiv, - textdiv, - titlediv, - downloaddiv -) { - // Main function that plots the graphs and initializes the bar menus - globals.CHART_DIV = chartdiv; - globals.TITLE_DIV = titlediv; - globals.TEXT_DIV = textdiv; - globals.CSV_DIV = csvdiv; - globals.dark_mode = plotly_figure.theme === "dark"; - globals.DOWNLOAD_DIV = downloaddiv; - console.log("main.js loaded"); - console.log("plotly_figure", plotly_figure); - let graphs = plotly_figure; - - const loading = document.getElementById("loading"); - - // We add the event listeners for csv file/type changes - globals.CSV_DIV.querySelector("#csv_file").addEventListener( - "change", - function () { - console.log("file changed"); - loadingOverlay("Loading CSV"); - setTimeout(function () { - non_blocking(function () { - checkFile(globals.CSV_DIV); - }, 2)(); - setTimeout(function () { - loading.classList.remove("show"); - }, 200); - }, 1000); - } - ); - globals.CSV_DIV.querySelector("#csv_trace_type").addEventListener( - "change", - function () { - console.log("type changed"); - checkFile(globals.CSV_DIV, true); - } - ); - - globals.filename = openbbFilename(graphs); - - // Sets the config with the custom buttons - CONFIG = { - plotGlPixelRatio: 1, - scrollZoom: true, - responsive: true, - displaylogo: false, - displayModeBar: true, - modeBarButtonsToRemove: ["lasso2d", "select2d", "downloadImage"], - modeBarButtons: [ - [ - { - name: "Download CSV (Ctrl+Shift+S)", - icon: ICONS.downloadCsv, - click: async function (gd) { - await downloadCsvButton(gd); - }, - }, - { - name: "Download Chart as Image (Ctrl+S)", - icon: ICONS.downloadImage, - click: async function () { - await downloadImageButton(); - }, - }, - // { - // name: "Upload Image (Ctrl+U)", - // icon: Plotly.Icons.uploadImage, - // click: function (gd) { - // downloadImage(); - // }, - // }, - ], - [ - { - name: "Edit Color (Ctrl+E)", - icon: ICONS.changeColor, - click: function () { - // We need to check if the button is active or not - let title = "Edit Color (Ctrl+E)"; - let button = globals.barButtons[title]; - let active = true; - if (button.style.border == "transparent") { - active = false; - } - // We call the function that changes the border color - button_pressed(title, active); - changeColor(); - }, - }, - "drawline", - "drawopenpath", - "drawcircle", - "drawrect", - "eraseshape", - ], - [ - { - name: "Overlay chart from CSV (Ctrl+O)", - icon: ICONS.plotCsv, - click: function () { - // We make sure to close any other popup that might be open - // before opening the CSV popup - closePopup(); - openPopup("popup_csv"); - }, - }, - { - name: "Add Text (Ctrl+T)", - icon: ICONS.addText, - click: function () { - openPopup("popup_text"); - }, - }, - { - name: "Change Titles (Ctrl+Shift+T)", - icon: ICONS.changeTitle, - click: function () { - openPopup("popup_title"); - }, - }, - { - name: "Change Theme", - icon: ICONS.sunIcon, - click: function () { - changeTheme(); - }, - }, - ], - ["hoverClosestCartesian", "hoverCompareCartesian", "toggleSpikelines"], - [ - { - name: "Auto Scale (Ctrl+Shift+A)", - icon: Plotly.Icons.autoscale, - click: function () { - autoscaleButton(); - }, - }, - "zoomIn2d", - "zoomOut2d", - "autoScale2d", - "zoom2d", - "pan2d", - ], - ], - }; - graphs.layout.title = ""; - - // We make sure to fill in any missing layout properties with default values - if (!("font" in graphs.layout)) { - graphs.layout["font"] = { - family: "Fira Code, monospace, Arial Black", - size: 18, - }; - } - graphs.layout.annotations = !graphs.layout.annotations - ? [] - : graphs.layout.annotations; - - if (!("margin" in graphs.layout)) { - graphs.layout["margin"] = { - l: 0, - r: 0, - b: 0, - t: 0, - pad: 2, - }; - } - - // RIP: Juan hated it so had to remove it - // graphs.layout.xaxis.tickangle = -20; - - graphs.layout.autosize = true; - // We set the height and width to undefined, so that plotly.js can - // automatically resize the chart to fit the PyWry window - delete graphs.layout.height; - delete graphs.layout.width; - - if (graphs.layout.annotations != undefined) { - graphs.layout.annotations.forEach(function (annotation) { - // We make sure to fill in any missing annotation properties with default values - // We also make sure to set the font size to a reasonable value based on the - // width of the client window - if (!("font" in annotation) || !("size" in annotation.font)) { - annotation["font"] = { - family: "Fira Code, monospace, Arial Black", - size: 16, - }; - } - - if (annotation.text != undefined) { - if (annotation.text[0] == "/") { - globals.cmd_src_idx = graphs.layout.annotations.indexOf(annotation); - } - } - annotation.font.size = Math.min( - globals.CHART_DIV.clientWidth / 50, - annotation.font.size - ); - }); - } - - // We add spaces to all trace names, due to Fira Code font width issues - // to make sure that the legend is not cut off - graphs.data.forEach(function (trace) { - if (trace.name != undefined) { - let name_length = trace.name.length; - trace.name = trace.name + " "; - trace.hoverlabel = { - namelength: name_length, - }; - } - }); - - // Set the default dragmode to pan and set the font size to a reasonable value - graphs.layout.dragmode = "pan"; - graphs.layout.font.size = Math.min( - globals.CHART_DIV.clientWidth / 50, - graphs.layout.font.size - ); - - // We check for the dark mode - if (graphs.layout.template.layout.mapbox.style == "dark") { - document.body.style.backgroundColor = "#000000"; - document.getElementById("openbb_footer").style.color = "#000000"; - graphs.layout.template.layout.paper_bgcolor = "#000000"; - graphs.layout.template.layout.plot_bgcolor = "#000000"; - } else { - document.body.style.backgroundColor = "#FFFFFF"; - document.getElementById("openbb_footer").style.color = "#FFFFFF"; - } - - // We set the plot config and plot the chart - Plotly.setPlotConfig(CONFIG); - Plotly.react(globals.CHART_DIV, graphs, { responsive: true }); - - let AXES = Object.keys(graphs.layout).filter( - (x) => x.startsWith("xaxis") || x.startsWith("yaxis") - ); - - // We set all the axes automargin to false - if (AXES.length > 0) { - AXES.forEach((axis) => { - let margin = axis.startsWith("y") ? "l+r" : "t+b"; - graphs.layout[axis].automargin = margin; - }); - Plotly.react(globals.CHART_DIV, graphs, { responsive: true }); - } - - // Create global variables to for use later - const modebar = document.getElementsByClassName("modebar-container")[0]; - const modebar_buttons = modebar.getElementsByClassName("modebar-btn"); - globals.barButtons = {}; - - const captureButtons = [ - "Download CSV", - "Download Chart as Image", - "Overlay chart from CSV", - "Add Text", - "Change Titles", - "Auto Scale (Ctrl+Shift+A)", - "Reset Axes", - ]; - - for (let i = 0; i < modebar_buttons.length; i++) { - // We add the buttons to the global variable for later use - // and set the border to transparent so we can change the - // color of the buttons when they are pressed - let button = modebar_buttons[i]; - if (captureButtons.includes(button.getAttribute("data-title"))) { - button.classList.add("ph-capture"); - } - button.style.border = "transparent"; - globals.barButtons[button.getAttribute("data-title")] = button; - } - - // We change the Plotly default Autoscale button icon and title to Reset Axes - globals.barButtons["Reset Axes"] = globals.barButtons["Autoscale"]; - globals.barButtons["Autoscale"] - .getElementsByTagName("path")[0] - .setAttribute("d", Plotly.Icons.home.path); - globals.barButtons["Autoscale"].setAttribute("data-title", "Reset Axes"); - - if (globals.CHART_DIV.layout.yaxis.type != undefined) { - if (globals.CHART_DIV.layout.yaxis.type == "log" && !globals.logYaxis) { - console.log("yaxis.type changed to log"); - globals.logYaxis = true; - - // We update the yaxis exponent format to SI, - // set the tickformat to '.0s' and the exponentbase to 100 - let layout_update = { - "yaxis.exponentformat": "SI", - "yaxis.tickformat": ".0s", - "yaxis.exponentbase": 100, - }; - Plotly.update(globals.CHART_DIV, layout_update); - } - if (globals.CHART_DIV.layout.yaxis.type == "linear" && globals.logYaxis) { - console.log("yaxis.type changed to linear"); - globals.logYaxis = false; - - // We update the yaxis exponent format to none, - // set the tickformat to null and the exponentbase to 10 - let layout_update = { - "yaxis.exponentformat": "none", - "yaxis.tickformat": null, - "yaxis.exponentbase": 10, - }; - Plotly.update(globals.CHART_DIV, layout_update); - } - } - - if (window.plotly_figure.layout.template.layout.mapbox.style === "light") { - for (const el of document.styleSheets[0].cssRules) { - if (el.selectorText === ".modebar-group") { - el.style.backgroundColor = "#FFFFFF"; - } - } - } - - function hideModebar() { - if (globals.modebarHidden) { - modebar.style.display = "flex"; - globals.modebarHidden = false; - } else { - modebar.style.display = "none"; - globals.modebarHidden = true; - } - } - - function autoscaleButton() { - // We need to check if the button is active or not - let title = "Auto Scale (Ctrl+Shift+A)"; - let button = globals.barButtons[title]; - let active = true; - if (button.style.border == "transparent") { - active = false; - globals.CHART_DIV.on( - "plotly_relayout", - non_blocking(async function (eventdata) { - if (eventdata["xaxis.range[0]"] == undefined) { - return; - } - await autoScaling(eventdata, globals.CHART_DIV); - }, 100) - ); - } else { - // If the button isn't active, we remove the listener so - // the graphs don't autoscale anymore - globals.CHART_DIV.removeAllListeners("plotly_relayout"); - } - button_pressed(title, active); - } - - async function downloadImageButton() { - let filename = globals.filename; - let ext = "png"; - let writable; - if (window.showSaveFilePicker) { - const handle = await showSaveFilePicker({ - suggestedName: `${filename}.${ext}`, - types: [ - { - description: "PNG Image", - accept: { - "image/png": [".png"], - }, - }, - { - description: "JPEG Image", - accept: { - "image/jpeg": [".jpeg"], - }, - }, - { - description: "SVG Image", - accept: { - "image/svg+xml": [".svg"], - }, - }, - ], - excludeAcceptAllOption: true, - }); - writable = await handle.createWritable(); - filename = handle.name; - ext = handle.name.split(".").pop(); - } - - loadingOverlay(`Saving ${ext.toUpperCase()}`); - hideModebar(); - non_blocking(async function () { - await downloadImage(filename, ext, writable); - setTimeout(function () { - setTimeout(function () { - loading.classList.remove("show"); - hideModebar(); - }, 50); - }, 25); - }, 2)(); - } - - async function downloadCsvButton(gd) { - let filename = globals.filename; - let writable; - - if (window.showSaveFilePicker) { - const handle = await showSaveFilePicker({ - suggestedName: `${filename}.csv`, - types: [ - { - description: "CSV File", - accept: { - "image/csv": [".csv"], - }, - }, - ], - excludeAcceptAllOption: true, - }); - writable = await handle.createWritable(); - filename = handle.name; - } - - loadingOverlay("Saving CSV"); - setTimeout(async function () { - await downloadData(gd, filename, writable); - }, 500); - setTimeout(function () { - loading.classList.remove("show"); - }, 1000); - } - - // We setup keyboard shortcuts custom to OpenBB - window.document.addEventListener("keydown", function (e) { - if (e.key.toLowerCase() == "h" && (e.ctrlKey || e.metaKey)) { - e.preventDefault(); - hideModebar(); - } - - if (e.ctrlKey) { - if (e.shiftKey && e.key.toLowerCase() == "t") { - openPopup("popup_title"); - } else if (e.key.toLowerCase() == "t") { - openPopup("popup_text"); - } else if (e.key.toLowerCase() == "e") { - changeColor(); - } else if (e.shiftKey && e.key.toLowerCase() == "s") { - e.preventDefault(); - downloadCsvButton(globals.CHART_DIV); - } else if (e.key.toLowerCase() == "s") { - e.preventDefault(); - downloadImageButton(); - } else if (e.key.toLowerCase() == "o") { - e.preventDefault(); - openPopup("popup_csv"); - } else if (e.shiftKey && e.key.toLowerCase() == "a") { - e.preventDefault(); - autoscaleButton(); - } - } else if (e.key == "Escape") { - closePopup(); - } - }); - - // send a relayout event to trigger the initial zoom/bars-resize - // check if the xaxis.range is defined - if ( - graphs.layout.xaxis != undefined && - graphs.layout.xaxis.range != undefined - ) { - Plotly.relayout(globals.CHART_DIV, { - "xaxis.range[0]": graphs.layout.xaxis.range[0], - "xaxis.range[1]": graphs.layout.xaxis.range[1], - }); - } - - // We find all xaxis that have showticklabels set to true - let XAXIS = Object.keys(globals.CHART_DIV.layout) - .filter((x) => x.startsWith("xaxis")) - .filter((x) => globals.CHART_DIV.layout[x].showticklabels); - - let TRACES = globals.CHART_DIV.data.filter((trace) => - trace?.name?.startsWith("Volume") - ); - - window.addEventListener("resize", function () { - // We check to see if the window.innerWidth is smaller than 900px - let layout_update = {}; - let width = window.innerWidth; - let height = window.innerHeight; - let tick_size = - height > 420 && width < 920 ? 9 : height > 420 && width < 500 ? 10 : 8; - - if (width < 920) { - // We hide the modebar and set the number of ticks to 5 - TRACES.forEach((trace) => { - if (trace.type == "bar") { - trace.opacity = 1; - trace.marker.line.width = 0.09; - if (globals.volume.yaxis == undefined) { - globals.volume.yaxis = "yaxis" + trace.yaxis.replace("y", ""); - layout_update[globals.volume.yaxis + ".tickfont.size"] = tick_size; - - globals.volume.tickfont = - globals.CHART_DIV.layout[globals.volume.yaxis].tickfont; - - globals.CHART_DIV.layout.margin.l -= 40; - } - } - }); - - XAXIS.forEach((x) => { - if (globals.old_nticks?.[x] == undefined) { - layout_update[x + ".nticks"] = 6; - globals.old_nticks[x] = globals.CHART_DIV.layout[x].nticks || 10; - } - }); - - modebar.style.display = "none"; - globals.modebarHidden = true; - } else if (globals.modebarHidden) { - // We show the modebar - modebar.style.display = "flex"; - globals.modebarHidden = false; - - if (globals.old_nticks != undefined) { - XAXIS.forEach((x) => { - if (globals.old_nticks[x] != undefined) { - layout_update[x + ".nticks"] = globals.old_nticks[x]; - globals.old_nticks[x] = undefined; - } - }); - } - - if (globals.volume.yaxis != undefined) { - TRACES.forEach((trace) => { - if (trace.type == "bar") { - trace.opacity = 0.5; - trace.marker.line.width = 0.2; - layout_update[globals.volume.yaxis + ".tickfont.size"] = - globals.volume.tickfont.size + 3; - globals.CHART_DIV.layout.margin.l += 40; - globals.volume.yaxis = undefined; - } - }); - } - } - - if (Object.keys(layout_update).length > 0) { - Plotly.relayout(globals.CHART_DIV, layout_update); - } - }); - - // We check to see if window.save_png is defined and true - if (window.save_image != undefined && window.export_image) { - // We get the extension of the file and check if it is valid - let filename = window.export_image.split("/").pop(); - const extension = filename.split(".").pop().replace("jpg", "jpeg"); - - if (["jpeg", "png", "svg", "pdf"].includes(extension)) { - hideModebar(); - non_blocking(function () { - downloadImage(filename.split(".")[0], extension); - }, 2)(); - } - } - function changeTheme() { - globals.dark_mode = !globals.dark_mode; - document.body.style.backgroundColor = globals.dark_mode ? "#000" : "#fff"; - globals.CHART_DIV.layout.font.color = globals.dark_mode ? "#fff" : "#000"; - - const changeIcon = globals.dark_mode ? ICONS.sunIcon : ICONS.moonIcon; - - globals.barButtons["Change Theme"] - .getElementsByTagName("path")[0] - .setAttribute("d", changeIcon.path); - - globals.barButtons["Change Theme"] - .getElementsByTagName("svg")[0] - .setAttribute("viewBox", changeIcon.viewBox); - - const volumeColors = { - "#e4003a": "#c80000", - "#00ACFF": "#009600", - "#009600": "#00ACFF", - "#c80000": "#e4003a", - }; - - TRACES.forEach((trace) => { - if (trace.type == "bar") { - trace.marker.color.forEach((color, i) => { - trace.marker.color[i] = volumeColors[color] || color; - }); - } - }); - - Plotly.update( - globals.CHART_DIV, - {}, - { - template: globals.dark_mode - ? DARK_CHARTS_TEMPLATE - : LIGHT_CHARTS_TEMPLATE, - } - ); - } -} diff --git a/openbb_terminal/core/plots/web/main_table.js b/openbb_terminal/core/plots/web/main_table.js deleted file mode 100644 index f4b49958bb46..000000000000 --- a/openbb_terminal/core/plots/web/main_table.js +++ /dev/null @@ -1,119 +0,0 @@ -function TableProcessor(data) { - const parsedData = JSON.parse(data); - console.log(parsedData); - const processedData = processData(parsedData); - console.log(processedData); - const body = document.getElementsByTagName("body")[0]; - const table = new Tabulator("#example-table", { - height: body.clientHeight - 54, - layout: "fitColumns", - data: processedData.data, - columns: processedData.columns, - }); - - const div = document.createElement("div"); - div.innerHTML = ` -
- - - - - - - -
- - `; - body.appendChild(div); - const filterField = document.getElementById("filter-field"); - const filterType = document.getElementById("filter-type"); - const filterValue = document.getElementById("filter-value"); - const filterClear = document.getElementById("filter-clear"); - - filterField.addEventListener("change", function (e) { - table.setFilter(filterField.value, filterType.value, filterValue.value); - }); - - filterType.addEventListener("change", function (e) { - table.setFilter(filterField.value, filterType.value, filterValue.value); - }); - - filterValue.addEventListener("keyup", function (e) { - table.setFilter(filterField.value, filterType.value, filterValue.value); - }); - - filterClear.addEventListener("click", function (e) { - table.clearFilter(); - }); -} - -function processData(data) { - /* - data is coming as { - columns: ["Name", "Age"], - data: ["John", 30] - } - */ - /* - final data should be { - columns: [ - { - title: "Name", - field: "name", - sorter: "string", - }, - { - title: "Age", - field: "age", - sorter: "number", - } - ], - data: { - name: "John", - age: "30", - } - } - */ - const columns = data.columns.map((column) => { - return { - title: column, - field: column, - sorter: column.includes("Change"), - /*formatter: (cell) => { - if (column.startsWith("Change")) { - if (cell.getValue() > 0) { - return `${cell.getValue()}`; - } else { - return `${cell.getValue()}`; - } - } else { - return cell.getValue(); - } - },*/ - }; - }); - const finalData = data.data.map((row) => { - const obj = {}; - row.forEach((item, index) => { - obj[data.columns[index]] = item; - }); - return obj; - }); - return { - columns, - data: finalData, - }; -} diff --git a/openbb_terminal/core/plots/web/popups.js b/openbb_terminal/core/plots/web/popups.js deleted file mode 100644 index 3e9c5e5cef84..000000000000 --- a/openbb_terminal/core/plots/web/popups.js +++ /dev/null @@ -1,738 +0,0 @@ -function get_popup(data = null, popup_id = null) { - let popup = null; - popup_id = popup_id.replace("popup_", ""); - const style = - "padding: 5px 2px 2px 5px !important; margin: 2px 0 !important;"; - - if (popup_id == "title") { - let title = globals.title; - data = globals.CHART_DIV.layout; - let yaxes = Object.keys(data).filter((k) => k.startsWith("yaxis")); - let xaxes = Object.keys(data).filter((k) => k.startsWith("xaxis")); - - globals.TITLE_DIV.innerHTML = ` -
-
- - -
-
-
-
- -
- - -
- `; - - // if there are multiple titles we create an input for each - let yaxis_div = ""; - for (let i = 0; i < yaxes.length; i++) { - if (data[yaxes[i]]?.title?.text != undefined) { - let title = data[yaxes[i]].title.text; - yaxis_div += ` -
- - -
- `; - } - } - if (yaxis_div != "") { - globals.TITLE_DIV.querySelector("#yaxis_div").innerHTML = yaxis_div; - } - - let xaxis_div = ""; - for (let i = 0; i < xaxes.length; i++) { - if (data[xaxes[i]]?.title?.text != undefined) { - let title = data[xaxes[i]].title.text; - xaxis_div += ` -
- - -
- `; - } - } - if (xaxis_div != "") { - globals.TITLE_DIV.querySelector("#xaxis_div").innerHTML = xaxis_div; - } - - // when opening the popup, we make sure to focus on the title input - globals.TITLE_DIV.style.display = "inline-block"; - globals.TITLE_DIV.querySelector("#title_text").focus(); - popup = globals.TITLE_DIV; - } else if (popup_id == "text") { - let has_annotation = data == undefined ? false : true; - if (data == undefined) { - data = { - text: "", - font: { - color: "#0088CC", - size: 18, - }, - bordercolor: "#822661", - }; - } - - // we replace
with \n so that the textarea can display the text properly - data.text = data.text.replace(/
/g, "\n"); - - let yanchor = - globals.TEXT_DIV.querySelector("#addtext_above") == null - ? "above" - : globals.TEXT_DIV.querySelector("#addtext_above").checked - ? "above" - : "below"; - - globals.TEXT_DIV.innerHTML = ` -
-
-
-
-
-
- - -
-
- - -
-

- -
-
- - -
-
- - -
-

- `; - - if (has_annotation) { - globals.TEXT_DIV.innerHTML += ` -
- - - - -
- `; - } else { - globals.TEXT_DIV.innerHTML += ` -
- - -
- `; - - if (globals.TEXT_DIV.querySelector("#addtext_annotation") != null) { - globals.TEXT_DIV.querySelector("#addtext_annotation").remove(); - } - } - - // when opening the popup, we make sure to focus on the textarea - globals.TEXT_DIV.style.display = "inline-block"; - globals.TEXT_DIV.querySelector("#addtext_textarea").focus(); - popup = globals.TEXT_DIV; - } else if (popup_id == "csv") { - globals.CSV_DIV.style.display = "inline-block"; - popup = globals.CSV_DIV; - console.log("csv"); - } else if (popup_id == "upload") { - globals.TEXT_DIV.style.display = "inline-block"; - globals.TEXT_DIV.innerHTML = ` -
-

Media preview (you can share it on twitter):

- ${data.url} -
- - Share - -
-
- `; - popup = globals.TEXT_DIV; - console.log("upload"); - } else if (popup_id == "download") { - popup = globals.DOWNLOAD_DIV; - - popup.querySelector("#download_path").innerHTML = ` -
- `; - - openfile_button = popup.querySelector("#openfile_button"); - openfile_button.onclick = function () { - window.ipc.postMessage(`#OPEN:${data}`); - }; - - openfolder_button = popup.querySelector("#openfolder_button"); - openfolder_button.onclick = function () { - folder_path = data.split("\\").slice(0, -1).join("\\"); - window.ipc.postMessage(`#OPEN:${folder_path}`); - }; - - globals.DOWNLOAD_DIV.style.display = "inline-block"; - } - - let popup_divs = [ - globals.TITLE_DIV, - globals.TEXT_DIV, - globals.CSV_DIV, - globals.DOWNLOAD_DIV, - ]; - popup_divs.forEach(function (div) { - if (div.id != popup.id) { - div.style.display = "none"; - } - }); - - return popup; -} - -function get_popup_data(popup_id = null) { - // popup_id is either 'title', 'text', or 'csv' (for now) - // and is used to determine which popup to get data from - let data = null; - - if (popup_id == "title") { - data = { title: globals.TITLE_DIV.querySelector("#title_text").value }; - - let xaxis_div = globals.TITLE_DIV.querySelector("#xaxis_div"); - let yaxis_div = globals.TITLE_DIV.querySelector("#yaxis_div"); - console.log("xaxis_div: ", xaxis_div, "yaxis_div: ", yaxis_div); - - if (xaxis_div != null) { - // We query all inputs that start with 'title_xaxis' - let xaxis_inputs = xaxis_div.querySelectorAll( - "input[id^=title_xaxis], select[id^=title_xaxis]" - ); - xaxis_inputs.forEach(function (input) { - let xaxis_id = input.id.replace("title_", ""); - data[xaxis_id] = input.value; - }); - } - - if (yaxis_div != null) { - // We query all inputs that start with 'title_yaxis' - let yaxis_inputs = yaxis_div.querySelectorAll( - "input[id^=title_yaxis], select[id^=title_yaxis]" - ); - yaxis_inputs.forEach(function (input) { - let yaxis_id = input.id.replace("title_", ""); - data[yaxis_id] = input.value; - }); - } - console.log("Title data:", data); - } else if (popup_id == "text") { - data = { - text: globals.TEXT_DIV.querySelector("#addtext_textarea").value, - color: globals.TEXT_DIV.querySelector("#addtext_color").value, - size: globals.TEXT_DIV.querySelector("#addtext_size").value, - yanchor: globals.TEXT_DIV.querySelector("#addtext_above").checked - ? "above" - : "below", - bordercolor: globals.TEXT_DIV.querySelector("#addtext_border").value, - }; - if (globals.TEXT_DIV.querySelector("#addtext_annotation") != null) { - data.annotation = JSON.parse( - globals.TEXT_DIV.querySelector("#addtext_annotation").value - ); - } - - // we replace \n with
so that line breaks are displayed properly on the graph - data.text = data.text.replace(/\n/g, "
"); - console.log("Text data:", data); - } else if (popup_id == "csv") { - let trace_type = globals.CSV_DIV.querySelector("#csv_trace_type").value; - if (trace_type == "candlestick") { - data = { - x: globals.CSV_DIV.querySelector("#csv_x").value, - open: globals.CSV_DIV.querySelector("#csv_open").value, - high: globals.CSV_DIV.querySelector("#csv_high").value, - low: globals.CSV_DIV.querySelector("#csv_low").value, - close: globals.CSV_DIV.querySelector("#csv_close").value, - increasing: globals.CSV_DIV.querySelector("#csv_increasing").value, - decreasing: globals.CSV_DIV.querySelector("#csv_decreasing").value, - same_yaxis: globals.CSV_DIV.querySelector("#csv_same_yaxis").checked - ? true - : false, - }; - } else if (trace_type == "scatter") { - data = { - x: globals.CSV_DIV.querySelector("#csv_x").value, - y: globals.CSV_DIV.querySelector("#csv_y").value, - color: globals.CSV_DIV.querySelector("#csv_color").value, - percent_change: globals.CSV_DIV.querySelector("#csv_percent_change") - .checked - ? true - : false, - same_yaxis: globals.CSV_DIV.querySelector("#csv_same_yaxis").checked - ? true - : false, - }; - } else if (trace_type == "bar") { - let orientation = globals.CSV_DIV.querySelector("#csv_bar_horizontal") - .checked - ? "h" - : "v"; - data = { - x: globals.CSV_DIV.querySelector("#csv_x").value, - y: globals.CSV_DIV.querySelector("#csv_y").value, - color: globals.CSV_DIV.querySelector("#csv_color").value, - same_yaxis: globals.CSV_DIV.querySelector("#csv_same_yaxis").checked - ? true - : false, - orientation: orientation, - }; - } - data.trace_type = trace_type; - data.name = globals.CSV_DIV.querySelector("#csv_name").value; - console.log("CSV data:", data); - data.file = globals.CSV_DIV.querySelector("#csv_file"); - } - return data; -} - -const layout_defaults = { - overlaying: "y", - side: "left", - tickfont: { size: 12 }, - tickpadding: 5, - showgrid: false, - showline: false, - showticklabels: true, - showlegend: true, - zeroline: false, - anchor: "x", - type: "linear", - autorange: true, -}; - -function on_submit(popup_id, on_annotation = null) { - // popup_id is either 'title', 'text', or 'csv' (for now) - // and is used to determine which popup to get data from - let popup_data = get_popup_data(popup_id); - let gd = globals.CHART_DIV; - Plotly.update(gd, {}, { hovermode: "closest" }); - - if (popup_id == "text") { - if (!popup_data.text == "") { - if ("annotation" in popup_data) { - let current_text = popup_data.annotation.text; - let data = { - x: popup_data.annotation.x, - y: popup_data.annotation.y, - yref: popup_data.annotation.yref, - }; - plot_text(data, popup_data, current_text); - return; - } - - gd.on("plotly_clickannotation", function (eventData) { - console.log("plotly_clickannotation", eventData); - let annotation = eventData.annotation; - openPopup("popup_text"); - get_popup(annotation, (popup_id = "text")); - - if (on_annotation != null) { - let data = { - x: popup_data.annotation.x, - y: popup_data.annotation.y, - yref: popup_data.annotation.yref, - }; - plot_text(data, popup_data, popup_data.annotation.text); - } - Plotly.update(gd, {}, { hovermode: "x" }); - }); - - let clickHandler = function (eventData) { - console.log("plotly_click", eventData); - let x = eventData.points[0].x; - let yaxis = eventData.points[0].fullData.yaxis; - let y = 0; - - // We need to check if the trace is a candlestick or not - // this is because the y value is stored in the high or low - if (eventData.points[0].y != undefined) { - y = eventData.points[0].y; - } else if (eventData.points[0].low != undefined) { - if (popup_data.yanchor == "below") { - y = eventData.points[0].low; - } else { - y = eventData.points[0].high; - } - } - let data = { - x: x, - y: y, - yref: yaxis, - }; - plot_text(data, popup_data); - Plotly.update(gd, {}, { hovermode: "x" }); - }; - - Plotly.update(gd, {}, { dragmode: "select" }); - gd.on("plotly_click", clickHandler); - } else { - let textarea = globals.TEXT_DIV.querySelector("#addtext_textarea"); - document.getElementById("popup_textarea_warning").style.display = "block"; - textarea.style.border = "1px solid red"; - textarea.focus(); - - globals.TEXT_DIV.style.display = "inline-block"; - return; - } - } else if (popup_id == "title") { - document.getElementById("title").innerHTML = popup_data.title; - globals.title = popup_data.title; - - let to_update = {}; - - Object.keys(popup_data).forEach(function (key) { - if (key != "title") { - to_update[key + ".title"] = popup_data[key]; - } - }); - - console.log(to_update); - - Plotly.update(gd, {}, to_update); - } else if (popup_id == "csv") { - console.log("got popup file"); - let popup_file = popup_data.file; - - if (popup_file.files.length > 0) { - console.log("file selected"); - - let file = popup_file.files[0]; - let popup_file_reader = new FileReader(); - popup_file_reader.onload = function (e) { - let lines = e.target.result - .split("\n") - .map((x) => x.replace(/\r/g, "")); - let data = []; - let headers = lines[0].split(","); - let trace = {}; - let new_yaxis = false; - - for (let i = 1; i < lines.length; i++) { - let obj = {}; - let currentline = lines[i].split(","); - for (let j = 0; j < headers.length; j++) { - obj[headers[j]] = currentline[j]; - } - data.push(obj); - } - - // We get main plotly trace to get the x/y axis - let main_trace = gd.data[0]; - - // We check how many yaxis have ticklabels on the left - let left_yaxis_ticks = Object.keys(gd.layout) - .filter((k) => k.startsWith("yaxis")) - .map((k) => gd.layout[k]) - .filter( - (yaxis) => - yaxis.side == "left" && - (yaxis.overlaying == "y" || - (yaxis.fixedrange != undefined && yaxis.fixedrange == true)) - ).length; - - // Multiply by 5 to get the xshift for cmd source text - let add_xshift = Math.min(left_yaxis_ticks * 5, 30); - - // We set showlegend's to true - main_trace.showlegend = true; - gd.layout.showlegend = true; - - // Just in case xaxis/yaxis is not defined - if (main_trace.xaxis == undefined) { - main_trace.xaxis = "x"; - } - if (main_trace.yaxis == undefined) { - main_trace.yaxis = "y"; - } - - // Set the yaxis id - let yaxis_id = main_trace.yaxis; - let yaxis; - - // If we want to plot on a secondary yaxis - // we get the number of yaxis and add 1 to it - if (popup_data.same_yaxis == false) { - let yaxes = Object.keys(gd.layout) - .filter((k) => k.startsWith("yaxis")) - .map((k) => gd.layout[k]); - - yaxis = `y${yaxes.length + 1}`; - yaxis_id = `yaxis${yaxes.length + 1}`; - console.log(`yaxis: ${yaxis} ${yaxis_id}`); - - // If percent change is true we set the yaxis id - // in the globals so we can use it later - if ( - globals.csv_yaxis_id == null && - popup_data.percent_change == true - ) { - globals.csv_yaxis_id = yaxis_id; - globals.csv_yaxis = yaxis; - } - } else { - // Plot on the same yaxis - yaxis = main_trace.yaxis.replace("yaxis", "y"); - } - - // We get the yaxis ticksuffix - let ticksuffix = left_yaxis_ticks > 0 ? " " : ""; - if (globals.percent_yaxis_added || globals.added_traces.length > 0) { - ticksuffix = " ".repeat(left_yaxis_ticks); - } - - // Bar trace - if (popup_data.trace_type == "bar") { - trace = { - x: data.map(function (row) { - return row[popup_data.x]; - }), - y: data.map(function (row) { - return row[popup_data.y]; - }), - type: popup_data.trace_type, - name: popup_data.name, - marker: { color: popup_data.color, opacity: 0.7 }, - orientation: popup_data.orientation, - showlegend: true, - yaxis: yaxis, - }; - } - - // Candlestick trace - if (popup_data.trace_type == "candlestick") { - trace = { - x: data.map(function (row) { - return row[popup_data.x]; - }), - open: data.map(function (row) { - return row[popup_data.open]; - }), - high: data.map(function (row) { - return row[popup_data.high]; - }), - low: data.map(function (row) { - return row[popup_data.low]; - }), - close: data.map(function (row) { - return row[popup_data.close]; - }), - type: popup_data.trace_type, - name: popup_data.name, - increasing: { - line: { color: popup_data.increasing }, - fillcolor: popup_data.increasing, - }, - decreasing: { - line: { color: popup_data.decreasing }, - fillcolor: popup_data.decreasing, - }, - showlegend: true, - yaxis: yaxis, - }; - } - - // Scatter trace - if (popup_data.trace_type == "scatter") { - // We get the first non null value - orginal_data = data; - let non_null = data.findIndex( - (x) => x[popup_data.y] != null && x[popup_data.y] != 0 - ); - console.log(`non_null: ${non_null} ${data[non_null][popup_data.y]}`); - - trace = { - x: data.map(function (row) { - return row[popup_data.x]; - }), - y: data.map(function (row) { - if (popup_data.percent_change) { - return ( - (row[popup_data.y] - data[non_null][popup_data.y]) / - data[non_null][popup_data.y] - ); - } else { - return row[popup_data.y]; - } - }), - type: popup_data.trace_type, - mode: "lines", - name: popup_data.name, - line: { color: popup_data.color }, - customdata: data.map(function (row) { - return row[popup_data.y]; - }), - hovertemplate: "%{customdata}", - showlegend: true, - connectgaps: true, - xaxis: main_trace.xaxis, - yaxis: popup_data.percent_change ? globals.csv_yaxis : yaxis, - }; - - // For the percent change we add a new yaxis - // if it doesn't exist - if ( - !globals.percent_yaxis_added && - popup_data.percent_change == true && - popup_data.same_yaxis == false - ) { - gd.layout[yaxis_id] = { - ...layout_defaults, - title: { - text: "% Change", - font: { - size: 14, - }, - standoff: 0, - }, - ticksuffix: ticksuffix, - tickformat: ".0%", - }; - new_yaxis = true; - globals.percent_yaxis_added = true; - if (globals.cmd_src_idx != null) { - let xshift = gd.layout.annotations[globals.cmd_src_idx].xshift; - xshift -= left_yaxis_ticks > 0 ? 50 + add_xshift : 35; - - // just in case we have a lot of yaxis - xshift += xshift < -320 ? 10 + 2 * left_yaxis_ticks : 0; - - gd.layout.annotations[globals.cmd_src_idx].xshift = xshift; - } - gd.layout.margin.l += left_yaxis_ticks > 0 ? 50 + add_xshift : 45; - } - } - - // New yaxis and not percent change - if (!popup_data.percent_change && popup_data.same_yaxis == false) { - gd.layout[yaxis_id] = { - ...layout_defaults, - title: { - text: popup_data.name, - font: { - size: 14, - }, - standoff: 0, - }, - ticksuffix: ticksuffix, - layer: "below traces", - }; - new_yaxis = true; - if (globals.cmd_src_idx != null) { - let xshift = gd.layout.annotations[globals.cmd_src_idx].xshift; - xshift -= left_yaxis_ticks > 0 ? 40 + add_xshift : 40; - - // just in case we have a lot of yaxis - xshift += xshift < -320 ? 10 + 2 * left_yaxis_ticks : 0; - - gd.layout.annotations[globals.cmd_src_idx].xshift = xshift; - } - gd.layout.margin.l += left_yaxis_ticks > 0 ? 50 : 45; - } - console.log("trace: ", trace); - - globals.added_traces.push(trace.name); - - Plotly.addTraces(gd, trace); - Plotly.react(gd, gd.data, gd.layout); - - if (new_yaxis) { - gd.layout[yaxis_id].automargin = false; - Plotly.react(gd, gd.data, gd.layout); - } - - // We empty the fields and innerHTML after the plot is made - globals.CSV_DIV.querySelector("#csv_colors").innerHTML = ""; - globals.CSV_DIV.querySelector("#csv_columns").innerHTML = ""; - globals.CSV_DIV.querySelector("#csv_plot_yaxis_options").style.display = - "none"; - - globals.CSV_DIV.querySelectorAll("input").forEach(function (input) { - input.value = ""; - }); - globals.CSV_DIV.querySelectorAll("textarea").forEach(function (input) { - input.value = ""; - }); - }; - - popup_file_reader.readAsText(file); - } - } - closePopup(); -} - -function on_cancel() { - // We close any popup that is open - closePopup(); -} - -function on_delete(popup_id) { - let gd = globals.CHART_DIV; - closePopup(); - - if (popup_id == "text") { - let annotation = JSON.parse( - globals.TEXT_DIV.querySelector("#addtext_annotation").value - ); - gd.layout.annotations.splice(gd.layout.annotations.indexOf(annotation), 1); - gd.layout.dragmode = "pan"; - - Plotly.react(gd, gd.data, gd.layout); - - globals.TEXT_DIV.style.display = "none"; - } -} - -function closePopup() { - // We set the display to none to hide the popup overlay - var popup = document.getElementById("popup_overlay"); - popup.style.display = "none"; -} - -function openPopup(popup_id, popup_data = null) { - // We make sure to close the incase there is a popup already open - closePopup(); - var overlay = document.getElementById("popup_overlay"); - // We get the popup div and set the display to block to show the popup - overlay.style.display = "block"; - get_popup(popup_data, popup_id); -}