From 9656851c8257362b669ce6dd68ce7230387c6040 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Thu, 23 Jan 2025 08:27:40 -0600 Subject: [PATCH 01/10] feat(CullingInfo): add culling info component --- .../examples/CullingInfo/CullingInfo.md | 37 ++++++++ .../CullingInfo/CullingInfoCustomExample.tsx | 18 ++++ .../CullingInfo/CullingInfoExample.tsx | 16 ++++ .../module/src/CullingInfo/CullingInfo.tsx | 93 +++++++++++++++++++ .../src/CullingInfo/CullingInfoUtils.ts | 32 +++++++ packages/module/src/CullingInfo/index.ts | 2 + packages/module/src/index.ts | 3 + 7 files changed, 201 insertions(+) create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfo.md create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx create mode 100644 packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx create mode 100644 packages/module/src/CullingInfo/CullingInfo.tsx create mode 100644 packages/module/src/CullingInfo/CullingInfoUtils.ts create mode 100644 packages/module/src/CullingInfo/index.ts diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfo.md b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfo.md new file mode 100644 index 00000000..e1d07141 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfo.md @@ -0,0 +1,37 @@ +--- +# Sidenav top-level section +# should be the same for all markdown files +section: Component groups +subsection: Status and state indicators +# Sidenav secondary level section +# should be the same for all markdown files +id: Culling information +# 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: ['CullingInformation'] +sourceLink: https://github.com/patternfly/react-component-groups/blob/main/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfo.md +--- + +import CullingInformation from '@patternfly/react-component-groups/dist/dynamic/CullingInfo'; + +A **culling information** component displays a warning for when an object will become culled or stale. It can display this as a tooltip or text. + +## Examples + +### Basic culling information + +A basic culling information example + +```js file="./CullingInfoExample.tsx" + +``` + +### Culling information with customized props + +For further customization, you can choose to render the tooltip as a message beside the icon instead. And you can utilize all properties of the [Tooltip component](/components/tooltip), with the exception of `content`. + +```js file="./CullingInfoCustomExample.tsx" + +``` \ No newline at end of file diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx new file mode 100644 index 00000000..ae0b1ff1 --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import CullingInformation from '@patternfly/react-component-groups/dist/dynamic/CullingInfo'; + + +export const CustomizedRenderExample: React.FunctionComponent = () => { + const staleDate = new Date('Sun Jan 26 2020'); + const warningDate = new Date('Mon Feb 03 2025'); + const cullingDate = new Date('Fri Feb 07 2025'); + return <> + ({msg} Hello there. Last seen: {` `})}> + + +}; \ No newline at end of file diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx new file mode 100644 index 00000000..ccb347bb --- /dev/null +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import CullingInformation from '@patternfly/react-component-groups/dist/dynamic/CullingInfo'; + +export const BasicExample: React.FunctionComponent = () => { + const staleDate = new Date('Sun Jan 26 2020'); + const warningDate = new Date('Mon Feb 03 2025'); + const cullingDate = new Date('Fri Feb 07 2025'); + return <> + + + +}; diff --git a/packages/module/src/CullingInfo/CullingInfo.tsx b/packages/module/src/CullingInfo/CullingInfo.tsx new file mode 100644 index 00000000..13360a98 --- /dev/null +++ b/packages/module/src/CullingInfo/CullingInfo.tsx @@ -0,0 +1,93 @@ +import React from 'react'; +import { ExclamationCircleIcon, ExclamationTriangleIcon } from '@patternfly/react-icons'; +import { Tooltip, TooltipProps } from '@patternfly/react-core'; +import clsx from 'clsx'; +import { createUseStyles } from 'react-jss'; +import { CullingDate, CullingInfo, calculateTooltip } from './CullingInfoUtils'; + +export type Render = (config: { msg: string }) => React.ReactElement | null; + +const useStyles = createUseStyles({ + inventoryCullingWarning: { + color: 'var(--pf-v6-global--warning-color--200)', + fontWeight: 'var(--pf-v6-global--FontWeight--bold)', + svg: { + marginRight: 'var(--pf-v5-global--spacer--sm)' + } + }, + inventoryCullingDanger: { + color: 'var(--pf-v6-global--warning-color--200)', + fontWeight: 'var(--pf-v6-global--FontWeight--bold)', + svg: { + marginRight: 'var(--pf-v6-global--spacer--sm)' + } + } +}); + +export interface CullingInformation extends Omit { + /** Option to add custom css classes */ + className?: string; + /** Warning date for when object becomes stale */ + staleWarning: CullingDate; + /** Date when object becomes culled */ + culled: CullingDate; + /** Date when object becomes stale */ + stale: CullingDate; + /** Current date */ + currDate: CullingDate; + /** Optional prop to add custom children */ + children?: React.ReactElement> | undefined; + /** Option to add custom message ReactElement */ + render?: Render; +} + +const CullingInformation: React.FunctionComponent = ({ + culled = new Date(0), + className, + staleWarning = new Date(0), + stale = new Date(0), + currDate = new Date(0), + children, + render, + ...props +}) => { + const classes = useStyles(); + + if (new Date(currDate).valueOf() - new Date(stale).valueOf() < 0) { + return render + ? render({ + msg: '', + }) + : children || null; + } + + const { isWarn, isError, msg }: CullingInfo = calculateTooltip(culled, staleWarning, currDate); + if (render) { + return ( + + {isWarn && } + {isError && } + {render({ msg })} + + ); + } + + return ( + + + + {isError && } + {isWarn && } + {children} + + + + ); +}; + +export default CullingInformation; + diff --git a/packages/module/src/CullingInfo/CullingInfoUtils.ts b/packages/module/src/CullingInfo/CullingInfoUtils.ts new file mode 100644 index 00000000..8348d663 --- /dev/null +++ b/packages/module/src/CullingInfo/CullingInfoUtils.ts @@ -0,0 +1,32 @@ +export type CullingDate = string | number | Date; + +export interface CullingInfo { + isWarn?: boolean; + isError?: boolean; + msg: string; +} +export type CalculateTooltip = (culled: CullingDate, warning: CullingDate, currDate: CullingDate) => CullingInfo; + +export const seconds = 1000; +export const minutes: number = seconds * 60; +export const hours: number = minutes * 60; +export const days: number = hours * 24; + +export const calculateTooltip: CalculateTooltip = (culled, warning, currDate) => { + const culledDate: Date = new Date(culled); + const warningDate: Date = new Date(warning); + const diffTime: number = new Date(currDate).valueOf() - warningDate.valueOf(); + const removeIn: number = Math.ceil((culledDate.valueOf() - new Date(currDate).valueOf()) / days); + const msg = `System scheduled for inventory removal in ${removeIn} days`; + if (diffTime >= 0) { + return { + isError: true, + msg, + }; + } + + return { + isWarn: true, + msg, + }; +}; \ No newline at end of file diff --git a/packages/module/src/CullingInfo/index.ts b/packages/module/src/CullingInfo/index.ts new file mode 100644 index 00000000..d10b92a6 --- /dev/null +++ b/packages/module/src/CullingInfo/index.ts @@ -0,0 +1,2 @@ +export { default } from './CullingInfo'; +export * from './CullingInfo'; \ No newline at end of file diff --git a/packages/module/src/index.ts b/packages/module/src/index.ts index 934a4057..08812a9b 100644 --- a/packages/module/src/index.ts +++ b/packages/module/src/index.ts @@ -66,6 +66,9 @@ export * from './ErrorStack'; export { default as ErrorBoundary } from './ErrorBoundary'; export * from './ErrorBoundary'; +export { default as CullingInfo } from './CullingInfo'; +export * from './CullingInfo'; + export { default as ColumnManagementModal } from './ColumnManagementModal'; export * from './ColumnManagementModal'; From be6dad8b676207f1a8cc3a699ad0ed3b88f41124 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Tue, 28 Jan 2025 16:30:40 -0600 Subject: [PATCH 02/10] fix: use semantic tokens, fix styling, delete cullingInfoUtils --- .../CullingInfo/CullingInfoCustomExample.tsx | 32 +++++++-- .../CullingInfo/CullingInfoExample.tsx | 29 ++++++-- .../module/src/CullingInfo/CullingInfo.tsx | 69 ++++++++++++++----- .../src/CullingInfo/CullingInfoUtils.ts | 32 --------- 4 files changed, 101 insertions(+), 61 deletions(-) delete mode 100644 packages/module/src/CullingInfo/CullingInfoUtils.ts diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx index ae0b1ff1..465128f7 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoCustomExample.tsx @@ -1,5 +1,6 @@ import React from 'react'; import CullingInformation from '@patternfly/react-component-groups/dist/dynamic/CullingInfo'; +import { Stack, StackItem } from '@patternfly/react-core'; export const CustomizedRenderExample: React.FunctionComponent = () => { @@ -7,12 +8,29 @@ export const CustomizedRenderExample: React.FunctionComponent = () => { const warningDate = new Date('Mon Feb 03 2025'); const cullingDate = new Date('Fri Feb 07 2025'); return <> - ({msg} Hello there. Last seen: {` `})}> - + + + ({msg})}> + + + + + (This is an error message. Item is past due)}> + + + + + + }; \ No newline at end of file diff --git a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx index ccb347bb..2912e11d 100644 --- a/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx +++ b/packages/module/patternfly-docs/content/extensions/component-groups/examples/CullingInfo/CullingInfoExample.tsx @@ -1,16 +1,33 @@ import React from 'react'; import CullingInformation from '@patternfly/react-component-groups/dist/dynamic/CullingInfo'; +import { Stack, StackItem } from '@patternfly/react-core'; export const BasicExample: React.FunctionComponent = () => { const staleDate = new Date('Sun Jan 26 2020'); const warningDate = new Date('Mon Feb 03 2025'); const cullingDate = new Date('Fri Feb 07 2025'); return <> - - + + + + + + + + + + + + + }; diff --git a/packages/module/src/CullingInfo/CullingInfo.tsx b/packages/module/src/CullingInfo/CullingInfo.tsx index 13360a98..4b259799 100644 --- a/packages/module/src/CullingInfo/CullingInfo.tsx +++ b/packages/module/src/CullingInfo/CullingInfo.tsx @@ -3,27 +3,39 @@ import { ExclamationCircleIcon, ExclamationTriangleIcon } from '@patternfly/reac import { Tooltip, TooltipProps } from '@patternfly/react-core'; import clsx from 'clsx'; import { createUseStyles } from 'react-jss'; -import { CullingDate, CullingInfo, calculateTooltip } from './CullingInfoUtils'; -export type Render = (config: { msg: string }) => React.ReactElement | null; +type Render = (config: { msg: string }) => React.ReactElement | null; +type CullingDate = string | number | Date; + +interface CullingInfo { + isWarn?: boolean; + isError?: boolean; + msg: string; +} + +const seconds = 1000; +const minutes: number = seconds * 60; +const hours: number = minutes * 60; +const days: number = hours * 24; + +type CalculateTooltip = (culled: CullingDate, warning: CullingDate, currDate: CullingDate) => CullingInfo; const useStyles = createUseStyles({ inventoryCullingWarning: { - color: 'var(--pf-v6-global--warning-color--200)', - fontWeight: 'var(--pf-v6-global--FontWeight--bold)', - svg: { - marginRight: 'var(--pf-v5-global--spacer--sm)' - } + color: 'var(--pf-t--global--icon--color--status--warning--default)', }, inventoryCullingDanger: { - color: 'var(--pf-v6-global--warning-color--200)', - fontWeight: 'var(--pf-v6-global--FontWeight--bold)', - svg: { - marginRight: 'var(--pf-v6-global--spacer--sm)' - } - } + color: 'var(--pf-t--global--icon--color--status--danger--default)', + }, + iconMargin: { + marginRight: 'var(--pf-t--global--spacer--sm)' + }, + messageFont: { + fontWeight: 'var(--pf-t--global--font--weight--200)', + }, }); +/** extends TooltipProps */ export interface CullingInformation extends Omit { /** Option to add custom css classes */ className?: string; @@ -39,6 +51,8 @@ export interface CullingInformation extends Omit { children?: React.ReactElement> | undefined; /** Option to add custom message ReactElement */ render?: Render; + /** Optional custom warning message */ + message?: string; } const CullingInformation: React.FunctionComponent = ({ @@ -49,10 +63,30 @@ const CullingInformation: React.FunctionComponent = ({ currDate = new Date(0), children, render, + message, ...props }) => { const classes = useStyles(); + const calculateTooltip: CalculateTooltip = (culled, warning, currDate) => { + const culledDate: Date = new Date(culled); + const warningDate: Date = new Date(warning); + const diffTime: number = new Date(currDate).valueOf() - warningDate.valueOf(); + const removeIn: number = Math.ceil((culledDate.valueOf() - new Date(currDate).valueOf()) / days); + const msg = message ? message : `System scheduled for inventory removal in ${removeIn} days`; + if (diffTime >= 0) { + return { + isError: true, + msg, + }; + } + + return { + isWarn: true, + msg, + }; + }; + if (new Date(currDate).valueOf() - new Date(stale).valueOf() < 0) { return render ? render({ @@ -67,9 +101,12 @@ const CullingInformation: React.FunctionComponent = ({ - {isWarn && } - {isError && } - {render({ msg })} + {isWarn && } + {isError && } + + {render({ msg })} + + ); } diff --git a/packages/module/src/CullingInfo/CullingInfoUtils.ts b/packages/module/src/CullingInfo/CullingInfoUtils.ts deleted file mode 100644 index 8348d663..00000000 --- a/packages/module/src/CullingInfo/CullingInfoUtils.ts +++ /dev/null @@ -1,32 +0,0 @@ -export type CullingDate = string | number | Date; - -export interface CullingInfo { - isWarn?: boolean; - isError?: boolean; - msg: string; -} -export type CalculateTooltip = (culled: CullingDate, warning: CullingDate, currDate: CullingDate) => CullingInfo; - -export const seconds = 1000; -export const minutes: number = seconds * 60; -export const hours: number = minutes * 60; -export const days: number = hours * 24; - -export const calculateTooltip: CalculateTooltip = (culled, warning, currDate) => { - const culledDate: Date = new Date(culled); - const warningDate: Date = new Date(warning); - const diffTime: number = new Date(currDate).valueOf() - warningDate.valueOf(); - const removeIn: number = Math.ceil((culledDate.valueOf() - new Date(currDate).valueOf()) / days); - const msg = `System scheduled for inventory removal in ${removeIn} days`; - if (diffTime >= 0) { - return { - isError: true, - msg, - }; - } - - return { - isWarn: true, - msg, - }; -}; \ No newline at end of file From 20247da6dc6ca2547cea231d5f10e581d069e832 Mon Sep 17 00:00:00 2001 From: Zein Sleiman Date: Thu, 30 Jan 2025 15:37:05 -0600 Subject: [PATCH 03/10] fix: fix font semantic token; put Icon in a Button --- packages/module/src/CullingInfo/CullingInfo.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/module/src/CullingInfo/CullingInfo.tsx b/packages/module/src/CullingInfo/CullingInfo.tsx index 4b259799..51c51a2b 100644 --- a/packages/module/src/CullingInfo/CullingInfo.tsx +++ b/packages/module/src/CullingInfo/CullingInfo.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { ExclamationCircleIcon, ExclamationTriangleIcon } from '@patternfly/react-icons'; -import { Tooltip, TooltipProps } from '@patternfly/react-core'; +import { Button, Tooltip, TooltipProps } from '@patternfly/react-core'; import clsx from 'clsx'; import { createUseStyles } from 'react-jss'; @@ -31,7 +31,7 @@ const useStyles = createUseStyles({ marginRight: 'var(--pf-t--global--spacer--sm)' }, messageFont: { - fontWeight: 'var(--pf-t--global--font--weight--200)', + fontWeight: 'var(--pf-t--global--font--weight--body--bold)', }, }); @@ -101,8 +101,12 @@ const CullingInformation: React.FunctionComponent = ({ - {isWarn && } - {isError && } + {isWarn && +