From 01f8b57b6e3f466992efe92e4d91085fa0d7090b Mon Sep 17 00:00:00 2001 From: plucik Date: Fri, 29 Nov 2024 13:49:12 +0200 Subject: [PATCH] integrates range cell selection module into query result datagrid change copy functionality from all table data/selected to only selected changes generate method due to changed selected data type --- .../src/components/QueryResultTabs.vue | 99 +++++++++---------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/pgmanage/app/static/pgmanage_frontend/src/components/QueryResultTabs.vue b/pgmanage/app/static/pgmanage_frontend/src/components/QueryResultTabs.vue index 24b2dfe41..5ab868dd0 100644 --- a/pgmanage/app/static/pgmanage_frontend/src/components/QueryResultTabs.vue +++ b/pgmanage/app/static/pgmanage_frontend/src/components/QueryResultTabs.vue @@ -78,6 +78,7 @@ import escape from 'lodash/escape'; import isNil from 'lodash/isNil'; import isEmpty from 'lodash/isEmpty'; import mean from 'lodash/mean'; +import last from 'lodash/last'; import { Tab } from "bootstrap"; export default { @@ -114,7 +115,10 @@ export default { data: [], placeholderHeaderFilter: "No Matching Data", autoResize: false, - selectableRows: true, + selectableRangeAutoFocus:false, + selectableRange:1, + selectableRangeColumns:true, + selectableRangeRows:true, height: "100%", layout: "fitDataStretch", columnDefaults: { @@ -123,7 +127,7 @@ export default { maxInitialWidth: 200, }, clipboard: "copy", - clipboardCopyRowRange: "selected", + clipboardCopyRowRange: "range", clipboardCopyConfig: { columnHeaders: false, //do not include column headers in clipboard output }, @@ -208,33 +212,29 @@ export default { }, methods: { copyTableData(format) { - const selectedData = this.getSelectedDataInDisplayOrder(); - const data = selectedData.length > 0 ? selectedData : this.table.getData(); - const headers = this.columns; + const data = last(this.table.getRangesData()); + + let headers = []; + let headerIndexMap = {}; // Map header titles to their original indices + + Object.keys(last(data)).forEach((key) => { + const originalIndex = parseInt(key, 10); + const header = this.columns[originalIndex]; + headers.push(header); + headerIndexMap[header] = originalIndex; + }); if (format === "json") { - const jsonOutput = this.generateJson(data, headers); + const jsonOutput = this.generateJson(data, headers, headerIndexMap); this.copyToClipboard(jsonOutput); } else if (format === "csv") { - const csvOutput = this.generateCsv(data, headers); + const csvOutput = this.generateCsv(data, headers, headerIndexMap); this.copyToClipboard(csvOutput); } else if (format === "markdown") { - const markdownOutput = this.generateMarkdown(data, headers); + const markdownOutput = this.generateMarkdown(data, headers, headerIndexMap); this.copyToClipboard(markdownOutput); } }, - getSelectedDataInDisplayOrder() { - const rowComponents = this.table.getSelectedRows(); - - const rowsWithPosition = rowComponents.map((row) => ({ - data: row.getData(), - position: row.getPosition(), - })); - - rowsWithPosition.sort((a, b) => a.position - b.position); - - return rowsWithPosition.map((row) => row.data); - }, copyToClipboard(text) { navigator.clipboard .writeText(text) @@ -244,38 +244,39 @@ export default { showToast("error", error); }); }, - generateJson(data, headers) { - const columns = headers.map((col, index) => ({ - field: index, - title: col, - })); - + generateJson(data, headers, headerIndexMap) { const mappedData = data.map((row) => { const mappedRow = {}; - columns.forEach((col) => { - mappedRow[col.title] = row[col.field]; + headers.forEach((header) => { + const originalIndex = headerIndexMap[header]; + mappedRow[header] = row[originalIndex]; }); return mappedRow; }); return JSON.stringify(mappedData, null, 2); }, - generateCsv(data, headers) { + generateCsv(data, headers, headerIndexMap) { const csvRows = []; // Add header row csvRows.push(headers.join(settingsStore.csvDelimiter)); data.forEach((row) => { - csvRows.push(row.join(settingsStore.csvDelimiter)); + const rowValues = headers.map((header) => { + const originalIndex = headerIndexMap[header]; + return row[originalIndex] || ""; + }) + csvRows.push(rowValues.join(settingsStore.csvDelimiter)); }); return csvRows.join("\n"); }, - generateMarkdown(data, headers) { - const columnWidths = headers.map((header, index) => { + generateMarkdown(data, headers, headerIndexMap) { + const columnWidths = headers.map((header) => { + const originalIndex = headerIndexMap[header]; const maxDataLength = data.reduce( - (max, row) => Math.max(max, (row[index] || "").toString().length), + (max, row) => Math.max(max, (row[originalIndex] || "").toString().length), 0 ); return Math.max(header.length, maxDataLength); @@ -299,12 +300,12 @@ export default { ); data.forEach((row) => { - mdRows.push( - `| ${row - .map((cell, index) => pad(cell || "", columnWidths[index])) - .join(" | ")} |` - ); + const rowValues = headers.map((header, index) => { + const originalIndex = headerIndexMap[header]; + return pad(row[originalIndex] || "", columnWidths[index]); }); + mdRows.push(`| ${rowValues.join(" | ")} |`); + }); return mdRows.join("\n"); }, @@ -410,28 +411,26 @@ export default { return colName === '?column?' ? `column-${idx}` : colName }) let cellContextMenu = () => { - const isAnyRowsSelected = !!this.table.getSelectedData().length; - const copyText = `${isAnyRowsSelected ? "selected" : "table data"}` return [ { - label: `
Copy ${copyText} as JSON
`, + label: + '
Copy
', + action: function (e, cell) { + cell.getTable().copyToClipboard(); + }, + }, + { + label: `
Copy as JSON
`, action: () => this.copyTableData("json"), }, { - label: `
Copy ${copyText} as CSV
`, + label: `
Copy as CSV
`, action: () => this.copyTableData("csv"), }, { - label: `
Copy ${copyText} as Markdown
`, + label: `
Copy as Markdown
`, action: () => this.copyTableData("markdown"), }, - { - label: - '
Copy
', - action: function (e, cell) { - cell.getTable().copyToClipboard("selected"); - }, - }, { label: '
View Content
',