diff --git a/src/components/ChangelogDialog/ChangelogDialog.scss b/src/components/ChangelogDialog/ChangelogDialog.scss index 3a39178f..53836400 100644 --- a/src/components/ChangelogDialog/ChangelogDialog.scss +++ b/src/components/ChangelogDialog/ChangelogDialog.scss @@ -30,4 +30,13 @@ $maxItemsHeight: 70vh; color: var(--g-color-text-secondary); text-align: center; } + + &__loading { + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + height: 70vh; + width: 100%; + } } diff --git a/src/components/ChangelogDialog/ChangelogDialog.tsx b/src/components/ChangelogDialog/ChangelogDialog.tsx index bd1a7448..e599f4de 100644 --- a/src/components/ChangelogDialog/ChangelogDialog.tsx +++ b/src/components/ChangelogDialog/ChangelogDialog.tsx @@ -2,10 +2,11 @@ import React from 'react'; import {ArrowUpRightFromSquare} from '@gravity-ui/icons'; import type {DialogProps} from '@gravity-ui/uikit'; -import {Dialog, Icon, Link} from '@gravity-ui/uikit'; +import {Dialog, Icon, Link, Loader} from '@gravity-ui/uikit'; import {block} from '../utils/cn'; +import {ErrorContainer} from './components/ErrorContainer/ErrorContainer'; import {Item} from './components/Item/Item'; import i18n from './i18n'; import type {ChangelogItem} from './types'; @@ -24,6 +25,9 @@ export interface ChangelogDialogProps { onClose: DialogProps['onClose']; onLinkClick?: (link: string) => void; onStoryClick?: (storyId: string) => void; + onRetryClick?: () => void; + loading?: boolean; + error?: boolean | {title: string; description: string}; } let nextId = 1; @@ -41,6 +45,9 @@ export function ChangelogDialog({ onClose, onStoryClick, onLinkClick, + onRetryClick, + loading, + error, }: ChangelogDialogProps) { const idRef = React.useRef(); idRef.current = idRef.current || getNextId(); @@ -67,19 +74,27 @@ export function ChangelogDialog({ ) : null} - {items.length > 0 ? ( - items.map((item, index) => ( - - )) - ) : ( -
{i18n('label_empty')}
+ {loading && ( +
+ +
)} + {error && !loading && } + {!error && + !loading && + (items.length > 0 ? ( + items.map((item, index) => ( + + )) + ) : ( +
{i18n('label_empty')}
+ ))}
); diff --git a/src/components/ChangelogDialog/__stories__/ChangelogDialog.stories.tsx b/src/components/ChangelogDialog/__stories__/ChangelogDialog.stories.tsx index 5b1fda35..9c6fb4e6 100644 --- a/src/components/ChangelogDialog/__stories__/ChangelogDialog.stories.tsx +++ b/src/components/ChangelogDialog/__stories__/ChangelogDialog.stories.tsx @@ -108,7 +108,6 @@ const DefaultTemplate: StoryFn = (props: ChangelogDialogPr }; export const Default = DefaultTemplate.bind({}); - Default.args = { open: false, items, @@ -121,4 +120,21 @@ Default.args = { onClose: () => { console.log('close'); }, + onRetryClick: () => { + console.log('retry'); + }, +}; + +export const Loading = DefaultTemplate.bind({}); +Loading.args = { + ...Default.args, + open: true, + loading: true, +}; + +export const Error = DefaultTemplate.bind({}); +Error.args = { + ...Default.args, + open: true, + error: true, }; diff --git a/src/components/ChangelogDialog/components/ErrorContainer/ErrorContainer.tsx b/src/components/ChangelogDialog/components/ErrorContainer/ErrorContainer.tsx new file mode 100644 index 00000000..d970b604 --- /dev/null +++ b/src/components/ChangelogDialog/components/ErrorContainer/ErrorContainer.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +import {Alert} from '@gravity-ui/uikit'; + +import i18n from '../../i18n'; + +interface ErrorContainerProps { + onRetryClick?: () => void; + error?: boolean | {title?: string; description?: string}; +} + +export function ErrorContainer({onRetryClick, error}: ErrorContainerProps) { + const {title, description} = React.useMemo(() => { + return error && typeof error === 'object' ? error : {}; + }, [error]); + + return ( + + ); +} diff --git a/src/components/ChangelogDialog/i18n/en.json b/src/components/ChangelogDialog/i18n/en.json index 572990dc..1310d91d 100644 --- a/src/components/ChangelogDialog/i18n/en.json +++ b/src/components/ChangelogDialog/i18n/en.json @@ -4,5 +4,7 @@ "label_new": "New", "button_view_story": "View story", "label_empty": "No data", - "action_read-more": "Read more" + "action_read-more": "Read more", + "label_error-title": "Unable load changelog", + "button_retry": "Retry" } diff --git a/src/components/ChangelogDialog/i18n/ru.json b/src/components/ChangelogDialog/i18n/ru.json index c16621b5..7a9391c2 100644 --- a/src/components/ChangelogDialog/i18n/ru.json +++ b/src/components/ChangelogDialog/i18n/ru.json @@ -4,5 +4,7 @@ "label_new": "New", "button_view_story": "Посмотреть сториз", "label_empty": "Нет данных", - "action_read-more": "Читать далее" + "action_read-more": "Читать далее", + "label_error-title": "Не удалось загрузить список изменений", + "button_retry": "Повторить" } diff --git a/src/components/ChangelogDialog/types.ts b/src/components/ChangelogDialog/types.ts index 5f4f94e0..96177c94 100644 --- a/src/components/ChangelogDialog/types.ts +++ b/src/components/ChangelogDialog/types.ts @@ -1,3 +1,5 @@ +import React from 'react'; + interface ImageData { src: string; alt?: string; @@ -9,7 +11,7 @@ export interface ChangelogItem { isNew?: boolean; title: string; image?: ImageData; - description: string; + description: React.ReactNode; storyId?: string; link?: string; }