From 591a2ec2c669050bfec76ef0d43a690746423665 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Thu, 21 Apr 2022 17:50:44 -0400 Subject: [PATCH] fix(loading): ensure loading spinners are displayed (#412) * fix(security): jmx credentials view displays loading spinner * fix(recordings): table toolbars remain visible while loading allows actions such as creation, upload to be triggered while content view is still loading * fix(rules): display loading spinner * fix(templates): table toolbar remains visible while loading allows event templates to be uploaded while content view is still loading (cherry picked from commit a83c8954ea00f1de5692b33eb823db9c69ced660) --- src/app/Events/EventTemplates.tsx | 38 ++++---- src/app/Recordings/RecordingsTable.tsx | 31 ++++--- src/app/Rules/Rules.tsx | 6 +- src/app/SecurityPanel/StoreJmxCredentials.tsx | 90 ++++++++++--------- 4 files changed, 92 insertions(+), 73 deletions(-) diff --git a/src/app/Events/EventTemplates.tsx b/src/app/Events/EventTemplates.tsx index 0069b9c6d..b6423f94c 100644 --- a/src/app/Events/EventTemplates.tsx +++ b/src/app/Events/EventTemplates.tsx @@ -249,26 +249,32 @@ export const EventTemplates = () => { setSortBy({ index, direction }); }; + const toolbar: JSX.Element = (<> + + + + + + + + + + + + + + + ); if (errorMessage != '') { - return () + return (); } else if (isLoading) { - return () + return (<> + { toolbar } + + ); } else { return (<> - - - - - - - - - - - - - - + { toolbar } = (props) => { + let view: JSX.Element; if (props.errorMessage != '') { - return () + view = () } else if (props.isLoading) { - return () + view = () } else if (props.isEmpty) { - return ( - <> - { props.toolbar } + view = (<> No {props.tableTitle} - ) + ); } else { - return (<> - { props.toolbar } + view = (<> @@ -93,4 +91,9 @@ export const RecordingsTable: React.FunctionComponent = (p ); } + + return (<> + { props.toolbar } + { view } + ); }; diff --git a/src/app/Rules/Rules.tsx b/src/app/Rules/Rules.tsx index 7d03700c1..425d64a54 100644 --- a/src/app/Rules/Rules.tsx +++ b/src/app/Rules/Rules.tsx @@ -200,7 +200,9 @@ export const Rules = () => { }; const viewContent = () => { - if (rules.length === 0) { + if (isLoading) { + return ; + } else if (rules.length === 0) { return (<> @@ -209,8 +211,6 @@ export const Rules = () => { ); - } else if (isLoading) { - return ; } else { return (<>
{ const context = React.useContext(ServiceContext); @@ -66,12 +67,17 @@ const Component = () => { const [headerChecked, setHeaderChecked] = React.useState(false); const [checkedIndices, setCheckedIndices] = React.useState([] as number[]); const [showAuthModal, setShowAuthModal] = React.useState(false); + const [isLoading, setIsLoading] = React.useState(false); const tableColumns: string[] = ['Target Alias', 'Connect URL']; const tableTitle = 'Stored Credentials'; const refreshStoredTargetsList = React.useCallback(() => { - addSubscription(context.api.getTargetsWithStoredJmxCredentials().subscribe(t => setStoredTargets(t))); + setIsLoading(true); + addSubscription(context.api.getTargetsWithStoredJmxCredentials().subscribe((t: Target[]) => { + setStoredTargets(t); + setIsLoading(false); + })); }, [context, context.api, context.targets, setStoredTargets]); React.useEffect(() => { @@ -194,49 +200,53 @@ const Component = () => { return storedTargets.map((t, idx) => ); }, [storedTargets, checkedIndices]); - return ( - <> - {storedTargets.length === 0 ? ( - <> - - - - - No {tableTitle} - - - - ) : ( - <> - - - - - - ))} - - - {targetRows} - - - )} - - - ); + let content: JSX.Element; + if (isLoading) { + content = (<> + + ); + } else if (storedTargets.length === 0) { + content = (<> + + + + No {tableTitle} + + + ); + } else { + content = (<> + + + + + ))} + + + {targetRows} + + ); + } + + return (<> + + { content } + + ); }; export const StoreJmxCredentials: SecurityCard = { title: 'Store JMX Credentials', - description: `Targets for which Cryostat has stored JMX credentials are listed here. - If a Target JVM requires JMX authentication, Cryostat will use stored credentials + description: `Targets for which Cryostat has stored JMX credentials are listed here. + If a Target JVM requires JMX authentication, Cryostat will use stored credentials when attempting to open JMX connections to the target.`, content: Component, };
- {tableColumns.map((key, idx) => ( - {key}
+ {tableColumns.map((key, idx) => ( + {key}