-
Notifications
You must be signed in to change notification settings - Fork 905
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
New homepage #5613
Conversation
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #5613 +/- ##
==========================================
- Coverage 67.03% 67.03% -0.01%
==========================================
Files 3296 3304 +8
Lines 63343 63456 +113
Branches 10087 10104 +17
==========================================
+ Hits 42465 42536 +71
- Misses 18429 18462 +33
- Partials 2449 2458 +9
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
src/plugins/home/public/application/components/homepage/section.tsx
Outdated
Show resolved
Hide resolved
export const homepageSavedObjectType: SavedObjectsType = { | ||
name: 'homepage', | ||
hidden: false, | ||
namespaceType: 'single', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably look into if this is correct or if this value should be something different
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
src/plugins/home/public/application/components/homepage/section.tsx
Outdated
Show resolved
Hide resolved
src/plugins/home/public/application/components/homepage/section.tsx
Outdated
Show resolved
Hide resolved
Signed-off-by: Matt Provost <[email protected]>
telemetry={telemetry} | ||
/> | ||
</Route> | ||
{homeConfig.disableNextHomePage ? ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If disabled, shall we register the new homepage? From the consume logic, it is more like isNextHomePageDefaultIndexPage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was implemented like this after a discussion with @AMoo-Miki. I'm open to different naming, but I think disableNextHomePage
is less confusing. The majority of users are going to just go to the default route, so it effectively functions the same
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, just concern on if we should register the useless route.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The route is not useless, as it needs to be viewable when "off" so that an admin or user can preview it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see the confusion now. I've renamed it to something that better reflects its functionality.
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
Signed-off-by: Matt Provost <[email protected]>
// TODO: is there a better way to check if the title is custom? | ||
const title = | ||
branding.applicationTitle !== 'OpenSearch Dashboards' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Surprisingly no. Different parts of the code consider the default title to be varying cases of this. Since this is what every other place is using, it should be safe enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I must say, for your first real contribution to OSD and considering the size of the PR and the number of not very well-documented features that you've touched here, this is a phenomenally well-written PR. All my comments are nitpicking stuff except for the navigation API change. I did not expect that. Great job! I even played around with the UI and found no issues no matter which way I pushed it. Did not see that coming.
@@ -0,0 +1,9 @@ | |||
.home-homepage-pageBody { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
.home-homepage-pageBody { | |
.homepagePage { |
following BEM
<RedirectAppLinks application={application}> | ||
<EuiButtonEmpty | ||
flush="both" | ||
href={getUrlForApp('management', { path: 'opensearch-dashboards/settings#defaultRoute' })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to do this for all links since they are internal links and this is how you trigger SPA routing
href={getUrlForApp('management', { path: 'opensearch-dashboards/settings#defaultRoute' })} | |
onClick={() => navigateToApp('management', { path: 'opensearch-dashboards/settings#defaultRoute' })} |
const getUrlForApp = application.getUrlForApp; | ||
const { show, save } = application.capabilities.advancedSettings ?? {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const getUrlForApp = application.getUrlForApp; | |
const { show, save } = application.capabilities.advancedSettings ?? {}; | |
const { navigateToApp, capabilities } = application; | |
const { show, save } = capabilities.advancedSettings ?? {}; |
error$.next(undefined); | ||
|
||
// TODO: make this debounce time configurable | ||
const combinedSave$ = combineLatest([heroes$, sections$]).pipe(debounceTime(1000)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
const combinedSave$ = combineLatest([heroes$, sections$]).pipe(debounceTime(1000)); | |
const combinedSections$ = combineLatest([heroes$, sections$]).pipe(debounceTime(1000)); |
const subscriptions = new Subscription(); | ||
|
||
this.fetchHomepageData() | ||
.then((homepage) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
.then((homepage) => { | |
.then((homepageSavedObj) => { |
id: (opts.id as string) || '', | ||
defaults: { | ||
heroes: [], | ||
sections: [{ id: 'home:workWithData' }, { id: 'home:learnBasics' }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was wondering how you'd initialize it. Nice!
const Card: FC<{ | ||
imgSrc: string; | ||
imgAlt: string; | ||
title: string; | ||
description: string; | ||
footerButtonProps?: EuiButtonProps; | ||
footerUrl: string; | ||
footerText: string; | ||
footerExternal?: boolean; | ||
}> = ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
const Card: FC<{ | |
imgSrc: string; | |
imgAlt: string; | |
title: string; | |
description: string; | |
footerButtonProps?: EuiButtonProps; | |
footerUrl: string; | |
footerText: string; | |
footerExternal?: boolean; | |
}> = ({ | |
interface CardProps { | |
imgSrc: string; | |
imgAlt: string; | |
title: string; | |
description: string; | |
footer: { | |
buttonProps?: EuiButtonProps; | |
url: string; | |
text: string; | |
external?: boolean; | |
}; | |
} | |
const Card: FC<CardProps> = ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, i like this pattern. Nit, could use some tests
const sideItems: React.ReactNode[] = [ | ||
<EuiButtonEmpty | ||
iconType="wrench" | ||
href={getUrlForApp('dev_tools', { path: '#/console' })} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, use navigateToApp
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ashwin-pc, to expedite this, can you please make the suggestion and then accept it?
const homepage: SavedHomepage = await this.savedHomepageLoader.get(id); | ||
|
||
if (!id) { | ||
await homepage.save({}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if save()
fail here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in getHomepage
(The function that eventually calls this) he's called out about how errors need to be tested. I dont think he got to that in this iteration. I also see that he's throwing all the errors which mean that its up to the parent function to catch it and handle them. Dont think they are being handled here.
const homepage = sectionTypes.getHomepage(); | ||
|
||
const subscriptions = new Subscription(); | ||
subscriptions.add(homepage.heroes$.subscribe(setHeroes)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i am confused on why we need to add subscriptions on sections and heroes here? Are these built for the functionalities of allowing users to add and delete sections or heroes in the future?
Because currently I see the implementation exposes the registerSection
service API to allow other plugins to register sections or heroes, and it seems like for rendering something like the homepage, we can just fetch all the registered sections and heroes at the start of the application, and render the page all at once without the need of constant listening on them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes the goal is to allow the user to modify these sections and customize the homepage. This PR does not have the editing capability just yet, but it does lay down the plumbing.
sections: SerializedSection[] | SerializedSection; | ||
} | ||
|
||
export function createSavedHomepageClass(services: SavedObjectOpenSearchDashboardsServices) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering why we need to introduce the saved object logic for implementing new homepage.
It seems like currently the concept of saved object within dashboard does not really associate with an entire page. And it also makes the homepage harder to maintain because of the possible saved object migrations.
I am wondering
- why can't we use a simpler route such as utilizing the config
uiSettings
for saving homepage instead of creating a new saved object such as below; and the_id
here also stores the version so we do not need to worry about versioning.
{
"_index": ".kibana_1",
"_id": "config:2.12.0",
"_score": 1,
"_source": {
"config": {
"buildNum": 221231,
"defaultIndex": "ff959d40-b880-11e8-a6d9-e546fe2bba5f"
},
"type": "config",
"references": [],
"migrationVersion": {
"config": "7.9.0"
},
"updated_at": "2024-02-22T02:15:31.504Z"
}
}
- or why cant we save user specific configs using
browser storage
as the source of truth that is referenced in this PR Feat (core): Make theme settings user-specific and user-configurable #5652?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont think i understood your comment about uiSettings. How does that work? How does that differ from Saved Objects?
Also Isnt the homepage just a glorified Dashboard? And that uses saved objects to figure out which embeddable to show and where. The homepage saved object does something similar too. Yes there will be a migration, but that will be needed wherever the user needs to be able to configure their own data.
As for briwser storage. The homepage needs to be tied to a user or workspace. It has to follow them no matter where they login. The PR you reference saves that in local storage which cannot do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think at first i did not understand why we need to introduce the saved object concept into homepage, i thought it is just a page that needs to be rendered once when starting up the application. And then if we needed to save some user configuration, maybe we can just do something like uiSettings.set("useHomePage", true)
, and if we need to see which homepage users want to use, we do uiSettings.get("useHomePage")
So after looking at your explanations, it seems like we want to make the homepage more configurable to the user, and almost similar to the concept of a dashboard, where user can create their own homepage, add or remove different sections to it, and save it, and that is why we want to use saved object, correct? @ashwin-pc
} | ||
|
||
export interface Homepage { | ||
heroes$: Observable<HeroSection[] | undefined>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the hero, why would happen if multiple different plugin register hero for themselves, which hero should we display? In my understanding, we should just display one hero per screen?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont think that was a requirement. Maybe based on how the homepage evolves we may restrict that. cc @kgcreative ?
@ashwin-pc Could you also link me the issue for adding a toggle in advanced setting for the new home page? Currently, i see we can toggle this feature in the yml file; do we wanna switch the toggle to advance setting toggle, or do we wanna keep both toggles? If we keep both, what if user toggle differently for two toggles? |
closing the PR since #6065 has been merged. Thats the same PR, just that the toggle has moved from the yaml config to the advanced settings. |
Description
Implements the new homepage design. The scope of this change is limited to the structure of the page and configuration through saved objects. Better configuration and more features will be added in subsequent PRs.
Issues Resolved
Closes #4966
Closes #5251
Screenshot
Testing the changes
Unit tests have been implemented for the section type API, to ensure that the service works as expected.
Check List
yarn test:jest
yarn test:jest_integration