diff --git a/.gitignore b/.gitignore index 72ffeb44fe7c..e3616f955db9 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,8 @@ website/functions website/terminaltest !build/docker/compose.env openbb_terminal/core/plots/assets/plotly*.js -openbb_terminal/core/plots/plotly_temp.html -openbb_terminal/core/plots/table_temp.html .dccache +*rome.json # pyinstaller artifacts *.pyo diff --git a/build/pyinstaller/macOS/darwin/Resources/LICENSE.txt b/build/pyinstaller/macOS/darwin/Resources/LICENSE.txt index b366787995e3..793f55bb6076 100644 --- a/build/pyinstaller/macOS/darwin/Resources/LICENSE.txt +++ b/build/pyinstaller/macOS/darwin/Resources/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2022 OpenBB Inc. +Copyright (c) 2021-2023 OpenBB Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/frontend-components/plotly/src/App.tsx b/frontend-components/plotly/src/App.tsx index c2e7e60a5ef1..87c4e8f7c77b 100644 --- a/frontend-components/plotly/src/App.tsx +++ b/frontend-components/plotly/src/App.tsx @@ -50,6 +50,8 @@ function App() { title: "", }; let filename = data.layout?.title?.text + .replace(/ -/g, "") + .replace(/-/g, "") .replace(/|<\/b>/g, "") .replace(/ /g, "_"); let date = new Date().toISOString().slice(0, 10).replace(/-/g, ""); diff --git a/frontend-components/plotly/src/utils/utils.ts b/frontend-components/plotly/src/utils/utils.ts index d5aea8d6bb01..c1710524977d 100644 --- a/frontend-components/plotly/src/utils/utils.ts +++ b/frontend-components/plotly/src/utils/utils.ts @@ -1,377 +1,382 @@ // @ts-nocheck import domtoimage from "dom-to-image"; -import { Figure } from "react-plotly.js"; import * as Plotly from "plotly.js-dist-min"; +import { Figure } from "react-plotly.js"; const exportNativeFileSystem = async ({ - fileHandle, - blob, + fileHandle, + blob, }: { - fileHandle?: FileSystemFileHandle | null; - blob: Blob; + fileHandle?: FileSystemFileHandle | null; + blob: Blob; }) => { - if (!fileHandle) { - return; - } + if (!fileHandle) { + return; + } - return writeFileHandler({ fileHandle, blob }); + return writeFileHandler({ fileHandle, blob }); }; const writeFileHandler = async ({ - fileHandle, - blob, + fileHandle, + blob, }: { - fileHandle: FileSystemFileHandle; - blob: Blob; + fileHandle: FileSystemFileHandle; + blob: Blob; }) => { - const writer = await fileHandle.createWritable(); - await writer.write(blob); - await writer.close(); + const writer = await fileHandle.createWritable(); + await writer.write(blob); + await writer.close(); }; const IMAGE_TYPE: FilePickerAcceptType[] = [ - { - description: "PNG Image", - accept: { - "image/png": [".png"], - }, - }, - { - description: "JPEG Image", - accept: { - "image/jpeg": [".jpeg"], - }, - }, - { - description: "SVG Image", - accept: { - "image/svg+xml": [".svg"], - }, - }, + { + description: "PNG Image", + accept: { + "image/png": [".png"], + }, + }, + { + description: "JPEG Image", + accept: { + "image/jpeg": [".jpeg"], + }, + }, + { + description: "SVG Image", + accept: { + "image/svg+xml": [".svg"], + }, + }, ]; const getNewFileHandle = ({ - filename, - is_image, + filename, + is_image, }: { - filename: string; - is_image?: boolean; + filename: string; + is_image?: boolean; }): Promise => { - if ("showSaveFilePicker" in window) { - const opts: SaveFilePickerOptions = { - suggestedName: filename, - types: is_image - ? IMAGE_TYPE - : [ - { - description: "CSV File", - accept: { - "image/csv": [".csv"], - }, - }, - ], - excludeAcceptAllOption: true, - }; - - return showSaveFilePicker(opts); - } - - return new Promise((resolve) => { - resolve(null); - }); + try { + if ("showSaveFilePicker" in window) { + const opts: SaveFilePickerOptions = { + suggestedName: filename, + types: is_image + ? IMAGE_TYPE + : [ + { + description: "CSV File", + accept: { + "image/csv": [".csv"], + }, + }, + ], + excludeAcceptAllOption: true, + }; + + return showSaveFilePicker(opts); + } + } catch (error) { + console.error(error); + } + + return new Promise((resolve) => { + resolve(null); + }); }; export const saveToFile = ( - blob: Blob, - fileName: string, - fileHandle?: FileSystemFileHandle | null + blob: Blob, + fileName: string, + fileHandle?: FileSystemFileHandle | null, ) => { - try { - if (fileHandle === null) { - throw new Error("Cannot access filesystem"); - } - return exportNativeFileSystem({ fileHandle, blob }); - } catch (error) { - console.error("oops, something went wrong!", error); - const url = URL.createObjectURL(blob); - const link = document.createElement("a"); - link.setAttribute("href", url); - link.setAttribute("download", fileName); - link.style.visibility = "hidden"; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - return new Promise((resolve) => { - resolve(true); - }); + try { + if (fileHandle === null) { + throw new Error("Cannot access filesystem"); + } + return exportNativeFileSystem({ fileHandle, blob }); + } catch (error) { + console.error("oops, something went wrong!", error); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.setAttribute("href", url); + link.setAttribute("download", fileName); + link.style.visibility = "hidden"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } + return new Promise((resolve) => { + resolve(true); + }); }; export async function downloadCSV( - gd: Figure, - downloadFinished: (change: boolean) => void + gd: Figure, + downloadFinished: (change: boolean) => void, ) { - let data = gd.data; - let columns: string[] = []; - let rows: any[] = []; - - 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"; - - data.forEach(function (trace) { - if (trace.type == "candlestick") { - if (columns.length == 0) { - columns = ["Date", "Open", "High", "Low", "Close"]; - } - trace.x.forEach(function (x, i) { - rows.push([ - x, - trace.open[i], - trace.high[i], - trace.low[i], - trace.close[i], - ]); - }); - } - - if (trace.type == "scatter") { - if (columns.length == 0) { - columns.push(xaxis); - } - columns.push(trace.name != undefined ? trace.name : yaxis); - trace.x.forEach(function (x, i) { - if (rows[i] == undefined) { - rows[i] = [x]; - } - rows[i].push(trace.y[i]); - }); - } - }); - - return await downloadData(columns, rows, downloadFinished); + const data = gd.data; + let columns: string[] = []; + const rows: any[] = []; + + const xaxis = + "title" in gd.layout["xaxis"] && + gd.layout["xaxis"]["title"]["text"] !== undefined + ? gd.layout["xaxis"]["title"]["text"] + : "x"; + + const yaxis = + "title" in gd.layout["yaxis"] && + gd.layout["yaxis"]["title"]["text"] !== undefined + ? gd.layout["yaxis"]["title"]["text"] + : "y"; + + data.forEach(function (trace) { + if (trace.type === "candlestick") { + if (columns.length === 0) { + columns = ["Date", "Open", "High", "Low", "Close"]; + } + trace.x.forEach(function (x, i) { + rows.push([ + x, + trace.open[i], + trace.high[i], + trace.low[i], + trace.close[i], + ]); + }); + } + + if (["scatter", "bar"].includes(trace.type)) { + if (columns.length === 0) { + columns.push(xaxis); + } + columns.push(trace.name !== undefined ? trace.name : yaxis); + trace.x.forEach(function (x, i) { + if (rows[i] === undefined) { + rows[i] = [x]; + } + rows[i].push(trace.y[i]); + }); + } + }); + + return await downloadData(columns, rows, downloadFinished); } export async function downloadData( - columns: any, - data: any, - downloadFinished: (change: boolean) => void + columns: any, + data: any, + downloadFinished: (change: boolean) => void, ) { - const headers = columns; - const rows = data.map((row: any) => - row.map((cell: any) => { - if (cell == null) { - return ""; - } else if (typeof cell === "object") { - return JSON.stringify(cell); - } else { - return cell.toString().replace(/"/g, '""'); - } - }) - ); - const csvData = [headers, ...rows]; - - const csvContent = csvData.map((e) => e.join(",")).join("\n"); - const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); - const filename = `${window.title}.csv`; - try { - let fileHandle = await getNewFileHandle({ - filename: filename, - }); - - await loadingOverlay("Saving CSV"); - - non_blocking(async function () { - // @ts-ignore - saveToFile(blob, filename, fileHandle).then(async function () { - await new Promise((resolve) => setTimeout(resolve, 1500)); - if (!fileHandle) { - downloadFinished(true); - } - await loadingOverlay("", true); - }); - }, 2)(); - } catch (error) { - console.error(error); - } + const headers = columns; + const rows = data.map((row: any) => + row.map((cell: any) => { + if (cell == null) { + return ""; + } else if (typeof cell === "object") { + return JSON.stringify(cell); + } else { + return cell.toString().replace(/"/g, '""'); + } + }), + ); + const csvData = [headers, ...rows]; + + const csvContent = csvData.map((e) => e.join(",")).join("\n"); + const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); + const filename = `${window.title}.csv`; + try { + const fileHandle = await getNewFileHandle({ + filename: filename, + }); + + await loadingOverlay("Saving CSV"); + + non_blocking(async function () { + // @ts-ignore + saveToFile(blob, filename, fileHandle).then(async function () { + await new Promise((resolve) => setTimeout(resolve, 1500)); + if (!fileHandle) { + downloadFinished(true); + } + await loadingOverlay("", true); + }); + }, 2)(); + } catch (error) { + console.error(error); + } } function loadingOverlay(message?: string, is_close?: boolean) { - const loading = window.document.getElementById("loading") as HTMLElement; - const loading_text = window.document.getElementById( - "loading_text" - ) as HTMLElement; - return new Promise((resolve) => { - if (is_close) { - loading.classList.remove("show"); - } else { - // @ts-ignore - loading_text.innerHTML = message; - loading.classList.add("show"); - } - - let is_loaded = setInterval(function () { - if ( - is_close - ? !loading.classList.contains("show") - : loading.classList.contains("show") - ) { - clearInterval(is_loaded); - resolve(true); - } - }, 0.01); - }); + const loading = window.document.getElementById("loading") as HTMLElement; + const loading_text = window.document.getElementById( + "loading_text", + ) as HTMLElement; + return new Promise((resolve) => { + if (is_close) { + loading.classList.remove("show"); + } else { + // @ts-ignore + loading_text.innerHTML = message; + loading.classList.add("show"); + } + + const is_loaded = setInterval(function () { + if ( + is_close + ? !loading.classList.contains("show") + : loading.classList.contains("show") + ) { + clearInterval(is_loaded); + resolve(true); + } + }, 0.01); + }); } export const non_blocking = (func: Function, delay: number) => { - let timeout: number; - return function () { - // @ts-ignore - const context = this; - const args = arguments; - clearTimeout(timeout); - timeout = setTimeout(() => func.apply(context, args), delay); - }; + let timeout: number; + return function () { + // @ts-ignore + const context = this; + const args = arguments; + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(context, args), delay); + }; }; 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, + 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) { - const chart = document.getElementById("plotlyChart") as HTMLElement; - - if (init) { - chart.layout.annotations.push(openbb_watermark); - if ( - chart.globals.cmd_idx != undefined && - chart.globals.cmd_src != undefined - ) { - chart.layout.annotations[chart.globals.cmd_idx].text = - chart.globals.cmd_src; - } - - Plotly.relayout(chart, { - "title.text": chart.globals.title, - margin: chart.globals.old_margin, - }); - } - - if (!init) { - if ( - chart.globals.cmd_idx != undefined && - chart.globals.cmd_src != undefined - ) { - chart.layout.annotations[chart.globals.cmd_idx].text = ""; - } - chart.layout.annotations.splice(old_index, 1); - - Plotly.relayout(chart, { - "title.text": "", - margin: margin, - }); - } + const chart = document.getElementById("plotlyChart") as HTMLElement; + + if (init) { + chart.layout.annotations.push(openbb_watermark); + if ( + chart.globals.cmd_idx !== undefined && + chart.globals.cmd_src !== undefined + ) { + chart.layout.annotations[chart.globals.cmd_idx].text = + chart.globals.cmd_src; + } + + Plotly.relayout(chart, { + "title.text": chart.globals.title, + margin: chart.globals.old_margin, + }); + } + + if (!init) { + if ( + chart.globals.cmd_idx !== undefined && + chart.globals.cmd_src !== undefined + ) { + chart.layout.annotations[chart.globals.cmd_idx].text = ""; + } + chart.layout.annotations.splice(old_index, 1); + + Plotly.relayout(chart, { + "title.text": "", + margin: margin, + }); + } } export async function saveImage( - id: string, - filename: string, - extension: string + id: string, + filename: string, + extension: string, ) { - const chart = document.getElementById(id) as HTMLElement; - - if (["svg", "pdf"].includes(extension)) { - const chart = document.getElementById("plotlyChart") as HTMLElement; - const margin = chart.layout.margin; - const old_index = chart.layout.annotations.length; - - await setWatermarks(margin, old_index, true); - - Plotly.downloadImage(chart, { - format: "svg", - height: chart.clientHeight, - width: chart.clientWidth, - filename: window.title, - }); - - await setWatermarks(margin, old_index, false); - await loadingOverlay("", true); - return; - } - - non_blocking(async function () { - domtoimage.toBlob(chart).then(function (blob: Blob) { - saveToFile(blob, filename, null); - }); - }, 2)(); + const chart = document.getElementById(id) as HTMLElement; + + if (["svg", "pdf"].includes(extension)) { + const chart = document.getElementById("plotlyChart") as HTMLElement; + const margin = chart.layout.margin; + const old_index = chart.layout.annotations.length; + + await setWatermarks(margin, old_index, true); + + Plotly.downloadImage(chart, { + format: "svg", + height: chart.clientHeight, + width: chart.clientWidth, + filename: window.title, + }); + + await setWatermarks(margin, old_index, false); + await loadingOverlay("", true); + return; + } + + non_blocking(async function () { + domtoimage.toBlob(chart).then(function (blob: Blob) { + saveToFile(blob, filename, null); + }); + }, 2)(); } export async function downloadImage( - id: string, - hidemodebar: () => void, - loading: (bool: boolean) => void, - downloadFinished: (bool: boolean) => void + id: string, + hidemodebar: () => void, + loading: (bool: boolean) => void, + downloadFinished: (bool: boolean) => void, ) { - const chart = document.getElementById(id) as HTMLElement; - const filename = `${window.title}.png`; - - try { - loading(true); - let fileHandle = await getNewFileHandle({ - filename: filename, - is_image: true, - }); - let extension: string = "png"; - if (fileHandle !== null) { - // @ts-ignore - extension = fileHandle.name.split(".").pop(); - } - await loadingOverlay(`Saving ${extension.toUpperCase()}`); - - if (["svg", "pdf"].includes(extension)) { - await saveImage(id, filename, extension); - hidemodebar(false); - loading(false); - if (!fileHandle) { - downloadFinished(true); - } - return; - } - - non_blocking(async function () { - domtoimage.toBlob(chart).then(function (blob: Blob) { - saveToFile(blob, filename, fileHandle).then(async function () { - await loadingOverlay("", true); - hidemodebar(false); - loading(false); - if (!fileHandle) { - downloadFinished(true); - } - }); - }); - }, 2)(); - } catch (error) { - console.error(error); - hidemodebar(false); - loading(false); - } + const chart = document.getElementById(id) as HTMLElement; + const filename = `${window.title}.png`; + + try { + loading(true); + const fileHandle = await getNewFileHandle({ + filename: filename, + is_image: true, + }); + let extension = "png"; + if (fileHandle !== null) { + // @ts-ignore + extension = fileHandle.name.split(".").pop(); + } + await loadingOverlay(`Saving ${extension.toUpperCase()}`); + + if (["svg", "pdf"].includes(extension)) { + await saveImage(id, filename, extension); + hidemodebar(false); + loading(false); + if (!fileHandle) { + downloadFinished(true); + } + return; + } + + non_blocking(async function () { + domtoimage.toBlob(chart).then(function (blob: Blob) { + saveToFile(blob, filename, fileHandle).then(async function () { + await loadingOverlay("", true); + hidemodebar(false); + loading(false); + if (!fileHandle) { + downloadFinished(true); + } + }); + }); + }, 2)(); + } catch (error) { + console.error(error); + hidemodebar(false); + loading(false); + } + loading(false); } diff --git a/frontend-components/tables/src/App.tsx b/frontend-components/tables/src/App.tsx index d7b57c7e6b12..75c92ee6c2a7 100644 --- a/frontend-components/tables/src/App.tsx +++ b/frontend-components/tables/src/App.tsx @@ -50,9 +50,9 @@ function App() { const transformData = (data: any) => { if (!data) return null; - let filename = data.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, ""); + const filename = data.title?.replace(/|<\/b>/g, "").replace(/ /g, "_"); + const date = new Date().toISOString().slice(0, 10).replace(/-/g, ""); + const time = new Date().toISOString().slice(11, 19).replace(/:/g, ""); window.title = `openbb_${filename}_${date}_${time}`; const columns = data.columns; @@ -62,7 +62,7 @@ function App() { const transformedRow = {}; row.forEach((value: any, index: number) => { //@ts-ignore - transformedRow[columns[index]] = value || ""; + transformedRow[columns[index]] = value ? value : value === 0 ? 0 : ""; }); return transformedRow; }); diff --git a/frontend-components/tables/src/components/Table/ColumnHeader.tsx b/frontend-components/tables/src/components/Table/ColumnHeader.tsx index edd23391be19..21023836379a 100644 --- a/frontend-components/tables/src/components/Table/ColumnHeader.tsx +++ b/frontend-components/tables/src/components/Table/ColumnHeader.tsx @@ -8,310 +8,308 @@ import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"; export const magnitudeRegex = new RegExp("^([0-9]+)(\\s)([kKmMbBtT])$"); function Filter({ - column, - table, - numberOfColumns, + column, + table, + numberOfColumns, }: { - column: any; - table: any; - numberOfColumns: number; + column: any; + table: any; + numberOfColumns: number; }) { - const values = table - .getPreFilteredRowModel() - .flatRows.map((row: { getValue: (arg0: any) => any }) => - row.getValue(column.id) - ); + function getTime(value: string | number | Date) { + if (!value) return null; + const date = new Date(value); + const year = date.getFullYear(); + const month = + date.getMonth() + 1 > 9 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`; + const day = date.getDate() > 9 ? date.getDate() : `0${date.getDate()}`; + return `${year}-${month}-${day}`; + } - const areAllValuesString = values.every( - (value: null) => typeof value === "string" || value === null - ); + const values = table + .getPreFilteredRowModel() + .flatRows.map((row: { getValue: (arg0: any) => any }) => + row.getValue(column.id), + ); - const areAllValuesNumber = values.every( - (value: null | number | string) => - typeof value === "number" || - magnitudeRegex.test(value as string) || - value === null || - value === "" - ); + const areAllValuesString = values.every( + (value: null) => typeof value === "string" || value === null, + ); - const valuesContainStringWithSpaces = values.some( - (value: string | string[]) => - typeof value === "string" && value.includes(" ") - ); + const areAllValuesNumber = values.every( + (value: null | number | string) => + typeof value === "number" || + magnitudeRegex.test(value as string) || + value === null || + value === "", + ); - const columnFilterValue = column.getFilterValue(); + const valuesContainStringWithSpaces = values.some( + (value: string | string[]) => + typeof value === "string" && value.includes(" "), + ); - const isProbablyDate = values.every((value: string) => { - if (typeof value !== "string") return false; - const only_numbers = value?.replace(/[^0-9]/g, "").trim(); - return ( - only_numbers?.length >= 4 && - (includesDateNames(column.id) || - (column.id.toLowerCase() === "index" && !valuesContainStringWithSpaces)) - ); - }); + const columnFilterValue = column.getFilterValue(); - if (isProbablyDate) { - function getTime(value: string | number | Date) { - if (!value) return null; - const date = new Date(value); - const year = date.getFullYear(); - const month = - date.getMonth() + 1 > 9 - ? date.getMonth() + 1 - : `0${date.getMonth() + 1}`; - const day = date.getDate() > 9 ? date.getDate() : `0${date.getDate()}`; - return `${year}-${month}-${day}`; - } + const isProbablyDate = values.every((value: string) => { + if (typeof value !== "string") return false; + const only_numbers = value?.replace(/[^0-9]/g, "").trim(); + return ( + only_numbers?.length >= 4 && + (includesDateNames(column.id) || + (column.id.toLowerCase() === "index" && !valuesContainStringWithSpaces)) + ); + }); - return ( -
- { - const value = new Date(e.target.value).getTime(); - column.setFilterValue((old: [string, string]) => [value, old?.[1]]); - }} - placeholder={`Start date`} - className="_input" - /> - { - const value = new Date(e.target.value).getTime(); - column.setFilterValue((old: [string, string]) => [old?.[0], value]); - }} - placeholder={`End date`} - className="_input" - /> -
- ); - } + if (isProbablyDate) { + return ( +
+ { + const value = new Date(e.target.value).getTime(); + column.setFilterValue((old: [string, string]) => [value, old?.[1]]); + }} + placeholder={"Start date"} + className="_input" + /> + { + const value = new Date(e.target.value).getTime(); + column.setFilterValue((old: [string, string]) => [old?.[0], value]); + }} + placeholder={"End date"} + className="_input" + /> +
+ ); + } - if (areAllValuesNumber) { - return ( -
- - column.setFilterValue((old: [number, number]) => [ - e.target.value, - old?.[1], - ]) - } - placeholder={`Min`} - className="_input p-0.5" - /> - - column.setFilterValue((old: [number, number]) => [ - old?.[0], - e.target.value, - ]) - } - placeholder={`Max`} - className="_input p-0.5" - /> -
- ); - } - if (areAllValuesString) { - return ( -
- column.setFilterValue(e.target.value)} - placeholder={`Search...`} - className="_input" - /> -
- ); - } - return
; + if (areAllValuesNumber) { + return ( +
+ + column.setFilterValue((old: [number, number]) => [ + e.target.value, + old?.[1], + ]) + } + placeholder={"Min"} + className="_input p-0.5" + /> + + column.setFilterValue((old: [number, number]) => [ + old?.[0], + e.target.value, + ]) + } + placeholder={"Max"} + className="_input p-0.5" + /> +
+ ); + } + if (areAllValuesString) { + return ( +
+ column.setFilterValue(e.target.value)} + placeholder={"Search..."} + className="_input" + /> +
+ ); + } + return
; } const reorderColumn = ( - draggedColumnId: string, - targetColumnId: string, - columnOrder: string[] + draggedColumnId: string, + targetColumnId: string, + columnOrder: string[], ) => { - columnOrder.splice( - columnOrder.indexOf(targetColumnId), - 0, - columnOrder.splice(columnOrder.indexOf(draggedColumnId), 1)[0] as string - ); - return [...columnOrder]; + columnOrder.splice( + columnOrder.indexOf(targetColumnId), + 0, + columnOrder.splice(columnOrder.indexOf(draggedColumnId), 1)[0] as string, + ); + return [...columnOrder]; }; const DraggableColumnHeader: FC<{ - header: any; - table: any; - advanced: boolean; - idx: number; - lockFirstColumn: boolean; - setLockFirstColumn: (value: boolean) => void; + header: any; + table: any; + advanced: boolean; + idx: number; + lockFirstColumn: boolean; + setLockFirstColumn: (value: boolean) => void; }> = ({ - header, - table, - advanced, - idx, - lockFirstColumn, - setLockFirstColumn, + header, + table, + advanced, + idx, + lockFirstColumn, + setLockFirstColumn, }) => { - const { getState, setColumnOrder } = table; - const { columnOrder } = getState(); - const { column } = header; + const { getState, setColumnOrder } = table; + const { columnOrder } = getState(); + const { column } = header; - const [, dropRef] = useDrop({ - accept: "column", - drop: (draggedColumn: any) => { - const newColumnOrder = reorderColumn( - draggedColumn.id, - column.id, - columnOrder - ); - setColumnOrder(newColumnOrder); - }, - }); + const [, dropRef] = useDrop({ + accept: "column", + drop: (draggedColumn: any) => { + const newColumnOrder = reorderColumn( + draggedColumn.id, + column.id, + columnOrder, + ); + setColumnOrder(newColumnOrder); + }, + }); - const [{ isDragging }, dragRef, previewRef] = useDrag({ - collect: (monitor) => ({ - isDragging: monitor.isDragging(), - }), - item: () => column, - type: "column", - }); + const [{ isDragging }, dragRef, previewRef] = useDrag({ + collect: (monitor) => ({ + isDragging: monitor.isDragging(), + }), + item: () => column, + type: "column", + }); - const renderField = () => ( -
- {header.isPlaceholder ? null : ( - <> -
-
- {flexRender(column.columnDef.header, header.getContext())} - {column.getCanSort() && ( -
- - -
- )} -
- {advanced && column.id !== "select" && ( - - )} -
- {advanced && column.getCanFilter() ? ( -
- -
- ) : null} - - )} -
- ); + const renderField = () => ( +
+ {header.isPlaceholder ? null : ( + <> +
+
+ {flexRender(column.columnDef.header, header.getContext())} + {column.getCanSort() && ( +
+ + +
+ )} +
+ {advanced && column.id !== "select" && ( + + )} +
+ {advanced && column.getCanFilter() ? ( +
+ +
+ ) : null} + + )} +
+ ); - return ( - - {idx === 0 ? ( - - - {renderField()} - - - -
- -
-
-
-
- ) : ( - renderField() - )} - - - ); + return ( + + {idx === 0 ? ( + + + {renderField()} + + + +
+ +
+
+
+
+ ) : ( + renderField() + )} +