Add drill down for compose chart page block
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
v-if="renderer"
|
||||
:chart="renderer"
|
||||
class="flex-fill p-1"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
:chart="chart"
|
||||
:record="record"
|
||||
:reporter="reporter"
|
||||
@click="drillDown"
|
||||
/>
|
||||
</wrap>
|
||||
</template>
|
||||
@@ -17,7 +18,7 @@
|
||||
import { mapActions } from 'vuex'
|
||||
import base from './base'
|
||||
import ChartComponent from '../Chart'
|
||||
import { NoID } from '@cortezaproject/corteza-js'
|
||||
import { NoID, compose } from '@cortezaproject/corteza-js'
|
||||
import { evaluatePrefilter } from 'corteza-webapp-compose/src/lib/record-filter'
|
||||
|
||||
export default {
|
||||
@@ -33,12 +34,18 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
chart: null,
|
||||
|
||||
filter: undefined,
|
||||
|
||||
drillDownFilter: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.fetchChart()
|
||||
this.refreshBlock(this.refresh)
|
||||
|
||||
this.$root.$on('drill-down-chart', this.drillDown)
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -49,7 +56,7 @@ export default {
|
||||
async fetchChart (params = {}) {
|
||||
const { chartID } = this.options
|
||||
|
||||
if (chartID === NoID) {
|
||||
if (!chartID) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -61,15 +68,18 @@ export default {
|
||||
},
|
||||
|
||||
reporter (r) {
|
||||
const nr = { ...r }
|
||||
if (nr.filter) {
|
||||
this.filter = r
|
||||
|
||||
let filter = r.filter
|
||||
|
||||
if (filter) {
|
||||
// If we use ${record} or ${ownerID} and there is no record, resolve empty
|
||||
/* eslint-disable no-template-curly-in-string */
|
||||
if (!this.record && (nr.filter.includes('${record') || nr.filter.includes('${ownerID}'))) {
|
||||
if (!this.record && (filter.includes('${record') || filter.includes('${ownerID}'))) {
|
||||
return new Promise((resolve) => resolve([]))
|
||||
}
|
||||
|
||||
nr.filter = evaluatePrefilter(nr.filter, {
|
||||
filter = evaluatePrefilter(filter, {
|
||||
record: this.record,
|
||||
recordID: (this.record || {}).recordID || NoID,
|
||||
ownerID: (this.record || {}).ownedBy || NoID,
|
||||
@@ -78,7 +88,8 @@ export default {
|
||||
}
|
||||
|
||||
const { namespaceID } = this.namespace
|
||||
return this.$ComposeAPI.recordReport({ namespaceID, ...nr })
|
||||
|
||||
return this.$ComposeAPI.recordReport({ namespaceID, ...r, filter })
|
||||
},
|
||||
|
||||
refresh () {
|
||||
@@ -87,6 +98,60 @@ export default {
|
||||
this.key++
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} name
|
||||
* Based on drill down configuration, either changes the linked block on the page
|
||||
* or opens it in a modal wit the filter and dimensions from the chart and the clicked value
|
||||
*/
|
||||
drillDown ({ name }) {
|
||||
const { chartID, drillDown } = this.options
|
||||
|
||||
if (!drillDown.enabled) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get recordListID that is linked
|
||||
let { moduleID, dimensions, filter } = this.filter
|
||||
|
||||
// Construct filter
|
||||
const dimensionFilter = dimensions ? `(${dimensions} = '${name}')` : ''
|
||||
filter = filter ? `(${filter})` : ''
|
||||
const prefilter = [dimensionFilter, filter].filter(f => f).join(' AND ')
|
||||
|
||||
if (drillDown.blockID) {
|
||||
// Use linked record list to display drill down data
|
||||
const { pageID = NoID } = this.page
|
||||
const { recordID = NoID } = this.record || {}
|
||||
// Construct its uniqueID to identify it
|
||||
const recordListUniqueID = [pageID, recordID, drillDown.blockID].map(v => v || NoID).join('-')
|
||||
|
||||
this.$root.$emit(`drill-down-recordList:${recordListUniqueID}`, prefilter)
|
||||
} else {
|
||||
// Open in modal
|
||||
const block = new compose.PageBlockRecordList({
|
||||
title: `${dimensions} = '${name}'`,
|
||||
blockID: `drillDown-${chartID}`,
|
||||
options: {
|
||||
moduleID,
|
||||
prefilter,
|
||||
presort: 'createdAt DESC',
|
||||
hideRecordReminderButton: true,
|
||||
hideRecordViewButton: false,
|
||||
hideConfigureFieldsButton: false,
|
||||
hideImportButton: true,
|
||||
selectable: true,
|
||||
allowExport: true,
|
||||
perPage: 14,
|
||||
showTotalCount: true,
|
||||
magnifyOption: 'modal',
|
||||
},
|
||||
})
|
||||
|
||||
this.$root.$emit('magnify-page-block', { block })
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -3,28 +3,68 @@
|
||||
<b-form-group
|
||||
:label="$t('chart.display')"
|
||||
>
|
||||
<b-form-select
|
||||
v-model="block.options.chartID"
|
||||
:options="chartOptions"
|
||||
text-field="name"
|
||||
value-field="chartID"
|
||||
/>
|
||||
<b-input-group class="d-flex w-100">
|
||||
<vue-select
|
||||
v-model="block.options.chartID"
|
||||
:options="charts"
|
||||
:clearable="true"
|
||||
:placeholder="$t('chart.pick')"
|
||||
:reduce="option => option.chartID"
|
||||
label="name"
|
||||
append-to-body
|
||||
label-f
|
||||
class="chart-selector bg-white"
|
||||
@input="chartSelected"
|
||||
/>
|
||||
<b-input-group-append>
|
||||
<b-button
|
||||
:title="$t('chart.openInBuilder')"
|
||||
:disabled="!selectedChart || (!selectedChart.canUpdateChart && !selectedChart.canDeleteChart)"
|
||||
variant="light"
|
||||
class="d-flex align-items-center"
|
||||
:to="{ name: 'admin.charts.edit', params: { chartID: (selectedChart || {}).chartID }, query: null }"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', 'external-link-alt']" />
|
||||
</b-button>
|
||||
</b-input-group-append>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
|
||||
<b-button
|
||||
v-if="selectedChart"
|
||||
:disabled="!selectedChart.canUpdateChart && !selectedChart.canDeleteChart"
|
||||
variant="light"
|
||||
:to="{ name: 'admin.charts.edit', params: { chartID: selectedChart.chartID }, query: null }"
|
||||
>
|
||||
{{ $t('chart.openInBuilder') }}
|
||||
</b-button>
|
||||
<template v-if="isDrillDownAvailable">
|
||||
<b-form-group
|
||||
:description="$t('chart.drillDown.description')"
|
||||
label-class="d-flex align-items-center"
|
||||
class="mb-1"
|
||||
>
|
||||
<template #label>
|
||||
{{ $t('chart.drillDown.label') }}
|
||||
<b-form-checkbox
|
||||
v-model="options.drillDown.enabled"
|
||||
switch
|
||||
class="ml-1"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<vue-select
|
||||
v-model="options.drillDown.blockID"
|
||||
:options="drillDownOptions"
|
||||
:disabled="!options.drillDown.enabled"
|
||||
:get-option-label="o => o.title || o.kind"
|
||||
:reduce="option => option.blockID"
|
||||
:clearable="true"
|
||||
:placeholder="$t('chart.drillDown.openInModal')"
|
||||
append-to-body
|
||||
class="block-selector bg-white"
|
||||
/>
|
||||
</b-form-group>
|
||||
</template>
|
||||
</b-tab>
|
||||
</template>
|
||||
<script>
|
||||
import base from './base'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { NoID } from '@cortezaproject/corteza-js'
|
||||
import base from './base'
|
||||
import { VueSelect } from 'vue-select'
|
||||
|
||||
export default {
|
||||
i18nOptions: {
|
||||
@@ -33,6 +73,10 @@ export default {
|
||||
|
||||
name: 'Chart',
|
||||
|
||||
components: {
|
||||
VueSelect,
|
||||
},
|
||||
|
||||
extends: base,
|
||||
|
||||
computed: {
|
||||
@@ -40,20 +84,82 @@ export default {
|
||||
charts: 'chart/set',
|
||||
}),
|
||||
|
||||
chartOptions () {
|
||||
return [
|
||||
{ chartID: NoID, name: this.$t('chart.pick') },
|
||||
...this.charts,
|
||||
]
|
||||
},
|
||||
|
||||
selectedChart () {
|
||||
if (!this.options.chartID || this.options.chartID === NoID) {
|
||||
return
|
||||
}
|
||||
|
||||
return this.chartOptions.find(({ chartID }) => chartID === this.options.chartID)
|
||||
return this.charts.find(({ chartID }) => chartID === this.options.chartID)
|
||||
},
|
||||
|
||||
selectedChartModuleID () {
|
||||
if (!this.selectedChart) return
|
||||
|
||||
const { moduleID } = (this.selectedChart.config.reports[0] || {})
|
||||
|
||||
return moduleID
|
||||
},
|
||||
|
||||
isDrillDownAvailable () {
|
||||
if (!this.selectedChart) return
|
||||
|
||||
const { metrics = [] } = (this.selectedChart.config.reports[0] || {})
|
||||
|
||||
return !metrics.some(({ type }) => type === 'gauge')
|
||||
},
|
||||
|
||||
drillDownOptions () {
|
||||
return this.page.blocks.filter(({ blockID, kind, options = {} }) => kind === 'RecordList' && blockID !== NoID && options.moduleID === this.selectedChartModuleID)
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
chartSelected () {
|
||||
this.options.drillDown = {
|
||||
enabled: false,
|
||||
blockID: '',
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.input-group > .chart-selector {
|
||||
position: relative;
|
||||
-ms-flex: 1 1 auto;
|
||||
flex: 1 1 auto;
|
||||
width: 1%;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.block-selector, .chart-selector {
|
||||
&:not(.vs--open) .vs__selected + .vs__search {
|
||||
// force this to not use any space
|
||||
// we still need it to be rendered for the focus
|
||||
width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.vs__selected-options {
|
||||
// do not allow growing
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.vs__selected {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.vs__dropdown-menu .vs__dropdown-option {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
/>
|
||||
|
||||
<column-picker
|
||||
v-if="options.allRecords"
|
||||
v-if="!options.hideConfigureFieldsButton"
|
||||
:module="recordListModule"
|
||||
:fields="fields"
|
||||
class="float-left"
|
||||
@@ -96,27 +96,39 @@
|
||||
/>
|
||||
</div>
|
||||
</b-row>
|
||||
<b-row
|
||||
v-if="options.selectable"
|
||||
v-show="selected.length > 0"
|
||||
class="mt-2 no-gutters"
|
||||
|
||||
<div
|
||||
v-if="drillDownFilter"
|
||||
class="d-flex justify-content-end mt-1"
|
||||
>
|
||||
<b-col
|
||||
cols="4"
|
||||
class="pt-1 text-nowrap font-weight-bold"
|
||||
<b-button
|
||||
variant="outline-light"
|
||||
size="sm"
|
||||
class="text-nowrap text-primary border-0"
|
||||
@click="setDrillDownFilter(undefined)"
|
||||
>
|
||||
{{ $t('recordList.drillDown.filter.remove') }}
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="options.selectable && selected.length"
|
||||
class="d-flex align-items-center mt-1"
|
||||
>
|
||||
<div
|
||||
class="d-flex align-items-baseline my-auto pt-1 text-nowrap h-100"
|
||||
>
|
||||
{{ $t('recordList.selected', { count: selected.length, total: items.length }) }}
|
||||
<a
|
||||
href="#"
|
||||
<b-button
|
||||
variant="link"
|
||||
class="p-0 text-decoration-none"
|
||||
@click.prevent="handleSelectAllOnPage({ isChecked: false })"
|
||||
>
|
||||
({{ $t('recordList.cancelSelection') }})
|
||||
</a>
|
||||
</b-col>
|
||||
<b-col
|
||||
class="text-right"
|
||||
cols="8"
|
||||
>
|
||||
</b-button>
|
||||
</div>
|
||||
|
||||
<div class="ml-auto">
|
||||
<automation-buttons
|
||||
class="d-inline m-0"
|
||||
:buttons="options.selectionButtons"
|
||||
@@ -171,8 +183,8 @@
|
||||
/>
|
||||
</b-button>
|
||||
</template>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</div>
|
||||
</b-container>
|
||||
</template>
|
||||
|
||||
@@ -665,7 +677,9 @@ export default {
|
||||
|
||||
processing: false,
|
||||
// prefilter from block config
|
||||
prefilter: null,
|
||||
prefilter: undefined,
|
||||
recordListFilter: [],
|
||||
drillDownFilter: undefined,
|
||||
|
||||
// raw query string used to build final filter
|
||||
query: null,
|
||||
@@ -696,8 +710,6 @@ export default {
|
||||
// component
|
||||
ctr: 0,
|
||||
items: [],
|
||||
idPrefix: `rl:${this.blockIndex}`,
|
||||
recordListFilter: [],
|
||||
showingDeletedRecords: false,
|
||||
}
|
||||
},
|
||||
@@ -884,23 +896,8 @@ export default {
|
||||
|
||||
'record.recordID': {
|
||||
immediate: true,
|
||||
handler (recordID = NoID) {
|
||||
const { pageID = NoID } = this.page
|
||||
|
||||
// Set uniqueID so that events dont mix
|
||||
if (this.uniqueID) {
|
||||
this.$root.$off(`record-line:collect:${this.uniqueID}`)
|
||||
this.$root.$off(`page-block:validate:${this.uniqueID}`)
|
||||
this.$root.$off(`refetch-non-record-blocks:${pageID}`)
|
||||
}
|
||||
|
||||
this.uniqueID = [pageID, recordID, this.blockIndex].map(v => v || NoID).join('-')
|
||||
this.$root.$on(`record-line:collect:${this.uniqueID}`, this.resolveRecords)
|
||||
this.$root.$on(`page-block:validate:${this.uniqueID}`, this.validatePageBlock)
|
||||
this.$root.$on(`refetch-non-record-blocks:${pageID}`, () => {
|
||||
this.refresh(true)
|
||||
})
|
||||
|
||||
handler () {
|
||||
this.createEvents()
|
||||
this.getStorageRecordListFilter()
|
||||
this.prepRecordList()
|
||||
this.refresh(true)
|
||||
@@ -908,10 +905,12 @@ export default {
|
||||
},
|
||||
},
|
||||
|
||||
mounted () {
|
||||
this.createEvents()
|
||||
},
|
||||
|
||||
beforeDestroy () {
|
||||
this.$root.$off(`record-line:collect:${this.uniqueID}`)
|
||||
this.$root.$off(`page-block:validate:${this.uniqueID}`)
|
||||
this.$root.$off(`refetch-non-record-blocks:${this.page.pageID}`)
|
||||
this.destroyEvents()
|
||||
},
|
||||
|
||||
created () {
|
||||
@@ -921,6 +920,34 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
createEvents () {
|
||||
const { pageID = NoID } = this.page
|
||||
const { recordID = NoID } = this.record || {}
|
||||
|
||||
// Set uniqueID so that events dont mix
|
||||
if (this.uniqueID) {
|
||||
this.$root.$off(`record-line:collect:${this.uniqueID}`)
|
||||
this.$root.$off(`page-block:validate:${this.uniqueID}`)
|
||||
this.$root.$off(`drill-down-recordList:${this.uniqueID}`)
|
||||
this.$root.$off(`refetch-non-record-blocks:${pageID}`)
|
||||
}
|
||||
|
||||
this.uniqueID = [pageID, recordID, this.block.blockID].map(v => v || NoID).join('-')
|
||||
this.$root.$on(`record-line:collect:${this.uniqueID}`, this.resolveRecords)
|
||||
this.$root.$on(`page-block:validate:${this.uniqueID}`, this.validatePageBlock)
|
||||
this.$root.$on(`drill-down-recordList:${this.uniqueID}`, this.setDrillDownFilter)
|
||||
this.$root.$on(`refetch-non-record-blocks:${pageID}`, () => {
|
||||
this.refresh(true)
|
||||
})
|
||||
},
|
||||
|
||||
destroyEvents () {
|
||||
this.$root.$off(`record-line:collect:${this.uniqueID}`)
|
||||
this.$root.$off(`page-block:validate:${this.uniqueID}`)
|
||||
this.$root.$off(`refetch-non-record-blocks:${this.page.pageID}`)
|
||||
this.$root.$off(`drill-down-recordList:${this.uniqueID}`)
|
||||
},
|
||||
|
||||
onFilter (filter = []) {
|
||||
this.recordListFilter = filter
|
||||
this.setStorageRecordListFilter()
|
||||
@@ -989,7 +1016,7 @@ export default {
|
||||
|
||||
return {
|
||||
r,
|
||||
id: id || (r.recordID !== NoID ? r.recordID : `${this.idPrefix}:${this.ctr++}`),
|
||||
id: id || (r.recordID !== NoID ? r.recordID : `${this.uniqueID}:${this.ctr++}`),
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1022,7 +1049,7 @@ export default {
|
||||
module: this.recordListModule,
|
||||
refField: this.options.refField,
|
||||
positionField: this.options.positionField,
|
||||
idPrefix: this.idPrefix,
|
||||
idPrefix: this.uniqueID,
|
||||
})
|
||||
},
|
||||
|
||||
@@ -1350,7 +1377,7 @@ export default {
|
||||
this.selected = []
|
||||
|
||||
// Compute query based on query, prefilter and recordListFilter
|
||||
const query = queryToFilter(this.query, this.prefilter, this.recordListModule.filterFields(this.options.fields), this.recordListFilter)
|
||||
const query = queryToFilter(this.query, this.drillDownFilter || this.prefilter, this.recordListModule.filterFields(this.options.fields), this.recordListFilter)
|
||||
|
||||
const { moduleID, namespaceID } = this.recordListModule
|
||||
if (this.filter.pageCursor) {
|
||||
@@ -1455,6 +1482,11 @@ export default {
|
||||
onImportSuccessful () {
|
||||
this.refresh(true)
|
||||
},
|
||||
|
||||
setDrillDownFilter (drillDownFilter) {
|
||||
this.drillDownFilter = drillDownFilter
|
||||
this.pullRecords(true)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
:title="$t('general.label.magnify')"
|
||||
variant="outline-light"
|
||||
class="text-secondary d-print-none border-0"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : block.blockID)"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : { blockID: block.blockID })"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', isBlockOpened ? 'times' : 'search-plus']" />
|
||||
</b-button>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
:title="$t('general.label.magnify')"
|
||||
variant="outline-light"
|
||||
class="d-print-none border-0"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : block.blockID)"
|
||||
@click="$root.$emit('magnify-page-block', isBlockOpened ? undefined : { blockID: block.blockID })"
|
||||
>
|
||||
<font-awesome-icon :icon="['fas', isBlockOpened ? 'times' : 'search-plus']" />
|
||||
</b-button>
|
||||
|
||||
@@ -51,6 +51,10 @@ export default {
|
||||
block: undefined,
|
||||
record: undefined,
|
||||
page: undefined,
|
||||
|
||||
// Used if you want to display a specific block in the modal
|
||||
// Otherwise its retrieved based on the page and blockID
|
||||
customBlock: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -95,7 +99,9 @@ export default {
|
||||
},
|
||||
|
||||
created () {
|
||||
this.$root.$on('magnify-page-block', blockID => {
|
||||
this.$root.$on('magnify-page-block', ({ blockID, block } = {}) => {
|
||||
this.customBlock = block
|
||||
blockID = blockID || (block || {}).blockID
|
||||
this.$router.push({ query: { ...this.$route.query, blockID } })
|
||||
})
|
||||
},
|
||||
@@ -117,7 +123,7 @@ export default {
|
||||
return
|
||||
}
|
||||
|
||||
this.block = this.page.blocks.find(block => block.blockID === blockID)
|
||||
this.block = this.customBlock || this.page.blocks.find(block => block.blockID === blockID)
|
||||
const { namespaceID, moduleID } = this.page
|
||||
const recordID = paramsRecordID || queryRecordID
|
||||
|
||||
|
||||
@@ -123,17 +123,14 @@ export default {
|
||||
fullPageNavigation: true,
|
||||
showTotalCount: true,
|
||||
presort: 'createdAt DESC',
|
||||
// Set allrecords configuration
|
||||
allRecords: true,
|
||||
hideConfigureFieldsButton: false,
|
||||
rowViewUrl: 'admin.modules.record.view',
|
||||
rowEditUrl: 'admin.modules.record.edit',
|
||||
rowCreateUrl: 'admin.modules.record.create',
|
||||
},
|
||||
})
|
||||
|
||||
// Set allrecords configuration
|
||||
this.block.options = {
|
||||
...this.block.options,
|
||||
allRecords: true,
|
||||
rowViewUrl: 'admin.modules.record.view',
|
||||
rowEditUrl: 'admin.modules.record.edit',
|
||||
rowCreateUrl: 'admin.modules.record.create',
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
@@ -3,18 +3,28 @@ import { Apply, CortezaID, NoID } from '../../../cast'
|
||||
|
||||
const kind = 'Chart'
|
||||
|
||||
interface DrillDown {
|
||||
enabled: boolean;
|
||||
blockID?: string;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
chartID: string;
|
||||
refreshRate: number;
|
||||
showRefresh: boolean;
|
||||
magnifyOption: string;
|
||||
drillDown: DrillDown;
|
||||
}
|
||||
|
||||
const defaults: Readonly<Options> = Object.freeze({
|
||||
chartID: NoID,
|
||||
chartID: '',
|
||||
refreshRate: 0,
|
||||
magnifyOption: '',
|
||||
showRefresh: false,
|
||||
magnifyOption: '',
|
||||
drillDown: {
|
||||
enabled: false,
|
||||
blockID: ''
|
||||
}
|
||||
})
|
||||
|
||||
export class PageBlockChart extends PageBlock {
|
||||
@@ -30,10 +40,15 @@ export class PageBlockChart extends PageBlock {
|
||||
applyOptions (o?: Partial<Options>): void {
|
||||
if (!o) return
|
||||
|
||||
Apply(this.options, o, CortezaID, 'chartID')
|
||||
o.chartID = o.chartID === NoID ? '' : o.chartID
|
||||
|
||||
Apply(this.options, o, String, 'chartID', 'magnifyOption')
|
||||
Apply(this.options, o, Number, 'refreshRate')
|
||||
Apply(this.options, o, Boolean, 'showRefresh')
|
||||
Apply(this.options, o, String, 'magnifyOption')
|
||||
|
||||
if (o.drillDown) {
|
||||
this.options.drillDown = o.drillDown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ interface Options {
|
||||
hideHeader: boolean;
|
||||
hideAddButton: boolean;
|
||||
hideImportButton: boolean;
|
||||
hideConfigureFieldsButton: boolean;
|
||||
hideSearch: boolean;
|
||||
hidePaging: boolean;
|
||||
hideSorting: boolean;
|
||||
@@ -62,6 +63,7 @@ const defaults: Readonly<Options> = Object.freeze({
|
||||
hideHeader: false,
|
||||
hideAddButton: false,
|
||||
hideImportButton: false,
|
||||
hideConfigureFieldsButton: true,
|
||||
hideSearch: false,
|
||||
hidePaging: false,
|
||||
hideSorting: false,
|
||||
@@ -130,6 +132,7 @@ export class PageBlockRecordList extends PageBlock {
|
||||
'hideHeader',
|
||||
'hideAddButton',
|
||||
'hideImportButton',
|
||||
'hideConfigureFieldsButton',
|
||||
'hideSearch',
|
||||
'hidePaging',
|
||||
'fullPageNavigation',
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
:theme="theme"
|
||||
autoresize
|
||||
class="position-absolute w-100 h-100 overflow-hidden"
|
||||
v-on="$listeners"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -80,7 +80,11 @@ chart:
|
||||
label: Configure chart
|
||||
reportLabel: Report {{l}}
|
||||
reportsLabel: Reports
|
||||
display: 'Chart to display inside this block:'
|
||||
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.
|
||||
openInModal: Open in modal
|
||||
edit:
|
||||
label: Edit chart
|
||||
dimension:
|
||||
@@ -224,6 +228,9 @@ record:
|
||||
recordList:
|
||||
addRecord: Add
|
||||
cancelSelection: Cancel
|
||||
drillDown:
|
||||
filter:
|
||||
remove: Remove drill down filter
|
||||
tooltip:
|
||||
deleteSelected: Delete selected records
|
||||
undeleteSelected: Undelete selected records
|
||||
|
||||
Reference in New Issue
Block a user