Fixed pagination with Filmstrip
This commit is contained in:
parent
c24bb65e3a
commit
aab6481bb2
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Title",
|
||||
"PropertyPaneDescription": "Display the highlights and goals of the latest soccer matches ",
|
||||
"BasicGroupName": "General",
|
||||
"DescriptionFieldLabel": "Title"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue