Fixed pagination with Filmstrip

This commit is contained in:
Hugo Bernier 2020-11-22 19:16:41 -05:00
parent c24bb65e3a
commit aab6481bb2
8 changed files with 35 additions and 157 deletions

View File

@ -3,7 +3,7 @@
## Summary
- This react web part sample displays Soccer Highlights from a public Soccer API.
- It shows a maxium of 100 highlights at one time.
- It shows a maximum of 100 highlights at one time.
- The web part show live status of game scores and ability to watch them live in small or full screen view.
- You can view the highlights as FilmStrip Control (Thanks to Hugo for the tip and great blog) or Flat Mode.
- You can configure highlights per page and use Paging.
@ -16,13 +16,13 @@
### Usage
**1) Deploy the package to SharePoint Online App Catalog.
1) Deploy the package to SharePoint Online App Catalog.
**2) Add the Web Part to Page, Configure the web Part, provide Title and Page Size.**
2) Add the Web Part to Page, Configure the web Part, provide Title and Page Size.
**3) Add the Web Part to Page, Configure the web Part, provide Title and Page Size.**
3) Add the Web Part to Page, Configure the web Part, provide Title and Page Size.
**4) Click on Pager to move Pages or arrows or dots in filmstrip view. **
4) Click on Pager to move Pages or arrows or dots in filmstrip view.
## Used SharePoint Framework Version
@ -34,6 +34,7 @@
- [Office 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
## Prerequisites
None
## Solution

View File

@ -4971,22 +4971,6 @@
"integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
"dev": true
},
"active-event-stack": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/active-event-stack/-/active-event-stack-1.0.0.tgz",
"integrity": "sha1-a1uS661xmvrpgs1R9Jw4xbaADFA=",
"requires": {
"immutable": "^3.7.4",
"lodash": "^3.9.3"
},
"dependencies": {
"lodash": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
}
}
},
"adal-angular": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/adal-angular/-/adal-angular-1.0.16.tgz",
@ -11084,11 +11068,6 @@
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
"dev": true
},
"immutable": {
"version": "3.8.2",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz",
"integrity": "sha1-wkOZUUVbs5kT2vKBN28VMOEErfM="
},
"import-cwd": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
@ -17288,18 +17267,6 @@
}
}
},
"react-dialog": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-dialog/-/react-dialog-1.0.2.tgz",
"integrity": "sha1-gT/tQPSSlGeTRqMpjUYPe5iCGAE=",
"requires": {
"active-event-stack": "^1.0.0",
"classnames": "^2.2.3",
"react-draggable": "^2.2.6",
"react-onclickoutside": "^5.10.0",
"react-resizable": "^1.7.1"
}
},
"react-dom": {
"version": "16.8.5",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.5.tgz",
@ -17328,14 +17295,6 @@
"resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz",
"integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA="
},
"react-draggable": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-2.2.6.tgz",
"integrity": "sha1-OoBuEPLaa6v+pBNr5lEOibDXaQE=",
"requires": {
"classnames": "^2.2.5"
}
},
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -17370,14 +17329,6 @@
}
}
},
"react-onclickoutside": {
"version": "5.11.1",
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-5.11.1.tgz",
"integrity": "sha1-ADFOUlZ89V+rqUyrus0RlhkHBiM=",
"requires": {
"create-react-class": "^15.5.x"
}
},
"react-paging": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/react-paging/-/react-paging-0.2.1.tgz",
@ -17442,26 +17393,6 @@
"react-dom-factories": "^1.0.0"
}
},
"react-resizable": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-1.11.0.tgz",
"integrity": "sha512-VoGz2ddxUFvildS8r8/29UZJeyiM3QJnlmRZSuXm+FpTqq/eIrMPc796Y9XQLg291n2hFZJtIoP1xC3hSTw/jg==",
"requires": {
"prop-types": "15.x",
"react-draggable": "^4.0.3"
},
"dependencies": {
"react-draggable": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.3.tgz",
"integrity": "sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==",
"requires": {
"classnames": "^2.2.5",
"prop-types": "^15.6.0"
}
}
}
},
"react-slick": {
"version": "0.27.13",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.27.13.tgz",

View File

@ -62,9 +62,6 @@ export default class ReactSpFxWebPart extends BaseClientSideWebPart<IReactSpFxWe
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('title', {
label: strings.DescriptionFieldLabel
}),
PropertyPaneSlider('pageSize',{
label:"Highlights Per Page",
min:1,

View File

@ -46,7 +46,7 @@ export interface ISportsHighlights {
export interface ISportsHighlightProps {
title: string;
embed: string
embed: string;
id: string;
date: Date;
side1: ISide;
@ -54,6 +54,7 @@ export interface ISportsHighlightProps {
competition: ICompetition;
thumbnail: string;
videos: IVideo[];
url: string;
}

View File

@ -1,14 +1,10 @@
import * as React from "react";
import styles from "./ReactSpFx.module.scss";
import { IReactSpFxProps, ISportsHighlightsState } from "./IReactSpFxProps";
import { escape } from "@microsoft/sp-lodash-subset";
import SportsHighlightsList from "./SportsHighlightsList";
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
import { setVirtualParent } from "office-ui-fabric-react";
import SportsHighlights from "./SportsHighlightsList";
import "bootstrap/dist/css/bootstrap.css";
export default class ReactSpFx extends React.Component<IReactSpFxProps> {
@ -17,28 +13,13 @@ export default class ReactSpFx extends React.Component<IReactSpFxProps> {
}
public render(): React.ReactElement<IReactSpFxProps> {
const globalComponent = this;
return (
<div className={styles.container}>
{!this.props.title && (
<Placeholder
iconName="Soccer Highlights"
iconText="Configure your web part"
description="Set Web Part Title and choose Page Size to hide this section."
buttonLabel="Configure the Web Part"
onConfigure={this.props.onConfigure}
/>
)}
{typeof this.props.title !== "undefined" && (
<div id="mainDiv">
<WebPartTitle
displayMode={this.props.displayMode}
title={this.props.title}
updateProperty={this.props.updateProperty}
/>
</div>
)}
<span></span>
<WebPartTitle
displayMode={this.props.displayMode}
title={this.props.title}
updateProperty={this.props.updateProperty}
/>
<SportsHighlightsList pageSize={this.props.pageSize} showFlatMode={this.props.showFlatMode}
/>
</div>

View File

@ -1,8 +1,5 @@
import React from "react";
import ReactDOM from "react-dom";
import { ISportsHighlightProps, ISportsHighlights } from "./IReactSpFxProps";
import SportsVideo from "./SportsVideo";
import ReactMarkdownWithHtml from "react-markdown/with-html";
import { FilmstripLayout } from './filmstripLayout/index';
import styles from './filmstripLayout/FilmstripLayout.module.scss';
@ -13,7 +10,6 @@ import {
DocumentCardDetails,
DocumentCardTitle,
IDocumentCardPreviewProps,
DocumentCardLocation,
DocumentCardType,
} from "office-ui-fabric-react/lib/DocumentCard";
@ -32,24 +28,20 @@ export default class SportVideoListFilmStripView extends React.Component<
isDialogOpen: false,
};
}
openDialog = (video: ISportsHighlightProps) => {
console.log("I awas clicked:" + video.title);
this.setState({ isDialogOpen: true });
};
handleClose = () => this.setState({ isDialogOpen: false });
public render(): React.ReactElement<ISportsHighlights> {
const videos = this.props.highLights;
console.log("Video Highlights", videos);
return (
<div>
<div className={styles.filmStrip}>
<FilmstripLayout
ariaLabel={
"Sample filmstrip layout web part, showing sample items., Use right and left arrow keys to navigate between cards in the film strip."
"Soccer highlights web part, showing soccer highlights. Use right and left arrow keys to navigate between cards in the film strip."
}
>
{this.props.highLights.map((video: ISportsHighlightProps, i) => {
{videos.map((video: ISportsHighlightProps, i) => {
let videoDate = new Date(video.date.toString());
const previewProps: IDocumentCardPreviewProps = {
previewImages: [
@ -70,24 +62,14 @@ export default class SportVideoListFilmStripView extends React.Component<
>
<DocumentCard
type={DocumentCardType.normal}
onClick={(ev: React.SyntheticEvent<HTMLElement>) =>
this.openDialog(video)
}
onClickHref={video.url}
>
{/* <DocumentCardPreview {...previewProps} /> */}
<DocumentCardPreview {...previewProps} />
<DocumentCardDetails>
{/* <DocumentCardTitle
title={video.title}
shouldTruncate={false}
/> */}
<div
id={"video" + video.title}
dangerouslySetInnerHTML={{
__html: video.embed,
}}
style={{ width: 268, padding: "2px" }}
title={"click to play " + video.title}
/>
<DocumentCardTitle
title={video.side1.name+ ' vs ' + video.side2.name}
shouldTruncate={true}
/>
<DocumentCardActivity
activity={
videoDate.toLocaleString()

View File

@ -1,14 +1,10 @@
import React from "react";
import ReactDOM from "react-dom";
import {
ISportsHightLightsProps,
ISportsHighlightPagingState,
ISportsHighlightsState,
ISportsHighlightProps,
} from "./IReactSpFxProps";
//import SportsHighlight from "./SportsHighlight";
import SportVideoListFilmStripView from "./SportVideoListFilmStripView";
import Paging from "react-paging";
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import axios from "axios";
import SportsVideoList from "./SportsVideoList";
@ -34,18 +30,20 @@ export default class SportsHighlightsList extends React.Component<
const data : ISportsHighlightProps[] = await resp.data;
let slicedItems : ISportsHighlightProps[] = data.slice(0, this.props.pageSize);
this.setState({ pagedSportHighlights: data, slicedSportHighlights: slicedItems });
};
}
async componentDidMount() {
public async componentDidMount() {
console.log("Mounted");
this.GetData();
}
public render(): React.ReactElement<ISportsHightLightsProps> {
if(!this.props.showFlatMode){
return <SportVideoListFilmStripView highLights={this.state.slicedSportHighlights} />;
}
let pageCountDivisor: number = this.props.pageSize;
let pageCount: number;
let pageButtons = [];
@ -63,19 +61,8 @@ export default class SportsHighlightsList extends React.Component<
slicedSportHighlights: slicedItems
});
};
// const pagedItems: JSX.Element = (
// <SportVideoListFilmStripView highLights={this.state.slicedSportHighlights} />
// );
var pagedItems: JSX.Element = null;
if(!this.props.showFlatMode){
pagedItems = (<SportVideoListFilmStripView highLights={this.state.slicedSportHighlights} />);
}
else{
pagedItems = (<SportsVideoList videos={this.state.slicedSportHighlights} /> );
}
var pagedItems: JSX.Element = (<SportsVideoList videos={this.state.slicedSportHighlights} /> );
if (highlightItems.length > 0) {
pageCount = Math.ceil(highlightItems.length / pageCountDivisor);
}
@ -90,14 +77,12 @@ export default class SportsHighlightsList extends React.Component<
{i + 1}{" "}
</PrimaryButton>
);
}
}
return (
<div>
<div className={`ms-Grid-row`} style={{paddingLeft:"8px"}}>
<div className={`ms-Grid-row`} style={{paddingLeft:"8px"}}>
<div className="ms-Grid-col ms-u-lg12">{pageButtons}</div>
</div>
<hr />
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-u-lg12">{pagedItems}</div>
</div>

View File

@ -1,6 +1,6 @@
define([], function() {
return {
"PropertyPaneDescription": "Title",
"PropertyPaneDescription": "Display the highlights and goals of the latest soccer matches ",
"BasicGroupName": "General",
"DescriptionFieldLabel": "Title"
}