From 83e65f02a2e6cc671872d51aabf1ff06d843d8f5 Mon Sep 17 00:00:00 2001 From: vikas Date: Mon, 8 May 2017 19:18:58 +1000 Subject: [PATCH] [SDESK-1172] Repeat summary for recurring events (#190) [SDESK-1172] Test case fix [SDESK-1172] Changes after review --- .../components/RepeatEventSummary/_test.jsx | 132 ++++++++++++++++++ .../components/RepeatEventSummary/index.jsx | 100 +++++++++++++ client/components/index.js | 1 + client/containers/RepeatEventForm.jsx | 55 +++++++- 4 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 client/components/RepeatEventSummary/_test.jsx create mode 100644 client/components/RepeatEventSummary/index.jsx diff --git a/client/components/RepeatEventSummary/_test.jsx b/client/components/RepeatEventSummary/_test.jsx new file mode 100644 index 000000000..a74698e39 --- /dev/null +++ b/client/components/RepeatEventSummary/_test.jsx @@ -0,0 +1,132 @@ +import React from 'react' +import { mount } from 'enzyme' +import { RepeatEventSummary } from './index' +import moment from 'moment' + +class TestForm extends React.Component { + render() { + const { byDay, interval, frequency, endRepeatMode, until, count, startDate } = this.props + return ( + + ) + } +} + +TestForm.propTypes = { + byDay: React.PropTypes.string, + interval: React.PropTypes.number, + frequency: React.PropTypes.string, + endRepeatMode: React.PropTypes.string, + until: React.PropTypes.object, + count: React.PropTypes.string, + startDate: React.PropTypes.object, +} + +describe('', () => { + const event = { + _id: '5800d71930627218866f1e80', + dates: { + start: moment('2016-10-15T14:30+0000'), + end: moment('2016-10-20T15:00+0000'), + }, + definition_short: 'definition_short 1', + location: [{ name: 'location1' }], + name: 'name1', + files: [{ + media: { + name: 'file.pdf', + length: 1000, + }, + filemeta: { media_id: 'media1' }, + }], + links: ['http://www.google.com'], + _plannings: [], + } + + const mountForm = (recEvent) => { + const { byday, interval, frequency, endRepeatMode, until, count } = + recEvent.dates.recurring_rule + return ( + mount() + ) + } + + it('Shows appropriate repeat summary for a given frequency with intervals', () => { + const recEvent = { + ...event, + dates: { + start: moment('2016-10-15T14:30+0000'), + end: moment('2016-10-20T15:00+0000'), + recurring_rule: { + frequency: 'MONTHLY', + interval: '3', + }, + }, + } + let wrapper = mountForm(recEvent) + expect(wrapper.find('.repeatSummary').text()).toBe('Repeat summary: Every 3 months on day 15') + }) + it('Shows appropriate repeat summary for a given frequency with intervals and until a date', () => { + const recEvent = { + ...event, + dates: { + start: moment('2016-10-15T14:30+0000'), + end: moment('2016-10-20T15:00+0000' ), + recurring_rule: { + endRepeatMode: 'until', + frequency: 'DAILY', + interval: '3', + until: moment('2020-07-01T00:00'), + }, + }, + } + let wrapper = mountForm(recEvent) + expect(wrapper.find('.repeatSummary').text()).toBe('Repeat summary: Every 3 days, until 1 Jul 2020') + }) + it('Shows appropriate repeat summary for a given frequency with intervals and for a number of occurances', () => { + const recEvent = { + ...event, + dates: { + start: moment('2016-10-15T14:30+0000'), + end: moment('2016-10-20T15:00+0000'), + recurring_rule: { + endRepeatMode: 'count', + frequency: 'DAILY', + interval: '3', + count: '9', + }, + }, + } + let wrapper = mountForm(recEvent) + expect(wrapper.find('.repeatSummary').text()).toBe('Repeat summary: Every 3 days, 9 times') + }) + it('Shows appropriate repeat summary for a given weekly frequency with intervals and by days', () => { + const recEvent = { + ...event, + dates: { + start: moment('2016-10-15T14:30+0000'), + end: moment('2016-10-20T15:00+0000'), + recurring_rule: { + frequency: 'WEEKLY', + interval: '3', + byday: 'TH FR', + }, + }, + } + let wrapper = mountForm(recEvent) + expect(wrapper.find('.repeatSummary').text()).toBe('Repeat summary: Every 3 weeks on Thursday, Friday') + }) + +}) diff --git a/client/components/RepeatEventSummary/index.jsx b/client/components/RepeatEventSummary/index.jsx new file mode 100644 index 000000000..f66a2e2e9 --- /dev/null +++ b/client/components/RepeatEventSummary/index.jsx @@ -0,0 +1,100 @@ +import React from 'react' + +export class RepeatEventSummary extends React.Component { + constructor(props) { + super(props) + } + + getDaysFromByDays() { + let byDays = this.props.byDay && this.props.byDay.length > 0 ? this.props.byDay : + this.props.startDate ? this.props.startDate.format('dd').toUpperCase() : '' + + if (byDays) { + const days = { + 'MO': 'Monday', + 'TU': 'Tuesday', + 'WE': 'Wednesday', + 'TH': 'Thursday', + 'FR': 'Friday', + 'SA': 'Saturday', + 'SU': 'Sunday', + } + + let dayNames = [] + + byDays.split(' ').forEach((day) => { + dayNames.push(days[day]) + }) + return dayNames + } + } + + getPrefix() { + let prefix = '' + if (this.props.interval > 1) { + const duration = this.props.frequency === 'DAILY' ? 'days' : + this.props.frequency.replace('LY', 's').toLowerCase() + prefix = 'Every ' + this.props.interval + ' ' + duration + } else { + if (this.props.frequency) { + const f = this.props.frequency + prefix = f === 'YEARLY' ? 'Annualy' : (f.charAt(0).toUpperCase() + f.slice(1).toLowerCase()) + } + } + return prefix + } + + getStemText() { + let stemText = '' + const days = this.getDaysFromByDays() + switch(this.props.frequency) { + case 'WEEKLY': + stemText = days && days.length > 0 ? ('on ' + days.join(', ')) : '' + break + case 'MONTHLY': + stemText = this.props.startDate ? ('on day ' + this.props.startDate.format('D')) : '' + break + case 'YEARLY': + stemText = this.props.startDate ? ('on ' + this.props.startDate.format('MMM D')) : '' + break + } + return stemText + } + + getSuffix() { + let suffix = '' + if (this.props.endRepeatMode !== 'unlimited') { + if (this.props.endRepeatMode === 'count' && parseInt(this.props.count) > 0) { + suffix = ', ' + this.props.count + ' times' + } else if (this.props.endRepeatMode === 'until' && this.props.until && + this.props.until.isValid()) { + suffix = ', until ' + this.props.until.format('D MMM YYYY') + } + } + return suffix + } + + getRepeatSummary() { + const stemText = this.getStemText() + return this.getPrefix() + (stemText !== '' ? ( ' ' + stemText ) : '') + this.getSuffix() + } + + render() { + return ( +
+ {'Repeat summary: ' + this.getRepeatSummary()} + +
+ ) + } +} + +RepeatEventSummary.propTypes = { + byDay: React.PropTypes.string, + interval: React.PropTypes.string, + frequency: React.PropTypes.string, + endRepeatMode: React.PropTypes.string, + until: React.PropTypes.object, + count: React.PropTypes.string, + startDate: React.PropTypes.object, +} diff --git a/client/components/index.js b/client/components/index.js index 9682bc52f..bcf166e4a 100644 --- a/client/components/index.js +++ b/client/components/index.js @@ -17,3 +17,4 @@ import * as fields from './fields' export { fields } import * as tooltips from './Tooltips' export { tooltips } +export { RepeatEventSummary } from './RepeatEventSummary/index' diff --git a/client/containers/RepeatEventForm.jsx b/client/containers/RepeatEventForm.jsx index 9c6eb7012..3fb7ea7be 100644 --- a/client/containers/RepeatEventForm.jsx +++ b/client/containers/RepeatEventForm.jsx @@ -1,25 +1,41 @@ import React, { PropTypes } from 'react' import { Field, formValueSelector } from 'redux-form' -import { fields } from '../components' +import { fields, RepeatEventSummary } from '../components' import { connect } from 'react-redux' class RepeatEventFormComponent extends React.Component { constructor(props) { super(props) - const { endRepeatMode } = props + } + + componentWillMount() { + const { endRepeatMode, frequency, interval, start } = this.props + + const intervals = interval || 1 + const startDate = start || null if (endRepeatMode) { - this.state = { endRepeatMode: endRepeatMode } + this.state = { + endRepeatMode: endRepeatMode, + interval: intervals, + frequency: frequency, + date: startDate, + } } else { // if endRepeatMode not present set the default value for it - this.state = { endRepeatMode: 'unlimited' } + this.state = { + endRepeatMode: 'unlimited', + interval: intervals, + frequency: frequency, + date: startDate, + } this.props.change('dates.recurring_rule.endRepeatMode', 'unlimited') } } componentWillReceiveProps(nextProps) { - const { endRepeatMode, until, count } = nextProps + const { endRepeatMode, until, count, frequency, start, interval } = nextProps if (until && endRepeatMode != 'until') { // force the selection of 'until' for endRepeatMode @@ -41,6 +57,22 @@ class RepeatEventFormComponent extends React.Component { if (endRepeatMode && endRepeatMode !== this.state.endRepeatMode) { this.setState({ endRepeatMode: endRepeatMode }) + return + } + + if (frequency !== this.props.frequency) { + this.setState({ frequency: frequency }) + return + } + + if (start !== this.props.start) { + this.setState({ date: start }) + return + } + + if (interval !== this.props.interval) { + this.setState({ interval: interval }) + return } } @@ -138,6 +170,13 @@ class RepeatEventFormComponent extends React.Component { ref="recurring_rule--until" component={fields.DayPickerInput} /> + ) @@ -149,6 +188,9 @@ RepeatEventFormComponent.propTypes = { endRepeatMode: PropTypes.oneOf(['unlimited', 'count', 'until']), until: PropTypes.object, count: PropTypes.string, + byDay: PropTypes.string, + start: PropTypes.object, + interval: PropTypes.string, } // This is the same name defined in EventForm.jsx because it is just a sub form @@ -158,6 +200,9 @@ const mapStateToProps = (state) => ({ endRepeatMode: selector(state, 'dates.recurring_rule.endRepeatMode'), until: selector(state, 'dates.recurring_rule.until'), count: selector(state, 'dates.recurring_rule.count'), + byDay: selector(state, 'dates.recurring_rule.byday'), + start: selector(state, 'dates.start'), + interval: selector(state, 'dates.recurring_rule.interval'), }) export const RepeatEventForm = connect(mapStateToProps)(RepeatEventFormComponent)