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

show dialog for keeping user activity #50

This commit is contained in:
lana-k
2021-08-21 18:44:29 +02:00
parent 0cae368350
commit 09cec13a9c
5 changed files with 171 additions and 29 deletions

View File

@@ -0,0 +1,83 @@
<template>
<modal
:name="name"
classes="dialog"
height="auto"
:clickToClose="false"
>
<div class="dialog-header">
{{ title }}
<close-icon @click="$emit('cancel')" :disabled="loading"/>
</div>
<div class="dialog-body">
<div v-if="loading" class="loading-dialog-body">
<loading-indicator :size="30" class="state-icon"/>
{{ loadingMsg }}
</div>
<div v-else class="loading-dialog-body">
<img :src="require('@/assets/images/success.svg')" class="success-icon state-icon" />
{{ successMsg }}
</div>
</div>
<div class="dialog-buttons-container">
<button
class="secondary"
:disabled="loading"
@click="$emit('cancel')"
>
Cancel
</button>
<button
class="primary"
:disabled="loading"
@click="$emit('action')"
>
{{ actionBtnName }}
</button>
</div>
</modal>
</template>
<script>
import LoadingIndicator from '@/components/LoadingIndicator'
import CloseIcon from '@/components/svg/close'
export default {
name: 'loadingDialog',
props: {
loadingMsg: String,
successMsg: String,
actionBtnName: String,
name: String,
title: String,
loading: Boolean
},
watch: {
loading () {
if (this.loading) {
this.$modal.show(this.name)
}
}
},
components: { LoadingIndicator, CloseIcon },
methods: {
cancel () {
this.$emit('cancel')
}
}
}
</script>
<style scoped>
.loading-dialog-body {
display: flex;
align-items: center;
}
.success-icon {
width: 30px;
}
.state-icon {
margin-right: 8px;
}
</style>

View File

@@ -9,22 +9,31 @@ async function _copyBlob (blob) {
]) ])
} }
async function _copyFromDataUrl (url) {
const blob = dataUrlToBlob(url)
await _copyBlob(blob)
Lib.notifier('Image copied to clipboard successfully', 'long')
}
async function _copyCanvas (canvas) {
canvas.toBlob(async (blob) => {
await _copyBlob(blob)
Lib.notifier('Image copied to clipboard successfully', 'long')
}, 'image/png', 1)
}
export default { export default {
async copyCsv (str) { async copyCsv (str) {
await navigator.clipboard.writeText(str) await navigator.clipboard.writeText(str)
Lib.notifier('CSV copied to clipboard successfully', 'long') Lib.notifier('CSV copied to clipboard successfully', 'long')
}, },
async copyCanvas (canvas, type) { async copyImage (source) {
canvas.toBlob(async (blob) => { if (source instanceof HTMLCanvasElement) {
await _copyBlob(blob) console.log('canvas')
Lib.notifier('Image copied to clipboard successfully', 'long') return _copyCanvas(source)
}, 'image/png', 1) } else {
}, return _copyFromDataUrl(source)
}
async copyFromDataUrl (url) {
const blob = dataUrlToBlob(url)
await _copyBlob(blob)
Lib.notifier('Image copied to clipboard successfully', 'long')
} }
} }

View File

@@ -31,7 +31,6 @@ import PlotlyEditor from 'react-chart-editor'
import chartHelper from '@/lib/chartHelper' import chartHelper from '@/lib/chartHelper'
import dereference from 'react-chart-editor/lib/lib/dereference' import dereference from 'react-chart-editor/lib/lib/dereference'
import fIo from '@/lib/utils/fileIo' import fIo from '@/lib/utils/fileIo'
import cIo from '@/lib/utils/clipboardIo'
export default { export default {
name: 'Chart', name: 'Chart',
@@ -90,13 +89,12 @@ export default {
return chartHelper.getOptionsForSave(this.state, this.dataSources) return chartHelper.getOptionsForSave(this.state, this.dataSources)
}, },
async saveAsPng () { async saveAsPng () {
const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png') const url = await this.prepareCopy()
this.$emit('loadingImageCompleted') this.$emit('loadingImageCompleted')
fIo.downloadFromUrl(url, 'chart') fIo.downloadFromUrl(url, 'chart')
}, },
async copyPngToClipboard () { async prepareCopy () {
const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png') return await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png')
cIo.copyFromDataUrl(url)
} }
} }
} }

View File

@@ -15,7 +15,6 @@
<script> <script>
import fIo from '@/lib/utils/fileIo' import fIo from '@/lib/utils/fileIo'
import cIo from '@/lib/utils/clipboardIo'
import $ from 'jquery' import $ from 'jquery'
import 'pivottable' import 'pivottable'
import 'pivottable/dist/pivot.css' import 'pivottable/dist/pivot.css'
@@ -166,15 +165,14 @@ export default {
fIo.downloadFromUrl(canvas.toDataURL('image/png'), 'pivot', 'image/png') fIo.downloadFromUrl(canvas.toDataURL('image/png'), 'pivot', 'image/png')
} }
}, },
async copyPngToClipboard () {
async prepareCopy () {
if (this.pivotOptions.rendererName === 'Custom chart') { if (this.pivotOptions.rendererName === 'Custom chart') {
this.pivotOptions.rendererOptions.customChartComponent.copyPngToClipboard() return await this.pivotOptions.rendererOptions.customChartComponent.prepareCopy()
} else if (this.pivotOptions.rendererName in $.pivotUtilities.plotly_renderers) { } else if (this.pivotOptions.rendererName in $.pivotUtilities.plotly_renderers) {
const url = await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png') return await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
cIo.copyFromDataUrl(url)
} else { } else {
const canvas = await getPivotCanvas(this.$refs.pivotOutput) return await getPivotCanvas(this.$refs.pivotOutput)
cIo.copyCanvas(canvas)
} }
} }
} }

View File

@@ -42,13 +42,25 @@
</icon-button> </icon-button>
<icon-button <icon-button
:loading="copyingImage"
tooltip="Copy visualisation to clipboard" tooltip="Copy visualisation to clipboard"
tooltip-position="top-left" tooltip-position="top-left"
@click="copyToClipboard" @click="prepareCopy"
> >
<clipboard-icon/> <clipboard-icon/>
</icon-button> </icon-button>
</side-tool-bar> </side-tool-bar>
<loading-dialog
loadingMsg="Rendering the visualisation..."
successMsg="Image is ready"
actionBtnName="Copy"
name="prepareCopy"
title="Copy to clipboard"
:loading="preparingCopy"
@action="copyToClipboard"
@cancel="cancelCopy"
/>
</div> </div>
</template> </template>
@@ -61,6 +73,8 @@ import ChartIcon from '@/components/svg/chart'
import PivotIcon from '@/components/svg/pivot' import PivotIcon from '@/components/svg/pivot'
import PngIcon from '@/components/svg/png' import PngIcon from '@/components/svg/png'
import ClipboardIcon from '@/components/svg/clipboard' import ClipboardIcon from '@/components/svg/clipboard'
import cIo from '@/lib/utils/clipboardIo'
import loadingDialog from '@/components/LoadingDialog'
export default { export default {
name: 'DataView', name: 'DataView',
@@ -73,13 +87,17 @@ export default {
ChartIcon, ChartIcon,
PivotIcon, PivotIcon,
PngIcon, PngIcon,
ClipboardIcon ClipboardIcon,
loadingDialog
}, },
data () { data () {
return { return {
mode: this.initMode || 'chart', mode: this.initMode || 'chart',
importToPngEnabled: true, importToPngEnabled: true,
loadingImage: false loadingImage: false,
copyingImage: false,
preparingCopy: false,
dataToCopy: null
} }
}, },
watch: { watch: {
@@ -106,12 +124,33 @@ export default {
getOptionsForSave () { getOptionsForSave () {
return this.$refs.viewComponent.getOptionsForSave() return this.$refs.viewComponent.getOptionsForSave()
}, },
copyToClipboard () { async prepareCopy () {
if ('ClipboardItem' in window) { if ('ClipboardItem' in window) {
this.$refs.viewComponent.copyPngToClipboard() this.preparingCopy = true
this.$modal.show('prepareCopy')
const t0 = performance.now()
setTimeout(async () => {
this.dataToCopy = await this.$refs.viewComponent.prepareCopy()
const t1 = performance.now()
if ((t1 - t0) < 950) {
this.$modal.hide('prepareCopy')
this.copyToClipboard()
} else {
this.preparingCopy = false
}
}, 0)
} else { } else {
alert("Your browser doesn't support copying images into the clipboard. If you use Firefox you can enable it by setting dom.events.asyncClipboard.clipboardItem to true.") alert("Your browser doesn't support copying images into the clipboard. If you use Firefox you can enable it by setting dom.events.asyncClipboard.clipboardItem to true.")
} }
},
async copyToClipboard () {
cIo.copyImage(this.dataToCopy)
this.$modal.hide('prepareCopy')
},
cancelCopy () {
this.dataToCopy = null
this.$modal.hide('prepareCopy')
} }
} }
} }
@@ -132,4 +171,19 @@ export default {
height: 100%; height: 100%;
overflow: auto; overflow: auto;
} }
>>>.vm--container {
animation: show-modal 1s linear 0s 1;
}
@keyframes show-modal {
0% {
opacity: 0;
}
99% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style> </style>