1
0
mirror of https://github.com/lana-k/sqliteviz.git synced 2025-12-06 10:08:52 +08:00

copy png to clipboard #50

This commit is contained in:
lana-k
2021-08-20 21:45:05 +02:00
parent 949e6b626e
commit ead861b610
12 changed files with 346 additions and 36 deletions

278
package-lock.json generated
View File

@@ -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",

View File

@@ -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",

View File

@@ -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
}

View File

@@ -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')
}
}

View File

@@ -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)
}
}
}

View File

@@ -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)

View File

@@ -14,14 +14,15 @@
</template>
<script>
import html2canvas from 'html2canvas'
import plotly from 'plotly.js'
import fIo from '@/lib/utils/fileIo'
import cIo from '@/lib/utils/clipboardIo'
import $ from 'jquery'
import 'pivottable'
import 'pivottable/dist/pivot.css'
import PivotUi from './PivotUi'
import { getPivotCanvas } from './pivotHelper'
import Chart from '@/views/Main/Workspace/Tabs/Tab/DataView/Chart'
import chartHelper from '@/lib/chartHelper'
import Vue from 'vue'
const ChartClass = Vue.extend(Chart)
@@ -156,21 +157,27 @@ export default {
if (this.pivotOptions.rendererName === 'Custom chart') {
this.pivotOptions.rendererOptions.customChartComponent.saveAsPng()
} else if (this.pivotOptions.rendererName in $.pivotUtilities.plotly_renderers) {
const chartElement = this.$refs.pivotOutput.querySelector('.js-plotly-plot')
const url = await plotly.toImage(chartElement, {
format: 'png',
width: null,
height: null
})
const url = await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
this.$emit('loadingImageCompleted')
fIo.downloadFromUrl(url, 'pivot')
} else {
const tableElement = this.$refs.pivotOutput.querySelector('.pvtTable')
const canvas = await html2canvas(tableElement)
const canvas = await getPivotCanvas(this.$refs.pivotOutput)
this.$emit('loadingImageCompleted')
fIo.downloadFromUrl(canvas.toDataURL('image/png'), 'pivot', 'image/png')
}
}
},
async copyPngToClipboard () {
if (this.pivotOptions.rendererName === 'Custom chart') {
this.pivotOptions.rendererOptions.customChartComponent.copyPngToClipboard()
} else if (this.pivotOptions.rendererName in $.pivotUtilities.plotly_renderers) {
const url = await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
cIo.copyFromDataUrl(url)
} else {
const canvas = await getPivotCanvas(this.$refs.pivotOutput)
cIo.copyCanvas(canvas)
}
},
}
}
</script>

View File

@@ -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)
}

View File

@@ -40,6 +40,14 @@
>
<png-icon />
</icon-button>
<icon-button
tooltip="Copy visualisation to clipboard"
tooltip-position="top-left"
@click="copyToClipboard"
>
<clipboard-icon/>
</icon-button>
</side-tool-bar>
</div>
</template>
@@ -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()
}
}
}

View File

@@ -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', () => {

View File

@@ -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', () => {

View File

@@ -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', () => {