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

plotly in pivot

This commit is contained in:
lana-k
2024-12-10 21:41:07 +01:00
parent 637d8d26dd
commit eee67763b5
5 changed files with 67 additions and 74 deletions

View File

@@ -3,7 +3,9 @@
<div class="warning chart-warning" v-show="!dataSources && visible"> <div class="warning chart-warning" v-show="!dataSources && visible">
There is no data to build a chart. Run your SQL query and make sure the result is not empty. There is no data to build a chart. Run your SQL query and make sure the result is not empty.
</div> </div>
<div class="chart" :style="{ height: !dataSources ? 'calc(100% - 40px)' : '100%' }">
<PlotlyEditor <PlotlyEditor
v-show="visible"
:data="state.data" :data="state.data"
:layout="state.layout" :layout="state.layout"
:frames="state.frames" :frames="state.frames"
@@ -14,12 +16,11 @@
:useResizeHandler="useResizeHandler" :useResizeHandler="useResizeHandler"
:debug="true" :debug="true"
:advancedTraceTypeSelector="true" :advancedTraceTypeSelector="true"
class="chart"
ref="plotlyEditor" ref="plotlyEditor"
:style="{ height: !dataSources ? 'calc(100% - 40px)' : '100%' }"
@update="update" @update="update"
@render="onRender" @render="onRender"
/> />
</div>
</div> </div>
</template> </template>
@@ -105,11 +106,10 @@ export default {
} }
}, },
methods: { methods: {
handleResize () { async handleResize () {
this.visible = false this.visible = false
this.$nextTick(() => { await this.$nextTick()
this.visible = true this.visible = true
})
}, },
onRender (data, layout, frames) { onRender (data, layout, frames) {
// TODO: check changes and enable Save button if needed // TODO: check changes and enable Save button if needed

View File

@@ -140,13 +140,11 @@ import $ from 'jquery'
import Multiselect from 'vue-multiselect' import Multiselect from 'vue-multiselect'
import PivotSortBtn from './PivotSortBtn' 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 { createApp } from 'vue'
export default { export default {
name: 'pivotUi', name: 'pivotUi',
props: ['keyNames', 'modelValue'], props: ['keyNames', 'modelValue'],
emits: ['loadingCustomChartImageCompleted', 'update:modelValue', 'update'], emits: ['update:modelValue', 'update'],
components: { components: {
Multiselect, Multiselect,
PivotSortBtn PivotSortBtn
@@ -163,13 +161,7 @@ export default {
val1: (this.modelValue && this.modelValue.vals && this.modelValue.vals[0]) || '', val1: (this.modelValue && this.modelValue.vals && this.modelValue.vals[0]) || '',
val2: (this.modelValue && this.modelValue.vals && this.modelValue.vals[1]) || '', val2: (this.modelValue && this.modelValue.vals && this.modelValue.vals[1]) || '',
colOrder: (this.modelValue && this.modelValue.colOrder) || 'key_a_to_z', colOrder: (this.modelValue && this.modelValue.colOrder) || 'key_a_to_z',
rowOrder: (this.modelValue && this.modelValue.rowOrder) || 'key_a_to_z', rowOrder: (this.modelValue && this.modelValue.rowOrder) || 'key_a_to_z'
customChartComponent:
(
this.modelValue &&
this.modelValue.rendererOptions &&
this.modelValue.rendererOptions.customChartComponent
) || createApp(Chart)
} }
}, },
computed: { computed: {
@@ -223,12 +215,6 @@ export default {
this.returnValue() this.returnValue()
} }
}, },
created () {
this.customChartComponent.onUpdate = () => { this.$emit('update') }
this.customChartComponent.onLoadingImageCompleted = () => {
this.$emit('loadingCustomChartImageCompleted')
}
},
methods: { methods: {
returnValue () { returnValue () {
const vals = [] const vals = []
@@ -245,11 +231,6 @@ export default {
aggregatorName: this.aggregator.name, aggregatorName: this.aggregator.name,
renderer: this.renderer.fun, renderer: this.renderer.fun,
rendererName: this.renderer.name, rendererName: this.renderer.name,
rendererOptions: this.renderer.name !== 'Custom chart'
? undefined
: {
customChartComponent: this.customChartComponent
},
vals vals
}) })
} }

View File

@@ -7,14 +7,24 @@
:key-names="columns" :key-names="columns"
v-model="pivotOptions" v-model="pivotOptions"
@update="$emit('update')" @update="$emit('update')"
@loadingCustomChartImageCompleted="$emit('loadingImageCompleted')"
/> />
<div ref="pivotOutput" class="pivot-output"/> <div ref="pivotOutput" class="pivot-output"/>
<div
ref="customChartOutput"
v-show="viewCustomChart"
class="custom-chart-output"
>
<chart
ref="customChart"
v-bind="customChartComponentProps"
@update="$emit('update')"
@onLoadingImageCompleted="$emit('loadingImageCompleted')"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import { createApp } from 'vue'
import fIo from '@/lib/utils/fileIo' import fIo from '@/lib/utils/fileIo'
import $ from 'jquery' import $ from 'jquery'
import 'pivottable' import 'pivottable'
@@ -35,7 +45,8 @@ export default {
'update:importToPngEnabled' 'update:importToPngEnabled'
], ],
components: { components: {
PivotUi PivotUi,
Chart
}, },
data () { data () {
return { return {
@@ -50,8 +61,7 @@ export default {
aggregator: $.pivotUtilities.aggregators.Count(), aggregator: $.pivotUtilities.aggregators.Count(),
vals: [], vals: [],
rendererName: 'Table', rendererName: 'Table',
renderer: $.pivotUtilities.renderers.Table, renderer: $.pivotUtilities.renderers.Table
rendererOptions: undefined
} }
: { : {
rows: this.initOptions.rows, rows: this.initOptions.rows,
@@ -64,15 +74,11 @@ export default {
](this.initOptions.vals), ](this.initOptions.vals),
vals: this.initOptions.vals, vals: this.initOptions.vals,
rendererName: this.initOptions.rendererName, rendererName: this.initOptions.rendererName,
renderer: $.pivotUtilities.renderers[this.initOptions.rendererName], renderer: $.pivotUtilities.renderers[this.initOptions.rendererName]
rendererOptions: !this.initOptions.rendererOptions },
? undefined customChartComponentProps: {
: { initOptions: this.initOptions?.rendererOptions?.customChartOptions,
customChartComponent: createApp(Chart, { forPivot: true
initOptions: this.initOptions
.rendererOptions.customChartOptions
})
}
} }
} }
}, },
@@ -115,13 +121,13 @@ export default {
}, },
mounted () { mounted () {
this.show() this.show()
// We need to detect resizing because plotly doesn't resize when resixe its container // We need to detect resizing because plotly doesn't resize when resize its container
// but it resize on window.resize (we will trigger it manualy in order to make plotly resize) // but it resize on window.resize (we will trigger it manualy in order to make plotly resize)
this.resizeObserver = new ResizeObserver(this.handleResize) this.resizeObserver = new ResizeObserver(this.handleResize)
this.resizeObserver.observe(this.$refs.pivotOutput) this.resizeObserver.observe(this.$refs.customChartOutput)
}, },
beforeUnmount () { beforeUnmount () {
this.resizeObserver.unobserve(this.$refs.pivotOutput) this.resizeObserver.unobserve(this.$refs.customChartOutput)
}, },
methods: { methods: {
handleResize () { handleResize () {
@@ -149,6 +155,12 @@ export default {
} }
} }
if (this.viewCustomChart) {
options.rendererOptions = {
getCustomComponentsProps: () => this.customChartComponentProps
}
}
$(this.$refs.pivotOutput).pivot( $(this.$refs.pivotOutput).pivot(
function (callback) { function (callback) {
const rowCount = !this.dataSources ? 0 : this.dataSources[this.columns[0]].length const rowCount = !this.dataSources ? 0 : this.dataSources[this.columns[0]].length
@@ -172,7 +184,7 @@ export default {
getOptionsForSave () { getOptionsForSave () {
const options = { ...this.pivotOptions } const options = { ...this.pivotOptions }
if (options.rendererOptions) { if (options.rendererOptions) {
const chartComponent = this.pivotOptions.rendererOptions.customChartComponent const chartComponent = this.$refs.customChart
options.rendererOptions = { options.rendererOptions = {
customChartOptions: chartComponent.getOptionsForSave() customChartOptions: chartComponent.getOptionsForSave()
} }
@@ -183,7 +195,7 @@ export default {
async saveAsPng () { async saveAsPng () {
if (this.viewCustomChart) { if (this.viewCustomChart) {
this.pivotOptions.rendererOptions.customChartComponent.saveAsPng() this.$refs.customChart.saveAsPng()
} else { } else {
const source = this.viewStandartChart const source = this.viewStandartChart
? await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png') ? await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
@@ -196,7 +208,7 @@ export default {
async prepareCopy () { async prepareCopy () {
if (this.viewCustomChart) { if (this.viewCustomChart) {
return await this.pivotOptions.rendererOptions.customChartComponent.prepareCopy() return await this.$refs.customChart.prepareCopy()
} }
if (this.viewStandartChart) { if (this.viewStandartChart) {
return await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png') return await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'png')
@@ -206,7 +218,7 @@ export default {
async saveAsSvg () { async saveAsSvg () {
if (this.viewCustomChart) { if (this.viewCustomChart) {
this.pivotOptions.rendererOptions.customChartComponent.saveAsSvg() this.$refs.customChart.saveAsSvg()
} else if (this.viewStandartChart) { } else if (this.viewStandartChart) {
const url = await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'svg') const url = await chartHelper.getImageDataUrl(this.$refs.pivotOutput, 'svg')
fIo.downloadFromUrl(url, 'pivot') fIo.downloadFromUrl(url, 'pivot')
@@ -215,7 +227,7 @@ export default {
saveAsHtml () { saveAsHtml () {
if (this.viewCustomChart) { if (this.viewCustomChart) {
this.pivotOptions.rendererOptions.customChartComponent.saveAsHtml() this.$refs.customChart.saveAsHtml()
return return
} }
@@ -246,7 +258,8 @@ export default {
background-color: var(--color-white); background-color: var(--color-white);
} }
.pivot-output { .pivot-output,
.custom-chart-output {
flex-grow: 1; flex-grow: 1;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
@@ -288,4 +301,7 @@ export default {
.pivot-output :deep(textarea:focus-visible) { .pivot-output :deep(textarea:focus-visible) {
outline: none; outline: none;
} }
.pivot-output:empty {
flex-grow: 0;
}
</style> </style>

View File

@@ -50,14 +50,9 @@ export function _getDataSources (pivotData) {
} }
function customChartRenderer (data, options) { function customChartRenderer (data, options) {
options.customChartComponent.dataSources = _getDataSources(data) const propsRef = options.getCustomComponentsProps()
options.customChartComponent.forPivot = true propsRef.dataSources = _getDataSources(data)
return null
const container = document.createElement('div')
options.customChartComponent.mount(container)
return $(container)
} }
$.extend( $.extend(

View File

@@ -131,6 +131,7 @@ export default {
const fromPosition = this.tab.layout[from] const fromPosition = this.tab.layout[from]
this.tab.layout[from] = this.tab.layout[to] this.tab.layout[from] = this.tab.layout[to]
this.tab.layout[to] = fromPosition this.tab.layout[to] = fromPosition
window.dispatchEvent(new Event('resize'))
events.send('inquiry.panel', null, { panel: to }) events.send('inquiry.panel', null, { panel: to })
}, },