Added Collage Feature

- At the request of another user a option has been added to allow a collage of images to be shown in a flex grid layout
- Added in placeholder configuration screen
- Fixed webpart not loading the 5 temporary items on first adding webpart to new page in local workbench
- General maintenance to remove unused imports
- Updated CSS to add in collage feature
This commit is contained in:
Omar 2022-03-11 01:11:48 +00:00
parent 51eebc82de
commit 47ddd9bcfa
8 changed files with 135 additions and 20 deletions

View File

@ -1,6 +1,6 @@
{
"name": "hero-webpart",
"version": "0.0.1",
"version": "1.2.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -2,7 +2,7 @@
"id": "71d58a4f-1896-46aa-94a5-dbef33d14166",
"alias": "HeroWebpartWebPart",
"componentType": "WebPart",
"version": "0.0.1",
"version": "1.2.0",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [

View File

@ -12,13 +12,13 @@ import HeroWebpart from './components/HeroWebpart';
import { IHeroWebpartProps } from './components/IHeroWebpartProps';
import { PropertyFieldToggleWithCallout } from '@pnp/spfx-property-controls/lib/PropertyFieldToggleWithCallout';
import { PropertyFieldSliderWithCallout } from '@pnp/spfx-property-controls/lib/PropertyFieldSliderWithCallout';
import { CalloutTriggers } from '@pnp/spfx-property-controls/lib/PropertyFieldHeader';
import { PropertyFieldCollectionData, CustomCollectionFieldType } from '@pnp/spfx-property-controls/lib/PropertyFieldCollectionData';
import { PropertyFieldFilePicker, IPropertyFieldFilePickerProps, IFilePickerResult } from "@pnp/spfx-property-controls/lib/PropertyFieldFilePicker";
import { FilePicker , IFilePickerProps } from '@pnp/spfx-controls-react/lib/FilePicker';
import { IFilePickerResult } from "@pnp/spfx-property-controls/lib/PropertyFieldFilePicker";
import { FilePicker } from '@pnp/spfx-controls-react/lib/FilePicker';
import { PropertyPaneWebPartInformation } from '@pnp/spfx-property-controls/lib/PropertyPaneWebPartInformation';
import { DisplayMode } from '@microsoft/sp-core-library';
export interface IHeroWebpartWebPartProps {
title: string;
@ -26,9 +26,11 @@ export interface IHeroWebpartWebPartProps {
hideFirstPageJump: boolean;
hideLastPageJump: boolean;
showAllHero: boolean;
showCollage: boolean;
collectionData: any[];
filePickerResult: IFilePickerResult;
pageLimit:number;
displayMode: DisplayMode;
}
export default class HeroWebpartWebPart extends BaseClientSideWebPart<IHeroWebpartWebPartProps> {
@ -42,9 +44,11 @@ export default class HeroWebpartWebPart extends BaseClientSideWebPart<IHeroWebpa
hideFirstPageJump:this.properties.hideFirstPageJump,
hideLastPageJump:this.properties.hideLastPageJump,
spfxContext: this.context,
showAllHero: this.properties.showAllHero,
showAllHero: this.properties.showAllHero?this.properties.showAllHero:false,
showCollage: this.properties.showCollage?this.properties.showCollage:false,
pageLimit:5,
items:this.properties.collectionData?this.properties.collectionData:[]
items:this.properties.collectionData?this.properties.collectionData:[],
displayMode: this.displayMode,
}
);
@ -132,11 +136,20 @@ export default class HeroWebpartWebPart extends BaseClientSideWebPart<IHeroWebpa
],
disabled: false
}),
PropertyFieldToggleWithCallout('showCollage', {
calloutTrigger: CalloutTriggers.Hover,
key: 'showCollage',
label: 'Show collage of all images?',
calloutContent: React.createElement('p', {}, 'Enabling this will show all images in a collage view'),
onText: 'ON',
offText: 'OFF',
checked: this.properties.showCollage,
}),
PropertyFieldToggleWithCallout('showAllHero', {
calloutTrigger: CalloutTriggers.Hover,
key: 'showAllHeroFieldId',
label: 'Show all courses in Hero view?',
calloutContent: React.createElement('p', {}, 'Enabling this will show all courses in the Hero view'),
label: 'Show all images in Hero view?',
calloutContent: React.createElement('p', {}, 'Enabling this will show all images in the Hero view'),
onText: 'ON',
offText: 'OFF',
checked: this.properties.showAllHero,

View File

@ -11,9 +11,8 @@ export default class Hero extends React.Component<IHeroLayoutProps> {
public render(): React.ReactElement<IHeroLayoutProps> {
//const classTotal = "itemShow"+this.props.totalShow;
const items = this.props.items;
const viewType = items.length==1 ? "heroOne" : items.length==2 ? "heroTwo" : items.length==3 ? "heroThree" :
const viewType = this.props.isCollage ? "heroCollage" : items.length==1 ? "heroOne" : items.length==2 ? "heroTwo" : items.length==3 ? "heroThree" :
items.length==4 ? "heroFour" : items.length==5 ? "heroFive" : "heroFive";
var arr = [];
arr.push(items);
@ -25,7 +24,7 @@ export default class Hero extends React.Component<IHeroLayoutProps> {
className={styles.heroItem}
items={arr}
getItemCountForPage={this._getItemCountForPage}
onRenderCell={this._onRenderHeroItem}
onRenderCell={this.props.isCollage?this._onRenderHeroCollage:this._onRenderHeroItem}
{...this.props.listProps}
/>
</div>
@ -70,4 +69,25 @@ export default class Hero extends React.Component<IHeroLayoutProps> {
</div>
);
}
private _onRenderHeroCollage = (items: any, index: number | undefined): JSX.Element => {
const thumbRend = "https://media.akamai.odsp.cdn.office.net/uksouth1-mediap.svc.ms/transform/thumbnail?provider=url&inputFormat=jpg&docid=";
var smalltemUrl;
return(
<div className={styles["collageContainer"]}>
{items.map((item) => (
smalltemUrl= item.Hyperlink ? item.Hyperlink : "#",
<div className={styles["collageitem"]}>
<div className={styles["collageItemInner"]}>
<a href={smalltemUrl}>
<img src={item.filePicker[0].fileNameWithoutExtension=='blankEntry154873'?item.filePicker[0].fileAbsoluteUrl:thumbRend+item.filePicker[0].fileAbsoluteUrl+"&w=960"}/>
<div className={styles.heroTitle}>{item.Title}</div>
<div className={styles.description}><div className={styles.heroTitleHover}>{item.Title}</div><div className={styles.info}>{item.Description ? item.Description.length>150 ? item.Description.substring(0, 150)+".." : item.Description : "Description coming soon"}</div></div>
</a>
</div>
</div>
))}
</div>
);
}
}

View File

@ -284,6 +284,65 @@
font-size: 14px;
}
}
:global(.heroCollage) .collageContainer
{
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
.collageitem {
overflow: hidden;
flex-shrink: 1;
padding: 6px;
width: calc(33% - 12px);
a{
width: 100%;
}
img{
width: inherit;
}
.heroTitle {
font-size: 14px;
width: calc(33% - 12px);
margin: -80px 0px 0px 0px;
position: absolute;
bottom: unset;
}
.heroTitleHover{
font-size: 16px;
}
.info{
font-size: 12px;
}
.description{
@include ms-fontColor-white;
position: absolute;
margin: -90px 0px 0px 0px;
bottom: unset;
background: rgba(0, 0, 0, 0);
width: calc(33% - 12px);
transition: .5s ease;
font-size: 18px;
padding: 20px 0px;;
text-align: center;
}
}
.collageItemInner:hover {
.description {
background: rgba(0, 0, 0, 0.9);
width: calc(33% - 12px);
position: absolute;
margin: -90px 0px 0px 0px;
bottom: unset;
.info,.heroTitleHover{
opacity: 1;
}
}
}
}
@media all and (max-width: 768px) {

View File

@ -8,6 +8,8 @@ import { sp } from '@pnp/sp';
import { Stack, IStackProps, IStackTokens } from 'office-ui-fabric-react/lib/Stack';
import { Label } from 'office-ui-fabric-react/lib/Label';
import { Spinner, SpinnerSize } from 'office-ui-fabric-react/lib/Spinner';
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
import { DisplayMode } from '@microsoft/sp-core-library';
const stackTokens: IStackTokens = { childrenGap: 20 };
@ -87,11 +89,17 @@ export default class HeroWebpart extends React.Component<IHeroWebpartProps, IHer
<Stack {...rowProps} tokens={tokens.spinnerStack}>
<Label>Loading</Label>
<Spinner size={SpinnerSize.large} />
</Stack>
</Stack> &&
<Placeholder iconName='Edit'
iconText='Configure your web part'
description='Please configure the web part.'
buttonLabel='Configure'
hideButton={this.props.displayMode === DisplayMode.Read}
onConfigure={this._onConfigure} />
);
}else{
var itemList:any[];
this.props.showAllHero ? itemList = this.state.itemsPaginated : itemList = this.state.items;
var itemList:any[] = this.state.items;
this.props.showAllHero && !this.props.showCollage ? itemList = this.state.itemsPaginated : itemList = this.state.items;
}
return (
@ -99,9 +107,10 @@ export default class HeroWebpart extends React.Component<IHeroWebpartProps, IHer
<div className={styles.titleHead}>
{this.props.title}
</div>
<Hero items={this.props.showAllHero ? this.state.itemsPaginated : this.state.items.slice(0, 5)}/>
{this.props.showAllHero ?
<Pagination
{this.props.showAllHero &&
<>
<Hero items={this.props.showAllHero ? this.state.itemsPaginated : this.state.items.slice(0, 5)} isCollage={this.props.showCollage}/>
<Pagination
currentPage={this.state.currentPage}
totalPages={this.state.totalPages}
onChange={(page) => this._getPage(page)}
@ -109,10 +118,20 @@ export default class HeroWebpart extends React.Component<IHeroWebpartProps, IHer
hideFirstPageJump={this.props.hideFirstPageJump} // Optional
hideLastPageJump={this.props.hideLastPageJump} // Optional
limiterIcon={"Emoji12"} // Optional
/> : "" }
</div>
/>
</>
}
{!this.props.showAllHero &&
<Hero items={this.state.items} isCollage={this.props.showCollage}/>
}
</div>
);
}
private _onConfigure() {
// Context of the web part
this.props.spfxContext.propertyPane.open();
}
}

View File

@ -4,4 +4,5 @@ import { IListProps } from 'office-ui-fabric-react/lib/List';
export interface IHeroLayoutProps {
items:any[];
listProps?: Partial<IListProps>;
isCollage:boolean;
}

View File

@ -1,4 +1,5 @@
import { WebPartContext } from '@microsoft/sp-webpart-base';
import { DisplayMode } from '@microsoft/sp-core-library';
export interface IHeroWebpartProps {
title: string;
@ -8,5 +9,7 @@ export interface IHeroWebpartProps {
hideFirstPageJump: boolean;
hideLastPageJump: boolean;
showAllHero: boolean;
showCollage: boolean;
items:any[];
displayMode: DisplayMode;
}