diff --git a/package-lock.json b/package-lock.json index 932c438..3317a45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "sqliteviz", - "version": "0.15.3", + "version": "0.16.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "sqliteviz", - "version": "0.15.3", + "version": "0.16.0", "license": "Apache-2.0", "dependencies": { "codemirror": "^5.57.0", "core-js": "^3.6.5", + "dataurl-to-blob": "^0.0.1", "html2canvas": "^1.1.4", "jquery": "^3.6.0", "nanoid": "^3.1.12", @@ -5077,6 +5078,18 @@ "node": ">=6" } }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, "node_modules/cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -6746,6 +6759,14 @@ "node": ">=0.10" } }, + "node_modules/dataurl-to-blob": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/dataurl-to-blob/-/dataurl-to-blob-0.0.1.tgz", + "integrity": "sha1-B75KpV2G1MtWIk5Y4xgR9diFxMs=", + "dependencies": { + "jshint": "^2.9.2" + } + }, "node_modules/date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", @@ -6755,6 +6776,11 @@ "node": ">=4.0" } }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, "node_modules/dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", @@ -7333,7 +7359,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, "dependencies": { "domelementtype": "^2.0.1", "entities": "^2.0.0" @@ -7342,8 +7367,7 @@ "node_modules/dom-serializer/node_modules/domelementtype": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" }, "node_modules/domain-browser": { "version": "1.2.0", @@ -7358,8 +7382,7 @@ "node_modules/domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, "node_modules/domhandler": { "version": "2.4.2", @@ -7780,8 +7803,7 @@ "node_modules/entities": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, "node_modules/errno": { "version": "0.1.7", @@ -8723,6 +8745,14 @@ "node": ">=6" } }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -12823,6 +12853,87 @@ "node": ">=4" } }, + "node_modules/jshint": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.1.tgz", + "integrity": "sha512-vymzfR3OysF5P774x6zYv0bD4EpH6NWRxpq54wO9mA9RuY49yb1teKSICkLx2Ryx+mfzlVVNNbTBtsRtg78t7g==", + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/jshint/node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/jshint/node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "node_modules/jshint/node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/jshint/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/jshint/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/jshint/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/json-loader": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", @@ -18831,6 +18942,17 @@ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", "dev": true }, + "node_modules/shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -19856,6 +19978,17 @@ "node": ">=4" } }, + "node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/strongly-connected-components": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", @@ -27691,6 +27824,15 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -29141,12 +29283,25 @@ "assert-plus": "^1.0.0" } }, + "dataurl-to-blob": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/dataurl-to-blob/-/dataurl-to-blob-0.0.1.tgz", + "integrity": "sha1-B75KpV2G1MtWIk5Y4xgR9diFxMs=", + "requires": { + "jshint": "^2.9.2" + } + }, "date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", "dev": true }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + }, "dateformat": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", @@ -29627,7 +29782,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dev": true, "requires": { "domelementtype": "^2.0.1", "entities": "^2.0.0" @@ -29636,8 +29790,7 @@ "domelementtype": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", - "dev": true + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" } } }, @@ -29650,8 +29803,7 @@ "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", - "dev": true + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, "domhandler": { "version": "2.4.2", @@ -30046,8 +30198,7 @@ "entities": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", - "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", - "dev": true + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" }, "errno": { "version": "0.1.7", @@ -30833,6 +30984,11 @@ "strip-eof": "^1.0.0" } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", @@ -34363,6 +34519,86 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, + "jshint": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.1.tgz", + "integrity": "sha512-vymzfR3OysF5P774x6zYv0bD4EpH6NWRxpq54wO9mA9RuY49yb1teKSICkLx2Ryx+mfzlVVNNbTBtsRtg78t7g==", + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "requires": { + "date-now": "^0.1.4" + } + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "json-loader": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", @@ -39562,6 +39798,11 @@ "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", "dev": true }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -40488,6 +40729,11 @@ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", "dev": true }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=" + }, "strongly-connected-components": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz", diff --git a/package.json b/package.json index 2bfb29e..ed72f1c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "codemirror": "^5.57.0", "core-js": "^3.6.5", + "dataurl-to-blob": "^0.0.1", "html2canvas": "^1.1.4", "jquery": "^3.6.0", "nanoid": "^3.1.12", diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.js b/src/lib/chartHelper.js similarity index 69% rename from src/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.js rename to src/lib/chartHelper.js index 1a19f94..8558ef6 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.js +++ b/src/lib/chartHelper.js @@ -1,4 +1,5 @@ import dereference from 'react-chart-editor/lib/lib/dereference' +import plotly from 'plotly.js' export function getOptionsFromDataSources (dataSources) { if (!dataSources) { @@ -23,7 +24,17 @@ export function getOptionsForSave (state, dataSources) { return stateCopy } +export async function getImageDataUrl (element, type) { + const chartElement = element.querySelector('.js-plotly-plot') + return await plotly.toImage(chartElement, { + format: type, + width: null, + height: null + }) +} + export default { getOptionsFromDataSources, - getOptionsForSave + getOptionsForSave, + getImageDataUrl } diff --git a/src/lib/utils/clipboardIo.js b/src/lib/utils/clipboardIo.js index 4557b6b..e9cbd5c 100644 --- a/src/lib/utils/clipboardIo.js +++ b/src/lib/utils/clipboardIo.js @@ -1,8 +1,30 @@ import Lib from 'plotly.js/src/lib' +import dataUrlToBlob from 'dataurl-to-blob' + +async function _copyBlob(blob) { + await navigator.clipboard.write([ + new ClipboardItem({ + [blob.type]: blob + }) + ]) +} export default { async copyCsv (str) { await navigator.clipboard.writeText(str) Lib.notifier('CSV copied to clipboard successfully', 'long') + }, + + async copyCanvas (canvas, type) { + canvas.toBlob(async (blob) => { + await _copyBlob(blob) + Lib.notifier('Image copied to clipboard successfully', 'long') + }, 'image/png', 1) + }, + + async copyFromDataUrl (url) { + const blob = dataUrlToBlob(url) + await _copyBlob(blob) + Lib.notifier('Image copied to clipboard successfully', 'long') } } diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/index.vue b/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/index.vue index fafc830..1dc8a81 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/index.vue +++ b/src/views/Main/Workspace/Tabs/Tab/DataView/Chart/index.vue @@ -28,9 +28,10 @@ import plotly from 'plotly.js' import 'react-chart-editor/lib/react-chart-editor.min.css' import PlotlyEditor from 'react-chart-editor' -import chartHelper from './chartHelper' +import chartHelper from '@/lib/chartHelper' import dereference from 'react-chart-editor/lib/lib/dereference' import fIo from '@/lib/utils/fileIo' +import cIo from '@/lib/utils/clipboardIo' export default { name: 'Chart', @@ -89,10 +90,13 @@ export default { return chartHelper.getOptionsForSave(this.state, this.dataSources) }, async saveAsPng () { - const chartElement = this.$refs.plotlyEditor.$el.querySelector('.js-plotly-plot') - const url = await plotly.toImage(chartElement, { format: 'png', width: null, height: null }) + const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png') this.$emit('loadingImageCompleted') fIo.downloadFromUrl(url, 'chart') + }, + async copyPngToClipboard () { + const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png') + cIo.copyFromDataUrl(url) } } } diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/index.vue b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/index.vue index 98b6fd2..023fcce 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/index.vue +++ b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/index.vue @@ -139,7 +139,7 @@ import $ from 'jquery' import Multiselect from 'vue-multiselect' import PivotSortBtn from './PivotSortBtn' -import { renderers, aggregators, zeroValAggregators, twoValAggregators } from './pivotHelper' +import { renderers, aggregators, zeroValAggregators, twoValAggregators } from '../pivotHelper' import Chart from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart' import Vue from 'vue' const ChartClass = Vue.extend(Chart) diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/index.vue b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/index.vue index 3e7e58c..2f5c9d6 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/index.vue +++ b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/index.vue @@ -14,14 +14,15 @@ diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/pivotHelper.js b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper.js similarity index 91% rename from src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/pivotHelper.js rename to src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper.js index d20d8f9..9cd00eb 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/pivotHelper.js +++ b/src/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper.js @@ -2,6 +2,7 @@ import $ from 'jquery' import 'pivottable' import 'pivottable/dist/export_renderers.js' import 'pivottable/dist/plotly_renderers.js' +import html2canvas from 'html2canvas' export const zeroValAggregators = [ 'Count', @@ -75,3 +76,8 @@ export const aggregators = Object.keys($.pivotUtilities.aggregators).map(key => fun: $.pivotUtilities.aggregators[key] } }) + +export async function getPivotCanvas (pivotOutput) { + const tableElement = pivotOutput.querySelector('.pvtTable') + return await html2canvas(tableElement) +} diff --git a/src/views/Main/Workspace/Tabs/Tab/DataView/index.vue b/src/views/Main/Workspace/Tabs/Tab/DataView/index.vue index 652a6df..06e0f10 100644 --- a/src/views/Main/Workspace/Tabs/Tab/DataView/index.vue +++ b/src/views/Main/Workspace/Tabs/Tab/DataView/index.vue @@ -40,6 +40,14 @@ > + + + + @@ -52,6 +60,7 @@ import IconButton from '@/components/IconButton' import ChartIcon from '@/components/svg/chart' import PivotIcon from '@/components/svg/pivot' import PngIcon from '@/components/svg/png' +import ClipboardIcon from '@/components/svg/clipboard' export default { name: 'DataView', @@ -63,7 +72,8 @@ export default { IconButton, ChartIcon, PivotIcon, - PngIcon + PngIcon, + ClipboardIcon }, data () { return { @@ -95,6 +105,9 @@ export default { }, getOptionsForSave () { return this.$refs.viewComponent.getOptionsForSave() + }, + copyToClipboard () { + this.$refs.viewComponent.copyPngToClipboard() } } } diff --git a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Chart.spec.js b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Chart.spec.js index f28aec5..44de677 100644 --- a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Chart.spec.js +++ b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Chart.spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai' import sinon from 'sinon' import { mount, shallowMount } from '@vue/test-utils' import Chart from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart' -import chartHelper from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper' +import chartHelper from '@/lib/chartHelper' import * as dereference from 'react-chart-editor/lib/lib/dereference' describe('Chart.vue', () => { diff --git a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Pivot/PivotUi/pivotHelper.spec.js b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Pivot/PivotUi/pivotHelper.spec.js index 581668e..c352f92 100644 --- a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Pivot/PivotUi/pivotHelper.spec.js +++ b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/Pivot/PivotUi/pivotHelper.spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { _getDataSources } from '@/views/Main/Workspace/Tabs/Tab/DataView/Pivot/PivotUi/pivotHelper' +import { _getDataSources } from '@/views/Main/Workspace/Tabs/Tab/DataView/Pivot/pivotHelper' describe('pivotHelper.js', () => { it('_getDataSources returns data sources', () => { diff --git a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.spec.js b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.spec.js index b35550c..79c6176 100644 --- a/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.spec.js +++ b/tests/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper.spec.js @@ -1,6 +1,6 @@ import { expect } from 'chai' import sinon from 'sinon' -import * as chartHelper from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart/chartHelper' +import * as chartHelper from '@/lib/chartHelper' import * as dereference from 'react-chart-editor/lib/lib/dereference' describe('chartHelper.js', () => {