Merge pull request #1978 from omarelanis/master

This commit is contained in:
Hugo Bernier 2021-08-01 21:16:49 -04:00 committed by GitHub
commit c2addb4c66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 183 additions and 160 deletions

View File

@ -33,6 +33,7 @@ hero-webpart | [Omar El-Anis](https://github.com/omarelanis) @ SP Bytes www.spby
Version|Date|Comments
-------|----|--------
1.2|July 27, 2021|Updated to automatically detect how many items are being displayed and adjust the display layout based on this<br/>Updated design to show the title on all images<br/>Updated description area on hover<br/>Updated hover effect of image to show a zoom effect when hovering over an item<br/>General cleaning up of CSS and code
1.1|March 10, 2021|Update comment
1.0|January 29, 2021|Initial release

View File

@ -9,7 +9,7 @@
"This solution creates a customisable Hero web part, it uses a stored collection from the PnP PropertyFieldCollectionData control "
],
"creationDateTime": "2021-04-02",
"updateDateTime": "2021-04-02",
"updateDateTime": "2021-07-27",
"products": [
"SharePoint",
"Office"

View File

@ -3,7 +3,7 @@
"solution": {
"name": "Hero Layout Webpart",
"id": "5efc0426-3e59-4fc7-b638-73eb77aaf788",
"version": "1.0.0.0",
"version": "1.2.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,

View File

@ -1,6 +1,6 @@
{
"name": "hero-webpart",
"version": "0.0.1",
"version": "1.2.0",
"private": true,
"main": "lib/index.js",
"scripts": {

View File

@ -26,7 +26,8 @@
"isPaginated": false,
"hideFirstPageJump": false,
"hideLastPageJump": false,
"showAllHero": false
"showAllHero": false,
"totalShow": 5
}
}
],

View File

@ -25,7 +25,8 @@
"isPaginated":false,
"hideFirstPageJump":false,
"hideLastPageJump":false,
"showAllHero":false
"showAllHero":false,
"totalShow":5
}
}]
}

View File

@ -12,6 +12,7 @@ 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';
@ -105,27 +106,28 @@ export default class HeroWebpartWebPart extends BaseClientSideWebPart<IHeroWebpa
title: "Select File",
type: CustomCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => {
return (
React.createElement(FilePicker, {
key: itemId,
context: this.context,
buttonLabel:"Select File",
onChange: (selectedFile: IFilePickerResult[]) => {
onUpdate(field.id, selectedFile);
return (
React.createElement(FilePicker, {
key: itemId,
context: this.context,
buttonLabel:"Select File",
onChange: (selectedFile: IFilePickerResult[]) => {
onUpdate(field.id, selectedFile);
return Event;
},
onSave: (filePickerResult: IFilePickerResult[]) => {
// write code to save file to SharePoint doc library
// if you are uploading the file via the upload tab which I've not implemented here
onUpdate(field.id, filePickerResult);
return Event;
},
onSave: (filePickerResult: IFilePickerResult[]) => {
// write code to save file to SharePoint doc library
// if you are uploading the file via the upload tab which I've not implemented here
onUpdate(field.id, filePickerResult);
return Event;
},
hideLocalUploadTab: true,
hideLocalMultipleUploadTab: true,
hideLinkUploadTab: true
})
);
}
},
hideLocalUploadTab: true,
hideLocalMultipleUploadTab: true,
hideLinkUploadTab: true
})
);
},
required: true
}
],
disabled: false

View File

@ -11,12 +11,15 @@ 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" :
items.length==4 ? "heroFour" : items.length==5 ? "heroFive" : "heroFive";
var arr = [];
arr.push(items);
return (
<div role="group">
<div role="group" className={viewType}>
<List
role="presentation"
className={styles.heroItem}
@ -37,7 +40,7 @@ export default class Hero extends React.Component<IHeroLayoutProps> {
const thumbRend = "https://media.akamai.odsp.cdn.office.net/uksouth1-mediap.svc.ms/transform/thumbnail?provider=url&inputFormat=jpg&docid=";
const secondItems = items.slice(1,5);
const firstItem = items.slice(0,1)[0];
var firstItemUrl = firstItem.filePicker[0].Hyperlink ? firstItem.filePicker[0].Hyperlink : "#";
var firstItemUrl = firstItem.Hyperlink ? firstItem.Hyperlink : "#";
var smalltemUrl;
return(
<div className={styles.heroItem}>
@ -46,18 +49,20 @@ export default class Hero extends React.Component<IHeroLayoutProps> {
<div className={styles["flexitems"]}>
<a href={firstItemUrl}>
<img src={firstItem.filePicker[0].fileNameWithoutExtension=='blankEntry154873'?firstItem.filePicker[0].fileAbsoluteUrl:thumbRend+firstItem.filePicker[0].fileAbsoluteUrl+"&w=960"}/>
<div className={styles.description}><div className={styles.heroTitle}>{firstItem.Title}</div>{firstItem.Description ? firstItem.Description.length>150 ? firstItem.Description.substring(0, 150)+".." : firstItem.Description : "Description coming soon"}</div>
<div className={styles.heroTitle}>{firstItem.Title}</div>
<div className={styles.description}><div className={styles.heroTitleHover}>{firstItem.Title}</div><div className={styles.info}>{firstItem.Description ? firstItem.Description.length>150 ? firstItem.Description.substring(0, 150)+".." : firstItem.Description : "Description coming soon"}</div></div>
</a>
</div>
</div>
</div>
<div className={styles["flexcontainer"]}>
{secondItems.map((item) => (
smalltemUrl= item.filePicker[0].Hyperlink ? item.filePicker[0].Hyperlink : "#",
smalltemUrl= item.Hyperlink ? item.Hyperlink : "#",
<div className={styles["flexitems"]}>
<a href={smalltemUrl}>
<img src={item.filePicker[0].fileNameWithoutExtension=='blankEntry154873'?item.filePicker[0].fileAbsoluteUrl:thumbRend+item.filePicker[0].fileAbsoluteUrl+"&w=960"}/>
<div className={styles.description}><div className={styles.heroTitle}>{item.Title}</div>{item.Description ? item.Description.length>150 ? item.Description.substring(0, 150)+".." : item.Description : "Description coming soon"}</div>
<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>
))}

View File

@ -72,91 +72,62 @@
}
}
.carouselContent{
color:"[theme: themeSecondary, default: #0078d7]";
min-height:600px;
height:600px;
}
.carouselButtonsContainer{
color:"[theme: themeSecondary, default: #0078d7]";
}
.carouselContentOne, .carouselContentTwo, .carouselContentThree, .carouselContentFour{
color:"[theme: themeSecondary, default: #0078d7]";
min-height:530px;
height:530px;
}
.carouselContentOne{
:global(.ms-List-page .ms-List-cell){
width: 100%!important;
padding:0%
}
:global(.ms-List-page .ms-List-cell div) {
width: 100%!important;
}
}
.carouselContentTwo {
:global(.ms-List-page .ms-List-cell){
width: 46%!important;
padding:2%
}
:global(.ms-List-page .ms-List-cell div) {
width: 100%!important;
}
}
.carouselContentThree{
:global(.ms-List-page .ms-List-cell){
width: 29%!important;
padding:2%
}
:global(.ms-List-page .ms-List-cell div) {
width: 100%!important;
}
}
.carouselContentFour{
:global(.ms-List-page .ms-List-cell){
width: 24%!important;
padding:1%
}
:global(.ms-List-page .ms-List-cell div) {
width: 100%!important;
}
}
.heroTitle{
.heroTitleHover{
@include ms-font-xl;
padding-bottom: 10px;
font-weight: 600;
}
.heroTitle{
@include ms-fontColor-white;
font-size: 26px;
font-weight: 600;
position: absolute;
bottom: 5px;
width: 100%;
padding: 30px 0px;;
text-align: center;
background-image: linear-gradient(180deg,transparent 15%,rgba(0,0,0,.7));
height: fit-content!important;
}
.info,.heroTitleHover{
opacity: 0;
}
.heroItem {
flex: auto;
flex-grow: 0;
flex-shrink: 0;
display: flex;
.flexcontainer .flexitems:hover img{
transform: scale(1.1);
transition: .4s ease;
}
.flexcontainer .flexitems:hover .heroTitle{
opacity: 0;
}
.flexcontainer .flexitems:hover .description {
opacity: 1;
background: rgba(0, 0, 0, 0.9);
.info,.heroTitleHover{
opacity: 1;
}
}
.flexcontainer .flexitems .description{
@include ms-fontColor-white;
position: absolute;
bottom: 5px;
background: rgba(0, 0, 0, 0.9);
color: #f1f1f1;
width: calc(100% - 40px);
transition: .5s ease;
opacity: 0;
color: white;
font-size: 16px;
padding: 20px 0px;;
text-align: center;
}
@include ms-fontColor-white;
position: absolute;
bottom: 0px;
background: rgba(0, 0, 0, 0);
width: calc(100% - 40px);
transition: .5s ease;
font-size: 18px;
padding: 20px 0px;;
text-align: center;
}
.flexcontainer .flexitems{
overflow: hidden;
@ -164,10 +135,14 @@
.flexcontainer:nth-child(1){
flex: auto;
flex-basis: 40%;
flex-basis: 50%;
flex-shrink: 1;
padding-right:5px;
padding-bottom: 7px;
padding-bottom: 5px;
.heroTitle{
width: 100%;
}
*{
height: 100%;
@ -201,33 +176,115 @@
.flexcontainer:nth-child(2) {
flex: auto;
flex-basis: 60%;
flex-basis: 50%;
flex-grow: 0;
flex-shrink: 0;
display: flex;
display: flex;
flex-direction: row;
flex-wrap: wrap;
.heroTitle{
width: calc(100% - 5px);
}
img{
width:100%;
height:100%;
}
.description {
width: calc(100% - 5px);
width: 100%;
}
.flexitems{
padding-right:5px;
flex-basis: calc(50% - 5px);
flex-shrink: 1;
flex-grow: 1;
align-self: auto;
position: relative;
padding-bottom: 5px;
min-height: 200px;
}
.flexitems:hover{
margin-bottom: 5px;
}
}
}
:global(.heroThree) .heroItem {
.flexcontainer:nth-child(1){
flex-basis: 60%;
.focusItem .flexitems{
padding-bottom: 5px;
}
}
.flexcontainer:nth-child(2)
{
flex-basis: 40%;
.flexitems {
flex-basis: 50%;
flex-direction: column;
}
}
}
:global(.heroFive) .heroItem {
.flexcontainer:nth-child(1){
min-height: 400px;
}
}
:global(.heroOne) .heroItem {
display: inline-block;
width: 100%;
.flexcontainer:nth-child(1){
min-height: 400px;
.focusItem .flexitems{
max-height: 400px;
}
}
}
:global(.heroThree) .heroItem .flexcontainer:nth-child(2) {
.heroTitle {
font-size: 24px;
}
.heroTitleHover{
font-size: 22px;
}
.info{
font-size: 18px;
}
}
:global(.heroFour) .heroItem .flexcontainer:nth-child(2){
.heroTitle {
font-size: 20px;
}
.heroTitleHover{
font-size: 18px;
}
.info{
font-size: 14px;
}
}
:global(.heroFive) .heroItem .flexcontainer:nth-child(2){
.heroTitle {
font-size: 20px;
}
.heroTitleHover{
font-size: 18px;
}
.info{
font-size: 14px;
}
}
@media all and (max-width: 768px) {
.heroItem {
@ -240,55 +297,4 @@
}
}
}
@media only screen and (max-width: 600px) {
.carouselContentOne, .carouselContentTwo, .carouselContentThree, .carouselContentFour{
:global(.ms-List-page .ms-List-cell){
width: 100%!important;
height: 160px;
}
:global(.ms-List-page .ms-List-cell img){
width: 100%!important;
height: 100px!important;
}
:global(.ms-List-page .ms-List-cell .ms-Image){
width: 100%!important;
height: 100px!important;
}
:global(.ms-List-page .ms-List-cell div){
max-height: 100px;
}
:global(.ms-List-page .ms-List-cell div){
max-height: 100px;
}
:global(.ms-List-page .ms-List-cell .ms-DocumentCardLocation){
display:none;
}
:global(.ms-List-page .ms-List-cell){
.subGroup{
display:none;
}
}
:global(.ms-List-page .ms-List-cell){
.subGroup ~ .subGroup{
display:inline-block;
}
}
:global(.ms-List-page .ms-List-cell){
.subGroup ~ .subGroup a{
display:inline-block;
width: 48%!important;
float: left;
}
}
:global(.ms-List-page .ms-List-cell){
.subGroup ~ .subGroup a *{
font-size:8px
}
}
:global(.ms-List-page .ms-List-cell .ms-DocumentCardDetails .ms-DocumentCardTitle:nth-child(2)){
display:none;
}
}
}
}

View File

@ -2,10 +2,7 @@ import * as React from 'react';
import styles from './HeroWebpart.module.scss';
import { IHeroWebpartProps } from './IHeroWebpartProps';
import {IHeroState} from './IHeroWebpartState';
import { escape } from '@microsoft/sp-lodash-subset';
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
import { PnPClientStorage } from "@pnp/common";
import { IHeroLayoutProps } from './IHeroLayoutProps';
import Hero from './HeroLayout';
import { sp } from '@pnp/sp';
import { Stack, IStackProps, IStackTokens } from 'office-ui-fabric-react/lib/Stack';
@ -25,8 +22,6 @@ const tokens = {
},
};
const storage = new PnPClientStorage();
export default class HeroWebpart extends React.Component<IHeroWebpartProps, IHeroState> {
constructor(props: IHeroWebpartProps) {
@ -73,6 +68,18 @@ export default class HeroWebpart extends React.Component<IHeroWebpartProps, IHer
return b;
}
public componentDidUpdate(prevProps : IHeroWebpartProps, prevState : IHeroState) : void
{
// If properties have changed bind it and update webpart
if(this.props.items !== prevProps.items)
{
this.setState({items:this.props.items});
if(this.props.showAllHero){
this._getPage(this.state.currentPage);
}
}
}
public render(): React.ReactElement<IHeroWebpartProps> {
if(this.state.items.length<=0){
this._getItems();