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

[Manual backport 2.x] Introduce the redesign page and applications headers behind a switch (#7637) #7692

Merged
merged 1 commit into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions changelogs/fragments/7637.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Introduce the redesign page and applications headers behind a switch ([#7637](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7637))
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
"dependencies": {
"@aws-crypto/client-node": "^3.1.1",
"@elastic/datemath": "5.0.3",
"@elastic/eui": "npm:@opensearch-project/oui@1.8.1",
"@elastic/eui": "npm:@opensearch-project/oui@1.9.0",
"@elastic/good": "^9.0.1-kibana3",
"@elastic/numeral": "npm:@amoo-miki/[email protected]",
"@elastic/request-crypto": "2.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/osd-ui-framework/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"enzyme-adapter-react-16": "^1.9.1"
},
"devDependencies": {
"@elastic/eui": "npm:@opensearch-project/oui@1.8.1",
"@elastic/eui": "npm:@opensearch-project/oui@1.9.0",
"@osd/babel-preset": "1.0.0",
"@osd/optimizer": "1.0.0",
"comment-stripper": "^0.0.4",
Expand Down
2 changes: 1 addition & 1 deletion packages/osd-ui-shared-deps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"dependencies": {
"@elastic/charts": "31.1.0",
"@elastic/eui": "npm:@opensearch-project/oui@1.8.1",
"@elastic/eui": "npm:@opensearch-project/oui@1.9.0",
"@elastic/numeral": "npm:@amoo-miki/[email protected]",
"@opensearch/datemath": "5.0.3",
"@osd/i18n": "1.0.0",
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions src/core/public/application/application_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ const createStartContractMock = (): jest.Mocked<ApplicationStart> => {
navigateToUrl: jest.fn(),
getUrlForApp: jest.fn(),
registerMountContext: jest.fn(),
setAppLeftControls: jest.fn(),
setAppCenterControls: jest.fn(),
setAppRightControls: jest.fn(),
setAppBadgeControls: jest.fn(),
setAppDescriptionControls: jest.fn(),
setAppBottomControls: jest.fn(),
};
};

Expand Down Expand Up @@ -98,6 +104,18 @@ const createInternalStartContractMock = (): jest.Mocked<InternalApplicationStart
capabilities: capabilitiesServiceMock.createStartContract().capabilities,
currentAppId$: currentAppId$.asObservable(),
currentActionMenu$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentLeftControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentCenterControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentRightControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentBadgeControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentDescriptionControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
currentBottomControls$: new BehaviorSubject<MountPoint | undefined>(undefined),
setAppLeftControls: jest.fn(),
setAppCenterControls: jest.fn(),
setAppRightControls: jest.fn(),
setAppBadgeControls: jest.fn(),
setAppDescriptionControls: jest.fn(),
setAppBottomControls: jest.fn(),
getComponent: jest.fn(),
getUrlForApp: jest.fn(),
navigateToApp: jest.fn().mockImplementation((appId) => currentAppId$.next(appId)),
Expand Down
32 changes: 31 additions & 1 deletion src/core/public/application/application_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from './application_service.test.mocks';

import { createElement } from 'react';
import { BehaviorSubject, Subject } from 'rxjs';
import { BehaviorSubject, Subject, Observable } from 'rxjs';
import { bufferCount, take, takeUntil } from 'rxjs/operators';
import { shallow, mount } from 'enzyme';

Expand All @@ -51,7 +51,9 @@ import {
AppStatus,
AppUpdater,
WorkspaceAvailability,
InternalApplicationStart,
} from './types';
import { MountPoint } from '../types';
import { act } from 'react-dom/test-utils';
import { workspacesServiceMock } from '../mocks';

Expand Down Expand Up @@ -937,6 +939,34 @@ describe('#start()', () => {
expect(setupDeps.redirectTo).not.toHaveBeenCalled();
});
});

describe('AppControls', () => {
test.each(['Left', 'Center', 'Right', 'Badge', 'Description', 'Bottom'])(
'records the App%sControls',
async (container) => {
const { register } = service.setup(setupDeps);

register(Symbol(), createApp({ id: `app${container}` }));
const appStart = await service.start(startDeps);
const setControls = appStart[
`setApp${container}Controls` as keyof InternalApplicationStart
] as (mount: MountPoint | undefined) => void;
const currentControls$ = appStart[
`current${container}Controls$` as keyof InternalApplicationStart
] as Observable<MountPoint | undefined>;

const oldMountPoint = jest.fn();
const expectedMountPoint = jest.fn();

await appStart.navigateToApp(`app${container}`);
setControls(oldMountPoint);
setControls(expectedMountPoint);

const mountPoint = await currentControls$.pipe(take(1)).toPromise();
expect(mountPoint).toBe(expectedMountPoint);
}
);
});
});

describe('#stop()', () => {
Expand Down
142 changes: 142 additions & 0 deletions src/core/public/application/application_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { RecursiveReadonly } from '@osd/utility-types';
import { MountPoint } from '../types';
import { HttpSetup, HttpStart } from '../http';
import { OverlayStart } from '../overlays';
import { HeaderControlsContainer } from '../chrome/constants';
import { ContextSetup, IContextContainer } from '../context';
import { PluginOpaqueId } from '../plugins';
import { AppRouter } from './ui';
Expand Down Expand Up @@ -104,6 +105,12 @@ interface AppUpdaterWrapper {
interface AppInternalState {
leaveHandler?: AppLeaveHandler;
actionMenu?: MountPoint;
leftControls?: MountPoint;
centerControls?: MountPoint;
rightControls?: MountPoint;
badgeControls?: MountPoint;
descriptionControls?: MountPoint;
bottomControls?: MountPoint;
}

/**
Expand All @@ -117,6 +124,15 @@ export class ApplicationService {
private readonly appInternalStates = new Map<string, AppInternalState>();
private currentAppId$ = new BehaviorSubject<string | undefined>(undefined);
private currentActionMenu$ = new BehaviorSubject<MountPoint | undefined>(undefined);

// HeaderControls
private currentLeftControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private currentCenterControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private currentRightControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private currentBadgeControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private currentDescriptionControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);
private currentBottomControls$ = new BehaviorSubject<MountPoint | undefined>(undefined);

private readonly statusUpdaters$ = new BehaviorSubject<Map<symbol, AppUpdaterWrapper>>(new Map());
private readonly subscriptions: Subscription[] = [];
private stop$ = new Subject();
Expand Down Expand Up @@ -291,6 +307,15 @@ export class ApplicationService {

this.currentAppId$.subscribe(() => this.refreshCurrentActionMenu());

this.currentAppId$.subscribe(() => this.refreshCurrentControls(HeaderControlsContainer.LEFT));
this.currentAppId$.subscribe(() => this.refreshCurrentControls(HeaderControlsContainer.CENTER));
this.currentAppId$.subscribe(() => this.refreshCurrentControls(HeaderControlsContainer.RIGHT));
this.currentAppId$.subscribe(() => this.refreshCurrentControls(HeaderControlsContainer.BADGE));
this.currentAppId$.subscribe(() =>
this.refreshCurrentControls(HeaderControlsContainer.DESCRIPTION)
);
this.currentAppId$.subscribe(() => this.refreshCurrentControls(HeaderControlsContainer.BOTTOM));

return {
applications$: applications$.pipe(
map((apps) => new Map([...apps.entries()].map(([id, app]) => [id, getAppInfo(app)]))),
Expand All @@ -306,6 +331,46 @@ export class ApplicationService {
distinctUntilChanged(),
takeUntil(this.stop$)
),

// HeaderControls
currentLeftControls$: this.currentLeftControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),
currentCenterControls$: this.currentCenterControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),
currentRightControls$: this.currentRightControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),
currentBadgeControls$: this.currentBadgeControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),
currentDescriptionControls$: this.currentDescriptionControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),
currentBottomControls$: this.currentBottomControls$.pipe(
distinctUntilChanged(),
takeUntil(this.stop$)
),

setAppLeftControls: (mount: MountPoint | undefined) =>
this.setAppLeftControls(this.currentAppId$.value, mount),
setAppCenterControls: (mount: MountPoint | undefined) =>
this.setAppCenterControls(this.currentAppId$.value, mount),
setAppRightControls: (mount: MountPoint | undefined) =>
this.setAppRightControls(this.currentAppId$.value, mount),
setAppBadgeControls: (mount: MountPoint | undefined) =>
this.setAppBadgeControls(this.currentAppId$.value, mount),
setAppDescriptionControls: (mount: MountPoint | undefined) =>
this.setAppDescriptionControls(this.currentAppId$.value, mount),
setAppBottomControls: (mount: MountPoint | undefined) =>
this.setAppBottomControls(this.currentAppId$.value, mount),

history: this.history!,
registerMountContext: this.mountContext.registerContext,
getUrlForApp: (
Expand Down Expand Up @@ -339,6 +404,12 @@ export class ApplicationService {
appStatuses$={applicationStatuses$}
setAppLeaveHandler={this.setAppLeaveHandler}
setAppActionMenu={this.setAppActionMenu}
setAppLeftControls={this.setAppLeftControls}
setAppCenterControls={this.setAppCenterControls}
setAppRightControls={this.setAppRightControls}
setAppBadgeControls={this.setAppBadgeControls}
setAppDescriptionControls={this.setAppDescriptionControls}
setAppBottomControls={this.setAppBottomControls}
setIsMounting={(isMounting) => httpLoadingCount$.next(isMounting ? 1 : 0)}
/>
);
Expand Down Expand Up @@ -367,6 +438,71 @@ export class ApplicationService {
this.currentActionMenu$.next(currentActionMenu);
};

private setAppLeftControls = (appPath: string | undefined, mount: MountPoint | undefined) =>
this.setAppControls(appPath, mount, HeaderControlsContainer.LEFT);

private setAppCenterControls = (appPath: string | undefined, mount: MountPoint | undefined) =>
this.setAppControls(appPath, mount, HeaderControlsContainer.CENTER);

private setAppRightControls = (appPath: string | undefined, mount: MountPoint | undefined) =>
this.setAppControls(appPath, mount, HeaderControlsContainer.RIGHT);

private setAppBadgeControls = (appPath: string | undefined, mount: MountPoint | undefined) =>
this.setAppControls(appPath, mount, HeaderControlsContainer.BADGE);

private setAppDescriptionControls = (
appPath: string | undefined,
mount: MountPoint | undefined
) => this.setAppControls(appPath, mount, HeaderControlsContainer.DESCRIPTION);

private setAppBottomControls = (appPath: string | undefined, mount: MountPoint | undefined) =>
this.setAppControls(appPath, mount, HeaderControlsContainer.BOTTOM);

private setAppControls = (
appPath: string | undefined,
mount: MountPoint | undefined,
container: HeaderControlsContainer
) => {
if (!appPath) return;

this.appInternalStates.set(appPath, {
...(this.appInternalStates.get(appPath) ?? {}),
[`${container}Controls`]: mount,
});

this.refreshCurrentControls(container);
};

private refreshCurrentControls = (container: HeaderControlsContainer) => {
const appId = this.currentAppId$.getValue();
switch (container) {
case HeaderControlsContainer.LEFT:
return this.currentLeftControls$.next(
appId ? this.appInternalStates.get(appId)?.leftControls : undefined
);
case HeaderControlsContainer.CENTER:
return this.currentCenterControls$.next(
appId ? this.appInternalStates.get(appId)?.centerControls : undefined
);
case HeaderControlsContainer.RIGHT:
return this.currentRightControls$.next(
appId ? this.appInternalStates.get(appId)?.rightControls : undefined
);
case HeaderControlsContainer.BADGE:
return this.currentBadgeControls$.next(
appId ? this.appInternalStates.get(appId)?.badgeControls : undefined
);
case HeaderControlsContainer.DESCRIPTION:
return this.currentDescriptionControls$.next(
appId ? this.appInternalStates.get(appId)?.descriptionControls : undefined
);
case HeaderControlsContainer.BOTTOM:
return this.currentBottomControls$.next(
appId ? this.appInternalStates.get(appId)?.bottomControls : undefined
);
}
};

private async shouldNavigate(overlays: OverlayStart): Promise<boolean> {
const currentAppId = this.currentAppId$.value;
if (currentAppId === undefined) {
Expand Down Expand Up @@ -402,6 +538,12 @@ export class ApplicationService {
this.stop$.next();
this.currentAppId$.complete();
this.currentActionMenu$.complete();
this.currentLeftControls$.complete();
this.currentCenterControls$.complete();
this.currentRightControls$.complete();
this.currentBadgeControls$.complete();
this.currentDescriptionControls$.complete();
this.currentBottomControls$.complete();
this.statusUpdaters$.complete();
this.subscriptions.forEach((sub) => sub.unsubscribe());
window.removeEventListener('beforeunload', this.onBeforeUnload);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ describe('AppRouter', () => {
appStatuses$={mountersToAppStatus$()}
setAppLeaveHandler={noop}
setAppActionMenu={noop}
setAppLeftControls={noop}
setAppCenterControls={noop}
setAppRightControls={noop}
setAppBadgeControls={noop}
setAppDescriptionControls={noop}
setAppBottomControls={noop}
setIsMounting={noop}
/>
);
Expand Down
Loading
Loading