Merge pull request #1586 from DonKirkham/upgrade-react-carousel
This commit is contained in:
commit
9012702df9
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.10.0",
|
||||
"version": "1.11.0",
|
||||
"libraryName": "react-carousel",
|
||||
"libraryId": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
||||
"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
|
||||
|
||||
![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
|
||||
|
||||
|
@ -60,6 +60,7 @@ Solution|Author(s)
|
|||
--------|---------
|
||||
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|Don Kirkham ([@DonKirkham](https://twitter.com/DonKirkham))
|
||||
|
||||
## Version history
|
||||
|
||||
|
@ -67,6 +68,7 @@ Version|Date|Comments
|
|||
-------|----|--------
|
||||
1.0.0|July 11, 2019|Initial release
|
||||
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
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-carousel-client-side-solution",
|
||||
"id": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
||||
"version": "2.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/react-carousel.sppkg"
|
||||
}
|
||||
}
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||
"solution": {
|
||||
"name": "react-carousel-client-side-solution",
|
||||
"id": "263a1d21-f4c7-4a46-a364-e5f995286b9b",
|
||||
"version": "3.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"developer": {
|
||||
"name": "Contoso",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-core-library": "1.10.0",
|
||||
"@microsoft/sp-http": "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.11.0",
|
||||
"@microsoft/sp-http": "1.11.0",
|
||||
"@microsoft/sp-lodash-subset": "1.11.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.11.0",
|
||||
"@microsoft/sp-property-pane": "1.11.0",
|
||||
"@microsoft/sp-webpart-base": "1.11.0",
|
||||
"@microsoft/teams-js": "^1.6.0",
|
||||
"@pnp/common": "^1.3.11",
|
||||
"@pnp/graph": "^1.3.11",
|
||||
|
@ -46,10 +46,10 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@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",
|
||||
"@microsoft/sp-build-web": "1.11.0",
|
||||
"@microsoft/sp-module-interfaces": "1.11.0",
|
||||
"@microsoft/sp-tslint-rules": "1.11.0",
|
||||
"@microsoft/sp-webpart-workbench": "1.11.0",
|
||||
"@types/chai": "3.4.34",
|
||||
"@types/mocha": "2.2.38",
|
||||
"@types/react": "16.8.8",
|
||||
|
|
|
@ -19,225 +19,229 @@ import * as strings from 'CarouselWebPartStrings';
|
|||
import { DisplayMode } from '@microsoft/sp-core-library';
|
||||
import { CommunicationColors } from '@uifabric/fluent-theme/lib/fluent/FluentColors';
|
||||
import {
|
||||
Spinner,
|
||||
SpinnerSize,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
Label,
|
||||
Icon,
|
||||
ImageFit,
|
||||
Image,
|
||||
ImageLoadState,
|
||||
Spinner,
|
||||
SpinnerSize,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
Label,
|
||||
Icon,
|
||||
ImageFit,
|
||||
Image,
|
||||
ImageLoadState,
|
||||
} from 'office-ui-fabric-react';
|
||||
|
||||
|
||||
export default class Carousel extends React.Component<ICarouselProps, ICarouselState> {
|
||||
private spService: spservices = null;
|
||||
private _teamsContext: microsoftTeams.Context = null;
|
||||
private spService: spservices = null;
|
||||
private _teamsContext: microsoftTeams.Context = null;
|
||||
|
||||
|
||||
public constructor(props: ICarouselProps) {
|
||||
super(props);
|
||||
this.spService = new spservices(this.props.context);
|
||||
public constructor(props: ICarouselProps) {
|
||||
super(props);
|
||||
this.spService = new spservices(this.props.context);
|
||||
|
||||
if (this.props.context.microsoftTeams) {
|
||||
this.props.context.microsoftTeams.getContext(context => {
|
||||
this._teamsContext = context;
|
||||
console.log('ctt', this._teamsContext.theme);
|
||||
this.setState({ teamsTheme: this._teamsContext.theme });
|
||||
});
|
||||
if (this.props.context.microsoftTeams) {
|
||||
this.props.context.microsoftTeams.getContext(context => {
|
||||
this._teamsContext = context;
|
||||
console.log('ctt', this._teamsContext.theme);
|
||||
this.setState({ teamsTheme: this._teamsContext.theme });
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.state = {
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
hasError: false,
|
||||
teamsTheme: 'default',
|
||||
photoIndex: 0,
|
||||
carouselImages: [],
|
||||
loadingImage: true
|
||||
};
|
||||
}
|
||||
this.state = {
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
hasError: false,
|
||||
teamsTheme: 'default',
|
||||
photoIndex: 0,
|
||||
carouselImages: [],
|
||||
loadingImage: true
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private onConfigure() {
|
||||
// Context of the web part
|
||||
this.props.context.propertyPane.open();
|
||||
}
|
||||
private onConfigure() {
|
||||
// Context of the web part
|
||||
this.props.context.propertyPane.open();
|
||||
}
|
||||
|
||||
|
||||
private async loadPictures() {
|
||||
private async loadPictures() {
|
||||
|
||||
this.setState({ isLoading: true, hasError: false });
|
||||
const tenantUrl = `https://${location.host}`;
|
||||
let galleryImages: ICarouselImages[] = [];
|
||||
let carouselImages: React.ReactElement<HTMLElement>[] = [];
|
||||
this.setState({ isLoading: true, hasError: false });
|
||||
const tenantUrl = `https://${location.host}`;
|
||||
let galleryImages: ICarouselImages[] = [];
|
||||
let carouselImages: React.ReactElement<HTMLElement>[] = [];
|
||||
|
||||
try {
|
||||
const images = await this.spService.getImages(this.props.siteUrl, this.props.list, this.props.numberImages);
|
||||
try {
|
||||
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
|
||||
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 `;
|
||||
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 thumbnailUrl = `${tenantUrl}/_api/v2.0/sharePoint:${image.File.ServerRelativeUrl}:/driveItem/thumbnails/0/c240x240/content?preferNoRedirect=true `;
|
||||
|
||||
let mediaType: string = '';
|
||||
switch (image.File_x0020_Type) {
|
||||
case ('jpg' || 'jpeg' || 'png' || 'tiff' || 'gif'):
|
||||
mediaType = 'image';
|
||||
break;
|
||||
case ('mp4'):
|
||||
mediaType = 'video';
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
let mediaType: string = '';
|
||||
switch (image.File_x0020_Type) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
case 'png':
|
||||
case 'tiff':
|
||||
case 'gif':
|
||||
mediaType = 'image';
|
||||
break;
|
||||
case 'mp4':
|
||||
mediaType = 'video';
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
galleryImages.push(
|
||||
{
|
||||
imageUrl: pURL,
|
||||
mediaType: mediaType,
|
||||
serverRelativeUrl: image.File.ServerRelativeUrl,
|
||||
caption: image.Title ? image.Title : image.File.Name,
|
||||
description: image.Description ? image.Description : '',
|
||||
linkUrl: ''
|
||||
},
|
||||
);
|
||||
galleryImages.push(
|
||||
{
|
||||
imageUrl: pURL,
|
||||
mediaType: mediaType,
|
||||
serverRelativeUrl: image.File.ServerRelativeUrl,
|
||||
caption: image.Title ? image.Title : image.File.Name,
|
||||
description: image.Description ? image.Description : '',
|
||||
linkUrl: ''
|
||||
},
|
||||
);
|
||||
|
||||
// Create Carousel Slides from Images
|
||||
// Create Carousel Slides from Images
|
||||
|
||||
carouselImages = galleryImages.map((galleryImage, i) => {
|
||||
return (
|
||||
<div className='slideLoading' >
|
||||
carouselImages = galleryImages.map((galleryImage, i) => {
|
||||
return (
|
||||
<div className='slideLoading' >
|
||||
|
||||
{galleryImage.mediaType == 'video' ?
|
||||
<div >
|
||||
<Player
|
||||
poster={galleryImage.imageUrl}
|
||||
style={{ width: '100%', height: '400px' }}>
|
||||
<BigPlayButton position="center" />
|
||||
<source src={galleryImage.serverRelativeUrl}
|
||||
/>
|
||||
</Player>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<Image src={galleryImage.imageUrl}
|
||||
onLoadingStateChange={async (loadState: ImageLoadState) => {
|
||||
console.log('imageload Status ' + i, loadState, galleryImage.imageUrl);
|
||||
if (loadState == ImageLoadState.loaded) {
|
||||
this.setState({ loadingImage: false });
|
||||
}
|
||||
}}
|
||||
height={'400px'}
|
||||
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' }}>
|
||||
<h2 style={{fontSize: FontSizes.size20, textTransform: 'uppercase', color: 'white' }}>{galleryImage.caption}</h2>
|
||||
<p>{galleryImage.description}</p>
|
||||
</div>
|
||||
{galleryImage.mediaType == 'video' ?
|
||||
<div >
|
||||
<Player
|
||||
poster={galleryImage.imageUrl}
|
||||
style={{ width: '100%', height: '400px' }}>
|
||||
<BigPlayButton position="center" />
|
||||
<source src={galleryImage.serverRelativeUrl}
|
||||
/>
|
||||
</Player>
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
<Image src={galleryImage.imageUrl}
|
||||
onLoadingStateChange={async (loadState: ImageLoadState) => {
|
||||
console.log('imageload Status ' + i, loadState, galleryImage.imageUrl);
|
||||
if (loadState == ImageLoadState.loaded) {
|
||||
this.setState({ loadingImage: false });
|
||||
}
|
||||
}}
|
||||
height={'400px'}
|
||||
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' }}>
|
||||
<h2 style={{ fontSize: FontSizes.size20, textTransform: 'uppercase', color: 'white' }}>{galleryImage.caption}</h2>
|
||||
<p>{galleryImage.description}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
this.setState({ carouselImages: carouselImages, isLoading: false });
|
||||
}
|
||||
} catch (error) {
|
||||
this.setState({ hasError: true, errorMessage: decodeURIComponent(error.message) });
|
||||
}
|
||||
}
|
||||
this.setState({ carouselImages: carouselImages, isLoading: false });
|
||||
}
|
||||
} catch (error) {
|
||||
this.setState({ hasError: true, errorMessage: decodeURIComponent(error.message) });
|
||||
}
|
||||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
await this.loadPictures();
|
||||
}
|
||||
public async componentDidMount() {
|
||||
await this.loadPictures();
|
||||
}
|
||||
|
||||
public async componentDidUpdate(prevProps: ICarouselProps) {
|
||||
public async componentDidUpdate(prevProps: ICarouselProps) {
|
||||
|
||||
if (!this.props.list || !this.props.siteUrl) return;
|
||||
// Get Properties change
|
||||
if (prevProps.list !== this.props.list || prevProps.numberImages !== this.props.numberImages) {
|
||||
/*
|
||||
this.galleryImages = [];
|
||||
this._carouselImages = [];
|
||||
this.setState({ images: this.galleryImages, carouselImages: t.his._carouselImages, isLoading: false });
|
||||
*/
|
||||
await this.loadPictures();
|
||||
}
|
||||
}
|
||||
public render(): React.ReactElement<ICarouselProps> {
|
||||
const sliderSettings = {
|
||||
dots: true,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1,
|
||||
lazyLoad: 'progressive',
|
||||
autoplaySpeed: 3000,
|
||||
initialSlide: this.state.photoIndex,
|
||||
arrows: true,
|
||||
draggable: true,
|
||||
adaptiveHeight: true,
|
||||
useCSS: true,
|
||||
useTransform: true,
|
||||
};
|
||||
if (!this.props.list || !this.props.siteUrl) return;
|
||||
// Get Properties change
|
||||
if (prevProps.list !== this.props.list || prevProps.numberImages !== this.props.numberImages) {
|
||||
/*
|
||||
this.galleryImages = [];
|
||||
this._carouselImages = [];
|
||||
this.setState({ images: this.galleryImages, carouselImages: t.his._carouselImages, isLoading: false });
|
||||
*/
|
||||
await this.loadPictures();
|
||||
}
|
||||
}
|
||||
public render(): React.ReactElement<ICarouselProps> {
|
||||
const sliderSettings = {
|
||||
dots: true,
|
||||
infinite: true,
|
||||
speed: 500,
|
||||
slidesToShow: 1,
|
||||
slidesToScroll: 1,
|
||||
lazyLoad: 'progressive',
|
||||
autoplaySpeed: 3000,
|
||||
initialSlide: this.state.photoIndex,
|
||||
arrows: true,
|
||||
draggable: true,
|
||||
adaptiveHeight: true,
|
||||
useCSS: true,
|
||||
useTransform: true,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.carousel}>
|
||||
<div>
|
||||
</div>
|
||||
{
|
||||
(!this.props.list) ?
|
||||
<Placeholder iconName='Edit'
|
||||
iconText={strings.WebpartConfigIconText}
|
||||
description={strings.WebpartConfigDescription}
|
||||
buttonLabel={strings.WebPartConfigButtonLabel}
|
||||
hideButton={this.props.displayMode === DisplayMode.Read}
|
||||
onConfigure={this.onConfigure.bind(this)} />
|
||||
:
|
||||
this.state.hasError ?
|
||||
<MessageBar messageBarType={MessageBarType.error}>
|
||||
{this.state.errorMessage}
|
||||
</MessageBar>
|
||||
:
|
||||
this.state.isLoading ?
|
||||
<Spinner size={SpinnerSize.large} label='loading images...' />
|
||||
:
|
||||
this.state.carouselImages.length == 0 ?
|
||||
<div style={{ width: '300px', margin: 'auto' }}>
|
||||
<Icon iconName="PhotoCollection"
|
||||
style={{ fontSize: '250px', color: '#d9d9d9' }} />
|
||||
<Label style={{ width: '250px', margin: 'auto', fontSize: FontSizes.size20 }}>No images in the library</Label>
|
||||
</div>
|
||||
:
|
||||
<div style={{ width: '100%', height: '100%'}}>
|
||||
return (
|
||||
<div className={styles.carousel}>
|
||||
<div>
|
||||
</div>
|
||||
{
|
||||
(!this.props.list) ?
|
||||
<Placeholder iconName='Edit'
|
||||
iconText={strings.WebpartConfigIconText}
|
||||
description={strings.WebpartConfigDescription}
|
||||
buttonLabel={strings.WebPartConfigButtonLabel}
|
||||
hideButton={this.props.displayMode === DisplayMode.Read}
|
||||
onConfigure={this.onConfigure.bind(this)} />
|
||||
:
|
||||
this.state.hasError ?
|
||||
<MessageBar messageBarType={MessageBarType.error}>
|
||||
{this.state.errorMessage}
|
||||
</MessageBar>
|
||||
:
|
||||
this.state.isLoading ?
|
||||
<Spinner size={SpinnerSize.large} label='loading images...' />
|
||||
:
|
||||
this.state.carouselImages.length == 0 ?
|
||||
<div style={{ width: '300px', margin: 'auto' }}>
|
||||
<Icon iconName="PhotoCollection"
|
||||
style={{ fontSize: '250px', color: '#d9d9d9' }} />
|
||||
<Label style={{ width: '250px', margin: 'auto', fontSize: FontSizes.size20 }}>No images in the library</Label>
|
||||
</div>
|
||||
:
|
||||
<div style={{ width: '100%', height: '100%' }}>
|
||||
|
||||
<div style={{ width: '100%'}}>
|
||||
<Slider
|
||||
{...sliderSettings}
|
||||
autoplay={true}
|
||||
onReInit={() => {
|
||||
if (!this.state.loadingImage)
|
||||
$(".slideLoading").removeClass("slideLoading");
|
||||
}}>
|
||||
{
|
||||
this.state.carouselImages
|
||||
}
|
||||
</Slider>
|
||||
</div>
|
||||
{
|
||||
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>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div style={{ width: '100%' }}>
|
||||
<Slider
|
||||
{...sliderSettings}
|
||||
autoplay={true}
|
||||
onReInit={() => {
|
||||
if (!this.state.loadingImage)
|
||||
$(".slideLoading").removeClass("slideLoading");
|
||||
}}>
|
||||
{
|
||||
this.state.carouselImages
|
||||
}
|
||||
</Slider>
|
||||
</div>
|
||||
{
|
||||
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>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
|
Loading…
Reference in New Issue