Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(auth): only show retry button for auth failures #545

Merged
merged 1 commit into from
Oct 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app/ErrorView/ErrorView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
import { ExclamationCircleIcon } from '@patternfly/react-icons';

export const authFailMessage = 'Auth failure';
export const isAuthFail = (message: string) => message === authFailMessage;
export interface ErrorViewProps {
title: string | React.ReactNode;
message: string | React.ReactNode;
Expand Down
92 changes: 59 additions & 33 deletions src/app/Events/EventTemplates.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import {
ToolbarGroup,
ToolbarItem,
TextInput,
Text,
} from '@patternfly/react-core';
import { UploadIcon } from '@patternfly/react-icons';
import {
Expand All @@ -72,7 +71,7 @@ import {
import { useHistory } from 'react-router-dom';
import { concatMap, filter, first } from 'rxjs/operators';
import { LoadingView } from '@app/LoadingView/LoadingView';
import { authFailMessage, ErrorView } from '@app/ErrorView/ErrorView';
import { authFailMessage, ErrorView, isAuthFail } from '@app/ErrorView/ErrorView';
import { DeleteWarningType } from '@app/Modal/DeleteWarningUtils';
import { DeleteWarningModal } from '@app/Modal/DeleteWarningModal';

Expand All @@ -95,12 +94,15 @@ export const EventTemplates = () => {
const [rowDeleteData, setRowDeleteData] = React.useState({} as IRowData);
const addSubscription = useSubscriptions();

const tableColumns = [
{ title: 'Name', transforms: [sortable] },
'Description',
{ title: 'Provider', transforms: [sortable] },
{ title: 'Type', transforms: [sortable] },
];
const tableColumns = React.useMemo(
() => [
{ title: 'Name', transforms: [sortable] },
'Description',
{ title: 'Provider', transforms: [sortable] },
{ title: 'Type', transforms: [sortable] },
],
[sortable]
);

React.useEffect(() => {
let filtered;
Expand Down Expand Up @@ -219,14 +221,17 @@ export const EventTemplates = () => {
[filteredTemplates]
);

const handleDelete = (rowData) => {
addSubscription(
context.api
.deleteCustomEventTemplate(rowData[0])
.pipe(first())
.subscribe(() => {} /* do nothing - notification will handle updating state */)
);
};
const handleDelete = React.useCallback(
(rowData) => {
addSubscription(
context.api
.deleteCustomEventTemplate(rowData[0])
.pipe(first())
.subscribe(() => {} /* do nothing - notification will handle updating state */)
);
},
[addSubscription, context.api]
);

const actionResolver = (rowData: IRowData, extraData: IExtraData) => {
if (typeof extraData.rowIndex == 'undefined') {
Expand Down Expand Up @@ -268,7 +273,7 @@ export const EventTemplates = () => {
return actions;
};

const handleModalToggle = () => {
const handleModalToggle = React.useCallback(() => {
setModalOpen((v) => {
if (v) {
setUploadFile(undefined);
Expand All @@ -277,15 +282,18 @@ export const EventTemplates = () => {
}
return !v;
});
};
}, [setModalOpen, setUploadFile, setUploadFilename, setUploading]);

const handleFileChange = (value, filename) => {
setFileRejected(false);
setUploadFile(value);
setUploadFilename(filename);
};
const handleFileChange = React.useCallback(
(value, filename) => {
setFileRejected(false);
setUploadFile(value);
setUploadFilename(filename);
},
[setFileRejected, setUploadFile, setUploadFilename]
);

const handleUploadSubmit = () => {
const handleUploadSubmit = React.useCallback(() => {
if (!uploadFile) {
window.console.error('Attempted to submit template upload without a file selected');
return;
Expand All @@ -304,21 +312,33 @@ export const EventTemplates = () => {
}
})
);
};
}, [
uploadFile,
window.console,
setUploading,
addSubscription,
context.api,
setUploadFile,
setUploadFilename,
setModalOpen,
]);

const handleUploadCancel = () => {
const handleUploadCancel = React.useCallback(() => {
setUploadFile(undefined);
setUploadFilename('');
setModalOpen(false);
};
}, [setUploadFile, setUploadFilename, setModalOpen]);

const handleFileRejected = () => {
const handleFileRejected = React.useCallback(() => {
setFileRejected(true);
};
}, [setFileRejected]);

const handleSort = (event, index, direction) => {
setSortBy({ index, direction });
};
const handleSort = React.useCallback(
(event, index, direction) => {
setSortBy({ index, direction });
},
[setSortBy]
);

const handleDeleteButton = React.useCallback(
(rowData) => {
Expand Down Expand Up @@ -379,7 +399,13 @@ export const EventTemplates = () => {
}, [context.target, context.target.setAuthRetry]);

if (errorMessage != '') {
return <ErrorView title={'Error retrieving event templates'} message={errorMessage} retry={authRetry} />;
return (
<ErrorView
title={'Error retrieving event templates'}
message={errorMessage}
retry={isAuthFail(errorMessage) ? authRetry : undefined}
/>
);
} else if (isLoading) {
return (
<>
Expand Down
103 changes: 58 additions & 45 deletions src/app/Events/EventTypes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ import {
ToolbarItemVariant,
Pagination,
TextInput,
Text,
Button,
} from '@patternfly/react-core';
import { expandable, Table, TableBody, TableHeader, TableVariant } from '@patternfly/react-table';
import { concatMap, filter, first } from 'rxjs/operators';
import { LoadingView } from '@app/LoadingView/LoadingView';
import { authFailMessage, ErrorView } from '@app/ErrorView/ErrorView';
import { authFailMessage, ErrorView, isAuthFail } from '@app/ErrorView/ErrorView';

export interface EventType {
name: string;
Expand All @@ -75,6 +73,10 @@ type Row = {
fullWidth?: boolean;
};

const getCategoryString = (eventType: EventType): string => {
return eventType.category.join(', ').trim();
};

export const EventTypes = () => {
const context = React.useContext(ServiceContext);
const addSubscription = useSubscriptions();
Expand All @@ -89,15 +91,18 @@ export const EventTypes = () => {
const [isLoading, setIsLoading] = React.useState(false);
const [errorMessage, setErrorMessage] = React.useState('');

const tableColumns = [
{
title: 'Name',
cellFormatters: [expandable],
},
'Type ID',
'Description',
'Categories',
];
const tableColumns = React.useMemo(
() => [
{
title: 'Name',
cellFormatters: [expandable],
},
'Type ID',
'Description',
'Categories',
],
[expandable]
);

const handleTypes = React.useCallback(
(types) => {
Expand Down Expand Up @@ -128,10 +133,10 @@ export const EventTypes = () => {
context.api.doGet<EventType[]>(`targets/${encodeURIComponent(target.connectUrl)}/events`)
)
)
.subscribe(
(value) => handleTypes(value),
(err) => handleError(err)
)
.subscribe({
next: handleTypes,
error: handleError,
})
);
}, [addSubscription, context.target, context.api]);

Expand All @@ -145,16 +150,9 @@ export const EventTypes = () => {
}, [addSubscription, context, context.target, refreshEvents]);

React.useEffect(() => {
const sub = context.target.authFailure().subscribe(() => {
setErrorMessage(authFailMessage);
});
return () => sub.unsubscribe();
addSubscription(context.target.authFailure().subscribe(() => setErrorMessage(authFailMessage)));
}, [context.target]);

const getCategoryString = (eventType: EventType): string => {
return eventType.category.join(', ').trim();
};

const filterTypesByText = React.useCallback(() => {
if (!filterText) {
return types;
Expand Down Expand Up @@ -196,38 +194,53 @@ export const EventTypes = () => {
setDisplayedTypes(rows);
}, [currentPage, perPage, filterTypesByText, openRow]);

const onCurrentPage = (evt, currentPage) => {
setOpenRow(-1);
setCurrentPage(currentPage);
};
const onCurrentPage = React.useCallback(
(evt, currentPage) => {
setOpenRow(-1);
setCurrentPage(currentPage);
},
[setOpenRow, setCurrentPage]
);

const onPerPage = (evt, perPage) => {
const offset = (currentPage - 1) * prevPerPage.current;
prevPerPage.current = perPage;
setOpenRow(-1);
setPerPage(perPage);
setCurrentPage(1 + Math.floor(offset / perPage));
};
const onPerPage = React.useCallback(
(evt, perPage) => {
const offset = (currentPage - 1) * prevPerPage.current;
prevPerPage.current = perPage;
setOpenRow(-1);
setPerPage(perPage);
setCurrentPage(1 + Math.floor(offset / perPage));
},
[currentPage, prevPerPage, setOpenRow, setPerPage, setCurrentPage]
);

const onCollapse = (event, rowKey, isOpen) => {
if (isOpen) {
if (openRow === -1) {
setOpenRow(rowKey);
const onCollapse = React.useCallback(
(event, rowKey, isOpen) => {
if (isOpen) {
if (openRow === -1) {
setOpenRow(rowKey);
} else {
setOpenRow(rowKey > openRow ? rowKey - 1 : rowKey);
}
} else {
setOpenRow(rowKey > openRow ? rowKey - 1 : rowKey);
setOpenRow(-1);
}
} else {
setOpenRow(-1);
}
};
},
[setOpenRow, openRow]
);

const authRetry = React.useCallback(() => {
context.target.setAuthRetry();
}, [context.target, context.target.setAuthRetry]);

// TODO replace table with data list so collapsed event options can be custom formatted
if (errorMessage != '') {
return <ErrorView title={'Error retrieving event types'} message={errorMessage} retry={authRetry} />;
return (
<ErrorView
title={'Error retrieving event types'}
message={errorMessage}
retry={isAuthFail(errorMessage) ? authRetry : undefined}
/>
);
} else if (isLoading) {
return <LoadingView />;
} else {
Expand Down
6 changes: 1 addition & 5 deletions src/app/Recordings/ActiveRecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,7 @@ export const ActiveRecordingsTable: React.FunctionComponent<ActiveRecordingsTabl
}, [addSubscription, context, context.notificationChannel, setRecordings]);

React.useEffect(() => {
addSubscription(
context.target.authFailure().subscribe(() => {
setErrorMessage(authFailMessage);
})
);
addSubscription(context.target.authFailure().subscribe(() => setErrorMessage(authFailMessage)));
}, [context, context.target, setErrorMessage, addSubscription]);

React.useEffect(() => {
Expand Down
13 changes: 7 additions & 6 deletions src/app/Recordings/RecordingActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ export const RecordingActions: React.FunctionComponent<RecordingActionsProps> =
const addSubscription = useSubscriptions();

React.useEffect(() => {
const sub = context.api
.grafanaDatasourceUrl()
.pipe(first())
.subscribe(() => setGrafanaEnabled(true));
return () => sub.unsubscribe();
}, [context.api, setGrafanaEnabled]);
addSubscription(
context.api
.grafanaDatasourceUrl()
.pipe(first())
.subscribe(() => setGrafanaEnabled(true))
);
}, [context.api, setGrafanaEnabled, addSubscription]);

const grafanaUpload = React.useCallback(() => {
notifications.info('Upload Started', `Recording "${props.recording.name}" uploading...`);
Expand Down
8 changes: 6 additions & 2 deletions src/app/Recordings/RecordingsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
import { TableComposable, Thead, Tr, Th, OuterScrollContainer, InnerScrollContainer } from '@patternfly/react-table';
import { LoadingView } from '@app/LoadingView/LoadingView';
import { ErrorView } from '@app/ErrorView/ErrorView';
import { ErrorView, isAuthFail } from '@app/ErrorView/ErrorView';
import { ServiceContext } from '@app/Shared/Services/Services';

export interface RecordingsTableProps {
Expand Down Expand Up @@ -77,7 +77,11 @@ export const RecordingsTable: React.FunctionComponent<RecordingsTableProps> = (p
if (props.errorMessage != '') {
view = (
<>
<ErrorView title={'Error retrieving recordings'} message={props.errorMessage} retry={authRetry}></ErrorView>
<ErrorView
title={'Error retrieving recordings'}
message={props.errorMessage}
retry={isAuthFail(props.errorMessage) ? authRetry : undefined}
/>
</>
);
} else if (props.isLoading) {
Expand Down
Loading