forked from migtools/lib-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(🎸): Add ResolvedQuery, LoadingEmptyState, and Tooltip (migtools#80)
* feat: 🎸 Add ResolvedQuery, LoadingEmptyState, and Tooltip This adds lib-ui candidates from the forklift-ui repo * Remove conditional tooltip & update results array to map * Change name from result(s)Map nto result(s)WithErrorTitle(s)
- Loading branch information
1 parent
126abe8
commit ed50b7e
Showing
10 changed files
with
306 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { UseMutationResult, UseQueryResult } from 'react-query'; | ||
|
||
export type UnknownResult = Pick< | ||
UseQueryResult<unknown>, | ||
'isError' | 'isLoading' | 'isIdle' | 'error' | ||
>; | ||
|
||
export type UnknownMutationResult = Pick< | ||
UseMutationResult<unknown>, | ||
'isError' | 'isLoading' | 'isIdle' | 'error' | 'reset' | ||
>; | ||
|
||
export type ResultsWithErrorTitles = { result: UnknownResult; errorTitle: string }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { | ||
Bullseye, | ||
EmptyState, | ||
EmptyStateBody, | ||
Spinner, | ||
SpinnerProps, | ||
Title, | ||
} from '@patternfly/react-core'; | ||
import * as React from 'react'; | ||
|
||
interface ILoadingEmptyStateProps { | ||
className?: string; | ||
spinnerProps?: Partial<SpinnerProps>; | ||
body?: React.ReactNode; | ||
} | ||
|
||
const LoadingEmptyState: React.FunctionComponent<ILoadingEmptyStateProps> = ({ | ||
className = '', | ||
spinnerProps = {}, | ||
body = null, | ||
}: ILoadingEmptyStateProps) => ( | ||
<Bullseye className={className}> | ||
<EmptyState variant="large"> | ||
<div className="pf-c-empty-state__icon"> | ||
<Spinner aria-labelledby="loadingPrefLabel" size="xl" {...spinnerProps} /> | ||
</div> | ||
<Title id="loadingPrefLabel" headingLevel="h2"> | ||
Loading... | ||
</Title> | ||
{body ? <EmptyStateBody>{body}</EmptyStateBody> : null} | ||
</EmptyState> | ||
</Bullseye> | ||
); | ||
|
||
export default LoadingEmptyState; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import * as React from 'react'; | ||
import { UseMutationResult } from 'react-query'; | ||
import { | ||
Spinner, | ||
Alert, | ||
AlertActionCloseButton, | ||
SpinnerProps, | ||
AlertProps, | ||
AlertGroup, | ||
} from '@patternfly/react-core'; | ||
import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; | ||
import { getAggregateQueryStatus } from '../../queries/helpers'; | ||
import { ResultsWithErrorTitles } from '../../common/types'; | ||
import { KubeClientError } from '../../modules/kube-client/types'; | ||
import LoadingEmptyState from '../LoadingEmptyState'; | ||
|
||
export type QuerySpinnerMode = 'inline' | 'emptyState' | 'none'; | ||
|
||
export interface IResolvedQueriesProps { | ||
resultsWithErrorTitles: ResultsWithErrorTitles[]; | ||
errorsInline?: boolean; | ||
spinnerMode?: QuerySpinnerMode; | ||
emptyStateBody?: React.ReactNode; | ||
spinnerProps?: Partial<SpinnerProps>; | ||
alertProps?: Partial<AlertProps>; | ||
className?: string; | ||
forceLoadingState?: boolean; | ||
children?: React.ReactNode; | ||
} | ||
|
||
export const ResolvedQueries: React.FunctionComponent<IResolvedQueriesProps> = ({ | ||
resultsWithErrorTitles, | ||
errorsInline = true, | ||
spinnerMode = 'emptyState', | ||
emptyStateBody = null, | ||
spinnerProps = {}, | ||
alertProps = {}, | ||
className = '', | ||
forceLoadingState = false, | ||
children = null, | ||
}: IResolvedQueriesProps) => { | ||
const status = getAggregateQueryStatus(resultsWithErrorTitles.map((r) => r.result)); | ||
const erroredResults = resultsWithErrorTitles.filter( | ||
(resultWithErrorTitle) => resultWithErrorTitle.result.isError | ||
); | ||
let spinner: React.ReactNode = null; | ||
if (spinnerMode === 'inline') { | ||
spinner = <Spinner size="lg" className={className} {...spinnerProps} />; | ||
} else if (spinnerMode === 'emptyState') { | ||
spinner = <LoadingEmptyState spinnerProps={spinnerProps} body={emptyStateBody} />; | ||
} | ||
|
||
return ( | ||
<> | ||
{status === 'loading' || forceLoadingState ? ( | ||
spinner | ||
) : status === 'error' ? ( | ||
<AlertGroup aria-live="assertive"> | ||
{erroredResults.map((resultWithErrorTitle, index) => { | ||
const { result, errorTitle } = resultWithErrorTitle; | ||
return ( | ||
<Alert | ||
key={`error-${index}`} | ||
variant="danger" | ||
isInline={errorsInline} | ||
title={errorTitle} | ||
className={`${ | ||
index !== erroredResults.length - 1 ? spacing.mbMd : '' | ||
} ${className}`} | ||
actionClose={ | ||
(result as { reset?: () => void }).reset ? ( | ||
<AlertActionCloseButton | ||
aria-label="Dismiss error" | ||
onClose={(result as UseMutationResult<unknown>).reset} | ||
/> | ||
) : null | ||
} | ||
{...alertProps} | ||
> | ||
{result.error ? ( | ||
<> | ||
{(result.error as Error).message || null} | ||
{(result.error as KubeClientError).response ? ( | ||
<> | ||
<br /> | ||
{(result.error as KubeClientError).response?.data?.message} | ||
</> | ||
) : null} | ||
{(result.error as Response).status | ||
? `${(result.error as Response).status}: ${ | ||
(result.error as Response).statusText | ||
}` | ||
: null} | ||
{typeof result.error === 'string' ? result.error : null} | ||
</> | ||
) : null} | ||
</Alert> | ||
); | ||
})} | ||
</AlertGroup> | ||
) : ( | ||
children | ||
)} | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import * as React from 'react'; | ||
import { UnknownResult } from '../../common/types'; | ||
import { ResolvedQueries, IResolvedQueriesProps } from './ResolvedQueries'; | ||
|
||
export interface IResolvedQueryProps extends Omit<IResolvedQueriesProps, 'resultsWithErrorTitles'> { | ||
result: UnknownResult; | ||
errorTitle: string; | ||
} | ||
|
||
export const ResolvedQuery: React.FunctionComponent<IResolvedQueryProps> = ({ | ||
result, | ||
errorTitle, | ||
...props | ||
}: IResolvedQueryProps) => ( | ||
<ResolvedQueries {...props} resultsWithErrorTitles={[{ result, errorTitle }]} /> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export * from './ResolvedQueries'; | ||
export * from './ResolvedQuery'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { AxiosError } from 'axios'; | ||
|
||
export type KubeClientError = AxiosError<{ message: string }>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { QueryStatus } from 'react-query'; | ||
import { UnknownResult } from '../common/types'; | ||
|
||
export const getAggregateQueryStatus = (queryResults: UnknownResult[]): QueryStatus => { | ||
if (queryResults.some((result) => result.isError)) return 'error'; | ||
if (queryResults.some((result) => result.isLoading)) return 'loading'; | ||
if (queryResults.every((result) => result.isIdle)) return 'idle'; | ||
return 'success'; | ||
}; |
Oops, something went wrong.