-
Notifications
You must be signed in to change notification settings - Fork 667
Add Inventory card #1810
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 Inventory card #1810
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,20 @@ | ||
| import * as React from 'react'; | ||
| import { Icon } from 'patternfly-react'; | ||
|
|
||
| import { StatusGroupMapper } from '@console/internal/components/dashboard/inventory-card/inventory-item'; | ||
|
|
||
| export const getRouteStatusGroups: StatusGroupMapper = (resources) => ({ | ||
| 'demo-inventory-group': { | ||
| statusIDs: ['Accepted'], | ||
| count: resources.length, | ||
| filterType: 'route-status', | ||
| }, | ||
| }); | ||
|
|
||
| export const DemoGroupIcon: React.FC<{}> = () => ( | ||
| <Icon | ||
| type="fa" | ||
| name="address-book" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--warn" | ||
| /> | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| import { SubsystemHealth } from '@console/internal/components/dashboards-page/overview-dashboard/health-card'; | ||
| import { GridPosition } from '@console/internal/components/dashboard/grid'; | ||
| import { CapacityQuery } from '@console/internal/components/dashboards-page/overview-dashboard/capacity-query-types'; | ||
| import { FirehoseResource } from '@console/internal/components/utils'; | ||
| import { K8sKind } from '@console/internal/module/k8s'; | ||
| import { StatusGroupMapper } from '@console/internal/components/dashboard/inventory-card/inventory-item'; | ||
|
|
||
| import { Extension } from './extension'; | ||
| import { LazyLoader } from './types'; | ||
|
|
@@ -62,6 +65,31 @@ namespace ExtensionProperties { | |
| /** The Prometheus query */ | ||
| query: string; | ||
| } | ||
|
|
||
| export interface DashboardsOverviewInventoryItem { | ||
| /** Resource which will be fetched and grouped by `mapper` function. */ | ||
| resource: FirehoseResource; | ||
|
||
|
|
||
| /** Additional resources which will be fetched and passed to `mapper` function. */ | ||
| additionalResources?: FirehoseResource[]; | ||
|
|
||
| /** The model for `resource` which will be fetched. The model is used for getting model's label or abbr. */ | ||
| model: K8sKind; | ||
|
|
||
| /** Defines whether model's label or abbr should be used when rendering the item. Defaults to false (label). */ | ||
| useAbbr?: boolean; | ||
|
|
||
| /** Function which will map various statuses to groups. */ | ||
| mapper: StatusGroupMapper; | ||
| } | ||
|
|
||
| export interface DashboardsInventoryItemGroup { | ||
| /** The ID of status group. */ | ||
| id: string; | ||
|
|
||
| /** React component representing status group icon. */ | ||
| icon: React.ReactElement; | ||
| } | ||
| } | ||
|
|
||
| export interface DashboardsOverviewHealthURLSubsystem<R> | ||
|
|
@@ -114,3 +142,21 @@ export interface DashboardsOverviewCapacityQuery | |
| export const isDashboardsOverviewCapacityQuery = ( | ||
| e: Extension<any>, | ||
| ): e is DashboardsOverviewCapacityQuery => e.type === 'Dashboards/Overview/Capacity/Query'; | ||
|
|
||
| export interface DashboardsOverviewInventoryItem | ||
| extends Extension<ExtensionProperties.DashboardsOverviewInventoryItem> { | ||
| type: 'Dashboards/Overview/Inventory/Item'; | ||
| } | ||
|
|
||
| export const isDashboardsOverviewInventoryItem = ( | ||
| e: Extension<any>, | ||
| ): e is DashboardsOverviewInventoryItem => e.type === 'Dashboards/Overview/Inventory/Item'; | ||
|
|
||
| export interface DashboardsInventoryItemGroup | ||
| extends Extension<ExtensionProperties.DashboardsInventoryItemGroup> { | ||
| type: 'Dashboards/Inventory/Item/Group'; | ||
| } | ||
|
|
||
| export const isDashboardsInventoryItemGroup = ( | ||
| e: Extension<any>, | ||
| ): e is DashboardsInventoryItemGroup => e.type === 'Dashboards/Inventory/Item/Group'; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| .co-inventory-card__item { | ||
| align-items: center; | ||
| border-bottom: 1px solid $pf-color-black-300; | ||
| display: flex; | ||
| font-size: 1rem; | ||
| justify-content: space-between; | ||
| padding: 1em 0; | ||
| } | ||
|
|
||
| .co-inventory-card__item-status { | ||
| align-items: center; | ||
| display: flex; | ||
| flex-wrap: wrap; | ||
|
|
||
| :last-child { | ||
| margin-right: 0; | ||
| } | ||
| } | ||
|
|
||
| .co-inventory-card__item-title { | ||
| margin-right: 0.5em; | ||
| } | ||
|
|
||
| .co-inventory-card__status { | ||
| align-items: center; | ||
| display: flex; | ||
| flex-shrink: 0; | ||
| margin-right: 0.5em; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon { | ||
| font-size: 1.125rem; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon--error { | ||
| color: $pf-color-red-100; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon--question { | ||
| color: $pf-color-black-300; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon--ok { | ||
| color: $pf-color-light-green-400; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon--progress { | ||
| color: $pf-color-black-600; | ||
| } | ||
|
|
||
| .co-inventory-card__status-icon--warn { | ||
| color: $pf-color-gold-400; | ||
| } | ||
|
|
||
| .co-inventory-card__status-text { | ||
| margin-left: 0.25em; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| import * as React from 'react'; | ||
| import { Icon } from 'patternfly-react'; | ||
| import { Link } from 'react-router-dom'; | ||
|
|
||
| import * as plugins from '../../../plugins'; | ||
| import { LoadingInline } from '../../utils'; | ||
| import { K8sResourceKind, K8sKind } from '../../../module/k8s'; | ||
| import { InventoryStatusGroup } from './status-group'; | ||
|
|
||
| const getPluginStatusGroupIcons = () => { | ||
| const pluginGroups = {}; | ||
| plugins.registry.getDashboardsInventoryItemGroups().forEach(group => { | ||
| pluginGroups[group.properties.id] = group.properties.icon; | ||
| }); | ||
| return pluginGroups; | ||
| }; | ||
|
|
||
| const statusGroupIcons = { | ||
| [InventoryStatusGroup.OK]: ( | ||
| <Icon | ||
| type="fa" | ||
| name="check-circle" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--ok" | ||
| /> | ||
| ), | ||
| [InventoryStatusGroup.WARN]: ( | ||
| <Icon | ||
| type="fa" | ||
| name="exclamation-triangle" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--warn" | ||
| /> | ||
| ), | ||
| [InventoryStatusGroup.ERROR]: ( | ||
| <Icon | ||
| type="fa" | ||
| name="exclamation-circle" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--error" | ||
| /> | ||
| ), | ||
| [InventoryStatusGroup.PROGRESS]: ( | ||
| <Icon | ||
| type="pf" | ||
| name="in-progress" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--progress" | ||
| /> | ||
| ), | ||
| [InventoryStatusGroup.NOT_MAPPED]: ( | ||
| <Icon | ||
| type="fa" | ||
| name="question-circle" | ||
| className="co-inventory-card__status-icon co-inventory-card__status-icon--question" | ||
| /> | ||
| ), | ||
| ...getPluginStatusGroupIcons(), | ||
| }; | ||
|
|
||
| const Status: React.FC<StatusProps> = React.memo(({ groupID, count, statusIDs, kind, namespace, filterType}) => { | ||
| const statusItems = encodeURIComponent(statusIDs.join(',')); | ||
| const namespacePath = namespace ? `ns/${namespace}` : 'all-namespaces'; | ||
| const to = filterType && statusItems.length > 0 ? `/k8s/${namespacePath}/${kind.plural}?rowFilter-${filterType}=${statusItems}` : `/k8s/${namespacePath}/${kind.plural}`; | ||
| const groupIcon = statusGroupIcons[groupID] || statusGroupIcons[InventoryStatusGroup.NOT_MAPPED]; | ||
| return ( | ||
| <div className="co-inventory-card__status"> | ||
| <Link to={to} style={{textDecoration: 'none'}}> | ||
| {groupIcon} | ||
| <span className="co-inventory-card__status-text">{count}</span> | ||
| </Link> | ||
| </div> | ||
| ); | ||
| }); | ||
|
|
||
| export const InventoryItem: React.FC<InventoryItemProps> = React.memo(({ kind, useAbbr, resources, additionalResources, isLoading, mapper, namespace }) => { | ||
| const groups = mapper(resources, additionalResources); | ||
| let title: string; | ||
| if (useAbbr) { | ||
| title = resources.length !== 1 ? `${kind.abbr}s` : kind.abbr; | ||
| } else { | ||
| title = resources.length !== 1 ? kind.labelPlural : kind.label; | ||
| } | ||
| return ( | ||
| <div className="co-inventory-card__item"> | ||
| <div className="co-inventory-card__item-title">{isLoading ? title : `${resources.length} ${title}`}</div> | ||
| {isLoading ? <LoadingInline /> : ( | ||
| <div className="co-inventory-card__item-status"> | ||
| {Object.keys(groups).filter(key => groups[key].count > 0).map((key, index) => ( | ||
| <Status | ||
| key={index} | ||
| kind={kind} | ||
| namespace={namespace} | ||
| groupID={key} | ||
| count={groups[key].count} | ||
| statusIDs={groups[key].statusIDs} | ||
| filterType={groups[key].filterType} | ||
| /> | ||
| ))} | ||
| </div> | ||
| )} | ||
| </div> | ||
| ); | ||
| }); | ||
|
|
||
| export type StatusGroupMapper = (resources: K8sResourceKind[], additionalResources?: {[key: string]: K8sResourceKind[]}) => {[key in InventoryStatusGroup | string]: {filterType?: string, statusIDs: string[], count: number}}; | ||
|
|
||
| type StatusProps = { | ||
| groupID: InventoryStatusGroup | string; | ||
| count: number; | ||
| statusIDs: string[]; | ||
| kind: K8sKind; | ||
| namespace?: string; | ||
| filterType?: string; | ||
| } | ||
|
|
||
| type InventoryItemProps = { | ||
| resources: K8sResourceKind[]; | ||
| additionalResources?: {[key: string]: K8sResourceKind[]}; | ||
| mapper: StatusGroupMapper; | ||
| kind: K8sKind; | ||
| useAbbr?: boolean; | ||
| isLoading: boolean; | ||
| namespace?: string; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| export enum InventoryStatusGroup { | ||
| OK = 'OK', | ||
| WARN = 'WARN', | ||
| ERROR = 'ERROR', | ||
| PROGRESS = 'PROGRESS', | ||
| NOT_MAPPED = 'NOT_MAPPED', | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.