Webclient: Add Toasts component and show on known host CUD operations (#4556)
* Add Toasts component and show on known host CUD operations * add slide transition * NIT Co-authored-by: Brent Clark <brent@backboneiq.com>
This commit is contained in:
parent
8203a2fdeb
commit
81d031ca0f
5 changed files with 91 additions and 4 deletions
12
webclient/package-lock.json
generated
12
webclient/package-lock.json
generated
|
@ -22784,6 +22784,18 @@
|
||||||
"@babel/runtime": "^7.4.4"
|
"@babel/runtime": "^7.4.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@material-ui/lab": {
|
||||||
|
"version": "4.0.0-alpha.60",
|
||||||
|
"resolved": "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.60.tgz",
|
||||||
|
"integrity": "sha512-fadlYsPJF+0fx2lRuyqAuJj7hAS1tLDdIEEdov5jlrpb5pp4b+mRDUqQTUxi4inRZHS1bEXpU8QWUhO6xX88aA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.4.4",
|
||||||
|
"@material-ui/utils": "^4.11.2",
|
||||||
|
"clsx": "^1.0.4",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-is": "^16.8.0 || ^17.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@material-ui/styles": {
|
"@material-ui/styles": {
|
||||||
"version": "4.11.4",
|
"version": "4.11.4",
|
||||||
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@material-ui/core": "^4.12.3",
|
"@material-ui/core": "^4.12.3",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||||
"@material-ui/styles": "^4.11.4",
|
"@material-ui/styles": "^4.11.4",
|
||||||
"@testing-library/jest-dom": "^5.16.1",
|
"@testing-library/jest-dom": "^5.16.1",
|
||||||
"@testing-library/react": "^12.1.2",
|
"@testing-library/react": "^12.1.2",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// eslint-disable-next-line
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import React, { useCallback, useEffect, useState } from 'react';
|
|
||||||
import { Select, MenuItem } from '@material-ui/core';
|
import { Select, MenuItem } from '@material-ui/core';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import FormControl from '@material-ui/core/FormControl';
|
import FormControl from '@material-ui/core/FormControl';
|
||||||
|
@ -14,6 +13,7 @@ import ErrorOutlinedIcon from '@material-ui/icons/ErrorOutlined';
|
||||||
import { KnownHostDialog } from 'dialogs';
|
import { KnownHostDialog } from 'dialogs';
|
||||||
import { HostDTO } from 'services';
|
import { HostDTO } from 'services';
|
||||||
import { DefaultHosts, Host, getHostPort } from 'types';
|
import { DefaultHosts, Host, getHostPort } from 'types';
|
||||||
|
import Toast from 'components/Toast/Toast';
|
||||||
|
|
||||||
import './KnownHosts.css';
|
import './KnownHosts.css';
|
||||||
|
|
||||||
|
@ -44,6 +44,10 @@ const KnownHosts = (props) => {
|
||||||
edit: null,
|
edit: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [showCreateToast, setShowCreateToast] = useState(false)
|
||||||
|
const [showDeleteToast, setShowDeleteToast] = useState(false)
|
||||||
|
const [showEditToast, setShowEditToast] = useState(false)
|
||||||
|
|
||||||
const loadKnownHosts = useCallback(async () => {
|
const loadKnownHosts = useCallback(async () => {
|
||||||
const hosts = await HostDTO.getAll();
|
const hosts = await HostDTO.getAll();
|
||||||
|
|
||||||
|
@ -96,6 +100,7 @@ const KnownHosts = (props) => {
|
||||||
|
|
||||||
closeKnownHostDialog();
|
closeKnownHostDialog();
|
||||||
HostDTO.delete(id);
|
HostDTO.delete(id);
|
||||||
|
setShowDeleteToast(true)
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDialogSubmit = async ({ id, name, host, port }) => {
|
const handleDialogSubmit = async ({ id, name, host, port }) => {
|
||||||
|
@ -111,6 +116,7 @@ const KnownHosts = (props) => {
|
||||||
hosts: s.hosts.map(h => h.id === id ? hostDTO : h),
|
hosts: s.hosts.map(h => h.id === id ? hostDTO : h),
|
||||||
selectedHost: hostDTO
|
selectedHost: hostDTO
|
||||||
}));
|
}));
|
||||||
|
setShowEditToast(true)
|
||||||
} else {
|
} else {
|
||||||
const newHost: Host = { name, host, port, editable: true };
|
const newHost: Host = { name, host, port, editable: true };
|
||||||
newHost.id = await HostDTO.add(newHost) as number;
|
newHost.id = await HostDTO.add(newHost) as number;
|
||||||
|
@ -120,6 +126,7 @@ const KnownHosts = (props) => {
|
||||||
hosts: [...s.hosts, newHost],
|
hosts: [...s.hosts, newHost],
|
||||||
selectedHost: newHost,
|
selectedHost: newHost,
|
||||||
}));
|
}));
|
||||||
|
setShowCreateToast(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
closeKnownHostDialog();
|
closeKnownHostDialog();
|
||||||
|
@ -206,6 +213,9 @@ const KnownHosts = (props) => {
|
||||||
onSubmit={handleDialogSubmit}
|
onSubmit={handleDialogSubmit}
|
||||||
handleClose={closeKnownHostDialog}
|
handleClose={closeKnownHostDialog}
|
||||||
/>
|
/>
|
||||||
|
<Toast open={showCreateToast} onClose={() => setShowCreateToast(false)}>Host successfully created.</Toast>
|
||||||
|
<Toast open={showDeleteToast} onClose={() => setShowDeleteToast(false)}>Host successfully deleted.</Toast>
|
||||||
|
<Toast open={showEditToast} onClose={() => setShowEditToast(false)}>Host successfully edited.</Toast>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
65
webclient/src/components/Toast/Toast.tsx
Normal file
65
webclient/src/components/Toast/Toast.tsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
|
import Alert, { AlertProps } from '@material-ui/lab/Alert';
|
||||||
|
import CheckCircleIcon from '@material-ui/icons/CheckCircle';
|
||||||
|
import Slide, { SlideProps } from '@material-ui/core/Slide';
|
||||||
|
import Snackbar from '@material-ui/core/Snackbar';
|
||||||
|
|
||||||
|
const iconMapping = {
|
||||||
|
success: <CheckCircleIcon />
|
||||||
|
}
|
||||||
|
|
||||||
|
function Toast(props) {
|
||||||
|
const { open, onClose, severity, autoHideDuration, children } = props
|
||||||
|
|
||||||
|
const rootElemRef = React.useRef(document.createElement('div'));
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
document.body.appendChild(rootElemRef.current)
|
||||||
|
return () => {
|
||||||
|
rootElemRef.current.remove();
|
||||||
|
}
|
||||||
|
}, [rootElemRef])
|
||||||
|
|
||||||
|
const handleClose = (event?: React.SyntheticEvent, reason?: string) => {
|
||||||
|
if (reason === 'clickaway') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onClose(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
const node = (
|
||||||
|
<Snackbar
|
||||||
|
open={open}
|
||||||
|
autoHideDuration={autoHideDuration}
|
||||||
|
onClose={handleClose}
|
||||||
|
TransitionComponent={TransitionLeft}
|
||||||
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
|
||||||
|
>
|
||||||
|
<Alert onClose={handleClose} severity={severity} iconMapping={iconMapping}>
|
||||||
|
{children}
|
||||||
|
</Alert>
|
||||||
|
</Snackbar>
|
||||||
|
)
|
||||||
|
if (!rootElemRef.current) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return ReactDOM.createPortal(
|
||||||
|
node,
|
||||||
|
rootElemRef.current
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.defaultProps = {
|
||||||
|
severity: 'success',
|
||||||
|
// 10s wait before automatically dismissing the Toast.
|
||||||
|
autoHideDuration: 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
function TransitionLeft(props) {
|
||||||
|
return <Slide {...props} direction="left" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Toast
|
|
@ -1,5 +1,4 @@
|
||||||
// eslint-disable-next-line
|
import { useState, useCallback } from 'react';
|
||||||
import React, { useState, useCallback } from "react";
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Redirect } from 'react-router-dom';
|
import { Redirect } from 'react-router-dom';
|
||||||
import { makeStyles } from '@material-ui/core/styles';
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
Loading…
Reference in a new issue