Skip to content

Commit

Permalink
Fix cluster dashboard (#870)
Browse files Browse the repository at this point in the history
Rework error handling function for authheader to always provide a message and not rely on response.json();

Add cluster storage and usage routes to new MVC structure.

Remove file export options, as they are not functional enough for production environments
  • Loading branch information
FancMa01 authored Sep 11, 2024
1 parent f77e641 commit 8e18fad
Show file tree
Hide file tree
Showing 8 changed files with 292 additions and 429 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import Text from '../../../common/Text';
import { Button, message, Dropdown } from 'antd';
import { Button, Dropdown } from 'antd';
import { DownOutlined } from '@ant-design/icons';
import { authHeader, handleError } from '../../../common/AuthHeader.js';

import { useLocation } from 'react-router-dom';
import DashboardModal from './DashboardModal';

const ExportMenu = (selectedCluster) => {
const ExportMenu = () => {
const {
application: { applicationId },
} = useSelector((state) => state.applicationReducer);
Expand All @@ -23,89 +23,21 @@ const ExportMenu = (selectedCluster) => {
setDataType(splitName[splitName.length - 1]);
});

// const menu = (
// <Menu onClick={(e) => handleMenuClick(e)}>
// <Menu.Item key="CSV">
// <i className="fa fa-lg fa-file"></i> {<Text text="CSV" />}
// </Menu.Item>
// <Menu.Item key="JSON">
// <i className="fa fa-lg fa-file-text-o"></i> {<Text text="JSON" />}
// </Menu.Item>
// <Menu.Item key="API">
// <i className="fa fa-lg fa-link"></i> {<Text text="API" />}
// </Menu.Item>
// </Menu>
// );

const menuItems = [
{ key: 'CSV', icon: <i className="fa fa-lg fa-file"></i>, label: 'CSV' },
{ key: 'JSON', icon: <i className="fa fa-lg fa-file-text-o"></i>, label: 'JSON' },
{ key: 'API', icon: <i className="fa fa-lg fa-link"></i>, label: 'API' },
{
key: 'API',
icon: <i className="fa fa-lg fa-link"></i>,
label: 'API',
onClick: (e) => {
handleMenuClick(e);
},
},
];

const handleMenuClick = async (e) => {
if (e.key === 'API') {
setModalVisible(true);
}

if (e.key === 'CSV' || e.key === 'JSON') {
await getFile(e.key);
}
};

const getFile = async (type) => {
try {
//TO DO --- write checks using dataType State to reach out to correct API's
//example if (dataType === 'notifications') {
const payload = {
method: 'GET',
header: authHeader(),
};

let response;
if (dataType === 'notifications') {
response = await fetch(`/api/notifications/read/${applicationId}/file/${type}`, payload);
}

if (dataType === 'clusterUsage') {
response = await fetch(
`/api/cluster/clusterStorageHistory/file/${type}/${selectedCluster.selectedCluster}`,
payload
);
}

if (!response.ok) handleError(response);
const blob = await response.blob();
const newBlob = new Blob([blob]);

const blobUrl = window.URL.createObjectURL(newBlob);

const link = document.createElement('a');
link.href = blobUrl;
link.setAttribute('download', `Tombolo-${dataType}.${type}`);
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);

//send delete request after file is downloaded
const payload2 = {
method: 'DELETE',
header: authHeader(),
};
if (dataType === 'notifications') {
const response2 = await fetch(`/api/notifications/read/${applicationId}/file/${type}`, payload2);

if (!response2.ok) handleError(response2);
}

if (dataType === 'clusterUsage') {
const response2 = await fetch(`/api/cluster/clusterStorageHistory/file/${type}`, payload2);

if (!response2.ok) handleError(response2);
}
} catch (error) {
message.error('Failed to fetch notifications');
}
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ function CurrentClusterUsageCharts({ selectedCluster, setSelectedCluster }) {
};

const response = await fetch(`/api/cluster/currentClusterUsage/${clusterId}`, payload);
if (!response.ok) handleError(response);
if (!response.ok) {
handleError(response);
return;
}
const data = await response.json();

const groupedUsage = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ function ClusterUsage() {
const queryData = JSON.stringify({ clusterId, historyDateRange });

const response = await fetch(`/api/cluster/clusterStorageHistory/${queryData}`, payload);
if (!response.ok) handleError(response);
if (!response.ok) {
handleError(response);
return;
}
const data = await response.json();
setClusterUsageHistory(data);
} catch (err) {
Expand Down
15 changes: 9 additions & 6 deletions Tombolo/client-reactjs/src/components/common/AuthHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ export function handleError(response) {
store.dispatch(userActions.logout());
} else if (response.status == 422) {
throw Error('Error occurred while saving the data. Please check the form data');
} else if (response.status == 404) {
message.error('404: Resource not found on server');
return;
} else if (typeof response === 'string') {
message.error(response);
return;
} else {
let errorMessage = '';
response.json().then((responseData) => {
errorMessage = responseData.message;
//throw new Error(errorMessage);
message.error(errorMessage);
});
//if we have not defined a handling above, throw undefined error
message.error('An undefined error occurred. Please try again later');
return;
}
}

Expand Down
Loading

0 comments on commit 8e18fad

Please sign in to comment.