feat: support custom app icons
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
---
|
||||
'@backstage/core-api': patch
|
||||
'@backstage/plugin-catalog': patch
|
||||
---
|
||||
|
||||
Minor refactoring of BackstageApp.getSystemIcons to support custom registered
|
||||
icons. Custom Icons can be added using:
|
||||
|
||||
```tsx
|
||||
import AlarmIcon from '@material-ui/icons/Alarm';
|
||||
import MyPersonIcon from './MyPerson';
|
||||
|
||||
const app = createApp({
|
||||
icons: {
|
||||
user: MyPersonIcon // override system icon
|
||||
alert: AlarmIcon, // Custom icon
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -39,10 +39,15 @@ import { EntityPage } from './components/catalog/EntityPage';
|
||||
import Root from './components/Root';
|
||||
import { providers } from './identityProviders';
|
||||
import * as plugins from './plugins';
|
||||
import AlarmIcon from '@material-ui/icons/Alarm';
|
||||
|
||||
const app = createApp({
|
||||
apis,
|
||||
plugins: Object.values(plugins),
|
||||
icons: {
|
||||
// Custom icon example
|
||||
alert: AlarmIcon,
|
||||
},
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
return (
|
||||
|
||||
@@ -25,6 +25,9 @@ metadata:
|
||||
- url: https://example.com/web
|
||||
title: Website
|
||||
icon: web
|
||||
- url: https://example.com/alert
|
||||
title: Alerts
|
||||
icon: alert
|
||||
spec:
|
||||
type: service
|
||||
lifecycle: experimental
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
routeElementDiscoverer,
|
||||
traverseElementTree,
|
||||
} from '../extensions/traversal';
|
||||
import { IconComponent, SystemIconKey, SystemIcons } from '../icons';
|
||||
import { IconComponent, IconComponentMap, IconKey } from '../icons';
|
||||
import { BackstagePlugin } from '../plugin';
|
||||
import { RouteRef } from '../routing';
|
||||
import {
|
||||
@@ -95,7 +95,7 @@ export function generateBoundRoutes(
|
||||
|
||||
type FullAppOptions = {
|
||||
apis: Iterable<AnyApiFactory>;
|
||||
icons: SystemIcons;
|
||||
icons: IconComponentMap;
|
||||
plugins: BackstagePlugin<any, any>[];
|
||||
components: AppComponents;
|
||||
themes: AppTheme[];
|
||||
@@ -144,7 +144,7 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
private configApi?: ConfigApi;
|
||||
|
||||
private readonly apis: Iterable<AnyApiFactory>;
|
||||
private readonly icons: SystemIcons;
|
||||
private readonly icons: IconComponentMap;
|
||||
private readonly plugins: BackstagePlugin<any, any>[];
|
||||
private readonly components: AppComponents;
|
||||
private readonly themes: AppTheme[];
|
||||
@@ -169,7 +169,7 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
return this.plugins;
|
||||
}
|
||||
|
||||
getSystemIcon(key: SystemIconKey): IconComponent {
|
||||
getSystemIcon(key: IconKey): IconComponent {
|
||||
return this.icons[key];
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ComponentType } from 'react';
|
||||
import { IconComponent, SystemIconKey, SystemIcons } from '../icons';
|
||||
import { IconComponent, IconComponentMap, IconKey } from '../icons';
|
||||
import { BackstagePlugin, AnyExternalRoutes } from '../plugin/types';
|
||||
import { RouteRef } from '../routing';
|
||||
import { AnyApiFactory } from '../apis';
|
||||
@@ -94,7 +94,7 @@ export type AppOptions = {
|
||||
/**
|
||||
* Supply icons to override the default ones.
|
||||
*/
|
||||
icons?: Partial<SystemIcons>;
|
||||
icons?: IconComponentMap;
|
||||
|
||||
/**
|
||||
* A list of all plugins to include in the app.
|
||||
@@ -169,9 +169,9 @@ export type BackstageApp = {
|
||||
getPlugins(): BackstagePlugin<any, any>[];
|
||||
|
||||
/**
|
||||
* Get a common icon for this app.
|
||||
* Get a common or custom icon for this app.
|
||||
*/
|
||||
getSystemIcon(key: SystemIconKey): IconComponent;
|
||||
getSystemIcon(key: IconKey): IconComponent;
|
||||
|
||||
/**
|
||||
* Provider component that should wrap the Router created with getRouter()
|
||||
|
||||
@@ -15,15 +15,19 @@
|
||||
*/
|
||||
|
||||
import { SvgIconProps } from '@material-ui/core';
|
||||
import MuiDashboardIcon from '@material-ui/icons/Dashboard';
|
||||
import MuiHelpIcon from '@material-ui/icons/Help';
|
||||
import PeopleIcon from '@material-ui/icons/People';
|
||||
import PersonIcon from '@material-ui/icons/Person';
|
||||
import React from 'react';
|
||||
import { useApp } from '../app/AppContext';
|
||||
import { IconComponent, SystemIconKey, SystemIcons } from './types';
|
||||
import { IconComponent, SystemIconKey, IconComponentMap } from './types';
|
||||
|
||||
export const defaultSystemIcons: SystemIcons = {
|
||||
export const defaultSystemIcons: IconComponentMap = {
|
||||
user: PersonIcon,
|
||||
group: PeopleIcon,
|
||||
dashboard: MuiDashboardIcon,
|
||||
help: MuiHelpIcon,
|
||||
};
|
||||
|
||||
const overridableSystemIcon = (key: SystemIconKey): IconComponent => {
|
||||
@@ -35,5 +39,7 @@ const overridableSystemIcon = (key: SystemIconKey): IconComponent => {
|
||||
return Component;
|
||||
};
|
||||
|
||||
export const UserIcon = overridableSystemIcon('user');
|
||||
export const DashboardIcon = overridableSystemIcon('dashboard');
|
||||
export const GroupIcon = overridableSystemIcon('group');
|
||||
export const HelpIcon = overridableSystemIcon('help');
|
||||
export const UserIcon = overridableSystemIcon('user');
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
import { ComponentType } from 'react';
|
||||
import { SvgIconProps } from '@material-ui/core';
|
||||
|
||||
export type SystemIconKey = 'user' | 'group' | 'dashboard' | 'help';
|
||||
|
||||
export type IconComponent = ComponentType<SvgIconProps>;
|
||||
export type SystemIconKey = 'user' | 'group';
|
||||
export type SystemIcons = { [key in SystemIconKey]: IconComponent };
|
||||
export type IconKey = SystemIconKey | string;
|
||||
export type IconComponentMap = { [key in IconKey]: IconComponent };
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { IconComponent, InfoCard, useApp } from '@backstage/core';
|
||||
import { IconComponent, IconKey, InfoCard, useApp } from '@backstage/core';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import LanguageIcon from '@material-ui/icons/Language';
|
||||
import React from 'react';
|
||||
@@ -33,9 +33,8 @@ export const EntityLinksCard = ({ cols = undefined }: Props) => {
|
||||
const { entity } = useEntity();
|
||||
const app = useApp();
|
||||
|
||||
// TODO: Refactor App.icons & App.getSystemIcon to support custom icons
|
||||
const iconResolver = (key: string | undefined): IconComponent => {
|
||||
return app.getSystemIcon(key as any) ?? LanguageIcon;
|
||||
const iconResolver = (key: IconKey | undefined): IconComponent => {
|
||||
return app.getSystemIcon(key ?? '') ?? LanguageIcon;
|
||||
};
|
||||
|
||||
const links = entity?.metadata?.links;
|
||||
|
||||
Reference in New Issue
Block a user