diff --git a/package-lock.json b/package-lock.json
index b0d00071..57aec016 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23968,10 +23968,12 @@
"version": "5.0.0-prerelease.0",
"license": "MIT",
"dependencies": {
+ "@openshift-console/dynamic-plugin-sdk": "^1.1.0",
"@patternfly/react-core": "^5.1.1",
"@patternfly/react-icons": "^5.1.1",
"@patternfly/react-table": "^5.1.1",
"clsx": "^2.0.0",
+ "lodash": "^4.17.21",
"react-jss": "^10.10.0"
},
"devDependencies": {
diff --git a/package.json b/package.json
index 58b83e90..b90c3317 100644
--- a/package.json
+++ b/package.json
@@ -29,18 +29,18 @@
},
"devDependencies": {
"@babel/core": "^7.19.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.19.6",
"@babel/preset-env": "^7.19.4",
"@babel/preset-flow": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@babel/preset-typescript": "^7.18.6",
+ "@octokit/rest": "^18.0.0",
"@testing-library/dom": "^8.0.7",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "14.4.3",
"@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.49.0",
- "@babel/plugin-proposal-private-property-in-object": "^7.19.6",
- "@octokit/rest": "^18.0.0",
"babel-jest": "^29.2.2",
"babel-polyfill": "6.26.0",
"chokidar": "^3.5.3",
@@ -68,6 +68,6 @@
"serve": "^14.1.2",
"surge": "^0.23.1",
"ts-jest": "29.0.3",
- "whatwg-fetch": "^3.6.2"
+ "whatwg-fetch": "^3.6.2"
}
}
diff --git a/packages/module/package.json b/packages/module/package.json
index 7f5cb0d3..049592cb 100644
--- a/packages/module/package.json
+++ b/packages/module/package.json
@@ -31,9 +31,11 @@
"tag": "prerelease"
},
"dependencies": {
+ "@openshift-console/dynamic-plugin-sdk": "^1.1.0",
"@patternfly/react-core": "^5.1.1",
"@patternfly/react-icons": "^5.1.1",
"@patternfly/react-table": "^5.1.1",
+ "lodash": "^4.17.21",
"react-jss": "^10.10.0",
"clsx": "^2.0.0"
},
diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/LinkStatusExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/LinkStatusExample.tsx
new file mode 100644
index 00000000..d71201c7
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/LinkStatusExample.tsx
@@ -0,0 +1,6 @@
+import React from 'react';
+import { SecondaryStatus } from '@patternfly/react-component-groups/dist/dynamic/Status';
+
+export const BasicExample: React.FunctionComponent = () => (
+
+);
diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/Status.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/Status.md
new file mode 100644
index 00000000..275435ca
--- /dev/null
+++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/Status.md
@@ -0,0 +1,27 @@
+---
+# Sidenav top-level section
+# should be the same for all markdown files
+section: extensions
+subsection: Component groups
+# Sidenav secondary level section
+# should be the same for all markdown files
+id: Status
+# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility)
+source: react
+# If you use typescript, the name of the interface to display props for
+# These are found through the sourceProps function provided in patternfly-docs.source.js
+propComponents: ['Status']
+sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/Status/Status.md
+---
+
+import Status from '@patternfly/react-component-groups/dist/dynamic/Status';
+
+The **Status** component displays different statuses for an item. There are a variety of statuses that can be displayed components for example the link button status.
+
+### Status supported
+
+By default, the Status logo displays as normal and in full color, meaning that it is supported.
+
+```js file="./LinkStatusExample.tsx"
+
+```
\ No newline at end of file
diff --git a/packages/module/src/Status/LinkStatus.tsx b/packages/module/src/Status/LinkStatus.tsx
new file mode 100644
index 00000000..2a40d0e2
--- /dev/null
+++ b/packages/module/src/Status/LinkStatus.tsx
@@ -0,0 +1,14 @@
+import * as React from 'react';
+import { Button } from '@patternfly/react-core';
+import { StatusIconAndText } from '@openshift-console/dynamic-plugin-sdk';
+
+const LinkStatus: React.FC = ({ linkTitle, ...other }) =>
+
+
+export interface LinkStatusProps extends React.ComponentProps {
+ linkTitle?: string;
+};
+
+export default LinkStatus;
diff --git a/packages/module/src/Status/NodeUnschedulableStatus.tsx b/packages/module/src/Status/NodeUnschedulableStatus.tsx
new file mode 100644
index 00000000..3a150ff2
--- /dev/null
+++ b/packages/module/src/Status/NodeUnschedulableStatus.tsx
@@ -0,0 +1,27 @@
+import * as React from 'react';
+import { WarningStatus } from './statuses';
+
+export interface StatusComponentProps {
+ title?: string;
+ iconOnly?: boolean;
+ noTooltip?: boolean;
+ className?: string;
+ popoverTitle?: string;
+};
+
+const NodeUnschedulableStatus: React.FC = ({
+ status,
+ title,
+ iconOnly,
+ noTooltip,
+ className,
+}) => {
+ const statusProps = { title: title || status, iconOnly, noTooltip, className };
+ return ;
+};
+
+export interface NodeUnschedulableStatusProps extends StatusComponentProps {
+ status: string;
+};
+
+export default NodeUnschedulableStatus;
diff --git a/packages/module/src/Status/SecondaryStatus.tsx b/packages/module/src/Status/SecondaryStatus.tsx
new file mode 100644
index 00000000..6080e873
--- /dev/null
+++ b/packages/module/src/Status/SecondaryStatus.tsx
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import * as _ from 'lodash';
+
+export interface SecondaryStatusProps {
+ status?: string | string[];
+ className?: string;
+ dataStatusID?: string;
+};
+
+const SecondaryStatus: React.FC = ({ status, className, dataStatusID }) => {
+ const statusLabel = _.compact(_.concat([], status)).join(', ');
+ const cssClassName = className || '';
+ if (statusLabel) {
+ return (
+
+ {statusLabel}
+
+ );
+ }
+ return null;
+};
+
+export default SecondaryStatus;
diff --git a/packages/module/src/Status/Status.tsx b/packages/module/src/Status/Status.tsx
new file mode 100644
index 00000000..c91ed861
--- /dev/null
+++ b/packages/module/src/Status/Status.tsx
@@ -0,0 +1,10 @@
+import * as React from 'react';
+import { StatusComponent as Status } from './StatusCompnent';
+
+export interface StatusIconProps {
+ status: string;
+};
+
+export const StatusIcon: React.FC = ({ status }) => (
+
+);
\ No newline at end of file
diff --git a/packages/module/src/Status/StatusCompnent.tsx b/packages/module/src/Status/StatusCompnent.tsx
new file mode 100644
index 00000000..a79e6f3b
--- /dev/null
+++ b/packages/module/src/Status/StatusCompnent.tsx
@@ -0,0 +1,209 @@
+import * as React from 'react';
+import { BanIcon } from '@patternfly/react-icons/dist/esm/icons/ban-icon';
+import { ClipboardListIcon } from '@patternfly/react-icons/dist/esm/icons/clipboard-list-icon';
+import { HourglassHalfIcon } from '@patternfly/react-icons/dist/esm/icons/hourglass-half-icon';
+import { HourglassStartIcon } from '@patternfly/react-icons/dist/esm/icons/hourglass-start-icon';
+import { NotStartedIcon } from '@patternfly/react-icons/dist/esm/icons/not-started-icon';
+import { SyncAltIcon } from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
+import { UnknownIcon } from '@patternfly/react-icons/dist/esm/icons/unknown-icon';
+import { YellowExclamationTriangleIcon } from './icons';
+import { ErrorStatus, InfoStatus, ProgressStatus, SuccessStatus } from './statuses';
+import clsx from 'clsx';
+
+const DASH = '-';
+const MEMO = {};
+
+interface StatusComponentProps {
+ title?: string;
+ iconOnly?: boolean;
+ noTooltip?: boolean;
+ className?: string;
+ popoverTitle?: string;
+}
+
+const CamelCaseWrap: React.FC = ({ value, dataTest }) => {
+ if (!value) {
+ return '-';
+ }
+
+ if (MEMO[value]) {
+ return MEMO[value];
+ }
+
+ // Add word break points before capital letters (but keep consecutive capital letters together).
+ const words = value.match(/[A-Z]+[^A-Z]*|[^A-Z]+/g);
+ const rendered = (
+
+ {words!.map((word, i) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ {word}
+ {i !== words!.length - 1 && }
+
+ ))}
+
+ );
+ MEMO[value] = rendered;
+ return rendered;
+};
+
+interface CamelCaseWrapProps {
+ value: string;
+ dataTest?: string;
+}
+
+export interface StatusProps extends StatusComponentProps {
+ status?: string;
+ icon?: React.ReactElement;
+ spin?: boolean;
+ children?: React.ReactNode;
+}
+
+interface StatusIconAndTextProps extends StatusComponentProps {
+ icon?: React.ReactElement;
+ spin?: boolean;
+ };
+
+/**
+ * Component for displaying a status icon and text
+ * @param {string} [title] - (optional) status text
+ * @param {boolean} [iconOnly] - (optional) if true, only displays icon
+ * @param {boolean} [noTooltip] - (optional) if true, tooltip won't be displayed
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {React.ReactElement} [icon] - (optional) icon to be displayed
+ * @param {boolean} [spin] - (optional) if true, icon rotates
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+const StatusIconAndText: React.FC = ({ icon, title, spin, iconOnly, noTooltip, className }) => {
+ if (!title) {
+ return <>{DASH}>;
+ }
+
+ return (
+
+ {icon &&
+ React.cloneElement(icon, {
+ className: clsx(
+ spin && 'fa-spin',
+ icon.props.className,
+ !iconOnly && 'co-icon-and-text__icon co-icon-flex-child'
+ )
+ })}
+ {!iconOnly && }
+
+ );
+};
+
+interface StatusComponentProps {
+ title?: string;
+ iconOnly?: boolean;
+ noTooltip?: boolean;
+ className?: string;
+ popoverTitle?: string;
+}
+
+/**
+ * Component for displaying a status message
+ * @param {string} status - type of status to be displayed
+ * @param {string} [title] - (optional) status text
+ * @param {boolean} [iconOnly] - (optional) if true, only displays icon
+ * @param {boolean} [noTooltip] - (optional) if true, tooltip won't be displayed
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {string} [popoverTitle] - (optional) title for popover
+ * @param {ReactNode} [children] - (optional) children for the component
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export const Status: React.FC = ({ status, title, children, iconOnly, noTooltip, className }) => {
+ const statusProps = { title: title || status, iconOnly, noTooltip, className };
+ switch (status) {
+ case 'New':
+ return } />;
+
+ case 'Pending':
+ return } />;
+
+ case 'Planning':
+ return } />;
+
+ case 'ContainerCreating':
+ case 'UpgradePending':
+ case 'PendingUpgrade':
+ case 'PendingRollback':
+ return ;
+
+ case 'In Progress':
+ case 'Installing':
+ case 'InstallReady':
+ case 'Replacing':
+ case 'Running':
+ case 'Updating':
+ case 'Upgrading':
+ case 'PendingInstall':
+ return } />;
+
+ case 'Cancelled':
+ case 'Deleting':
+ case 'Expired':
+ case 'Not Ready':
+ case 'Cancelling':
+ case 'Terminating':
+ case 'Superseded':
+ case 'Uninstalling':
+ return } />;
+
+ case 'Warning':
+ case 'RequiresApproval':
+ return } />;
+
+ case 'ContainerCannotRun':
+ case 'CrashLoopBackOff':
+ case 'Critical':
+ case 'ErrImagePull':
+ case 'Error':
+ case 'Failed':
+ case 'Failure':
+ case 'ImagePullBackOff':
+ case 'InstallCheckFailed':
+ case 'Lost':
+ case 'Rejected':
+ case 'UpgradeFailed':
+ return {children};
+
+ case 'Accepted':
+ case 'Active':
+ case 'Bound':
+ case 'Complete':
+ case 'Completed':
+ case 'Created':
+ case 'Enabled':
+ case 'Succeeded':
+ case 'Ready':
+ case 'Up to date':
+ case 'Loaded':
+ case 'Provisioned as node':
+ case 'Preferred':
+ case 'Connected':
+ case 'Deployed':
+ return ;
+
+ case 'Info':
+ return {children};
+
+ case 'Unknown':
+ return } />;
+
+ case 'PipelineNotStarted':
+ return } />;
+
+ default:
+ return status ? : <>{DASH}>;
+ }
+};
+
+export default Status;
diff --git a/packages/module/src/Status/icons.tsx b/packages/module/src/Status/icons.tsx
new file mode 100644
index 00000000..64c778f4
--- /dev/null
+++ b/packages/module/src/Status/icons.tsx
@@ -0,0 +1,94 @@
+import * as React from 'react';
+import { Icon } from '@patternfly/react-core';
+import { ArrowCircleUpIcon } from '@patternfly/react-icons/dist/esm/icons/arrow-circle-up-icon';
+import { ResourcesAlmostFullIcon } from '@patternfly/react-icons/dist/esm/icons/resources-almost-full-icon';
+import { ResourcesFullIcon } from '@patternfly/react-icons/dist/esm/icons/resources-full-icon';
+import { SyncAltIcon } from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
+import { UnknownIcon } from '@patternfly/react-icons/dist/esm/icons/unknown-icon';
+
+
+export interface ColoredIconProps {
+ className?: string;
+ title?: string;
+ size?: 'sm' | 'md' | 'lg' | 'xl';
+};
+
+/**
+ * Component for displaying a green check mark circle icon
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {string} [title] - (optional) icon title
+ * @param {string} [size] - (optional) icon size: ('sm', 'md', 'lg', 'xl')
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export declare const GreenCheckCircleIcon: React.FC;
+/**
+ * Component for displaying a red exclamation mark circle icon
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {string} [title] - (optional) icon title
+ * @param {string} [size] - (optional) icon size: ('sm', 'md', 'lg', 'xl')
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export declare const RedExclamationCircleIcon: React.FC;
+/**
+ * Component for displaying a yellow triangle exclamation icon
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {string} [title] - (optional) icon title
+ * @param {string} [size] - (optional) icon size: ('sm', 'md', 'lg', 'xl')
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export declare const YellowExclamationTriangleIcon: React.FC;
+/**
+ * Component for displaying a blue info circle icon
+ * @param {string} [className] - (optional) additional class name for the component
+ * @param {string} [title] - (optional) icon title
+ * @param {string} [size] - (optional) icon size: ('sm', 'md', 'lg', 'xl')
+ * @example
+ * ```tsx
+ *
+ * ```
+ */
+export declare const BlueInfoCircleIcon: React.FC;
+
+
+export const GrayUnknownIcon: React.FC = ({ className, title, size }) => (
+
+
+
+);
+
+export const BlueSyncIcon: React.FC = ({ className, title, size }) => (
+
+
+
+);
+
+export const RedResourcesFullIcon: React.FC = ({ className, title, size }) => (
+
+
+
+);
+
+export const YellowResourcesAlmostFullIcon: React.FC = ({
+ className,
+ title,
+ size,
+}) => (
+
+
+
+);
+
+export const BlueArrowCircleUpIcon: React.FC = ({ className, title, size }) => (
+
+
+
+);
diff --git a/packages/module/src/Status/index.tsx b/packages/module/src/Status/index.tsx
new file mode 100644
index 00000000..69c8be5e
--- /dev/null
+++ b/packages/module/src/Status/index.tsx
@@ -0,0 +1,6 @@
+export * from './icons';
+export * from './statuses';
+export * from './Status';
+
+export { default as SecondaryStatus } from './SecondaryStatus';
+export { default as NodeUnschedulableStatus } from './NodeUnschedulableStatus';
diff --git a/packages/module/src/Status/statuses.tsx b/packages/module/src/Status/statuses.tsx
new file mode 100644
index 00000000..fbec2e7f
--- /dev/null
+++ b/packages/module/src/Status/statuses.tsx
@@ -0,0 +1,56 @@
+import * as React from 'react';
+import { HourglassHalfIcon } from '@patternfly/react-icons/dist/esm/icons/hourglass-half-icon';
+import { useTranslation } from 'react-i18next';
+import {
+ GenericStatus,
+ StatusComponentProps,
+ ErrorStatus as SdkErrorStatus,
+ InfoStatus as SdkInfoStatus,
+ ProgressStatus as SdkProgressStatus,
+ SuccessStatus as SdkSuccessStatus,
+} from '@openshift-console/dynamic-plugin-sdk';
+import { YellowExclamationTriangleIcon } from './icons';
+
+export const ErrorStatus: React.FC = ({ title, ...props }) => {
+ const { t } = useTranslation();
+ return ;
+};
+
+export const InfoStatus: React.FC = ({ title, ...props }) => {
+ const { t } = useTranslation();
+ return ;
+};
+
+export const ProgressStatus: React.FC = ({ title, ...props }) => {
+ const { t } = useTranslation();
+ return ;
+};
+
+export const SuccessStatus: React.FC = ({ title, ...props }) => {
+ const { t } = useTranslation();
+ return ;
+};
+
+export const PendingStatus: React.FC = (props) => {
+ const { t } = useTranslation();
+ return (
+
+ );
+};
+PendingStatus.displayName = 'PendingStatus';
+
+export const WarningStatus: React.FC = (props) => {
+ const { t } = useTranslation();
+ return (
+
+ );
+};
+WarningStatus.displayName = 'WarningStatus';