Merge pull request #1553 from nanddeepn/react-calendar-allday

Added all day event functionality
This commit is contained in:
Hugo Bernier 2020-10-18 22:00:12 -04:00 committed by GitHub
commit cd5433c3df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 292 additions and 263 deletions

View File

@ -104,13 +104,15 @@ Start Date | Date | yes | Event Date
End Date| Date| yes | Event Date End Date| Date| yes | Event Date
## Solution ## Solution
The Web Part Use PnPjs library, Office-ui-fabric-react components. react Big-Calendar Compoment
The Web Part Use PnPjs library, Office-ui-fabric-react components. react Big-Calendar Component
Solution|Author(s) Solution|Author(s)
--------|--------- --------|---------
Calendar Web Part|João Mendes Calendar Web Part|João Mendes
Calendar Web Part|Mohamed Derhalli Calendar Web Part|Mohamed Derhalli
Calendar Web Part (Upgrade)|Hugo Bernier ([@bernier](https://twitter.com/bernierh), [Tahoe Ninjas](https://tahoeninjas.blog/)) Calendar Web Part (Upgrade)|Hugo Bernier ([@bernier](https://twitter.com/bernierh), [Tahoe Ninjas](https://tahoeninjas.blog/))
Calendar Web Part|Nanddeep Nachan ([@NanddeepNachan](https://twitter.com/NanddeepNachan))
## Version history ## Version history
@ -120,6 +122,7 @@ Version|Date|Comments
1.0.1|June 10, 2019|update add recurrence events 1.0.1|June 10, 2019|update add recurrence events
1.0.2|April 25, 2020|Update styles according to the applied theme 1.0.2|April 25, 2020|Update styles according to the applied theme
1.0.3|June 06, 2020|Upgrade to SPFx 1.10.0 1.0.3|June 06, 2020|Upgrade to SPFx 1.10.0
1.0.4|October 18, 2020|Added support for all-day events
## Disclaimer ## Disclaimer

View File

@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "react-calendar-client-side-solution", "name": "react-calendar-client-side-solution",
"id": "3a13208b-3874-4036-9262-4edd22e88187", "id": "3a13208b-3874-4036-9262-4edd22e88187",
"version": "1.0.0.0", "version": "1.0.4.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": true, "skipFeatureDeployment": true,
"isDomainIsolated": false "isDomainIsolated": false

View File

@ -1,7 +1,7 @@
{ {
"name": "react-calendar", "name": "react-calendar",
"main": "lib/index.js", "main": "lib/index.js",
"version": "1.0.2", "version": "1.0.4",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"

View File

@ -1,33 +1,34 @@
import { IEventData } from '../../services/IEventData'; import { IEventData } from '../../services/IEventData';
import { IUserPermissions } from '../../services/IUserPermissions'; import { IUserPermissions } from '../../services/IUserPermissions';
import { DayOfWeek} from 'office-ui-fabric-react/lib/DatePicker'; import { DayOfWeek } from 'office-ui-fabric-react/lib/DatePicker';
import { IDropdownOption } from 'office-ui-fabric-react/'; import { IDropdownOption } from 'office-ui-fabric-react/';
export interface IEventState { export interface IEventState {
showPanel: boolean; showPanel: boolean;
eventData:IEventData; eventData: IEventData;
firstDayOfWeek?: DayOfWeek; firstDayOfWeek?: DayOfWeek;
startSelectedHour: IDropdownOption ; startSelectedHour: IDropdownOption;
startSelectedMin: IDropdownOption ; startSelectedMin: IDropdownOption;
endSelectedHour: IDropdownOption ; endSelectedHour: IDropdownOption;
endSelectedMin: IDropdownOption ; endSelectedMin: IDropdownOption;
startDate?: Date; startDate?: Date;
endDate?: Date; endDate?: Date;
editorState?: any; editorState?: any;
selectedUsers: string[]; selectedUsers: string[];
locationLatitude: number; locationLatitude: number;
locationLongitude: number; locationLongitude: number;
errorMessage?:string; errorMessage?: string;
hasError?:boolean; hasError?: boolean;
disableButton?: boolean; disableButton?: boolean;
isSaving?:boolean; isSaving?: boolean;
isDeleting?:boolean; isDeleting?: boolean;
displayDialog:boolean; displayDialog: boolean;
userPermissions?: IUserPermissions; userPermissions?: IUserPermissions;
isloading:boolean; isloading: boolean;
isAllDayEvent: boolean;
siteRegionalSettings: any; siteRegionalSettings: any;
recurrenceSeriesEdited?:boolean; recurrenceSeriesEdited?: boolean;
showRecurrenceSeriesInfo:boolean; showRecurrenceSeriesInfo: boolean;
newRecurrenceEvent:boolean; newRecurrenceEvent: boolean;
recurrenceAction:string; recurrenceAction: string;
recurrenceDescription?:string; recurrenceDescription?: string;
} }

View File

@ -79,7 +79,6 @@ export class Event extends React.Component<IEventProps, IEventState> {
navigator.geolocation.getCurrentPosition((position) => { navigator.geolocation.getCurrentPosition((position) => {
this.latitude = position.coords.latitude; this.latitude = position.coords.latitude;
this.longitude = position.coords.longitude; this.longitude = position.coords.longitude;
}); });
} else { } else {
/* geolocation IS NOT available */ /* geolocation IS NOT available */
@ -104,10 +103,11 @@ export class Event extends React.Component<IEventProps, IEventState> {
isSaving: false, isSaving: false,
displayDialog: false, displayDialog: false,
isloading: false, isloading: false,
isAllDayEvent: this.props.event && this.props.event.fAllDayEvent,
siteRegionalSettings: undefined, siteRegionalSettings: undefined,
recurrenceSeriesEdited: false, recurrenceSeriesEdited: false,
showRecurrenceSeriesInfo:false, showRecurrenceSeriesInfo: false,
newRecurrenceEvent:false, newRecurrenceEvent: false,
recurrenceAction: 'display', recurrenceAction: 'display',
userPermissions: { hasPermissionAdd: false, hasPermissionDelete: false, hasPermissionEdit: false, hasPermissionView: false }, userPermissions: { hasPermissionAdd: false, hasPermissionDelete: false, hasPermissionEdit: false, hasPermissionView: false },
}; };
@ -148,13 +148,15 @@ export class Event extends React.Component<IEventProps, IEventState> {
* @memberof Event * @memberof Event
*/ */
private async onSave() { private async onSave() {
let eventData: IEventData = this.state.eventData; let eventData: IEventData = this.state.eventData;
let panelMode = this.props.panelMode; let panelMode = this.props.panelMode;
let startDate: string = null; let startDate: string = null;
let endDate: string = null; let endDate: string = null;
eventData.fRecurrence = false; eventData.fRecurrence = false;
// set All day event
eventData.fAllDayEvent = this.state.isAllDayEvent;
// if there are new Event recurrence or Edited recurrence series // if there are new Event recurrence or Edited recurrence series
if (this.state.recurrenceSeriesEdited || this.state.newRecurrenceEvent) { if (this.state.recurrenceSeriesEdited || this.state.newRecurrenceEvent) {
eventData.RecurrenceData = this.returnedRecurrenceInfo.recurrenceData; eventData.RecurrenceData = this.returnedRecurrenceInfo.recurrenceData;
@ -163,16 +165,17 @@ export class Event extends React.Component<IEventProps, IEventState> {
if (eventData.EventType == "0" && this.state.newRecurrenceEvent) { if (eventData.EventType == "0" && this.state.newRecurrenceEvent) {
eventData.EventType = "1"; eventData.EventType = "1";
eventData.fRecurrence= true; eventData.fRecurrence = true;
eventData.UID = getGUID();
}
if (eventData.EventType == "1" && this.state.recurrenceSeriesEdited) {
eventData.fRecurrence= true;
eventData.UID = getGUID(); eventData.UID = getGUID();
} }
} else { if (eventData.EventType == "1" && this.state.recurrenceSeriesEdited) {
if (this.state.eventData.EventType == '1'){ // recurrence exception eventData.fRecurrence = true;
eventData.UID = getGUID();
}
}
else {
if (this.state.eventData.EventType == '1') { // recurrence exception
eventData.RecurrenceID = eventData.EventDate.toString(); eventData.RecurrenceID = eventData.EventDate.toString();
eventData.MasterSeriesItemID = eventData.ID.toString(); eventData.MasterSeriesItemID = eventData.ID.toString();
eventData.EventType = "4"; eventData.EventType = "4";
@ -185,20 +188,19 @@ export class Event extends React.Component<IEventProps, IEventState> {
endDate = `${moment(this.state.endDate).format('YYYY/MM/DD')}`; endDate = `${moment(this.state.endDate).format('YYYY/MM/DD')}`;
} }
// Start Date
const startTime = `${this.state.startSelectedHour.key}:${this.state.startSelectedMin.key}`; const startTime = `${this.state.startSelectedHour.key}:${this.state.startSelectedMin.key}`;
const startDateTime = `${startDate} ${startTime}`; const startDateTime = `${startDate} ${startTime}`;
const start = moment(startDateTime, 'YYYY/MM/DD HH:mm').toLocaleString(); const start = moment(startDateTime, 'YYYY/MM/DD HH:mm').toLocaleString();
eventData.EventDate = new Date(start); eventData.EventDate = new Date(start);
// End Date // End Date
const endTime = `${this.state.endSelectedHour.key}:${this.state.endSelectedMin.key}`; const endTime = `${this.state.endSelectedHour.key}:${this.state.endSelectedMin.key}`;
const endDateTime = `${endDate} ${endTime}`; const endDateTime = `${endDate} ${endTime}`;
const end = moment(endDateTime, 'YYYY/MM/DD HH:mm').toLocaleString(); const end = moment(endDateTime, 'YYYY/MM/DD HH:mm').toLocaleString();
eventData.EndDate = new Date(end); eventData.EndDate = new Date(end);
// get Geolocation // get Geolocation
eventData.geolocation = { Latitude: this.latitude, Longitude: this.longitude }; eventData.geolocation = { Latitude: this.latitude, Longitude: this.longitude };
const locationInfo = await this.spService.getGeoLactionName(this.latitude, this.longitude); const locationInfo = await this.spService.getGeoLactionName(this.latitude, this.longitude);
eventData.location = locationInfo ? locationInfo.display_name : 'N/A'; eventData.location = locationInfo ? locationInfo.display_name : 'N/A';
@ -213,7 +215,6 @@ export class Event extends React.Component<IEventProps, IEventState> {
try { try {
for (const user of this.attendees) { for (const user of this.attendees) {
const userInfo: any = await this.spService.getUserByLoginName(user.id, this.props.siteUrl); const userInfo: any = await this.spService.getUserByLoginName(user.id, this.props.siteUrl);
eventData.attendes.push(Number(userInfo.Id)); eventData.attendes.push(Number(userInfo.Id));
} }
@ -255,7 +256,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
* @param {number} [eventId] * @param {number} [eventId]
* @memberof Event * @memberof Event
*/ */
private async renderEventData(eventId?: number) { private async renderEventData(eventId?: number) {
this.setState({ isloading: true }); this.setState({ isloading: true });
const event: IEventData = !eventId ? this.props.event : await this.spService.getEvent(this.props.siteUrl, this.props.listId, eventId); const event: IEventData = !eventId ? this.props.event : await this.spService.getEvent(this.props.siteUrl, this.props.listId, eventId);
@ -479,7 +480,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
this.setState({ isDeleting: false }); this.setState({ isDeleting: false });
this.props.onDissmissPanel(true); this.props.onDissmissPanel(true);
} catch (error) { } catch (error) {
this.setState({ hasError: true, errorMessage: error.message, isDeleting: false, displayDialog:false }); this.setState({ hasError: true, errorMessage: error.message, isDeleting: false, displayDialog: false });
} }
} }
@ -616,7 +617,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
} }
return format("{}{} {} {}", return format("{}{} {} {}",
frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency): format(strings.everyNthFormat, frequency), frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency) : format(strings.everyNthFormat, frequency),
strings.weekLabel, strings.weekLabel,
strings.onLabel, strings.onLabel,
days.join(", ")); days.join(", "));
@ -634,7 +635,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
const day: number = parseInt(rule["day"]); const day: number = parseInt(rule["day"]);
return format("{}{} {}", return format("{}{} {}",
frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency): format(strings.everyNthFormat, frequency), frequency === 1 ? format(strings.everyFormat, frequency) : frequency === 2 ? format(strings.everySecondFormat, frequency) : format(strings.everyNthFormat, frequency),
strings.monthLabel, strings.monthLabel,
format(strings.onTheDayFormat, day) format(strings.onTheDayFormat, day)
); );
@ -676,7 +677,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
switch (key) { switch (key) {
case "monthFrequency": case "monthFrequency":
const frequency = parseInt(rule[key]); const frequency = parseInt(rule[key]);
switch(frequency) { switch (frequency) {
case 1: case 1:
frequencyFormat = format(strings.everyFormat, frequency); frequencyFormat = format(strings.everyFormat, frequency);
break; break;
@ -719,7 +720,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
let month: string; let month: string;
let day: string; let day: string;
for (let key of keys) { for (let key of keys) {
switch(key) { switch (key) {
case "yearFrequency": case "yearFrequency":
const frequency = parseInt(rule[key]); const frequency = parseInt(rule[key]);
const frequencyFormat = frequency == 1 ? strings.everyFormat : frequency == 2 ? strings.everySecondFormat : strings.everyNthFormat; const frequencyFormat = frequency == 1 ? strings.everyFormat : frequency == 2 ? strings.everySecondFormat : strings.everyNthFormat;
@ -770,7 +771,7 @@ export class Event extends React.Component<IEventProps, IEventState> {
let order: string; let order: string;
let dayTypeString: string; let dayTypeString: string;
for (let key of keys) { for (let key of keys) {
switch(key) { switch (key) {
case "yearFrequency": case "yearFrequency":
const frequency = parseInt(rule[key]); const frequency = parseInt(rule[key]);
const frequencyFormat = frequency === 1 ? strings.everyFormat : frequency === 2 ? strings.everySecondFormat : strings.everyNthFormat; const frequencyFormat = frequency === 1 ? strings.everyFormat : frequency === 2 ? strings.everySecondFormat : strings.everyNthFormat;
@ -814,37 +815,36 @@ export class Event extends React.Component<IEventProps, IEventState> {
}); });
const recurrenceInfo: any = await promise; const recurrenceInfo: any = await promise;
if(recurrenceInfo != null) if (recurrenceInfo != null) {
{ let keys = Object.keys(recurrenceInfo.recurrence.rule[0].repeat[0]);
let keys = Object.keys(recurrenceInfo.recurrence.rule[0].repeat[0]); const recurrenceTypes = ["daily", "weekly", "monthly", "monthlyByDay", "yearly", "yearlyByDay"];
const recurrenceTypes = ["daily", "weekly", "monthly", "monthlyByDay", "yearly", "yearlyByDay"]; for (var key of keys) {
for (var key of keys) { const rule = recurrenceInfo.recurrence.rule[0].repeat[0][key][0]['$'];
const rule = recurrenceInfo.recurrence.rule[0].repeat[0][key][0]['$']; switch (recurrenceTypes.indexOf(key)) {
switch(recurrenceTypes.indexOf(key)) { case 0:
case 0: return this.parseDailyRule(rule);
return this.parseDailyRule(rule); break;
break; case 1:
case 1: return this.parseWeeklyRule(rule);
return this.parseWeeklyRule(rule); break;
break; case 2:
case 2: return this.parseMonthlyRule(rule);
return this.parseMonthlyRule(rule); break;
break; case 3:
case 3: return this.parseMonthlyByDayRule(rule);
return this.parseMonthlyByDayRule(rule); break;
break; case 4:
case 4: return this.parseYearlyRule(rule);
return this.parseYearlyRule(rule); break;
break; case 5:
case 5: return this.parseYearlyByDayRule(rule);
return this.parseYearlyByDayRule(rule); break;
break; default:
default: continue;
continue; }
} }
} }
} }
}
/** /**
@ -898,17 +898,17 @@ export class Event extends React.Component<IEventProps, IEventState> {
<div> <div>
{ {
(this.state.eventData && (this.state.eventData.EventType !== "0" && this.state.showRecurrenceSeriesInfo !== true)) ? (this.state.eventData && (this.state.eventData.EventType !== "0" && this.state.showRecurrenceSeriesInfo !== true)) ?
<div> <div>
<h2 style={{ display: 'inline-block', verticalAlign: 'top' }}>{ strings.recurrenceEventLabel }</h2> <h2 style={{ display: 'inline-block', verticalAlign: 'top' }}>{strings.recurrenceEventLabel}</h2>
{ this.state.recurrenceDescription ? <span style={{ display: 'block' }} >{ this.state.recurrenceDescription }</span> : null } {this.state.recurrenceDescription ? <span style={{ display: 'block' }} >{this.state.recurrenceDescription}</span> : null}
<DefaultButton <DefaultButton
style={{ display: 'inline-block', marginLeft: '330px', verticalAlign: 'top', width: 'auto' }} style={{ display: 'inline-block', marginLeft: '330px', verticalAlign: 'top', width: 'auto' }}
iconProps={{ iconName: 'RecurringEvent' }} iconProps={{ iconName: 'RecurringEvent' }}
allowDisabledFocus={true} allowDisabledFocus={true}
onClick={this.onEditRecurrence} onClick={this.onEditRecurrence}
> >
{ strings.editRecurrenceSeries } {strings.editRecurrenceSeries}
</DefaultButton> </DefaultButton>
</div> </div>
: '' : ''
@ -948,62 +948,66 @@ export class Event extends React.Component<IEventProps, IEventState> {
hidden={this.state.showRecurrenceSeriesInfo} hidden={this.state.showRecurrenceSeriesInfo}
/> />
</div> </div>
<div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}> {!this.state.isAllDayEvent &&
<Dropdown <div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}>
selectedKey={this.state.startSelectedHour.key} <Dropdown
onChange={this.onStartChangeHour} selectedKey={this.state.startSelectedHour.key}
label={strings.StartHourLabel} onChange={this.onStartChangeHour}
disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true} label={strings.StartHourLabel}
options={[ disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true}
{ key: '00', text: '00' }, options={[
{ key: '01', text: '01' }, { key: '00', text: '00' },
{ key: '02', text: '02' }, { key: '01', text: '01' },
{ key: '03', text: '03' }, { key: '02', text: '02' },
{ key: '04', text: '04' }, { key: '03', text: '03' },
{ key: '05', text: '05' }, { key: '04', text: '04' },
{ key: '06', text: '06' }, { key: '05', text: '05' },
{ key: '07', text: '07' }, { key: '06', text: '06' },
{ key: '08', text: '08' }, { key: '07', text: '07' },
{ key: '09', text: '09' }, { key: '08', text: '08' },
{ key: '10', text: '10' }, { key: '09', text: '09' },
{ key: '11', text: '11' }, { key: '10', text: '10' },
{ key: '12', text: '12' }, { key: '11', text: '11' },
{ key: '13', text: '13' }, { key: '12', text: '12' },
{ key: '14', text: '14' }, { key: '13', text: '13' },
{ key: '15', text: '15' }, { key: '14', text: '14' },
{ key: '16', text: '16' }, { key: '15', text: '15' },
{ key: '17', text: '17' }, { key: '16', text: '16' },
{ key: '18', text: '18' }, { key: '17', text: '17' },
{ key: '19', text: '19' }, { key: '18', text: '18' },
{ key: '20', text: '20' }, { key: '19', text: '19' },
{ key: '21', text: '21' }, { key: '20', text: '20' },
{ key: '22', text: '22' }, { key: '21', text: '21' },
{ key: '23', text: '23' } { key: '22', text: '22' },
]} { key: '23', text: '23' }
/> ]}
</div> />
<div style={{ display: 'inline-block', verticalAlign: 'top', }}> </div>
<Dropdown }
label={strings.StartMinLabel} {!this.state.isAllDayEvent &&
selectedKey={this.state.startSelectedMin.key} <div style={{ display: 'inline-block', verticalAlign: 'top', }}>
onChange={this.onStartChangeMin} <Dropdown
disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true} label={strings.StartMinLabel}
options={[ selectedKey={this.state.startSelectedMin.key}
{ key: '00', text: '00' }, onChange={this.onStartChangeMin}
{ key: '05', text: '05' }, disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true}
{ key: '10', text: '10' }, options={[
{ key: '15', text: '15' }, { key: '00', text: '00' },
{ key: '20', text: '20' }, { key: '05', text: '05' },
{ key: '25', text: '25' }, { key: '10', text: '10' },
{ key: '30', text: '30' }, { key: '15', text: '15' },
{ key: '35', text: '35' }, { key: '20', text: '20' },
{ key: '40', text: '40' }, { key: '25', text: '25' },
{ key: '45', text: '45' }, { key: '30', text: '30' },
{ key: '50', text: '50' }, { key: '35', text: '35' },
{ key: '55', text: '55' } { key: '40', text: '40' },
]} { key: '45', text: '45' },
/> { key: '50', text: '50' },
</div> { key: '55', text: '55' }
]}
/>
</div>
}
<br /> <br />
<div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}> <div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}>
<DatePicker <DatePicker
@ -1020,75 +1024,94 @@ export class Event extends React.Component<IEventProps, IEventState> {
hidden={this.state.showRecurrenceSeriesInfo} hidden={this.state.showRecurrenceSeriesInfo}
/> />
</div> </div>
<div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}> {!this.state.isAllDayEvent &&
<Dropdown <div style={{ display: 'inline-block', verticalAlign: 'top', paddingRight: 10 }}>
selectedKey={this.state.endSelectedHour.key} <Dropdown
onChange={this.onEndChangeHour} selectedKey={this.state.endSelectedHour.key}
label={strings.EndHourLabel} onChange={this.onEndChangeHour}
disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true} label={strings.EndHourLabel}
options={[ disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true}
{ key: '00', text: '00' }, options={[
{ key: '01', text: '01' }, { key: '00', text: '00' },
{ key: '02', text: '02' }, { key: '01', text: '01' },
{ key: '03', text: '03' }, { key: '02', text: '02' },
{ key: '04', text: '04' }, { key: '03', text: '03' },
{ key: '05', text: '05' }, { key: '04', text: '04' },
{ key: '06', text: '06' }, { key: '05', text: '05' },
{ key: '07', text: '07' }, { key: '06', text: '06' },
{ key: '08', text: '08' }, { key: '07', text: '07' },
{ key: '09', text: '09' }, { key: '08', text: '08' },
{ key: '10', text: '10' }, { key: '09', text: '09' },
{ key: '11', text: '11' }, { key: '10', text: '10' },
{ key: '12', text: '12' }, { key: '11', text: '11' },
{ key: '13', text: '13' }, { key: '12', text: '12' },
{ key: '14', text: '14' }, { key: '13', text: '13' },
{ key: '15', text: '15' }, { key: '14', text: '14' },
{ key: '16', text: '16' }, { key: '15', text: '15' },
{ key: '17', text: '17' }, { key: '16', text: '16' },
{ key: '18', text: '18' }, { key: '17', text: '17' },
{ key: '19', text: '19' }, { key: '18', text: '18' },
{ key: '20', text: '20' }, { key: '19', text: '19' },
{ key: '21', text: '21' }, { key: '20', text: '20' },
{ key: '22', text: '22' }, { key: '21', text: '21' },
{ key: '23', text: '23' } { key: '22', text: '22' },
]} { key: '23', text: '23' }
/> ]}
</div> />
<div style={{ display: 'inline-block', verticalAlign: 'top', }}> </div>
<Dropdown }
label={strings.EndMinLabel} {!this.state.isAllDayEvent &&
selectedKey={this.state.endSelectedMin.key} <div style={{ display: 'inline-block', verticalAlign: 'top', }}>
onChange={this.onEndChangeMin} <Dropdown
disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true} label={strings.EndMinLabel}
options={[ selectedKey={this.state.endSelectedMin.key}
{ key: '00', text: '00' }, onChange={this.onEndChangeMin}
{ key: '05', text: '05' }, disabled={this.state.userPermissions.hasPermissionAdd || this.state.userPermissions.hasPermissionEdit ? false : true}
{ key: '10', text: '10' }, options={[
{ key: '15', text: '15' }, { key: '00', text: '00' },
{ key: '20', text: '20' }, { key: '05', text: '05' },
{ key: '25', text: '25' }, { key: '10', text: '10' },
{ key: '30', text: '30' }, { key: '15', text: '15' },
{ key: '35', text: '35' }, { key: '20', text: '20' },
{ key: '40', text: '40' }, { key: '25', text: '25' },
{ key: '45', text: '45' }, { key: '30', text: '30' },
{ key: '50', text: '50' }, { key: '35', text: '35' },
{ key: '55', text: '55' }, { key: '40', text: '40' },
{ key: '59', text: '59' } { key: '45', text: '45' },
]} { key: '50', text: '50' },
/> { key: '55', text: '55' },
</div> { key: '59', text: '59' }
]}
/>
</div>
}
<Label>{this.state.siteRegionalSettings ? this.state.siteRegionalSettings.Description : ''}</Label> <Label>{this.state.siteRegionalSettings ? this.state.siteRegionalSettings.Description : ''}</Label>
<br /> <br />
{
<div style={{ display: 'inline-block', verticalAlign: 'top', width: '200px' }}>
<Toggle
defaultChecked={this.state.eventData && this.state.eventData.fAllDayEvent}
inlineLabel={true}
label={strings.allDayEventLabel}
onText={strings.onLabel}
offText={strings.offLabel}
onChange={(ev, checked: boolean) => {
ev.preventDefault();
this.setState({ isAllDayEvent: checked });
}}
/>
</div>
<br />
{
this.state.eventData && (this.state.eventData.EventType == "0") ? this.state.eventData && (this.state.eventData.EventType == "0") ?
<div style={{ display: 'inline-block', verticalAlign: 'top', width: '200px' }}> <div style={{ display: 'inline-block', verticalAlign: 'top', width: '200px' }}>
<Toggle <Toggle
defaultChecked={false} defaultChecked={false}
inlineLabel={true} inlineLabel={true}
label={ strings.ifRecurrenceLabel } label={strings.ifRecurrenceLabel}
onText={ strings.onLabel } onText={strings.onLabel}
offText={ strings.offLabel } offText={strings.offLabel}
onChange={(ev, checked: boolean) => { onChange={(ev, checked: boolean) => {
ev.preventDefault(); ev.preventDefault();
this.setState({ showRecurrenceSeriesInfo: checked, newRecurrenceEvent: checked }); this.setState({ showRecurrenceSeriesInfo: checked, newRecurrenceEvent: checked });
@ -1109,12 +1132,11 @@ export class Event extends React.Component<IEventProps, IEventState> {
siteUrl={this.props.siteUrl} siteUrl={this.props.siteUrl}
returnRecurrenceData={this.returnRecurrenceInfo} returnRecurrenceData={this.returnRecurrenceInfo}
> >
</EventRecurrenceInfo> </EventRecurrenceInfo>
) )
} }
< Label > {strings.eventDescriptionLabel }</Label> <Label>{strings.eventDescriptionLabel}</Label>
<div className={styles.description}> <div className={styles.description}>
<Editor <Editor
@ -1125,7 +1147,6 @@ export class Event extends React.Component<IEventProps, IEventState> {
</div> </div>
<div> <div>
<PeoplePicker <PeoplePicker
webAbsoluteUrl={this.props.siteUrl} webAbsoluteUrl={this.props.siteUrl}
context={this.props.context} context={this.props.context}
titleText={strings.AttendeesLabel} titleText={strings.AttendeesLabel}

View File

@ -1,25 +1,25 @@
export interface IEventData { export interface IEventData {
Id?:number; Id?: number;
ID?:number; ID?: number;
title: string; title: string;
Description?: any; Description?: any;
location?:string; location?: string;
EventDate: Date; EventDate: Date;
EndDate: Date; EndDate: Date;
color?:string; color?: string;
ownerInitial?: string; ownerInitial?: string;
ownerPhoto?:string; ownerPhoto?: string;
ownerEmail?:string; ownerEmail?: string;
ownerName?:string; ownerName?: string;
fAllDayEvent?: boolean; fAllDayEvent?: boolean;
attendes?: number[]; attendes?: number[];
geolocation?: {Longitude:number, Latitude: number}; geolocation?: { Longitude: number, Latitude: number };
Category?: string; Category?: string;
Duration?: number; Duration?: number;
RecurrenceData?:string; RecurrenceData?: string;
fRecurrence?:string | boolean; fRecurrence?: string | boolean;
EventType?:string; EventType?: string;
UID?:string; UID?: string;
RecurrenceID?: string; RecurrenceID?: string;
MasterSeriesItemID?: string; MasterSeriesItemID?: string;
} }

View File

@ -76,7 +76,6 @@ export default class spservices {
let results = null; let results = null;
try { try {
const web = new Web(siteUrl); const web = new Web(siteUrl);
const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl); const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl);
results = await web.lists.getById(listId).items.add({ results = await web.lists.getById(listId).items.add({
@ -87,7 +86,7 @@ export default class spservices {
EventDate: new Date(moment(newEvent.EventDate).add(siteTimeZoneHours, 'hours').toISOString()), EventDate: new Date(moment(newEvent.EventDate).add(siteTimeZoneHours, 'hours').toISOString()),
EndDate: new Date(moment(newEvent.EndDate).add(siteTimeZoneHours, 'hours').toISOString()), EndDate: new Date(moment(newEvent.EndDate).add(siteTimeZoneHours, 'hours').toISOString()),
Location: newEvent.location, Location: newEvent.location,
fAllDayEvent: false, fAllDayEvent: newEvent.fAllDayEvent,
fRecurrence: newEvent.fRecurrence, fRecurrence: newEvent.fRecurrence,
Category: newEvent.Category, Category: newEvent.Category,
EventType: newEvent.EventType, EventType: newEvent.EventType,
@ -96,7 +95,8 @@ export default class spservices {
MasterSeriesItemID: newEvent.MasterSeriesItemID, MasterSeriesItemID: newEvent.MasterSeriesItemID,
RecurrenceID: newEvent.RecurrenceID ? moment(newEvent.RecurrenceID).add(siteTimeZoneHours, 'hours').toISOString() : undefined, RecurrenceID: newEvent.RecurrenceID ? moment(newEvent.RecurrenceID).add(siteTimeZoneHours, 'hours').toISOString() : undefined,
}); });
} catch (error) { }
catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
return results; return results;
@ -117,13 +117,13 @@ export default class spservices {
try { try {
const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl); const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl);
const web = new Web(siteUrl); const web = new Web(siteUrl);
//"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId" //"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId"
const event = await web.lists.getById(listId).items.usingCaching().getById(eventId) const event = await web.lists.getById(listId).items.usingCaching().getById(eventId)
.select("RecurrenceID", "MasterSeriesItemID", "Id", "ID", "ParticipantsPickerId", "EventType", "Title", "Description", "EventDate", "EndDate", "Location", "Author/SipAddress", "Author/Title", "Geolocation", "fAllDayEvent", "fRecurrence", "RecurrenceData", "RecurrenceData", "Duration", "Category", "UID") .select("RecurrenceID", "MasterSeriesItemID", "Id", "ID", "ParticipantsPickerId", "EventType", "Title", "Description", "EventDate", "EndDate", "Location", "Author/SipAddress", "Author/Title", "Geolocation", "fAllDayEvent", "fRecurrence", "RecurrenceData", "RecurrenceData", "Duration", "Category", "UID")
.expand("Author") .expand("Author")
.get(); .get();
returnEvent = { returnEvent = {
Id: event.ID, Id: event.ID,
ID: event.ID, ID: event.ID,
@ -139,7 +139,7 @@ export default class spservices {
color: '', color: '',
ownerName: event.Author.Title, ownerName: event.Author.Title,
attendes: event.ParticipantsPickerId, attendes: event.ParticipantsPickerId,
fAllDayEvent: false, fAllDayEvent: event.fAllDayEvent,
geolocation: { Longitude: event.Geolocation ? event.Geolocation.Longitude : 0, Latitude: event.Geolocation ? event.Geolocation.Latitude : 0 }, geolocation: { Longitude: event.Geolocation ? event.Geolocation.Longitude : 0, Latitude: event.Geolocation ? event.Geolocation.Latitude : 0 },
Category: event.Category, Category: event.Category,
Duration: event.Duration, Duration: event.Duration,
@ -149,13 +149,13 @@ export default class spservices {
RecurrenceID: event.RecurrenceID, RecurrenceID: event.RecurrenceID,
MasterSeriesItemID: event.MasterSeriesItemID, MasterSeriesItemID: event.MasterSeriesItemID,
}; };
} catch (error) { }
catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
return returnEvent; return returnEvent;
} }
/** /**
* *
* @param {IEventData} newEvent * @param {IEventData} newEvent
@ -167,13 +167,12 @@ export default class spservices {
public async updateEvent(updateEvent: IEventData, siteUrl: string, listId: string) { public async updateEvent(updateEvent: IEventData, siteUrl: string, listId: string) {
let results = null; let results = null;
try { try {
// delete all recursive extentions before update recurrence event
// delete all recursive extentions before update recurrence event
if (updateEvent.EventType.toString() == "1") await this.deleteRecurrenceExceptions(updateEvent, siteUrl, listId); if (updateEvent.EventType.toString() == "1") await this.deleteRecurrenceExceptions(updateEvent, siteUrl, listId);
const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl); const siteTimeZoneHours: number = await this.getSiteTimeZoneHours(siteUrl);
const web = new Web(siteUrl); const web = new Web(siteUrl);
//"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId" //"Title","fRecurrence", "fAllDayEvent","EventDate", "EndDate", "Description","ID", "Location","Geolocation","ParticipantsPickerId"
let newItem: any = { let newItem: any = {
Title: updateEvent.title, Title: updateEvent.title,
@ -183,12 +182,13 @@ export default class spservices {
EventDate: new Date(moment(updateEvent.EventDate).add(siteTimeZoneHours, 'hours').toISOString()), EventDate: new Date(moment(updateEvent.EventDate).add(siteTimeZoneHours, 'hours').toISOString()),
EndDate: new Date(moment(updateEvent.EndDate).add(siteTimeZoneHours, 'hours').toISOString()), EndDate: new Date(moment(updateEvent.EndDate).add(siteTimeZoneHours, 'hours').toISOString()),
Location: updateEvent.location, Location: updateEvent.location,
fAllDayEvent: false, fAllDayEvent: updateEvent.fAllDayEvent,
fRecurrence: updateEvent.fRecurrence, fRecurrence: updateEvent.fRecurrence,
Category: updateEvent.Category, Category: updateEvent.Category,
RecurrenceData: updateEvent.RecurrenceData ? await this.deCodeHtmlEntities(updateEvent.RecurrenceData) : "", RecurrenceData: updateEvent.RecurrenceData ? await this.deCodeHtmlEntities(updateEvent.RecurrenceData) : "",
EventType: updateEvent.EventType, EventType: updateEvent.EventType,
}; };
if (updateEvent.UID) { if (updateEvent.UID) {
newItem.UID = updateEvent.UID; newItem.UID = updateEvent.UID;
} }
@ -197,7 +197,8 @@ export default class spservices {
} }
results = await web.lists.getById(listId).items.getById(updateEvent.Id).update(newItem); results = await web.lists.getById(listId).items.getById(updateEvent.Id).update(newItem);
} catch (error) { }
catch (error) {
return Promise.reject(error); return Promise.reject(error);
} }
return results; return results;
@ -489,6 +490,7 @@ export default class spservices {
if (results && results.Row.length > 0) { if (results && results.Row.length > 0) {
let event: any = ''; let event: any = '';
for (event of results.Row) { for (event of results.Row) {
const initialsArray: string[] = event.Author[0].title.split(' '); const initialsArray: string[] = event.Author[0].title.split(' ');
const initials: string = initialsArray[0].charAt(0) + initialsArray[initialsArray.length - 1].charAt(0); const initials: string = initialsArray[0].charAt(0) + initialsArray[initialsArray.length - 1].charAt(0);
@ -501,22 +503,20 @@ export default class spservices {
const CategoryColorValue: any[] = categoryColor.filter((value) => { const CategoryColorValue: any[] = categoryColor.filter((value) => {
return value.category == event.Category; return value.category == event.Category;
}); });
const isAllDayEvent: boolean = event.fAllDayEvent === "Yes";
for (const attendee of event.ParticipantsPicker) { for (const attendee of event.ParticipantsPicker) {
attendees.push(parseInt(attendee.id)); attendees.push(parseInt(attendee.id));
} }
events.push({ events.push({
Id: event.ID, Id: event.ID,
ID: event.ID, ID: event.ID,
EventType: event.EventType, EventType: event.EventType,
title: await this.deCodeHtmlEntities(event.Title), title: await this.deCodeHtmlEntities(event.Title),
Description: event.Description, Description: event.Description,
EventDate: isAllDayEvent ? new Date(moment(event.EventDate).toISOString()) : new Date(moment(event.EventDate).subtract((siteTimeZoneHours), 'hour').toISOString()),
EventDate: new Date(moment(event.EventDate).subtract((siteTimeZoneHours), 'hour').toISOString()), EndDate: isAllDayEvent ? new Date(moment(event.EndDate).toISOString()) : new Date(moment(event.EndDate).subtract(siteTimeZoneHours, 'hour').toISOString()),
EndDate: new Date(moment(event.EndDate).subtract(siteTimeZoneHours, 'hour').toISOString()),
location: event.Location, location: event.Location,
ownerEmail: event.Author[0].email, ownerEmail: event.Author[0].email,
ownerPhoto: userPictureUrl ? ownerPhoto: userPictureUrl ?
@ -525,7 +525,7 @@ export default class spservices {
color: CategoryColorValue.length > 0 ? CategoryColorValue[0].color : '#1a75ff', // blue default color: CategoryColorValue.length > 0 ? CategoryColorValue[0].color : '#1a75ff', // blue default
ownerName: event.Author[0].title, ownerName: event.Author[0].title,
attendes: attendees, attendes: attendees,
fAllDayEvent: false, fAllDayEvent: isAllDayEvent,
geolocation: { Longitude: parseFloat(geolocation[0]), Latitude: parseFloat(geolocation[1]) }, geolocation: { Longitude: parseFloat(geolocation[0]), Latitude: parseFloat(geolocation[1]) },
Category: event.Category, Category: event.Category,
Duration: event.Duration, Duration: event.Duration,
@ -540,6 +540,7 @@ export default class spservices {
let parseEvt: parseRecurrentEvent = new parseRecurrentEvent(); let parseEvt: parseRecurrentEvent = new parseRecurrentEvent();
events = parseEvt.parseEvents(events, null, null); events = parseEvt.parseEvents(events, null, null);
} }
// Return Data // Return Data
return events; return events;
} catch (error) { } catch (error) {

View File

@ -114,6 +114,7 @@ define([], function () {
showMore: "more", showMore: "more",
recurrenceEventLabel: "Recurrence Event", recurrenceEventLabel: "Recurrence Event",
editRecurrenceSeries: "Edit Recurrence Series", editRecurrenceSeries: "Edit Recurrence Series",
allDayEventLabel: "All Day Event ?",
ifRecurrenceLabel: "Recurrence ?", ifRecurrenceLabel: "Recurrence ?",
onLabel: "On", onLabel: "On",
offLabel: "Off", offLabel: "Off",

View File

@ -114,6 +114,7 @@ declare interface ICalendarWebPartStrings {
showMore: string; showMore: string;
recurrenceEventLabel: string; recurrenceEventLabel: string;
editRecurrenceSeries: string; editRecurrenceSeries: string;
allDayEventLabel: string;
ifRecurrenceLabel: string; ifRecurrenceLabel: string;
onLabel: string; onLabel: string;
offLabel: string; offLabel: string;

View File

@ -114,6 +114,7 @@ define([], function () {
showMore: "mer", showMore: "mer",
recurrenceEventLabel: "Återkommande händelse", recurrenceEventLabel: "Återkommande händelse",
editRecurrenceSeries: "Redigera serie", editRecurrenceSeries: "Redigera serie",
allDayEventLabel: "All Day Event ?",
ifRecurrenceLabel: "Återkommande ?", ifRecurrenceLabel: "Återkommande ?",
onLabel: "På", onLabel: "På",
offLabel: "Av", offLabel: "Av",