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

New homepage #5613

Closed
wants to merge 67 commits into from
Closed
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
0e4a30d
Layout initial new homepage implementation
BSFishy Dec 14, 2023
1572cac
Add some things I for some reason didn't get in the initial commit
BSFishy Dec 14, 2023
7babcc1
Add formatting line
BSFishy Dec 14, 2023
8a48a5f
Flesh out some more of the homepage implementation
BSFishy Dec 14, 2023
f9183d4
Add doc comment explaining get homepage function
BSFishy Dec 14, 2023
ca0eb55
Remove unused function
BSFishy Dec 14, 2023
76ec36a
Rename functions to more accurately describe what they do
BSFishy Dec 14, 2023
1c00578
WE HAVE RENDERING
BSFishy Dec 15, 2023
c4eea91
Make some fixed/clarifications around the lazy rendering
BSFishy Dec 15, 2023
f87bb41
Add basic layout for hero sections and sections
BSFishy Dec 15, 2023
cb4538c
Set up proper section rendering
BSFishy Dec 15, 2023
35ffb80
Add page layout
BSFishy Dec 15, 2023
6a8ae77
Add homepage saved object edit button
BSFishy Dec 18, 2023
ea5b7e1
Memoize section content
BSFishy Dec 19, 2023
f50aa73
Add data section
BSFishy Dec 19, 2023
c0203d4
Add learn basics section
BSFishy Dec 19, 2023
e192c1a
Small cleanup things
BSFishy Dec 19, 2023
06a18f3
Misc changes
BSFishy Dec 21, 2023
1d45b7c
Remove custom card display
BSFishy Jan 4, 2024
cfe4512
Fix breadcrumbs not updating
BSFishy Jan 4, 2024
2fc43e4
Add small todo comment
BSFishy Jan 4, 2024
afedf5b
Inline section rendering
BSFishy Jan 4, 2024
ad7e3bd
Fix section type service mock
BSFishy Jan 8, 2024
9892fa3
Fix jest tests
BSFishy Jan 8, 2024
950f892
Merge branch 'main' into newest-home
BSFishy Jan 8, 2024
f66827e
Fix the test mocks
BSFishy Jan 8, 2024
c60d61e
Add throw tests
BSFishy Jan 8, 2024
0ffeea4
Remove default hero section
BSFishy Jan 8, 2024
decff05
Add a few more tests
BSFishy Jan 8, 2024
ea10edb
Add footer
BSFishy Jan 9, 2024
b0b9721
Fix some of the testing
BSFishy Jan 9, 2024
dd23069
Add homepage saved object test
BSFishy Jan 9, 2024
86e63b3
Add basic getHomepage test
BSFishy Jan 9, 2024
a91d9aa
Remove copilot comments
BSFishy Jan 9, 2024
70e0ff2
Add some more tests to ensure functionality is as intended
BSFishy Jan 11, 2024
ebaddb6
Remove unused file
BSFishy Jan 11, 2024
c24a44e
Add test subjects
BSFishy Jan 12, 2024
18cfbe0
Update changelog
BSFishy Jan 16, 2024
0626331
Update with guidance from UX
BSFishy Jan 16, 2024
e68b7e0
Convert homepage to use observables
BSFishy Jan 16, 2024
c9b225a
Add doc comment
BSFishy Jan 16, 2024
4d5e2ef
Finish functionality for observable based homepage
BSFishy Jan 17, 2024
e25eecb
Rename heros to heroes
BSFishy Jan 17, 2024
3d5224d
Update footer i18n ids
BSFishy Jan 17, 2024
07948ad
Extract layout into its own component
BSFishy Jan 17, 2024
063a3f7
Make the new home experience configurable
BSFishy Jan 18, 2024
a004be0
Move all legacy home stuff into legacy folder
BSFishy Jan 19, 2024
9f1f88b
Update loading and error designs
BSFishy Jan 22, 2024
e3ccc61
Change from Webpack import to file path
BSFishy Jan 22, 2024
99eedf6
Add config value for disabling new homepage
BSFishy Jan 22, 2024
32844b3
Reverse list
BSFishy Jan 22, 2024
bb7d2e3
Redo some of the comments
BSFishy Jan 22, 2024
fc12da9
Remove old todo comment
BSFishy Jan 22, 2024
ae334f9
Merge branch 'main' into newest-home
BSFishy Jan 22, 2024
40ffea4
Add welcome screen & branding & fix tests
BSFishy Jan 23, 2024
7f33cd4
Make new homepage disabled by default
BSFishy Jan 24, 2024
f839074
Change disable homepage behavior
BSFishy Jan 24, 2024
2b16a10
Change some names around
BSFishy Jan 24, 2024
7899ca5
Add back recently accessed
BSFishy Jan 24, 2024
c2176cd
Reduce weight of ingestion image
BSFishy Jan 24, 2024
14aa57a
Minor comment addressing
BSFishy Jan 25, 2024
9e4554f
Update learn section with UX feedback
BSFishy Jan 25, 2024
018c984
Merge branch 'main' into newest-home
BSFishy Jan 25, 2024
a61ef5d
Small redesign cleanup
BSFishy Jan 25, 2024
cd0da80
Fix useShowWelcome semantics
BSFishy Jan 29, 2024
083eb3f
Actually fix show welcome this time
BSFishy Jan 29, 2024
9e0d5b3
Rename config option
BSFishy Jan 29, 2024
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
4 changes: 1 addition & 3 deletions src/plugins/home/opensearch_dashboards.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@
"ui": true,
"requiredPlugins": ["data", "urlForwarding"],
"optionalPlugins": ["usageCollection", "telemetry", "dataSource"],
"requiredBundles": [
"opensearchDashboardsReact", "dataSourceManagement"
]
"requiredBundles": ["opensearchDashboardsReact", "dataSourceManagement", "savedObjects"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
@import "synopsis";
@import "welcome";
@import "tutorial/tutorial";
@import "homepage/homepage";
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import React from 'react';
import { I18nProvider } from '@osd/i18n/react';
import PropTypes from 'prop-types';
import { Home } from './home';
import { Homepage } from './homepage';
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
import { FeatureDirectory } from './feature_directory';
import { TutorialDirectory } from './tutorial_directory';
import { Tutorial } from './tutorial/tutorial';
Expand Down Expand Up @@ -92,7 +93,7 @@ export function HomeApp({ directories, solutions }) {
<Route exact path="/feature_directory">
<FeatureDirectory addBasePath={addBasePath} directories={directories} />
</Route>
<Route exact path="/">
<Route exact path="/legacy">
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
<Home
addBasePath={addBasePath}
directories={directories}
Expand All @@ -103,6 +104,9 @@ export function HomeApp({ directories, solutions }) {
telemetry={telemetry}
/>
</Route>
<Route exact path="/">
<Homepage />
</Route>
<Route path="*" exact={true} component={RedirectToDefaultApp} />
</Switch>
</Router>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.home-homepage-pageBody {
Copy link
Member

Choose a reason for hiding this comment

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

nit:

Suggested change
.home-homepage-pageBody {
.homepagePage {

following BEM

// This is needed to make sure the page body is not wider than the page.
// This is otherwise not possible with the props on EuiPageTemplate.
padding: 0 $euiSizeL;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { FC } from 'react';
import { EuiPanel } from '@elastic/eui';
import { RenderFn } from '../../../services/section_type/section_type';
import { LazyRender } from './lazy_render';

interface Props {
render: RenderFn;
}

export const HeroSection: FC<Props> = ({ render }) => {
return (
<EuiPanel hasBorder={false} hasShadow={false}>
<LazyRender render={render} />
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState, useEffect } from 'react';
import { i18n } from '@osd/i18n';
import { EuiPageTemplate, EuiButtonEmpty } from '@elastic/eui';
import { Homepage as HomepageType } from '../../../services/section_type/section_type';
import { getServices } from '../../opensearch_dashboards_services';
import { HeroSection } from './hero_section';
import { Section } from './section';

export const Homepage = () => {
const { sectionTypes, application } = getServices();
const getUrl = application.getUrlForApp;

// TODO: ideally, this should be some sort of observable so changes can be made without having to explicitly hit a save button
const [homepage, setHomepage] = useState<HomepageType>();
const [error, setError] = useState();
const isLoading = !homepage && !error;

useEffect(() => {
sectionTypes.getHomepage().then(setHomepage).catch(setError);
}, [sectionTypes]);

if (isLoading) {
return <span>Loading...</span>;
}

if (error) {
// TODO: what is the correct way to handle errors here?
// eslint-disable-next-line no-console
console.error(error);

return <span>Error loading homepage</span>;
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
}

const sideItems: React.ReactNode[] = [
<EuiButtonEmpty iconType="indexOpen" href={getUrl('home', { path: '#/tutorial_directory' })}>
Add data
</EuiButtonEmpty>,
<EuiButtonEmpty iconType="gear" href={getUrl('management')}>
Manage
</EuiButtonEmpty>,
<EuiButtonEmpty iconType="wrench" href={getUrl('dev_tools', { path: '#/console' })}>
Dev tools
</EuiButtonEmpty>,
].reverse();

function renderSections() {
return homepage!.sections.map(({ render, title, description, links }, i) => (
<Section key={i} title={title} description={description} links={links} render={render} />
));
}

const hero = homepage!.heroes[0];

return (
<EuiPageTemplate
restrictWidth={1400}
pageHeader={{
pageTitle: i18n.translate('home.title', { defaultMessage: 'Home' }),
rightSideItems: sideItems,
alignItems: 'center',
}}
pageContentProps={{
color: 'transparent',
hasBorder: false,
hasShadow: false,
}}
pageContentBodyProps={{
paddingSize: 'none',
className: 'home-homepage-pageBody',
}}
>
{hero && <HeroSection render={hero.render} />}
{renderSections()}
</EuiPageTemplate>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { Homepage } from './homepage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { FC, useRef, useEffect } from 'react';
import { RenderFn } from '../../../services/section_type/section_type';

interface Props {
render: RenderFn;
}

export const LazyRender: FC<Props> = ({ render }) => {
const ref = useRef(null);

// by using a useEffect here, this should be a 2 birds with 1 stone situation, where we defer rendering and also get the unmount behavior at the same time
useEffect(() => {
if (!ref.current) {
return;
}

return render(ref.current);
}, [render]);

// display: contents is used so that this component doesn't affect the rendering of the child render function
return <div style={{ display: 'contents' }} ref={ref} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { FC, useState } from 'react';
import {
EuiPanel,
EuiButtonIcon,
EuiTitle,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
EuiLink,
} from '@elastic/eui';
import { RenderFn, Section as SectionType } from '../../../services/section_type/section_type';
import { LazyRender } from './lazy_render';

interface Props {
render: RenderFn;
title: SectionType['title'];
description?: SectionType['description'];
links?: SectionType['links'];
}

// TODO: the way this is implemented currently will mount and unmount whenever the section is expanded/collapsed. Do we want to keep it this way?
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
export const Section: FC<Props> = ({ render, title, description, links }) => {
const [isExpanded, setExpanded] = useState(true);

const hasDescription = !!description;
const hasLinks = !!links && links.length > 0;
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
const hasDescriptionSection = hasDescription || hasLinks;
const hasDescriptionSpacer = hasDescription && hasLinks;

const toggleExpanded = () => setExpanded((expanded) => !expanded);

return (
<EuiPanel hasBorder={false} hasShadow={false} paddingSize="none" color="transparent">
<EuiFlexGroup direction="row" alignItems="center" gutterSize="s" responsive={false}>
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType={isExpanded ? 'arrowUp' : 'arrowRight'}
onClick={toggleExpanded}
size="s"
iconSize="m"
aria-label={isExpanded ? 'Collapse section' : 'Expand section'}
BSFishy marked this conversation as resolved.
Show resolved Hide resolved
/>
</EuiFlexItem>
<EuiFlexItem grow>
<EuiTitle size="l">
<h2>{title}</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
{isExpanded && (
<EuiFlexGroup direction="row">
{hasDescriptionSection && (
<EuiFlexItem grow={1}>
{description}
{hasDescriptionSpacer && <EuiSpacer />}
{hasLinks && links.map(({ label, url }, i) => <EuiLink href={url}>{label}</EuiLink>)}
</EuiFlexItem>
)}
<EuiFlexItem grow={3}>
<LazyRender render={render} />
</EuiFlexItem>
</EuiFlexGroup>
)}
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { UrlForwardingStart } from '../../../url_forwarding/public';
import { TutorialService } from '../services/tutorials';
import { FeatureCatalogueRegistry } from '../services/feature_catalogue';
import { EnvironmentService } from '../services/environment';
import { SectionTypeService } from '../services/section_type';
import { ConfigSchema } from '../../config';
import { HomePluginBranding } from '..';
import { DataSourcePluginStart } from '../../../data_source/public';
Expand Down Expand Up @@ -73,6 +74,7 @@ export interface HomeOpenSearchDashboardsServices {
getBranding: () => HomePluginBranding;
};
dataSource?: DataSourcePluginStart;
sectionTypes: SectionTypeService;
}

let services: HomeOpenSearchDashboardsServices | null = null;
Expand Down
31 changes: 27 additions & 4 deletions src/plugins/home/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
FeatureCatalogueRegistrySetup,
TutorialService,
TutorialServiceSetup,
SectionTypeService,
SectionTypeServiceSetup,
} from './services';
import { ConfigSchema } from '../config';
import { setServices } from './application/opensearch_dashboards_services';
Expand All @@ -58,6 +60,8 @@
import { PLUGIN_ID, HOME_APP_BASE_PATH } from '../common/constants';
import { DataSourcePluginStart } from '../../data_source/public';

import { renderFn } from './testing';

export interface HomePluginStartDependencies {
data: DataPublicPluginStart;
telemetry?: TelemetryPluginStart;
Expand All @@ -81,6 +85,7 @@
private readonly featuresCatalogueRegistry = new FeatureCatalogueRegistry();
private readonly environmentService = new EnvironmentService();
private readonly tutorialService = new TutorialService();
private readonly sectionTypeService = new SectionTypeService();

constructor(private readonly initializerContext: PluginInitializerContext<ConfigSchema>) {}

Expand Down Expand Up @@ -122,6 +127,7 @@
featureCatalogue: this.featuresCatalogueRegistry,
injectedMetadata: coreStart.injectedMetadata,
dataSource,
sectionTypes: this.sectionTypeService,
});
coreStart.chrome.docTitle.change(
i18n.translate('home.pageTitle', { defaultMessage: 'Home' })
Expand Down Expand Up @@ -149,18 +155,34 @@
order: 500,
});

const sectionTypes = { ...this.sectionTypeService.setup() };

Check warning on line 158 in src/plugins/home/public/plugin.ts

View check run for this annotation

Codecov / codecov/patch

src/plugins/home/public/plugin.ts#L158

Added line #L158 was not covered by tests

// TODO: register base section types
sectionTypes.registerHeroSection({ id: 'hello:world', render: renderFn });
sectionTypes.registerSection({

Check warning on line 162 in src/plugins/home/public/plugin.ts

View check run for this annotation

Codecov / codecov/patch

src/plugins/home/public/plugin.ts#L161-L162

Added lines #L161 - L162 were not covered by tests
id: 'hello:world',
title: 'Hello world!',
description: 'This is a description',
links: [{ label: 'Link', url: 'https://google.com' }],
render: renderFn,
});

return {
featureCatalogue,
environment: { ...this.environmentService.setup() },
tutorials: { ...this.tutorialService.setup() },
sectionTypes,
};
}

public start(
{ application: { capabilities, currentAppId$ }, http }: CoreStart,
{ urlForwarding }: HomePluginStartDependencies
) {
public start(core: CoreStart, { data, urlForwarding }: HomePluginStartDependencies) {
const {
application: { capabilities, currentAppId$ },
http,
} = core;

Check warning on line 182 in src/plugins/home/public/plugin.ts

View check run for this annotation

Codecov / codecov/patch

src/plugins/home/public/plugin.ts#L182

Added line #L182 was not covered by tests

this.featuresCatalogueRegistry.start({ capabilities });
this.sectionTypeService.start({ core, data });

Check warning on line 185 in src/plugins/home/public/plugin.ts

View check run for this annotation

Codecov / codecov/patch

src/plugins/home/public/plugin.ts#L185

Added line #L185 was not covered by tests

// If the home app is the initial location when loading OpenSearch Dashboards...
if (
Expand Down Expand Up @@ -204,6 +226,7 @@
*/

environment: EnvironmentSetup;
sectionTypes: SectionTypeServiceSetup;
}
export interface HomePublicPluginStart {
featureCatalogue: FeatureCatalogueRegistry;
Expand Down
Loading
Loading