diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js new file mode 100644 index 0000000000000000000000000000000000000000..7d30303aa43e1d03cffa54f8db197a3d1e617831 --- /dev/null +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/api.js @@ -0,0 +1,31 @@ +import { AI_METRICS } from '~/analytics/shared/constants'; + +/** + * @typedef {Object} TableMetric + * @property {String} identifier - Identifier for the specified metric + * @property {String} value - Display friendly value + */ + +/** + * @typedef {Object} AiMetricItem + * @property {Float} codeSuggestionsUsageRate - Usage rate % + */ + +/** + * @typedef {Object} AiMetricResponseItem + * @property {TableMetric} code_suggestions_usage_rate + */ + +/** + * Takes the raw `aiMetrics` graphql response and prepares the data for display + * in the tiled column chart. + * + * @param {AiMetricItem} data + * @returns {AiMetricResponseItem} AI metrics ready for rendering in the dashboard + */ +export const extractGraphqlAiData = ({ codeSuggestionsUsageRate = '-' } = {}) => ({ + [AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE]: { + identifier: AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, + value: codeSuggestionsUsageRate, + }, +}); diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/components/metric_table.vue b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/components/metric_table.vue index dfc0e8428df81018496ae08c1f4ec40a6f9b499b..9fec0a12ca9955f419148568e2fb148912fbc3fb 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/components/metric_table.vue +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/components/metric_table.vue @@ -1,7 +1,7 @@ <script> import { GlTableLite, GlSkeletonLoader } from '@gitlab/ui'; import { toYmd } from '~/analytics/shared/utils'; -import { AI_METRICS } from '~/analytics/shared/constants'; +import { dasherize } from '~/lib/utils/text_utility'; import { BUCKETING_INTERVAL_ALL } from '../../graphql/constants'; import VulnerabilitiesQuery from '../graphql/vulnerabilities.query.graphql'; import FlowMetricsQuery from '../graphql/flow_metrics.query.graphql'; @@ -31,6 +31,7 @@ import { extractGraphqlFlowData, extractQueryResponseFromNamespace, } from '../../api'; +import { extractGraphqlAiData } from '../api'; const NOW = generateValueStreamDashboardStartDate(); const DASHBOARD_TIME_PERIODS = generateDateRanges(NOW); @@ -87,7 +88,7 @@ export default { methods: { rowAttributes({ metric: { identifier } }) { return { - 'data-testid': `ai-impact-metric-${identifier.replaceAll('_', '-')}`, + 'data-testid': `ai-impact-metric-${dasherize(identifier)}`, }; }, @@ -184,16 +185,13 @@ export default { }, }); - const { codeSuggestionsUsageRate = '-' } = extractQueryResponseFromNamespace({ + const responseData = extractQueryResponseFromNamespace({ result, resultKey: 'aiMetrics', }); return { ...timePeriod, - [AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE]: { - identifier: AI_METRICS.CODE_SUGGESTIONS_USAGE_RATE, - value: codeSuggestionsUsageRate, - }, + ...extractGraphqlAiData(responseData), }; }, }, diff --git a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/utils.js b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/utils.js index 258f870de3a931f3d9c534825dc96ccafd00fe0c..55a981c68870bb9eef19198574a2259715f61d3d 100644 --- a/ee/app/assets/javascripts/analytics/dashboards/ai_impact/utils.js +++ b/ee/app/assets/javascripts/analytics/dashboards/ai_impact/utils.js @@ -18,8 +18,16 @@ const getStartOfMonth = (now) => dateAtFirstDayOfMonth(getStartOfDay(now)); * @param {Date} now Current date * @returns {Array} Tuple of time periods */ -export const generateDateRanges = (now) => - [1, 2, 3, 4, 5].reduce( +export const generateDateRanges = (now) => { + const currentMonth = { + key: 'this-month', + label: monthInWords(now, true), + start: getStartOfMonth(now), + end: now, + thClass: 'gl-w-10p', + }; + + return [1, 2, 3, 4, 5].reduce( (acc, nMonth) => { const thisMonthStart = getStartOfMonth(now); const start = nMonthsBefore(thisMonthStart, nMonth); @@ -35,16 +43,9 @@ export const generateDateRanges = (now) => ...acc, ]; }, - [ - { - key: 'this-month', - label: monthInWords(now, true), - start: getStartOfMonth(now), - end: now, - thClass: 'gl-w-10p', - }, - ], + [currentMonth], ); +}; /** * Generates all the table columns based on the given date. @@ -63,8 +64,6 @@ export const generateTableColumns = (now) => [ key: 'change', label: sprintf(__('Change (%%)')), description: __('Past 6 Months'), - start: nMonthsBefore(getStartOfMonth(now), 6), - end: nSecondsBefore(getStartOfMonth(now), 1), thClass: 'gl-w-20p', }, ]; diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap index 1bfb1592a075f6c2cd8e4cff51182b7ef2ecf100..f772e6098e8594e1a14d1f279b6e4df98e9b2a65 100644 --- a/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/__snapshots__/utils_spec.js.snap @@ -239,10 +239,8 @@ Array [ }, Object { "description": "Past 6 Months", - "end": 2020-02-29T23:59:59.000Z, "key": "change", "label": "Change (%)", - "start": 2019-09-01T00:00:00.000Z, "thClass": "gl-w-20p", }, ] @@ -299,10 +297,8 @@ Array [ }, Object { "description": "Past 6 Months", - "end": 2021-06-30T23:59:59.000Z, "key": "change", "label": "Change (%)", - "start": 2021-01-01T00:00:00.000Z, "thClass": "gl-w-20p", }, ] @@ -359,10 +355,8 @@ Array [ }, Object { "description": "Past 6 Months", - "end": 2021-02-28T23:59:59.000Z, "key": "change", "label": "Change (%)", - "start": 2020-09-01T00:00:00.000Z, "thClass": "gl-w-20p", }, ] diff --git a/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js new file mode 100644 index 0000000000000000000000000000000000000000..472fdda6199a62dd1dafb380a09b85e15c61c329 --- /dev/null +++ b/ee/spec/frontend/analytics/dashboards/ai_impact/api_spec.js @@ -0,0 +1,33 @@ +import { extractGraphqlAiData } from 'ee/analytics/dashboards/ai_impact/api'; + +describe('AI impact dashboard api', () => { + describe('extractGraphqlAiData', () => { + it('returns `-` when the payload is undefined', () => { + expect(extractGraphqlAiData()).toEqual({ + code_suggestions_usage_rate: { + identifier: 'code_suggestions_usage_rate', + value: '-', + }, + }); + }); + + it('returns `-` when the value is undefined', () => { + expect(extractGraphqlAiData({ codeSuggestionsUsageRate: undefined })).toEqual({ + code_suggestions_usage_rate: { + identifier: 'code_suggestions_usage_rate', + value: '-', + }, + }); + }); + + it('formats the value for the table', () => { + const value = 33.33; + expect(extractGraphqlAiData({ codeSuggestionsUsageRate: value })).toEqual({ + code_suggestions_usage_rate: { + identifier: 'code_suggestions_usage_rate', + value, + }, + }); + }); + }); +});