diff --git a/samples/react-calendar/package-lock.json b/samples/react-calendar/package-lock.json index 09e64c5aa..cd8185890 100644 --- a/samples/react-calendar/package-lock.json +++ b/samples/react-calendar/package-lock.json @@ -18718,6 +18718,11 @@ "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", "dev": true }, + "string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==" + }, "string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", diff --git a/samples/react-calendar/package.json b/samples/react-calendar/package.json index 7a5080875..e2000b03c 100644 --- a/samples/react-calendar/package.json +++ b/samples/react-calendar/package.json @@ -43,6 +43,7 @@ "react-dom": "16.7.0", "react-draft-wysiwyg": "^1.13.2", "spfx-uifabric-themes": "^0.6.0", + "string-format": "^2.0.0", "typescript": "^3.2.4", "xml2js": "^0.4.19" }, diff --git a/samples/react-calendar/src/controls/Event/IEventState.ts b/samples/react-calendar/src/controls/Event/IEventState.ts index 6e3bc4477..7185d7b25 100644 --- a/samples/react-calendar/src/controls/Event/IEventState.ts +++ b/samples/react-calendar/src/controls/Event/IEventState.ts @@ -29,4 +29,5 @@ export interface IEventState { showRecurrenceSeriesInfo:boolean; newRecurrenceEvent:boolean; recurrenceAction:string; + recurrenceDescription?:string; } diff --git a/samples/react-calendar/src/controls/Event/event.tsx b/samples/react-calendar/src/controls/Event/event.tsx index 944e7a72b..323d564bd 100644 --- a/samples/react-calendar/src/controls/Event/event.tsx +++ b/samples/react-calendar/src/controls/Event/event.tsx @@ -4,6 +4,7 @@ import * as strings from 'CalendarWebPartStrings'; import { IEventProps } from './IEventProps'; import { IEventState } from './IEventState'; import * as moment from 'moment'; +import { parseString } from 'xml2js'; import 'react-big-calendar/lib/css/react-big-calendar.css'; import { PeoplePicker, PrincipalType } from "@pnp/spfx-controls-react/lib/PeoplePicker"; import { @@ -44,6 +45,7 @@ import { Map, ICoordinates, MapType } from "@pnp/spfx-controls-react/lib/Map"; import { EventRecurrenceInfo } from '../../controls/EventRecurrenceInfo/EventRecurrenceInfo'; import { getGUID } from '@pnp/common'; import { toLocaleShortDateString } from '../../utils/dateUtils'; +const format = require('string-format'); const DayPickerStrings: IDatePickerStrings = { months: [strings.January, strings.February, strings.March, strings.April, strings.May, strings.June, strings.July, strings.August, strings.September, strings.October, strings.November, strings.December], @@ -177,6 +179,7 @@ export class Event extends React.Component { eventData.fRecurrence = true; eventData.UID = getGUID(); panelMode = IPanelModelEnum.add; + eventData.RecurrenceData = await this.returnExceptionRecurrenceInfo(eventData.RecurrenceData); } startDate = `${moment(this.state.startDate).format('YYYY/MM/DD')}`; endDate = `${moment(this.state.endDate).format('YYYY/MM/DD')}`; @@ -299,6 +302,8 @@ export class Event extends React.Component { event.geolocation.Latitude = this.latitude; event.geolocation.Longitude = this.longitude; + + const recurrenceInfo = event.EventType === "4" && event.MasterSeriesItemID !== "" ? event.RecurrenceData : await this.returnExceptionRecurrenceInfo(event.RecurrenceData); // Update Component Data this.setState({ eventData: event, @@ -315,6 +320,7 @@ export class Event extends React.Component { siteRegionalSettings: siteRegionalSettigns, locationLatitude: this.latitude, locationLongitude: this.longitude, + recurrenceDescription: recurrenceInfo }); } else { editorState = EditorState.createEmpty(); @@ -337,8 +343,6 @@ export class Event extends React.Component { * @memberof Event */ public async componentDidMount() { - - await this.renderEventData(); } @@ -566,6 +570,280 @@ export class Event extends React.Component { this.setState({ showRecurrenceSeriesInfo: true, recurrenceSeriesEdited: true }); } + /** + * + * + * @private + * @param {string} rule + * @memberof Event + */ + private parseDailyRule(rule): string { + const keys = Object.keys(rule); + if (keys.indexOf("weekday") !== -1 && rule["weekday"] === "TRUE") + return format("{} {}", format(strings.everyFormat, 1), strings.weekDayLabel); + + if (keys.indexOf("dayFrequency") !== -1) { + const dayFrequency: number = parseInt(rule["dayFrequency"]); + const frequencyFormat = dayFrequency === 1 ? strings.everyFormat : dayFrequency === 2 ? strings.everySecondFormat : strings.everyNthFormat; + return format("{} {}", format(frequencyFormat, dayFrequency), strings.dayLable); + } + + return "Invalid recurrence format"; + } + + /** + * + * + * @private + * @param { string } rule + * @memberof Event + */ + private parseWeeklyRule(rule): string { + const frequency: number = parseInt(rule["weekFrequency"]); + const keys = Object.keys(rule); + const dayMap: any = { + "mo": strings.Monday, + "tu": strings.Tuesday, + "we": strings.Wednesday, + "th": strings.Thursday, + "fr": strings.Friday, + "sa": strings.Saturday, + "su": strings.Sunday + }; + let days: string[] = []; + for (let key of keys) { + days.push(dayMap[key]); + } + + return format("{}{} {} {}", + frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency): format(strings.everyNthFormat, frequency), + strings.weekLabel, + strings.onLabel, + days.join(", ")); + } + + /** + * + * + * @private + * @param { string } rule + * @memberof Event + */ + private parseMonthlyRule(rule): string { + const frequency: number = parseInt(rule["monthFrequency"]); + const day: number = parseInt(rule["day"]); + + return format("{}{} {}", + frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency): format(strings.everyNthFormat, frequency), + strings.monthLabel, + format(strings.onTheDayFormat, day) + ); + } + + /** + * + * @private + * @param { string } rule + * @memberof Event + */ + private parseMonthlyByDayRule(rule): string { + let keys: string[] = Object.keys(rule); + const dayTypeMap: any = { + "day": strings.weekDayLabel, + "weekend_day": strings.weekEndDay, + "mo": strings.Monday, + "tu": strings.Tuesday, + "we": strings.Wednesday, + "th": strings.Thursday, + "fr": strings.Friday, + "sa": strings.Saturday, + "su": strings.Sunday + }; + + const orderType: any = { + "first": strings.firstLabel, + "second": strings.secondLabel, + "third": strings.thirdLabel, + "fourth": strings.fourthLabel, + "last": strings.lastLabel + }; + + let order: string; + let dayType: string; + let frequencyFormat: string; + + for (let key of keys) { + switch (key) { + case "monthFrequency": + const frequency = parseInt(rule[key]); + switch(frequency) { + case 1: + frequencyFormat = format(strings.everyFormat, frequency); + break; + case 2: + frequencyFormat = format(strings.everySecondFormat, frequency); + break; + default: + frequencyFormat = format(strings.everyNthFormat, frequency); + break; + } + break; + case "weekDayOfMonth": + order = orderType[rule[key]]; + break; + default: + dayType = dayTypeMap[rule[key]]; + break; + } + } + + return format("{} {} {} {} {}{}", + frequencyFormat, + strings.monthLabel.toLowerCase(), + strings.onTheLabel, + order, + dayType, + strings.theSuffix); + } + + /** + * + * @private + * @param rule + * @memberof Event + */ + private parseYearlyRule(rule): string { + const keys: string[] = Object.keys(rule); + const months: string[] = DayPickerStrings.months; + let frequencyString: string; + let month: string; + let day: string; + for (let key of keys) { + switch(key) { + case "yearFrequency": + const frequency = parseInt(rule[key]); + const frequencyFormat = frequency == 1 ? strings.everyFormat : frequency == 2 ? strings.everySecondFormat : strings.everyNthFormat; + frequencyString = format(frequencyFormat, frequency); + break; + case "month": + month = months[parseInt(rule[key]) - 1]; + break; + case "day": + day = rule[key]; + break; + } + } + + return format("{} {} {}", frequencyString, strings.yearLabel, format(strings.theNthOfMonthFormat, month, day)); + } + + /** + * + * + * @private + * @param rule + * @memberof Event + */ + private parseYearlyByDayRule(rule): string { + const keys: string[] = Object.keys(rule); + const months: string[] = DayPickerStrings.months; + const orderMap: any = { + "first": strings.firstLabel, + "second": strings.secondLabel, + "third": strings.thirdLabel, + "fourth": strings.fourthLabel, + "last": strings.lastLabel + }; + const dayTypeMap: any = { + "day": strings.weekDayLabel, + "weekend_day": strings.weekEndDay, + "mo": strings.Monday, + "tu": strings.Tuesday, + "we": strings.Wednesday, + "th": strings.Thursday, + "fr": strings.Friday, + "sa": strings.Saturday, + "su": strings.Sunday + }; + let frequencyString: string; + let month: string; + let order: string; + let dayTypeString: string; + for (let key of keys) { + switch(key) { + case "yearFrequency": + const frequency = parseInt(rule[key]); + const frequencyFormat = frequency === 1 ? strings.everyFormat : frequency === 2 ? strings.everySecondFormat : strings.everyNthFormat; + frequencyString = format(frequencyFormat, frequency); + break; + case "weekDayOfMonth": + order = orderMap[rule[key]]; + break; + case "month": + month = months[parseInt(rule[key]) - 1]; + break; + default: + dayTypeString = dayTypeMap[rule[key]]; + break; + } + + return format("{} {} {}", + frequencyString, + strings.yearLabel, + format(strings.onTheDayTypeFormat, order, dayTypeString.toLowerCase(), strings.theSuffix) + ); + } + } + + /** + * + * + * @private + * @param {string} recurrenceData + * @memberof Event + */ + private async returnExceptionRecurrenceInfo(recurrenceData: string) { + const promise = new Promise((resolve, reject) => { + parseString(recurrenceData, (err, result) => { + if (err) { + reject(err); + } + + resolve(result); + }); + }); + + const recurrenceInfo: any = await promise; + let keys = Object.keys(recurrenceInfo.recurrence.rule[0].repeat[0]); + const recurrenceTypes = ["daily", "weekly", "monthly", "monthlyByDay", "yearly", "yearlyByDay"]; + for (var key of keys) { + const rule = recurrenceInfo.recurrence.rule[0].repeat[0][key][0]['$']; + switch(recurrenceTypes.indexOf(key)) { + case 0: + return this.parseDailyRule(rule); + break; + case 1: + return this.parseWeeklyRule(rule); + break; + case 2: + return this.parseMonthlyRule(rule); + break; + case 3: + return this.parseMonthlyByDayRule(rule); + break; + case 4: + return this.parseYearlyRule(rule); + break; + case 5: + return this.parseYearlyByDayRule(rule); + break; + default: + continue; + } + } + } + + /** * * @@ -579,6 +857,7 @@ export class Event extends React.Component { //console.log(this.returnedRecurrenceInfo); } + /** * * @@ -588,6 +867,7 @@ export class Event extends React.Component { public render(): React.ReactElement { const { editorState } = this.state; + return (
{ (this.state.eventData && (this.state.eventData.EventType !== "0" && this.state.showRecurrenceSeriesInfo !== true)) ?

{ strings.recurrenceEventLabel }

+ { this.state.recurrenceDescription ? { this.state.recurrenceDescription } : null } end) || (rTotal > 0 && rTotal <= total)) loop = false; } } + if (e.fRecurrence === "1" && e.MasterSeriesItemID !== "") { + const ni = this.cloneObj(e); + er.push(ni); + } return er; } //end recurrence check } diff --git a/samples/react-calendar/src/webparts/calendar/loc/en-us.js b/samples/react-calendar/src/webparts/calendar/loc/en-us.js index 7a117bce2..1e232061b 100644 --- a/samples/react-calendar/src/webparts/calendar/loc/en-us.js +++ b/samples/react-calendar/src/webparts/calendar/loc/en-us.js @@ -126,6 +126,15 @@ define([], function () { patternLabel: "Pattern", dateRangeLabel: "Date Range", occurrencesLabel: "occurrences", - ofMonthLabel: "of" + ofMonthLabel: "of", + everyFormat: "Every {0} ", + everySecondFormat: "Every {0} ", + everyNthFormat: "Every {0} ", + onTheDayFormat: "on the {0}th day", + onTheLabel: "on the", + theSuffix: "", + yearLabel: "year", + theNthOfMonthFormat: "on {0} {1}", + onTheDayTypeFormat: "on the {0} {1}" } }); diff --git a/samples/react-calendar/src/webparts/calendar/loc/mystrings.d.ts b/samples/react-calendar/src/webparts/calendar/loc/mystrings.d.ts index 8311be1f9..238de9155 100644 --- a/samples/react-calendar/src/webparts/calendar/loc/mystrings.d.ts +++ b/samples/react-calendar/src/webparts/calendar/loc/mystrings.d.ts @@ -127,7 +127,15 @@ declare interface ICalendarWebPartStrings { dateRangeLabel: string; occurrencesLabel: string; ofMonthLabel:string; - + everyFormat: string; + everySecondFormat: string; + everyNthFormat: string; + onTheDayFormat: string; + onTheLabel: string; + theSuffix: string; + yearLabel: string; + theNthOfMonthFormat: string; + onTheDayTypeFormat: string; } declare module 'CalendarWebPartStrings' { diff --git a/samples/react-calendar/src/webparts/calendar/loc/sv-se.js b/samples/react-calendar/src/webparts/calendar/loc/sv-se.js index 773d0e0d6..a005be723 100644 --- a/samples/react-calendar/src/webparts/calendar/loc/sv-se.js +++ b/samples/react-calendar/src/webparts/calendar/loc/sv-se.js @@ -5,7 +5,7 @@ define([], function () { OcurrencesLabel: "Tillfällen", dateRangeLabel: "Datumintervall", weekEndDay: "Helgdag", - weekDayLabel: "Veckodag", + weekDayLabel: "Arbetsdag", lastLabel: "sista", fourthLabel: "fjärde", thirdLabel: "tredje", @@ -16,7 +16,7 @@ define([], function () { ofEveryLabel: "för varje ", AllowedValues1to12Label: "Tillåtna värder 1 till 12", noEndDate: "inget slutdatum", - everyweekdays: "alla veckodagar", + everyweekdays: "alla arbetsdagar", days: "dag", every: "var", EndByLabel: "slutar den", @@ -113,7 +113,7 @@ define([], function () { nextLabel: "Nästa", showMore: "mer", recurrenceEventLabel: "Återkommande händelse", - editRecurrenceSeries: "Redigera återkommande händelse", + editRecurrenceSeries: "Redigera serie", ifRecurrenceLabel: "Återkommande ?", onLabel: "På", offLabel: "Av", @@ -126,7 +126,15 @@ define([], function () { patternLabel: "Schema", dateRangeLabel: "Datumintervall", occurrencesLabel: "tillfällen", - ofMonthLabel: "i" + ofMonthLabel: "i", + everyFormat: "Varje ", + everySecondFormat: "Varannan ", + everyNthFormat: "Var {0}:e ", + onTheDayFormat: "den {0}:e dagen", + onTheLabel: "på den", + theSuffix: "en", + theNthOfMonthFormat: "den {1} {0}", + onTheDayTypeFormat: "på den {0} {1}{2}" } }); \ No newline at end of file