React-Calendar Update (#864)

* commit first

* Update README.md

* Update README.md

* first commit

* Change Docs

* Update README.md

* Update README.md

* Update Calendar Web Part

* Update README.md

* Update README.md

* Update Docs

* Update - Suport Create Event in SiteTimeZone

* update Docs

* update docs

* Update comments

* upd default start/end dates on prop panel

* update Prop

* upd default props panel

* upd comments

* code fix for title special characters

* Update Version

* upd to usereffectivebasepermissions to check perm

* commit changes

* commit changes

* commit changes

* Commit changes
This commit is contained in:
joaojmendes 2019-05-13 17:12:21 +01:00 committed by Vesa Juvonen
parent 3137501e4f
commit ef0fffe82f
5 changed files with 583 additions and 53 deletions

View File

@ -1,6 +1,6 @@
{
"name": "react-calendar",
"version": "0.0.1",
"version": "1.0.0",
"private": true,
"engines": {
"node": ">=0.10.0"

View File

@ -167,7 +167,6 @@ export class Event extends React.Component<IEventProps, IEventState> {
const end = moment(endDateTime, 'YYYY/MM/DD HH:mm').toLocaleString();
eventData.end = new Date(end);
debugger;
// get Geolocation
eventData.geolocation = { Latitude: this.latitude, Longitude: this.longitude };

View File

@ -13,7 +13,7 @@ import * as moment from 'moment';
import { SiteUser } from "@pnp/sp/src/siteusers";
import { IUserPermissions } from './IUserPermissions';
import { dateAdd } from "@pnp/common";
import { escape } from '@microsoft/sp-lodash-subset';
const ADMIN_ROLETEMPLATE_ID = "62e90394-69f5-4237-9190-012177145e10"; // Global Admin TemplateRoleId
// Class Services
@ -60,7 +60,12 @@ export default class spservices {
siteTimeZoneDaylightBias = siteRegionalSettings.Information.DaylightBias;
// Formula to calculate the number of hours need to get UTC Date.
numberHours = (siteTimeZoneBias / 60) + (siteTimeZoneDaylightBias / 60) - currentDateTimeOffSet;
// numberHours = (siteTimeZoneBias / 60) + (siteTimeZoneDaylightBias / 60) - currentDateTimeOffSet;
if ( siteTimeZoneBias >= 0 ){
numberHours = ((siteTimeZoneBias / 60) - currentDateTimeOffSet) + siteTimeZoneDaylightBias/60 ;
}else {
numberHours = ((siteTimeZoneBias / 60) - currentDateTimeOffSet) ;
}
}
catch (error) {
return Promise.reject(error);
@ -235,11 +240,13 @@ export default class spservices {
let userPermissions: IUserPermissions = undefined;
try {
const web = new Web(siteUrl);
hasPermissionAdd = await web.lists.getById(listId).currentUserHasPermissions(PermissionKind.AddListItems);
hasPermissionEdit = await web.lists.getById(listId).currentUserHasPermissions(PermissionKind.EditListItems);
hasPermissionDelete = await web.lists.getById(listId).currentUserHasPermissions(PermissionKind.DeleteListItems);
hasPermissionView = await web.lists.getById(listId).currentUserHasPermissions(PermissionKind.ViewListItems);
userPermissions = { hasPermissionAdd: hasPermissionAdd, hasPermissionEdit: hasPermissionEdit, hasPermissionDelete: hasPermissionDelete, hasPermissionView: hasPermissionView };
const userEffectivePermissions = await web.lists.getById(listId).effectiveBasePermissions.get();
// chaeck user permissions
hasPermissionAdd = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.AddListItems);
hasPermissionEdit =sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.EditListItems);
hasPermissionDelete =sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.DeleteListItems);
hasPermissionView = sp.web.lists.getById(listId).hasPermissions(userEffectivePermissions, PermissionKind.ViewListItems);
userPermissions = { hasPermissionAdd: hasPermissionAdd, hasPermissionEdit: hasPermissionEdit, hasPermissionDelete: hasPermissionDelete, hasPermissionView: hasPermissionView };
} catch (error) {
return Promise.reject(error);
}
@ -375,46 +382,46 @@ export default class spservices {
}
);
if (results && results.Row.length > 0) {
for (const event of results.Row) {
const initialsArray: string[] = event.Author[0].title.split(' ');
const initials: string = initialsArray[0].charAt(0) + initialsArray[initialsArray.length - 1].charAt(0);
const userPictureUrl = await this.getUserProfilePictureUrl(`i:0#.f|membership|${event.Author[0].email}`);
const attendees: number[] = [];
const first: number = event.Geolocation.indexOf('(') + 1;
const last: number = event.Geolocation.indexOf(')');
const geo = event.Geolocation.substring(first, last);
const geolocation = geo.split(' ');
const CategoryColorValue: any[] = categoryColor.filter((value) => {
return value.category == event.Category;
});
for (const attendee of event.ParticipantsPicker) {
attendees.push(parseInt(attendee.id));
}
events.push({
id: event.ID,
title: event.Title,
Description: event.Description,
// start: moment(event.EventDate).utc().toDate().setUTCMinutes(this.siteTimeZoneOffSet),
start: new Date(moment(event.EventDate).subtract(siteTimeZoneHoursToUTC, 'hour').toISOString()),
// end: new Date(moment(event.EndDate).toLocaleString()),
end: new Date(moment(event.EndDate).subtract(siteTimeZoneHoursToUTC, 'hour').toISOString()),
location: event.Location,
ownerEmail: event.Author[0].email,
ownerPhoto: userPictureUrl ?
`https://outlook.office365.com/owa/service.svc/s/GetPersonaPhoto?email=${event.Author[0].email}&UA=0&size=HR96x96` : '',
ownerInitial: initials,
// color: await this.colorGenerate(),
color: CategoryColorValue.length > 0 ? CategoryColorValue[0].color : await this.colorGenerate,
ownerName: event.Author[0].title,
attendes: attendees,
allDayEvent: false,
geolocation: { Longitude: parseFloat(geolocation[0]), Latitude: parseFloat(geolocation[1]) },
Category: event.Category
});
}
if (results && results.Row.length > 0) {
for (const event of results.Row) {
const initialsArray: string[] = event.Author[0].title.split(' ');
const initials: string = initialsArray[0].charAt(0) + initialsArray[initialsArray.length - 1].charAt(0);
const userPictureUrl = await this.getUserProfilePictureUrl(`i:0#.f|membership|${event.Author[0].email}`);
const attendees: number[] = [];
const first: number = event.Geolocation.indexOf('(') + 1;
const last: number = event.Geolocation.indexOf(')');
const geo = event.Geolocation.substring(first, last);
const geolocation = geo.split(' ');
const CategoryColorValue: any[] = categoryColor.filter((value) => {
return value.category == event.Category;
});
for (const attendee of event.ParticipantsPicker) {
attendees.push(parseInt(attendee.id));
}
events.push({
id: event.ID,
title: await this.deCodeHtmlEntities(event.Title),
Description: event.Description,
// start: moment(event.EventDate).utc().toDate().setUTCMinutes(this.siteTimeZoneOffSet),
start: new Date(moment(event.EventDate).subtract((siteTimeZoneHoursToUTC), 'hour').toISOString()),
// end: new Date(moment(event.EndDate).toLocaleString()),
end: new Date(moment(event.EndDate).subtract(siteTimeZoneHoursToUTC, 'hour').toISOString()),
location: event.Location,
ownerEmail: event.Author[0].email,
ownerPhoto: userPictureUrl ?
`https://outlook.office365.com/owa/service.svc/s/GetPersonaPhoto?email=${event.Author[0].email}&UA=0&size=HR96x96` : '',
ownerInitial: initials,
// color: await this.colorGenerate(),
color: CategoryColorValue.length > 0 ? CategoryColorValue[0].color : await this.colorGenerate,
ownerName: event.Author[0].title,
attendes: attendees,
allDayEvent: false,
geolocation: { Longitude: parseFloat(geolocation[0]), Latitude: parseFloat(geolocation[1]) },
Category: event.Category
});
}
}
// Return Data
return events;
} catch (error) {
@ -467,4 +474,525 @@ export default class spservices {
return Promise.reject(error);
}
}
public async enCodeHtmlEntities(string: string) {
const HtmlEntitiesMap = {
"'": "&apos;",
"<": "&lt;",
">": "&gt;",
" ": "&nbsp;",
"¡": "&iexcl;",
"¢": "&cent;",
"£": "&pound;",
"¤": "&curren;",
"¥": "&yen;",
"¦": "&brvbar;",
"§": "&sect;",
"¨": "&uml;",
"©": "&copy;",
"ª": "&ordf;",
"«": "&laquo;",
"¬": "&not;",
"®": "&reg;",
"¯": "&macr;",
"°": "&deg;",
"±": "&plusmn;",
"²": "&sup2;",
"³": "&sup3;",
"´": "&acute;",
"µ": "&micro;",
"¶": "&para;",
"·": "&middot;",
"¸": "&cedil;",
"¹": "&sup1;",
"º": "&ordm;",
"»": "&raquo;",
"¼": "&frac14;",
"½": "&frac12;",
"¾": "&frac34;",
"¿": "&iquest;",
"À": "&Agrave;",
"Á": "&Aacute;",
"Â": "&Acirc;",
"Ã": "&Atilde;",
"Ä": "&Auml;",
"Å": "&Aring;",
"Æ": "&AElig;",
"Ç": "&Ccedil;",
"È": "&Egrave;",
"É": "&Eacute;",
"Ê": "&Ecirc;",
"Ë": "&Euml;",
"Ì": "&Igrave;",
"Í": "&Iacute;",
"Î": "&Icirc;",
"Ï": "&Iuml;",
"Ð": "&ETH;",
"Ñ": "&Ntilde;",
"Ò": "&Ograve;",
"Ó": "&Oacute;",
"Ô": "&Ocirc;",
"Õ": "&Otilde;",
"Ö": "&Ouml;",
"×": "&times;",
"Ø": "&Oslash;",
"Ù": "&Ugrave;",
"Ú": "&Uacute;",
"Û": "&Ucirc;",
"Ü": "&Uuml;",
"Ý": "&Yacute;",
"Þ": "&THORN;",
"ß": "&szlig;",
"à": "&agrave;",
"á": "&aacute;",
"â": "&acirc;",
"ã": "&atilde;",
"ä": "&auml;",
"å": "&aring;",
"æ": "&aelig;",
"ç": "&ccedil;",
"è": "&egrave;",
"é": "&eacute;",
"ê": "&ecirc;",
"ë": "&euml;",
"ì": "&igrave;",
"í": "&iacute;",
"î": "&icirc;",
"ï": "&iuml;",
"ð": "&eth;",
"ñ": "&ntilde;",
"ò": "&ograve;",
"ó": "&oacute;",
"ô": "&ocirc;",
"õ": "&otilde;",
"ö": "&ouml;",
"÷": "&divide;",
"ø": "&oslash;",
"ù": "&ugrave;",
"ú": "&uacute;",
"û": "&ucirc;",
"ü": "&uuml;",
"ý": "&yacute;",
"þ": "&thorn;",
"ÿ": "&yuml;",
"Œ": "&OElig;",
"œ": "&oelig;",
"Š": "&Scaron;",
"š": "&scaron;",
"Ÿ": "&Yuml;",
"ƒ": "&fnof;",
"ˆ": "&circ;",
"˜": "&tilde;",
"Α": "&Alpha;",
"Β": "&Beta;",
"Γ": "&Gamma;",
"Δ": "&Delta;",
"Ε": "&Epsilon;",
"Ζ": "&Zeta;",
"Η": "&Eta;",
"Θ": "&Theta;",
"Ι": "&Iota;",
"Κ": "&Kappa;",
"Λ": "&Lambda;",
"Μ": "&Mu;",
"Ν": "&Nu;",
"Ξ": "&Xi;",
"Ο": "&Omicron;",
"Π": "&Pi;",
"Ρ": "&Rho;",
"Σ": "&Sigma;",
"Τ": "&Tau;",
"Υ": "&Upsilon;",
"Φ": "&Phi;",
"Χ": "&Chi;",
"Ψ": "&Psi;",
"Ω": "&Omega;",
"α": "&alpha;",
"β": "&beta;",
"γ": "&gamma;",
"δ": "&delta;",
"ε": "&epsilon;",
"ζ": "&zeta;",
"η": "&eta;",
"θ": "&theta;",
"ι": "&iota;",
"κ": "&kappa;",
"λ": "&lambda;",
"μ": "&mu;",
"ν": "&nu;",
"ξ": "&xi;",
"ο": "&omicron;",
"π": "&pi;",
"ρ": "&rho;",
"ς": "&sigmaf;",
"σ": "&sigma;",
"τ": "&tau;",
"υ": "&upsilon;",
"φ": "&phi;",
"χ": "&chi;",
"ψ": "&psi;",
"ω": "&omega;",
"ϑ": "&thetasym;",
"ϒ": "&Upsih;",
"ϖ": "&piv;",
"": "&ndash;",
"—": "&mdash;",
"": "&lsquo;",
"": "&rsquo;",
"": "&sbquo;",
"“": "&ldquo;",
"”": "&rdquo;",
"„": "&bdquo;",
"†": "&dagger;",
"‡": "&Dagger;",
"•": "&bull;",
"…": "&hellip;",
"‰": "&permil;",
"": "&prime;",
"″": "&Prime;",
"": "&lsaquo;",
"": "&rsaquo;",
"‾": "&oline;",
"": "&frasl;",
"€": "&euro;",
"": "&image;",
"℘": "&weierp;",
"": "&real;",
"™": "&trade;",
"ℵ": "&alefsym;",
"←": "&larr;",
"↑": "&uarr;",
"→": "&rarr;",
"↓": "&darr;",
"↔": "&harr;",
"↵": "&crarr;",
"⇐": "&lArr;",
"⇑": "&UArr;",
"⇒": "&rArr;",
"⇓": "&dArr;",
"⇔": "&hArr;",
"∀": "&forall;",
"∂": "&part;",
"∃": "&exist;",
"∅": "&empty;",
"∇": "&nabla;",
"∈": "&isin;",
"∉": "&notin;",
"∋": "&ni;",
"∏": "&prod;",
"∑": "&sum;",
"": "&minus;",
"": "&lowast;",
"√": "&radic;",
"∝": "&prop;",
"∞": "&infin;",
"∠": "&ang;",
"∧": "&and;",
"": "&or;",
"∩": "&cap;",
"": "&cup;",
"∫": "&int;",
"∴": "&there4;",
"": "&sim;",
"≅": "&cong;",
"≈": "&asymp;",
"≠": "&ne;",
"≡": "&equiv;",
"≤": "&le;",
"≥": "&ge;",
"⊂": "&sub;",
"⊃": "&sup;",
"⊄": "&nsub;",
"⊆": "&sube;",
"⊇": "&supe;",
"⊕": "&oplus;",
"⊗": "&otimes;",
"⊥": "&perp;",
"⋅": "&sdot;",
"⌈": "&lceil;",
"⌉": "&rceil;",
"⌊": "&lfloor;",
"⌋": "&rfloor;",
"⟨": "&lang;",
"⟩": "&rang;",
"◊": "&loz;",
"♠": "&spades;",
"♣": "&clubs;",
"♥": "&hearts;",
"♦": "&diams;"
};
var entityMap = HtmlEntitiesMap;
string = string.replace(/&/g, '&amp;');
string = string.replace(/"/g, '&quot;');
for (var key in entityMap) {
var entity = entityMap[key];
var regex = new RegExp(key, 'g');
string = string.replace(regex, entity);
}
return string;
}
public async deCodeHtmlEntities(string: string) {
const HtmlEntitiesMap = {
"'": "&#39;",
"<": "&lt;",
">": "&gt;",
" ": "&nbsp;",
"¡": "&iexcl;",
"¢": "&cent;",
"£": "&pound;",
"¤": "&curren;",
"¥": "&yen;",
"¦": "&brvbar;",
"§": "&sect;",
"¨": "&uml;",
"©": "&copy;",
"ª": "&ordf;",
"«": "&laquo;",
"¬": "&not;",
"®": "&reg;",
"¯": "&macr;",
"°": "&deg;",
"±": "&plusmn;",
"²": "&sup2;",
"³": "&sup3;",
"´": "&acute;",
"µ": "&micro;",
"¶": "&para;",
"·": "&middot;",
"¸": "&cedil;",
"¹": "&sup1;",
"º": "&ordm;",
"»": "&raquo;",
"¼": "&frac14;",
"½": "&frac12;",
"¾": "&frac34;",
"¿": "&iquest;",
"À": "&Agrave;",
"Á": "&Aacute;",
"Â": "&Acirc;",
"Ã": "&Atilde;",
"Ä": "&Auml;",
"Å": "&Aring;",
"Æ": "&AElig;",
"Ç": "&Ccedil;",
"È": "&Egrave;",
"É": "&Eacute;",
"Ê": "&Ecirc;",
"Ë": "&Euml;",
"Ì": "&Igrave;",
"Í": "&Iacute;",
"Î": "&Icirc;",
"Ï": "&Iuml;",
"Ð": "&ETH;",
"Ñ": "&Ntilde;",
"Ò": "&Ograve;",
"Ó": "&Oacute;",
"Ô": "&Ocirc;",
"Õ": "&Otilde;",
"Ö": "&Ouml;",
"×": "&times;",
"Ø": "&Oslash;",
"Ù": "&Ugrave;",
"Ú": "&Uacute;",
"Û": "&Ucirc;",
"Ü": "&Uuml;",
"Ý": "&Yacute;",
"Þ": "&THORN;",
"ß": "&szlig;",
"à": "&agrave;",
"á": "&aacute;",
"â": "&acirc;",
"ã": "&atilde;",
"ä": "&auml;",
"å": "&aring;",
"æ": "&aelig;",
"ç": "&ccedil;",
"è": "&egrave;",
"é": "&eacute;",
"ê": "&ecirc;",
"ë": "&euml;",
"ì": "&igrave;",
"í": "&iacute;",
"î": "&icirc;",
"ï": "&iuml;",
"ð": "&eth;",
"ñ": "&ntilde;",
"ò": "&ograve;",
"ó": "&oacute;",
"ô": "&ocirc;",
"õ": "&otilde;",
"ö": "&ouml;",
"÷": "&divide;",
"ø": "&oslash;",
"ù": "&ugrave;",
"ú": "&uacute;",
"û": "&ucirc;",
"ü": "&uuml;",
"ý": "&yacute;",
"þ": "&thorn;",
"ÿ": "&yuml;",
"Œ": "&OElig;",
"œ": "&oelig;",
"Š": "&Scaron;",
"š": "&scaron;",
"Ÿ": "&Yuml;",
"ƒ": "&fnof;",
"ˆ": "&circ;",
"˜": "&tilde;",
"Α": "&Alpha;",
"Β": "&Beta;",
"Γ": "&Gamma;",
"Δ": "&Delta;",
"Ε": "&Epsilon;",
"Ζ": "&Zeta;",
"Η": "&Eta;",
"Θ": "&Theta;",
"Ι": "&Iota;",
"Κ": "&Kappa;",
"Λ": "&Lambda;",
"Μ": "&Mu;",
"Ν": "&Nu;",
"Ξ": "&Xi;",
"Ο": "&Omicron;",
"Π": "&Pi;",
"Ρ": "&Rho;",
"Σ": "&Sigma;",
"Τ": "&Tau;",
"Υ": "&Upsilon;",
"Φ": "&Phi;",
"Χ": "&Chi;",
"Ψ": "&Psi;",
"Ω": "&Omega;",
"α": "&alpha;",
"β": "&beta;",
"γ": "&gamma;",
"δ": "&delta;",
"ε": "&epsilon;",
"ζ": "&zeta;",
"η": "&eta;",
"θ": "&theta;",
"ι": "&iota;",
"κ": "&kappa;",
"λ": "&lambda;",
"μ": "&mu;",
"ν": "&nu;",
"ξ": "&xi;",
"ο": "&omicron;",
"π": "&pi;",
"ρ": "&rho;",
"ς": "&sigmaf;",
"σ": "&sigma;",
"τ": "&tau;",
"υ": "&upsilon;",
"φ": "&phi;",
"χ": "&chi;",
"ψ": "&psi;",
"ω": "&omega;",
"ϑ": "&thetasym;",
"ϒ": "&Upsih;",
"ϖ": "&piv;",
"": "&ndash;",
"—": "&mdash;",
"": "&lsquo;",
"": "&rsquo;",
"": "&sbquo;",
"“": "&ldquo;",
"”": "&rdquo;",
"„": "&bdquo;",
"†": "&dagger;",
"‡": "&Dagger;",
"•": "&bull;",
"…": "&hellip;",
"‰": "&permil;",
"": "&prime;",
"″": "&Prime;",
"": "&lsaquo;",
"": "&rsaquo;",
"‾": "&oline;",
"": "&frasl;",
"€": "&euro;",
"": "&image;",
"℘": "&weierp;",
"": "&real;",
"™": "&trade;",
"ℵ": "&alefsym;",
"←": "&larr;",
"↑": "&uarr;",
"→": "&rarr;",
"↓": "&darr;",
"↔": "&harr;",
"↵": "&crarr;",
"⇐": "&lArr;",
"⇑": "&UArr;",
"⇒": "&rArr;",
"⇓": "&dArr;",
"⇔": "&hArr;",
"∀": "&forall;",
"∂": "&part;",
"∃": "&exist;",
"∅": "&empty;",
"∇": "&nabla;",
"∈": "&isin;",
"∉": "&notin;",
"∋": "&ni;",
"∏": "&prod;",
"∑": "&sum;",
"": "&minus;",
"": "&lowast;",
"√": "&radic;",
"∝": "&prop;",
"∞": "&infin;",
"∠": "&ang;",
"∧": "&and;",
"": "&or;",
"∩": "&cap;",
"": "&cup;",
"∫": "&int;",
"∴": "&there4;",
"": "&sim;",
"≅": "&cong;",
"≈": "&asymp;",
"≠": "&ne;",
"≡": "&equiv;",
"≤": "&le;",
"≥": "&ge;",
"⊂": "&sub;",
"⊃": "&sup;",
"⊄": "&nsub;",
"⊆": "&sube;",
"⊇": "&supe;",
"⊕": "&oplus;",
"⊗": "&otimes;",
"⊥": "&perp;",
"⋅": "&sdot;",
"⌈": "&lceil;",
"⌉": "&rceil;",
"⌊": "&lfloor;",
"⌋": "&rfloor;",
"⟨": "&lang;",
"⟩": "&rang;",
"◊": "&loz;",
"♠": "&spades;",
"♣": "&clubs;",
"♥": "&hearts;",
"♦": "&diams;"
};
var entityMap = HtmlEntitiesMap;
for (var key in entityMap) {
var entity = entityMap[key];
var regex = new RegExp(entity, 'g');
string = string.replace(regex, key);
}
string = string.replace(/&quot;/g, '"');
string = string.replace(/&amp;/g, '&');
return string;
}
}

View File

@ -38,10 +38,11 @@
border-style: 'solid';
border-width: 1.3px;
border-color: #e6e6e6;
height: 40px;
height:auto;
justify-content: 'center';
display: 'flex';
align-items: 'top';
}
.eventStyle{
@ -55,12 +56,15 @@
}
.DocumentCardTitle {
font-weight: 'bold';
font-weight: $ms-font-weight-semibold;
height: '100%';
text-overflow: ellipsis;
display: 'flex';
justify-content: 'center';
}
.DocumentCardTitleTime{
padding-top: 10px;
justify-content: 'center';
display: 'flex';
align-items: 'top';

View File

@ -193,7 +193,7 @@ export default class Calendar extends React.Component<ICalendarProps, ICalendarS
</div>
<DocumentCardDetails>
<div className={styles.DocumentCardDetails}>
<DocumentCardTitle title={event.title} shouldTruncate={true} className={styles.DocumentCardTitle} styles={{ root: { color: event.color } }} />
<DocumentCardTitle title={event.title} shouldTruncate={true} className={styles.DocumentCardTitle} styles={{ root: { color: event.color} }} />
</div>
{
@ -202,7 +202,6 @@ export default class Calendar extends React.Component<ICalendarProps, ICalendarS
:
<span className={styles.DocumentCardTitleTime}>{moment(event.start).format('dddd')} </span>
}
<span className={styles.DocumentCardTitleTime}>{moment(event.start).format('HH:mm')}H - {moment(event.end).format('HH:mm')}H</span>
<Icon iconName='MapPin' className={styles.locationIcon} style={{ color: event.color }} />
<DocumentCardTitle