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:
@@ -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,13 +16,12 @@
|
|||||||
: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>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 })
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user