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 {
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')
async copyImage (source) {
if (source instanceof HTMLCanvasElement) {
console.log('canvas')
return _copyCanvas(source)
} else {
return _copyFromDataUrl(source)
}
}
}

View File

@@ -31,7 +31,6 @@ import PlotlyEditor from 'react-chart-editor'
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',
@@ -90,13 +89,12 @@ export default {
return chartHelper.getOptionsForSave(this.state, this.dataSources)
},
async saveAsPng () {
const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png')
const url = await this.prepareCopy()
this.$emit('loadingImageCompleted')
fIo.downloadFromUrl(url, 'chart')
},
async copyPngToClipboard () {
const url = await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png')
cIo.copyFromDataUrl(url)
async prepareCopy () {
return await chartHelper.getImageDataUrl(this.$refs.plotlyEditor.$el, 'png')
}
}
}

View File

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

View File

@@ -41,14 +41,26 @@
<png-icon />
</icon-button>
<icon-button
<icon-button
:loading="copyingImage"
tooltip="Copy visualisation to clipboard"
tooltip-position="top-left"
@click="copyToClipboard"
@click="prepareCopy"
>
<clipboard-icon/>
</icon-button>
</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>
</template>
@@ -61,6 +73,8 @@ import ChartIcon from '@/components/svg/chart'
import PivotIcon from '@/components/svg/pivot'
import PngIcon from '@/components/svg/png'
import ClipboardIcon from '@/components/svg/clipboard'
import cIo from '@/lib/utils/clipboardIo'
import loadingDialog from '@/components/LoadingDialog'
export default {
name: 'DataView',
@@ -73,13 +87,17 @@ export default {
ChartIcon,
PivotIcon,
PngIcon,
ClipboardIcon
ClipboardIcon,
loadingDialog
},
data () {
return {
mode: this.initMode || 'chart',
importToPngEnabled: true,
loadingImage: false
loadingImage: false,
copyingImage: false,
preparingCopy: false,
dataToCopy: null
}
},
watch: {
@@ -106,12 +124,33 @@ export default {
getOptionsForSave () {
return this.$refs.viewComponent.getOptionsForSave()
},
copyToClipboard () {
async prepareCopy () {
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 {
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%;
overflow: auto;
}
>>>.vm--container {
animation: show-modal 1s linear 0s 1;
}
@keyframes show-modal {
0% {
opacity: 0;
}
99% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>