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

Add navControlsPrimaryHeaderRight slot to header #9223

2 changes: 2 additions & 0 deletions changelogs/fragments/9223.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Add navControlsNewPrimaryHeaderRight slot to header ([#9223](/~https://github.com/opensearch-project/OpenSearch-Dashboards/pull/9223))
2 changes: 2 additions & 0 deletions src/core/public/chrome/chrome_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ const createStartContractMock = () => {
registerCenter: jest.fn(),
registerRight: jest.fn(),
registerLeftBottom: jest.fn(),
registerNewPrimaryHeaderRight: jest.fn(),
getLeft$: jest.fn(),
getCenter$: jest.fn(),
getRight$: jest.fn(),
getLeftBottom$: jest.fn(),
getNewPrimaryHeaderRight$: jest.fn(),
},
navGroup: {
getNavGroupsMap$: jest.fn(() => new BehaviorSubject({})),
Expand Down
1 change: 1 addition & 0 deletions src/core/public/chrome/chrome_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ export class ChromeService {
navControlsExpandedCenter$={navControls.getExpandedCenter$()}
navControlsExpandedRight$={navControls.getExpandedRight$()}
navControlsLeftBottom$={navControls.getLeftBottom$()}
navControlsNewPrimaryHeaderRight$={navControls.getNewPrimaryHeaderRight$()}
onIsLockedUpdate={setIsNavDrawerLocked}
isLocked$={getIsNavDrawerLocked$}
branding={injectedMetadata.getBranding()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,28 @@ describe('RecentlyAccessed#start()', () => {
expect(await navControls.getLeftBottom$().pipe(take(1)).toPromise()).toEqual([nc2, nc1, nc3]);
});
});

describe('new primary header right controls', () => {
it('allows registration', async () => {
const navControls = getStart();
const nc = { mount: jest.fn() };
navControls.registerNewPrimaryHeaderRight(nc);
expect(await navControls.getNewPrimaryHeaderRight$().pipe(take(1)).toPromise()).toEqual([nc]);
});

it('sorts controls by order property', async () => {
const navControls = getStart();
const nc1 = { mount: jest.fn(), order: 10 };
const nc2 = { mount: jest.fn(), order: 0 };
const nc3 = { mount: jest.fn(), order: 20 };
navControls.registerNewPrimaryHeaderRight(nc1);
navControls.registerNewPrimaryHeaderRight(nc2);
navControls.registerNewPrimaryHeaderRight(nc3);
expect(await navControls.getNewPrimaryHeaderRight$().pipe(take(1)).toPromise()).toEqual([
nc2,
nc1,
nc3,
]);
});
});
});
17 changes: 17 additions & 0 deletions src/core/public/chrome/nav_controls/nav_controls_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export interface ChromeNavControls {
registerCenter(navControl: ChromeNavControl): void;
/** Register a nav control to be presented on the left-bottom side of the left navigation. */
registerLeftBottom(navControl: ChromeNavControl): void;
/** Register a nav control to be presented on the right side of the new primary chrome header. */
Copy link
Member

Choose a reason for hiding this comment

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

what does the "new primary chrome header" refer to?

Copy link
Member

Choose a reason for hiding this comment

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

So we're trying to introduce an API to register a global control button which is available for all application headers and page headers. Can we simply call it registerHeaderRight?

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'm open to renaming it to registerHeaderRight. I just want to add some explanations for my naming convention. I added 'New' to distinguish it from the legacy header since this slot won't be displayed in that header. I added 'Primary' to distinguish it from the secondary header, as it's positioned on the right side of the primary header. Do you think this naming convention is reasonable? Using 'headerRight' is simpler, but I'm not sure if it might confuse others into thinking that the registered elements won't be displayed.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the explanation! I got the point of "Primary" now :)
For "New", since legacy header is meant to be deprecated, so I don't feel necessary to distinguish it from the legacy one, imagine in the future, the legacy header was removed, then the "New" will sound a bit strange. what about calling it registerPrimaryHeaderRight?

registerNewPrimaryHeaderRight(navControl: ChromeNavControl): void;
/** @internal */
getLeft$(): Observable<ChromeNavControl[]>;
/** @internal */
Expand All @@ -72,6 +74,8 @@ export interface ChromeNavControls {
getCenter$(): Observable<ChromeNavControl[]>;
/** @internal */
getLeftBottom$(): Observable<ChromeNavControl[]>;
/** @internal */
getNewPrimaryHeaderRight$(): Observable<ChromeNavControl[]>;
}

/** @internal */
Expand All @@ -87,6 +91,9 @@ export class NavControlsService {
new Set()
);
const navControlsLeftBottom$ = new BehaviorSubject<ReadonlySet<ChromeNavControl>>(new Set());
const navControlsNewPrimaryHeaderRight$ = new BehaviorSubject<ReadonlySet<ChromeNavControl>>(
new Set()
);

return {
// In the future, registration should be moved to the setup phase. This
Expand Down Expand Up @@ -115,6 +122,11 @@ export class NavControlsService {
new Set([...navControlsLeftBottom$.value.values(), navControl])
),

registerNewPrimaryHeaderRight: (navControl: ChromeNavControl) =>
navControlsNewPrimaryHeaderRight$.next(
new Set([...navControlsNewPrimaryHeaderRight$.value.values(), navControl])
),

getLeft$: () =>
navControlsLeft$.pipe(
map((controls) => sortBy([...controls.values()], 'order')),
Expand Down Expand Up @@ -145,6 +157,11 @@ export class NavControlsService {
map((controls) => sortBy([...controls.values()], 'order')),
takeUntil(this.stop$)
),
getNewPrimaryHeaderRight$: () =>
navControlsNewPrimaryHeaderRight$.pipe(
map((controls) => sortBy([...controls.values()], 'order')),
takeUntil(this.stop$)
),
};
}

Expand Down
Loading
Loading