Merge pull request #3076 from petkir/petkir-react-calendar-feed-Upgrade-jszip

react-calendar-feed devDependencies Version Missmatch Upgrade to SPFX 1.15.2
This commit is contained in:
Hugo Bernier 2022-11-08 13:26:15 -05:00 committed by GitHub
commit d5f95c8087
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 46241 additions and 15427 deletions

View File

@ -0,0 +1,5 @@
require('@rushstack/eslint-config/patch/modern-module-resolution');
module.exports = {
extends: ['@microsoft/eslint-config-spfx/lib/profiles/react'],
parserOptions: { tsconfigRootDir: __dirname }
};

View File

@ -30,3 +30,6 @@ obj
# Styles Generated Code
*.scss.ts
.heft
release

View File

View File

@ -4,26 +4,10 @@
* Chrome browser: https://aka.ms/spfx-debugger-extensions
*/
"version": "0.2.0",
"configurations": [{
"name": "Local workbench",
"type": "chrome",
"request": "launch",
"url": "https://localhost:4321/temp/workbench.html",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222"
]
},
"configurations": [
{
"name": "Hosted workbench",
"type": "chrome",
"type": "pwa-chrome",
"request": "launch",
"url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
"webRoot": "${workspaceRoot}",
@ -40,4 +24,4 @@
]
}
]
}
}

View File

@ -2,7 +2,7 @@
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.10.0",
"version": "1.15.0",
"libraryName": "react-calendar-feed",
"libraryId": "25653136-fc83-4abe-b9d2-a4ac041959d5",
"packageManager": "npm",

View File

@ -25,25 +25,31 @@ For more information about how this solution was built, including some design de
## Compatibility
![SPFx 1.10](https://img.shields.io/badge/SPFx-1.10.0-green.svg)
![Node.js v10 | v8](https://img.shields.io/badge/Node.js-v10%20%7C%20v8-green.svg)
This sample is optimally compatible with the following environment configuration:
![SPFx 1.15.2](https://img.shields.io/badge/SPFx-1.15.2-green.svg)
![Node.js v16 | v14 | v12](https://img.shields.io/badge/Node.js-v16%20%7C%20v14%20%7C%20v12-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Local Workbench Partially](https://img.shields.io/badge/Local%20Workbench-Partially-yellow.svg "Some functionality may not work on local workbech")
![Local Workbench Unsupported](https://img.shields.io/badge/Local%20Workbench-Unsupported-red.svg "Local workbench is no longer available as of SPFx 1.13 and above")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
![Compatible with Remote Containers](https://img.shields.io/badge/Remote%20Containers-Compatible-green.svg)
For more information about SPFx compatibility, please refer to <https://aka.ms/spfx-matrix>
## Applies to
- [SharePoint Framework](https://learn.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
- [Microsoft 365 tenant](https://learn.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
> Get your own free development tenant by subscribing to [Microsoft 365 developer program](http://aka.ms/m365devprogram)
## Prerequisites
Before you can use this web part example, you will need one of the following:
- A publicly-accessible iCal feed (i.e.: .ics)
- A publicly-accessible iCal feed (i.e.: `.ics`)
- A publicly-accessible RSS feed of events (e.g.: Google calendar)
- A WordPress WP-FullCalendar feed
- An Exchange Public Calendar
@ -70,6 +76,7 @@ Version|Date|Comments
5.0|August 17, 2019|Converted to SPFx 1.9.1; Refreshed carousel code; Addresses #735, #909. Also added **Convert from UTC** option to handle feeds which do not provide time zone information.
5.1|April 16, 2020|Converted to SPFx 1.10.0; Fixed issue with UTC mode when in narrow view. Updated resizing behavior and styles to match OOB calendar view. Added support for themes and theme variants.
5.2|July 15, 2020|Fixed issue to support IE11
5.3|October 21, 2022|Upgrade to 1.15 Security fixes Removed IE11 Support
## Minimal Path to Awesome
@ -85,7 +92,7 @@ Version|Date|Comments
- Specify a maximum number of events to retrieve
- If necessary, specify to use a proxy. Use this option if you encounter issues where your feed provider does not accept your tenant URL as a CORS origin.
- If desired, specify how long (in minutes) you want to expire your users' local storage and refresh the events.
- Exclude IE11 support with gulp parameter ```--NoIE11``` this is in-case-sensitive
> This sample can also be opened with [VS Code Remote Development](https://code.visualstudio.com/docs/remote/remote-overview). Visit https://aka.ms/spfx-devcontainer for further instructions.

View File

@ -9,7 +9,7 @@
"This web part uses event feeds from various sources and renders events using a look and feel that is consistent with the SharePoint out-of-the-box Group calendar/events web part."
],
"creationDateTime": "2020-07-16",
"updateDateTime": "2020-07-16",
"updateDateTime": "2022-10-22",
"products": [
"SharePoint"
],
@ -20,7 +20,7 @@
},
{
"key": "SPFX-VERSION",
"value": "1.10.0"
"value": "1.15.2"
},
{
"key": "SPFX-SUPPORTSTHEMEVARIANTS",
@ -42,7 +42,7 @@
"authors": [
{
"gitHubAccount": "hugoabernier",
"company": "Tahoe Ninjas",
"company": "Microsoft",
"pictureUrl": "https://github.com/hugoabernier.png",
"name": "Hugo Bernier",
"twitter": "bernierh"

View File

@ -1,4 +0,0 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "temp/deploy"
}

View File

@ -1,7 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./temp/deploy/",
"workingDir": "./release/assets/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "react-calendar-feed",
"accessKey": "<!-- ACCESS KEY -->"
}
}

View File

@ -1,10 +1,37 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"metadata": {
"shortDescription": {
"default": "react-calendar-feed description"
},
"longDescription": {
"default": "react-calendar-feed description"
},
"screenshotPaths": [],
"videoUrl": "",
"categories": []
},
"name": "react-calendar-feed-client-side-solution",
"id": "25653136-fc83-4abe-b9d2-a4ac041959d5",
"version": "5.2.0.0",
"includeClientSideAssets": true
"version": "5.3.0.0",
"includeClientSideAssets": true,
"developer": {
"name": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"websiteUrl": "",
"mpnId": "Undefined-1.15.0"
},
"features": [
{
"title": "react-calendar-feed Feature",
"description": "The feature that activates elements of the react-calendar-feed solution.",
"id": "57a544de-10aa-4e29-91d9-fce0ac688566",
"version": "5.2.0.0"
}
]
},
"paths": {
"zippedPackage": "solution/react-calendar-feed.sppkg"

View File

@ -2,9 +2,6 @@
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://localhost:5432/workbench",
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx",
}

View File

@ -3,9 +3,20 @@
const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
const path = require('path');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
//build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
let needIESupport = true;
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
/*
Only here For documentation
let needIESupport = false;
if (!!process.argv && process.argv.length > 0) {
needIESupport = process.argv.findIndex(item => '--noie11' === item.toLowerCase()) === -1;
}
@ -32,10 +43,10 @@ if (needIESupport) {
additionalConfiguration: (generatedConfiguration) => {
generatedConfiguration.module.rules.push({
test: /\.js$/,
/*
This selector increase the webpack(gulp serve) time 5 times then without
exclude: [/node_modules\/(?!(rss-parser))/],
*/
//
//This selector increase the webpack(gulp serve) time 5 times then without
// exclude: [/node_modules\/(?!(rss-parser))/],
//
include: [
path.resolve(__dirname, "node_modules/rss-parser"),
],
@ -49,5 +60,5 @@ if (needIESupport) {
process.stdout.write(`No IE11 Support is set \n`);
}
*/
build.initialize(gulp);

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +1,50 @@
{
"name": "react-calendar-feed",
"version": "5.2.0",
"version": "5.3.0",
"private": true,
"main": "lib/index.js",
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.10.0",
"@microsoft/sp-lodash-subset": "1.10.0",
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
"@microsoft/sp-property-pane": "1.10.0",
"@microsoft/sp-webpart-base": "1.10.0",
"@microsoft/sp-core-library": "1.15.2",
"@microsoft/sp-lodash-subset": "1.15.2",
"@microsoft/sp-office-ui-fabric-core": "1.15.2",
"@microsoft/sp-property-pane": "1.15.2",
"@microsoft/sp-webpart-base": "1.15.2",
"@pnp/common": "^1.2.8",
"@pnp/logging": "^1.2.8",
"@pnp/odata": "^1.2.8",
"@pnp/sp": "^1.2.8",
"@pnp/spfx-controls-react": "^1.11.0",
"@pnp/spfx-property-controls": "^1.13.1",
"@types/es6-promise": "0.0.33",
"@types/react": "16.8.8",
"@types/react-dom": "16.8.3",
"@types/webpack-env": "1.13.1",
"@pnp/spfx-controls-react": "3.11.0",
"@pnp/spfx-property-controls": "3.10.0",
"feedparser": "^2.2.9",
"ical.js": "^1.3.0",
"ics-js": "^0.10.2",
"moment": "^2.29.2",
"office-ui-fabric-react": "6.189.2",
"react": "16.8.5",
"react-dom": "16.8.5",
"office-ui-fabric-react": "7.185.7",
"react": "16.13.1",
"react-dom": "16.13.1",
"react-slick": "^0.23.2",
"rss-parser": "^3.6.2",
"slick-carousel": "^1.8.1"
},
"resolutions": {
"@types/react": "16.8.8"
"rss-parser": "^3.12.0",
"slick-carousel": "^1.8.1",
"tslib": "2.3.1"
},
"devDependencies": {
"@babel/core": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
"@microsoft/eslint-config-spfx": "1.15.2",
"@microsoft/eslint-plugin-spfx": "1.15.2",
"@microsoft/rush-stack-compiler-4.5": "0.2.2",
"@microsoft/sp-build-web": "1.15.2",
"@microsoft/sp-module-interfaces": "1.10.0",
"@microsoft/sp-tslint-rules": "1.10.0",
"@microsoft/sp-webpart-workbench": "1.12.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"ajv": "~5.2.2",
"babel-loader": "^8.1.0",
"gulp": "~3.9.1",
"webpack": "^4.43.0"
"@microsoft/sp-module-interfaces": "1.15.2",
"@rushstack/eslint-config": "2.5.1",
"@types/react": "16.9.51",
"@types/react-dom": "16.9.8",
"@types/webpack-env": "~1.15.2",
"ajv": "^6.12.5",
"eslint-plugin-react-hooks": "4.3.0",
"gulp": "4.0.2",
"typescript": "4.5.5"
}
}

View File

@ -1,5 +1,3 @@
import { IReadonlyTheme } from '@microsoft/sp-component-base';
export interface IPaginationProps {
currentPage: number;
totalItems: number;

View File

@ -1,4 +1,4 @@
import { ActionButton, IButtonProps } from "office-ui-fabric-react/lib/Button";
import { ActionButton } from "office-ui-fabric-react/lib/Button";
import { Icon } from "office-ui-fabric-react/lib/Icon";
import { css } from "office-ui-fabric-react/lib/Utilities";
import * as React from "react";
@ -44,7 +44,7 @@ export const Pagination = (props: IPaginationProps) => {
return (
<div className={css(styles.Pagination, props.showPageNum ? null : styles.noPageNum)}>
<ActionButton className={css(styles.prev, prevDisabled && styles.nogo)}
onRenderIcon={(_props: IButtonProps) => {
onRenderIcon={() => {
// we use the render custom icon method to render the icon consistently with the right icon
return (
<Icon iconName="ChevronLeft" />
@ -60,7 +60,7 @@ export const Pagination = (props: IPaginationProps) => {
<ActionButton className={css(styles.next, nextDisabled && styles.nogo)}
data-automation-id="nextPage"
disabled={nextDisabled}
onRenderMenuIcon={(_props: IButtonProps) => {
onRenderMenuIcon={() => {
// we use the render custom menu icon method to render the icon to the right of the text
return (
<Icon iconName="ChevronRight" />

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { css } from '@uifabric/utilities/lib/css';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import * as React from 'react';
@ -19,12 +20,12 @@ export const FilmstripLayout = (props: { children: any; clientWidth: number; the
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick.min.css');
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.8.1/slick-theme.min.css');
let topElem: React.MutableRefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
let _slider: React.MutableRefObject<Slider> = useRef<Slider>(null);
const topElem: React.MutableRefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
const _slider: React.MutableRefObject<Slider> = useRef<Slider>(null);
const [isSmall, isMedium] = useBreakpoints(props.clientWidth, [696, 928]);
let numSlides: number = 3;
let numSlides = 3;
if (isSmall) {
numSlides = 2;
} else if (isMedium) {
@ -33,8 +34,9 @@ export const FilmstripLayout = (props: { children: any; clientWidth: number; the
numSlides = 4;
}
var isInfinite: boolean = React.Children.count(props.children) > numSlides;
var settings: any = {
const isInfinite: boolean = React.Children.count(props.children) > numSlides;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const settings: any = {
accessibility: true,
arrows: false,
autoplaySpeed: 5000,
@ -43,7 +45,7 @@ export const FilmstripLayout = (props: { children: any; clientWidth: number; the
return (
<a>
<div role="button" className={styles.carouselDotsContainer} aria-label={`Carousel Dot ${i}`} data-is-focusable={true} tabIndex={0}>
<span className={styles.carouselDot} tabIndex={-1}></span>
<span className={styles.carouselDot} tabIndex={-1} />
</div>
</a>
);

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { HttpClient, HttpClientResponse } from "@microsoft/sp-http";
import { IWebPartContext } from "@microsoft/sp-webpart-base";
import * as moment from "moment";
@ -111,13 +112,8 @@ export abstract class BaseCalendarService implements ICalendarService {
* @param feedUrl The URL where to retrieve the events
*/
protected async fetchResponseAsJson(feedUrl: string): Promise<any> {
try {
const response = await this.fetchResponse(feedUrl);
return await response.json();
}
catch (error) {
throw error;
}
}
/**

View File

@ -1,10 +1,13 @@
import { MockCalendarService } from "./MockCalendarService";
/* eslint-disable @typescript-eslint/no-explicit-any */
//import { MockCalendarService } from "./MockCalendarService";
import { RSSCalendarService } from "./RSSCalendarService";
import { WordPressFullCalendarService } from "./WordPressFullCalendarService";
import { iCalCalendarService } from "./iCalCalendarService";
import { ExchangePublicCalendarService } from "./ExchangePublicCalendarService";
import { SharePointCalendarService } from "./SharePointCalendarService";
// Localization
import * as strings from "CalendarServicesStrings";
@ -48,13 +51,13 @@ export class CalendarServiceProviderList {
];
// only include the Mock service provider in DEBUG
if (DEBUG) {
/*
providers.push({
label: strings.MockProviderName,
key: CalendarServiceProviderType.Mock,
initialize: () => new MockCalendarService()
});
}
*/
return providers;
}

View File

@ -5,7 +5,7 @@ import { ICalendarService } from "..";
import { ICalendarEvent } from "../ICalendarEvent";
import { iCalCalendarService } from "../iCalCalendarService";
// tslint:disable-next-line:class-name
export class ExchangePublicCalendarService extends iCalCalendarService implements ICalendarService {
constructor() {
super();
@ -17,7 +17,7 @@ export class ExchangePublicCalendarService extends iCalCalendarService implement
// we allow users to pass either the .html URL or
// the .ics, but we really need the .ics file
const htmlExtension:string = ".html";
const htmlExtension = ".html";
if (this.FeedUrl.indexOf(htmlExtension, this.FeedUrl.length - htmlExtension.length) >= 0) {
// the url ends with .html. Replace it with .ics
const root: string = this.FeedUrl.substring(0, this.FeedUrl.length - htmlExtension.length);

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* MockExtensionService
* This provider will NOT be listed in the list of available providers when this solution is packaged with --ship.

View File

@ -9,7 +9,7 @@
import { ICalendarService } from "..";
import { BaseCalendarService } from "../BaseCalendarService";
import { ICalendarEvent } from "../ICalendarEvent";
import RSSParser from 'rss-parser';
import * as RSSParser from 'rss-parser';
export class RSSCalendarService extends BaseCalendarService implements ICalendarService {
constructor() {
@ -20,11 +20,11 @@ export class RSSCalendarService extends BaseCalendarService implements ICalendar
public getEvents = (): Promise<ICalendarEvent[]> => {
const parameterizedFeedUrl: string = this.getCORSUrl(this.replaceTokens(this.FeedUrl, this.EventRange));
let parser = new RSSParser();
const parser = new RSSParser();
return parser.parseURL(parameterizedFeedUrl).then(feed => {
let events: ICalendarEvent[] = feed.items.map(item => {
let pubDate: Date = this.convertToDate(item.isoDate);
const events: ICalendarEvent[] = feed.items.map(item => {
const pubDate: Date = this.convertToDate(item.isoDate);
const eventItem: ICalendarEvent = {
title: item.title,
start: pubDate,

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* ExtensionService
*/
import { HttpClientResponse } from "@microsoft/sp-http";
import { ICalendarService } from "..";
import { BaseCalendarService } from "../BaseCalendarService";
import { ICalendarEvent } from "../ICalendarEvent";
@ -22,28 +23,28 @@ export class SharePointCalendarService extends BaseCalendarService
);
// Get the URL
let webUrl = parameterizedFeedUrl.toLowerCase();
const webUrl = parameterizedFeedUrl.toLowerCase();
// Break the URL into parts
let urlParts = webUrl.split("/");
const urlParts = webUrl.split("/");
// Get the web root
let webRoot = urlParts[0] + "/" + urlParts[1] + "/" + urlParts[2];
const webRoot = urlParts[0] + "/" + urlParts[1] + "/" + urlParts[2];
// Get the list URL
let listUrl = webUrl.substring(webRoot.length);
const listUrl = webUrl.substring(webRoot.length);
// Find the "lists" portion of the URL to get the site URL
let webLocation = listUrl.substr(0, listUrl.indexOf("lists/"));
let siteUrl = webRoot + webLocation;
const webLocation = listUrl.substr(0, listUrl.indexOf("lists/"));
const siteUrl = webRoot + webLocation;
// Open the web associated to the site
let web = new Web(siteUrl);
const web = new Web(siteUrl);
// Get the web
await web.get();
// Build a filter so that we don't retrieve every single thing unless necesssary
let dateFilter: string = "EventDate ge datetime'" + this.EventRange.Start.toISOString() + "' and EndDate lt datetime'" + this.EventRange.End.toISOString() + "'";
const dateFilter: string = "EventDate ge datetime'" + this.EventRange.Start.toISOString() + "' and EndDate lt datetime'" + this.EventRange.End.toISOString() + "'";
try {
const items = await web.getList(listUrl)
.items.select("Id,Title,Description,EventDate,EndDate,fAllDayEvent,Category,Location")
@ -51,8 +52,8 @@ export class SharePointCalendarService extends BaseCalendarService
.filter(dateFilter)
.get();
// Once we get the list, convert to calendar events
let events: ICalendarEvent[] = items.map((item: any) => {
let eventUrl: string = combine(webUrl, "DispForm.aspx?ID=" + item.Id);
const events: ICalendarEvent[] = items.map((item: any) => {
const eventUrl: string = combine(webUrl, "DispForm.aspx?ID=" + item.Id);
const eventItem: ICalendarEvent = {
title: item.Title,
start: item.EventDate,

View File

@ -17,7 +17,7 @@ export class WordPressFullCalendarService extends BaseCalendarService implements
try {
const data = await this.fetchResponseAsJson(parameterizedFeedUrl);
let events: ICalendarEvent[] = data.map((e: IWordPressFullCalendarEventResponse) => {
const events: ICalendarEvent[] = data.map((e: IWordPressFullCalendarEventResponse) => {
const startDate: Date = this.convertToDate(e.start);
const endDate: Date = this.convertToDate(e.end);
const eventItem: ICalendarEvent = {

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* ExtensionService
*/
@ -22,10 +23,10 @@ export class iCalCalendarService extends BaseCalendarService implements ICalenda
const jsonified: any = ICAL.parse(data);
const comp: any = new ICAL.Component(jsonified);
const veventList: any[] = comp.getAllSubcomponents("vevent");
let events: ICalendarEvent[] = veventList.map((vevent: any) => {
const events: ICalendarEvent[] = veventList.map((vevent: any) => {
const event: ICAL.Event = new ICAL.Event(vevent);
let startDate = this.convertToDate(event.startDate);
let endDate = this.convertToDate(event.endDate);
const startDate = this.convertToDate(event.startDate);
const endDate = this.convertToDate(event.endDate);
const eventItem: ICalendarEvent = {
title: event.summary,

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as React from "react";
import * as ReactDom from "react-dom";
@ -35,7 +36,7 @@ import CalendarFeedSummary from "./components/CalendarFeedSummary";
import { ICalendarFeedSummaryProps } from "./components/CalendarFeedSummary.types";
// Support for theme variants
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme, ISemanticColors } from '@microsoft/sp-component-base';
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme } from '@microsoft/sp-component-base';
/**
* Calendar Feed Summary Web Part
@ -56,7 +57,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
}
protected onInit(): Promise<void> {
return new Promise<void>((resolve, _reject) => {
return new Promise<void>((resolve) => {
// Consume the new ThemeProvider service
this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey);
@ -270,6 +271,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
/**
* If we get resized, call the Render method so that we can switch between the narrow view and the regular view
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected onAfterResize(newWidth: number): void {
// redraw the web part
this.render();
@ -324,7 +326,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
return strings.FeedUrlValidationNoUrl;
}
if (!feedUrl.match(/(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/)) {
if (!feedUrl.match(/(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-/]))?/)) {
return strings.FeedUrlValidationInvalidFormat;
}
@ -345,7 +347,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
} = this.properties;
// get the first provider matching the type selected
let providerItem: any = this._providerList.filter(p => p.key === this.properties.feedType)[0];
const providerItem: any = this._providerList.filter(p => p.key === this.properties.feedType)[0];
// make sure we got a valid provider
if (!providerItem) {
@ -354,7 +356,7 @@ export default class CalendarFeedSummaryWebPart extends BaseClientSideWebPart<IC
}
// get an instance
let provider: ICalendarService = providerItem.initialize();
const provider: ICalendarService = providerItem.initialize();
// pass props
provider.Context = this.context;

View File

@ -14,10 +14,10 @@ import { FilmstripLayout } from "../../../shared/components/filmstripLayout/inde
import { IReadonlyTheme } from '@microsoft/sp-component-base';
// the key used when caching events
const CacheKey: string = "calendarFeedSummary";
const CacheKey = "calendarFeedSummary";
// this is the same width that the SharePoint events web parts use to render as narrow
const MaxMobileWidth: number = 480;
const MaxMobileWidth = 480;
/**
* Displays a feed summary from a given calendar feed provider. Renders a different view for mobile/narrow web parts.
@ -47,7 +47,7 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
* @param prevProps The previous props before changes are applied
* @param prevState The previous state before changes are applied
*/
public componentDidUpdate(prevProps: ICalendarFeedSummaryProps, prevState: ICalendarFeedSummaryState): void {
public componentDidUpdate(prevProps: ICalendarFeedSummaryProps): void {
// only reload if the provider info has changed
const prevProvider: ICalendarService = prevProps.provider;
const currProvider: ICalendarService = this.props.provider;
@ -240,7 +240,7 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
const isEditMode: boolean = this.props.displayMode === DisplayMode.Edit;
let pagedEvents: ICalendarEvent[] = events;
let usePaging: boolean = false;
let usePaging = false;
if (maxEvents > 0 && events.length > maxEvents) {
// calculate the page size
@ -261,6 +261,7 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
items={pagedEvents}
onRenderCell={(item, _index) => (
<EventCard
key={'eventCard'+_index}
isEditMode={isEditMode}
event={item}
isNarrow={true}
@ -330,7 +331,7 @@ export default class CalendarFeedSummary extends React.Component<ICalendarFeedSu
// load from cache if: 1) we said to use cache, and b) if we have something in cache
if (useCacheIfPossible && localStorage.getItem(CacheKey)) {
let feedCache: IFeedCache = JSON.parse(localStorage.getItem(CacheKey));
const feedCache: IFeedCache = JSON.parse(localStorage.getItem(CacheKey));
const { Name, FeedUrl } = this.props.provider;
const cacheStillValid: boolean = moment().isBefore(feedCache.expiry);

View File

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
* CalendarFeedSummary Types
* Contains the various types used by the component.
@ -6,7 +7,7 @@
* I kinda liked it.
*/
import { DisplayMode } from "@microsoft/sp-core-library";
import { IWebPartContext } from "@microsoft/sp-webpart-base";
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { Moment } from "moment";
import { ICalendarEvent, ICalendarService } from "../../../shared/services/CalendarService";
import { IReadonlyTheme } from '@microsoft/sp-component-base';
@ -17,7 +18,7 @@ import { IReadonlyTheme } from '@microsoft/sp-component-base';
export interface ICalendarFeedSummaryProps {
title: string;
displayMode: DisplayMode;
context: IWebPartContext;
context: WebPartContext;
updateProperty: (value: string) => void;
isConfigured: boolean;
provider: ICalendarService;

View File

@ -1,5 +1,5 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
"compilerOptions": {
"inlineSources": false,
"strictNullChecks": false,
@ -19,21 +19,17 @@
"./node_modules/@microsoft"
],
"types": [
"es6-promise",
"webpack-env"
"node"
],
"lib": [
"es5",
"dom",
"es2015.collection"
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts"
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",
"lib"
],
"extends": "./node_modules/@microsoft/rush-stack-compiler-2.9/includes/tsconfig-web.json"
}

View File

@ -1,30 +0,0 @@
{
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
}