Skip to content

[ChromeNavPackage] Refactor to work with ChromeNavigationNode#156526

Merged
sebelga merged 3 commits intoelastic:mainfrom
sebelga:chrome-nav/set-navigation-api
May 4, 2023
Merged

[ChromeNavPackage] Refactor to work with ChromeNavigationNode#156526
sebelga merged 3 commits intoelastic:mainfrom
sebelga:chrome-nav/set-navigation-api

Conversation

@sebelga
Copy link
Copy Markdown
Contributor

@sebelga sebelga commented May 3, 2023

In this PR I've refactored the @kbn/shared-ux-chrome-navigation to (hopefully) simplify the data model. This is a preparation work to be able to expose an api on the core Chrome service to set the navigation.

Goal

  • Externally: work with a single interface to define a navigation node: ChromeNavigationNode
  • Internally: have a single interface for all navigation node definition: ChromeNavigationNodeViewModel
  • Don't expose component props interface for the navigation configuration.
  • Only convert the ChromeNavigationNodeViewModel to eui nav props at the component level

What it unblocks

  • The ChromeNavigationNode and ChromeNavigationNodeViewModel will be imported by the Chrome service
  • The Chrome service will expose an api to convert a ChromeNavigationNode[] to a ChromeNavigationNodeViewModel[]: converting the link (pointing to appIds or deeplinkIds) to propert href

import { ChromeNavigationNodeViewModel } from '../../../types';

export const analyticsItemSet: NavItemProps[] = [
// TODO: Declare ChromeNavigationNode[] (with "link" to app id or deeplink id)
Copy link
Copy Markdown
Contributor Author

@sebelga sebelga May 3, 2023

Choose a reason for hiding this comment

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

The idea is to not use href here but link. The same way links will be defined when calling the chrome.project.setNavigation(/*<config-with-nodes-and-links>*/).

This can be done as a second chunk of work to limit the changes in this PR.

}, []);

return createSideNavData;
export const parseNavItems = (
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This utility handler is only in charge of building the path of each node and to remove any node that is not enabled.

The conversion to a MyEuiSideNavItem will occur at the component level (inside navigation_bucket.tsx)

export const NavigationBucket = (opts: NavigationBucketProps) => {
const { id, items, activeNavItemId, ...props } = opts;
const { navIsOpen } = useNavigation();
const navigationNodeToEuiItem = (
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is where we convert our ChromeNavigationNodeViewModel to a EuiSideNavItemType to render the jsx.

Copy link
Copy Markdown
Contributor

@Dosant Dosant left a comment

Choose a reason for hiding this comment

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

Looks great!

* Full path that points to this node (includes all parent ids). If not set
* the path is the id
*/
path?: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For what do you think this will be used?
Wouldn't path: string[] be more convenient?
Will this path include this node as the last item? or only parents?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This path includes everything. We could keep an array, but at the same time we can always build the array later if needed.

const path: string = 'stackManagement.someIntermediateSection.indexManagement.someDeepLinkId'

*/
path?: string;
isActive?: boolean;
href?: string;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should repeat what Chrome uses to generate the current side nav:

href is an absolute path used to enable right-click navigation/open in a new tab

url is a relative path used to call navigate() in onclick handler to prevent page reload

const url = appendAppPath(relativeBaseUrl, deepLink?.path || app.defaultPath);
const href = relativeToAbsolute(url);

Basically I agree with an idea, but we will likely need to add more things here, I don't mind doing it as we go

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I like the idea. Not sure about naming but we can see later. I wonder if url for absolute and relativePath for navigate purpose?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think href needs to be an absolute path. You can still right-click the link and choose to open it in a new tab when you use a relative string for href. It should be fine to use the same string for the href attribute and navigating. Unless there is some corner case I'm not aware of. But that's how it worked in the POC.

@sebelga
Copy link
Copy Markdown
Contributor Author

sebelga commented May 3, 2023

I've tested the PR using @tsullivan PR for search navigation (#156465) and it works well except the active state. This was expected as the active route should be provided by the Chrome service.

You can test it by creating this file inside the serverless_search x-pack plugin

// nav.tsx

/*
 * 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 { CoreStart } from '@kbn/core/public';
import {
  Navigation,
  NavigationKibanaProvider,
  ChromeNavigationNodeViewModel,
} from '@kbn/shared-ux-chrome-navigation';
import React from 'react';

const navItems: ChromeNavigationNodeViewModel[] = [
  {
    title: '',
    id: 'root',
    items: [
      { id: 'overview', title: 'Overview', href: '/app/enterprise_search/overview' },
      { id: 'indices', title: 'Indices', href: '/app/enterprise_search/content/search_indices' },
      { id: 'engines', title: 'Engines', href: '/app/enterprise_search/content/engines' },
      { id: 'api_keys', title: 'API keys', href: '/app/management/security/api_keys' },
      {
        id: 'ingest_pipelines',
        title: 'Ingest pipelines',
        href: '/app/management/ingest/ingest_pipelines',
      },
    ],
  },
];

export const serverlessSearchSideNavComponentProvider = (core: CoreStart) => () =>
  (
    <NavigationKibanaProvider core={core}>
      <Navigation
        navigationTree={[
          {
            id: 'search_project_nav',
            items: navItems,
            title: 'Search',
            icon: 'logoEnterpriseSearch',
          },
        ]}
        activeNavItemId="search_project_nav.root.overview"
        platformConfig={{}}
        homeHref="/app/enterprise_search/content/setup_guide"
        linkToCloud="projects"
      />
    </NavigationKibanaProvider>
  );

And then update the public/plugin.ts file

// public/plugin.ts

...

public start(
  core: CoreStart,
  _startDeps: ServerlessSearchPluginStartDependencies
): ServerlessSearchPluginStart {
  core.chrome.project.setSideNavComponent(serverlessSearchSideNavComponentProvider(core));
  return {};
}

@sebelga sebelga marked this pull request as ready for review May 3, 2023 15:09
@sebelga sebelga requested a review from a team as a code owner May 3, 2023 15:09
@sebelga sebelga requested a review from tsullivan May 3, 2023 15:09
@sebelga sebelga self-assigned this May 3, 2023
@sebelga sebelga added release_note:skip Skip the PR/issue when compiling release notes Team:SharedUX Platform AppEx-SharedUX (formerly Global Experience) t// Project:Serverless MVP labels May 3, 2023
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/appex-sharedux (Team:SharedUX)

Copy link
Copy Markdown
Member

@tsullivan tsullivan left a comment

Choose a reason for hiding this comment

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

LGTM

@sebelga
Copy link
Copy Markdown
Contributor Author

sebelga commented May 4, 2023

@elasticmachine merge upstream

@kibana-ci
Copy link
Copy Markdown

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
@kbn/shared-ux-chrome-navigation 11 15 +4

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
@kbn/shared-ux-chrome-navigation 3 2 -1
Unknown metric groups

API count

id before after diff
@kbn/shared-ux-chrome-navigation 21 31 +10

ESLint disabled line counts

id before after diff
enterpriseSearch 19 21 +2
securitySolution 398 401 +3
total +5

Total ESLint disabled count

id before after diff
enterpriseSearch 20 22 +2
securitySolution 478 481 +3
total +5

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @sebelga

@sebelga sebelga merged commit 5a65112 into elastic:main May 4, 2023
@sebelga sebelga deleted the chrome-nav/set-navigation-api branch May 4, 2023 09:41
@kibanamachine kibanamachine added v8.9.0 backport:skip This PR does not require backporting labels May 4, 2023
tsullivan added a commit to tsullivan/kibana that referenced this pull request May 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting Project:Serverless MVP release_note:skip Skip the PR/issue when compiling release notes Team:SharedUX Platform AppEx-SharedUX (formerly Global Experience) t// v8.9.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants