Add scatter chart
This commit is contained in:
@@ -2,17 +2,15 @@
|
||||
<report-edit
|
||||
:report.sync="editReport"
|
||||
:modules="modules"
|
||||
:dimension-field-kind="['Select']"
|
||||
:supported-metrics="1"
|
||||
un-skippable
|
||||
>
|
||||
<template #dimension-options="{ index, dimension, field }">
|
||||
<b-form-group
|
||||
v-if="showPicker(field)"
|
||||
:label="$t('edit.dimension.options.label')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<c-item-picker
|
||||
v-if="showPicker(field)"
|
||||
:value="getOptions(dimension)"
|
||||
:options="field.options.options"
|
||||
:labels="{
|
||||
|
||||
@@ -3,6 +3,27 @@
|
||||
:report.sync="editReport"
|
||||
:modules="modules"
|
||||
>
|
||||
<template #dimension-options="{ dimension }">
|
||||
<b-row>
|
||||
<b-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('edit.dimension.rotate.label')"
|
||||
:description="$t('edit.dimension.rotate.description')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-input
|
||||
v-model="dimension.rotateLabel"
|
||||
type="number"
|
||||
number
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
|
||||
<template #y-axis="{ report }">
|
||||
<div
|
||||
class="px-3"
|
||||
@@ -270,6 +291,22 @@
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
|
||||
<b-col
|
||||
v-if="metric.type === 'scatter'"
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('edit.metric.symbol.label')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="metric.symbol"
|
||||
:options="scatterSymbolOptions"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</template>
|
||||
|
||||
@@ -572,6 +609,7 @@ import base from './base'
|
||||
const ignoredCharts = [
|
||||
'funnel',
|
||||
'gauge',
|
||||
'heatmap',
|
||||
]
|
||||
|
||||
export default {
|
||||
@@ -637,6 +675,16 @@ export default {
|
||||
{ value: 'smooth', text: this.$t('edit.metric.lineStyle.smooth') },
|
||||
{ value: 'step', text: this.$t('edit.metric.lineStyle.step') },
|
||||
],
|
||||
|
||||
scatterSymbolOptions: [
|
||||
{ value: 'circle', text: this.$t('edit.metric.symbol.circle') },
|
||||
{ value: 'triangle', text: this.$t('edit.metric.symbol.triangle') },
|
||||
{ value: 'diamond', text: this.$t('edit.metric.symbol.diamond') },
|
||||
{ value: 'pin', text: this.$t('edit.metric.symbol.pin') },
|
||||
{ value: 'arrow', text: this.$t('edit.metric.symbol.arrow') },
|
||||
{ value: 'rect', text: this.$t('edit.metric.symbol.rect') },
|
||||
{ value: 'roundRect', text: this.$t('edit.metric.symbol.roundRect') },
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -153,18 +153,18 @@
|
||||
<template v-if="!unSkippable">
|
||||
<b-row>
|
||||
<b-col
|
||||
v-if="!d.skipMissing"
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('edit.dimension.rotate.label')"
|
||||
:description="$t('edit.dimension.rotate.description')"
|
||||
:label="$t('edit.dimension.defaultValueLabel')"
|
||||
:description="$t('edit.dimension.defaultValueFootnote')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-input
|
||||
v-model="d.rotateLabel"
|
||||
type="number"
|
||||
number
|
||||
<b-form-input
|
||||
v-model="d.default"
|
||||
:type="defaultValueInputType(d)"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
@@ -182,22 +182,10 @@
|
||||
>
|
||||
{{ $t('edit.dimension.skipMissingValues') }}
|
||||
</b-form-checkbox>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
|
||||
<b-col
|
||||
v-if="!d.skipMissing"
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<b-form-group
|
||||
:label="$t('edit.dimension.defaultValueLabel')"
|
||||
:description="$t('edit.dimension.defaultValueFootnote')"
|
||||
label-class="text-primary"
|
||||
>
|
||||
<b-form-input
|
||||
v-model="d.default"
|
||||
:type="defaultValueInputType(d)"
|
||||
<slot
|
||||
name="dimension-options-options"
|
||||
:dimension="d"
|
||||
/>
|
||||
</b-form-group>
|
||||
</b-col>
|
||||
@@ -423,7 +411,7 @@ export default {
|
||||
},
|
||||
|
||||
hasAxis () {
|
||||
return this.metrics.some(({ type }) => ['bar', 'line'].includes(type))
|
||||
return this.metrics.some(({ type }) => ['bar', 'line', 'scatter'].includes(type))
|
||||
},
|
||||
|
||||
dimensionFields () {
|
||||
@@ -503,6 +491,8 @@ export default {
|
||||
if (!this.isTemporalField(f)) {
|
||||
this.$set(d, 'modifier', this.dimensionModifiers[0].value)
|
||||
}
|
||||
|
||||
this.$set(d.meta, 'fields', [])
|
||||
},
|
||||
|
||||
onMetricFieldChange (field, m) {
|
||||
|
||||
@@ -110,7 +110,7 @@ export default {
|
||||
...module.systemFields(),
|
||||
].find(({ name }) => name === field)
|
||||
|
||||
if (meta.fields) {
|
||||
if (meta.fields && field.kind === 'Select') {
|
||||
data.labels = data.labels.map(value => {
|
||||
const { text } = field.options.options.find(o => o.value === value) || {}
|
||||
return text || value
|
||||
@@ -130,8 +130,9 @@ export default {
|
||||
const { namespaceID } = this.chart || {}
|
||||
const recordModule = this.getModuleByID(field.options.moduleID)
|
||||
if (recordModule && data.labels) {
|
||||
const isValidRecordID = (recordID) => recordID !== dimension.default && recordID !== 'undefined'
|
||||
await Promise.all(data.labels.map(recordID => {
|
||||
if (recordID && recordID !== 'undefined') {
|
||||
if (isValidRecordID(recordID)) {
|
||||
return this.$ComposeAPI.recordRead({ namespaceID, moduleID: recordModule.moduleID, recordID }).then(record => {
|
||||
record = new compose.Record(recordModule, record)
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ export default {
|
||||
},
|
||||
|
||||
hasAxis () {
|
||||
return this.reports.some(({ metrics = [] }) => metrics.some(m => ['bar', 'line'].includes(m.type)))
|
||||
return this.reports.some(({ metrics = [] }) => metrics.some(m => ['bar', 'line', 'scatter'].includes(m.type)))
|
||||
},
|
||||
|
||||
timelineOptions () {
|
||||
|
||||
@@ -253,6 +253,7 @@ export class BaseChart {
|
||||
return {
|
||||
labels: this.processLabels(labels, dimension),
|
||||
datasets,
|
||||
dimension,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ export default class Chart extends BaseChart {
|
||||
smooth: m.smooth,
|
||||
step: m.step ? 'middle' : undefined,
|
||||
roseType: m.rose ? 'radius' : undefined,
|
||||
symbol: m.symbol,
|
||||
stack: m.stack,
|
||||
tooltip: {
|
||||
fixed: m.fixTooltips,
|
||||
@@ -61,7 +62,7 @@ export default class Chart extends BaseChart {
|
||||
legend: l,
|
||||
} = reports[0] || {}
|
||||
|
||||
const hasAxis = datasets.some(({ type }: any) => ['bar', 'line'].includes(type))
|
||||
const hasAxis = datasets.some(({ type }: any) => ['bar', 'line', 'scatter'].includes(type))
|
||||
let horizontal = false
|
||||
|
||||
if (hasAxis) {
|
||||
@@ -127,7 +128,7 @@ export default class Chart extends BaseChart {
|
||||
}
|
||||
}
|
||||
|
||||
options.series = datasets.map(({ type, label, data, stack, tooltip, fill, smooth, step, roseType }: any, index: number) => {
|
||||
options.series = datasets.map(({ type, label, data, stack, tooltip, fill, smooth, step, roseType, symbol }: any, index: number) => {
|
||||
const { fixed, relative } = tooltip
|
||||
|
||||
const tooltipFormatter = t?.formatting ? t.formatting : `{a}<br />{b} : {c}${relative ? ' ({d}%)' : ''}`
|
||||
@@ -202,7 +203,7 @@ export default class Chart extends BaseChart {
|
||||
bottom: offset?.isDefault ? undefined : offset?.bottom,
|
||||
left: offset?.isDefault ? undefined : offset?.left,
|
||||
}
|
||||
} else if (['bar', 'line'].includes(type)) {
|
||||
} else if (['bar', 'line', 'scatter'].includes(type)) {
|
||||
options.tooltip.trigger = 'axis'
|
||||
|
||||
const defaultOffset = {
|
||||
@@ -240,6 +241,7 @@ export default class Chart extends BaseChart {
|
||||
areaStyle: {
|
||||
opacity: fill ? 0.7 : 0,
|
||||
},
|
||||
symbol,
|
||||
label: {
|
||||
show: fixed,
|
||||
position: 'inside',
|
||||
@@ -301,6 +303,7 @@ export default class Chart extends BaseChart {
|
||||
smooth: true,
|
||||
fill: false,
|
||||
rose: false,
|
||||
symbol: 'circle',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,11 @@ export default class FunnelChart extends BaseChart {
|
||||
const report = this.config.reports?.[ri]
|
||||
const d = report?.dimensions?.[0] as Dimension
|
||||
|
||||
for (const { value } of d.meta?.fields || []) {
|
||||
let { fields = [] } = d.meta || {}
|
||||
fields = fields.length ? fields : r.labels
|
||||
|
||||
for (let label of fields) {
|
||||
const value = typeof label === 'object' ? label.value : label
|
||||
values.push({
|
||||
// Use value for label and resolve it on FE (i18n)
|
||||
label: value,
|
||||
|
||||
@@ -11,6 +11,7 @@ export enum ChartType {
|
||||
doughnut='doughnut',
|
||||
funnel = 'funnel',
|
||||
gauge = 'gauge',
|
||||
scatter = 'scatter',
|
||||
}
|
||||
|
||||
export interface TemporalDataPoint {
|
||||
@@ -45,6 +46,7 @@ export interface Metric {
|
||||
modifier?: string;
|
||||
fx?: string;
|
||||
backgroundColor?: string;
|
||||
symbol?: string;
|
||||
[_: string]: any;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ edit:
|
||||
unselectAllItems: Unselect all
|
||||
noItemsFound: No options found
|
||||
rotate:
|
||||
label: Rotate label
|
||||
label: Rotate labels
|
||||
description: Labels can be rotated from -90 to 90 degrees.
|
||||
filter:
|
||||
customize: Customize filter
|
||||
@@ -97,6 +97,15 @@ edit:
|
||||
labelColor: Label color
|
||||
labelLabel: Label
|
||||
labelPlaceholder: Total
|
||||
symbol:
|
||||
label: Symbol
|
||||
circle: Circle
|
||||
triangle: Triangle
|
||||
diamond: Diamond
|
||||
pin: Pin
|
||||
arrow: Arrow
|
||||
rect: Rectangle
|
||||
roundRect: Rounded Rectangle
|
||||
legend:
|
||||
bottom: Bottom
|
||||
left: Left
|
||||
@@ -116,6 +125,7 @@ edit:
|
||||
label: Chart type *
|
||||
line: Line
|
||||
pie: Pie
|
||||
scatter: Scatter
|
||||
placeholder: Select metric output
|
||||
relative: Show relative value
|
||||
relativePrecision: 'Precision:'
|
||||
|
||||
Reference in New Issue
Block a user