3
0

Add ability to configure columns in metric and chart blocks

This commit is contained in:
Emmy Leke 2024-01-17 14:04:47 +01:00 committed by Jože Fortun
parent 03ec8d3930
commit 144eb912fb
9 changed files with 165 additions and 47 deletions

View File

@ -1,12 +1,15 @@
<template>
<div class="d-flex">
<b-button
size="lg"
variant="light"
:size="size"
:variant="variant"
class="flex-fill"
:disabled="disabled"
@click="showModal = true"
>
{{ $t('allRecords.columns.title') }}
<slot>
{{ $t('allRecords.columns.title') }}
</slot>
</b-button>
<b-modal
@ -60,6 +63,21 @@ export default {
required: true,
default: () => [],
},
disabled: {
type: Boolean,
default: false,
},
size: {
type: String,
default: 'lg',
},
variant: {
type: String,
default: 'light',
},
},
data () {
@ -70,10 +88,10 @@ export default {
}
},
created () {
this.filteredFields = this.fields.map(f => {
return { ...f.moduleField }
})
watch: {
fields (fields) {
this.filteredFields = this.module.filterFields(fields)
},
},
beforeDestroy () {

View File

@ -175,6 +175,7 @@ export default {
this.$root.$emit(`drill-down-recordList:${recordListUniqueID}`, prefilter)
} else {
const { title } = this.block
const { fields = [] } = this.options.drillDown.recordListOptions || {}
// Open in modal
const block = new compose.PageBlockRecordList({
@ -182,6 +183,7 @@ export default {
blockID: `drillDown-${chartID}`,
options: {
moduleID,
fields,
prefilter,
presort: 'createdAt DESC',
hideRecordReminderButton: true,

View File

@ -18,11 +18,11 @@
<b-input-group-append>
<b-button
v-b-tooltip.noninteractive.hover="{ title: $t('chart.openInBuilder'), container: '#body' }"
:disabled="!selectedChart || (!selectedChart.canUpdateChart && !selectedChart.canDeleteChart)"
v-b-tooltip.hover="{ title: $t(chartSelectorTooltip), container: '#body' }"
:disabled="selectedChart && (!selectedChart.canUpdateChart && !selectedChart.canDeleteChart)"
variant="extra-light"
class="d-flex align-items-center"
:to="{ name: 'admin.charts.edit', params: { chartID: (selectedChart || {}).chartID }, query: null }"
:to="{ name: chartExternalLink, params: { chartID: (selectedChart || {}).chartID }, query: null }"
>
<font-awesome-icon :icon="['fas', 'external-link-alt']" />
</b-button>
@ -32,6 +32,7 @@
<template v-if="isDrillDownAvailable">
<b-form-group
:label="$t('chart.drillDown.label')"
:description="$t('chart.drillDown.description')"
label-class="d-flex align-items-center text-primary"
class="mb-1"
@ -46,16 +47,32 @@
/>
</template>
<c-input-select
v-model="options.drillDown.blockID"
:options="drillDownOptions"
:get-option-key="getOptionKey"
:disabled="!options.drillDown.enabled"
:get-option-label="o => o.title || o.kind"
:reduce="option => option.blockID"
:clearable="true"
:placeholder="$t('chart.drillDown.openInModal')"
/>
<b-input-group>
<c-input-select
v-model="options.drillDown.blockID"
:options="drillDownOptions"
:get-option-key="getOptionKey"
:disabled="!options.drillDown.enabled"
:get-option-label="o => o.title || o.kind"
:reduce="option => option.blockID"
:clearable="true"
:placeholder="$t('chart.drillDown.openInModal')"
/>
<b-input-group-append>
<column-picker
ref="columnPicker"
:module="selectedChartModule"
:fields="selectedDrilldownFields"
:disabled="!!options.drillDown.blockID || !options.drillDown.enabled"
variant="extra-light"
size="md"
@updateFields="onUpdateFields"
>
<font-awesome-icon :icon="['fas', 'wrench']" />
</column-picker>
</b-input-group-append>
</b-input-group>
</b-form-group>
</template>
</b-tab>
@ -64,6 +81,7 @@
import base from './base'
import { mapGetters } from 'vuex'
import { NoID } from '@cortezaproject/corteza-js'
import ColumnPicker from 'corteza-webapp-compose/src/components/Admin/Module/Records/ColumnPicker'
export default {
i18nOptions: {
@ -72,11 +90,16 @@ export default {
name: 'Chart',
components: {
ColumnPicker,
},
extends: base,
computed: {
...mapGetters({
charts: 'chart/set',
getModuleByID: 'module/getByID',
}),
selectedChart () {
@ -87,6 +110,14 @@ export default {
return this.charts.find(({ chartID }) => chartID === this.options.chartID)
},
chartExternalLink () {
return !this.selectedChart ? 'admin.charts' : 'admin.charts.edit'
},
chartSelectorTooltip () {
return !this.selectedChart ? 'chart.openChartList' : 'chart.openInBuilder'
},
selectedChartModuleID () {
if (!this.selectedChart) return
@ -95,6 +126,18 @@ export default {
return moduleID
},
selectedChartModule () {
if (!this.selectedChartModuleID) return
return this.getModuleByID(this.selectedChartModuleID)
},
selectedDrilldownFields () {
if (!this.selectedChart) return []
return this.options.drillDown.recordListOptions.fields
},
isDrillDownAvailable () {
if (!this.selectedChart) return
@ -110,15 +153,16 @@ export default {
methods: {
chartSelected () {
this.options.drillDown = {
enabled: false,
blockID: '',
}
this.block.resetDrillDown()
},
getOptionKey ({ chartID }) {
return chartID
},
onUpdateFields (fields) {
this.options.drillDown.recordListOptions.fields = fields.map(({ fieldID }) => fieldID)
},
},
}
</script>

View File

@ -223,13 +223,16 @@ export default {
} else {
// Open in modal
const metricID = `${this.block.blockID}-${name.replace(/\s+/g, '-').toLowerCase()}-${moduleID}-${metricIndex}`
const { title } = this.block
const { fields = [] } = this.options.metrics[metricIndex].drillDown.recordListOptions || {}
const block = new compose.PageBlockRecordList({
title: name || title || this.$t('metric.metricDrillDown'),
blockID: `drillDown-${metricID}`,
options: {
moduleID,
fields,
prefilter: filter,
presort: 'createdAt DESC',
hideRecordReminderButton: true,

View File

@ -166,7 +166,7 @@
</b-form-group>
</fieldset>
<fieldset>
<fieldset v-if="selectedMetricModule">
<h5>
{{ $t('metric.edit.metricLabel') }}
</h5>
@ -263,23 +263,39 @@
>
<template #label>
{{ $t('metric.drillDown.label') }}
<b-form-checkbox
v-model="edit.drillDown.enabled"
switch
class="ml-1"
class="ml-1 mb-1"
/>
</template>
<c-input-select
v-model="edit.drillDown.blockID"
:options="drillDownOptions"
:disabled="!edit.drillDown.enabled"
:get-option-label="o => o.title || o.kind"
:reduce="option => option.blockID"
:clearable="true"
:placeholder="$t('metric.drillDown.openInModal')"
append-to-body
/>
<b-input-group>
<c-input-select
v-model="edit.drillDown.blockID"
:options="drillDownOptions"
:disabled="!edit.drillDown.enabled"
:get-option-label="o => o.title || o.kind"
:reduce="option => option.blockID"
:clearable="true"
:placeholder="$t('metric.drillDown.openInModal')"
append-to-body
/>
<b-input-group-append>
<column-picker
:module="selectedMetricModule"
:disabled="!!edit.drillDown.blockID || !edit.drillDown.enabled"
:fields="selectedDrilldownFields"
variant="extra-light"
size="md"
@updateFields="onUpdateFields"
>
<font-awesome-icon :icon="['fas', 'wrench']" />
</column-picker>
</b-input-group-append>
</b-input-group>
</b-form-group>
</fieldset>
</b-card>
@ -333,6 +349,7 @@ import base from '../base'
import MStyle from './MStyle'
import { mapGetters } from 'vuex'
import MetricBase from '../MetricBase'
import ColumnPicker from 'corteza-webapp-compose/src/components/Admin/Module/Records/ColumnPicker'
import { compose, NoID } from '@cortezaproject/corteza-js'
export default {
@ -344,6 +361,7 @@ export default {
components: {
MStyle,
MetricBase,
ColumnPicker,
},
extends: base,
@ -375,7 +393,7 @@ export default {
computed: {
...mapGetters({
modules: 'module/set',
moduleByID: 'module/getByID',
getModuleByID: 'module/getByID',
}),
fields () {
@ -383,7 +401,13 @@ export default {
return []
}
return this.moduleByID(this.edit.moduleID).fields
return this.getModuleByID(this.edit.moduleID).fields
},
selectedDrilldownFields () {
if (!this.edit || !this.edit.drillDown.recordListOptions.fields) return []
return this.edit.drillDown.recordListOptions.fields
},
metricFields () {
@ -406,6 +430,12 @@ export default {
drillDownOptions () {
return this.page.blocks.filter(({ blockID, kind, options = {} }) => kind === 'RecordList' && blockID !== NoID && options.moduleID === this.edit.moduleID)
},
selectedMetricModule () {
if (!this.edit.moduleID) return undefined
return this.getModuleByID(this.edit.moduleID)
},
},
watch: {
@ -471,6 +501,10 @@ export default {
}
},
onUpdateFields (fields) {
this.edit.drillDown.recordListOptions.fields = fields
},
setDefaultValues () {
this.edit = undefined
this.dimensionModifiers = []

View File

@ -1,11 +1,14 @@
import { PageBlock, PageBlockInput, Registry } from './base'
import { Apply, CortezaID, NoID } from '../../../cast'
import { Apply,NoID } from '../../../cast'
import { Options as PageBlockRecordListOptions } from './record-list'
import { cloneDeep, merge } from 'lodash'
const kind = 'Chart'
interface DrillDown {
enabled: boolean;
blockID?: string;
blockID: string;
recordListOptions: Partial<PageBlockRecordListOptions>;
}
interface Options {
@ -24,7 +27,10 @@ const defaults: Readonly<Options> = Object.freeze({
drillDown: {
enabled: false,
blockID: '',
},
recordListOptions: {
fields: [],
},
}
})
export class PageBlockChart extends PageBlock {
@ -47,9 +53,13 @@ export class PageBlockChart extends PageBlock {
Apply(this.options, o, Boolean, 'showRefresh')
if (o.drillDown) {
this.options.drillDown = o.drillDown
this.options.drillDown = merge({}, defaults.drillDown, o.drillDown)
}
}
resetDrillDown(): void {
this.options.drillDown = cloneDeep(defaults.drillDown)
}
}
Registry.set(kind, PageBlockChart)

View File

@ -1,14 +1,15 @@
import { PageBlock, PageBlockInput, Registry } from './base'
import { merge } from 'lodash'
import { Apply } from '../../../cast'
import { Options as PageBlockRecordListOptions } from './record-list'
const kind = 'Metric'
type Reporter = (p: ReporterParams) => Promise<any>
interface DrillDown {
enabled: boolean;
blockID?: string;
blockID: string;
recordListOptions: Partial<PageBlockRecordListOptions>;
}
interface ReporterParams {
@ -62,9 +63,13 @@ const defaultMetric: Readonly<Metric> = Object.freeze({
color: '#000000',
fontSize: undefined,
},
drillDown: {
enabled: false,
blockID: '',
recordListOptions: {
fields: [],
},
},
})

View File

@ -12,7 +12,7 @@ interface FilterPreset {
roles: string[];
}
interface Options {
export interface Options {
moduleID: string;
prefilter: string;
presort: string;

View File

@ -98,8 +98,9 @@ chart:
display: Chart to display inside this block
drillDown:
label: Drill down
description: If a record list is selected, it will be used to display the drill down data. If no record list is selected the drill down data will be shown in a modal.
description: If a record list is selected, it will be used to display the drill down data. If no record list is selected, the drill down data will be shown in a modal.
openInModal: Open in modal
configureColumns: Choose the default fields
edit:
label: Edit chart
dimension:
@ -119,6 +120,7 @@ chart:
chartId: Chart preview (ID {{0}})
searchPlaceholder: Type here to search all charts in this namespace
openInBuilder: Open in chart builder
openChartList: Open chart list
content:
ok: Ok
label: Content
@ -201,7 +203,7 @@ metric:
defaultMetricLabel: Unnamed metric
drillDown:
label: Drill down
description: If a record list is selected, it will be used to display the drill down data. If no record list is selected the drill down data will be shown in a modal.
description: If a record list is selected, it will be used to display the drill down data. If no record list is selected, the drill down data will be shown in a modal.
openInModal: Open in modal
edit:
bucketLabel: Bucket size