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

Implement new nav hierarchy for stateful/cloud #192805

Merged
merged 31 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
34f378e
change nav hierarchy for stateful cloud to use panelOpener
mgiota Sep 13, 2024
93ce699
Merge branch 'main' of github.com:elastic/kibana into change_navigation
mgiota Sep 17, 2024
7d98044
Merge branch 'main' into change_navigation
elasticmachine Sep 17, 2024
36e4e5a
Merge branch 'main' into change_navigation
elasticmachine Sep 17, 2024
4126228
Fix toggle panel from main button
sebelga Sep 18, 2024
bec5a72
Fix icon
sebelga Sep 18, 2024
f7d3ccb
Update func test helper to open/close panel with the link button
sebelga Sep 18, 2024
f1bdd6c
remove unused i18n keys
mgiota Sep 18, 2024
6832603
add machine learning supplied configurations
mgiota Sep 18, 2024
1611de1
Merge branch 'main' of github.com:elastic/kibana into change_navigation
mgiota Sep 18, 2024
7cbdd0a
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Sep 18, 2024
113b409
Merge branch 'main' into change_navigation
elasticmachine Sep 18, 2024
7c87646
bring back ml menu
mgiota Sep 18, 2024
6f79839
Merge branch 'main' into change_navigation
elasticmachine Sep 19, 2024
f35ab58
use sentence case for machine learning menu items
mgiota Sep 19, 2024
7c9cf84
add missing data set quality in stack management
mgiota Sep 19, 2024
bc10b40
fix failing tests
mgiota Sep 19, 2024
7904689
add more tests
mgiota Sep 19, 2024
d6c0493
Merge branch 'main' into change_navigation
elasticmachine Sep 23, 2024
f11ebf7
Merge branch 'main' into change_navigation
elasticmachine Sep 24, 2024
10fc7cc
Merge branch 'main' of github.com:elastic/kibana into change_navigation
mgiota Oct 1, 2024
9730199
uncomment tests
mgiota Oct 1, 2024
67d34b8
update infrastructure breadcrumb
mgiota Oct 1, 2024
8d3ab8f
update to sentence case
mgiota Oct 1, 2024
14b14b1
Merge branch 'main' into change_navigation
elasticmachine Oct 1, 2024
e542e88
add more test cases
mgiota Oct 1, 2024
f4ece0b
remove unnecessary comments
mgiota Oct 2, 2024
120e1c2
remove additional tests from sidenav tests
mgiota Oct 2, 2024
cc99a46
Merge branch 'main' into change_navigation
elasticmachine Oct 2, 2024
bf28378
add o11y sidenav functional tests
mgiota Oct 3, 2024
5f945a5
Merge branch 'main' into change_navigation
dominiqueclarke Oct 3, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -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.`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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;

Expand All @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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();
}
},
Expand Down
36 changes: 33 additions & 3 deletions test/functional/page_objects/solution_navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,22 @@ 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}`, {
timeout: TIMEOUT_CHECK,
});
} 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);
}
Expand Down Expand Up @@ -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 });
Expand Down Expand Up @@ -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
);

Expand Down
Loading
Loading