mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-12 04:12:16 +00:00
add toast (#2428)
This commit is contained in:
parent
237455f1a8
commit
a2cc17778c
3
frontend/src/components/toast/index.js
Normal file
3
frontend/src/components/toast/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import Toast from './toast'
|
||||||
|
|
||||||
|
export default Toast;
|
67
frontend/src/components/toast/notice-container.js
Normal file
67
frontend/src/components/toast/notice-container.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
||||||
|
import Notice from './notice';
|
||||||
|
|
||||||
|
class NoticeContainer extends React.Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.transitionTime = 300;
|
||||||
|
this.state = {notices: []}
|
||||||
|
}
|
||||||
|
|
||||||
|
addNotice = (notice) => {
|
||||||
|
const { notices } = this.state;
|
||||||
|
notice.key = this.getNoticeKey();
|
||||||
|
notices.push(notice);
|
||||||
|
this.setState({notices});
|
||||||
|
|
||||||
|
if (notice.duration > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.removeNotice(notice.key);
|
||||||
|
}, notice.duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeNotice = (key) => {
|
||||||
|
const { notices } = this.state;
|
||||||
|
this.setState({
|
||||||
|
notices: notices.filter((notice) => {
|
||||||
|
if (notice.key === key) {
|
||||||
|
if (notice.close) {
|
||||||
|
setTimeout(notice.close, this.transitionTime);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getNoticeKey = () => {
|
||||||
|
const { notices } = this.state;
|
||||||
|
return `notice-${new Date().getTime()}-${notices.length}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { notices } = this.state;
|
||||||
|
return (
|
||||||
|
<TransitionGroup className="toast-notification">
|
||||||
|
{notices.map((notice) => {
|
||||||
|
return (
|
||||||
|
<CSSTransition
|
||||||
|
key={notice.key}
|
||||||
|
classNames="toast-notice-wrapper notice"
|
||||||
|
timeout={this.transitionTime}
|
||||||
|
>
|
||||||
|
<Notice key={notice.key} {...notice} />
|
||||||
|
</CSSTransition>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TransitionGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoticeContainer;
|
22
frontend/src/components/toast/notice.js
Normal file
22
frontend/src/components/toast/notice.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
type: PropTypes.string.isRequired,
|
||||||
|
content: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Notice extends React.Component {
|
||||||
|
render() {
|
||||||
|
let { type, content } = this.props;
|
||||||
|
return (
|
||||||
|
<div className="toast-notice">
|
||||||
|
<span className={`alert alert-${type}`}>{content}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Notice.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default Notice;
|
49
frontend/src/components/toast/toast.css
Normal file
49
frontend/src/components/toast/toast.css
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
.toast-notification {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice-wrapper.notice-enter {
|
||||||
|
top: 0px;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice-wrapper.notice-enter-active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0.9125rem);
|
||||||
|
transition: all 300ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice-wrapper.notice-exit {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice-wrapper.notice-exit-active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-100%);
|
||||||
|
transition: all 300ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice {
|
||||||
|
position: relative;
|
||||||
|
top: 0.9125rem;
|
||||||
|
margin:0 auto 0.9125rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, .1);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: #454545;
|
||||||
|
font-size: 0.9125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast-notice>span {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.3125rem;
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
40
frontend/src/components/toast/toast.js
Normal file
40
frontend/src/components/toast/toast.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import NoticeContainer from './notice-container';
|
||||||
|
import './toast.css';
|
||||||
|
|
||||||
|
function createNotieContainer() {
|
||||||
|
const div = document.createElement('div')
|
||||||
|
document.body.appendChild(div)
|
||||||
|
const noticeContainer = ReactDOM.render(<NoticeContainer />, div)
|
||||||
|
return {
|
||||||
|
addNotice(notice) {
|
||||||
|
return noticeContainer.addNotice(notice)
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
ReactDOM.unmountComponentAtNode(div)
|
||||||
|
document.body.removeChild(div)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let noticeContainer
|
||||||
|
const notice = (type, content, duration = 2000, onClose) => {
|
||||||
|
if (!noticeContainer) noticeContainer = createNotieContainer()
|
||||||
|
return noticeContainer.addNotice({ type, content, duration, onClose })
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
info(content, duration, onClose) {
|
||||||
|
return notice('info', content, duration, onClose)
|
||||||
|
},
|
||||||
|
success(content, duration, onClose) {
|
||||||
|
return notice('success', content, duration, onClose)
|
||||||
|
},
|
||||||
|
warning(content, duration, onClose) {
|
||||||
|
return notice('warning', content, duration, onClose)
|
||||||
|
},
|
||||||
|
error(content, duration, onClose) {
|
||||||
|
return notice('danger', content, duration, onClose)
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { gettext } from '../../components/constants';
|
import { gettext } from '../../components/constants';
|
||||||
import editUtilties from '../../utils/editor-utilties';
|
import editUtilties from '../../utils/editor-utilties';
|
||||||
|
import Toast from '../../components/toast/';
|
||||||
import Loading from '../../components/loading';
|
import Loading from '../../components/loading';
|
||||||
import DraftListView from '../../components/draft-list-view/draft-list-view';
|
import DraftListView from '../../components/draft-list-view/draft-list-view';
|
||||||
import DraftListMenu from '../../components/draft-list-view/draft-list-menu';
|
import DraftListMenu from '../../components/draft-list-view/draft-list-menu';
|
||||||
@ -42,6 +43,9 @@ class DraftsView extends React.Component {
|
|||||||
let draft = this.state.currentDraft;
|
let draft = this.state.currentDraft;
|
||||||
editUtilties.deleteDraft(draft.id).then(res => {
|
editUtilties.deleteDraft(draft.id).then(res => {
|
||||||
this.initDraftList();
|
this.initDraftList();
|
||||||
|
Toast.success(gettext('Delete draft succeeded.'));
|
||||||
|
}).catch(() => {
|
||||||
|
Toast.error(gettext('Delete draft failed.'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +53,9 @@ class DraftsView extends React.Component {
|
|||||||
let draft = this.state.currentDraft;
|
let draft = this.state.currentDraft;
|
||||||
editUtilties.publishDraft(draft.id).then(res => {
|
editUtilties.publishDraft(draft.id).then(res => {
|
||||||
this.initDraftList();
|
this.initDraftList();
|
||||||
|
Toast.success(gettext('Publish draft succeeded.'));
|
||||||
|
}).catch(() => {
|
||||||
|
Toast.error(gettext('Publish draft failed.'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user