pbca26
8 years ago
committed by
GitHub
6 changed files with 152 additions and 70 deletions
@ -0,0 +1,79 @@ |
|||||
|
import React from "react"; |
||||
|
import {dismissToasterMessage} from "../../actions/actionCreators"; |
||||
|
import Store from "../../store"; |
||||
|
|
||||
|
// each toast will be displayed for 5 seconds
|
||||
|
const DISPLAY_LENGTH_MILLIS = 5000; |
||||
|
|
||||
|
/** |
||||
|
* Displays one toast message |
||||
|
* each messages has a type, title and a content message |
||||
|
*/ |
||||
|
class ToasterItem extends React.Component { |
||||
|
|
||||
|
constructor(props) { |
||||
|
super(props); |
||||
|
this.state = { |
||||
|
display: false, |
||||
|
message: null, |
||||
|
type: null, |
||||
|
title: null |
||||
|
}; |
||||
|
|
||||
|
this.dismissToast = this.dismissToast.bind(this); |
||||
|
|
||||
|
this.timeoutHandler = null; |
||||
|
} |
||||
|
|
||||
|
componentWillReceiveProps(props) { |
||||
|
if (props && |
||||
|
props.message && |
||||
|
props.display) { |
||||
|
this.setState({ |
||||
|
message: props.message, |
||||
|
display: props.display, |
||||
|
type: props._type, |
||||
|
title: props.title, |
||||
|
toastId: props.toastId |
||||
|
}); |
||||
|
} else { |
||||
|
this.setState({ |
||||
|
display: false, |
||||
|
message: null, |
||||
|
type: null, |
||||
|
title: null, |
||||
|
toastId: null |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
dismissToast(toastId) { |
||||
|
Store.dispatch(dismissToasterMessage(toastId)); |
||||
|
} |
||||
|
|
||||
|
renderToast() { |
||||
|
// ensure that setTimeout is called only once for each toast message
|
||||
|
if (!this.timeoutHandler) { |
||||
|
this.timeoutHandler = setTimeout(() => { |
||||
|
this.dismissToast(this.state.toastId); |
||||
|
}, DISPLAY_LENGTH_MILLIS); |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<div className={ 'toast toast-' + this.state.type }> |
||||
|
<button className="toast-close-button" role="button" |
||||
|
onClick={ () => this.dismissToast(this.state.toastId) }>× |
||||
|
</button> |
||||
|
<div className="toast-title">{ this.state.title }</div> |
||||
|
<div className="toast-message">{ this.state.message }</div> |
||||
|
</div> |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
render() { |
||||
|
return (this.state.message && this.state.display) ? |
||||
|
this.renderToast() : null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default ToasterItem; |
@ -1,69 +1,59 @@ |
|||||
import React from 'react'; |
import React from "react"; |
||||
import { dismissToasterMessage } from '../../actions/actionCreators'; |
import {dismissToasterMessage} from "../../actions/actionCreators"; |
||||
import Store from '../../store'; |
import Store from "../../store"; |
||||
|
import ToasterItem from "./toaster-item"; |
||||
|
|
||||
|
/** |
||||
|
* Container component used for creating multiple toasts |
||||
|
*/ |
||||
class Toaster extends React.Component { |
class Toaster extends React.Component { |
||||
constructor(props) { |
constructor(props) { |
||||
super(props); |
super(props); |
||||
this.state = { |
this.state = { |
||||
display: false, |
toasts: [] |
||||
message: null, |
|
||||
type: null, |
|
||||
title: null, |
|
||||
}; |
}; |
||||
this.dismissToast = this.dismissToast.bind(this); |
this.toastId = 0; |
||||
} |
} |
||||
|
|
||||
componentWillReceiveProps(props) { |
componentWillReceiveProps(props) { |
||||
if (props && |
if (props && |
||||
props.message && |
props.toasts) { |
||||
props.display) { |
|
||||
this.setState({ |
this.setState({ |
||||
message: props.message, |
toasts: props.toasts, |
||||
display: props.display, |
toastId: props.toasts.length |
||||
type: props.type, |
|
||||
title: props.title, |
|
||||
}); |
}); |
||||
} else { |
} else { |
||||
this.setState({ |
this.setState({ |
||||
display: false, |
toasts: [], |
||||
message: null, |
toastId: 0 |
||||
type: null, |
|
||||
title: null, |
|
||||
}); |
}); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
dismissToast() { |
dismissToast(toastId) { |
||||
Store.dispatch(dismissToasterMessage()); |
Store.dispatch(dismissToasterMessage(toastId)); |
||||
} |
} |
||||
|
|
||||
// TODO: multiple toasts
|
// render all current toasts
|
||||
renderToast() { |
render() { |
||||
setTimeout(() => { |
|
||||
Store.dispatch(dismissToasterMessage()); |
|
||||
}, 5000); |
|
||||
|
|
||||
return ( |
return ( |
||||
<div className="toaster"> |
<div id="toast-container" |
||||
<div |
|
||||
id="toast-container" |
|
||||
className="single-toast toast-bottom-right" |
className="single-toast toast-bottom-right" |
||||
aria-live="polite" |
aria-live="polite" |
||||
role="alert"> |
role="alert"> |
||||
<div className={ 'toast toast-' + this.state.type }> |
{this.state.toasts |
||||
<button className="toast-close-button" role="button" onClick={ this.dismissToast }>×</button> |
.map((toast) => { |
||||
<div className="toast-title">{ this.state.title }</div> |
// sets the toastId for all new toasts
|
||||
<div className="toast-message">{ this.state.message }</div> |
if (!toast.toastId) { |
||||
</div> |
toast.toastId = this.toastId++; |
||||
</div> |
|
||||
</div> |
|
||||
); |
|
||||
} |
} |
||||
|
|
||||
render() { |
return ( |
||||
return (this.state.message && this.state.display) ? |
<ToasterItem key={toast.toastId} {...toast} /> |
||||
this.renderToast() : null; |
); |
||||
|
})} |
||||
|
</div> |
||||
|
); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
|
Loading…
Reference in new issue