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 plugin infra for adding new dashboard tabs/cards #1742
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import * as React from 'react'; | ||
import { | ||
DashboardCard, | ||
DashboardCardTitle, | ||
DashboardCardBody, | ||
DashboardCardHeader, | ||
} from '@console/internal/components/dashboard/dashboard-card'; | ||
|
||
export const FooCard: React.FC<{}> = () => ( | ||
<DashboardCard> | ||
<DashboardCardHeader> | ||
<DashboardCardTitle>Foo Card</DashboardCardTitle> | ||
</DashboardCardHeader> | ||
<DashboardCardBody> | ||
<div>foo content</div> | ||
</DashboardCardBody> | ||
</DashboardCard> | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type LazyLoader<T extends {}> = () => Promise<React.ComponentType<Partial<T>>>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,18 +2,46 @@ import * as React from 'react'; | |
import { RouteComponentProps } from 'react-router-dom'; | ||
import { connect } from 'react-redux'; | ||
|
||
import * as plugins from '../../plugins'; | ||
import { OverviewDashboard } from './overview-dashboard/overview-dashboard'; | ||
import { HorizontalNav, PageHeading, LoadingBox } from '../utils'; | ||
import { HorizontalNav, PageHeading, LoadingBox, Page, AsyncComponent } from '../utils'; | ||
import { Dashboard } from '../dashboard/dashboard'; | ||
import { DashboardGrid, GridPosition } from '../dashboard/grid'; | ||
import { DashboardsCard } from '@console/plugin-sdk'; | ||
|
||
const tabs = [ | ||
const getCardsOnPosition = (cards: DashboardsCard[], position: GridPosition): React.ComponentType<any>[] => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To render lazy (async) components, you can use Promise-based There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using |
||
cards.filter(c => c.properties.position === position).map(c => () => <AsyncComponent loader={c.properties.loader} />); | ||
|
||
const getPluginTabPages = (): Page[] => { | ||
const cards = plugins.registry.getDashboardsCards(); | ||
return plugins.registry.getDashboardsTabs().map(tab => { | ||
const tabCards = cards.filter(c => c.properties.tab === tab.properties.id); | ||
return { | ||
href: tab.properties.id, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also write an extension check that ensures tab IDs are unique (and non-empty as well), I'll put it on my task list. In general, every time we add new extension types, we should also consider writing the corresponding extension checks to guard against potential conflicts. |
||
name: tab.properties.title, | ||
component: () => ( | ||
<Dashboard> | ||
<DashboardGrid | ||
mainCards={getCardsOnPosition(tabCards, GridPosition.MAIN)} | ||
leftCards={getCardsOnPosition(tabCards, GridPosition.LEFT)} | ||
rightCards={getCardsOnPosition(tabCards, GridPosition.RIGHT)} | ||
/> | ||
</Dashboard> | ||
), | ||
}; | ||
}); | ||
}; | ||
|
||
const tabs: Page[] = [ | ||
{ | ||
href: '', | ||
name: 'Overview', | ||
component: OverviewDashboard, | ||
}, | ||
...getPluginTabPages(), | ||
]; | ||
|
||
const _DashboardsPage: React.FC<DashboardsPageProps> = ({ match, kindsInFlight }) => { | ||
const DashboardsPage_: React.FC<DashboardsPageProps> = ({ match, kindsInFlight }) => { | ||
return kindsInFlight | ||
? <LoadingBox /> | ||
: ( | ||
|
@@ -28,7 +56,7 @@ const mapStateToProps = ({k8s}) => ({ | |
kindsInFlight: k8s.getIn(['RESOURCES', 'inFlight']), | ||
}); | ||
|
||
export const DashboardsPage = connect(mapStateToProps)(_DashboardsPage); | ||
export const DashboardsPage = connect(mapStateToProps)(DashboardsPage_); | ||
|
||
type DashboardsPageProps = RouteComponentProps & { | ||
kindsInFlight: 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.
FYI @spadgett plugins can add new tabs into existing Dashboards page, with tab ID reflected into the URL.