Before converting to hook
This commit is contained in:
parent
092482c498
commit
ce98f07dd9
|
@ -2,7 +2,7 @@
|
|||
"@microsoft/generator-sharepoint": {
|
||||
"isCreatingSolution": true,
|
||||
"environment": "spo",
|
||||
"version": "1.9.1",
|
||||
"version": "1.10.0",
|
||||
"libraryName": "react-calendar-feed",
|
||||
"libraryId": "25653136-fc83-4abe-b9d2-a4ac041959d5",
|
||||
"packageManager": "npm",
|
||||
|
|
|
@ -24,7 +24,7 @@ For more information about how this solution was built, including some design de
|
|||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![SPFx v1.9.1](https://img.shields.io/badge/SPFx-1.9.1-green.svg)
|
||||
![SPFx v1.10.0](https://img.shields.io/badge/SPFx-1.10.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
|
@ -40,9 +40,9 @@ Before you can use this web part example, you will need one of the following:
|
|||
- A WordPress WP-FullCalendar feed
|
||||
- An Exchange Public Calendar
|
||||
|
||||
It is important that all feeds do not require authentication. Also, make sure that your calendar includes upcoming events, as the web part will filter out evens that are earlier than today's date.
|
||||
This web part only supports anonymous external feeds. Also, make sure that your calendar includes upcoming events, as the web part will filter out evens that are earlier than today's date.
|
||||
|
||||
If your feed supports filtering by dates, you can specify **{s}** in the URL where the start date should be inserted, and the web part will automatically replace the **{s}** placeholder with today's date. Similarly, you can specify **{e}** in the URL where you wish the end date to be inserted, and the web part will automatically replace the placeholder for the end date, as determined by the date range you select.
|
||||
If your feed supports filtering by dates, you can specify `{s}` in the URL where the start date should be inserted, and the web part will automatically replace the `{s}` placeholder with today's date. Similarly, you can specify `{e}` in the URL where you wish the end date to be inserted, and the web part will automatically replace the placeholder for the end date, as determined by the date range you select.
|
||||
|
||||
## Solution
|
||||
|
||||
|
@ -59,6 +59,7 @@ Version|Date|Comments
|
|||
3.0|November 9, 2018|Converted to SPFx 1.7; Added SharePoint Calendar feed
|
||||
4.0|January 16, 2019|Converted to SPFx 1.7.1; Removed NPM libraries associated with issue #708.
|
||||
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
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"solution": {
|
||||
"name": "react-calendar-feed-client-side-solution",
|
||||
"id": "25653136-fc83-4abe-b9d2-a4ac041959d5",
|
||||
"version": "1.0.0.0",
|
||||
"version": "5.1.0.0",
|
||||
"includeClientSideAssets": true
|
||||
},
|
||||
"paths": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-calendar-feed",
|
||||
"version": "1.1.0",
|
||||
"version": "5.1.0",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
|
@ -12,10 +12,11 @@
|
|||
"test": "gulp test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.9.1",
|
||||
"@microsoft/sp-lodash-subset": "1.9.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
|
||||
"@microsoft/sp-webpart-base": "1.9.1",
|
||||
"@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",
|
||||
"@pnp/common": "^1.2.8",
|
||||
"@pnp/logging": "^1.2.8",
|
||||
"@pnp/odata": "^1.2.8",
|
||||
|
@ -29,6 +30,7 @@
|
|||
"feedparser": "^2.2.9",
|
||||
"ical.js": "^1.3.0",
|
||||
"ics-js": "^0.10.2",
|
||||
"moment": "^2.24.0",
|
||||
"office-ui-fabric-react": "6.189.2",
|
||||
"react": "16.8.5",
|
||||
"react-dom": "16.8.5",
|
||||
|
@ -41,10 +43,11 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/rush-stack-compiler-2.9": "0.7.16",
|
||||
"@microsoft/sp-build-web": "1.9.1",
|
||||
"@microsoft/sp-module-interfaces": "1.9.1",
|
||||
"@microsoft/sp-tslint-rules": "1.9.1",
|
||||
"@microsoft/sp-webpart-workbench": "1.9.1",
|
||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||
"@microsoft/sp-build-web": "1.10.0",
|
||||
"@microsoft/sp-module-interfaces": "1.10.0",
|
||||
"@microsoft/sp-tslint-rules": "1.10.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.10.0",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"ajv": "~5.2.2",
|
||||
|
|
|
@ -2,7 +2,8 @@ import * as moment from "moment";
|
|||
import { css } from "office-ui-fabric-react/lib/Utilities";
|
||||
import * as React from "react";
|
||||
import styles from "./DateBox.module.scss";
|
||||
import { DateBoxSize, IDateBoxProps, IDateBoxState } from "./DateBox.types";
|
||||
import { DateBoxSize, IDateBoxProps } from ".";
|
||||
import { IDateBoxState } from "./IDateBoxState";
|
||||
|
||||
/**
|
||||
* Shows a date in a SharePoint-looking date
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
export interface IDateBoxProps {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
className?: string;
|
||||
size: DateBoxSize;
|
||||
}
|
||||
|
||||
export interface IDateBoxState {
|
||||
// you just proved advertising works!
|
||||
}
|
||||
|
||||
export enum DateBoxSize {
|
||||
Small,
|
||||
Medium
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum DateBoxSize {
|
||||
Small,
|
||||
Medium
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { DateBoxSize } from "./DateBoxSize";
|
||||
|
||||
export interface IDateBoxProps {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
className?: string;
|
||||
size: DateBoxSize;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export interface IDateBoxState {
|
||||
// you just proved advertising works!
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
export * from "./DateBox";
|
||||
export * from "./DateBox.types";
|
||||
export * from "./IDateBoxProps";
|
||||
export * from "./DateBoxSize";
|
||||
|
|
|
@ -4,7 +4,8 @@ import * as ICS from "ics-js";
|
|||
import * as moment from "moment";
|
||||
import { ActionButton, DocumentCard, DocumentCardType, FocusZone, css } from "office-ui-fabric-react";
|
||||
import * as React from "react";
|
||||
import { IEventCardProps, IEventCardState } from ".";
|
||||
import { IEventCardProps } from ".";
|
||||
import { IEventCardState } from "./IEventCardState";
|
||||
import { DateBox, DateBoxSize } from "../DateBox";
|
||||
import styles from "./EventCard.module.scss";
|
||||
import { Text } from "@microsoft/sp-core-library";
|
||||
|
@ -88,7 +89,7 @@ export class EventCard extends React.Component<IEventCardProps, IEventCardState>
|
|||
// category,
|
||||
// location
|
||||
} = this.props.event;
|
||||
const eventDate: moment.Moment = moment.utc(start);
|
||||
const eventDate: moment.Moment = moment(start);
|
||||
const dateString: string = allDay ? eventDate.format(strings.AllDayDateFormat) : eventDate.format(strings.LocalizedTimeFormat);
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { ICalendarEvent } from "../../../shared/services/CalendarService";
|
||||
import { ICalendarEvent } from "../../services/CalendarService";
|
||||
|
||||
export interface IEventCardProps {
|
||||
isEditMode: boolean;
|
||||
event: ICalendarEvent;
|
||||
isNarrow: boolean;
|
||||
}
|
||||
|
||||
export interface IEventCardState {}
|
|
@ -0,0 +1,3 @@
|
|||
export interface IEventCardState {
|
||||
// Not in use
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
export * from "./EventCard";
|
||||
export * from "./EventCard.types";
|
||||
export * from "./IEventCardProps";
|
||||
|
|
|
@ -5,5 +5,3 @@ export interface IPagingProps {
|
|||
showPageNum: boolean;
|
||||
onPageUpdate: (pageNumber: number) => void;
|
||||
}
|
||||
|
||||
export interface IPagingState { }
|
|
@ -0,0 +1,3 @@
|
|||
export interface IPagingState {
|
||||
// Not in use
|
||||
}
|
|
@ -2,7 +2,8 @@ import { ActionButton, IButtonProps } 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";
|
||||
import { IPagingProps, IPagingState } from ".";
|
||||
import { IPagingProps } from ".";
|
||||
import { IPagingState } from "./IPagingState";
|
||||
import styles from "./Paging.module.scss";
|
||||
import * as strings from "CalendarFeedSummaryWebPartStrings";
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
export * from "./Paging";
|
||||
export * from "./Paging.types";
|
||||
export * from "./IPagingProps";
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
@import '~office-ui-fabric-react/dist/sass/References.scss';
|
||||
|
||||
@import "~office-ui-fabric-react/dist/sass/References.scss";
|
||||
:export {
|
||||
centerPadding: 50px;
|
||||
}
|
||||
|
@ -20,14 +19,6 @@
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
.sliderButtonRight {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.sliderButtonLeft {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
&:hover .sliderButtons {
|
||||
opacity: 1;
|
||||
|
||||
|
@ -45,8 +36,8 @@
|
|||
}
|
||||
|
||||
.indexButton {
|
||||
font-size: 17px;
|
||||
font-weight: 300;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
|
@ -67,6 +58,8 @@
|
|||
|
||||
&:hover {
|
||||
color: $ms-color-white;
|
||||
background-color: $ms-color-black;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&:active {
|
||||
|
@ -74,6 +67,39 @@
|
|||
}
|
||||
}
|
||||
|
||||
.carouselDotsContainer {
|
||||
.carouselDot {
|
||||
display: inline-block;
|
||||
background-color: $ms-color-black;
|
||||
height: 4px;
|
||||
width: 4px;
|
||||
opacity: 0.5;
|
||||
border: 2px solid $ms-color-black;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
opacity: 0.25;
|
||||
outline: 0;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global(.slick-active) {
|
||||
.carouselDotsContainer {
|
||||
.carouselDot {
|
||||
background-color: "[theme:themeDark, default: #005a9e]";
|
||||
opacity: 0.75;
|
||||
border-color: "[theme:themeDark, default: #005a9e]";
|
||||
|
||||
&:hover {
|
||||
background-color: "[theme:themeDarker, default: #004578]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.indexButton:global(.ms-Button-flexContainer):hover:global(.ms-Icon),
|
||||
.indexButton:global(.ms-Icon:hover),
|
||||
.indexButton:hover:global(.ms-Icon) {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import { css } from '@uifabric/utilities/lib/css';
|
||||
import { IconButton } from 'office-ui-fabric-react/lib/Button';
|
||||
import * as React from 'react';
|
||||
// import * as slick from 'slick-carousel';
|
||||
import Slider from 'react-slick';
|
||||
import { IFilmstripLayoutProps, IFilmstripLayoutState } from "./FilmstripLayout.types";
|
||||
|
||||
|
||||
import { IFilmstripLayoutProps } from "./IFilmstripLayoutProps";
|
||||
import { IFilmstripLayoutState} from "./IFilmstripLayoutState";
|
||||
import { SPComponentLoader } from '@microsoft/sp-loader';
|
||||
import styles from "./FilmstripLayout.module.scss";
|
||||
|
||||
|
@ -20,14 +18,32 @@ export class FilmstripLayout extends React.Component<
|
|||
// the slick slider used in normal views
|
||||
private _slider: Slider;
|
||||
|
||||
private _container: HTMLDivElement;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
constructor(props: IFilmstripLayoutProps) {
|
||||
super(props);
|
||||
|
||||
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css');
|
||||
SPComponentLoader.loadCss('https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css');
|
||||
this.state = {
|
||||
dimensions: undefined
|
||||
};
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
if (this._container) {
|
||||
this.setState({
|
||||
dimensions: {
|
||||
width: this._container.offsetWidth,
|
||||
height: this._container.offsetHeight,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Renders a slick switch, a slide for each child, and next/previous arrows
|
||||
|
@ -35,15 +51,35 @@ export class FilmstripLayout extends React.Component<
|
|||
public render(): React.ReactElement<IFilmstripLayoutProps> {
|
||||
// slick seems to have an issue with having "infinite" mode set to true and having less items than the number of slides per page
|
||||
// set infinite to true only if there are more than 3 children
|
||||
var isInfinite: boolean = React.Children.count(this.props.children) > 3;
|
||||
|
||||
let numSlides: number = 3;
|
||||
if (this.state.dimensions) {
|
||||
if (this.state.dimensions.width > 927) {
|
||||
numSlides = 4;
|
||||
} else if (this.state.dimensions.width <= 695) {
|
||||
numSlides = 2;
|
||||
}
|
||||
}
|
||||
|
||||
var isInfinite: boolean = React.Children.count(this.props.children) > numSlides;
|
||||
var settings: any = {
|
||||
accessibility: true,
|
||||
arrows: false,
|
||||
autoplaySpeed: 5000,
|
||||
dots: true,
|
||||
//dotsClass: css("slick-dots", styles.slickDots),
|
||||
customPaging: (i:number)=> {
|
||||
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>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
},
|
||||
infinite: isInfinite,
|
||||
slidesToShow: 4,
|
||||
slidesToScroll: 4,
|
||||
slidesToShow: numSlides,
|
||||
slidesToScroll: numSlides,
|
||||
speed: 500,
|
||||
centerPadding: styles.centerPadding,
|
||||
pauseOnHover: true,
|
||||
|
@ -51,60 +87,64 @@ export class FilmstripLayout extends React.Component<
|
|||
useCSS: true,
|
||||
rows: 1,
|
||||
respondTo: "slider",
|
||||
responsive: [
|
||||
{
|
||||
breakpoint: 499,
|
||||
settings: {
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 731,
|
||||
settings: {
|
||||
slidesToShow: 2,
|
||||
slidesToScroll: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 963,
|
||||
settings: {
|
||||
slidesToShow: 3,
|
||||
slidesToScroll: 3
|
||||
}
|
||||
},
|
||||
{
|
||||
breakpoint: 1028,
|
||||
settings: {
|
||||
slidesToShow: 4,
|
||||
slidesToScroll: 4
|
||||
}
|
||||
}
|
||||
]
|
||||
// responsive: [
|
||||
// // {
|
||||
// // breakpoint: 1440,
|
||||
// // settings: {
|
||||
// // slidesToShow: 4,
|
||||
// // slidesToScroll: 4,
|
||||
// // infinite: isInfinite,
|
||||
// // dots: true
|
||||
// // }
|
||||
// // },
|
||||
// {
|
||||
// breakpoint: 1024,
|
||||
// settings: {
|
||||
// slidesToShow: 3,
|
||||
// slidesToScroll: 3,
|
||||
// infinite: isInfinite,
|
||||
// dots: true
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// // breakpoint: 754,
|
||||
// breakpoint: 767,
|
||||
// settings: {
|
||||
// slidesToShow: 2,
|
||||
// slidesToScroll: 2,
|
||||
// infinite: isInfinite,
|
||||
// dots: true
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
};
|
||||
|
||||
console.log("Dimensions", this.state.dimensions);
|
||||
return (
|
||||
<div>
|
||||
<div className={css(styles.filmstripLayout, styles.filmStrip)} aria-label={this.props.ariaLabel}>
|
||||
<Slider ref={c => (this._slider = c)} {...settings}>
|
||||
WIDTH: {this.state.dimensions && this.state.dimensions.width}
|
||||
<div className={css(styles.filmstripLayout, styles.filmStrip)} aria-label={this.props.ariaLabel} ref={(el: HTMLDivElement) => (this._container = el)}>
|
||||
<Slider ref={(c:Slider) => (this._slider = c)} {...settings}>
|
||||
{this.props.children}
|
||||
</Slider>
|
||||
<div
|
||||
className={css(styles.indexButtonContainer, styles.sliderButtons, styles.sliderButtonLeft)}
|
||||
className={css(styles.indexButtonContainer, styles.sliderButtons)}
|
||||
style={{ left: "10px" }}
|
||||
onClick={() => this._slider.slickPrev()}
|
||||
>
|
||||
<IconButton
|
||||
className={css(styles.indexButton, styles.leftPositioned)}
|
||||
iconProps={{ iconName: "ChevronLeft" }}
|
||||
iconProps={{ iconName: "ChevronLeft", styles: {root: { fontSize:'28px', fontWeight:'400'} }}}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={css(styles.indexButtonContainer, styles.sliderButtons, styles.sliderButtonRight)}
|
||||
className={css(styles.indexButtonContainer, styles.sliderButtons)}
|
||||
style={{ right: "10px" }}
|
||||
onClick={() => this._slider.slickNext()}
|
||||
>
|
||||
<IconButton
|
||||
className={css(styles.indexButton, styles.rightPositioned)}
|
||||
iconProps={{ iconName: "ChevronRight" }}
|
||||
iconProps={{ iconName: "ChevronRight", styles: {root: { fontSize:'28px', fontWeight:'400'} }}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
export interface IFilmstripLayoutProps {
|
||||
ariaLabel?: string;
|
||||
}
|
||||
|
||||
export interface IFilmstripLayoutState { }
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
export interface IFilmstripLayoutState {
|
||||
dimensions: {
|
||||
width: any;
|
||||
height: any;
|
||||
};
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
export * from "./FilmstripLayout";
|
||||
export * from "./FilmstripLayout.types";
|
||||
export * from "./IFilmstripLayoutProps";
|
||||
|
|
|
@ -151,7 +151,7 @@ export class MockCalendarService extends BaseCalendarService implements ICalenda
|
|||
return new Promise<ICalendarEvent[]>((resolve: any) => {
|
||||
setTimeout(() => {
|
||||
resolve(this.filterEventRange(sampleEvents));
|
||||
}, 1000);
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
}
|
||||
|
||||
.webPartChrome {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-ms-flex-align: stretch;
|
||||
align-items: stretch;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
// display: -ms-flexbox;
|
||||
// display: flex;
|
||||
// -ms-flex-align: stretch;
|
||||
// align-items: stretch;
|
||||
// -ms-flex-direction: column;
|
||||
// flex-direction: column;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.headerSmMargin {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
|
||||
"compilerOptions": {
|
||||
"inlineSources": false,
|
||||
"strictNullChecks": false,
|
||||
|
|
Loading…
Reference in New Issue