Skip to content

Commit

Permalink
feat(dashboards and charts): editable tiles | slottable menu items
Browse files Browse the repository at this point in the history
- add new edit-tile event to dashboard renderer
- forward go to explore to analytics chart through tile definition
- add new editable property to tile definition that will add an "edit" item to
the analytics chart kebab menu. Clicking on edit, will emit an @edit-tile event
with the entire GridTile<T> object containing the tile layout, definition and index
  • Loading branch information
filipgutica committed Nov 1, 2024
1 parent f29661f commit ee386d3
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
{{ i18n.t('csvExport.exportButton') }}
</span>
</KDropdownItem>
<slot name="menu-items" />
</template>
</KDropdown>
<!-- Keep outside of dropdown, so we can independently affect its visibility -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
:class="{ 'custom-styling': isToggled}"
:config="(dashboardConfig as DashboardConfig)"
:context="context"
@edit-tile="onEditTile"
>
<template #slot-1>
<div class="slot-container">
Expand All @@ -32,7 +33,7 @@
</template>

<script setup lang="ts">
import type { DashboardConfig, DashboardRendererContext, TileConfig } from '../../src'
import type { DashboardConfig, DashboardRendererContext, TileConfig, TileDefinition, GridTile } from '../../src'
import { DashboardRenderer } from '../../src'
import { inject, ref } from 'vue'
import { ChartMetricDisplay } from '@kong-ui-public/analytics-chart'
Expand Down Expand Up @@ -135,6 +136,7 @@ const dashboardConfig: DashboardConfig = {
datasource: 'basic',
dimensions: ['route'],
},
editable: true,
},
layout: {
position: {
Expand Down Expand Up @@ -239,6 +241,10 @@ const dashboardConfig: DashboardConfig = {
const isToggled = ref(false)
const onEditTile = (tile: GridTile<TileDefinition>) => {
console.log('@edit-tile', tile)
}
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,19 @@
<!-- BarChartRenderer.vue -->
<template>
<QueryDataProvider
v-slot="{ data }"
<BaseAnalyticsChartRenderer
:chart-options="chartOptions"
:context="context"
:query="query"
:definition="definition"
:editable="editable"
:extra-props="{ showAnnotations: false }"
:height="height"
:query-ready="queryReady"
>
<div class="analytics-chart">
<AnalyticsChart
:allow-csv-export="chartOptions.allowCsvExport"
:chart-data="data"
:chart-options="options"
:chart-title="chartOptions.chartTitle"
legend-position="bottom"
:show-annotations="false"
:synthetics-data-key="chartOptions.syntheticsDataKey"
tooltip-title=""
/>
</div>
</QueryDataProvider>
/>
</template>

<script setup lang="ts">
import BaseAnalyticsChartRenderer from './BaseAnalyticsChartRenderer.vue'
import type { BarChartOptions, RendererProps } from '../types'
import QueryDataProvider from './QueryDataProvider.vue'
import { computed } from 'vue'
import type { AnalyticsChartOptions } from '@kong-ui-public/analytics-chart'
import { AnalyticsChart } from '@kong-ui-public/analytics-chart'
const props = defineProps<RendererProps<BarChartOptions>>()
const options = computed((): AnalyticsChartOptions => ({
type: props.chartOptions.type,
stacked: props.chartOptions.stacked,
chartDatasetColors: props.chartOptions.chartDatasetColors,
}))
defineProps<RendererProps<BarChartOptions>>()
</script>

<style scoped lang="scss">
.analytics-chart {
height: v-bind('`${height}px`');
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<template>
<QueryDataProvider
v-slot="{ data }"
:context="context"
:query="definition.query"
:query-ready="queryReady"
>
<div class="analytics-chart">
<AnalyticsChart
:allow-csv-export="chartOptions.allowCsvExport"
:chart-data="data"
:chart-options="options"
:chart-title="chartOptions.chartTitle"
legend-position="bottom"
:synthetics-data-key="chartOptions.syntheticsDataKey"
tooltip-title=""
v-bind="extraProps"
>
<template
v-if="editable"
#menu-items
>
<KDropdownItem @click="editTile">
{{ i18n.t('renderer.edit') }}
</KDropdownItem>
</template>
</AnalyticsChart>
</div>
</QueryDataProvider>
</template>

<script setup lang="ts">
import type { RendererProps, TileDefinition } from '../types'
import QueryDataProvider from './QueryDataProvider.vue'
import { computed, defineProps } from 'vue'
import type { AnalyticsChartOptions } from '@kong-ui-public/analytics-chart'
import { AnalyticsChart } from '@kong-ui-public/analytics-chart'
import composables from '../composables'
const props = defineProps<RendererProps<any> & { extraProps?: Record<string, any> }>()
const emit = defineEmits<{
(e: 'edit-tile', tile: TileDefinition): void
}>()
const { i18n } = composables.useI18n()
const options = computed((): AnalyticsChartOptions => ({
type: props.chartOptions.type,
stacked: props.chartOptions.stacked ?? false,
chartDatasetColors: props.chartOptions.chartDatasetColors,
}))
const editTile = () => {
emit('edit-tile', props.definition)
}
</script>

<style scoped lang="scss">
.analytics-chart {
height: v-bind('`${height}px`');
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
:definition="tile.meta"
:height="tile.layout.size.rows * (config.tileHeight || DEFAULT_TILE_HEIGHT) + parseInt(KUI_SPACE_70, 10)"
:query-ready="queryReady"
@edit-tile="onEditTile(tile)"
/>
</template>
</GridLayout>
</div>
</template>

<script setup lang="ts">
import type { DashboardConfig, DashboardRendererContext, GridTile, TileConfig, TileDefinition, DashboardRendererContextInternal } from '../types'
import type { DashboardConfig, DashboardRendererContext, GridTile, TileConfig, TileDefinition, DashboardRendererContextInternal, EditTileEvent } from '../types'
import DashboardTile from './DashboardTile.vue'
import { computed, inject } from 'vue'
import composables from '../composables'
Expand All @@ -53,6 +54,10 @@ const props = defineProps<{
config: DashboardConfig,
}>()
const emit = defineEmits<{
(e: 'edit-tile', tile: GridTile<TileDefinition>): void
}>()
const { i18n } = composables.useI18n()
// Note: queryBridge is not directly used by the DashboardRenderer component. It is required by many of the
Expand Down Expand Up @@ -151,6 +156,10 @@ const mergedContext = computed<DashboardRendererContextInternal>(() => {
// Right now, tiles don't have unique keys. Perhaps in the future they will,
// and we can use that instead of `index` as the fragment key.
const onEditTile = (tile: GridTile<TileDefinition>) => {
emit('edit-tile', tile)
}
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
:is="componentData.component"
v-if="componentData"
v-bind="componentData.rendererProps"
@edit-tile="onEditTile"
/>
</div>
</template>
Expand Down Expand Up @@ -34,6 +35,10 @@ const props = withDefaults(defineProps<{
height: DEFAULT_TILE_HEIGHT,
})
const emit = defineEmits<{
(e: 'edit-tile', tile: TileDefinition): void
}>()
const rendererLookup: Record<DashboardTileType, Component | undefined> = {
'timeseries_line': TimeseriesChartRenderer,
'horizontal_bar': BarChartRenderer,
Expand All @@ -51,14 +56,19 @@ const componentData = computed(() => {
return component && {
component,
rendererProps: {
query: props.definition.query,
definition: props.definition,
context: props.context,
queryReady: props.queryReady,
chartOptions: props.definition.chart,
height: props.height - PADDING_SIZE * 2,
editable: props.definition.editable,
},
}
})
const onEditTile = (definition: TileDefinition) => {
emit('edit-tile', definition)
}
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,24 @@ const overrideTimeframe: Ref<Timeframe> = computed(() => {
return relativePeriod
})
const options = computed<ProviderProps>(() => ({
datasource: props.query?.datasource,
overrideTimeframe: overrideTimeframe.value,
tz: props.context.tz,
additionalFilter: props.context.filters as ExploreFilter[], // TODO: Decide how to handle metric card filters.
longCardTitles: props.chartOptions.longCardTitles,
containerTitle: props.chartOptions.chartTitle,
description: props.chartOptions.description,
percentileLatency: props.chartOptions.percentileLatency,
refreshInterval: props.context.refreshInterval,
queryReady: props.queryReady,
}))
const options = computed<ProviderProps>(() => {
const datasource = props.definition.query?.datasource
if (datasource && datasource !== 'advanced' && datasource !== 'basic') {
throw new Error(`Invalid datasource value: ${datasource}`)
}
return {
datasource,
overrideTimeframe: overrideTimeframe.value,
tz: props.context.tz,
additionalFilter: props.context.filters as ExploreFilter[], // TODO: Decide how to handle metric card filters.
longCardTitles: props.chartOptions.longCardTitles,
containerTitle: props.chartOptions.chartTitle,
description: props.chartOptions.description,
percentileLatency: props.chartOptions.percentileLatency,
refreshInterval: props.context.refreshInterval,
queryReady: props.queryReady,
}
})
</script>

<style scoped lang="scss">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<QueryDataProvider
v-slot="{ data }"
:context="context"
:query="query"
:query="definition.query"
:query-ready="queryReady"
>
<div class="analytics-chart">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,18 @@
<!-- TimeseriesChartRenderer.vue -->
<template>
<QueryDataProvider
v-slot="{ data }"
<BaseAnalyticsChartRenderer
:chart-options="chartOptions"
:context="context"
:query="query"
:definition="definition"
:editable="editable"
:height="height"
:query-ready="queryReady"
>
<div class="analytics-chart">
<AnalyticsChart
:allow-csv-export="chartOptions.allowCsvExport"
:chart-data="data"
:chart-options="options"
:chart-title="chartOptions.chartTitle"
legend-position="bottom"
:synthetics-data-key="chartOptions.syntheticsDataKey"
tooltip-title=""
/>
</div>
</QueryDataProvider>
/>
</template>
<script setup lang="ts">
import type { RendererProps, TimeseriesChartOptions } from '../types'
import QueryDataProvider from './QueryDataProvider.vue'
import { computed } from 'vue'
import type { AnalyticsChartOptions } from '@kong-ui-public/analytics-chart'
import { AnalyticsChart } from '@kong-ui-public/analytics-chart'
const props = defineProps<RendererProps<TimeseriesChartOptions>>()

const options = computed((): AnalyticsChartOptions => {
// Default `stacked` to false.
const stacked = props.chartOptions.stacked ?? false
<script setup lang="ts">
import BaseAnalyticsChartRenderer from './BaseAnalyticsChartRenderer.vue'
import type { TimeseriesChartOptions, RendererProps } from '../types'
// Note that `fill` and `stacked` are linked; it's not possible to have a non-filled stacked chart.
// This matches our intuitions about how these charts work.
return {
type: props.chartOptions.type,
stacked,
chartDatasetColors: props.chartOptions.chartDatasetColors,
}
})
defineProps<RendererProps<TimeseriesChartOptions>>()
</script>

<style scoped lang="scss">
.analytics-chart {
height: v-bind('`${height}px`');
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<QueryDataProvider
v-slot="{ data }"
:context="context"
:query="query"
:query="definition.query"
:query-ready="queryReady"
>
<TopNTable
Expand Down
3 changes: 2 additions & 1 deletion packages/analytics/dashboard-renderer/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"24h": "Last 24-Hour Summary",
"7d": "Last 7-Day Summary",
"30d": "Last 30-Day Summary"
}
},
"edit": "Edit"
},
"queryDataProvider": {
"timeRangeExceeded": "The time range for this report is outside of your organization's data retention period"
Expand Down
Loading

0 comments on commit ee386d3

Please sign in to comment.