Convert Notifications components to TypeScript
parent
47f7d4b312
commit
7175d37b7e
|
@ -1,17 +1,32 @@
|
|||
import React, {Component} from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {Notification as NotificationType} from 'src/types/notifications'
|
||||
|
||||
import classnames from 'classnames'
|
||||
|
||||
import {dismissNotification as dismissNotificationAction} from 'shared/actions/notifications'
|
||||
import {dismissNotification as dismissNotificationAction} from 'src/shared/actions/notifications'
|
||||
|
||||
import {NOTIFICATION_TRANSITION} from 'shared/constants/index'
|
||||
import {NOTIFICATION_TRANSITION} from 'src/shared/constants/index'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
interface Props {
|
||||
notification: NotificationType
|
||||
dismissNotification: (id: string) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
opacity: number
|
||||
height: number
|
||||
dismissed: boolean
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class Notification extends Component {
|
||||
class Notification extends Component<Props, State> {
|
||||
private notificationRef: HTMLElement
|
||||
private dismissalTimer: number
|
||||
private deletionTimer: number
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
@ -22,7 +37,7 @@ class Notification extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
public componentDidMount() {
|
||||
const {
|
||||
notification: {duration},
|
||||
} = this.props
|
||||
|
@ -31,41 +46,16 @@ class Notification extends Component {
|
|||
|
||||
if (duration >= 0) {
|
||||
// Automatically dismiss notification after duration prop
|
||||
this.dismissTimer = setTimeout(this.handleDismiss, duration)
|
||||
this.dismissalTimer = window.setTimeout(this.handleDismiss, duration)
|
||||
}
|
||||
}
|
||||
|
||||
updateHeight() {
|
||||
if (this.notificationRef) {
|
||||
const {height} = this.notificationRef.getBoundingClientRect()
|
||||
this.setState({height})
|
||||
}
|
||||
public componentWillUnmount() {
|
||||
clearTimeout(this.dismissalTimer)
|
||||
clearTimeout(this.deletionTimer)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.dismissTimer)
|
||||
clearTimeout(this.deleteTimer)
|
||||
}
|
||||
|
||||
handleDismiss = () => {
|
||||
const {
|
||||
notification: {id},
|
||||
dismissNotification,
|
||||
} = this.props
|
||||
|
||||
this.setState({dismissed: true})
|
||||
this.deleteTimer = setTimeout(
|
||||
() => dismissNotification(id),
|
||||
NOTIFICATION_TRANSITION
|
||||
)
|
||||
}
|
||||
|
||||
onNotificationRef = ref => {
|
||||
this.notificationRef = ref
|
||||
this.updateHeight()
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const {
|
||||
notification: {type, message, icon},
|
||||
} = this.props
|
||||
|
@ -81,7 +71,7 @@ class Notification extends Component {
|
|||
|
||||
return (
|
||||
<div className={notificationContainerClass} style={style}>
|
||||
<div className={notificationClass} ref={this.onNotificationRef}>
|
||||
<div className={notificationClass} ref={this.handleNotificationRef}>
|
||||
<span className={`icon ${icon}`} />
|
||||
<div className="notification-message">{message}</div>
|
||||
<button className="notification-close" onClick={this.handleDismiss} />
|
||||
|
@ -89,19 +79,31 @@ class Notification extends Component {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {func, number, shape, string} = PropTypes
|
||||
private updateHeight = (): void => {
|
||||
if (this.notificationRef) {
|
||||
const {height} = this.notificationRef.getBoundingClientRect()
|
||||
this.setState({height})
|
||||
}
|
||||
}
|
||||
|
||||
Notification.propTypes = {
|
||||
notification: shape({
|
||||
id: string.isRequired,
|
||||
type: string.isRequired,
|
||||
message: string.isRequired,
|
||||
duration: number.isRequired,
|
||||
icon: string.isRequired,
|
||||
}).isRequired,
|
||||
dismissNotification: func.isRequired,
|
||||
private handleDismiss = (): void => {
|
||||
const {
|
||||
notification: {id},
|
||||
dismissNotification,
|
||||
} = this.props
|
||||
|
||||
this.setState({dismissed: true})
|
||||
this.deletionTimer = window.setTimeout(
|
||||
() => dismissNotification(id),
|
||||
NOTIFICATION_TRANSITION
|
||||
)
|
||||
}
|
||||
|
||||
private handleNotificationRef = (ref: HTMLElement): void => {
|
||||
this.notificationRef = ref
|
||||
this.updateHeight()
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
|
@ -1,44 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import Notification from 'shared/components/Notification'
|
||||
|
||||
const Notifications = ({notifications, inPresentationMode}) => (
|
||||
<div
|
||||
className={`${
|
||||
inPresentationMode
|
||||
? 'notification-center__presentation-mode'
|
||||
: 'notification-center'
|
||||
}`}
|
||||
>
|
||||
{notifications.map(n => <Notification key={n.id} notification={n} />)}
|
||||
</div>
|
||||
)
|
||||
|
||||
const {arrayOf, bool, number, shape, string} = PropTypes
|
||||
|
||||
Notifications.propTypes = {
|
||||
notifications: arrayOf(
|
||||
shape({
|
||||
id: string.isRequired,
|
||||
type: string.isRequired,
|
||||
message: string.isRequired,
|
||||
duration: number.isRequired,
|
||||
icon: string,
|
||||
})
|
||||
),
|
||||
inPresentationMode: bool,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
notifications,
|
||||
app: {
|
||||
ephemeral: {inPresentationMode},
|
||||
},
|
||||
}) => ({
|
||||
notifications,
|
||||
inPresentationMode,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(Notifications)
|
|
@ -0,0 +1,47 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {Notification as NotificationType} from 'src/types/notifications'
|
||||
import Notification from 'src/shared/components/Notification'
|
||||
|
||||
interface Props {
|
||||
inPresentationMode?: boolean
|
||||
notifications: NotificationType[]
|
||||
}
|
||||
|
||||
class Notifications extends PureComponent<Props> {
|
||||
public static defaultProps: Partial<Props> = {
|
||||
inPresentationMode: false,
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {notifications} = this.props
|
||||
|
||||
return (
|
||||
<div className={this.className}>
|
||||
{notifications.map(n => <Notification key={n.id} notification={n} />)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get className(): string {
|
||||
const {inPresentationMode} = this.props
|
||||
|
||||
if (inPresentationMode) {
|
||||
return 'notification-center__presentation-mode'
|
||||
}
|
||||
|
||||
return 'notification-center'
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
notifications,
|
||||
app: {
|
||||
ephemeral: {inPresentationMode},
|
||||
},
|
||||
}) => ({
|
||||
notifications,
|
||||
inPresentationMode,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(Notifications)
|
Loading…
Reference in New Issue