import React from 'react'; import { WithTranslation } from 'react-i18next'; import { connect } from 'react-redux'; import { createCalendarClickedEvent } from '../../analytics/AnalyticsEvents'; import { sendAnalytics } from '../../analytics/functions'; import { IReduxState, IStore } from '../../app/types'; import { translate } from '../../base/i18n/functions'; import Icon from '../../base/icons/components/Icon'; import { IconCalendar } from '../../base/icons/svg'; import AbstractPage from '../../base/react/components/AbstractPage'; import Spinner from '../../base/ui/components/web/Spinner'; import { openSettingsDialog } from '../../settings/actions.web'; import { SETTINGS_TABS } from '../../settings/constants'; import { refreshCalendar } from '../actions.web'; import { ERRORS } from '../constants'; import CalendarListContent from './CalendarListContent.web'; /** * The type of the React {@code Component} props of {@link CalendarList}. */ interface IProps extends WithTranslation { /** * The error object containing details about any error that has occurred * while interacting with calendar integration. */ _calendarError?: { error: string; }; /** * Whether or not a calendar may be connected for fetching calendar events. */ _hasIntegrationSelected: boolean; /** * Whether or not events have been fetched from a calendar. */ _hasLoadedEvents: boolean; /** * Indicates if the list is disabled or not. */ disabled?: boolean; /** * The Redux dispatch function. */ dispatch: IStore['dispatch']; } /** * Component to display a list of events from the user's calendar. */ class CalendarList extends AbstractPage { /** * Initializes a new {@code CalendarList} instance. * * @inheritdoc */ constructor(props: IProps) { super(props); // Bind event handlers so they are only bound once per instance. this._getRenderListEmptyComponent = this._getRenderListEmptyComponent.bind(this); this._onOpenSettings = this._onOpenSettings.bind(this); this._onKeyPressOpenSettings = this._onKeyPressOpenSettings.bind(this); this._onRefreshEvents = this._onRefreshEvents.bind(this); } /** * Implements React's {@link Component#render}. * * @inheritdoc */ render() { const { disabled } = this.props; return ( CalendarListContent ? : null ); } /** * Returns a component for showing the error message related to calendar * sync. * * @private * @returns {React$Component} */ _getErrorMessage() { const { _calendarError = { error: undefined }, t } = this.props; let errorMessageKey = 'calendarSync.error.generic'; let showRefreshButton = true; let showSettingsButton = true; if (_calendarError.error === ERRORS.GOOGLE_APP_MISCONFIGURED) { errorMessageKey = 'calendarSync.error.appConfiguration'; showRefreshButton = false; showSettingsButton = false; } else if (_calendarError.error === ERRORS.AUTH_FAILED) { errorMessageKey = 'calendarSync.error.notSignedIn'; showRefreshButton = false; } return (

{ t(errorMessageKey) }

{ showSettingsButton &&
{ t('calendarSync.permissionButton') }
} { showRefreshButton &&
{ t('calendarSync.refresh') }
}
); } /** * Returns a list empty component if a custom one has to be rendered instead * of the default one in the {@link NavigateSectionList}. * * @private * @returns {React$Component} */ _getRenderListEmptyComponent() { const { _calendarError, _hasIntegrationSelected, _hasLoadedEvents, t } = this.props; if (_calendarError) { return this._getErrorMessage(); } else if (_hasIntegrationSelected && _hasLoadedEvents) { return (

{ t('calendarSync.noEvents') }

{ t('calendarSync.refresh') }
); } else if (_hasIntegrationSelected && !_hasLoadedEvents) { return (
); } return (
{
{ t('welcomepage.connectCalendarText', { app: interfaceConfig.APP_NAME, provider: interfaceConfig.PROVIDER_NAME }) }
{ t('welcomepage.connectCalendarButton') }
); } /** * Opens {@code SettingsDialog}. * * @private * @returns {void} */ _onOpenSettings() { sendAnalytics(createCalendarClickedEvent('connect')); this.props.dispatch(openSettingsDialog(SETTINGS_TABS.CALENDAR)); } /** * KeyPress handler for accessibility. * * @param {Object} e - The key event to handle. * * @returns {void} */ _onKeyPressOpenSettings(e: React.KeyboardEvent) { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); this._onOpenSettings(); } } /** * Gets an updated list of calendar events. * * @private * @returns {void} */ _onRefreshEvents() { this.props.dispatch(refreshCalendar(true)); } } /** * Maps (parts of) the Redux state to the associated props for the * {@code CalendarList} component. * * @param {Object} state - The Redux state. * @private * @returns {{ * _calendarError: Object, * _hasIntegrationSelected: boolean, * _hasLoadedEvents: boolean * }} */ function _mapStateToProps(state: IReduxState) { const { error, events, integrationType, isLoadingEvents } = state['features/calendar-sync']; return { _calendarError: error, _hasIntegrationSelected: Boolean(integrationType), _hasLoadedEvents: Boolean(events) || !isLoadingEvents }; } export default translate(connect(_mapStateToProps)(CalendarList));