mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-22 17:23:54 +01:00
Toast notifications.
This commit is contained in:
parent
2837251db7
commit
aec012fb79
1
assets/times.svg
Normal file
1
assets/times.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path d="M207.6 256l107.72-107.72c6.23-6.23 6.23-16.34 0-22.58l-25.03-25.03c-6.23-6.23-16.34-6.23-22.58 0L160 208.4 52.28 100.68c-6.23-6.23-16.34-6.23-22.58 0L4.68 125.7c-6.23 6.23-6.23 16.34 0 22.58L112.4 256 4.68 363.72c-6.23 6.23-6.23 16.34 0 22.58l25.03 25.03c6.23 6.23 16.34 6.23 22.58 0L160 303.6l107.72 107.72c6.23 6.23 16.34 6.23 22.58 0l25.03-25.03c6.23-6.23 6.23-16.34 0-22.58L207.6 256z"/></svg>
|
After Width: | Height: | Size: 468 B |
26
components/common/Toast.js
Normal file
26
components/common/Toast.js
Normal file
@ -0,0 +1,26 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { useSpring, animated } from 'react-spring';
|
||||
import styles from './Toast.module.css';
|
||||
import Icon from 'components/common/Icon';
|
||||
import Close from 'assets/times.svg';
|
||||
|
||||
export default function Toast({ message, timeout = 3000, onClose }) {
|
||||
const props = useSpring({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0,0px,0)',
|
||||
from: { opacity: 0, transform: 'translate3d(0,-40px,0)' },
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(onClose, timeout);
|
||||
}, []);
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<animated.div className={styles.toast} style={props} onClick={onClose}>
|
||||
<div className={styles.message}>{message}</div>
|
||||
<Icon className={styles.close} icon={<Close />} size="small" />
|
||||
</animated.div>,
|
||||
document.getElementById('__modals'),
|
||||
);
|
||||
}
|
25
components/common/Toast.module.css
Normal file
25
components/common/Toast.module.css
Normal file
@ -0,0 +1,25 @@
|
||||
.toast {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 300px;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 8px 16px;
|
||||
color: var(--gray50);
|
||||
background: var(--green400);
|
||||
margin: auto;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: var(--font-size-normal);
|
||||
}
|
||||
|
||||
.close {
|
||||
margin-left: 20px;
|
||||
}
|
@ -14,12 +14,14 @@ import Plus from 'assets/plus.svg';
|
||||
import Trash from 'assets/trash.svg';
|
||||
import Check from 'assets/check.svg';
|
||||
import styles from './AccountSettings.module.css';
|
||||
import Toast from '../common/Toast';
|
||||
|
||||
export default function AccountSettings() {
|
||||
const [addAccount, setAddAccount] = useState();
|
||||
const [editAccount, setEditAccount] = useState();
|
||||
const [deleteAccount, setDeleteAccount] = useState();
|
||||
const [saved, setSaved] = useState(0);
|
||||
const [message, setMessage] = useState();
|
||||
const { data } = useFetch(`/api/accounts`, {}, { update: [saved] });
|
||||
|
||||
const Checkmark = ({ is_admin }) => (is_admin ? <Icon icon={<Check />} size="medium" /> : null);
|
||||
@ -52,6 +54,7 @@ export default function AccountSettings() {
|
||||
|
||||
function handleSave() {
|
||||
setSaved(state => state + 1);
|
||||
setMessage('Saved successfully.');
|
||||
handleClose();
|
||||
}
|
||||
|
||||
@ -97,6 +100,7 @@ export default function AccountSettings() {
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{message && <Toast message={message} onClose={() => setMessage(null)} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -5,12 +5,19 @@ import Button from 'components/common/Button';
|
||||
import ChangePasswordForm from '../forms/ChangePasswordForm';
|
||||
import Modal from 'components/common/Modal';
|
||||
import Dots from 'assets/ellipsis-h.svg';
|
||||
import Toast from '../common/Toast';
|
||||
|
||||
export default function ProfileSettings() {
|
||||
const user = useSelector(state => state.user);
|
||||
const [changePassword, setChangePassword] = useState(false);
|
||||
const [message, setMessage] = useState();
|
||||
const { user_id } = user;
|
||||
|
||||
function handleSave() {
|
||||
setChangePassword(false);
|
||||
setMessage('Saved successfully.');
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader>
|
||||
@ -27,11 +34,12 @@ export default function ProfileSettings() {
|
||||
<Modal title="Change password">
|
||||
<ChangePasswordForm
|
||||
values={{ user_id }}
|
||||
onSave={() => setChangePassword(false)}
|
||||
onSave={handleSave}
|
||||
onClose={() => setChangePassword(false)}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{message && <Toast message={message} onClose={() => setMessage(null)} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import Code from 'assets/code.svg';
|
||||
import Link from 'assets/link.svg';
|
||||
import styles from './WebsiteSettings.module.css';
|
||||
import useFetch from '../../hooks/useFetch';
|
||||
import Toast from '../common/Toast';
|
||||
|
||||
export default function WebsiteSettings() {
|
||||
const [editWebsite, setEditWebsite] = useState();
|
||||
@ -25,6 +26,7 @@ export default function WebsiteSettings() {
|
||||
const [showCode, setShowCode] = useState();
|
||||
const [showUrl, setShowUrl] = useState();
|
||||
const [saved, setSaved] = useState(0);
|
||||
const [message, setMessage] = useState();
|
||||
const { data } = useFetch(`/api/websites`, {}, { update: [saved] });
|
||||
|
||||
const Buttons = row => (
|
||||
@ -66,6 +68,7 @@ export default function WebsiteSettings() {
|
||||
|
||||
function handleSave() {
|
||||
setSaved(state => state + 1);
|
||||
setMessage('Saved successfully.');
|
||||
handleClose();
|
||||
}
|
||||
|
||||
@ -127,6 +130,7 @@ export default function WebsiteSettings() {
|
||||
<ShareUrlForm values={showUrl} onClose={handleClose} />
|
||||
</Modal>
|
||||
)}
|
||||
{message && <Toast message={message} onClose={() => setMessage(null)} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user