From a6daeecf6de57dce5017602b70bf300d46685aab Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 7 Jan 2025 15:12:09 +0300 Subject: [PATCH 1/6] add alert box component --- packages/components/package.json | 2 +- .../components/AlertBox/AlertBox.story.tsx | 38 ++++++++++++ .../components/AlertBox/AlertBox.styles.ts | 14 +++++ .../src/components/AlertBox/AlertBox.test.tsx | 58 +++++++++++++++++++ .../src/components/AlertBox/AlertBox.tsx | 50 ++++++++++++++++ .../src/components/AlertBox/index.ts | 1 + packages/components/src/components/index.ts | 1 + packages/components/src/constants/tests.ts | 7 +++ 8 files changed, 170 insertions(+), 1 deletion(-) create mode 100644 packages/components/src/components/AlertBox/AlertBox.story.tsx create mode 100644 packages/components/src/components/AlertBox/AlertBox.styles.ts create mode 100644 packages/components/src/components/AlertBox/AlertBox.test.tsx create mode 100644 packages/components/src/components/AlertBox/AlertBox.tsx create mode 100644 packages/components/src/components/AlertBox/index.ts diff --git a/packages/components/package.json b/packages/components/package.json index e80910e..582a690 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -89,5 +89,5 @@ "typecheck": "tsc --emitDeclarationOnly false --noEmit" }, "types": "dist/index.d.ts", - "version": "3.8.0" + "version": "3.9.0" } diff --git a/packages/components/src/components/AlertBox/AlertBox.story.tsx b/packages/components/src/components/AlertBox/AlertBox.story.tsx new file mode 100644 index 0000000..889a748 --- /dev/null +++ b/packages/components/src/components/AlertBox/AlertBox.story.tsx @@ -0,0 +1,38 @@ +import { Meta, StoryFn } from '@storybook/react'; +import React from 'react'; + +import { AlertBox, AlertBoxProps } from './AlertBox'; + +const variants: string[] = ['error', 'warning', 'info', 'success']; + +const meta: Meta = { + title: 'AlertBox', + component: AlertBox, + parameters: { + controls: { + exclude: ['onRemove'], + }, + }, + args: { + error: 'test', + variant: 'error', + title: 'Title', + }, + argTypes: { + error: { control: 'text' }, + title: { control: 'text' }, + variant: { + control: { type: 'select', options: variants }, + }, + }, +}; + +export const Basic: StoryFn = ({ ...args }: AlertBoxProps) => { + return ( +
+ +
+ ); +}; + +export default meta; diff --git a/packages/components/src/components/AlertBox/AlertBox.styles.ts b/packages/components/src/components/AlertBox/AlertBox.styles.ts new file mode 100644 index 0000000..71209f3 --- /dev/null +++ b/packages/components/src/components/AlertBox/AlertBox.styles.ts @@ -0,0 +1,14 @@ +import { css } from '@emotion/css'; + +/** + * Styles + */ +export const getStyles = () => { + return { + errorInfo: css` + padding: 0; + margin: 0; + font-size: 12px; + `, + }; +}; diff --git a/packages/components/src/components/AlertBox/AlertBox.test.tsx b/packages/components/src/components/AlertBox/AlertBox.test.tsx new file mode 100644 index 0000000..4e6e879 --- /dev/null +++ b/packages/components/src/components/AlertBox/AlertBox.test.tsx @@ -0,0 +1,58 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import { getJestSelectors, createSelector } from '@volkovlabs/jest-selectors'; +import React from 'react'; + +import { AlertBox } from './AlertBox'; +import { TEST_IDS } from '../../constants'; + +/** + * Properties + */ +type Props = React.ComponentProps; + +describe('Alert box', () => { + /** + * Selectors + */ + const getSelectors = getJestSelectors(TEST_IDS.alertBox); + const selectors = getSelectors(screen); + + /** + * Get Component + */ + const getComponent = (props: Partial) => { + return ; + }; + + it('Should show Alert box', () => { + const onChange = jest.fn(); + + render(getComponent({ error: 'Test Error', title: 'Test title', variant: 'error', onRemove: onChange })); + expect(selectors.root()).toBeVisible(); + }); + + it('Should not show Alert box if no errors', () => { + const onChange = jest.fn(); + + const { queryByTestId } = render( + getComponent({ error: '', title: 'Test title', variant: 'error', onRemove: onChange }) + ); + + expect(queryByTestId(TEST_IDS.alertBox.root.selector())).toBeNull(); + }); + + it('Should show Alert box details', () => { + const onChange = jest.fn(); + + render( + getComponent({ error: 'Test Error text in details', title: 'Test title', variant: 'error', onRemove: onChange }) + ); + expect(selectors.root()).toBeVisible(); + expect(selectors.sectionHeader()).toBeVisible(); + expect(selectors.details(true)).not.toBeInTheDocument(); + + fireEvent.click(selectors.sectionHeader()); + expect(selectors.details()).toBeVisible(); + expect(selectors.details()).toHaveTextContent('Test Error text in details'); + }); +}); diff --git a/packages/components/src/components/AlertBox/AlertBox.tsx b/packages/components/src/components/AlertBox/AlertBox.tsx new file mode 100644 index 0000000..672f830 --- /dev/null +++ b/packages/components/src/components/AlertBox/AlertBox.tsx @@ -0,0 +1,50 @@ +import { Alert, useStyles2 } from '@grafana/ui'; +import React, { useState } from 'react'; + +import { getStyles } from './AlertBox.styles'; +import { CollapsableSection } from '../CollapsableSection'; +import { TEST_IDS } from '../../constants'; + +/** + * Properties + */ +export type AlertBoxProps = { + error: string; + variant: 'success' | 'warning' | 'error' | 'info'; + title: string; + onRemove: (event: React.MouseEvent) => void; +}; + +/** + * Alert Box + */ +export const AlertBox: React.FC = ({ error, variant, title, onRemove }) => { + /** + * Styles + */ + const styles = useStyles2(getStyles); + + /** + * States + */ + const [open, setOpen] = useState(false); + + return error ? ( + + setOpen(!open)} + headerDataTestId={TEST_IDS.alertBox.sectionHeader.selector()} + contentDataTestId={TEST_IDS.alertBox.sectionContent.selector()} + > +
+ {error} +
+
+
+ ) : ( + <> + ); +}; diff --git a/packages/components/src/components/AlertBox/index.ts b/packages/components/src/components/AlertBox/index.ts new file mode 100644 index 0000000..06a8b04 --- /dev/null +++ b/packages/components/src/components/AlertBox/index.ts @@ -0,0 +1 @@ +export * from './AlertBox'; diff --git a/packages/components/src/components/index.ts b/packages/components/src/components/index.ts index b99576b..313a540 100644 --- a/packages/components/src/components/index.ts +++ b/packages/components/src/components/index.ts @@ -1,4 +1,5 @@ export * from './AutosizeCodeEditor'; +export * from './AlertBox'; export * from './CollapsableSection'; export * from './Collapse'; export * from './DatasourceEditor'; diff --git a/packages/components/src/constants/tests.ts b/packages/components/src/constants/tests.ts index 1566104..9e32b4d 100644 --- a/packages/components/src/constants/tests.ts +++ b/packages/components/src/constants/tests.ts @@ -1,4 +1,5 @@ import { createSelector } from '@volkovlabs/jest-selectors'; +import { AlertBox } from '../components/AlertBox'; /** * Test Identifiers @@ -38,4 +39,10 @@ export const TEST_IDS = { loadingMessage: createSelector('data-testid payload-editor loading-message'), errorMessage: createSelector('data-testid payload-editor error-message'), }, + alertBox: { + root: createSelector('data-testid alert-box root'), + details: createSelector('data-testid alert-box details'), + sectionHeader: createSelector('data-testid alert-box section-header'), + sectionContent: createSelector('data-testid alert-box section-content'), + }, }; From b980f12d4d8a2ee37ff48d77be2f0ff4640ef237 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 7 Jan 2025 15:15:42 +0300 Subject: [PATCH 2/6] lint fixes --- packages/components/src/components/AlertBox/AlertBox.tsx | 4 ++-- packages/components/src/components/index.ts | 2 +- packages/components/src/constants/tests.ts | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/components/src/components/AlertBox/AlertBox.tsx b/packages/components/src/components/AlertBox/AlertBox.tsx index 672f830..7368387 100644 --- a/packages/components/src/components/AlertBox/AlertBox.tsx +++ b/packages/components/src/components/AlertBox/AlertBox.tsx @@ -1,9 +1,9 @@ import { Alert, useStyles2 } from '@grafana/ui'; import React, { useState } from 'react'; -import { getStyles } from './AlertBox.styles'; -import { CollapsableSection } from '../CollapsableSection'; import { TEST_IDS } from '../../constants'; +import { CollapsableSection } from '../CollapsableSection'; +import { getStyles } from './AlertBox.styles'; /** * Properties diff --git a/packages/components/src/components/index.ts b/packages/components/src/components/index.ts index 313a540..65a3bd5 100644 --- a/packages/components/src/components/index.ts +++ b/packages/components/src/components/index.ts @@ -1,5 +1,5 @@ -export * from './AutosizeCodeEditor'; export * from './AlertBox'; +export * from './AutosizeCodeEditor'; export * from './CollapsableSection'; export * from './Collapse'; export * from './DatasourceEditor'; diff --git a/packages/components/src/constants/tests.ts b/packages/components/src/constants/tests.ts index 9e32b4d..0e0cf47 100644 --- a/packages/components/src/constants/tests.ts +++ b/packages/components/src/constants/tests.ts @@ -1,5 +1,4 @@ import { createSelector } from '@volkovlabs/jest-selectors'; -import { AlertBox } from '../components/AlertBox'; /** * Test Identifiers From 1e613be4b97d65605a0e32a75c6548bcee8f9396 Mon Sep 17 00:00:00 2001 From: vitPinchuk Date: Tue, 7 Jan 2025 16:22:04 +0300 Subject: [PATCH 3/6] update to details --- .../src/components/AlertBox/AlertBox.test.tsx | 58 ---------- .../src/components/AlertBox/AlertBox.tsx | 50 --------- .../src/components/AlertBox/index.ts | 1 - .../AlertBoxWithDetails.story.tsx} | 14 ++- .../AlertBoxWithDetails.styles.ts} | 0 .../AlertBoxWithDetails.test.tsx | 103 ++++++++++++++++++ .../AlertWithDetails/AlertBoxWithDetails.tsx | 71 ++++++++++++ .../src/components/AlertWithDetails/index.ts | 1 + packages/components/src/components/index.ts | 2 +- 9 files changed, 184 insertions(+), 116 deletions(-) delete mode 100644 packages/components/src/components/AlertBox/AlertBox.test.tsx delete mode 100644 packages/components/src/components/AlertBox/AlertBox.tsx delete mode 100644 packages/components/src/components/AlertBox/index.ts rename packages/components/src/components/{AlertBox/AlertBox.story.tsx => AlertWithDetails/AlertBoxWithDetails.story.tsx} (58%) rename packages/components/src/components/{AlertBox/AlertBox.styles.ts => AlertWithDetails/AlertBoxWithDetails.styles.ts} (100%) create mode 100644 packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx create mode 100644 packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx create mode 100644 packages/components/src/components/AlertWithDetails/index.ts diff --git a/packages/components/src/components/AlertBox/AlertBox.test.tsx b/packages/components/src/components/AlertBox/AlertBox.test.tsx deleted file mode 100644 index 4e6e879..0000000 --- a/packages/components/src/components/AlertBox/AlertBox.test.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { fireEvent, render, screen } from '@testing-library/react'; -import { getJestSelectors, createSelector } from '@volkovlabs/jest-selectors'; -import React from 'react'; - -import { AlertBox } from './AlertBox'; -import { TEST_IDS } from '../../constants'; - -/** - * Properties - */ -type Props = React.ComponentProps; - -describe('Alert box', () => { - /** - * Selectors - */ - const getSelectors = getJestSelectors(TEST_IDS.alertBox); - const selectors = getSelectors(screen); - - /** - * Get Component - */ - const getComponent = (props: Partial) => { - return ; - }; - - it('Should show Alert box', () => { - const onChange = jest.fn(); - - render(getComponent({ error: 'Test Error', title: 'Test title', variant: 'error', onRemove: onChange })); - expect(selectors.root()).toBeVisible(); - }); - - it('Should not show Alert box if no errors', () => { - const onChange = jest.fn(); - - const { queryByTestId } = render( - getComponent({ error: '', title: 'Test title', variant: 'error', onRemove: onChange }) - ); - - expect(queryByTestId(TEST_IDS.alertBox.root.selector())).toBeNull(); - }); - - it('Should show Alert box details', () => { - const onChange = jest.fn(); - - render( - getComponent({ error: 'Test Error text in details', title: 'Test title', variant: 'error', onRemove: onChange }) - ); - expect(selectors.root()).toBeVisible(); - expect(selectors.sectionHeader()).toBeVisible(); - expect(selectors.details(true)).not.toBeInTheDocument(); - - fireEvent.click(selectors.sectionHeader()); - expect(selectors.details()).toBeVisible(); - expect(selectors.details()).toHaveTextContent('Test Error text in details'); - }); -}); diff --git a/packages/components/src/components/AlertBox/AlertBox.tsx b/packages/components/src/components/AlertBox/AlertBox.tsx deleted file mode 100644 index 7368387..0000000 --- a/packages/components/src/components/AlertBox/AlertBox.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { Alert, useStyles2 } from '@grafana/ui'; -import React, { useState } from 'react'; - -import { TEST_IDS } from '../../constants'; -import { CollapsableSection } from '../CollapsableSection'; -import { getStyles } from './AlertBox.styles'; - -/** - * Properties - */ -export type AlertBoxProps = { - error: string; - variant: 'success' | 'warning' | 'error' | 'info'; - title: string; - onRemove: (event: React.MouseEvent) => void; -}; - -/** - * Alert Box - */ -export const AlertBox: React.FC = ({ error, variant, title, onRemove }) => { - /** - * Styles - */ - const styles = useStyles2(getStyles); - - /** - * States - */ - const [open, setOpen] = useState(false); - - return error ? ( - - setOpen(!open)} - headerDataTestId={TEST_IDS.alertBox.sectionHeader.selector()} - contentDataTestId={TEST_IDS.alertBox.sectionContent.selector()} - > -
- {error} -
-
-
- ) : ( - <> - ); -}; diff --git a/packages/components/src/components/AlertBox/index.ts b/packages/components/src/components/AlertBox/index.ts deleted file mode 100644 index 06a8b04..0000000 --- a/packages/components/src/components/AlertBox/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './AlertBox'; diff --git a/packages/components/src/components/AlertBox/AlertBox.story.tsx b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx similarity index 58% rename from packages/components/src/components/AlertBox/AlertBox.story.tsx rename to packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx index 889a748..df9119b 100644 --- a/packages/components/src/components/AlertBox/AlertBox.story.tsx +++ b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx @@ -1,13 +1,13 @@ import { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { AlertBox, AlertBoxProps } from './AlertBox'; +import { AlertWithDetails, AlertWithDetailsProps } from './AlertBoxWithDetails'; const variants: string[] = ['error', 'warning', 'info', 'success']; -const meta: Meta = { - title: 'AlertBox', - component: AlertBox, +const meta: Meta = { + title: 'AlertBoxWithDetails', + component: AlertWithDetails, parameters: { controls: { exclude: ['onRemove'], @@ -17,20 +17,22 @@ const meta: Meta = { error: 'test', variant: 'error', title: 'Title', + display: true, }, argTypes: { error: { control: 'text' }, title: { control: 'text' }, + children: { control: 'text' }, variant: { control: { type: 'select', options: variants }, }, }, }; -export const Basic: StoryFn = ({ ...args }: AlertBoxProps) => { +export const Basic: StoryFn = ({ ...args }: AlertWithDetailsProps) => { return (
- +
); }; diff --git a/packages/components/src/components/AlertBox/AlertBox.styles.ts b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts similarity index 100% rename from packages/components/src/components/AlertBox/AlertBox.styles.ts rename to packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx new file mode 100644 index 0000000..021a5e8 --- /dev/null +++ b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx @@ -0,0 +1,103 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import { getJestSelectors, createSelector } from '@volkovlabs/jest-selectors'; +import React from 'react'; + +import { AlertWithDetails } from './AlertBoxWithDetails'; +import { TEST_IDS } from '../../constants'; + +/** + * Properties + */ +type Props = React.ComponentProps; + +describe('Alert box', () => { + /** + * Selectors + */ + const getSelectors = getJestSelectors(TEST_IDS.alertBox); + const selectors = getSelectors(screen); + + /** + * Get Component + */ + const getComponent = (props: Partial) => { + return ; + }; + + it('Should show Alert box with details', () => { + const onChange = jest.fn(); + + render( + getComponent({ error: 'Test Error', title: 'Test title', display: true, variant: 'error', onRemove: onChange }) + ); + expect(selectors.root()).toBeVisible(); + }); + + it('Should not show Alert box if disabled', () => { + const onChange = jest.fn(); + + const { queryByTestId } = render( + getComponent({ error: 'error', title: 'Test title', display: false, variant: 'error', onRemove: onChange }) + ); + + expect(queryByTestId(TEST_IDS.alertBox.root.selector())).toBeNull(); + }); + + it('Should show Alert box details for errors', () => { + const onChange = jest.fn(); + + render( + getComponent({ + error: 'Test Error text in details', + title: 'Test title', + display: true, + variant: 'error', + onRemove: onChange, + }) + ); + expect(selectors.root()).toBeVisible(); + expect(selectors.sectionHeader()).toBeVisible(); + expect(selectors.details(true)).not.toBeInTheDocument(); + + fireEvent.click(selectors.sectionHeader()); + expect(selectors.details()).toBeVisible(); + expect(selectors.details()).toHaveTextContent('Test Error text in details'); + }); + + it('Should show Alert box as alert', () => { + render( + getComponent({ + error: '', + title: 'Test title', + children: 'alert content', + display: true, + variant: 'error', + }) + ); + + expect(selectors.root()).toBeVisible(); + expect(selectors.sectionHeader(true)).not.toBeInTheDocument(); + expect(selectors.details(true)).not.toBeInTheDocument(); + + expect(selectors.root()).toHaveTextContent('alert content'); + }); + + it('Should show Alert with empty content', () => { + const onChange = jest.fn(); + + render( + getComponent({ + error: '', + title: '', + children: '', + display: true, + variant: 'error', + }) + ); + + expect(selectors.root()).toBeVisible(); + expect(selectors.sectionHeader(true)).not.toBeInTheDocument(); + expect(selectors.details(true)).not.toBeInTheDocument(); + expect(selectors.root()).toHaveTextContent(''); + }); +}); diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx new file mode 100644 index 0000000..c09a599 --- /dev/null +++ b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx @@ -0,0 +1,71 @@ +import { Alert, useStyles2 } from '@grafana/ui'; +import React, { ReactNode, useState } from 'react'; + +import { TEST_IDS } from '../../constants'; +import { CollapsableSection } from '../CollapsableSection'; +import { getStyles } from './AlertBoxWithDetails.styles'; + +/** + * Properties + */ +export type AlertWithDetailsProps = { + error: string; + variant: 'success' | 'warning' | 'error' | 'info'; + title: string; + onRemove?: (event: React.MouseEvent) => void; + children?: ReactNode; + display: boolean; +}; + +/** + * Alert Box + */ +export const AlertWithDetails: React.FC = ({ + children, + error, + variant, + title, + display, + onRemove, +}) => { + /** + * Styles + */ + const styles = useStyles2(getStyles); + + /** + * States + */ + const [open, setOpen] = useState(false); + + const returnContent = () => { + if (error) { + return ( + setOpen(!open)} + headerDataTestId={TEST_IDS.alertBox.sectionHeader.selector()} + contentDataTestId={TEST_IDS.alertBox.sectionContent.selector()} + > +
+ {error} +
+
+ ); + } + if (children) { + return children; + } + return <>; + }; + + return display ? ( + + {returnContent()} + + ) : ( + <> + ); +}; diff --git a/packages/components/src/components/AlertWithDetails/index.ts b/packages/components/src/components/AlertWithDetails/index.ts new file mode 100644 index 0000000..0aa4890 --- /dev/null +++ b/packages/components/src/components/AlertWithDetails/index.ts @@ -0,0 +1 @@ +export * from './AlertBoxWithDetails'; diff --git a/packages/components/src/components/index.ts b/packages/components/src/components/index.ts index 65a3bd5..8cb5ce1 100644 --- a/packages/components/src/components/index.ts +++ b/packages/components/src/components/index.ts @@ -1,4 +1,4 @@ -export * from './AlertBox'; +export * from './AlertWithDetails'; export * from './AutosizeCodeEditor'; export * from './CollapsableSection'; export * from './Collapse'; From fcb00be031d56808fff8395931a4f3060a8a8991 Mon Sep 17 00:00:00 2001 From: asimonok Date: Tue, 7 Jan 2025 17:00:09 +0300 Subject: [PATCH 4/6] Formatting and update styles --- .../AlertBoxWithDetails.styles.ts | 14 ---- .../AlertWithDetails/AlertBoxWithDetails.tsx | 71 ------------------- ...s.story.tsx => AlertWithDetails.story.tsx} | 10 +-- .../AlertWithDetails.styles.ts | 19 +++++ ...ils.test.tsx => AlertWithDetails.test.tsx} | 49 +++++-------- .../AlertWithDetails/AlertWithDetails.tsx | 51 +++++++++++++ .../src/components/AlertWithDetails/index.ts | 2 +- packages/components/src/constants/tests.ts | 9 ++- 8 files changed, 97 insertions(+), 128 deletions(-) delete mode 100644 packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts delete mode 100644 packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx rename packages/components/src/components/AlertWithDetails/{AlertBoxWithDetails.story.tsx => AlertWithDetails.story.tsx} (83%) create mode 100644 packages/components/src/components/AlertWithDetails/AlertWithDetails.styles.ts rename packages/components/src/components/AlertWithDetails/{AlertBoxWithDetails.test.tsx => AlertWithDetails.test.tsx} (51%) create mode 100644 packages/components/src/components/AlertWithDetails/AlertWithDetails.tsx diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts deleted file mode 100644 index 71209f3..0000000 --- a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.styles.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { css } from '@emotion/css'; - -/** - * Styles - */ -export const getStyles = () => { - return { - errorInfo: css` - padding: 0; - margin: 0; - font-size: 12px; - `, - }; -}; diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx b/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx deleted file mode 100644 index c09a599..0000000 --- a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { Alert, useStyles2 } from '@grafana/ui'; -import React, { ReactNode, useState } from 'react'; - -import { TEST_IDS } from '../../constants'; -import { CollapsableSection } from '../CollapsableSection'; -import { getStyles } from './AlertBoxWithDetails.styles'; - -/** - * Properties - */ -export type AlertWithDetailsProps = { - error: string; - variant: 'success' | 'warning' | 'error' | 'info'; - title: string; - onRemove?: (event: React.MouseEvent) => void; - children?: ReactNode; - display: boolean; -}; - -/** - * Alert Box - */ -export const AlertWithDetails: React.FC = ({ - children, - error, - variant, - title, - display, - onRemove, -}) => { - /** - * Styles - */ - const styles = useStyles2(getStyles); - - /** - * States - */ - const [open, setOpen] = useState(false); - - const returnContent = () => { - if (error) { - return ( - setOpen(!open)} - headerDataTestId={TEST_IDS.alertBox.sectionHeader.selector()} - contentDataTestId={TEST_IDS.alertBox.sectionContent.selector()} - > -
- {error} -
-
- ); - } - if (children) { - return children; - } - return <>; - }; - - return display ? ( - - {returnContent()} - - ) : ( - <> - ); -}; diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx b/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx similarity index 83% rename from packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx rename to packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx index df9119b..76ea2ba 100644 --- a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.story.tsx +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx @@ -1,12 +1,12 @@ import { Meta, StoryFn } from '@storybook/react'; import React from 'react'; -import { AlertWithDetails, AlertWithDetailsProps } from './AlertBoxWithDetails'; +import { AlertWithDetails, AlertWithDetailsProps } from './AlertWithDetails'; const variants: string[] = ['error', 'warning', 'info', 'success']; const meta: Meta = { - title: 'AlertBoxWithDetails', + title: 'AlertWithDetails', component: AlertWithDetails, parameters: { controls: { @@ -14,13 +14,13 @@ const meta: Meta = { }, }, args: { - error: 'test', + details: '{{some json example}}', variant: 'error', title: 'Title', - display: true, + children: 'Some content', }, argTypes: { - error: { control: 'text' }, + details: { control: 'textarea' }, title: { control: 'text' }, children: { control: 'text' }, variant: { diff --git a/packages/components/src/components/AlertWithDetails/AlertWithDetails.styles.ts b/packages/components/src/components/AlertWithDetails/AlertWithDetails.styles.ts new file mode 100644 index 0000000..fefddec --- /dev/null +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.styles.ts @@ -0,0 +1,19 @@ +import { css } from '@emotion/css'; +import { GrafanaTheme2 } from '@grafana/data'; + +/** + * Styles + */ +export const getStyles = (theme: GrafanaTheme2) => { + return { + details: css` + padding: 0; + margin: ${theme.spacing(1, 0, 0)}; + font-size: ${theme.typography.bodySmall.fontSize}; + `, + detailsContent: css` + padding: ${theme.spacing(1, 0)}; + font-size: ${theme.typography.bodySmall.fontSize}; + `, + }; +}; diff --git a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx b/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx similarity index 51% rename from packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx rename to packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx index 021a5e8..48e0505 100644 --- a/packages/components/src/components/AlertWithDetails/AlertBoxWithDetails.test.tsx +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx @@ -1,8 +1,8 @@ import { fireEvent, render, screen } from '@testing-library/react'; -import { getJestSelectors, createSelector } from '@volkovlabs/jest-selectors'; +import { getJestSelectors } from '@volkovlabs/jest-selectors'; import React from 'react'; -import { AlertWithDetails } from './AlertBoxWithDetails'; +import { AlertWithDetails } from './AlertWithDetails'; import { TEST_IDS } from '../../constants'; /** @@ -10,11 +10,11 @@ import { TEST_IDS } from '../../constants'; */ type Props = React.ComponentProps; -describe('Alert box', () => { +describe('AlertWithDetails', () => { /** * Selectors */ - const getSelectors = getJestSelectors(TEST_IDS.alertBox); + const getSelectors = getJestSelectors(TEST_IDS.alertWithDetails); const selectors = getSelectors(screen); /** @@ -27,57 +27,43 @@ describe('Alert box', () => { it('Should show Alert box with details', () => { const onChange = jest.fn(); - render( - getComponent({ error: 'Test Error', title: 'Test title', display: true, variant: 'error', onRemove: onChange }) - ); + render(getComponent({ details: 'Test Error', title: 'Test title', variant: 'error', onRemove: onChange })); expect(selectors.root()).toBeVisible(); }); - it('Should not show Alert box if disabled', () => { - const onChange = jest.fn(); - - const { queryByTestId } = render( - getComponent({ error: 'error', title: 'Test title', display: false, variant: 'error', onRemove: onChange }) - ); - - expect(queryByTestId(TEST_IDS.alertBox.root.selector())).toBeNull(); - }); - it('Should show Alert box details for errors', () => { const onChange = jest.fn(); render( getComponent({ - error: 'Test Error text in details', + details: 'Test Error text in details', title: 'Test title', - display: true, variant: 'error', onRemove: onChange, }) ); expect(selectors.root()).toBeVisible(); - expect(selectors.sectionHeader()).toBeVisible(); - expect(selectors.details(true)).not.toBeInTheDocument(); + expect(selectors.detailsSectionHeader()).toBeVisible(); + expect(selectors.detailsSectionContent(true)).not.toBeInTheDocument(); - fireEvent.click(selectors.sectionHeader()); - expect(selectors.details()).toBeVisible(); - expect(selectors.details()).toHaveTextContent('Test Error text in details'); + fireEvent.click(selectors.detailsSectionHeader()); + expect(selectors.detailsSectionContent()).toBeVisible(); + expect(selectors.detailsSectionContent()).toHaveTextContent('Test Error text in details'); }); it('Should show Alert box as alert', () => { render( getComponent({ - error: '', + details: '', title: 'Test title', children: 'alert content', - display: true, variant: 'error', }) ); expect(selectors.root()).toBeVisible(); - expect(selectors.sectionHeader(true)).not.toBeInTheDocument(); - expect(selectors.details(true)).not.toBeInTheDocument(); + expect(selectors.detailsSectionHeader(true)).not.toBeInTheDocument(); + expect(selectors.detailsSectionContent(true)).not.toBeInTheDocument(); expect(selectors.root()).toHaveTextContent('alert content'); }); @@ -87,17 +73,16 @@ describe('Alert box', () => { render( getComponent({ - error: '', + details: '', title: '', children: '', - display: true, variant: 'error', }) ); expect(selectors.root()).toBeVisible(); - expect(selectors.sectionHeader(true)).not.toBeInTheDocument(); - expect(selectors.details(true)).not.toBeInTheDocument(); + expect(selectors.detailsSectionHeader(true)).not.toBeInTheDocument(); + expect(selectors.detailsSectionContent(true)).not.toBeInTheDocument(); expect(selectors.root()).toHaveTextContent(''); }); }); diff --git a/packages/components/src/components/AlertWithDetails/AlertWithDetails.tsx b/packages/components/src/components/AlertWithDetails/AlertWithDetails.tsx new file mode 100644 index 0000000..905c1e5 --- /dev/null +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.tsx @@ -0,0 +1,51 @@ +import { Alert, useStyles2 } from '@grafana/ui'; +import React, { ReactNode, useState } from 'react'; + +import { TEST_IDS } from '../../constants'; +import { CollapsableSection } from '../CollapsableSection'; +import { getStyles } from './AlertWithDetails.styles'; + +/** + * Properties + */ +export type AlertWithDetailsProps = { + details?: string; + variant: 'success' | 'warning' | 'error' | 'info'; + title: string; + onRemove?: (event: React.MouseEvent) => void; + children?: ReactNode; +}; + +/** + * Alert With Details + */ +export const AlertWithDetails: React.FC = ({ children, details, variant, title, onRemove }) => { + /** + * Styles + */ + const styles = useStyles2(getStyles); + + /** + * States + */ + const [open, setOpen] = useState(false); + + return ( + + {children} + {!!details && ( + setOpen(!open)} + headerDataTestId={TEST_IDS.alertWithDetails.detailsSectionHeader.selector()} + contentDataTestId={TEST_IDS.alertWithDetails.detailsSectionContent.selector()} + > + {details} + + )} + + ); +}; diff --git a/packages/components/src/components/AlertWithDetails/index.ts b/packages/components/src/components/AlertWithDetails/index.ts index 0aa4890..61e75fd 100644 --- a/packages/components/src/components/AlertWithDetails/index.ts +++ b/packages/components/src/components/AlertWithDetails/index.ts @@ -1 +1 @@ -export * from './AlertBoxWithDetails'; +export * from './AlertWithDetails'; diff --git a/packages/components/src/constants/tests.ts b/packages/components/src/constants/tests.ts index 0e0cf47..291853a 100644 --- a/packages/components/src/constants/tests.ts +++ b/packages/components/src/constants/tests.ts @@ -38,10 +38,9 @@ export const TEST_IDS = { loadingMessage: createSelector('data-testid payload-editor loading-message'), errorMessage: createSelector('data-testid payload-editor error-message'), }, - alertBox: { - root: createSelector('data-testid alert-box root'), - details: createSelector('data-testid alert-box details'), - sectionHeader: createSelector('data-testid alert-box section-header'), - sectionContent: createSelector('data-testid alert-box section-content'), + alertWithDetails: { + root: createSelector('data-testid alert-with-details root'), + detailsSectionHeader: createSelector('data-testid alert-with-details details-section-header'), + detailsSectionContent: createSelector('data-testid alert-with-details details-section-content'), }, }; From 01962ce8cd8216e5650d87216f9c9fe206d88301 Mon Sep 17 00:00:00 2001 From: asimonok Date: Tue, 7 Jan 2025 17:01:41 +0300 Subject: [PATCH 5/6] Remove unused code --- .../src/components/AlertWithDetails/AlertWithDetails.test.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx b/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx index 48e0505..04f7fa6 100644 --- a/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.test.tsx @@ -69,8 +69,6 @@ describe('AlertWithDetails', () => { }); it('Should show Alert with empty content', () => { - const onChange = jest.fn(); - render( getComponent({ details: '', From c5323e1655a4e41a55337bead44fbe002438f0c2 Mon Sep 17 00:00:00 2001 From: asimonok Date: Tue, 7 Jan 2025 17:06:34 +0300 Subject: [PATCH 6/6] Update alert with details story to support onRemove property --- .../AlertWithDetails/AlertWithDetails.story.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx b/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx index 76ea2ba..d774e23 100644 --- a/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx +++ b/packages/components/src/components/AlertWithDetails/AlertWithDetails.story.tsx @@ -1,5 +1,5 @@ import { Meta, StoryFn } from '@storybook/react'; -import React from 'react'; +import React, { useState } from 'react'; import { AlertWithDetails, AlertWithDetailsProps } from './AlertWithDetails'; @@ -30,11 +30,8 @@ const meta: Meta = { }; export const Basic: StoryFn = ({ ...args }: AlertWithDetailsProps) => { - return ( -
- -
- ); + const [show, setShow] = useState(true); + return
{show && setShow(false)} />}
; }; export default meta;