Added new implementation for error handling (#901)
Now errors will display detailed information, modal box errors will prioritize detailed errors
This commit is contained in:
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.8cfac526.chunk.css",
|
||||
"main.js": "/static/js/main.926c7b22.chunk.js",
|
||||
"main.js.map": "/static/js/main.926c7b22.chunk.js.map",
|
||||
"main.js": "/static/js/main.6ca7d2e8.chunk.js",
|
||||
"main.js.map": "/static/js/main.6ca7d2e8.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.43a31377.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.43a31377.js.map",
|
||||
"static/css/2.60e04a19.chunk.css": "/static/css/2.60e04a19.chunk.css",
|
||||
"static/js/2.1bafa615.chunk.js": "/static/js/2.1bafa615.chunk.js",
|
||||
"static/js/2.1bafa615.chunk.js.map": "/static/js/2.1bafa615.chunk.js.map",
|
||||
"static/js/2.da0353b6.chunk.js": "/static/js/2.da0353b6.chunk.js",
|
||||
"static/js/2.da0353b6.chunk.js.map": "/static/js/2.da0353b6.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/css/2.60e04a19.chunk.css.map": "/static/css/2.60e04a19.chunk.css.map",
|
||||
"static/css/main.8cfac526.chunk.css.map": "/static/css/main.8cfac526.chunk.css.map",
|
||||
"static/js/2.1bafa615.chunk.js.LICENSE.txt": "/static/js/2.1bafa615.chunk.js.LICENSE.txt",
|
||||
"static/js/2.da0353b6.chunk.js.LICENSE.txt": "/static/js/2.da0353b6.chunk.js.LICENSE.txt",
|
||||
"static/media/minio_console_logo.0837460e.svg": "/static/media/minio_console_logo.0837460e.svg",
|
||||
"static/media/minio_operator_logo.1312b7c9.svg": "/static/media/minio_operator_logo.1312b7c9.svg"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.43a31377.js",
|
||||
"static/css/2.60e04a19.chunk.css",
|
||||
"static/js/2.1bafa615.chunk.js",
|
||||
"static/js/2.da0353b6.chunk.js",
|
||||
"static/css/main.8cfac526.chunk.css",
|
||||
"static/js/main.926c7b22.chunk.js"
|
||||
"static/js/main.6ca7d2e8.chunk.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link href="/styles/root-styles.css" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.60e04a19.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="loader-block"><svg class="loader-svg-container" viewBox="22 22 44 44"><circle class="loader-style MuiCircularProgress-circle MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle></svg></div></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.1bafa615.chunk.js"></script><script src="/static/js/main.926c7b22.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link href="/styles/root-styles.css" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.60e04a19.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="loader-block"><svg class="loader-svg-container" viewBox="22 22 44 44"><circle class="loader-style MuiCircularProgress-circle MuiCircularProgress-circleIndeterminate" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle></svg></div></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.da0353b6.chunk.js"></script><script src="/static/js/main.6ca7d2e8.chunk.js"></script></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
portal-ui/build/static/js/2.da0353b6.chunk.js
Normal file
3
portal-ui/build/static/js/2.da0353b6.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/2.da0353b6.chunk.js.map
Normal file
1
portal-ui/build/static/js/2.da0353b6.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
2
portal-ui/build/static/js/main.6ca7d2e8.chunk.js
Normal file
2
portal-ui/build/static/js/main.6ca7d2e8.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
portal-ui/build/static/js/main.6ca7d2e8.chunk.js.map
Normal file
1
portal-ui/build/static/js/main.6ca7d2e8.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { ErrorResponseHandler } from "./common/types";
|
||||
import {
|
||||
MENU_OPEN,
|
||||
OPERATOR_MODE,
|
||||
@@ -85,7 +86,7 @@ export const setSnackBarMessage = (message: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const setErrorSnackMessage = (message: string) => {
|
||||
export const setErrorSnackMessage = (message: ErrorResponseHandler) => {
|
||||
return {
|
||||
type: SET_ERROR_SNACK_MESSAGE,
|
||||
message,
|
||||
@@ -99,7 +100,7 @@ export const setModalSnackMessage = (message: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const setModalErrorSnackMessage = (message: string) => {
|
||||
export const setModalErrorSnackMessage = (message: ErrorResponseHandler) => {
|
||||
return {
|
||||
type: SET_MODAL_ERROR_MESSAGE,
|
||||
message,
|
||||
|
||||
@@ -18,6 +18,7 @@ import request from "superagent";
|
||||
import get from "lodash/get";
|
||||
import { clearSession } from "../utils";
|
||||
import { baseUrl } from "../../history";
|
||||
import { ErrorResponseHandler } from "../types";
|
||||
|
||||
export class API {
|
||||
invoke(method: string, url: string, data?: object) {
|
||||
@@ -42,11 +43,24 @@ export class API {
|
||||
const errMessage = get(
|
||||
err.response,
|
||||
"body.message",
|
||||
err.status.toString()
|
||||
`Error ${err.status.toString()}`
|
||||
);
|
||||
|
||||
const throwMessage =
|
||||
let detailedMessage = get(err.response, "body.detailedMessage", "");
|
||||
|
||||
if (errMessage === detailedMessage) {
|
||||
detailedMessage = "";
|
||||
}
|
||||
|
||||
const capMessage =
|
||||
errMessage.charAt(0).toUpperCase() + errMessage.slice(1);
|
||||
const capDetailed =
|
||||
detailedMessage.charAt(0).toUpperCase() + detailedMessage.slice(1);
|
||||
|
||||
const throwMessage: ErrorResponseHandler = {
|
||||
errorMessage: capMessage,
|
||||
detailedError: capDetailed,
|
||||
};
|
||||
|
||||
return Promise.reject(throwMessage);
|
||||
} else {
|
||||
|
||||
@@ -378,3 +378,8 @@ export interface AffinityConfiguration {
|
||||
nodeSelectorLabels?: ILabelKeyPair[];
|
||||
withPodAntiAffinity?: boolean;
|
||||
}
|
||||
|
||||
export interface ErrorResponseHandler {
|
||||
errorMessage: string;
|
||||
detailedError: string;
|
||||
}
|
||||
|
||||
@@ -93,22 +93,38 @@ export function systemReducer(
|
||||
case SET_SNACK_BAR_MESSAGE:
|
||||
return {
|
||||
...state,
|
||||
snackBar: { message: action.message, type: "message" },
|
||||
snackBar: {
|
||||
message: action.message,
|
||||
detailedErrorMsg: "",
|
||||
type: "message",
|
||||
},
|
||||
};
|
||||
case SET_ERROR_SNACK_MESSAGE:
|
||||
return {
|
||||
...state,
|
||||
snackBar: { message: action.message, type: "error" },
|
||||
snackBar: {
|
||||
message: action.message.errorMessage,
|
||||
detailedErrorMsg: action.message.detailedError,
|
||||
type: "error",
|
||||
},
|
||||
};
|
||||
case SET_SNACK_MODAL_MESSAGE:
|
||||
return {
|
||||
...state,
|
||||
modalSnackBar: { message: action.message, type: "message" },
|
||||
modalSnackBar: {
|
||||
message: action.message,
|
||||
detailedErrorMsg: "",
|
||||
type: "message",
|
||||
},
|
||||
};
|
||||
case SET_MODAL_ERROR_MESSAGE:
|
||||
return {
|
||||
...state,
|
||||
modalSnackBar: { message: action.message, type: "error" },
|
||||
modalSnackBar: {
|
||||
message: action.message.errorMessage,
|
||||
detailedErrorMsg: action.message.detailedError,
|
||||
type: "error",
|
||||
},
|
||||
};
|
||||
case SET_SERVER_DIAG_STAT:
|
||||
return {
|
||||
|
||||
@@ -27,8 +27,8 @@ import {
|
||||
modalBasic,
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { ChangePasswordRequest } from "../Buckets/types";
|
||||
import api from "../../../common/api";
|
||||
import { setModalErrorSnackMessage } from "../../../actions";
|
||||
import api from "../../../common/api";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -62,12 +62,18 @@ const ChangePassword = ({
|
||||
event.preventDefault();
|
||||
|
||||
if (newPassword !== reNewPassword) {
|
||||
setModalErrorSnackMessage("New passwords don't match");
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "New passwords don't match",
|
||||
detailedError: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
setModalErrorSnackMessage("Passwords must be at least 8 characters long");
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "Passwords must be at least 8 characters long",
|
||||
detailedError: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,13 +68,10 @@ const ChangeUserPassword = ({
|
||||
setLoading(true);
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
setModalErrorSnackMessage("Passwords must be at least 8 characters long");
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (newPassword.length < 8) {
|
||||
setModalErrorSnackMessage("Passwords must be at least 8 characters long");
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "Passwords must be at least 8 characters long",
|
||||
detailedError: "",
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,10 @@ const AddReplicationModal = ({
|
||||
setAddLoading(false);
|
||||
|
||||
if (itemVal.errorString && itemVal.errorString !== "") {
|
||||
setModalErrorSnackMessage(itemVal.errorString);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: itemVal.errorString,
|
||||
detailedError: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,7 +140,10 @@ const AddReplicationModal = ({
|
||||
|
||||
return;
|
||||
}
|
||||
setModalErrorSnackMessage("No changes applied");
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "No changes applied",
|
||||
detailedError: "",
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
setAddLoading(false);
|
||||
|
||||
@@ -75,7 +75,6 @@ import {
|
||||
} from "../../../../../../actions";
|
||||
import { BucketVersioning } from "../../../types";
|
||||
import RewindEnable from "./RewindEnable";
|
||||
import FileCopyIcon from "@material-ui/icons/FileCopy";
|
||||
import DeleteIcon from "@material-ui/icons/Delete";
|
||||
import DeleteMultipleObjects from "./DeleteMultipleObjects";
|
||||
|
||||
|
||||
@@ -93,9 +93,10 @@ const ShareFile = ({
|
||||
const versID = distributedSetup ? dataObject.version_id : "null";
|
||||
|
||||
if (diffDate < 0) {
|
||||
setModalErrorSnackMessage(
|
||||
"Selected date must be greater than current time."
|
||||
);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "Selected date must be greater than current time.",
|
||||
detailedError: "",
|
||||
});
|
||||
setShareURL("");
|
||||
setIsLoadingFile(false);
|
||||
|
||||
@@ -103,9 +104,10 @@ const ShareFile = ({
|
||||
}
|
||||
|
||||
if (diffDate > 604800000) {
|
||||
setModalErrorSnackMessage(
|
||||
"You can share a file only for less than 7 days."
|
||||
);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "You can share a file only for less than 7 days.",
|
||||
detailedError: "",
|
||||
});
|
||||
setShareURL("");
|
||||
setIsLoadingFile(false);
|
||||
|
||||
|
||||
223
portal-ui/src/screens/Console/Common/MainError/MainError.tsx
Normal file
223
portal-ui/src/screens/Console/Common/MainError/MainError.tsx
Normal file
@@ -0,0 +1,223 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useState, useEffect, useCallback } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import get from "lodash/get";
|
||||
import ArrowRightIcon from "@material-ui/icons/ArrowRight";
|
||||
import ErrorOutlineIcon from "@material-ui/icons/ErrorOutline";
|
||||
import CloseIcon from "@material-ui/icons/Close";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import { AppState } from "../../../../store";
|
||||
import { setErrorSnackMessage } from "../../../../actions";
|
||||
import { snackBarMessage } from "../../../../types";
|
||||
|
||||
interface IMainErrorProps {
|
||||
classes: any;
|
||||
snackBar: snackBarMessage;
|
||||
displayErrorMessage: typeof setErrorSnackMessage;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
mainErrorContainer: {
|
||||
position: "absolute",
|
||||
width: "100%",
|
||||
backgroundColor: "#fff",
|
||||
border: "#C72C48 1px solid",
|
||||
borderLeftWidth: 12,
|
||||
borderRadius: 3,
|
||||
zIndex: 1000,
|
||||
padding: "10px 15px",
|
||||
maxWidth: 600,
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
marginTop: 15,
|
||||
opacity: 0,
|
||||
transitionDuration: "0.2s",
|
||||
},
|
||||
mainErrorShow: {
|
||||
opacity: 1,
|
||||
},
|
||||
closeButton: {
|
||||
position: "absolute",
|
||||
right: 5,
|
||||
fontSize: "small",
|
||||
border: 0,
|
||||
backgroundColor: "#fff",
|
||||
cursor: "pointer",
|
||||
},
|
||||
errorTitle: {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
},
|
||||
errorLabel: {
|
||||
color: "#000",
|
||||
fontSize: 18,
|
||||
fontWeight: 500,
|
||||
marginLeft: 5,
|
||||
},
|
||||
messageIcon: {
|
||||
color: "#C72C48",
|
||||
display: "flex",
|
||||
"& svg": {
|
||||
width: 32,
|
||||
height: 32,
|
||||
},
|
||||
},
|
||||
simpleError: {
|
||||
marginTop: 5,
|
||||
padding: "2px 5px",
|
||||
fontSize: 16,
|
||||
color: "#000",
|
||||
},
|
||||
detailsButton: {
|
||||
color: "#9C9C9C",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
border: 0,
|
||||
backgroundColor: "transparent",
|
||||
paddingLeft: 5,
|
||||
fontSize: 14,
|
||||
transformDuration: "0.3s",
|
||||
cursor: "pointer",
|
||||
},
|
||||
extraDetailsContainer: {
|
||||
fontStyle: "italic",
|
||||
color: "#9C9C9C",
|
||||
lineHeight: 0,
|
||||
padding: "0 10px",
|
||||
transition: "all .2s ease-in-out",
|
||||
overflow: "hidden",
|
||||
},
|
||||
extraDetailsOpen: {
|
||||
lineHeight: 1,
|
||||
padding: "3px 10px",
|
||||
},
|
||||
arrowElement: {
|
||||
marginLeft: -5,
|
||||
},
|
||||
arrowOpen: {
|
||||
transform: "rotateZ(90deg)",
|
||||
transformDuration: "0.3s",
|
||||
},
|
||||
});
|
||||
|
||||
var timerI: any;
|
||||
|
||||
const startHideTimer = (callbackFunction: () => void) => {
|
||||
timerI = setInterval(callbackFunction, 10000);
|
||||
};
|
||||
|
||||
const stopHideTimer = () => {
|
||||
clearInterval(timerI);
|
||||
};
|
||||
|
||||
const MainError = ({
|
||||
classes,
|
||||
snackBar,
|
||||
displayErrorMessage,
|
||||
}: IMainErrorProps) => {
|
||||
const [detailsOpen, setDetailsOpen] = useState<boolean>(false);
|
||||
const [displayErrorMsg, setDisplayErrorMsg] = useState<boolean>(false);
|
||||
|
||||
const closeErrorMessage = useCallback(() => {
|
||||
setDisplayErrorMsg(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!displayErrorMsg) {
|
||||
displayErrorMessage({ detailedError: "", errorMessage: "" });
|
||||
setDetailsOpen(false);
|
||||
clearInterval(timerI);
|
||||
}
|
||||
}, [displayErrorMessage, displayErrorMsg]);
|
||||
|
||||
useEffect(() => {
|
||||
if (snackBar.message !== "" && snackBar.type === "error") {
|
||||
//Error message received, we trigger the animation
|
||||
setDisplayErrorMsg(true);
|
||||
startHideTimer(closeErrorMessage);
|
||||
}
|
||||
}, [closeErrorMessage, snackBar.message, snackBar.type]);
|
||||
|
||||
const detailsToggle = () => {
|
||||
setDetailsOpen(!detailsOpen);
|
||||
};
|
||||
|
||||
const message = get(snackBar, "message", "");
|
||||
const messageDetails = get(snackBar, "detailedErrorMsg", "");
|
||||
|
||||
if (snackBar.type !== "error" || message === "") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<div
|
||||
className={`${classes.mainErrorContainer} ${
|
||||
displayErrorMsg ? classes.mainErrorShow : ""
|
||||
}`}
|
||||
onMouseOver={stopHideTimer}
|
||||
onMouseLeave={() => startHideTimer(closeErrorMessage)}
|
||||
>
|
||||
<button className={classes.closeButton} onClick={closeErrorMessage}>
|
||||
<CloseIcon />
|
||||
</button>
|
||||
<div className={classes.errorTitle}>
|
||||
<span className={classes.messageIcon}>
|
||||
<ErrorOutlineIcon />
|
||||
</span>
|
||||
<span className={classes.errorLabel}>Error</span>
|
||||
</div>
|
||||
<div className={classes.simpleError}>{message}</div>
|
||||
{messageDetails !== "" && (
|
||||
<Fragment>
|
||||
<div className={classes.detailsContainerLink}>
|
||||
<button className={classes.detailsButton} onClick={detailsToggle}>
|
||||
Details
|
||||
<ArrowRightIcon
|
||||
className={`${classes.arrowElement} ${
|
||||
detailsOpen ? classes.arrowOpen : ""
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className={`${classes.extraDetailsContainer} ${
|
||||
detailsOpen ? classes.extraDetailsOpen : ""
|
||||
}`}
|
||||
>
|
||||
{messageDetails}
|
||||
</div>
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
snackBar: state.system.snackBar,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
displayErrorMessage: setErrorSnackMessage,
|
||||
};
|
||||
|
||||
const connector = connect(mapState, mapDispatchToProps);
|
||||
|
||||
export default connector(withStyles(styles)(MainError));
|
||||
@@ -144,6 +144,18 @@ const ModalWrapper = ({
|
||||
}
|
||||
: { maxWidth: "md" as const, fullWidth: true };
|
||||
|
||||
let message = "";
|
||||
|
||||
if (modalSnackMessage) {
|
||||
message = modalSnackMessage.detailedErrorMsg;
|
||||
if (
|
||||
modalSnackMessage.detailedErrorMsg === "" ||
|
||||
modalSnackMessage.detailedErrorMsg.length < 5
|
||||
) {
|
||||
message = modalSnackMessage.message;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={modalOpen}
|
||||
@@ -159,7 +171,7 @@ const ModalWrapper = ({
|
||||
onClose={() => {
|
||||
closeSnackBar();
|
||||
}}
|
||||
message={modalSnackMessage ? modalSnackMessage.message : ""}
|
||||
message={message}
|
||||
ContentProps={{
|
||||
className: `${classes.snackBar} ${
|
||||
modalSnackMessage && modalSnackMessage.type === "error"
|
||||
|
||||
@@ -115,9 +115,10 @@ const UpdateTierCredentialsModal = ({
|
||||
setModalErrorSnackMessage(err);
|
||||
});
|
||||
} else {
|
||||
setModalErrorSnackMessage(
|
||||
"There was an error retrieving tier information"
|
||||
);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "There was an error retrieving tier information",
|
||||
detailedError: "",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ import Storage from "./Storage/Storage";
|
||||
import PodDetails from "./Tenants/TenantDetails/pods/PodDetails";
|
||||
import Metrics from "./Dashboard/Metrics";
|
||||
import Hop from "./Tenants/TenantDetails/hop/Hop";
|
||||
import MainError from "./Common/MainError/MainError";
|
||||
|
||||
const drawerWidth = 245;
|
||||
|
||||
@@ -410,7 +411,9 @@ const Console = ({
|
||||
return;
|
||||
}
|
||||
// Open SnackBar
|
||||
setOpenSnackbar(true);
|
||||
if (snackBarMessage.type !== "error") {
|
||||
setOpenSnackbar(true);
|
||||
}
|
||||
}, [snackBarMessage]);
|
||||
|
||||
const location = useLocation();
|
||||
@@ -474,6 +477,7 @@ const Console = ({
|
||||
value={loadingProgress}
|
||||
/>
|
||||
)}
|
||||
<MainError />
|
||||
<div className={classes.snackDiv}>
|
||||
<Snackbar
|
||||
open={openSnackbar}
|
||||
|
||||
@@ -211,9 +211,11 @@ const PrDashboard = ({
|
||||
const widgetsWithValue = getWidgetsWithValue(res.widgets);
|
||||
setPanelInformation(widgetsWithValue);
|
||||
} else {
|
||||
displayErrorMessage(
|
||||
"Widget information could not be retrieved at this time. Please try again"
|
||||
);
|
||||
displayErrorMessage({
|
||||
errorMessage:
|
||||
"Widget information could not be retrieved at this time. Please try again",
|
||||
detailedError: "",
|
||||
});
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
|
||||
@@ -14,17 +14,16 @@
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useState, useEffect } from "react";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
import { Grid, LinearProgress } from "@material-ui/core";
|
||||
import { Grid } from "@material-ui/core";
|
||||
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
|
||||
import Tab from "@material-ui/core/Tab";
|
||||
import Tabs from "@material-ui/core/Tabs";
|
||||
import { containerForHeader } from "../Common/FormComponents/common/styleLibrary";
|
||||
import ErrorLogs from "./ErrorLogs/ErrorLogs";
|
||||
import LogsSearchMain from "./LogSearch/LogsSearchMain";
|
||||
import api from "../../../common/api";
|
||||
import { AppState } from "../../../store";
|
||||
|
||||
interface ILogsMainProps {
|
||||
|
||||
@@ -152,10 +152,10 @@ const NameTenant = ({
|
||||
});
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.error(err);
|
||||
setModalErrorSnackMessage(
|
||||
"Error validating if namespace already has tenants"
|
||||
);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "Error validating if namespace already has tenants",
|
||||
detailedError: err.detailedError,
|
||||
});
|
||||
});
|
||||
}, [
|
||||
namespace,
|
||||
|
||||
@@ -68,7 +68,10 @@ const DeleteTenant = ({
|
||||
|
||||
const removeRecord = () => {
|
||||
if (retypeTenant !== selectedTenant.name) {
|
||||
setErrorSnackMessage("Tenant name is not correct");
|
||||
setErrorSnackMessage({
|
||||
errorMessage: "Tenant name is incorrect",
|
||||
detailedError: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setDeleteLoading(true);
|
||||
|
||||
@@ -68,7 +68,10 @@ const DeletePod = ({
|
||||
|
||||
const removeRecord = () => {
|
||||
if (retypePod !== selectedPod.name) {
|
||||
setErrorSnackMessage("Tenant name is not correct");
|
||||
setErrorSnackMessage({
|
||||
errorMessage: "Tenant name is incorrect",
|
||||
detailedError: "",
|
||||
});
|
||||
return;
|
||||
}
|
||||
setDeleteLoading(true);
|
||||
|
||||
@@ -99,7 +99,10 @@ const PodsSummary = ({ match, history, loadingTenant }: IPodsSummary) => {
|
||||
setLoadingPods(false);
|
||||
})
|
||||
.catch((err) => {
|
||||
setErrorSnackMessage("Error loading pods");
|
||||
setErrorSnackMessage({
|
||||
errorMessage: "Error loading pods",
|
||||
detailedError: err.detailedError,
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [loadingPods, tenantName, tenantNamespace]);
|
||||
|
||||
@@ -99,7 +99,10 @@ const AddUser = ({
|
||||
event.preventDefault();
|
||||
|
||||
if (secretKey.length < 8) {
|
||||
setModalErrorSnackMessage("Passwords must be at least 8 characters long");
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "Passwords must be at least 8 characters long",
|
||||
detailedError: "",
|
||||
});
|
||||
setAddLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -79,9 +79,10 @@ const BulkAddToGroup = ({
|
||||
});
|
||||
} else {
|
||||
isSaving(false);
|
||||
setModalErrorSnackMessage(
|
||||
"You need to select at least one group to assign"
|
||||
);
|
||||
setModalErrorSnackMessage({
|
||||
errorMessage: "You need to select at least one group to assign",
|
||||
detailedError: "",
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
|
||||
import { ErrorResponseHandler } from "./common/types";
|
||||
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
export interface snackBarMessage {
|
||||
message: string;
|
||||
detailedErrorMsg?: string;
|
||||
detailedErrorMsg: string;
|
||||
type: "message" | "error";
|
||||
}
|
||||
|
||||
@@ -88,7 +91,7 @@ interface SetSnackBarMessage {
|
||||
|
||||
interface SetErrorSnackMessage {
|
||||
type: typeof SET_ERROR_SNACK_MESSAGE;
|
||||
message: string;
|
||||
message: ErrorResponseHandler;
|
||||
}
|
||||
|
||||
interface SetModalSnackMessage {
|
||||
@@ -98,7 +101,7 @@ interface SetModalSnackMessage {
|
||||
|
||||
interface SetModalErrorMessage {
|
||||
type: typeof SET_MODAL_ERROR_MESSAGE;
|
||||
message: string;
|
||||
message: ErrorResponseHandler;
|
||||
}
|
||||
|
||||
interface SetDistributedSetup {
|
||||
|
||||
Reference in New Issue
Block a user