Skip to content

Commit

Permalink
feat(analytics-chart): move actions into kebab menu [MA-3301] (#1741)
Browse files Browse the repository at this point in the history
* feat(analytics-chart): move actions into kebab menu [MA-3301]

CSV export link moved to inside an action menu

* feat(analytics-chart): update component spec [MA-3301]

* feat: adding jump to explore link back in [MA-3301]

* feat: move modal outside dropdown [MA-3301]

* fix: add ff checking

* fix: component test

* fix: address comment

---------

Co-authored-by: Filip Gutica <[email protected]>
  • Loading branch information
mihai-peteu and filipgutica authored Oct 31, 2024
1 parent 93d89f5 commit ed6a72e
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@
:chart-data="(exploreResult)"
:chart-options="analyticsChartOptions"
chart-title="Request count by Status Code"
:go-to-explore="(exploreLink)"
:legend-position="legendPosition"
:show-annotations="showAnnotationsToggle"
:show-legend-values="showLegendValuesToggle"
Expand Down Expand Up @@ -330,6 +331,8 @@ const exportCsv = () => {
setModalVisibility(true)
}
const exploreLink: string = 'https://cloud.konghq.tech/us/analytics/explorer'
const exploreResultText = ref('')
const hasError = computed(() => !isValidJson(exploreResultText.value))
const isValid = computed(() => exploreResultText.value !== undefined &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ function mouseMove(x1: number, y1: number, x2: number, y2: number, duration: num
describe('<AnalyticsChart />', () => {
beforeEach(() => {
cy.viewport(1280, 800)
cy.stub(composables, 'useEvaluateFeatureFlag').returns({
evaluateFeatureFlag: () => true,
})
})

it('Renders a line chart for total requests count with status code dimension', () => {
Expand Down Expand Up @@ -251,21 +254,52 @@ describe('<AnalyticsChart />', () => {
chartTitle: 'Requests',
},
})
cy.getTestId('csv-export-button').should('not.exist')

cy.getTestId('chart-action-menu').should('not.exist')
})

it('does not render an "Export" button if chart data is present but prop is set to `false`', () => {
it('renders the kebab menu with only the "Jump to Explore" link if no data is provided', () => {
cy.mount(AnalyticsChart, {
props: {
allowCsvExport: true,
goToExplore: 'https://cloud.konghq.tech/us/analytics/explorer',
chartData: emptyExploreResult,
chartOptions: {
type: 'timeseries_line',
},
chartTitle: 'Requests',
},
})

cy.getTestId('chart-action-menu').should('exist')

// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.getTestId('chart-action-menu').click().then(() => {
cy.getTestId('chart-jump-to-explore').should('exist')
cy.getTestId('csv-export-button').should('not.exist')
})
})

it('does not render an "Export" link in the kebab actions if chart data is present but prop is set to `false`', () => {
cy.mount(AnalyticsChart, {
props: {
allowCsvExport: false,
goToExplore: 'https://cloud.konghq.tech/us/analytics/explorer',
chartData: exploreResult,
chartOptions: {
type: 'timeseries_line',
},
chartTitle: 'Requests',
},
})
cy.getTestId('csv-export-button').should('not.exist')

cy.getTestId('chart-action-menu').should('exist')

// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.getTestId('chart-action-menu').click().then(() => {
cy.getTestId('chart-jump-to-explore').should('exist')
cy.getTestId('csv-export-modal').should('not.exist')
})
})

it('Renders an "Export" button, and tabulated data in the modal preview', () => {
Expand All @@ -280,10 +314,13 @@ describe('<AnalyticsChart />', () => {
},
})

cy.getTestId('csv-export-button').should('exist')
cy.getTestId('chart-action-menu').should('exist')

// eslint-disable-next-line cypress/unsafe-to-chain-command
cy.getTestId('csv-export-button').click().then(() => {
cy.getTestId('chart-action-menu').click().then(() => {
cy.getTestId('chart-jump-to-explore').should('not.exist')

cy.getTestId('csv-export-button').click()
cy.getTestId('csv-export-modal').should('exist')
cy.get('.modal-content .vitals-table').should('exist')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,55 @@
</KTooltip>
</div>
<div
v-if="allowCsvExport && hasValidChartData"
v-if="allowCsvExport && hasValidChartData && !hasKebabMenuAccess"
class="chart-export-button"
>
<CsvExportButton
:data="rawChartData"
:filename-prefix="filenamePrefix"
/>
</div>
<!-- More actions menu -->
<KDropdown
v-if="hasKebabMenuAccess && hasMenuOptions"
class="dropdown"
data-testid="chart-action-menu"
>
<MoreIcon
:color="KUI_COLOR_TEXT_NEUTRAL"
:size="KUI_ICON_SIZE_40"
/>
<template #items>
<KDropdownItem
v-if="!!goToExplore"
data-testid="chart-jump-to-explore"
>
<a :href="goToExplore">
{{ i18n.t('jumpToExplore') }}
</a>
</KDropdownItem>
<KDropdownItem
v-if="allowCsvExport && hasValidChartData"
class="chart-export-button"
data-testid="chart-csv-export"
>
<span
class="chart-export-trigger"
data-testid="csv-export-button"
@click="exportCsv()"
>
{{ i18n.t('csvExport.exportButton') }}
</span>
</KDropdownItem>
</template>
</KDropdown>
<!-- Keep outside of dropdown, so we can independently affect its visibility -->
<CsvExportModal
v-if="exportModalVisible"
:chart-data="rawChartData"
:filename="csvFilename"
@toggle-modal="setExportModalVisibility"
/>
</div>
<KEmptyState
v-if="!hasValidChartData"
Expand Down Expand Up @@ -110,13 +151,14 @@ import { ChartLegendPosition } from '../enums'
import StackedBarChart from './chart-types/StackedBarChart.vue'
import DoughnutChart from './chart-types/DoughnutChart.vue'
import type { PropType } from 'vue'
import { computed, provide, toRef } from 'vue'
import { computed, provide, toRef, ref } from 'vue'
import { msToGranularity } from '@kong-ui-public/analytics-utilities'
import type { AbsoluteTimeRangeV4, ExploreAggregations, ExploreResultV4, GranularityValues } from '@kong-ui-public/analytics-utilities'
import { hasMillisecondTimestamps, defaultStatusCodeColors } from '../utils'
import TimeSeriesChart from './chart-types/TimeSeriesChart.vue'
import { KUI_COLOR_TEXT_WARNING, KUI_ICON_SIZE_40 } from '@kong/design-tokens'
import { WarningIcon } from '@kong/icons'
import { KUI_COLOR_TEXT_NEUTRAL, KUI_COLOR_TEXT_WARNING, KUI_ICON_SIZE_40 } from '@kong/design-tokens'
import { MoreIcon, WarningIcon } from '@kong/icons'
import CsvExportModal from './CsvExportModal.vue'
import CsvExportButton from './CsvExportButton.vue'
const props = defineProps({
Expand All @@ -125,6 +167,11 @@ const props = defineProps({
required: false,
default: false,
},
goToExplore: {
type: String,
required: false,
default: '',
},
chartData: {
type: Object as PropType<ExploreResultV4>,
required: true,
Expand Down Expand Up @@ -190,6 +237,9 @@ const emit = defineEmits<{
}>()
const { i18n } = composables.useI18n()
const { evaluateFeatureFlag } = composables.useEvaluateFeatureFlag()
const hasKebabMenuAccess = evaluateFeatureFlag('ma-3043-analytics-chart-kebab-menu', false)
const rawChartData = toRef(props, 'chartData')
Expand All @@ -211,6 +261,15 @@ const computedChartData = computed(() => {
).value
})
const exportModalVisible = ref(false)
const setExportModalVisibility = (val: boolean) => {
exportModalVisible.value = val
}
const csvFilename = computed<string>(() => props.filenamePrefix || i18n.t('csvExport.defaultFilename'))
const exportCsv = () => {
setExportModalVisibility(true)
}
const timeRangeMs = computed<number | undefined>(() => {
if (!props.chartData?.meta) {
return 0
Expand Down Expand Up @@ -302,6 +361,8 @@ const showChartHeader = computed(() => {
return (hasValidChartData.value && resultSetTruncated.value && maxEntitiesShown.value) || props.chartTitle || (props.allowCsvExport && hasValidChartData.value)
})
const hasMenuOptions = computed(() => (props.allowCsvExport && hasValidChartData.value) || !!props.goToExplore)
const timeSeriesGranularity = computed<GranularityValues>(() => {
if (!props.chartData.meta.granularity_ms) {
Expand Down Expand Up @@ -413,6 +474,31 @@ provide('legendPosition', toRef(props, 'legendPosition'))
margin-left: var(--kui-space-50, $kui-space-50);
margin-top: var(--kui-space-10, $kui-space-10);
}
// Action menu
.dropdown {
display: flex;
margin-left: var(--kui-space-auto, $kui-space-auto);
margin-right: var(--kui-space-0, $kui-space-0);
li.k-dropdown-item {
a {
text-decoration: none;
}
}
a {
color: $kui-color-text;
&:hover {
color: $kui-color-text;
text-decoration: none;
}
}
&:hover {
cursor: pointer;
}
}
}
</style>
2 changes: 2 additions & 0 deletions packages/analytics/analytics-chart/src/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useExploreResultToDatasets from './useExploreResultToDatasets'
import useExploreResultToTimeDataset from './useExploreResultToTimeDatasets'
import useReportChartDataForSynthetics from './useReportChartDataForSynthetics'
import useTranslatedUnits from './useTranslatedUnits'
import useEvaluateFeatureFlag from './useEvauluateFeatureFlag'

// All composables must be exported as part of the default object for Cypress test stubs
export default {
Expand All @@ -23,4 +24,5 @@ export default {
useI18n,
useReportChartDataForSynthetics,
useTranslatedUnits,
useEvaluateFeatureFlag,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { AnalyticsBridge } from '@kong-ui-public/analytics-utilities'
import { inject } from 'vue'
import { INJECT_QUERY_PROVIDER } from '../constants'

export default function useEvaluateFeatureFlag() {

const queryBridge: AnalyticsBridge | undefined = inject(INJECT_QUERY_PROVIDER)

const evaluateFeatureFlag = (key: string, defaultValue: boolean) => {
if (!queryBridge) {
return defaultValue
}
return queryBridge.evaluateFeatureFlagFn(key, defaultValue)
}

return {
evaluateFeatureFlag,
}
}
1 change: 1 addition & 0 deletions packages/analytics/analytics-chart/src/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const INJECT_QUERY_PROVIDER = 'analytics-query-provider'
1 change: 1 addition & 0 deletions packages/analytics/analytics-chart/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"entityNoName": "no-name",
"debug": "debug",
"total": "Total",
"jumpToExplore": "Jump to Explore",
"chartUnits": {
"ms": "ms",
"bytes": "Byte{plural}",
Expand Down
1 change: 1 addition & 0 deletions packages/analytics/analytics-chart/src/types/chart-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface LegendValueEntry {
*/
export interface EnhancedLegendItem extends LegendItem {
value: LegendValueEntry
text: string
}

/**
Expand Down

0 comments on commit ed6a72e

Please sign in to comment.