Skip to content

Commit

Permalink
[Workspace][Page header] Integrate new page header for workspace pages (
Browse files Browse the repository at this point in the history
#7697)

* init page headers for workspace

Signed-off-by: tygao <tygao@amazon.com>

* update

Signed-off-by: tygao <tygao@amazon.com>

* update list page

Signed-off-by: tygao <tygao@amazon.com>

* Changeset file for PR #7697 created/updated

---------

Signed-off-by: tygao <tygao@amazon.com>
Co-authored-by: opensearch-changeset-bot[bot] <154024398+opensearch-changeset-bot[bot]@users.noreply.github.com>
  • Loading branch information
raintygao and opensearch-changeset-bot[bot] authored Aug 15, 2024
1 parent 7aef6e3 commit 36af5e7
Show file tree
Hide file tree
Showing 20 changed files with 874 additions and 423 deletions.
2 changes: 2 additions & 0 deletions changelogs/fragments/7697.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Integrate new page header for workspace pages ([#7697](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/7697))
3 changes: 2 additions & 1 deletion src/plugins/management/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"server": true,
"ui": true,
"optionalPlugins": ["home", "managementOverview"],
"requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils"]
"requiredBundles": ["opensearchDashboardsReact", "opensearchDashboardsUtils"],
"requiredPlugins": ["navigation"]
}

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

Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { FeatureCards } from './feature_cards';
import { AppCategory, ChromeNavLink } from 'opensearch-dashboards/public';
import { navigationPluginMock } from '../../../../navigation/public/mocks';
import { coreMock } from '../../../../../../src/core/public/mocks';

const mockCategory: AppCategory = {
id: 'dashboard',
label: 'Dashboard',
order: 2,
};

const mockSetAppDescriptionControls = coreMock.createStart().application.setAppDescriptionControls;
const mockNavigationUI = navigationPluginMock.createStartContract().ui;
mockNavigationUI.HeaderControl = () => null;

const navLinks: ChromeNavLink[] = [
{
id: '1',
Expand Down Expand Up @@ -85,18 +91,25 @@ const navLinks: ChromeNavLink[] = [
describe('<FeatureCards />', () => {
it('render with empty navLinks', () => {
const { container } = render(
<FeatureCards getStartedCards={[]} pageTitle="" navLinks={[]} navigateToApp={jest.fn()} />
<FeatureCards
pageDescription=""
navLinks={[]}
navigateToApp={jest.fn()}
setAppDescriptionControls={mockSetAppDescriptionControls}
navigationUI={mockNavigationUI}
/>
);
expect(container).toMatchSnapshot();
});

it('render with complex navLinks', () => {
const { container, getAllByTestId } = render(
<FeatureCards
getStartedCards={[]}
pageTitle=""
pageDescription=""
navLinks={navLinks}
navigateToApp={jest.fn()}
setAppDescriptionControls={mockSetAppDescriptionControls}
navigationUI={mockNavigationUI}
/>
);
expect(container).toMatchSnapshot();
Expand All @@ -107,10 +120,11 @@ describe('<FeatureCards />', () => {
const mockedNavigateToApp = jest.fn();
const { getByTestId } = render(
<FeatureCards
getStartedCards={[]}
pageTitle=""
pageDescription=""
navLinks={navLinks}
navigateToApp={mockedNavigateToApp}
setAppDescriptionControls={mockSetAppDescriptionControls}
navigationUI={mockNavigationUI}
/>
);
fireEvent.click(getByTestId('landingPageFeature_1'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,32 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { i18n } from '@osd/i18n';
import {
EuiCard,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiPageContent,
EuiPageHeader,
EuiPageHeaderSection,
EuiPanel,
EuiSpacer,
EuiTitle,
} from '@elastic/eui';
import { AppCategory, ChromeNavLink, CoreStart } from 'opensearch-dashboards/public';
import React, { useMemo } from 'react';
import { NavigationPublicPluginStart } from '../../../../../../src/plugins/navigation/public';

export interface FeatureCardsProps {
pageTitle: string;
pageDescription: string;
navLinks: ChromeNavLink[];
navigateToApp: CoreStart['application']['navigateToApp'];
getStartedCards: Array<{
id: string;
title: string;
description: string;
}>;
setAppDescriptionControls: CoreStart['application']['setAppDescriptionControls'];
navigationUI: NavigationPublicPluginStart['ui'];
}

const getStartedTitle = i18n.translate('management.gettingStarted.label', {
defaultMessage: 'Get started',
});

export const FeatureCards = ({
navLinks,
navigateToApp,
pageTitle,
getStartedCards,
setAppDescriptionControls,
pageDescription,
navigationUI: { HeaderControl },
}: FeatureCardsProps) => {
const itemsPerRow = 4;
const groupedCardForDisplay = useMemo(() => {
Expand All @@ -65,41 +55,14 @@ export const FeatureCards = ({
}
return (
<>
<EuiPageContent borderRadius="none">
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{pageTitle}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
{getStartedCards.length ? (
<>
<EuiSpacer size="s" />
<EuiTitle>
<h3>{getStartedTitle}</h3>
</EuiTitle>
<EuiFlexGrid columns={4}>
{getStartedCards.map((card) => {
return (
<EuiFlexItem>
<EuiPanel>
<EuiCard
title={card.title}
description={card.description}
data-test-subj={`getStartedCard_${card.id}`}
textAlign="left"
onClick={() => navigateToApp(card.id)}
titleSize="xs"
/>
</EuiPanel>
</EuiFlexItem>
);
})}
</EuiFlexGrid>
</>
) : null}
</EuiPageContent>
<HeaderControl
controls={[
{
description: pageDescription,
},
]}
setMountPoint={setAppDescriptionControls}
/>
<EuiPageContent hasShadow={false} hasBorder={false} color="transparent">
{groupedCardForDisplay.map((group) => (
<div key={group.category?.id}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/

import { renderApp } from './landing_page_application';
import { navigationPluginMock } from '../../navigation/public/mocks';
import { coreMock } from '../../../../src/core/public/mocks';

describe('Landing page application', () => {
it('renders and unmount without crashing', () => {
Expand All @@ -13,6 +15,9 @@ describe('Landing page application', () => {
props: {
navigateToApp: jest.fn(),
navLinks: [],
navigationUI: navigationPluginMock.createStartContract().ui,
setAppDescriptionControls: coreMock.createStart().application.setAppDescriptionControls,
pageDescription: '',
},
});

Expand Down
58 changes: 46 additions & 12 deletions src/plugins/management/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import {
AppNavLinkStatus,
DEFAULT_NAV_GROUPS,
WorkspaceAvailability,
ChromeNavLink,
} from '../../../core/public';

import { MANAGEMENT_APP_ID } from '../common/contants';
Expand All @@ -62,13 +61,17 @@ import {
LinkItemType,
getSortedNavLinks,
} from '../../../core/public';
import { NavigationPublicPluginStart } from '../../../../src/plugins/navigation/public';

interface ManagementSetupDependencies {
home?: HomePublicPluginSetup;
managementOverview?: ManagementOverViewPluginSetup;
}

export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart> {
interface ManagementStartDependencies {
navigation: NavigationPublicPluginStart;
}
export class ManagementPlugin
implements Plugin<ManagementSetup, ManagementStart, {}, ManagementStartDependencies> {
private readonly managementSections = new ManagementSectionsService();

private readonly appUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
Expand All @@ -81,7 +84,10 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
defaultMessage: 'Dashboards Management',
});

public setup(core: CoreSetup, { home, managementOverview }: ManagementSetupDependencies) {
public setup(
core: CoreSetup<ManagementStartDependencies>,
{ home, managementOverview }: ManagementSetupDependencies
) {
const opensearchDashboardsVersion = this.initializerContext.env.packageInfo.version;

core.application.register({
Expand Down Expand Up @@ -111,15 +117,30 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
const settingsLandingPageId = 'settings_landing';

const settingsLandingPageTitle = i18n.translate('management.settings.landingPage.title', {
defaultMessage: 'Settings and setup',
defaultMessage: 'Settings and setup overview',
});

const settingsLandingPageDescription = i18n.translate(
'management.settings.landingPage.description',
{
defaultMessage:
'Customize the appearance of the application, change feature behavior, and more.',
}
);

const dataAdministrationLandingPageId = 'data_administration_landing';

const dataAdministrationPageTitle = i18n.translate(
'management.dataAdministration.landingPage.title',
{
defaultMessage: 'Data administration',
defaultMessage: 'Data administration overview',
}
);

const dataAdministrationPageDescription = i18n.translate(
'management.dataAdministration.landingPage.description',
{
defaultMessage: 'Configure automation and access control policies to manage your data.',
}
);

Expand Down Expand Up @@ -186,18 +207,24 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
mount: async (params: AppMountParameters) => {
const { renderApp } = await import('./landing_page_application');
const [coreStart] = await core.getStartServices();
const [coreStart, { navigation }] = await core.getStartServices();
const navLinks = (
await getNavLinksByNavGroupId(DEFAULT_NAV_GROUPS.settingsAndSetup.id)
).filter((navLink) => navLink.id !== settingsLandingPageId);

coreStart.chrome.setBreadcrumbs([
{
text: settingsLandingPageTitle,
},
]);
return renderApp({
mountElement: params.element,
props: {
navigateToApp: coreStart.application.navigateToApp,
setAppDescriptionControls: coreStart.application.setAppDescriptionControls,
navLinks,
pageTitle: settingsLandingPageTitle,
getStartedCards: [],
pageDescription: settingsLandingPageDescription,
navigationUI: navigation.ui,
},
});
},
Expand All @@ -213,18 +240,25 @@ export class ManagementPlugin implements Plugin<ManagementSetup, ManagementStart
workspaceAvailability: WorkspaceAvailability.outsideWorkspace,
mount: async (params: AppMountParameters) => {
const { renderApp } = await import('./landing_page_application');
const [coreStart] = await core.getStartServices();
const [coreStart, { navigation }] = await core.getStartServices();
const navLinks = (
await getNavLinksByNavGroupId(DEFAULT_NAV_GROUPS.dataAdministration.id)
).filter((navLink) => navLink.id !== dataAdministrationLandingPageId);

coreStart.chrome.setBreadcrumbs([
{
text: dataAdministrationPageTitle,
},
]);

return renderApp({
mountElement: params.element,
props: {
navigateToApp: coreStart.application.navigateToApp,
navLinks,
pageTitle: dataAdministrationPageTitle,
getStartedCards: [],
pageDescription: dataAdministrationPageDescription,
navigationUI: navigation.ui,
setAppDescriptionControls: coreStart.application.setAppDescriptionControls,
},
});
},
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/workspace/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"ui": true,
"requiredPlugins": [
"savedObjects",
"opensearchDashboardsReact"
"opensearchDashboardsReact",
"navigation"
],
"optionalPlugins": ["savedObjectsManagement","management","dataSourceManagement","contentManagement"],
"requiredBundles": ["opensearchDashboardsReact", "home","dataSource"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ const WorkspaceCreator = ({
},
},
dataSourceManagement: {},
navigationUI: {
HeaderControl: () => null,
},
},
});
const registeredUseCases$ = new BehaviorSubject([
Expand Down
Loading

0 comments on commit 36af5e7

Please sign in to comment.