3
0

Address compose chart issues

This commit is contained in:
Katrin Yordanova
2022-11-24 15:46:31 +02:00
committed by Jože Fortun
parent c3c9ee89d3
commit fb03712755
9 changed files with 255 additions and 334 deletions
@@ -4,9 +4,35 @@
:modules="modules"
>
<template #y-axis="{ report }">
<h4 class="mb-3">
<h4 class="mb-0">
{{ $t('edit.yAxis.label') }}
</h4>
<small class="text-muted mb-3">
{{ $t('edit.yAxis.valueAppliedTo') }}
</small>
<b-form-group
horizontal
:label-cols="3"
class="mt-2"
breakpoint="md"
:label="$t('edit.yAxis.labelLabel')"
>
<b-input-group>
<b-form-input
v-model="report.yAxis.label"
/>
<b-input-group-append>
<chart-translator
:field.sync="report.yAxis.label"
:chart="chart"
:disabled="isNew"
highlight-key="yAxis.label"
button-variant="light"
/>
</b-input-group-append>
</b-input-group>
</b-form-group>
<b-form-group
horizontal
@@ -24,25 +50,28 @@
<b-form-group
horizontal
:label-cols="3"
class="mt-2"
class="mt-1"
breakpoint="md"
:label="$t('edit.yAxis.labelLabel')"
:label="$t('edit.yAxis.minLabel')"
>
<b-input-group>
<b-form-input
v-model="report.yAxis.label"
:placeholder="$t('edit.yAxis.labelPlaceholder')"
/>
<b-input-group-append>
<chart-translator
:field.sync="report.yAxis.label"
:chart="chart"
:disabled="isNew"
highlight-key="yAxis.label"
button-variant="light"
/>
</b-input-group-append>
</b-input-group>
<b-form-input
v-model="report.yAxis.min"
type="number"
:placeholder="$t('edit.yAxis.minPlaceholder')"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
class="mt-1"
breakpoint="md"
:label="$t('edit.yAxis.maxLabel')"
>
<b-form-input
v-model="report.yAxis.max"
type="number"
:placeholder="$t('edit.yAxis.maxPlaceholder')"
/>
</b-form-group>
<b-form-group
@@ -59,31 +88,6 @@
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
class="mt-1"
breakpoint="md"
:label="$t('edit.yAxis.minLabel')"
>
<b-form-input
v-model="report.yAxis.min"
:placeholder="$t('edit.yAxis.minPlaceholder')"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
class="mt-1"
breakpoint="md"
:label="$t('edit.yAxis.maxLabel')"
>
<b-form-input
v-model="report.yAxis.max"
:placeholder="$t('edit.yAxis.maxPlaceholder')"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
@@ -107,9 +111,6 @@
<b-form-checkbox
v-model="report.yAxis.beginAtZero"
:value="true"
:unchecked-value="false"
checked
>
{{ $t('edit.yAxis.axisScaleFromZero') }}
</b-form-checkbox>
@@ -182,8 +183,6 @@
<template v-if="hasRelativeDisplay(metric)">
<b-form-checkbox
v-model="metric.relativeValue"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.metric.relative') }}
</b-form-checkbox>
@@ -192,71 +191,59 @@
<template v-if="metric.type === 'line'">
<b-form-checkbox
v-model="metric.fill"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.metric.fillArea') }}
</b-form-checkbox>
</template>
<b-form-checkbox
v-model="metric.fixTooltips"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.metric.fixTooltips') }}
</b-form-checkbox>
</b-form-group>
</template>
<template #additional-config="{ report, metrics }">
<template #additional-config="{ report }">
<hr>
<div
v-for="(m, i) in metrics"
:key="i"
>
<template
v-if="m.type === 'pie' || m.type === 'doughnut'"
<template>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.legend.label') }}
</h4>
<b-form-group
horizontal
breakpoint="md"
>
<h5
v-if="metrics.length > 1"
class="d-flex align-items-center mb-3"
<b-form-checkbox
v-model="report.legend.isHidden"
>
<font-awesome-icon
class="grab metric-handle align-baseline text-secondary mr-2"
:icon="['fas', 'grip-vertical']"
/>
{{ $t('edit.metric.label') }} {{ i + 1 }}
</h5>
{{ $t('edit.additionalConfig.legend.hide') }}
</b-form-checkbox>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.legend.label') }}
</h4>
<b-form-group
horizontal
breakpoint="md"
>
<b-form-checkbox
v-model="report.legend.isHidden"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.additionalConfig.legend.hide') }}
</b-form-checkbox>
<b-form-checkbox
v-model="report.legend.isList"
<template v-if="!report.legend.isHidden">
<b-form-group
horizontal
class="mt-2 mb-1"
breakpoint="md"
:label-cols="3"
:label="$t('edit.additionalConfig.legend.orientation.label')"
:disabled="report.legend.isHidden"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.additionalConfig.legend.showAsList') }}
<b-form-select
v-model="report.legend.orientation"
:options="orientations"
/>
</b-form-group>
<b-form-checkbox
v-model="report.legend.isScrollable"
class="mb-1"
:disabled="report.legend.orientation !== 'horizontal'"
>
{{ $t('edit.additionalConfig.legend.scrollable') }}
</b-form-checkbox>
<b-form-checkbox
v-model="report.legend.isCustomized"
:disabled="report.legend.isHidden"
class="mb-3"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.additionalConfig.legend.position.customize') }}
</b-form-checkbox>
@@ -313,179 +300,107 @@
/>
</b-form-group>
</template>
</b-form-group>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.tooltip.label') }}
</h4>
<b-form-group
horizontal
breakpoint="md"
>
<b-form-checkbox
v-model="report.tooltip.labelsNextToPartition"
class="mb-3"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.additionalConfig.tooltip.labelNextToChartPartition') }}
</b-form-checkbox>
<b-form-group
horizontal
:label-cols="3"
breakpoint="md"
:label="$t('edit.additionalConfig.tooltip.formatting.label')"
:description="$t('edit.additionalConfig.tooltip.formatting.description')"
class="mt-1"
>
<b-input
v-model="report.tooltip.formatting"
:placeholder="$t('edit.additionalConfig.tooltip.formatting.placeholder')"
/>
</b-form-group>
</b-form-group>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.offset.label') }}
</h4>
</template>
</b-form-group>
</template>
<hr>
<template>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.tooltip.label') }}
</h4>
<b-form-group
horizontal
:label-cols="3"
breakpoint="md"
:label="$t('edit.additionalConfig.tooltip.formatting.label')"
:description="$t('edit.additionalConfig.tooltip.formatting.description')"
class="mt-1"
>
<b-input
v-model="report.tooltip.formatting"
:placeholder="$t('edit.additionalConfig.tooltip.formatting.placeholder')"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
breakpoint="md"
>
<b-form-checkbox
v-model="report.offset.isDefault"
class="mb-3"
:value="true"
:unchecked-value="false"
v-model="report.tooltip.labelsNextToPartition"
>
{{ $t('edit.additionalConfig.offset.default') }}
{{ $t('edit.additionalConfig.tooltip.labelNextToChartPartition') }}
</b-form-checkbox>
</b-form-group>
</template>
<hr>
<template>
<h4 class="mb-3">
{{ $t('edit.additionalConfig.offset.label') }}
</h4>
<b-form-checkbox
v-model="report.offset.isDefault"
class="mb-3"
>
{{ $t('edit.additionalConfig.offset.default') }}
</b-form-checkbox>
<b-form-group
v-if="!report.offset.isDefault"
horizontal
breakpoint="md"
>
<b-form-group
v-if="!report.offset.isDefault"
horizontal
:label-cols="3"
breakpoint="md"
:label="$t('edit.additionalConfig.offset.position.top')"
class="mt-1"
>
<b-form-group
horizontal
:label-cols="3"
breakpoint="md"
:label="$t('edit.additionalConfig.offset.position.top')"
class="mt-1"
>
<b-input
v-model="report.offset.top"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.right')"
breakpoint="md"
class="mt-1"
>
<b-input
v-model="report.offset.right"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.bottom')"
breakpoint="md"
class="mt-1"
>
<b-input
v-model="report.offset.bottom"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.left')"
breakpoint="md"
:description="$t('edit.additionalConfig.offset.valueRange')"
class="mt-1"
>
<b-input
v-model="report.offset.left"
placeholder="0"
/>
</b-form-group>
<b-input
v-model="report.offset.top"
placeholder="0"
/>
</b-form-group>
<hr>
</template>
<template v-if="m.type === 'bar' || m.type === 'line'">
<h4 class="mb-3">
{{ $t('edit.additionalConfig.offset.label') }}
</h4>
<b-form-checkbox
v-model="report.offset.isDefault"
class="mb-3"
:value="true"
:unchecked-value="false"
>
{{ $t('edit.additionalConfig.offset.default') }}
</b-form-checkbox>
<b-form-group
v-if="!report.offset.isDefault"
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.right')"
breakpoint="md"
class="mt-1"
>
<b-form-group
horizontal
:label-cols="3"
breakpoint="md"
:label="$t('edit.additionalConfig.offset.position.top')"
class="mt-1"
>
<b-input
v-model="report.offset.top"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.right')"
breakpoint="md"
class="mt-1"
>
<b-input
v-model="report.offset.right"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.bottom')"
breakpoint="md"
class="mt-1"
>
<b-input
v-model="report.offset.bottom"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.left')"
breakpoint="md"
:description="$t('edit.additionalConfig.offset.valueRange')"
class="mt-1"
>
<b-input
v-model="report.offset.left"
placeholder="0"
/>
</b-form-group>
<b-input
v-model="report.offset.right"
placeholder="0"
/>
</b-form-group>
</template>
</div>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.bottom')"
breakpoint="md"
class="mt-1"
>
<b-input
v-model="report.offset.bottom"
placeholder="0"
/>
</b-form-group>
<b-form-group
horizontal
:label-cols="3"
:label="$t('edit.additionalConfig.offset.position.left')"
breakpoint="md"
:description="$t('edit.additionalConfig.offset.valueRange')"
class="mt-1"
>
<b-input
v-model="report.offset.left"
placeholder="0"
/>
</b-form-group>
</b-form-group>
</template>
</template>
</report-edit>
</template>
@@ -538,6 +453,11 @@ export default {
{ value: 'center', text: this.$t('edit.yAxis.labelPosition.center') },
{ value: 'start', text: this.$t('edit.yAxis.labelPosition.bottom') },
],
orientations: [
{ value: 'horizontal', text: this.$t('edit.additionalConfig.legend.orientation.horizontal') },
{ value: 'vertical', text: this.$t('edit.additionalConfig.legend.orientation.vertical') },
],
}
},
@@ -56,11 +56,6 @@
</b-form-group>
</div>
<slot
name="y-axis"
:report="editReport"
/>
<!-- Configure report dimensions -->
<div v-if="!!module">
<hr>
@@ -260,6 +255,13 @@
</draggable>
</div>
<hr>
<slot
name="y-axis"
:report="editReport"
/>
<slot
name="additional-config"
:report="editReport"
@@ -1,8 +1,8 @@
<template>
<div class="h-100 position-relative">
<div class="d-flex flex-column align-items-center justify-content-center h-100 position-relative">
<div
v-if="processing"
class="d-flex align-items-center justify-content-center h-100"
class="d-flex flex-column align-items-center justify-content-center flex-fill"
>
<b-spinner />
</div>
@@ -10,7 +10,7 @@
<c-chart
v-if="renderer"
:chart="renderer"
class="p-1"
class="flex-fill p-1"
/>
</div>
</template>
@@ -169,42 +169,31 @@
<b-col
md="6"
sm="12"
style="min-height: 400px;"
>
<b-button
v-if="!error"
:disabled="processing || !reportsValid"
class="float-right"
variant="outline-primary"
@click.prevent="update"
>
{{ $t('edit.loadData') }}
</b-button>
<b-alert
:show="error"
variant="warning"
>
{{ error }}
</b-alert>
<div
class="chart-preview w-100 h-100 mt-5"
class="d-flex flex-column position-sticky"
style="top: 0;"
>
<chart-component
ref="chart"
:chart="chart"
:reporter="reporter"
width="200"
height="200"
@error="error=$event"
@updated="onUpdated"
/>
<b-button
:disabled="processing || !reportsValid"
variant="outline-primary"
@click.prevent="update"
>
{{ $t('edit.loadData') }}
</b-button>
<div
class="chart-preview mt-5"
>
<chart-component
ref="chart"
:chart="chart"
:reporter="reporter"
style="min-height: 400px;"
@updated="onUpdated"
/>
</div>
</div>
<!-- not supporting multiple reports for now
<b-button @click.prevent="reports.push(defaultReport)"
v-if="false"
class="float-right">+ Add report</b-button>
-->
</b-col>
</b-row>
</b-container>
@@ -241,6 +230,7 @@ import Reports from 'corteza-webapp-compose/src/components/Chart/Report'
import { chartConstructor } from 'corteza-webapp-compose/src/lib/charts'
import VueSelect from 'vue-select'
import { evaluatePrefilter } from 'corteza-webapp-compose/src/lib/record-filter'
import { debounce } from 'lodash'
const { colorschemes } = shared
const defaultReport = {
@@ -285,7 +275,6 @@ export default {
data () {
return {
chart: undefined,
error: null,
processing: false,
editReportIndex: undefined,
@@ -440,6 +429,15 @@ export default {
}
},
},
'chart.config': {
deep: true,
handler () {
debounce(function () {
this.update()
}, 500)
},
},
},
methods: {
+3 -6
View File
@@ -252,12 +252,7 @@ export class BaseChart {
}
defDimension (): Dimension {
return Object.assign({},
{
conditions: {},
meta: {},
labels: { rotateXAxisLabel: 0 }
})
return Object.assign({}, { conditions: {}, meta: {} })
}
defMetrics (): Metric {
@@ -277,6 +272,8 @@ export class BaseChart {
},
tooltip: {},
legend: {
isScrollable: true,
orientation: 'horizontal',
position: {
top: '0',
right: '0',
+22 -27
View File
@@ -163,11 +163,12 @@ export default class Chart extends BaseChart {
}
}
let pieLegend = {}
options.series = datasets.map(({ type, label, data, fill, tooltip }: any, index: number) => {
const { fixed, relative } = tooltip
const tooltipFormatter = t?.formatting ? t.formatting : `{a}<br />{b} : {c}${relative ? ' ({d}%)' : ''}`
const labelFormatter = `{c}${relative ? ' ({d}%)' : ''}`
if (['pie', 'doughnut'].includes(type)) {
const startRadius = type === 'doughnut' ? 40 : 0
@@ -176,7 +177,10 @@ export default class Chart extends BaseChart {
let lbl = {}
if (t?.labelsNextToPartition) {
lbl = { show: true }
lbl = {
show: true,
overflow: 'truncate',
}
} else {
lbl = {
show: fixed,
@@ -186,18 +190,6 @@ export default class Chart extends BaseChart {
}
}
const formatter = t?.formatting
? t.formatting
: `{a}<br />{b} : {c}${relative ? ' ({d}%)' : ''}`
if (l?.isCustomized) {
pieLegend = {
top: l?.position?.top || 'auto',
right: l?.position?.right || 'auto',
bottom: l?.position?.bottom || 'auto',
left: l?.position?.left || 'auto',
}
}
return {
z: index,
@@ -207,11 +199,11 @@ export default class Chart extends BaseChart {
center: ['50%', '55%'],
tooltip: {
trigger: 'item',
formatter,
formatter: tooltipFormatter,
},
label: {
...lbl,
fontSize: 14,
formatter: labelFormatter,
},
itemStyle: {
borderRadius: 5,
@@ -228,10 +220,10 @@ export default class Chart extends BaseChart {
data: labels.map((name: string, i: number) => {
return { name, value: data[i] }
}),
top: offset?.isDefault ? 45 : offset?.top,
right: offset?.isDefault ? 25 : offset?.right,
bottom: offset?.isDefault ? 40 : offset?.bottom,
left: offset?.isDefault ? 40 : offset?.left,
top: offset?.isDefault ? undefined : offset?.top,
right: offset?.isDefault ? undefined : offset?.right,
bottom: offset?.isDefault ? undefined : offset?.bottom,
left: offset?.isDefault ? undefined : offset?.left,
}
} else if (['bar', 'line'].includes(type)) {
options.tooltip.trigger = 'axis'
@@ -253,9 +245,8 @@ export default class Chart extends BaseChart {
options.grid = {
top: offset?.isDefault ? 45 : offset?.top,
right: offset?.isDefault ? 25 : offset?.right,
bottom: offset?.isDefault ? 40 : offset?.bottom,
left: offset?.isDefault ? 40 : offset?.left,
// prevents long labels like dates from being cut off
bottom: offset?.isDefault ? 25 : offset?.bottom,
left: offset?.isDefault ? 25 : offset?.left,
containLabel: true,
}
@@ -272,7 +263,7 @@ export default class Chart extends BaseChart {
position: 'inside',
align: 'center',
verticalAlign: 'middle',
fontSize: 14,
formatter: labelFormatter,
},
data,
}
@@ -286,8 +277,12 @@ export default class Chart extends BaseChart {
},
legend: {
show: !l?.isHidden,
type: l?.isList ? 'plain' : 'scroll',
...pieLegend,
type: l?.isScrollable ? 'scroll' : 'plain',
top: l?.isCustomized ? l?.position?.top : undefined,
right: l?.isCustomized ? l?.position?.right : undefined,
bottom: l?.isCustomized ? l?.position?.bottom : undefined,
left: l?.isCustomized ? l?.position?.left : 'center',
orient: l?.orientation || 'horizontal'
},
...options,
}
+2 -1
View File
@@ -76,7 +76,8 @@ export interface Position {
export interface Legend {
isHidden?: boolean;
isList?: boolean;
orientation?: string;
isScrollable?: boolean;
isCustomized?: boolean;
position?: Position;
}
+10 -6
View File
@@ -57,7 +57,7 @@ edit:
fieldLabel: Field
fieldPlaceholder: Select metric field
fillArea: Fill area below the line
fixTooltips: Show tooltips
fixTooltips: Always show tooltips
function:
avg: AVG
label: Function
@@ -108,10 +108,10 @@ edit:
axisScaleFromZero: Always begin axis scale at zero
label: Y-axis
rotate:
label: Rotate label
description: Labels can be rotated from -90 to 90 degrees. Applied to bar and line charts
label: Rotate labels
description: Labels can be rotated from -90 to 90 degrees
valueAppliedTo: Applied to bar and line charts
labelLabel: Axis label
labelPlaceholder: Axis label
labelPosition:
label: Label position
top: Top
@@ -126,7 +126,11 @@ edit:
legend:
label: Legend
hide: Hide legend
showAsList: Show as list
orientation:
label: Orientation
horizontal: Horizontal
vertical: Vertical
scrollable: Scrollable
position:
customize: Customize position
top: Top
@@ -139,7 +143,7 @@ edit:
labelNextToChartPartition: Show labels next to chart partition
formatting:
label: Formatting
description: '{a} - metrics field value, {b} - dimension field value, {c} - value of dimension field, {d} - percentage'
description: '{a} - metrics label, {b} - dimension value, {c} - metric value, {d} - metric value percentage'
placeholder: '{a}<br />{b} : {c} ({d}%)'
offset:
label: Offset
+7 -3
View File
@@ -3,13 +3,14 @@ package types
import (
"database/sql/driver"
"encoding/json"
"github.com/cortezaproject/corteza/server/pkg/locale"
"github.com/cortezaproject/corteza/server/pkg/sql"
"github.com/spf13/cast"
"strconv"
"strings"
"time"
"github.com/cortezaproject/corteza/server/pkg/locale"
"github.com/cortezaproject/corteza/server/pkg/sql"
"github.com/spf13/cast"
"github.com/cortezaproject/corteza/server/pkg/filter"
)
@@ -41,6 +42,9 @@ type (
Metrics []map[string]interface{} `json:"metrics,omitempty"`
Dimensions []map[string]interface{} `json:"dimensions,omitempty"`
YAxis map[string]interface{} `json:"yAxis,omitempty"`
Legend map[string]interface{} `json:"legend,omitempty"`
Tooltip map[string]interface{} `json:"tooltip,omitempty"`
Offset map[string]interface{} `json:"offset,omitempty"`
Renderer struct {
Version string `json:"version,omitempty" `
} `json:"renderer,omitempty"`