[8.x] Implement new nav hierarchy for stateful/cloud (#192805) (#194912)

# Backport

This will backport the following commits from `main` to `8.x`:
- [Implement new nav hierarchy for stateful/cloud
(#192805)](https://github.com/elastic/kibana/pull/192805)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Panagiota
Mitsopoulou","email":"panagiota.mitsopoulou@elastic.co"},"sourceCommit":{"committedDate":"2024-10-04T08:02:57Z","message":"Implement
new nav hierarchy for stateful/cloud (#192805)\n\n<strike>Depends on
https://github.com/elastic/kibana/issues/193526,\r\nWON'T
FIX</strike>\r\n\r\nFixes
https://github.com/elastic/kibana/issues/192803\r\nFixes
https://github.com/elastic/kibana/issues/191509\r\n\r\nThis PR updates
the nav hierarchy for stateful/cloud and changes the\r\n`accordion` to
`panelOpener`. The menu items have been updated according\r\nto the
Figma file and the discussions happening in
this\r\n[issue](https://github.com/elastic/kibana/issues/192050). I took
a video\r\nbelow of how the new navigation looks like with the new
changes\r\n\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e73c8dd9-b674-4146-bcde-443490569502\r\n\r\n##
What was changed\r\n- AI & ML menu is removed and split into\r\n - `AI
Assistant`\r\n- `Machine learning`: this menu was already present in the
footer, it\r\nwas moved in the body (after Infrastucture)\r\n-
`Applications` now opens a `panelOpener` instead of an `accordion`\r\n -
Synthetics was moved to a new section\r\n - “User Experience” was
renamed to “User experience” \r\n- `Infrastucture` now opens a
`panelOpener` instead of an `accordion`\r\n - Universal Profiling was
moved to a separate section below\r\n - Metrics Explorer was renamed to
Metrics explorer\r\n- `Machine learning` now opens a `panelOpener`
instead of an `accordion`\r\n- `Supplied Configurations` was added under
the Machine learning >\r\nAnomaly Detection section.\r\n- The machine
learning `link:\r\n'securitySolutionUI:machine_learning-landing'` was
completely removed.\r\nClicking on the `Machine learning` link will
slide out the panel instead\r\n(same behavior with clicking on the
icon). More details about why I\r\nremoved
this\r\n[here](https://github.com/elastic/kibana/pull/192805#issuecomment-2359368851)\r\n
- Use sentence/case for the menu items\r\n- `Other tools` now opens a
`panelOpener` instead of an `accordion`\r\n - Logs anomalies was added
here\r\n - Logs categories was added here\r\n - Visualize library was
added\r\n- Clicking on the 1st level menu items (Applications,
Infrastructure,\r\nMachine learning, Other tools) toggles the panel on
the right\r\n(arrowRight).\r\n- The icon was changed from the four small
squares to the right-facing\r\ncaret\r\n- The sub-nav menu slides out to
the right whenever the label OR the\r\nicon are clicked\r\n- `Getting
started` in the footer was renamed to `Add data`\r\n- `Data Set Quality`
was added under `Stack Management > Data` section\r\nbelow `Index
Management`\r\n\r\n\r\n## Functional Tests\r\nSome tests have been added
that test:\r\n- toggling of the panel when clicking on the link
button\r\n- `AI assistant` changes\r\n- `Infrastructure` changes\r\n-
`Other Tools` changes\r\n- `Machine Learning` changes\r\n\r\n\r\n## What
this PR doesn't do\r\nI faced some issues with the footer, so footer
will be separately\r\nhandled in this
[issue](https://github.com/elastic/kibana/issues/192865)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>\r\nCo-authored-by: Sébastien
Loix <sebastien.loix@elastic.co>\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Dominique Clarke
<dominique.clarke@elastic.co>","sha":"ab715099b0310019e44ed203bd0b5b3fab50f650","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor","ci:project-deploy-observability","Team:obs-ux-management","v8.16.0"],"title":"Implement
new nav hierarchy for
stateful/cloud","number":192805,"url":"https://github.com/elastic/kibana/pull/192805","mergeCommit":{"message":"Implement
new nav hierarchy for stateful/cloud (#192805)\n\n<strike>Depends on
https://github.com/elastic/kibana/issues/193526,\r\nWON'T
FIX</strike>\r\n\r\nFixes
https://github.com/elastic/kibana/issues/192803\r\nFixes
https://github.com/elastic/kibana/issues/191509\r\n\r\nThis PR updates
the nav hierarchy for stateful/cloud and changes the\r\n`accordion` to
`panelOpener`. The menu items have been updated according\r\nto the
Figma file and the discussions happening in
this\r\n[issue](https://github.com/elastic/kibana/issues/192050). I took
a video\r\nbelow of how the new navigation looks like with the new
changes\r\n\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e73c8dd9-b674-4146-bcde-443490569502\r\n\r\n##
What was changed\r\n- AI & ML menu is removed and split into\r\n - `AI
Assistant`\r\n- `Machine learning`: this menu was already present in the
footer, it\r\nwas moved in the body (after Infrastucture)\r\n-
`Applications` now opens a `panelOpener` instead of an `accordion`\r\n -
Synthetics was moved to a new section\r\n - “User Experience” was
renamed to “User experience” \r\n- `Infrastucture` now opens a
`panelOpener` instead of an `accordion`\r\n - Universal Profiling was
moved to a separate section below\r\n - Metrics Explorer was renamed to
Metrics explorer\r\n- `Machine learning` now opens a `panelOpener`
instead of an `accordion`\r\n- `Supplied Configurations` was added under
the Machine learning >\r\nAnomaly Detection section.\r\n- The machine
learning `link:\r\n'securitySolutionUI:machine_learning-landing'` was
completely removed.\r\nClicking on the `Machine learning` link will
slide out the panel instead\r\n(same behavior with clicking on the
icon). More details about why I\r\nremoved
this\r\n[here](https://github.com/elastic/kibana/pull/192805#issuecomment-2359368851)\r\n
- Use sentence/case for the menu items\r\n- `Other tools` now opens a
`panelOpener` instead of an `accordion`\r\n - Logs anomalies was added
here\r\n - Logs categories was added here\r\n - Visualize library was
added\r\n- Clicking on the 1st level menu items (Applications,
Infrastructure,\r\nMachine learning, Other tools) toggles the panel on
the right\r\n(arrowRight).\r\n- The icon was changed from the four small
squares to the right-facing\r\ncaret\r\n- The sub-nav menu slides out to
the right whenever the label OR the\r\nicon are clicked\r\n- `Getting
started` in the footer was renamed to `Add data`\r\n- `Data Set Quality`
was added under `Stack Management > Data` section\r\nbelow `Index
Management`\r\n\r\n\r\n## Functional Tests\r\nSome tests have been added
that test:\r\n- toggling of the panel when clicking on the link
button\r\n- `AI assistant` changes\r\n- `Infrastructure` changes\r\n-
`Other Tools` changes\r\n- `Machine Learning` changes\r\n\r\n\r\n## What
this PR doesn't do\r\nI faced some issues with the footer, so footer
will be separately\r\nhandled in this
[issue](https://github.com/elastic/kibana/issues/192865)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>\r\nCo-authored-by: Sébastien
Loix <sebastien.loix@elastic.co>\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Dominique Clarke
<dominique.clarke@elastic.co>","sha":"ab715099b0310019e44ed203bd0b5b3fab50f650"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/192805","number":192805,"mergeCommit":{"message":"Implement
new nav hierarchy for stateful/cloud (#192805)\n\n<strike>Depends on
https://github.com/elastic/kibana/issues/193526,\r\nWON'T
FIX</strike>\r\n\r\nFixes
https://github.com/elastic/kibana/issues/192803\r\nFixes
https://github.com/elastic/kibana/issues/191509\r\n\r\nThis PR updates
the nav hierarchy for stateful/cloud and changes the\r\n`accordion` to
`panelOpener`. The menu items have been updated according\r\nto the
Figma file and the discussions happening in
this\r\n[issue](https://github.com/elastic/kibana/issues/192050). I took
a video\r\nbelow of how the new navigation looks like with the new
changes\r\n\r\n\r\n\r\nhttps://github.com/user-attachments/assets/e73c8dd9-b674-4146-bcde-443490569502\r\n\r\n##
What was changed\r\n- AI & ML menu is removed and split into\r\n - `AI
Assistant`\r\n- `Machine learning`: this menu was already present in the
footer, it\r\nwas moved in the body (after Infrastucture)\r\n-
`Applications` now opens a `panelOpener` instead of an `accordion`\r\n -
Synthetics was moved to a new section\r\n - “User Experience” was
renamed to “User experience” \r\n- `Infrastucture` now opens a
`panelOpener` instead of an `accordion`\r\n - Universal Profiling was
moved to a separate section below\r\n - Metrics Explorer was renamed to
Metrics explorer\r\n- `Machine learning` now opens a `panelOpener`
instead of an `accordion`\r\n- `Supplied Configurations` was added under
the Machine learning >\r\nAnomaly Detection section.\r\n- The machine
learning `link:\r\n'securitySolutionUI:machine_learning-landing'` was
completely removed.\r\nClicking on the `Machine learning` link will
slide out the panel instead\r\n(same behavior with clicking on the
icon). More details about why I\r\nremoved
this\r\n[here](https://github.com/elastic/kibana/pull/192805#issuecomment-2359368851)\r\n
- Use sentence/case for the menu items\r\n- `Other tools` now opens a
`panelOpener` instead of an `accordion`\r\n - Logs anomalies was added
here\r\n - Logs categories was added here\r\n - Visualize library was
added\r\n- Clicking on the 1st level menu items (Applications,
Infrastructure,\r\nMachine learning, Other tools) toggles the panel on
the right\r\n(arrowRight).\r\n- The icon was changed from the four small
squares to the right-facing\r\ncaret\r\n- The sub-nav menu slides out to
the right whenever the label OR the\r\nicon are clicked\r\n- `Getting
started` in the footer was renamed to `Add data`\r\n- `Data Set Quality`
was added under `Stack Management > Data` section\r\nbelow `Index
Management`\r\n\r\n\r\n## Functional Tests\r\nSome tests have been added
that test:\r\n- toggling of the panel when clicking on the link
button\r\n- `AI assistant` changes\r\n- `Infrastructure` changes\r\n-
`Other Tools` changes\r\n- `Machine Learning` changes\r\n\r\n\r\n## What
this PR doesn't do\r\nI faced some issues with the footer, so footer
will be separately\r\nhandled in this
[issue](https://github.com/elastic/kibana/issues/192865)\r\n\r\n---------\r\n\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>\r\nCo-authored-by: Sébastien
Loix <sebastien.loix@elastic.co>\r\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Dominique Clarke
<dominique.clarke@elastic.co>","sha":"ab715099b0310019e44ed203bd0b5b3fab50f650"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Panagiota Mitsopoulou <panagiota.mitsopoulou@elastic.co>
This commit is contained in:
Kibana Machine 2024-10-04 19:51:27 +10:00 committed by GitHub
parent 29be4a5bcc
commit c483318790
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 409 additions and 271 deletions

View file

@ -274,11 +274,6 @@ function validateNodeProps<
`[Chrome navigation] Error in node [${id}]. Only one of "href" or "cloudLink" can be provided.`
);
}
if (renderAs === 'panelOpener' && !link) {
throw new Error(
`[Chrome navigation] Error in node [${id}]. If renderAs is set to "panelOpener", a "link" must also be provided.`
);
}
if (renderAs === 'item' && !link && !onClick) {
throw new Error(
`[Chrome navigation] Error in node [${id}]. If renderAs is set to "item", a "link" or "onClick" must also be provided.`

View file

@ -61,6 +61,7 @@ export const NavigationItemOpenPanel: FC<Props> = ({ item, navigateToUrl, active
const isNotMobile = useIsWithinMinBreakpoint('s');
const isIconVisible = isNotMobile && !isSideNavCollapsed && !!children && children.length > 0;
const isActive = isActiveFromUrl(item.path, activeNodes);
const hasLandingPage = Boolean(href);
const itemClassNames = classNames(
'sideNavItem',
@ -73,30 +74,36 @@ export const NavigationItemOpenPanel: FC<Props> = ({ item, navigateToUrl, active
[`nav-item-id-${id}`]: id,
[`nav-item-isActive`]: isActive,
});
const buttonDataTestSubj = classNames(`panelOpener`, `panelOpener-${path}`, {
[`panelOpener-id-${id}`]: id,
[`panelOpener-deepLinkId-${deepLink?.id}`]: !!deepLink,
});
const togglePanel = useCallback(() => {
if (selectedNode?.id === item.id) {
closePanel();
} else {
openPanel(item);
}
}, [selectedNode?.id, item, closePanel, openPanel]);
const onLinkClick = useCallback(
(e: React.MouseEvent) => {
if (!href) {
togglePanel();
return;
}
e.preventDefault();
navigateToUrl(href);
closePanel();
},
[closePanel, href, navigateToUrl]
[closePanel, href, navigateToUrl, togglePanel]
);
const onIconClick = useCallback(() => {
if (selectedNode?.id === item.id) {
closePanel();
} else {
openPanel(item);
}
}, [openPanel, closePanel, item, selectedNode]);
togglePanel();
}, [togglePanel]);
const isExpanded = selectedNode?.path === path;
@ -123,7 +130,7 @@ export const NavigationItemOpenPanel: FC<Props> = ({ item, navigateToUrl, active
size="s"
color="text"
onClick={onIconClick}
iconType="spaces"
iconType={hasLandingPage ? 'spaces' : 'arrowRight'}
iconSize="m"
aria-label={i18n.translate('sharedUXPackages.chrome.sideNavigation.togglePanel', {
defaultMessage: 'Toggle "{title}" panel navigation',

View file

@ -32,6 +32,12 @@ const getTestSubj = (selectedNode: PanelSelectedNode | null): string | undefined
});
};
const getTargetTestSubj = (target: EventTarget | null): string | undefined => {
if (!target) return;
return (target as HTMLElement).dataset.testSubj;
};
export const NavigationPanel: FC = () => {
const { euiTheme } = useEuiTheme();
const { isOpen, close, getContent, selectedNode } = usePanel();
@ -48,12 +54,22 @@ export const NavigationPanel: FC = () => {
const onOutsideClick = useCallback(
({ target }: Event) => {
// Only close if we are not clicking on the currently selected nav node
if (
!(target as HTMLButtonElement).dataset.testSubj?.includes(
`panelOpener-${selectedNode?.path}`
)
) {
let doClose = true;
if (target) {
// Only close if we are not clicking on the currently selected nav node
const testSubj =
getTargetTestSubj(target) ?? getTargetTestSubj((target as HTMLElement).parentNode);
if (
testSubj?.includes(`nav-item-${selectedNode?.path}`) ||
testSubj?.includes(`panelOpener-${selectedNode?.path}`)
) {
doClose = false;
}
}
if (doClose) {
close();
}
},

View file

@ -59,7 +59,11 @@ export function SolutionNavigationProvider(ctx: Pick<FtrProviderContext, 'getSer
// side nav related actions
sidenav: {
async expectLinkExists(
by: { deepLinkId: AppDeepLinkId } | { navId: string } | { text: string }
by:
| { deepLinkId: AppDeepLinkId }
| { navId: string }
| { text: string }
| { panelNavLinkId: string }
) {
if ('deepLinkId' in by) {
await testSubjects.existOrFail(`~nav-item-deepLinkId-${by.deepLinkId}`, {
@ -67,6 +71,10 @@ export function SolutionNavigationProvider(ctx: Pick<FtrProviderContext, 'getSer
});
} else if ('navId' in by) {
await testSubjects.existOrFail(`~nav-item-id-${by.navId}`, { timeout: TIMEOUT_CHECK });
} else if ('panelNavLinkId' in by) {
await testSubjects.existOrFail(`~panelNavItem-id-${by.panelNavLinkId}`, {
timeout: TIMEOUT_CHECK,
});
} else {
expect(await getByVisibleText('~nav-item', by.text)).not.be(null);
}
@ -130,6 +138,9 @@ export function SolutionNavigationProvider(ctx: Pick<FtrProviderContext, 'getSer
});
}
},
async clickPanelLink(deepLinkId: string) {
await testSubjects.click(`~panelNavItem-id-${deepLinkId}`);
},
async expectSectionExists(sectionId: NavigationId) {
log.debug('SolutionNavigation.sidenav.expectSectionExists', sectionId);
await testSubjects.existOrFail(getSectionIdTestSubj(sectionId), { timeout: TIMEOUT_CHECK });
@ -186,14 +197,33 @@ export function SolutionNavigationProvider(ctx: Pick<FtrProviderContext, 'getSer
return false;
}
},
async openPanel(sectionId: NavigationId) {
async openPanel(
sectionId: NavigationId,
{ button }: { button: 'icon' | 'link' } = { button: 'icon' }
) {
log.debug('SolutionNavigation.sidenav.openPanel', sectionId);
const isOpen = await this.isPanelOpen(sectionId);
if (isOpen) return;
const panelOpenerBtn = await testSubjects.find(
`~panelOpener-id-${sectionId}`,
button === 'icon' ? `~panelOpener-id-${sectionId}` : `~nav-item-id-${sectionId}`,
TIMEOUT_CHECK
);
await panelOpenerBtn.click();
},
async closePanel(
sectionId: NavigationId,
{ button }: { button: 'icon' | 'link' } = { button: 'icon' }
) {
log.debug('SolutionNavigation.sidenav.closePanel', sectionId);
const isOpen = await this.isPanelOpen(sectionId);
if (!isOpen) return;
const panelOpenerBtn = await testSubjects.find(
button === 'icon' ? `~panelOpener-id-${sectionId}` : `~nav-item-id-${sectionId}`,
TIMEOUT_CHECK
);

View file

@ -68,66 +68,10 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
link: 'slo',
},
{
id: 'aiMl',
title: i18n.translate('xpack.observability.obltNav.ml.aiAndMlGroupTitle', {
defaultMessage: 'AI & ML',
link: 'observabilityAIAssistant',
title: i18n.translate('xpack.observability.obltNav.aiMl.aiAssistant', {
defaultMessage: 'AI Assistant',
}),
renderAs: 'accordion',
children: [
{
link: 'observabilityAIAssistant',
title: i18n.translate('xpack.observability.obltNav.aiMl.aiAssistant', {
defaultMessage: 'AI Assistant',
}),
},
{
link: 'ml:anomalyDetection',
renderAs: 'item',
children: [
{
link: 'ml:singleMetricViewer',
},
{
link: 'ml:anomalyExplorer',
},
{
link: 'ml:settings',
},
],
},
{
title: i18n.translate('xpack.observability.obltNav.ml.logRateAnalysis', {
defaultMessage: 'Log rate analysis',
}),
link: 'ml:logRateAnalysis',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.includes(prepend('/app/ml/aiops/log_rate_analysis'));
},
},
{
link: 'logs:anomalies',
},
{
link: 'logs:log-categories',
},
{
title: i18n.translate('xpack.observability.obltNav.ml.changePointDetection', {
defaultMessage: 'Change point detection',
}),
link: 'ml:changePointDetections',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.includes(
prepend('/app/ml/aiops/change_point_detection')
);
},
},
{
title: i18n.translate('xpack.observability.obltNav.ml.job.notifications', {
defaultMessage: 'Job notifications',
}),
link: 'ml:notifications',
},
],
},
{
link: 'inventory',
@ -138,33 +82,26 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
title: i18n.translate('xpack.observability.obltNav.applications', {
defaultMessage: 'Applications',
}),
renderAs: 'accordion',
renderAs: 'panelOpener',
children: [
{
link: 'apm:services',
getIsActive: ({ pathNameSerialized }) => {
const regex = /app\/apm\/.*service.*/;
return regex.test(pathNameSerialized);
},
},
{
link: 'apm:traces',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/apm/traces'));
},
},
{
link: 'apm:dependencies',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/apm/dependencies'));
},
children: [
{ link: 'apm:services' },
{ link: 'apm:traces' },
{ link: 'apm:dependencies' },
{
link: 'ux',
title: i18n.translate('xpack.observability.obltNav.apm.ux', {
defaultMessage: 'User experience',
}),
},
],
},
{
id: 'synthetics',
title: i18n.translate('xpack.observability.obltNav.apm.syntheticsGroupTitle', {
defaultMessage: 'Synthetics',
}),
renderAs: 'accordion',
children: [
{
link: 'synthetics',
@ -172,10 +109,17 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
defaultMessage: 'Monitors',
}),
},
{ link: 'synthetics:certificates' },
{
link: 'synthetics:certificates',
title: i18n.translate(
'xpack.observability.obltNav.apm.synthetics.tlsCertificates',
{
defaultMessage: 'TLS certificates',
}
),
},
],
},
{ link: 'ux' },
],
},
{
@ -183,32 +127,36 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
title: i18n.translate('xpack.observability.obltNav.infrastructure', {
defaultMessage: 'Infrastructure',
}),
renderAs: 'accordion',
renderAs: 'panelOpener',
children: [
{
link: 'metrics:inventory',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/metrics/inventory'));
},
},
{
link: 'metrics:hosts',
getIsActive: ({ pathNameSerialized, prepend }) => {
return pathNameSerialized.startsWith(prepend('/app/metrics/hosts'));
},
},
{
link: 'metrics:metrics-explorer',
children: [
{
link: 'metrics:inventory',
title: i18n.translate('xpack.observability.infrastructure.inventory', {
defaultMessage: 'Infrastructure inventory',
}),
},
{ link: 'metrics:hosts' },
{
link: 'metrics:metrics-explorer',
title: i18n.translate(
'xpack.observability.obltNav.infrastructure.metricsExplorer',
{
defaultMessage: 'Metrics explorer',
}
),
},
],
},
{
id: 'profiling',
title: i18n.translate(
'xpack.observability.obltNav.infrastructure.universalProfiling',
{
defaultMessage: 'Universal Profiling',
defaultMessage: 'Universal profiling',
}
),
renderAs: 'accordion',
children: [
{
link: 'profiling:stacktraces',
@ -223,12 +171,182 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
},
],
},
{
id: 'machine_learning-landing',
renderAs: 'panelOpener',
title: i18n.translate('xpack.observability.obltNav.machineLearning', {
defaultMessage: 'Machine learning',
}),
children: [
{
children: [
{
link: 'ml:overview',
},
{
link: 'ml:notifications',
},
{
link: 'ml:memoryUsage',
title: i18n.translate(
'xpack.observability.obltNav.machineLearning.memoryUsage',
{
defaultMessage: 'Memory usage',
}
),
},
],
},
{
id: 'category-anomaly_detection',
title: i18n.translate('xpack.observability.obltNav.ml.anomaly_detection', {
defaultMessage: 'Anomaly detection',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:anomalyDetection',
title: i18n.translate('xpack.observability.obltNav.ml.anomaly_detection.jobs', {
defaultMessage: 'Jobs',
}),
},
{
link: 'ml:anomalyExplorer',
},
{
link: 'ml:singleMetricViewer',
},
{
link: 'ml:settings',
},
{
link: 'ml:suppliedConfigurations',
},
],
},
{
id: 'category-data_frame analytics',
title: i18n.translate('xpack.observability.obltNav.ml.data_frame_analytics', {
defaultMessage: 'Data frame analytics',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:dataFrameAnalytics',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_frame_analytics.jobs',
{
defaultMessage: 'Jobs',
}
),
},
{
link: 'ml:resultExplorer',
},
{
link: 'ml:analyticsMap',
},
],
},
{
id: 'category-model_management',
title: i18n.translate('xpack.observability.obltNav.ml.model_management', {
defaultMessage: 'Model management',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:nodesOverview',
title: i18n.translate(
'xpack.observability.obltNav.ml.model_management.trainedModels',
{
defaultMessage: 'Trained models',
}
),
},
],
},
{
id: 'category-data_visualizer',
title: i18n.translate('xpack.observability.obltNav.ml.data_visualizer', {
defaultMessage: 'Data visualizer',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:fileUpload',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer',
{
defaultMessage: 'File data visualizer',
}
),
},
{
link: 'ml:indexDataVisualizer',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_visualizer.data_view_data_visualizer',
{
defaultMessage: 'Data view data visualizer',
}
),
},
{
link: 'ml:dataDrift',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_visualizer.data_drift',
{
defaultMessage: 'Data drift',
}
),
},
],
},
{
id: 'category-aiops_labs',
title: i18n.translate('xpack.observability.obltNav.ml.aiops_labs', {
defaultMessage: 'Aiops labs',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:logRateAnalysis',
title: i18n.translate(
'xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis',
{
defaultMessage: 'Log rate analysis',
}
),
},
{
link: 'ml:logPatternAnalysis',
title: i18n.translate(
'xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis',
{
defaultMessage: 'Log pattern analysis',
}
),
},
{
link: 'ml:changePointDetections',
title: i18n.translate(
'xpack.observability.obltNav.ml.aiops_labs.change_point_detection',
{
defaultMessage: 'Change point detection',
}
),
},
],
},
],
},
{
id: 'otherTools',
title: i18n.translate('xpack.observability.obltNav.otherTools', {
defaultMessage: 'Other tools',
}),
renderAs: 'accordion',
renderAs: 'panelOpener',
icon: 'editorCodeBlock',
children: [
{
link: 'logs:stream',
@ -236,9 +354,27 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
defaultMessage: 'Logs stream',
}),
},
{
link: 'logs:anomalies',
title: i18n.translate('xpack.observability.obltNav.otherTools.logsAnomalies', {
defaultMessage: 'Logs anomalies',
}),
},
{
link: 'logs:log-categories',
title: i18n.translate('xpack.observability.obltNav.otherTools.logsCategories', {
defaultMessage: 'Logs categories',
}),
},
{ link: 'maps' },
{ link: 'canvas' },
{ link: 'graph' },
{
link: 'visualize',
title: i18n.translate('xpack.observability.obltNav.otherTools.logsCategories', {
defaultMessage: 'Visualize library',
}),
},
],
},
],
@ -248,8 +384,8 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
{ type: 'recentlyAccessed' },
{
type: 'navItem',
title: i18n.translate('xpack.observability.obltNav.getStarted', {
defaultMessage: 'Get started',
title: i18n.translate('xpack.observability.obltNav.addData', {
defaultMessage: 'Add data',
}),
link: 'observabilityOnboarding',
icon: 'launch',
@ -292,6 +428,7 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
title: 'Data',
children: [
{ link: 'management:index_management' },
{ link: 'management:data_quality' },
{ link: 'management:index_lifecycle_management' },
{ link: 'management:snapshot_restore' },
{ link: 'management:rollup_jobs' },
@ -350,135 +487,6 @@ export function createNavTree(pluginsStart: ObservabilityPublicPluginsStart) {
{
link: 'fleet',
},
{
id: 'machine_learning-landing',
link: 'securitySolutionUI:machine_learning-landing',
renderAs: 'panelOpener',
spaceBefore: null,
children: [
{
children: [
{
link: 'ml:overview',
},
{
link: 'ml:notifications',
},
{
link: 'ml:memoryUsage',
},
],
},
{
id: 'category-anomaly_detection',
title: i18n.translate('xpack.observability.obltNav.ml.anomaly_detection', {
defaultMessage: 'Anomaly detection',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:anomalyDetection',
title: i18n.translate('xpack.observability.obltNav.ml.anomaly_detection.jobs', {
defaultMessage: 'Jobs',
}),
},
{
link: 'ml:anomalyExplorer',
},
{
link: 'ml:singleMetricViewer',
},
{
link: 'ml:settings',
},
],
},
{
id: 'category-data_frame analytics',
title: i18n.translate('xpack.observability.obltNav.ml.data_frame_analytics', {
defaultMessage: 'Data frame analytics',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:dataFrameAnalytics',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_frame_analytics.jobs',
{
defaultMessage: 'Jobs',
}
),
},
{
link: 'ml:resultExplorer',
},
{
link: 'ml:analyticsMap',
},
],
},
{
id: 'category-model_management',
title: i18n.translate('xpack.observability.obltNav.ml.model_management', {
defaultMessage: 'Model management',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:nodesOverview',
},
],
},
{
id: 'category-data_visualizer',
title: i18n.translate('xpack.observability.obltNav.ml.data_visualizer', {
defaultMessage: 'Data visualizer',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:fileUpload',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer',
{
defaultMessage: 'File data visualizer',
}
),
},
{
link: 'ml:indexDataVisualizer',
title: i18n.translate(
'xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer',
{
defaultMessage: 'Data view data visualizer',
}
),
},
{
link: 'ml:dataDrift',
},
],
},
{
id: 'category-aiops_labs',
title: i18n.translate('xpack.observability.obltNav.ml.aiops_labs', {
defaultMessage: 'Aiops labs',
}),
breadcrumbStatus: 'hidden',
children: [
{
link: 'ml:logRateAnalysis',
},
{
link: 'ml:logPatternAnalysis',
},
{
link: 'ml:changePointDetections',
},
],
},
],
},
{
id: 'cloudLinkUserAndRoles',
cloudLink: 'userAndRoles',

View file

@ -32387,15 +32387,10 @@
"xpack.observability.obltNav.apm.syntheticsGroupTitle": "Synthetics",
"xpack.observability.obltNav.applications": "Applications",
"xpack.observability.obltNav.devTools": "Outils de développeur",
"xpack.observability.obltNav.getStarted": "Démarrer",
"xpack.observability.obltNav.headerSolutionSwitcher.obltSolutionTitle": "Observabilité",
"xpack.observability.obltNav.infrastructure": "Infrastructure",
"xpack.observability.obltNav.infrastructure.universalProfiling": "Universal Profiling",
"xpack.observability.obltNav.management": "Gestion",
"xpack.observability.obltNav.ml.aiAndMlGroupTitle": "IA et ML",
"xpack.observability.obltNav.ml.changePointDetection": "Modifier la détection du point",
"xpack.observability.obltNav.ml.job.notifications": "Notifications de tâches",
"xpack.observability.obltNav.ml.logRateAnalysis": "Analyse du taux de log",
"xpack.observability.obltNav.otherTools": "Autres outils",
"xpack.observability.obltNav.otherTools.logsStream": "Flux de logs",
"xpack.observability.obltNav.stackManagement": "Gestion de la Suite",

View file

@ -32132,15 +32132,10 @@
"xpack.observability.obltNav.apm.syntheticsGroupTitle": "Synthetics",
"xpack.observability.obltNav.applications": "アプリケーション",
"xpack.observability.obltNav.devTools": "開発者ツール",
"xpack.observability.obltNav.getStarted": "使ってみる",
"xpack.observability.obltNav.headerSolutionSwitcher.obltSolutionTitle": "Observability",
"xpack.observability.obltNav.infrastructure": "インフラストラクチャー",
"xpack.observability.obltNav.infrastructure.universalProfiling": "ユニバーサルプロファイリング",
"xpack.observability.obltNav.management": "管理",
"xpack.observability.obltNav.ml.aiAndMlGroupTitle": "AI & ML",
"xpack.observability.obltNav.ml.changePointDetection": "変化点検出",
"xpack.observability.obltNav.ml.job.notifications": "ジョブ通知",
"xpack.observability.obltNav.ml.logRateAnalysis": "ログレート分析",
"xpack.observability.obltNav.otherTools": "その他のツール",
"xpack.observability.obltNav.otherTools.logsStream": "ログストリーム",
"xpack.observability.obltNav.stackManagement": "スタック管理",

View file

@ -32175,15 +32175,10 @@
"xpack.observability.obltNav.apm.syntheticsGroupTitle": "Synthetics",
"xpack.observability.obltNav.applications": "应用程序",
"xpack.observability.obltNav.devTools": "开发者工具",
"xpack.observability.obltNav.getStarted": "开始使用",
"xpack.observability.obltNav.headerSolutionSwitcher.obltSolutionTitle": "Observability",
"xpack.observability.obltNav.infrastructure": "基础设施",
"xpack.observability.obltNav.infrastructure.universalProfiling": "Universal Profiling",
"xpack.observability.obltNav.management": "管理",
"xpack.observability.obltNav.ml.aiAndMlGroupTitle": "AI 和 ML",
"xpack.observability.obltNav.ml.changePointDetection": "更改点检测",
"xpack.observability.obltNav.ml.job.notifications": "作业通知",
"xpack.observability.obltNav.ml.logRateAnalysis": "日志速率分析",
"xpack.observability.obltNav.otherTools": "其他工具",
"xpack.observability.obltNav.otherTools.logsStream": "日志流",
"xpack.observability.obltNav.stackManagement": "Stack Management",

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export default function ({ getPageObjects, getService }: FtrProviderContext) {
@ -48,15 +49,35 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
deepLinkId: 'observabilityOnboarding',
});
// check the AI & ML subsection
await solutionNavigation.sidenav.openSection('observability_project_nav.aiMl'); // open AI & ML subsection
await solutionNavigation.sidenav.clickLink({ deepLinkId: 'ml:anomalyDetection' });
await solutionNavigation.sidenav.expectLinkActive({ deepLinkId: 'ml:anomalyDetection' });
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Anomaly Detection' });
// open apm (Application) panel using the link button (not the button icon)
await solutionNavigation.sidenav.openPanel('apm', { button: 'link' });
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('apm');
expect(isOpen).to.be(true);
}
await solutionNavigation.sidenav.closePanel('apm', { button: 'link' });
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('apm');
expect(isOpen).to.be(false);
}
// open Infrastructure panel using the icon button and navigate to some link inside the panel
await solutionNavigation.sidenav.openPanel('metrics', { button: 'icon' });
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('metrics');
expect(isOpen).to.be(true);
}
await solutionNavigation.sidenav.clickPanelLink('metrics:inventory');
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
deepLinkId: 'ml:anomalyDetection',
text: 'Infrastructure inventory',
});
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('metrics');
expect(isOpen).to.be(false);
}
// navigate to a different section
await solutionNavigation.sidenav.openSection('project_settings_project_nav');
await solutionNavigation.sidenav.clickLink({ deepLinkId: 'management' });

View file

@ -26,5 +26,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./pages/rule_details_page'));
loadTestFile(require.resolve('./pages/alert_details_page'));
loadTestFile(require.resolve('./pages/alerts/metric_threshold'));
loadTestFile(require.resolve('./sidenav/sidenav'));
});
}

View file

@ -0,0 +1,72 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getPageObjects, getService }: FtrProviderContext) {
const { common, solutionNavigation } = getPageObjects(['common', 'solutionNavigation']);
const spaces = getService('spaces');
const browser = getService('browser');
describe('o11y sidenav', () => {
let cleanUp: () => Promise<unknown>;
let spaceCreated: { id: string } = { id: '' };
before(async () => {
// Navigate to the spaces management page which will log us in Kibana
await common.navigateToUrl('management', 'kibana/spaces', {
shouldUseHashForSubUrl: false,
});
// Create a space with the observability solution and navigate to its home page
({ cleanUp, space: spaceCreated } = await spaces.create({ solution: 'oblt' }));
await browser.navigateTo(spaces.getRootUrl(spaceCreated.id));
});
after(async () => {
// Clean up space created
await cleanUp();
});
describe('sidenav & breadcrumbs', () => {
it('renders the correct nav and navigate to links', async () => {
await solutionNavigation.sidenav.clickLink({ navId: 'observabilityAIAssistant' }); // click on AI Assistant link
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'AI Assistant' });
// check Other Tools section
await solutionNavigation.sidenav.openPanel('otherTools', { button: 'link' });
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('otherTools');
expect(isOpen).to.be(true);
}
await solutionNavigation.sidenav.expectLinkExists({
panelNavLinkId: 'logs:anomalies',
});
await solutionNavigation.sidenav.expectLinkExists({
panelNavLinkId: 'logs:log-categories',
});
await solutionNavigation.sidenav.clickPanelLink('visualize');
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
text: 'Visualize library',
});
// check Machine Learning section
await solutionNavigation.sidenav.openPanel('machine_learning-landing');
{
const isOpen = await solutionNavigation.sidenav.isPanelOpen('machine_learning-landing');
expect(isOpen).to.be(true);
}
await solutionNavigation.sidenav.clickPanelLink('ml:suppliedConfigurations');
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
text: 'Supplied configurations',
});
});
});
});
}

View file

@ -52,6 +52,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
...xpackFunctionalConfig.get('kbnTestServer'),
serverArgs: [
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
'--xpack.cloud.id=ftr_fake_cloud_id:aGVsbG8uY29tOjQ0MyRFUzEyM2FiYyRrYm4xMjNhYmM=',
'--xpack.cloud.base_url=https://cloud.elastic.co',
'--xpack.spaces.allowSolutionVisibility=true',
`--elasticsearch.hosts=https://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`,
`--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`,
`--plugin-path=${resolve(__dirname, '../functional_with_es_ssl/plugins/alerts')}`,