You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MeetingList.native.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // @flow
  2. import React, { Component } from 'react';
  3. import { connect } from 'react-redux';
  4. import { refreshCalendarEntryList } from '../actions';
  5. import { appNavigate } from '../../app';
  6. import { translate } from '../../base/i18n';
  7. import { NavigateSectionList } from '../../base/react';
  8. import { getLocalizedDateFormatter } from '../../base/util';
  9. type Props = {
  10. /**
  11. * Indicates if the list is disabled or not.
  12. */
  13. disabled: boolean,
  14. /**
  15. * The Redux dispatch function.
  16. */
  17. dispatch: Function,
  18. /**
  19. * The calendar event list.
  20. */
  21. _eventList: Array<Object>,
  22. /**
  23. * The translate function.
  24. */
  25. t: Function
  26. };
  27. /**
  28. * Component to display a list of events from the (mobile) user's calendar.
  29. */
  30. class MeetingList extends Component<Props> {
  31. /**
  32. * Default values for the component's props.
  33. */
  34. static defaultProps = {
  35. _eventList: []
  36. };
  37. /**
  38. * Constructor of the MeetingList component.
  39. *
  40. * @inheritdoc
  41. */
  42. constructor(props) {
  43. super(props);
  44. this._onPress = this._onPress.bind(this);
  45. this._onRefresh = this._onRefresh.bind(this);
  46. this._toDisplayableItem = this._toDisplayableItem.bind(this);
  47. this._toDisplayableList = this._toDisplayableList.bind(this);
  48. this._toDateString = this._toDateString.bind(this);
  49. }
  50. /**
  51. * Implements the React Components's render method.
  52. *
  53. * @inheritdoc
  54. */
  55. render() {
  56. const { disabled } = this.props;
  57. return (
  58. <NavigateSectionList
  59. disabled = { disabled }
  60. onPress = { this._onPress }
  61. onRefresh = { this._onRefresh }
  62. sections = { this._toDisplayableList() } />
  63. );
  64. }
  65. _onPress: string => Function
  66. /**
  67. * Handles the list's navigate action.
  68. *
  69. * @private
  70. * @param {string} url - The url string to navigate to.
  71. * @returns {void}
  72. */
  73. _onPress(url) {
  74. const { dispatch } = this.props;
  75. dispatch(appNavigate(url));
  76. }
  77. _onRefresh: () => void
  78. /**
  79. * Callback to execute when the list is doing a pull-to-refresh.
  80. *
  81. * @private
  82. * @returns {void}
  83. */
  84. _onRefresh() {
  85. const { dispatch } = this.props;
  86. dispatch(refreshCalendarEntryList());
  87. }
  88. _toDisplayableItem: Object => Object
  89. /**
  90. * Creates a displayable object from an event.
  91. *
  92. * @private
  93. * @param {Object} event - The calendar event.
  94. * @returns {Object}
  95. */
  96. _toDisplayableItem(event) {
  97. return {
  98. key: `${event.id}-${event.startDate}`,
  99. lines: [
  100. event.url,
  101. this._toDateString(event)
  102. ],
  103. title: event.title,
  104. url: event.url
  105. };
  106. }
  107. _toDisplayableList: () => Array<Object>
  108. /**
  109. * Transforms the event list to a displayable list
  110. * with sections.
  111. *
  112. * @private
  113. * @returns {Array<Object>}
  114. */
  115. _toDisplayableList() {
  116. const { _eventList, t } = this.props;
  117. const now = Date.now();
  118. const nowSection = NavigateSectionList.createSection(
  119. t('calendarSync.now'),
  120. 'now'
  121. );
  122. const nextSection = NavigateSectionList.createSection(
  123. t('calendarSync.next'),
  124. 'next'
  125. );
  126. const laterSection = NavigateSectionList.createSection(
  127. t('calendarSync.later'),
  128. 'later'
  129. );
  130. for (const event of _eventList) {
  131. const displayableEvent = this._toDisplayableItem(event);
  132. if (event.startDate < now && event.endDate > now) {
  133. nowSection.data.push(displayableEvent);
  134. } else if (event.startDate > now) {
  135. if (nextSection.data.length
  136. && nextSection.data[0].startDate !== event.startDate) {
  137. laterSection.data.push(displayableEvent);
  138. } else {
  139. nextSection.data.push(displayableEvent);
  140. }
  141. }
  142. }
  143. const sectionList = [];
  144. for (const section of [
  145. nowSection,
  146. nextSection,
  147. laterSection
  148. ]) {
  149. if (section.data.length) {
  150. sectionList.push(section);
  151. }
  152. }
  153. return sectionList;
  154. }
  155. _toDateString: Object => string
  156. /**
  157. * Generates a date (interval) string for a given event.
  158. *
  159. * @private
  160. * @param {Object} event - The event.
  161. * @returns {string}
  162. */
  163. _toDateString(event) {
  164. /* eslint-disable max-len */
  165. const startDateTime = getLocalizedDateFormatter(event.startDate).format('lll');
  166. const endTime = getLocalizedDateFormatter(event.endDate).format('LT');
  167. return `${startDateTime} - ${endTime}`;
  168. /* eslint-enable max-len */
  169. }
  170. }
  171. /**
  172. * Maps redux state to component props.
  173. *
  174. * @param {Object} state - The redux state.
  175. * @returns {{
  176. * _eventList: Array
  177. * }}
  178. */
  179. export function _mapStateToProps(state: Object) {
  180. return {
  181. _eventList: state['features/calendar-sync'].events
  182. };
  183. }
  184. export default translate(connect(_mapStateToProps)(MeetingList));