Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RUM Dashboard] Chart breakdowns #69420

Merged
merged 93 commits into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
f9c20a1
added rum filters and tab
shahzad31 Jun 3, 2020
1f75371
update
shahzad31 Jun 3, 2020
f1c9bcf
move range filter into common
shahzad31 Jun 5, 2020
9f615df
Merge branch 'master' into rum-filters
shahzad31 Jun 5, 2020
2214001
fix issue in tab condition
shahzad31 Jun 5, 2020
eaf461c
Merge branch 'master' into rum-filters
shahzad31 Jun 5, 2020
95b510b
add clinet
shahzad31 Jun 5, 2020
b818fbd
update
shahzad31 Jun 8, 2020
ac24241
Merge branch 'master' into rum-filters
shahzad31 Jun 8, 2020
3cd29fb
added transactiont type filter
shahzad31 Jun 8, 2020
bae67c2
Merge branch 'rum-filters' into client-metrics
shahzad31 Jun 8, 2020
5a6c41a
update
shahzad31 Jun 8, 2020
a3c83cc
Merge branch 'master' into client-metrics
shahzad31 Jun 8, 2020
60ac2eb
update
shahzad31 Jun 9, 2020
a587d82
Merge branch 'master' into client-metrics
shahzad31 Jun 9, 2020
6496237
Merge branch 'master' into client-metrics
shahzad31 Jun 10, 2020
fd6d22a
update
shahzad31 Jun 10, 2020
89a93ed
update
shahzad31 Jun 10, 2020
c1a9ef2
added filter
shahzad31 Jun 10, 2020
e062152
Merge branch 'master' into client-metrics
shahzad31 Jun 11, 2020
d77652c
update
shahzad31 Jun 11, 2020
1d0afcc
update
shahzad31 Jun 11, 2020
f1259a7
fixed
shahzad31 Jun 11, 2020
fb0782b
Merge branch 'master' into client-metrics
shahzad31 Jun 11, 2020
638920d
added rum tests
shahzad31 Jun 11, 2020
b0b11e5
Merge branch 'master' into client-metrics
shahzad31 Jun 12, 2020
9dc10c5
update and added reset zoom button
shahzad31 Jun 12, 2020
b2b444a
snapshot
shahzad31 Jun 12, 2020
6a9749e
Merge branch 'master' into client-metrics
shahzad31 Jun 12, 2020
8702dc9
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 14, 2020
3c8f802
added breakdown filter button
shahzad31 Jun 15, 2020
ebf9761
Merge branch 'master' into client-metrics
shahzad31 Jun 15, 2020
e72de7b
update
shahzad31 Jun 15, 2020
746ef6f
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 15, 2020
a0176da
improve responsiveness
shahzad31 Jun 15, 2020
3c769a7
update
shahzad31 Jun 15, 2020
9e0b508
rename impression treds
shahzad31 Jun 15, 2020
c7d1521
update tooltip
shahzad31 Jun 15, 2020
1d94b3f
update
shahzad31 Jun 15, 2020
483d8fd
Merge branch 'master' into client-metrics
shahzad31 Jun 15, 2020
9ffcabb
Merge branch 'master' into client-metrics
shahzad31 Jun 16, 2020
ee3616e
update test
shahzad31 Jun 16, 2020
7e18010
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 16, 2020
20c779e
Suggested design improvements
formgeist Jun 16, 2020
bcb8ff8
update
shahzad31 Jun 17, 2020
1b8ef95
Merge branch 'master' into client-metrics
shahzad31 Jun 17, 2020
a05e6d6
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 17, 2020
352621a
fix types
shahzad31 Jun 18, 2020
a0a7a44
Merge branch 'master' into client-metrics
shahzad31 Jun 18, 2020
7056e40
fix e2e
shahzad31 Jun 18, 2020
92098c0
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 18, 2020
fc33078
fix issue with rum timing
shahzad31 Jun 18, 2020
9529d76
update snapshot
shahzad31 Jun 18, 2020
0733c7c
Merge pull request #2 from formgeist/client-metrics-ui-fixes
shahzad31 Jun 18, 2020
d3149ea
update snapshot
shahzad31 Jun 18, 2020
14e8851
fix types
shahzad31 Jun 18, 2020
9d143a5
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 18, 2020
b232189
update
shahzad31 Jun 18, 2020
627e217
Merge branch 'master' into client-metrics
shahzad31 Jun 18, 2020
bff7fe9
Merge branch 'master' into client-metrics
elasticmachine Jun 18, 2020
7206ffc
Merge branch 'client-metrics' of https://github.com/shahzad31/kibana …
shahzad31 Jun 18, 2020
4ba1889
fix issue came out of bad merge
shahzad31 Jun 18, 2020
bb2ae2e
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 18, 2020
a15b3f5
Merge branch 'client-metrics' into chart-breakdowns
shahzad31 Jun 18, 2020
291c30c
update
shahzad31 Jun 18, 2020
9ab0659
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 18, 2020
aaf36d7
commit
shahzad31 Jun 19, 2020
b5746f3
test
shahzad31 Jun 21, 2020
f9fe8e3
up
shahzad31 Jun 22, 2020
640695f
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 23, 2020
5892c9d
fix theme
shahzad31 Jun 23, 2020
ba2823d
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 23, 2020
5d267fe
update
shahzad31 Jun 25, 2020
986e9a5
upate
shahzad31 Jun 25, 2020
3797388
update
shahzad31 Jun 25, 2020
1690d15
update
shahzad31 Jun 25, 2020
c5b71a6
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 25, 2020
a11f183
update
shahzad31 Jun 25, 2020
9df90e9
added types
shahzad31 Jun 25, 2020
1b5af10
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 25, 2020
4b90edb
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 26, 2020
059ac73
Fix PR feedback
shahzad31 Jun 26, 2020
2d686b0
PR feedbck
shahzad31 Jun 26, 2020
e45f12f
update i18c
shahzad31 Jun 26, 2020
f12173b
update scenerios
shahzad31 Jun 26, 2020
b1573bd
remove unnecessary changes
shahzad31 Jun 26, 2020
e5f6628
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 26, 2020
041d90c
Merge branch 'master' into chart-breakdowns
elasticmachine Jun 26, 2020
a5ca6e2
Merge branch 'master' into chart-breakdowns
elasticmachine Jun 29, 2020
12937e1
update bdd spec
shahzad31 Jun 29, 2020
623a800
Merge branch 'chart-breakdowns' of https://github.com/shahzad31/kiban…
shahzad31 Jun 29, 2020
9d6ecd9
Merge branch 'master' into chart-breakdowns
shahzad31 Jun 29, 2020
fe89c69
update scenerios
shahzad31 Jun 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions x-pack/plugins/apm/e2e/cypress/integration/rum_dashboard.feature
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,33 @@ Feature: RUM Dashboard
When the user inspects the real user monitoring tab
Then should redirect to rum dashboard
And should have correct client metrics

Scenario: Rum page filters
Given a user click the filter
When the user select the filter
And user applies the selected filter
Then it filters the client metrics
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wdyt about this?

Scenario: Rum page filters
    When the user filters by "put-here-your-filter-name"
    Then the client metrics are filtered

The Given part could not be necessary, but the When one is key:

  • Given: preparation of the test before the scenario
  • When: the action that triggers the scenario
  • Then: the outcome/output to be verified after the scenario

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have updated this one as well.


Scenario: Page load distribution percentiles
Given a user browses the APM UI application for RUM Data
When the user inspects the real user monitoring tab
Then should redirect to rum dashboard
Comment on lines +18 to +20
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you take a look, these 3 steps all-together have been tested in the above scenario. What do you think about this scenario, rephrased:

Scenario: Page load distribution
Given a valid APM user
When the APM user inspects the RUM dashboard
Then the "page load" chart includes "percentile"
   And the "page load" chart includes "tooltip"
   And the "page load" chart includes "chart legend"

Using quotes in a step generates a generic method in the implementation code, where the quoted string is replaced by a variable:

Then(`the "{string}" chart includes {string}`, (chartName, element) => {
  // cypress code using "chartName" and "element" variables
  // i.e. locate the "chartName" chart and check for the "element"
})

And should display percentile for page load chart

Scenario: Page load distribution chart tooltip
Given a user browses the APM UI application for RUM Data
When the user inspects the real user monitoring tab
Then should redirect to rum dashboard
And should display tooltip on hover

Scenario: Page load distribution chart legends
Given a user browses the APM UI application for RUM Data
When the user inspects the real user monitoring tab
Then should redirect to rum dashboard
And should display chart legend

Scenario: Breakdown filter
Given a user click page load breakdown filter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is another scenario

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a BDD sequence, there is a Given/When/Then pattern that should be repeated across different scenarios.

When the user selected the breakdown
Then breakdown series should appear in chart

16 changes: 15 additions & 1 deletion x-pack/plugins/apm/e2e/cypress/integration/snapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,23 @@ module.exports = {
},
"RUM Dashboard": {
"Client metrics": {
"1": "62",
"1": "62 ",
"2": "0.07 sec",
"3": "0.01 sec"
},
"Page load distribution percentiles": {
"1": "50th",
"2": "75th",
"3": "90th",
"4": "95th"
},
"Rum page filters": {
"1": "15 ",
"2": "0.07 sec",
"3": "0.01 sec"
},
"Page load distribution chart legends": {
"1": "Overall"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 60 * 1000;

Given(`a user click page load breakdown filter`, () => {
// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiStat__title-isLoading').should('not.be.visible');
const breakDownBtn = cy.get('[data-cy=breakdown-popover_pageLoad]');
breakDownBtn.click();
});

When(`the user selected the breakdown`, () => {
cy.get('[data-cy=filter-breakdown-item_Browser]').click();
// click outside popover to close it
cy.get('[data-cy=pageLoadDist]').click();
});

Then(`breakdown series should appear in chart`, () => {
cy.get('.euiLoadingChart').should('not.be.visible');
cy.get('div.echLegendItem__label[title=Chrome] ')
.invoke('text')
.should('eq', 'Chrome');
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';
import { loginAndWaitForPage } from '../../../integration/helpers';

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 60 * 1000;

Given(`a user browses the APM UI application for RUM Data`, () => {
// open service overview page
const RANGE_FROM = 'now-24h';
const RANGE_TO = 'now';
loginAndWaitForPage(`/app/apm#/services`, { from: RANGE_FROM, to: RANGE_TO });
});

When(`the user inspects the real user monitoring tab`, () => {
// click rum tab
cy.get(':contains(Real User Monitoring)', { timeout: DEFAULT_TIMEOUT })
.last()
.click({ force: true });
});

Then(`should redirect to rum dashboard`, () => {
cy.url().should('contain', `/app/apm#/rum-overview`);
});

Then(`should have correct client metrics`, () => {
const clientMetrics = '[data-cy=client-metrics] .euiStat__title';

// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiStat__title-isLoading').should('not.be.visible');

cy.get(clientMetrics).eq(2).invoke('text').snapshot();

cy.get(clientMetrics).eq(1).invoke('text').snapshot();

cy.get(clientMetrics).eq(0).invoke('text').snapshot();
});

Then(`should display percentile for page load chart`, () => {
const pMarkers = '[data-cy=percentile-markers] span';

cy.get('.euiLoadingChart').should('be.visible');

// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiStat__title-isLoading').should('not.be.visible');

cy.get(pMarkers).eq(0).invoke('text').snapshot();

cy.get(pMarkers).eq(1).invoke('text').snapshot();

cy.get(pMarkers).eq(2).invoke('text').snapshot();

cy.get(pMarkers).eq(3).invoke('text').snapshot();
});

Then(`should display chart legend`, () => {
const chartLegend = 'div.echLegendItem__label';

// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiLoadingChart').should('not.be.visible');

cy.get(chartLegend).eq(0).invoke('text').snapshot();
});

Then(`should display tooltip on hover`, () => {
cy.get('.euiLoadingChart').should('not.be.visible');

const pMarkers = '[data-cy=percentile-markers] span.euiToolTipAnchor';

// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiLoadingChart').should('not.be.visible');

const marker = cy.get(pMarkers).eq(0);
marker.invoke('show');
marker.trigger('mouseover', { force: true });
cy.get('span[data-cy=percentileTooltipTitle]').should('be.visible');
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,26 @@
*/

import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps';
import { loginAndWaitForPage } from '../../integration/helpers';

/** The default time in ms to wait for a Cypress command to complete */
export const DEFAULT_TIMEOUT = 60 * 1000;

Given(`a user browses the APM UI application for RUM Data`, () => {
// open service overview page
const RANGE_FROM = 'now-24h';
const RANGE_TO = 'now';
loginAndWaitForPage(`/app/apm#/services`, { from: RANGE_FROM, to: RANGE_TO });
Given(`a user click the filter`, () => {
// wait for all loading to finish
cy.get('kbnLoadingIndicator').should('not.be.visible');
cy.get('.euiStat__title-isLoading').should('not.be.visible');
cy.get('#local-filter-os').click();
});

When(`the user inspects the real user monitoring tab`, () => {
// click rum tab
cy.get(':contains(Real User Monitoring)', { timeout: DEFAULT_TIMEOUT })
.last()
.click({ force: true });
When(`the user select the filter`, () => {
cy.get('button.euiSelectableListItem[title="Mac OS X"]').click();
});

Then(`should redirect to rum dashboard`, () => {
cy.url().should('contain', `/app/apm#/rum-overview`);
Then(`user applies the selected filter`, () => {
cy.get('[data-cy=applyFilter]').click();
});

Then(`should have correct client metrics`, () => {
Then(`it filters the client metrics`, () => {
const clientMetrics = '[data-cy=client-metrics] .euiStat__title';

// wait for all loading to finish
Expand Down
17 changes: 15 additions & 2 deletions x-pack/plugins/apm/e2e/ingest-data/replay.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const pLimit = require('p-limit');
const pRetry = require('p-retry');
const { argv } = require('yargs');
const ora = require('ora');
const userAgents = require('./user_agents');
const userIps = require('./rum_ips');

const APM_SERVER_URL = argv.serverUrl;
const SECRET_TOKEN = argv.secretToken;
Expand Down Expand Up @@ -66,14 +68,23 @@ function incrementSpinnerCount({ success }) {

spinner.text = `Remaining: ${remaining}. Succeeded: ${requestProgress.succeeded}. Failed: ${requestProgress.failed}.`;
}

let iterIndex = 0;
async function insertItem(item) {
try {
const url = `${APM_SERVER_URL}${item.url}`;
const headers = {
'content-type': 'application/x-ndjson',
};

if (item.url === '/intake/v2/rum/events') {
if (iterIndex === userAgents.length) {
iterIndex = 0;
}
headers['User-Agent'] = userAgents[iterIndex];
headers['X-Forwarded-For'] = userIps[iterIndex];
iterIndex++;
}

if (SECRET_TOKEN) {
headers.Authorization = `Bearer ${SECRET_TOKEN}`;
}
Expand Down Expand Up @@ -113,7 +124,9 @@ async function init() {
items.map(async (item) => {
try {
// retry 5 times with exponential backoff
await pRetry(() => limit(() => insertItem(item)), { retries: 5 });
await pRetry(() => limit(() => insertItem(item)), {
retries: 5,
});
incrementSpinnerCount({ success: true });
} catch (e) {
incrementSpinnerCount({ success: false });
Expand Down
19 changes: 19 additions & 0 deletions x-pack/plugins/apm/e2e/ingest-data/rum_ips.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

const IPS = [
'89.191.86.214', // check24.de
'167.40.79.24', // canada.ca
'151.101.130.217', // elastic.co
'185.143.68.17',
'151.101.130.217',
'185.143.68.17',
'185.143.68.17',
'151.101.130.217',
'185.143.68.17',
];

module.exports = IPS;
23 changes: 23 additions & 0 deletions x-pack/plugins/apm/e2e/ingest-data/user_agents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

/* eslint-disable no-console */

/* eslint-disable import/no-extraneous-dependencies */

const UserAgents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',
'Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/69.0.3497.105 Mobile/15E148 Safari/605.1',
'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1',
'Mozilla/5.0 (Linux; Android 7.0; Pixel C Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/52.0.2743.98 Safari/537.36',
'Mozilla/5.0 (X11; CrOS x86_64 8172.45.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.64 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9',
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1',
'Mozilla/5.0 (CrKey armv7l 1.5.16041) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.0 Safari/537.36',
];

module.exports = UserAgents;
4 changes: 2 additions & 2 deletions x-pack/plugins/apm/public/components/app/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { ServiceOverview } from '../ServiceOverview';
import { TraceOverview } from '../TraceOverview';
import { RumOverview } from '../RumDashboard';
import { RumOverviewLink } from '../../shared/Links/apm/RumOverviewLink';
import { EndUserExperienceLabel } from '../RumDashboard/translations';
import { I18LABELS } from '../RumDashboard/translations';

function getHomeTabs({
serviceMapEnabled = true,
Expand Down Expand Up @@ -111,7 +111,7 @@ export function Home({ tab }: Props) {
<EuiTitle size="l">
<h1>
{selectedTab.name === 'rum-overview'
? EndUserExperienceLabel
? I18LABELS.endUserExperience
: 'APM'}
</h1>
</EuiTitle>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { BreakdownGroup } from './BreakdownGroup';
import { BreakdownItem } from '../../../../../typings/ui_filters';
import {
CLIENT_GEO_COUNTRY_ISO_CODE,
USER_AGENT_DEVICE,
USER_AGENT_NAME,
USER_AGENT_OS,
} from '../../../../../common/elasticsearch_fieldnames';

interface Props {
id: string;
selectedBreakdowns: BreakdownItem[];
onBreakdownChange: (values: BreakdownItem[]) => void;
}

export const BreakdownFilter = ({
id,
selectedBreakdowns,
onBreakdownChange,
}: Props) => {
const categories: BreakdownItem[] = [
{
name: 'Browser',
type: 'category',
count: 0,
selected: selectedBreakdowns.some(({ name }) => name === 'Browser'),
fieldName: USER_AGENT_NAME,
},
{
name: 'OS',
type: 'category',
count: 0,
selected: selectedBreakdowns.some(({ name }) => name === 'OS'),
fieldName: USER_AGENT_OS,
},
{
name: 'Device',
type: 'category',
count: 0,
selected: selectedBreakdowns.some(({ name }) => name === 'Device'),
fieldName: USER_AGENT_DEVICE,
},
{
name: 'Location',
type: 'category',
count: 0,
selected: selectedBreakdowns.some(({ name }) => name === 'Location'),
fieldName: CLIENT_GEO_COUNTRY_ISO_CODE,
},
];

return (
<BreakdownGroup
id={id}
items={categories}
onChange={(selValues: BreakdownItem[]) => {
onBreakdownChange(selValues);
}}
/>
);
};
Loading