Merge pull request #1586 from DonKirkham/upgrade-react-carousel
This commit is contained in:
commit
9012702df9
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"@microsoft/generator-sharepoint": {
|
"@microsoft/generator-sharepoint": {
|
||||||
"version": "1.10.0",
|
"version": "1.11.0",
|
||||||
"libraryName": "react-carousel",
|
"libraryName": "react-carousel",
|
||||||
"libraryId": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
"libraryId": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
||||||
"environment": "spo",
|
"environment": "spo",
|
||||||
|
|
|
@ -27,7 +27,7 @@ It uses Microsoft Graph API to get image/video url and use PnPjs to load files f
|
||||||
|
|
||||||
## Used SharePoint Framework Version
|
## Used SharePoint Framework Version
|
||||||
|
|
||||||
![1.10](https://img.shields.io/badge/version-1.10.0-green.svg)
|
![1.11](https://img.shields.io/badge/version-1.11.0-green.svg)
|
||||||
|
|
||||||
## Applies to
|
## Applies to
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ Solution|Author(s)
|
||||||
--------|---------
|
--------|---------
|
||||||
Carousel Image/Video Web Part|João Mendes
|
Carousel Image/Video Web Part|João Mendes
|
||||||
Carousel Image/Video Web Part|Rahul Suryawanshi ([@rahulsuryawansh](https://twitter.com/rahulsuryawansh))
|
Carousel Image/Video Web Part|Rahul Suryawanshi ([@rahulsuryawansh](https://twitter.com/rahulsuryawansh))
|
||||||
|
Carousel Image/Video Web Part|Don Kirkham ([@DonKirkham](https://twitter.com/DonKirkham))
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
@ -67,6 +68,7 @@ Version|Date|Comments
|
||||||
-------|----|--------
|
-------|----|--------
|
||||||
1.0.0|July 11, 2019|Initial release
|
1.0.0|July 11, 2019|Initial release
|
||||||
2.0.0|June 17, 2020|Upgraded to SPFx v1.10.0 (Rahul Suryawanshi)
|
2.0.0|June 17, 2020|Upgraded to SPFx v1.10.0 (Rahul Suryawanshi)
|
||||||
|
3.0.0|October 31, 2020|Upgraded to SPFx v1.11.0 (Don Kirkham)
|
||||||
|
|
||||||
|
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
|
|
|
@ -1,14 +1,21 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||||
"solution": {
|
"solution": {
|
||||||
"name": "react-carousel-client-side-solution",
|
"name": "react-carousel-client-side-solution",
|
||||||
"id": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
"id": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
||||||
"version": "2.0.0.0",
|
"version": "3.0.0.0",
|
||||||
"includeClientSideAssets": true,
|
"includeClientSideAssets": true,
|
||||||
"skipFeatureDeployment": true,
|
"skipFeatureDeployment": true,
|
||||||
"isDomainIsolated": false
|
"isDomainIsolated": false,
|
||||||
},
|
"developer": {
|
||||||
"paths": {
|
"name": "Contoso",
|
||||||
"zippedPackage": "solution/react-carousel.sppkg"
|
"privacyUrl": "https://contoso.com/privacy",
|
||||||
}
|
"termsOfUseUrl": "https://contoso.com/terms-of-use",
|
||||||
}
|
"websiteUrl": "https://contoso.com/my-app",
|
||||||
|
"mpnId": "000000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"zippedPackage": "solution/react-carousel.sppkg"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -14,12 +14,12 @@
|
||||||
"test:watch": "./node_modules/.bin/jest --config ./config/jest.config.json --watchAll"
|
"test:watch": "./node_modules/.bin/jest --config ./config/jest.config.json --watchAll"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@microsoft/sp-core-library": "1.10.0",
|
"@microsoft/sp-core-library": "1.11.0",
|
||||||
"@microsoft/sp-http": "1.10.0",
|
"@microsoft/sp-http": "1.11.0",
|
||||||
"@microsoft/sp-lodash-subset": "1.10.0",
|
"@microsoft/sp-lodash-subset": "1.11.0",
|
||||||
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
|
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
|
||||||
"@microsoft/sp-property-pane": "1.10.0",
|
"@microsoft/sp-property-pane": "1.11.0",
|
||||||
"@microsoft/sp-webpart-base": "1.10.0",
|
"@microsoft/sp-webpart-base": "1.11.0",
|
||||||
"@microsoft/teams-js": "^1.6.0",
|
"@microsoft/teams-js": "^1.6.0",
|
||||||
"@pnp/common": "^1.3.11",
|
"@pnp/common": "^1.3.11",
|
||||||
"@pnp/graph": "^1.3.11",
|
"@pnp/graph": "^1.3.11",
|
||||||
|
@ -46,10 +46,10 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||||
"@microsoft/sp-build-web": "1.10.0",
|
"@microsoft/sp-build-web": "1.11.0",
|
||||||
"@microsoft/sp-module-interfaces": "1.10.0",
|
"@microsoft/sp-module-interfaces": "1.11.0",
|
||||||
"@microsoft/sp-tslint-rules": "1.10.0",
|
"@microsoft/sp-tslint-rules": "1.11.0",
|
||||||
"@microsoft/sp-webpart-workbench": "1.10.0",
|
"@microsoft/sp-webpart-workbench": "1.11.0",
|
||||||
"@types/chai": "3.4.34",
|
"@types/chai": "3.4.34",
|
||||||
"@types/mocha": "2.2.38",
|
"@types/mocha": "2.2.38",
|
||||||
"@types/react": "16.8.8",
|
"@types/react": "16.8.8",
|
||||||
|
|
|
@ -19,225 +19,229 @@ import * as strings from 'CarouselWebPartStrings';
|
||||||
import { DisplayMode } from '@microsoft/sp-core-library';
|
import { DisplayMode } from '@microsoft/sp-core-library';
|
||||||
import { CommunicationColors } from '@uifabric/fluent-theme/lib/fluent/FluentColors';
|
import { CommunicationColors } from '@uifabric/fluent-theme/lib/fluent/FluentColors';
|
||||||
import {
|
import {
|
||||||
Spinner,
|
Spinner,
|
||||||
SpinnerSize,
|
SpinnerSize,
|
||||||
MessageBar,
|
MessageBar,
|
||||||
MessageBarType,
|
MessageBarType,
|
||||||
Label,
|
Label,
|
||||||
Icon,
|
Icon,
|
||||||
ImageFit,
|
ImageFit,
|
||||||
Image,
|
Image,
|
||||||
ImageLoadState,
|
ImageLoadState,
|
||||||
} from 'office-ui-fabric-react';
|
} from 'office-ui-fabric-react';
|
||||||
|
|
||||||
|
|
||||||
export default class Carousel extends React.Component<ICarouselProps, ICarouselState> {
|
export default class Carousel extends React.Component<ICarouselProps, ICarouselState> {
|
||||||
private spService: spservices = null;
|
private spService: spservices = null;
|
||||||
private _teamsContext: microsoftTeams.Context = null;
|
private _teamsContext: microsoftTeams.Context = null;
|
||||||
|
|
||||||
|
|
||||||
public constructor(props: ICarouselProps) {
|
public constructor(props: ICarouselProps) {
|
||||||
super(props);
|
super(props);
|
||||||
this.spService = new spservices(this.props.context);
|
this.spService = new spservices(this.props.context);
|
||||||
|
|
||||||
if (this.props.context.microsoftTeams) {
|
if (this.props.context.microsoftTeams) {
|
||||||
this.props.context.microsoftTeams.getContext(context => {
|
this.props.context.microsoftTeams.getContext(context => {
|
||||||
this._teamsContext = context;
|
this._teamsContext = context;
|
||||||
console.log('ctt', this._teamsContext.theme);
|
console.log('ctt', this._teamsContext.theme);
|
||||||
this.setState({ teamsTheme: this._teamsContext.theme });
|
this.setState({ teamsTheme: this._teamsContext.theme });
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
teamsTheme: 'default',
|
teamsTheme: 'default',
|
||||||
photoIndex: 0,
|
photoIndex: 0,
|
||||||
carouselImages: [],
|
carouselImages: [],
|
||||||
loadingImage: true
|
loadingImage: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private onConfigure() {
|
private onConfigure() {
|
||||||
// Context of the web part
|
// Context of the web part
|
||||||
this.props.context.propertyPane.open();
|
this.props.context.propertyPane.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async loadPictures() {
|
private async loadPictures() {
|
||||||
|
|
||||||
this.setState({ isLoading: true, hasError: false });
|
this.setState({ isLoading: true, hasError: false });
|
||||||
const tenantUrl = `https://${location.host}`;
|
const tenantUrl = `https://${location.host}`;
|
||||||
let galleryImages: ICarouselImages[] = [];
|
let galleryImages: ICarouselImages[] = [];
|
||||||
let carouselImages: React.ReactElement<HTMLElement>[] = [];
|
let carouselImages: React.ReactElement<HTMLElement>[] = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const images = await this.spService.getImages(this.props.siteUrl, this.props.list, this.props.numberImages);
|
const images = await this.spService.getImages(this.props.siteUrl, this.props.list, this.props.numberImages);
|
||||||
|
|
||||||
for (const image of images) {
|
for (const image of images) {
|
||||||
|
|
||||||
if (image.FileSystemObjectType == 1) continue; // by pass folder item
|
if (image.FileSystemObjectType == 1) continue; // by pass folder item
|
||||||
const pURL = `${tenantUrl}/_api/v2.0/sharePoint:${image.File.ServerRelativeUrl}:/driveItem/thumbnails/0/large/content?preferNoRedirect=true `;
|
const pURL = `${tenantUrl}/_api/v2.0/sharePoint:${image.File.ServerRelativeUrl}:/driveItem/thumbnails/0/large/content?preferNoRedirect=true `;
|
||||||
const thumbnailUrl = `${tenantUrl}/_api/v2.0/sharePoint:${image.File.ServerRelativeUrl}:/driveItem/thumbnails/0/c240x240/content?preferNoRedirect=true `;
|
const thumbnailUrl = `${tenantUrl}/_api/v2.0/sharePoint:${image.File.ServerRelativeUrl}:/driveItem/thumbnails/0/c240x240/content?preferNoRedirect=true `;
|
||||||
|
|
||||||
let mediaType: string = '';
|
let mediaType: string = '';
|
||||||
switch (image.File_x0020_Type) {
|
switch (image.File_x0020_Type) {
|
||||||
case ('jpg' || 'jpeg' || 'png' || 'tiff' || 'gif'):
|
case 'jpg':
|
||||||
mediaType = 'image';
|
case 'jpeg':
|
||||||
break;
|
case 'png':
|
||||||
case ('mp4'):
|
case 'tiff':
|
||||||
mediaType = 'video';
|
case 'gif':
|
||||||
break;
|
mediaType = 'image';
|
||||||
default:
|
break;
|
||||||
continue;
|
case 'mp4':
|
||||||
break;
|
mediaType = 'video';
|
||||||
}
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
galleryImages.push(
|
galleryImages.push(
|
||||||
{
|
{
|
||||||
imageUrl: pURL,
|
imageUrl: pURL,
|
||||||
mediaType: mediaType,
|
mediaType: mediaType,
|
||||||
serverRelativeUrl: image.File.ServerRelativeUrl,
|
serverRelativeUrl: image.File.ServerRelativeUrl,
|
||||||
caption: image.Title ? image.Title : image.File.Name,
|
caption: image.Title ? image.Title : image.File.Name,
|
||||||
description: image.Description ? image.Description : '',
|
description: image.Description ? image.Description : '',
|
||||||
linkUrl: ''
|
linkUrl: ''
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create Carousel Slides from Images
|
// Create Carousel Slides from Images
|
||||||
|
|
||||||
carouselImages = galleryImages.map((galleryImage, i) => {
|
carouselImages = galleryImages.map((galleryImage, i) => {
|
||||||
return (
|
return (
|
||||||
<div className='slideLoading' >
|
<div className='slideLoading' >
|
||||||
|
|
||||||
{galleryImage.mediaType == 'video' ?
|
{galleryImage.mediaType == 'video' ?
|
||||||
<div >
|
<div >
|
||||||
<Player
|
<Player
|
||||||
poster={galleryImage.imageUrl}
|
poster={galleryImage.imageUrl}
|
||||||
style={{ width: '100%', height: '400px' }}>
|
style={{ width: '100%', height: '400px' }}>
|
||||||
<BigPlayButton position="center" />
|
<BigPlayButton position="center" />
|
||||||
<source src={galleryImage.serverRelativeUrl}
|
<source src={galleryImage.serverRelativeUrl}
|
||||||
/>
|
/>
|
||||||
</Player>
|
</Player>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div>
|
<div>
|
||||||
<Image src={galleryImage.imageUrl}
|
<Image src={galleryImage.imageUrl}
|
||||||
onLoadingStateChange={async (loadState: ImageLoadState) => {
|
onLoadingStateChange={async (loadState: ImageLoadState) => {
|
||||||
console.log('imageload Status ' + i, loadState, galleryImage.imageUrl);
|
console.log('imageload Status ' + i, loadState, galleryImage.imageUrl);
|
||||||
if (loadState == ImageLoadState.loaded) {
|
if (loadState == ImageLoadState.loaded) {
|
||||||
this.setState({ loadingImage: false });
|
this.setState({ loadingImage: false });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
height={'400px'}
|
height={'400px'}
|
||||||
imageFit={ImageFit.cover}
|
imageFit={ImageFit.cover}
|
||||||
/>
|
/>
|
||||||
<div style={{ background: 'rgba(0, 0, 0, 0.3)',overflow:'hidden', fontSize: FontSizes.size16, top:0, transition: '.7s ease', textAlign: 'left', width: '200px', height: '350px', position: 'absolute', color: '#ffffff', padding: '25px' }}>
|
<div style={{ background: 'rgba(0, 0, 0, 0.3)', overflow: 'hidden', fontSize: FontSizes.size16, top: 0, transition: '.7s ease', textAlign: 'left', width: '200px', height: '350px', position: 'absolute', color: '#ffffff', padding: '25px' }}>
|
||||||
<h2 style={{fontSize: FontSizes.size20, textTransform: 'uppercase', color: 'white' }}>{galleryImage.caption}</h2>
|
<h2 style={{ fontSize: FontSizes.size20, textTransform: 'uppercase', color: 'white' }}>{galleryImage.caption}</h2>
|
||||||
<p>{galleryImage.description}</p>
|
<p>{galleryImage.description}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setState({ carouselImages: carouselImages, isLoading: false });
|
this.setState({ carouselImages: carouselImages, isLoading: false });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.setState({ hasError: true, errorMessage: decodeURIComponent(error.message) });
|
this.setState({ hasError: true, errorMessage: decodeURIComponent(error.message) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidMount() {
|
public async componentDidMount() {
|
||||||
await this.loadPictures();
|
await this.loadPictures();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidUpdate(prevProps: ICarouselProps) {
|
public async componentDidUpdate(prevProps: ICarouselProps) {
|
||||||
|
|
||||||
if (!this.props.list || !this.props.siteUrl) return;
|
if (!this.props.list || !this.props.siteUrl) return;
|
||||||
// Get Properties change
|
// Get Properties change
|
||||||
if (prevProps.list !== this.props.list || prevProps.numberImages !== this.props.numberImages) {
|
if (prevProps.list !== this.props.list || prevProps.numberImages !== this.props.numberImages) {
|
||||||
/*
|
/*
|
||||||
this.galleryImages = [];
|
this.galleryImages = [];
|
||||||
this._carouselImages = [];
|
this._carouselImages = [];
|
||||||
this.setState({ images: this.galleryImages, carouselImages: t.his._carouselImages, isLoading: false });
|
this.setState({ images: this.galleryImages, carouselImages: t.his._carouselImages, isLoading: false });
|
||||||
*/
|
*/
|
||||||
await this.loadPictures();
|
await this.loadPictures();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public render(): React.ReactElement<ICarouselProps> {
|
public render(): React.ReactElement<ICarouselProps> {
|
||||||
const sliderSettings = {
|
const sliderSettings = {
|
||||||
dots: true,
|
dots: true,
|
||||||
infinite: true,
|
infinite: true,
|
||||||
speed: 500,
|
speed: 500,
|
||||||
slidesToShow: 1,
|
slidesToShow: 1,
|
||||||
slidesToScroll: 1,
|
slidesToScroll: 1,
|
||||||
lazyLoad: 'progressive',
|
lazyLoad: 'progressive',
|
||||||
autoplaySpeed: 3000,
|
autoplaySpeed: 3000,
|
||||||
initialSlide: this.state.photoIndex,
|
initialSlide: this.state.photoIndex,
|
||||||
arrows: true,
|
arrows: true,
|
||||||
draggable: true,
|
draggable: true,
|
||||||
adaptiveHeight: true,
|
adaptiveHeight: true,
|
||||||
useCSS: true,
|
useCSS: true,
|
||||||
useTransform: true,
|
useTransform: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.carousel}>
|
<div className={styles.carousel}>
|
||||||
<div>
|
<div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
(!this.props.list) ?
|
(!this.props.list) ?
|
||||||
<Placeholder iconName='Edit'
|
<Placeholder iconName='Edit'
|
||||||
iconText={strings.WebpartConfigIconText}
|
iconText={strings.WebpartConfigIconText}
|
||||||
description={strings.WebpartConfigDescription}
|
description={strings.WebpartConfigDescription}
|
||||||
buttonLabel={strings.WebPartConfigButtonLabel}
|
buttonLabel={strings.WebPartConfigButtonLabel}
|
||||||
hideButton={this.props.displayMode === DisplayMode.Read}
|
hideButton={this.props.displayMode === DisplayMode.Read}
|
||||||
onConfigure={this.onConfigure.bind(this)} />
|
onConfigure={this.onConfigure.bind(this)} />
|
||||||
:
|
:
|
||||||
this.state.hasError ?
|
this.state.hasError ?
|
||||||
<MessageBar messageBarType={MessageBarType.error}>
|
<MessageBar messageBarType={MessageBarType.error}>
|
||||||
{this.state.errorMessage}
|
{this.state.errorMessage}
|
||||||
</MessageBar>
|
</MessageBar>
|
||||||
:
|
:
|
||||||
this.state.isLoading ?
|
this.state.isLoading ?
|
||||||
<Spinner size={SpinnerSize.large} label='loading images...' />
|
<Spinner size={SpinnerSize.large} label='loading images...' />
|
||||||
:
|
:
|
||||||
this.state.carouselImages.length == 0 ?
|
this.state.carouselImages.length == 0 ?
|
||||||
<div style={{ width: '300px', margin: 'auto' }}>
|
<div style={{ width: '300px', margin: 'auto' }}>
|
||||||
<Icon iconName="PhotoCollection"
|
<Icon iconName="PhotoCollection"
|
||||||
style={{ fontSize: '250px', color: '#d9d9d9' }} />
|
style={{ fontSize: '250px', color: '#d9d9d9' }} />
|
||||||
<Label style={{ width: '250px', margin: 'auto', fontSize: FontSizes.size20 }}>No images in the library</Label>
|
<Label style={{ width: '250px', margin: 'auto', fontSize: FontSizes.size20 }}>No images in the library</Label>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div style={{ width: '100%', height: '100%'}}>
|
<div style={{ width: '100%', height: '100%' }}>
|
||||||
|
|
||||||
<div style={{ width: '100%'}}>
|
<div style={{ width: '100%' }}>
|
||||||
<Slider
|
<Slider
|
||||||
{...sliderSettings}
|
{...sliderSettings}
|
||||||
autoplay={true}
|
autoplay={true}
|
||||||
onReInit={() => {
|
onReInit={() => {
|
||||||
if (!this.state.loadingImage)
|
if (!this.state.loadingImage)
|
||||||
$(".slideLoading").removeClass("slideLoading");
|
$(".slideLoading").removeClass("slideLoading");
|
||||||
}}>
|
}}>
|
||||||
{
|
{
|
||||||
this.state.carouselImages
|
this.state.carouselImages
|
||||||
}
|
}
|
||||||
</Slider>
|
</Slider>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
this.state.loadingImage &&
|
this.state.loadingImage &&
|
||||||
<Spinner size={SpinnerSize.small} label={'Loading...'} style={{verticalAlign:'middle', right:'30%', top:20, position: 'absolute', fontSize: FontSizes.size18, color: CommunicationColors.primary }}></Spinner>
|
<Spinner size={SpinnerSize.small} label={'Loading...'} style={{ verticalAlign: 'middle', right: '30%', top: 20, position: 'absolute', fontSize: FontSizes.size18, color: CommunicationColors.primary }}></Spinner>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts"
|
"src/**/*.ts",
|
||||||
|
"src/**/*.tsx"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
|
Loading…
Reference in New Issue