-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate "time ago" components to React (#3385)
* Replace <am-time-ago> (angular-moment) and <rd-timer> with React component * PropTypes: Moment validation * Increase polling interval * Refine component implementation * Add tooltip with formatted date/time * Refine component implementation
- Loading branch information
1 parent
324a1f5
commit 807e6aa
Showing
10 changed files
with
146 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import moment from 'moment'; | ||
import { isNil } from 'lodash'; | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import PropTypes from 'prop-types'; | ||
import { Moment } from '@/components/proptypes'; | ||
import { clientConfig } from '@/services/auth'; | ||
|
||
const autoUpdateList = new Set(); | ||
|
||
function updateComponents() { | ||
autoUpdateList.forEach(component => component.update()); | ||
setTimeout(updateComponents, 30 * 1000); | ||
} | ||
updateComponents(); | ||
|
||
export class TimeAgo extends React.PureComponent { | ||
static propTypes = { | ||
// `date` and `placeholder` used in `getDerivedStateFromProps` | ||
// eslint-disable-next-line react/no-unused-prop-types | ||
date: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.number, | ||
PropTypes.instanceOf(Date), | ||
Moment, | ||
]), | ||
// eslint-disable-next-line react/no-unused-prop-types | ||
placeholder: PropTypes.string, | ||
autoUpdate: PropTypes.bool, | ||
}; | ||
|
||
static defaultProps = { | ||
date: null, | ||
placeholder: '', | ||
autoUpdate: true, | ||
}; | ||
|
||
static getDerivedStateFromProps({ date, placeholder }) { | ||
// if `date` prop is not empty and a valid date/time - convert it to `moment` | ||
date = !isNil(date) ? moment(date) : null; | ||
date = date && date.isValid() ? date : null; | ||
|
||
return { | ||
value: date ? date.fromNow() : placeholder, | ||
title: date ? date.format(clientConfig.dateTimeFormat) : '', | ||
}; | ||
} | ||
|
||
// Initial state, to get rid of React warning | ||
state = { | ||
title: null, | ||
value: null, | ||
}; | ||
|
||
componentDidMount() { | ||
autoUpdateList.add(this); | ||
this.update(true); | ||
} | ||
|
||
componentWillUnmount() { | ||
autoUpdateList.delete(this); | ||
} | ||
|
||
update(force = false) { | ||
if (force || this.props.autoUpdate) { | ||
this.setState(this.constructor.getDerivedStateFromProps(this.props)); | ||
} | ||
} | ||
|
||
render() { | ||
return <span title={this.state.title}>{this.state.value}</span>; | ||
} | ||
} | ||
|
||
export default function init(ngModule) { | ||
ngModule.directive('amTimeAgo', () => ({ | ||
link($scope, element, attr) { | ||
const modelName = attr.amTimeAgo; | ||
$scope.$watch(modelName, (value) => { | ||
ReactDOM.render(<TimeAgo date={value} />, element[0]); | ||
}); | ||
}, | ||
})); | ||
|
||
ngModule.component('rdTimeAgo', { | ||
bindings: { | ||
value: '=', | ||
}, | ||
controller($scope, $element) { | ||
$scope.$watch('$ctrl.value', () => { | ||
// Initial render will occur here as well | ||
ReactDOM.render(<TimeAgo date={this.value} placeholder="-" />, $element[0]); | ||
}); | ||
}, | ||
}); | ||
} | ||
|
||
init.init = true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.