Merge pull request #1586 from DonKirkham/upgrade-react-carousel

This commit is contained in:
Hugo Bernier 2020-11-04 17:31:10 -05:00 committed by GitHub
commit 9012702df9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 3293 additions and 5125 deletions

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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>
);
}
}

View File

@ -29,7 +29,8 @@
]
},
"include": [
"src/**/*.ts"
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",