diff --git a/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/EndField.jsx b/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/EndField.jsx
new file mode 100644
index 000000000..370ae844d
--- /dev/null
+++ b/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/EndField.jsx
@@ -0,0 +1,133 @@
+/**
+ * EndField component.
+ * @module components/manage/Widgets/RecurrenceWidget/EndField
+ *
+ *
+ * CUSTOMIZATIONS:
+ * - added customization to have this changes https://github.com/plone/volto/pull/5555/files
+ */
+
+import React from 'react';
+import PropTypes from 'prop-types';
+import { defineMessages, injectIntl } from 'react-intl';
+import { Form, Grid, Input, Radio } from 'semantic-ui-react';
+import DatetimeWidget from '@plone/volto/components/manage/Widgets/DatetimeWidget';
+
+const messages = defineMessages({
+ recurrenceEnds: { id: 'Recurrence ends', defaultMessage: 'Ends' },
+ recurrenceEndsCount: { id: 'Recurrence ends after', defaultMessage: 'after' },
+ recurrenceEndsUntil: { id: 'Recurrence ends on', defaultMessage: 'on' },
+ occurrences: { id: 'Occurences', defaultMessage: 'occurrence(s)' },
+});
+/**
+ * EndField component class.
+ * @function EndField
+ * @returns {string} Markup of the component.
+ */
+const EndField = ({ value, count, until, onChange, intl }) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ onChange('recurrenceEnds', value)}
+ />
+
+
+ {intl.formatMessage(messages.recurrenceEndsCount)}
+
+
+ {
+ onChange(
+ target.id,
+ target.value === '' ? undefined : target.value,
+ );
+ }}
+ />
+
+
+ {intl.formatMessage(messages.occurrences)}
+
+
+
+
+ onChange('recurrenceEnds', value)}
+ />
+
+
+
+ {
+ onChange(id, value === '' ? undefined : value);
+ }}
+ />
+
+
+
+
+
+
+ );
+};
+
+/**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+EndField.propTypes = {
+ value: PropTypes.string,
+ count: PropTypes.any,
+ until: PropTypes.any,
+ onChange: PropTypes.func,
+};
+
+/**
+ * Default properties.
+ * @property {Object} defaultProps Default properties.
+ * @static
+ */
+EndField.defaultProps = {
+ value: null,
+ count: null,
+ until: null,
+ onChange: null,
+};
+
+export default injectIntl(EndField);
diff --git a/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx b/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx
new file mode 100644
index 000000000..427701229
--- /dev/null
+++ b/src/customizations/volto/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx
@@ -0,0 +1,1025 @@
+/**
+ * RecurrenceWidget component.
+ * @module components/manage/Widgets/RecurrenceWidget
+ *
+ * * CUSTOMIZATIONS:
+ * - added customization to have this changes https://github.com/plone/volto/pull/5555/files
+ */
+
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { compose } from 'redux';
+//import { RRule, RRuleSet, rrulestr } from 'rrule';
+import { connect } from 'react-redux';
+
+import cx from 'classnames';
+import { isEqual, map, find, concat, remove } from 'lodash';
+import { defineMessages, injectIntl } from 'react-intl';
+import {
+ Form,
+ Grid,
+ Label,
+ Button,
+ Segment,
+ Modal,
+ Header,
+} from 'semantic-ui-react';
+
+import { SelectWidget, Icon, DatetimeWidget } from '@plone/volto/components';
+import { toBackendLang } from '@plone/volto/helpers';
+import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
+
+import saveSVG from '@plone/volto/icons/save.svg';
+import editingSVG from '@plone/volto/icons/editing.svg';
+import trashSVG from '@plone/volto/icons/delete.svg';
+
+import {
+ Days,
+ OPTIONS,
+ FREQUENCES,
+ WEEKLY_DAYS,
+ MONDAYFRIDAY_DAYS,
+ rrulei18n,
+} from '@plone/volto/components/manage/Widgets/RecurrenceWidget/Utils';
+
+import IntervalField from '@plone/volto/components/manage/Widgets/RecurrenceWidget/IntervalField';
+import ByDayField from '@plone/volto/components/manage/Widgets/RecurrenceWidget/ByDayField';
+import EndField from '@plone/volto/components/manage/Widgets/RecurrenceWidget/EndField';
+import ByMonthField from '@plone/volto/components/manage/Widgets/RecurrenceWidget/ByMonthField';
+import ByYearField from '@plone/volto/components/manage/Widgets/RecurrenceWidget/ByYearField';
+import Occurences from '@plone/volto/components/manage/Widgets/RecurrenceWidget/Occurences';
+
+const messages = defineMessages({
+ editRecurrence: {
+ id: 'Edit recurrence',
+ defaultMessage: 'Edit recurrence',
+ },
+ save: {
+ id: 'Save recurrence',
+ defaultMessage: 'Save',
+ },
+ remove: {
+ id: 'Remove recurrence',
+ defaultMessage: 'Remove',
+ },
+ repeat: {
+ id: 'Repeat',
+ defaultMessage: 'Repeat',
+ },
+ daily: {
+ id: 'Daily',
+ defaultMessage: 'Daily',
+ },
+ mondayfriday: {
+ id: 'Monday and Friday',
+ defaultMessage: 'Monday and Friday',
+ },
+
+ weekdays: {
+ id: 'Weekday',
+ defaultMessage: 'Weekday',
+ },
+ weekly: {
+ id: 'Weekly',
+ defaultMessage: 'Weekly',
+ },
+ monthly: {
+ id: 'Monthly',
+ defaultMessage: 'Monthly',
+ },
+ yearly: {
+ id: 'Yearly',
+ defaultMessage: 'Yearly',
+ },
+
+ repeatEvery: {
+ id: 'Repeat every',
+ defaultMessage: 'Repeat every',
+ },
+ repeatOn: {
+ id: 'Repeat on',
+ defaultMessage: 'Repeat on',
+ },
+
+ interval_daily: {
+ id: 'Interval Daily',
+ defaultMessage: 'days',
+ },
+ interval_weekly: {
+ id: 'Interval Weekly',
+ defaultMessage: 'week(s)',
+ },
+ interval_monthly: {
+ id: 'Interval Monthly',
+ defaultMessage: 'Month(s)',
+ },
+ interval_yearly: {
+ id: 'Interval Yearly',
+ defaultMessage: 'year(s)',
+ },
+ add_date: {
+ id: 'Add date',
+ defaultMessage: 'Add date',
+ },
+ select_date_to_add_to_recurrence: {
+ id: 'Select a date to add to recurrence',
+ defaultMessage: 'Select a date to add to recurrence',
+ },
+});
+
+const NoRRuleOptions = [
+ 'recurrenceEnds',
+ 'monthly',
+ 'weekdayOfTheMonthIndex',
+ 'weekdayOfTheMonth',
+ 'yearly',
+ 'monthOfTheYear',
+ 'byhour',
+ 'byminute',
+ 'bysecond',
+ 'bynmonthday',
+ 'exdates',
+ 'rdates',
+];
+/**
+ * RecurrenceWidget component class.
+ * @function RecurrenceWidget
+ * @returns {string} Markup of the component.
+ */
+class RecurrenceWidget extends Component {
+ /**
+ * Property types.
+ * @property {Object} propTypes Property types.
+ * @static
+ */
+ static propTypes = {
+ id: PropTypes.string.isRequired,
+ formData: PropTypes.object,
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string,
+ required: PropTypes.bool,
+ error: PropTypes.arrayOf(PropTypes.string),
+ value: PropTypes.string,
+ onChange: PropTypes.func.isRequired,
+ };
+
+ /**
+ * Default properties.
+ * @property {Object} defaultProps Default properties.
+ * @static
+ */
+ static defaultProps = {
+ description: null,
+ required: false,
+ error: [],
+ value: null,
+ };
+
+ /**
+ * Constructor
+ * @method constructor
+ * @param {Object} props Component properties
+ * @constructs Actions
+ */
+ constructor(props, intl) {
+ super(props);
+ const { RRuleSet, rrulestr } = props.rrule;
+
+ this.moment = this.props.moment.default;
+ this.moment.locale(toBackendLang(this.props.lang));
+
+ let rruleSet = this.props.value
+ ? rrulestr(props.value, {
+ compatible: true, //If set to True, the parser will operate in RFC-compatible mode. Right now it means that unfold will be turned on, and if a DTSTART is found, it will be considered the first recurrence instance, as documented in the RFC.
+ forceset: true,
+ // dtstart: props.formData.start
+ // ? this.getUTCDate(props.formData.start)
+ // .startOf('day')
+ // .toDate()
+ // : null,
+ })
+ : new RRuleSet();
+
+ this.state = {
+ open: false,
+ rruleSet: rruleSet,
+ formValues: this.getFormValues(rruleSet),
+ RRULE_LANGUAGE: rrulei18n(
+ this.props.intl,
+ this.moment,
+ toBackendLang(this.props.lang),
+ ),
+ };
+ }
+
+ componentDidMount() {
+ if (this.props.value) {
+ this.setRecurrenceStartEnd();
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ if (this.props.value) {
+ const changedStart =
+ prevProps.formData?.start !== this.props.formData?.start;
+ const changedEnd = prevProps.formData?.end !== this.props.formData?.end;
+
+ if (changedStart || changedEnd) {
+ let start = this.getUTCDate(this.props.formData?.start).toDate();
+ // let end = this.getUTCDate(this.props.formData?.end).toDate();
+
+ let changeFormValues = {};
+ if (changedEnd) {
+ changeFormValues.until = this.getUTCDate(
+ this.props.formData?.end,
+ ).toDate();
+ }
+ this.setState(
+ (prevState) => {
+ let rruleSet = prevState.rruleSet;
+
+ rruleSet = this.updateRruleSet(
+ rruleSet,
+ { ...prevState.formValues, ...changeFormValues },
+ 'dtstart',
+ start,
+ );
+
+ return {
+ ...prevState,
+ rruleSet,
+ };
+ },
+ () => {
+ //then, after set state, set recurrence rrule value
+ this.saveRrule();
+ },
+ );
+ }
+ }
+ }
+
+ editRecurrence = () => {
+ this.setRecurrenceStartEnd();
+ };
+
+ setRecurrenceStartEnd = () => {
+ const start = this.props.formData?.start;
+
+ const _start = new Date(start); //The date is already in utc from plone, so this is not necessary: this.getUTCDate(start).startOf('day').toDate();
+
+ this.setState((prevState) => {
+ let rruleSet = prevState.rruleSet;
+ const formValues = this.getFormValues(rruleSet); //to set default values, included end
+
+ rruleSet = this.updateRruleSet(rruleSet, formValues, 'dtstart', _start);
+ return {
+ ...prevState,
+ rruleSet,
+ formValues,
+ };
+ });
+ };
+
+ getUTCDate = (date) => {
+ return date.match(/T(.)*(-|\+|Z)/g)
+ ? this.moment(date).utc()
+ : this.moment(`${date}Z`).utc();
+ };
+
+ show = (dimmer) => () => {
+ this.setState({ dimmer, open: true });
+ this.editRecurrence();
+ };
+ close = () => this.setState({ open: false });
+
+ getFreq = (number, weekdays) => {
+ let freq = FREQUENCES.DAILY;
+ Object.entries(OPTIONS.frequences).forEach(([f, o]) => {
+ if (o.rrule === number) {
+ freq = f;
+ }
+ });
+ if (freq === FREQUENCES.WEEKLY && weekdays) {
+ if (isEqual(weekdays.sort(), WEEKLY_DAYS.map((w) => w.weekday).sort())) {
+ freq = FREQUENCES.WEEKDAYS;
+ }
+ }
+ return freq;
+ };
+
+ getWeekday = (number) => {
+ var day = null;
+ const n = number === -1 ? 6 : number; //because sunday for moment has index 0, but for rrule has index 6
+ Object.keys(Days).forEach((d) => {
+ if (Days[d].weekday === n) {
+ day = Days[d];
+ }
+ });
+ return day;
+ };
+
+ /**
+ * Called on init, to populate form values
+ * */
+ getFormValues = (rruleSet) => {
+ //default
+ let formValues = {
+ freq: FREQUENCES.DAILY,
+ interval: 1,
+ };
+
+ formValues = this.changeField(
+ formValues,
+ 'recurrenceEnds',
+ this.props.formData?.end ? 'until' : 'count',
+ );
+
+ const rrule = rruleSet.rrules()[0];
+
+ if (rrule) {
+ var freq = this.getFreq(rrule.options.freq, rrule.options.byweekday);
+
+ //init with rruleOptions
+ Object.entries(rrule.options).forEach(([option, value]) => {
+ switch (option) {
+ case 'freq':
+ formValues[option] = freq;
+ break;
+ case 'count':
+ if (value != null) {
+ formValues['recurrenceEnds'] = option;
+ formValues[option] = value;
+ }
+ break;
+ case 'until':
+ if (value != null) {
+ formValues['recurrenceEnds'] = option;
+ formValues[option] = value;
+ }
+ break;
+ case 'byweekday':
+ if (value && value.length > 0) {
+ if (isEqual(value, WEEKLY_DAYS)) {
+ formValues['freq'] = FREQUENCES.WEEKDAYS;
+ }
+ if (isEqual(value, MONDAYFRIDAY_DAYS)) {
+ formValues['freq'] = FREQUENCES.MONDAYFRIDAY;
+ }
+ }
+ formValues[option] = value
+ ? value.map((d) => {
+ return this.getWeekday(d);
+ })
+ : [];
+ break;
+ case 'bymonthday':
+ if (value && value.length > 0) {
+ if (freq === FREQUENCES.MONTHLY) {
+ formValues['monthly'] = option;
+ }
+ if (freq === FREQUENCES.YEARLY) {
+ formValues['yearly'] = option;
+ }
+ } else {
+ if (freq === FREQUENCES.MONTHLY) {
+ formValues['monthly'] = null;
+ }
+ if (freq === FREQUENCES.YEARLY) {
+ formValues['yearly'] = null;
+ }
+ }
+ formValues[option] = value;
+ break;
+ case 'bynweekday':
+ if (value && value.length > 0) {
+ //[weekDayNumber,orinal_number] -> translated is for example: [sunday, third] -> the third sunday of the month
+
+ if (freq === FREQUENCES.SMONTHLY) {
+ formValues['monthly'] = 'byweekday';
+ }
+ if (freq === FREQUENCES.YEARLY) {
+ formValues['yearly'] = 'byday';
+ }
+ formValues['weekdayOfTheMonth'] = value[0][0];
+ formValues['weekdayOfTheMonthIndex'] = value[0][1];
+ }
+ break;
+ case 'bymonth':
+ if (freq === FREQUENCES.YEARLY) {
+ formValues['yearly'] = 'byday';
+ }
+ formValues['monthOfTheYear'] = value ? value[0] : null;
+ break;
+
+ default:
+ formValues[option] = value;
+ }
+ });
+ }
+ return formValues;
+ };
+
+ formValuesToRRuleOptions = (formValues) => {
+ var values = Object.assign({}, formValues);
+
+ //remove NoRRuleOptions
+ NoRRuleOptions.forEach((opt) => {
+ delete values[opt];
+ });
+
+ //transform values for rrule
+ Object.keys(values).forEach((field) => {
+ var value = values[field];
+ switch (field) {
+ case 'freq':
+ if (value) {
+ value = OPTIONS.frequences[value].rrule;
+ }
+ break;
+ case 'until':
+ let mDate = null;
+ if (value) {
+ mDate = this.moment(new Date(value));
+ if (typeof value === 'string') {
+ mDate = this.moment(new Date(value));
+ } else {
+ //object-->Date()
+ mDate = this.moment(value);
+ }
+
+ if (this.props.formData.end) {
+ //set time from formData.end
+ const mEnd = this.moment(new Date(this.props.formData.end));
+ mDate.set('hour', mEnd.get('hour'));
+ mDate.set('minute', mEnd.get('minute'));
+ }
+ }
+ value = value ? mDate.toDate() : null;
+ break;
+ default:
+ break;
+ }
+
+ if (value === 0 || value) {
+ //set value
+ values[field] = value;
+ } else {
+ //remove empty values
+ delete values[field];
+ }
+ });
+
+ return values;
+ };
+
+ updateRruleSet = (rruleSet, formValues, field, value) => {
+ var rruleOptions = this.formValuesToRRuleOptions(formValues);
+ var dstart =
+ field === 'dtstart'
+ ? value
+ : rruleSet.dtstart()
+ ? rruleSet.dtstart()
+ : new Date();
+ var exdates =
+ field === 'exdates' ? value : Object.assign([], rruleSet.exdates());
+
+ var rdates =
+ field === 'rdates' ? value : Object.assign([], rruleSet.rdates());
+
+ rruleOptions.dtstart = dstart;
+
+ const { RRule, RRuleSet } = this.props.rrule;
+
+ let set = new RRuleSet();
+ //set.dtstart(dstart);
+ set.rrule(new RRule(rruleOptions));
+
+ exdates.map((ex) => set.exdate(ex));
+ rdates.map((r) => set.rdate(r));
+
+ return set;
+ };
+
+ getDefaultUntil = (freq) => {
+ const moment = this.moment;
+ var end = this.props.formData?.end
+ ? moment(new Date(this.props.formData.end))
+ : null;
+ var tomorrow = moment().add(1, 'days');
+ var nextWeek = moment().add(7, 'days');
+ var nextMonth = moment().add(1, 'months');
+ var nextYear = moment().add(1, 'years');
+
+ var until = end;
+ switch (freq) {
+ case FREQUENCES.DAILY:
+ until = end ? end : tomorrow;
+ break;
+ case FREQUENCES.WEEKLY:
+ until = end ? end : nextWeek;
+ break;
+ case FREQUENCES.WEEKDAYS:
+ until = end ? end : nextWeek;
+ break;
+ case FREQUENCES.MONDAYFRIDAY:
+ until = end ? end : nextWeek;
+ break;
+ case FREQUENCES.MONTHLY:
+ until = end ? end : nextMonth;
+ break;
+ case FREQUENCES.YEARLY:
+ until = end ? end : nextYear;
+ break;
+ default:
+ break;
+ }
+ if (this.props.formData.end) {
+ //set default end time
+ until.set('hour', end.get('hour'));
+ until.set('minute', end.get('minute'));
+ }
+
+ until = new Date(
+ until.get('year'),
+ until.get('month'),
+ until.get('date'),
+ until.get('hour'),
+ until.get('minute'),
+ );
+
+ return until;
+ };
+
+ changeField = (formValues, field, value) => {
+ // git p.log('field', field, 'value', value);
+ //get weekday from state.
+ const moment = this.moment;
+ const byweekday =
+ this.state?.rruleSet?.rrules().length > 0
+ ? this.state.rruleSet.rrules()[0].origOptions.byweekday
+ : null;
+ const currWeekday = this.getWeekday(moment().day() - 1);
+ const currMonth = moment().month() + 1;
+
+ const startMonth = this.props.formData?.start
+ ? moment(this.props.formData.start).month() + 1
+ : currMonth;
+
+ const startWeekday = this.props.formData?.start
+ ? this.getWeekday(moment(this.props.formData.start).day() - 1)
+ : currWeekday;
+ formValues[field] = value;
+
+ const defaultMonthDay = this.props.formData?.start
+ ? moment(this.props.formData.start).date()
+ : moment().date();
+
+ switch (field) {
+ case 'freq':
+ formValues.interval = 1;
+ const fconfig = OPTIONS.frequences[value];
+
+ //clear values
+ if (!fconfig.interval) {
+ formValues.interval = null;
+ }
+
+ formValues = this.changeField(formValues, 'byweekday', null);
+ formValues = this.changeField(formValues, 'yearly', null);
+ formValues = this.changeField(formValues, 'bymonthday', null);
+ formValues = this.changeField(formValues, 'byweekday', null);
+ formValues = this.changeField(formValues, 'monthOfTheYear', null);
+
+ if (!formValues.until) {
+ formValues.until = this.getDefaultUntil(value);
+ }
+
+ //set defaults
+ switch (value) {
+ case FREQUENCES.DAILY:
+ break;
+ case FREQUENCES.WEEKDAYS:
+ formValues = this.changeField(formValues, 'byweekday', WEEKLY_DAYS);
+ break;
+ case FREQUENCES.MONDAYFRIDAY:
+ formValues = this.changeField(
+ formValues,
+ 'byweekday',
+ MONDAYFRIDAY_DAYS,
+ );
+ break;
+ case FREQUENCES.WEEKLY:
+ formValues = this.changeField(formValues, 'byweekday', [
+ startWeekday,
+ ]);
+
+ break;
+ case FREQUENCES.MONTHLY:
+ formValues = this.changeField(formValues, 'monthly', 'bymonthday');
+
+ break;
+ case FREQUENCES.YEARLY:
+ formValues = this.changeField(formValues, 'yearly', 'bymonthday');
+ break;
+ default:
+ break;
+ }
+
+ break;
+
+ case 'recurrenceEnds':
+ if (value === 'count') {
+ formValues.count = 1;
+ formValues.until = null;
+ }
+ if (value === 'until') {
+ formValues.until = this.getDefaultUntil(formValues.freq);
+ formValues.count = null; //default value
+ }
+ break;
+
+ case 'byweekday':
+ formValues.byweekday = value;
+
+ if (FREQUENCES.WEEKLY !== formValues.freq) {
+ formValues.weekdayOfTheMonth = value ? value[0].weekday : null;
+ formValues.weekdayOfTheMonthIndex = value ? value[0].n : null;
+ } else {
+ delete formValues.weekdayOfTheMonth;
+ delete formValues.weekdayOfTheMonthIndex;
+ }
+
+ break;
+ case 'weekdayOfTheMonth':
+ var weekday = this.getWeekday(value); // get new day
+ var n = byweekday ? byweekday[0].n : 1;
+ //set nth value
+ formValues.byweekday = weekday ? [weekday.nth(n)] : null;
+ break;
+ case 'weekdayOfTheMonthIndex':
+ var week_day = byweekday ? byweekday[0] : currWeekday; //get day from state. If not set get current day
+ //set nth value
+ formValues.byweekday = value ? [week_day.nth(value)] : null;
+ break;
+
+ case 'monthOfTheYear':
+ if (value === null || value === undefined) {
+ delete formValues.bymonth;
+ } else {
+ formValues.bymonth = [value];
+ }
+ break;
+
+ case 'monthly':
+ if (value === 'bymonthday') {
+ formValues.bymonthday = [defaultMonthDay]; //default value
+ formValues = this.changeField(formValues, 'byweekday', null); //default value
+ }
+ if (value === 'byweekday') {
+ formValues.bymonthday = null; //default value
+ formValues = this.changeField(formValues, 'byweekday', [
+ currWeekday.nth(1),
+ ]); //default value
+ }
+ if (value === null) {
+ formValues = this.changeField(formValues, 'bymonthday', null); //default value
+ formValues = this.changeField(formValues, 'byweekday', null); //default value
+ }
+ break;
+ case 'yearly':
+ if (value === 'bymonthday') {
+ //sets bymonth and bymonthday in rruleset
+ formValues.bymonthday = [defaultMonthDay]; //default value
+
+ formValues = this.changeField(
+ formValues,
+ 'monthOfTheYear',
+ startMonth,
+ ); //default value: current month
+ formValues = this.changeField(formValues, 'byweekday', null); //default value
+ }
+ if (value === 'byday') {
+ formValues = this.changeField(formValues, 'bymonthday', null); //default value
+ formValues = this.changeField(formValues, 'byweekday', [
+ startWeekday.nth(1),
+ ]); //default value
+ formValues = this.changeField(
+ formValues,
+ 'monthOfTheYear',
+ startMonth,
+ ); //default value
+ }
+ break;
+ default:
+ break;
+ }
+ return formValues;
+ };
+
+ onChangeRule = (field, value) => {
+ var formValues = Object.assign({}, this.state.formValues);
+ formValues = this.changeField(formValues, field, value);
+
+ this.setState((prevState) => {
+ var rruleSet = prevState.rruleSet;
+ rruleSet = this.updateRruleSet(rruleSet, formValues, field, value);
+ return {
+ ...prevState,
+ rruleSet,
+ formValues,
+ };
+ });
+ };
+
+ exclude = (date) => {
+ let list = this.state.rruleSet.exdates().slice(0);
+ list.push(date);
+ this.onChangeRule('exdates', list);
+ };
+
+ undoExclude = (date) => {
+ let list = this.state.rruleSet.exdates().slice(0);
+ remove(list, (e) => {
+ return e.getTime() === date.getTime();
+ });
+ this.onChangeRule('exdates', list);
+ };
+
+ addDate = (date) => {
+ const moment = this.moment;
+ let all = concat(this.state.rruleSet.all(), this.state.rruleSet.exdates());
+
+ var simpleDate = moment(new Date(date)).startOf('day').toDate().getTime();
+ var exists = find(all, (e) => {
+ var d = moment(e).startOf('day').toDate().getTime();
+ return d === simpleDate;
+ });
+ if (!exists) {
+ let list = this.state.rruleSet.rdates().slice(0);
+ list.push(new Date(date));
+ this.onChangeRule('rdates', list);
+ }
+ };
+
+ saveRrule = () => {
+ var value = this.state.rruleSet.toString();
+ this.props.onChange(this.props.id, value);
+ };
+
+ save = () => {
+ this.saveRrule();
+ this.close();
+ };
+
+ remove = () => {
+ const { RRuleSet } = this.props.rrule;
+ this.props.onChange(this.props.id, null);
+ let rruleSet = new RRuleSet();
+ this.setState({
+ rruleSet: rruleSet,
+ formValues: this.getFormValues(rruleSet),
+ });
+ };
+
+ render() {
+ const { open, dimmer, rruleSet, formValues, RRULE_LANGUAGE } = this.state;
+
+ const { id, title, required, description, error, fieldSet, intl } =
+ this.props;
+
+ return (
+ 0}
+ className={cx('recurrence-widget', description ? 'help' : '')}
+ id={`${fieldSet || 'field'}-${id}`}
+ >
+
+
+
+
+
+
+
+
+ {rruleSet.rrules()[0] && (
+ <>
+
+
+
+
+
+ >
+ )}
+
+
+ {this.props.value && (
+
+ )}
+
+
+
+ {intl.formatMessage(messages.editRecurrence)}{' '}
+
+
+ {rruleSet.rrules().length > 0 && (
+
+
+
+
+
+
+
+
+
+ {intl.formatMessage(messages.add_date)}
+
+
+ {
+ this.addDate(value === '' ? undefined : value);
+ }}
+ />
+
+
+ )}
+
+
+
+
+
+ {map(error, (message) => (
+
+ ))}
+
+
+ {description && (
+
+
+ {description}
+
+
+ )}
+
+
+ );
+ }
+}
+
+export default compose(
+ injectLazyLibs(['moment', 'rrule']),
+ connect((state) => ({
+ lang: state.intl.locale,
+ })),
+ injectIntl,
+)(RecurrenceWidget);