Skip to content

Commit

Permalink
Update Project Selection in Serverless Top Navigation (#163076)
Browse files Browse the repository at this point in the history
## Summary

close #163014

- Changing `My Deployments -> Projects`
- Removing hardcoded url and passing one from the config
  • Loading branch information
Dosant authored Aug 7, 2023
1 parent 9377ae7 commit 1047eef
Show file tree
Hide file tree
Showing 18 changed files with 76 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,11 @@ export class ChromeService {
projectNavigation.setProjectHome(homeHref);
};

const setProjectsUrl = (projectsUrl: string) => {
validateChromeStyle();
projectNavigation.setProjectsUrl(projectsUrl);
};

const isIE = () => {
const ua = window.navigator.userAgent;
const msie = ua.indexOf('MSIE '); // IE 10 or older
Expand Down Expand Up @@ -317,6 +322,7 @@ export class ChromeService {
loadingCount$={http.getLoadingCount$()}
headerBanner$={headerBanner$.pipe(takeUntil(this.stop$))}
homeHref$={projectNavigation.getProjectHome$()}
projectsUrl$={projectNavigation.getProjectsUrl$()}
docLinks={docLinks}
kibanaVersion={injectedMetadata.getKibanaVersion()}
prependBasePath={http.basePath.prepend}
Expand Down Expand Up @@ -444,6 +450,7 @@ export class ChromeService {
getChromeStyle$: () => chromeStyle$.pipe(takeUntil(this.stop$)),
project: {
setHome: setProjectHome,
setProjectsUrl,
setNavigation: setProjectNavigation,
setSideNavComponent: setProjectSideNavComponent,
setBreadcrumbs: setProjectBreadcrumbs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export class ProjectNavigationService {
current: SideNavComponent | null;
}>({ current: null });
private projectHome$ = new BehaviorSubject<string | undefined>(undefined);
private projectsUrl$ = new BehaviorSubject<string | undefined>(undefined);
private projectNavigation$ = new BehaviorSubject<ChromeProjectNavigation | undefined>(undefined);
private activeNodes$ = new BehaviorSubject<ChromeProjectNavigationNode[][]>([]);
private projectNavigationNavTreeFlattened: Record<string, ChromeProjectNavigationNode> = {};
Expand Down Expand Up @@ -66,6 +67,12 @@ export class ProjectNavigationService {
getProjectHome$: () => {
return this.projectHome$.asObservable();
},
setProjectsUrl: (projectsUrl: string) => {
this.projectsUrl$.next(projectsUrl);
},
getProjectsUrl$: () => {
return this.projectsUrl$.asObservable();
},
setProjectNavigation: (projectNavigation: ChromeProjectNavigation) => {
this.projectNavigation$.next(projectNavigation);
this.projectNavigationNavTreeFlattened = flattenNav(projectNavigation.navigationTree);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ export interface InternalChromeStart extends ChromeStart {
*/
setHome(homeHref: string): void;

/**
* Sets the cloud's projects page.
* @param projectsUrl
*/
setProjectsUrl(projectsUrl: string): void;

/**
* Sets the project navigation config to be used for rendering project navigation.
* It is used for default project sidenav, project breadcrumbs, tracking active deep link.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe('Header', () => {
helpSupportUrl$: Rx.of('app/help'),
helpMenuLinks$: Rx.of([]),
homeHref$: Rx.of('app/home'),
projectsUrl$: Rx.of('/projects/'),
kibanaVersion: '8.9',
loadingCount$: Rx.of(0),
navControlsLeft$: Rx.of([]),
Expand Down Expand Up @@ -71,4 +72,15 @@ describe('Header', () => {
await toggleNav();
await toggleNav();
});

it('displays the link to projects', async () => {
render(
<ProjectHeader {...mockProps}>
<EuiHeader>Hello, world!</EuiHeader>
</ProjectHeader>
);

const projectsLink = await screen.getByTestId('projectsLink');
expect(projectsLink).toHaveAttribute('href', '/projects/');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ const headerStrings = {
}),
},
cloud: {
linkToDeployments: i18n.translate('core.ui.primaryNav.cloud.linkToDeployments', {
defaultMessage: 'My deployments',
linkToProjects: i18n.translate('core.ui.primaryNav.cloud.linkToProjects', {
defaultMessage: 'Projects',
}),
},
nav: {
Expand All @@ -100,6 +100,7 @@ export interface Props {
helpSupportUrl$: Observable<string>;
helpMenuLinks$: Observable<ChromeHelpMenuLink[]>;
homeHref$: Observable<string | undefined>;
projectsUrl$: Observable<string | undefined>;
kibanaVersion: string;
application: InternalApplicationStart;
loadingCount$: ReturnType<HttpStart['getLoadingCount$']>;
Expand Down Expand Up @@ -175,6 +176,7 @@ export const ProjectHeader = ({
const [isOpen, setIsOpen] = useLocalStorage(LOCAL_STORAGE_IS_OPEN_KEY, true);
const toggleCollapsibleNavRef = createRef<HTMLButtonElement & { euiAnimate: () => void }>();
const headerActionMenuMounter = useHeaderActionMenuMounter(observables.actionMenu$);
const projectsUrl = useObservable(observables.projectsUrl$);

return (
<>
Expand Down Expand Up @@ -233,8 +235,8 @@ export const ProjectHeader = ({
</EuiHeaderSectionItem>

<EuiHeaderSectionItem>
<EuiHeaderLink href="https://cloud.elastic.co/deployments">
{headerStrings.cloud.linkToDeployments}
<EuiHeaderLink href={projectsUrl} data-test-subj={'projectsLink'}>
{headerStrings.cloud.linkToProjects}
</EuiHeaderLink>
</EuiHeaderSectionItem>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const createStartContractMock = () => {
setChromeStyle: jest.fn(),
project: {
setHome: jest.fn(),
setProjectsUrl: jest.fn(),
setNavigation: jest.fn(),
setSideNavComponent: jest.fn(),
setBreadcrumbs: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.cloud.profile_url (string)',
'xpack.cloud.performance_url (string)',
'xpack.cloud.users_and_roles_url (string)',
'xpack.cloud.projects_url (any)', // It's a string (any because schema.conditional)
// can't be used to infer urls or customer id from the outside
'xpack.cloud.serverless.project_id (string)',
'xpack.discoverEnhanced.actions.exploreDataInChart.enabled (boolean)',
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/cloud/public/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const baseConfig = {
deployment_url: '/abc123',
profile_url: '/user/settings/',
organization_url: '/account/',
projects_url: '/projects/',
};

describe('Cloud Plugin', () => {
Expand Down Expand Up @@ -60,6 +61,11 @@ describe('Cloud Plugin', () => {
expect(setup.deploymentUrl).toBe('https://cloud.elastic.co/abc123');
});

it('exposes projectsUrl', () => {
const { setup } = setupPlugin();
expect(setup.projectsUrl).toBe('https://cloud.elastic.co/projects/');
});

it('exposes snapshotsUrl', () => {
const { setup } = setupPlugin();
expect(setup.snapshotsUrl).toBe('https://cloud.elastic.co/abc123/elasticsearch/snapshots/');
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/cloud/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface CloudConfigType {
base_url?: string;
profile_url?: string;
deployment_url?: string;
projects_url?: string;
billing_url?: string;
organization_url?: string;
users_and_roles_url?: string;
Expand All @@ -41,6 +42,7 @@ interface CloudUrls {
snapshotsUrl?: string;
performanceUrl?: string;
usersAndRolesUrl?: string;
projectsUrl?: string;
}

export class CloudPlugin implements Plugin<CloudSetup> {
Expand Down Expand Up @@ -121,6 +123,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
organizationUrl,
performanceUrl,
usersAndRolesUrl,
projectsUrl,
} = this.getCloudUrls();

let decodedId: DecodedCloudId | undefined;
Expand All @@ -136,6 +139,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
deploymentUrl,
profileUrl,
organizationUrl,
projectsUrl,
elasticsearchUrl: decodedId?.elasticsearchUrl,
kibanaUrl: decodedId?.kibanaUrl,
isServerlessEnabled: this.isServerlessEnabled,
Expand All @@ -158,6 +162,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
base_url: baseUrl,
performance_url: performanceUrl,
users_and_roles_url: usersAndRolesUrl,
projects_url: projectsUrl,
} = this.config;

const fullCloudDeploymentUrl = getFullCloudUrl(baseUrl, deploymentUrl);
Expand All @@ -166,6 +171,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
const fullCloudOrganizationUrl = getFullCloudUrl(baseUrl, organizationUrl);
const fullCloudPerformanceUrl = getFullCloudUrl(baseUrl, performanceUrl);
const fullCloudUsersAndRolesUrl = getFullCloudUrl(baseUrl, usersAndRolesUrl);
const fullCloudProjectsUrl = getFullCloudUrl(baseUrl, projectsUrl);
const fullCloudSnapshotsUrl = `${fullCloudDeploymentUrl}/${CLOUD_SNAPSHOTS_PATH}`;

return {
Expand All @@ -176,6 +182,7 @@ export class CloudPlugin implements Plugin<CloudSetup> {
snapshotsUrl: fullCloudSnapshotsUrl,
performanceUrl: fullCloudPerformanceUrl,
usersAndRolesUrl: fullCloudUsersAndRolesUrl,
projectsUrl: fullCloudProjectsUrl,
};
}
}
8 changes: 8 additions & 0 deletions x-pack/plugins/cloud/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ export interface CloudStart {
* The full URL to the users and roles page on Elastic Cloud. Undefined if not running on Cloud.
*/
usersAndRolesUrl?: string;
/**
* The full URL to the serverless projects page on Elastic Cloud. Undefined if not running in Serverless.
*/
projectsUrl?: string;
/**
* The full URL to the elasticsearch cluster.
*/
Expand Down Expand Up @@ -90,6 +94,10 @@ export interface CloudSetup {
* The full URL to the deployment management page on Elastic Cloud. Undefined if not running on Cloud.
*/
deploymentUrl?: string;
/**
* The full URL to the serverless projects page on Elastic Cloud. Undefined if not running in Serverless.
*/
projectsUrl?: string;
/**
* The full URL to the user profile page on Elastic Cloud. Undefined if not running on Cloud.
*/
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/cloud/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ const configSchema = schema.object({
users_and_roles_url: schema.maybe(schema.string()),
organization_url: schema.maybe(schema.string()),
profile_url: schema.maybe(schema.string()),
projects_url: schema.conditional(
schema.contextRef('serverless'),
true,
schema.string({ defaultValue: '/projects/' }),
schema.never()
),
trial_end_date: schema.maybe(schema.string()),
is_elastic_staff_owned: schema.maybe(schema.boolean()),
serverless: schema.maybe(
Expand All @@ -51,6 +57,7 @@ export const config: PluginConfigDescriptor<CloudConfigType> = {
performance_url: true,
organization_url: true,
profile_url: true,
projects_url: true,
trial_end_date: true,
is_elastic_staff_owned: true,
serverless: {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/serverless/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"requiredPlugins": [
"kibanaReact",
"management",
"cloud"
],
"optionalPlugins": [],
"requiredBundles": []
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/serverless/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export class ServerlessPlugin

// Casting the "chrome.projects" service to an "internal" type: this is intentional to obscure the property from Typescript.
const { project } = core.chrome as InternalChromeStart;
if (dependencies.cloud.projectsUrl) {
project.setProjectsUrl(dependencies.cloud.projectsUrl);
}

return {
setSideNavComponent: (sideNavigationComponent) =>
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/serverless/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
ChromeProjectNavigationNode,
} from '@kbn/core-chrome-browser';
import type { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public';
import type { Observable } from 'rxjs';

// eslint-disable-next-line @typescript-eslint/no-empty-interface
Expand All @@ -31,8 +32,10 @@ export interface ServerlessPluginStart {

export interface ServerlessPluginSetupDependencies {
management: ManagementSetup;
cloud: CloudSetup;
}

export interface ServerlessPluginStartDependencies {
management: ManagementStart;
cloud: CloudStart;
}
1 change: 1 addition & 0 deletions x-pack/plugins/serverless/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@
"@kbn/core-chrome-browser",
"@kbn/core-chrome-browser-internal",
"@kbn/i18n-react",
"@kbn/cloud-plugin",
]
}
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,6 @@
"core.ui.overlays.banner.attentionTitle": "Attention",
"core.ui.overlays.banner.closeButtonLabel": "Fermer",
"core.ui.primaryNav.addData": "Ajouter des intégrations",
"core.ui.primaryNav.cloud.linkToDeployments": "Mes déploiements",
"core.ui.primaryNav.goToHome.ariaLabel": "Accéder à la page d’accueil",
"core.ui.primaryNav.pinnedLinksAriaLabel": "Liens épinglés",
"core.ui.primaryNav.screenReaderLabel": "Principale",
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,6 @@
"core.ui.overlays.banner.attentionTitle": "注意",
"core.ui.overlays.banner.closeButtonLabel": "閉じる",
"core.ui.primaryNav.addData": "統合の追加",
"core.ui.primaryNav.cloud.linkToDeployments": "マイデプロイ",
"core.ui.primaryNav.goToHome.ariaLabel": "ホームページに移動",
"core.ui.primaryNav.pinnedLinksAriaLabel": "ピン留めされたリンク",
"core.ui.primaryNav.screenReaderLabel": "プライマリ",
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,6 @@
"core.ui.overlays.banner.attentionTitle": "注意",
"core.ui.overlays.banner.closeButtonLabel": "关闭",
"core.ui.primaryNav.addData": "添加集成",
"core.ui.primaryNav.cloud.linkToDeployments": "我的部署",
"core.ui.primaryNav.goToHome.ariaLabel": "前往主页",
"core.ui.primaryNav.pinnedLinksAriaLabel": "置顶链接",
"core.ui.primaryNav.screenReaderLabel": "主分片",
Expand Down

0 comments on commit 1047eef

Please sign in to comment.