Merge branch 'main' into patch-2

This commit is contained in:
Hugo Bernier 2021-10-31 14:01:24 -04:00 committed by GitHub
commit 9f9805d6bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
412 changed files with 140519 additions and 29723 deletions

View File

@ -0,0 +1,27 @@
> By submitting this pull request, you agree to the [contribution guidelines](https://github.com/pnp/sp-dev-fx-webparts/blob/main/CONTRIBUTING.md)
> If you aren't familiar with how to contribute to open-source repositories using GitHub, or if you find the instructions on this page confusing, [sign up](https://forms.office.com/Pages/ResponsePage.aspx?id=KtIy2vgLW0SOgZbwvQuRaXDXyCl9DkBHq4A2OG7uLpdUREZVRDVYUUJLT1VNRDM4SjhGMlpUNzBORy4u) for one of our [Sharing is Caring](https://pnp.github.io/sharing-is-caring/#pnp-sic-events) events. It's completely free, and we'll guide you through the process.
| Q | A |
| --------------- | --------------------------------------- |
| Bug fix? | yes |
| Related issues? | fixes #X, partially #Y, mentioned in #Z |
## What's in this Pull Request?
> Please describe the changes in this PR. Sample description or details around bugs which are being fixed.
>
> _(DELETE THIS PARAGRAPH AFTER READING)_
## Submitter Guidance (DELETE AFTER READING)
>
> *Please update this PR information accordingly. We'll use this as part of our release notes in monthly communications.*
>
> *Pull requests that do not follow this template will be automatically rejected.*
>
> *Please target your PR to `main` branch.*
>
> *Remember that this repository is maintained by community members who volunteer their time to help. Be courteous and patient.*
> _(DELETE THIS SECTION AFTER READING)_

View File

@ -24,14 +24,20 @@ Short summary on functionality and used technologies.
## Compatibility
![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg)
![SPFx 1.13.0](https://img.shields.io/badge/SPFx-1.13.0-green.svg)
![Node.js LTS v14 | LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%20v14%20%7C%20LTS%20v12%20%7C%20LTS%20v10-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Local | Hosted](https://img.shields.io/badge/Workbench-Local%20%7C%20Hosted-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Local Workbench Unsupported](https://img.shields.io/badge/Local%20Workbench-Unsupported-red.svg "Local workbench is no longer available as of SPFx 1.13 and above")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
> Don't worry if you're unsure about the compatibility matrix above. We'll verify it when we approve the PR.
>
> If using SPFx 1.12.1, update the SPFx and Node.js tags accordingly:
> ![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg)
> ![Node.js LTS v14 | LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%20v14%20%7C%20LTS%20v12%20%7C%20LTS%20v10-green.svg)
>
> If using an older version of SPFx, update the SPFx and Node.js compatibility tag accordingly:
> SPFx 1.11
> ![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
@ -42,10 +48,12 @@ Short summary on functionality and used technologies.
> ![Node.js LTS 6.x | LTS 8.x](https://img.shields.io/badge/Node.js-LTS%206.x%20%7C%20LTS%208.x-green.svg)
>
> If you built this sample specifically for SharePoint 2016, or SharePoint 2019 support, update the SharePoint compatibility tag accordingly:
> ![SharePoint 2019 | Online](https://img.shields.io/badge/SharePoint-2019%20%7C%20Online-yellow.svg)
> ![SharePoint 2016 | 2019 | Online](https://img.shields.io/badge/SharePoint-2016%20%7C%202019%20%7C%20Online-green.svg)
> ![Works with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Compatible-green.svg)
> ![Work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Compatible-green.svg)
> If you know your web part only works on the hosted workbench, you can use this for the workbench compatibility tag:
> ![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
> ![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "The solution requires access to XXX")
> ![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
>
>
> If you specifically built and tested this web part to work with Teams, use this for the Teams compatibility tag:
> ![Teams Yes: Designed for Microsoft Teams](https://img.shields.io/badge/Teams-Yes-green.svg "Designed for Microsoft Teams")
@ -79,8 +87,8 @@ folder name | [Author Name](LinkToYourGitHubProfile) ([@yourtwitterhandle](https
Version|Date|Comments
-------|----|--------
1.1|September 2, 2021|Update comment
1.0|August 29, 2021|Initial release
1.1|November 1, 2021|Update comment
1.0|October 29, 2021|Initial release
## Prerequisites

View File

@ -21,9 +21,14 @@ This simplistic sample web part demonstrates the use of JavaScript in a SharePoi
> Does only show data when hosted in SharePoint. No mock data at this point for local testing the rendering.
## Used SharePoint Framework Version
![SPFx 1.11.0](https://img.shields.io/badge/drop-1.11.0-green.svg)
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams") ![Local Workbench (Partially)](https://img.shields.io/badge/Local%20Workbench-Partially-yellow.svg "Only basic functionality works on local workbench") ![Hosted Workbench](https://img.shields.io/badge/Hosted%20Workbench-Fully-green.svg "Hosted workbench fully supported")
## Applies to
@ -49,13 +54,6 @@ Version|Date|Comments
1.1|May 15, 2017|Updated to GA Version
2.0|August 29, 2020|Upgraded to SPFx 1.11.0
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
@ -63,7 +61,7 @@ Version|Date|Comments
- `npm install`
- `tsd install`
- `gulp serve`
- `Open the *workbench* on your Office 365 Developer tenant`
- Open the *workbench* on your Office 365 Developer tenant
- Basic functionality can be tested locally, data is only shown when used in context of SharePoint
## Features
@ -77,4 +75,20 @@ This Web Part illustrates the following concepts on top of the SharePoint Framew
* Logging
* Rendering error messages.
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=js-display-list&authors=@VelinGeorgiev%20@sharepointknight&title=js-display-list%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=js-display-list&authors=@VelinGeorgiev%20@sharepointknight&title=js-display-list%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=js-display-list&authors=@VelinGeorgiev%20@sharepointknight&title=js-display-list%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/js-display-list" />

View File

@ -22,11 +22,22 @@ Alternatively, you can add the output files for the web part to a custom SPFx pr
* Copy all files from `js-workbench-customizer\dist` to the `dist` folder of your custom solution
* Copy the `workbenchCustomizer` folder from `js-workbench-customizer\lib\webparts` to the corresponding webparts folder of your custom solution
Note: This approach will not "pollute" your solution with additional resources or dependencies as the SPFx toolchain will ignore those additional files by default when you package your solution. You can also clean everything by running `gulp clean` as both the lib and dist folders are deleted and recreated again. Git will also ignore dist and lib folders by default, so the files will never be added to source control.
> **Note:** This approach will not "pollute" your solution with additional resources or dependencies as the SPFx toolchain will ignore those additional files by default when you package your solution. You can also clean everything by running `gulp clean` as both the lib and dist folders are deleted and recreated again. Git will also ignore dist and lib folders by default, so the files will never be added to source control.
## Used SharePoint Framework Version
![1.11.0](https://img.shields.io/badge/drop-1.11.0-green.svg)
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%202019-Not%20compatible-red.svg)
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%202016%20(Feature%20Pack%202)-Not%20compatible-red.svg)
![Local Workbench Compatible](https://img.shields.io/badge/Local%20Workbench-Compatible-green.svg)
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
@ -54,12 +65,6 @@ Version|Date|Comments
1.4|July 28, 2020|Update styles to minimise toolbar overlap
1.5|July 30, 2020|Update styles to improve full-width mode
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
* Clone this repository
@ -67,4 +72,20 @@ Version|Date|Comments
* `npm install`
* `gulp serve`
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=js-workbench-customizer&authors=@joelfmrodrigues&title=js-workbench-customizer%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=js-workbench-customizer&authors=@joelfmrodrigues&title=js-workbench-customizer%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=js-workbench-customizer&authors=@joelfmrodrigues&title=js-workbench-customizer%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/js-workbench-customizer" />

View File

@ -22,9 +22,14 @@ This is a sample web Part that illustrates the use of React Accessible Accordion
![Sample Web Part built using SPFx with React Framework showing list data in accordion format](./assets/AccordionPreview.png)
## Used SharePoint Framework Version
![1.10.0](https://img.shields.io/badge/drop-1.10.0-green.svg)
## Compatibility
![SPFx 1.10](https://img.shields.io/badge/SPFx-1.10.0-green.svg)
![Node.js LTS 10.x | LTS 8.x](https://img.shields.io/badge/Node.js-LTS%2010.x%7C%20LTS%208.x-green.svg) ![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
## Applies to
@ -46,11 +51,7 @@ Version|Date|Comments
2.0|January 19, 2020|Upgrade to SPFx 1.10
2.1|June 22, 2020|Added pagination (Abhishek Garg)
2.2|October 1, 2020 | Added new Pagination Configuration (@beau__cameron)
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
2.3|September 30, 2021 | Added sorting (@fthorild)
## Minimal Path to Awesome
@ -94,4 +95,19 @@ This sample illustrates the following concepts on top of the SharePoint Framewor
- searching in the fetched data by making use of Search Box from Office Fabric UI
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=REACT-ACCORDION&authors=@AbhishekGarg%20@gautamdsheth&title=REACT-ACCORDION%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=REACT-ACCORDION&authors=@AbhishekGarg%20@gautamdsheth&title=REACT-ACCORDION%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=REACT-ACCORDION&authors=@AbhishekGarg%20@gautamdsheth&title=REACT-ACCORDION%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-accordion" />

View File

@ -9,7 +9,7 @@
"This is a sample web Part that illustrates the use of React Accessible Accordion plugin for building SharePoint Framework client-side web parts to show SharePoint list data in Accordion format."
],
"creationDateTime": "2020-06-22",
"updateDateTime": "2020-06-22",
"updateDateTime": "2021-09-30",
"products": [
"SharePoint",
"Office"

View File

@ -3,7 +3,7 @@
"solution": {
"name": "react-accordion-client-side-solution",
"id": "6d6cf05b-cfe5-4d12-af19-19ec3aedcaf9",
"version": "2.2.0.0",
"version": "2.3.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},

View File

@ -1,6 +1,6 @@
{
"name": "react-accordion",
"version": "2.2.0",
"version": "2.3.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "react-accordion",
"version": "2.2.0",
"version": "2.3.0",
"private": true,
"main": "lib/index.js",
"engines": {

View File

@ -29,10 +29,13 @@
"properties": {
"description": "SPFx webpart which shows SharePoint list data in Accordion format",
"listName": "FAQ",
"totalItems":20,
"totalItems": 20,
"maxItemsPerPage": 5,
"allowPaging":true
"allowPaging": true,
"customSortField": "",
"sortById": false,
"sortByModified": false
}
}
]
}
}

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version, DisplayMode } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
import { IPropertyPaneConfiguration, PropertyPaneSlider, PropertyPaneTextField,PropertyPaneToggle } from "@microsoft/sp-property-pane";
import { IPropertyPaneConfiguration, PropertyPaneSlider, PropertyPaneTextField, PropertyPaneToggle } from "@microsoft/sp-property-pane";
import * as strings from 'ReactAccordionWebPartStrings';
import ReactAccordion from './components/ReactAccordion';
@ -13,16 +13,19 @@ export interface IReactAccordionWebPartProps {
choice: string;
title: string;
displayMode: DisplayMode;
totalItems:number;
totalItems: number;
maxItemsPerPage: number;
enablePaging:boolean;
enablePaging: boolean;
customSortField: string;
sortById: boolean;
sortByModified: boolean;
updateProperty: (value: string) => void;
}
export default class ReactAccordionWebPart extends BaseClientSideWebPart<IReactAccordionWebPartProps> {
public render(): void {
const element: React.ReactElement<IReactAccordionProps> = React.createElement(
ReactAccordion,
{
@ -31,9 +34,12 @@ export default class ReactAccordionWebPart extends BaseClientSideWebPart<IReactA
siteUrl: this.context.pageContext.web.absoluteUrl,
title: this.properties.title,
displayMode: this.displayMode,
totalItems:this.properties.totalItems,
totalItems: this.properties.totalItems,
maxItemsPerPage: this.properties.maxItemsPerPage,
enablePaging:this.properties.enablePaging,
enablePaging: this.properties.enablePaging,
customSortField: this.properties.customSortField,
sortById: this.properties.sortById,
sortByModified: this.properties.sortByModified,
updateProperty: (value: string) => {
this.properties.title = value;
}
@ -53,10 +59,10 @@ export default class ReactAccordionWebPart extends BaseClientSideWebPart<IReactA
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
//set maxitems to top
if(!this.properties.enablePaging){
if (!this.properties.enablePaging) {
this.properties.maxItemsPerPage = this.properties.totalItems;
}
return {
pages: [
{
@ -83,7 +89,7 @@ export default class ReactAccordionWebPart extends BaseClientSideWebPart<IReactA
label: strings.EnablePagingLabel
}),
PropertyPaneSlider('maxItemsPerPage', {
disabled:!this.properties.enablePaging,
disabled: !this.properties.enablePaging,
label: strings.MaxItemsPerPageLabel,
ariaLabel: strings.MaxItemsPerPageLabel,
min: 3,
@ -91,6 +97,14 @@ export default class ReactAccordionWebPart extends BaseClientSideWebPart<IReactA
value: 5,
showValue: true,
step: 1
}),
PropertyPaneTextField('customSortField', {
label: strings.CustomSortOrder
}),
PropertyPaneToggle('sortById', {
label: strings.SortById
}),PropertyPaneToggle('sortByModified', {
label: strings.SortByModified
})
]
}

View File

@ -10,5 +10,8 @@ export interface IReactAccordionProps {
maxItemsPerPage: number;
enablePaging:boolean;
totalItems:number;
customSortField:string;
sortById:boolean;
sortByModified:boolean;
updateProperty: (value: string) => void;
}
}

View File

@ -7,4 +7,5 @@ export interface IReactAccordionState {
listItems: IAccordionListItem[];
isLoading: boolean;
loaderMessage: string;
}
error: string;
}

View File

@ -30,7 +30,8 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
items: [],
listItems: [],
isLoading: false,
loaderMessage: ''
loaderMessage: '',
error: ''
};
if (!this.listNotConfigured(this.props)) {
@ -73,8 +74,24 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
}
private readItems(): void {
let restAPI = this.props.siteUrl + `/_api/web/Lists/GetByTitle('${this.props.listName}')/items?$select=Title,Description&$top=${this.props.totalItems}`;
const orders = [];
if (this.props.customSortField) {
orders.push(this.props.customSortField);
}
if (this.props.sortById) {
orders.push('ID');
}
if (this.props.sortByModified) {
orders.push('Modified');
}
const selects = `select=Title,Description${this.props.customSortField ? `,${this.props.customSortField}` : ''}`;
const restAPI = this.props.siteUrl + `/_api/web/Lists/GetByTitle('${this.props.listName}')/items?` +
`$${selects}` +
`${orders.length > 0 ? '&$orderby=' + orders.join(',') : ''}` +
`&$top=${this.props.totalItems}`;
this.props.spHttpClient.get(restAPI, SPHttpClient.configurations.v1, {
headers: {
@ -86,6 +103,11 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
return response.json();
})
.then((response: { value: IAccordionListItem[] }): void => {
if (!response.value) {
this.setState({
error: `No items were found, check the list Title and/or custom sort order field internal name`
});
}
let listItemsCollection = [...response.value];
@ -95,14 +117,16 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
items: response.value,
listItems: response.value,
isLoading: false,
loaderMessage: ""
loaderMessage: '',
error: ''
});
}, (error: any): void => {
this.setState({
status: 'Loading all items failed with error: ' + error,
pagedItems: [],
isLoading: false,
loaderMessage: ""
loaderMessage: "",
error: `Loading failed. Validate that you have entered a valid List Title and/or internal field name for the custom sort order ${error}`
});
});
@ -110,6 +134,7 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
public render(): React.ReactElement<IReactAccordionProps> {
let displayLoader;
let errorMessage;
let faqTitle;
let { items } = this.state;
let pageCountDivisor: number = this.props.maxItemsPerPage;
@ -149,7 +174,7 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
displayLoader = (null);
}
if(this.props.enablePaging){
if (this.props.enablePaging) {
if (items.length > 0) {
pageCount = Math.ceil(items.length / pageCountDivisor);
}
@ -157,6 +182,11 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
pageButtons.push(<PrimaryButton onClick={() => { _pagedButtonClick(i + 1, items); }}> {i + 1} </PrimaryButton>);
}
}
if (this.state.error) {
errorMessage = <div>{this.state.error}</div>;
}
return (
<div className={styles.reactAccordion}>
<div className={styles.container}>
@ -175,7 +205,7 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
<div className={`ms-Grid-row`}>
<div className='ms-Grid-col ms-u-lg12'>
{this.state.status}
<Accordion accordion={false}>
<Accordion>
{pagedItems}
</Accordion>
</div>
@ -186,7 +216,8 @@ export default class ReactAccordion extends React.Component<IReactAccordionProps
</div>
</div>
</div>
{errorMessage}
</div>
);
}
}
}

View File

@ -5,6 +5,9 @@ define([], function () {
"ListNameLabel": "List Name",
"MaxItemsPerPageLabel": "Max number of items per page",
"EnablePagingLabel":"Enable Paging",
"TotalItemsLabel":"Maximum items to retrieve"
"TotalItemsLabel":"Maximum items to retrieve",
"CustomSortOrder":"Custom sort order",
"SortById":"Sort by ID",
"SortByModified":"Sort by modified date"
}
});

View File

@ -5,6 +5,9 @@ declare interface IReactAccordionWebPartStrings {
MaxItemsPerPageLabel: string;
EnablePagingLabel: string;
TotalItemsLabel:string;
CustomSortOrder:string;
SortById:string;
SortByModified:string;
}
declare module 'ReactAccordionWebPartStrings' {

View File

@ -6,9 +6,14 @@ A version of [react-adaptivecards](https://github.com/pnp/sp-dev-fx-webparts/tre
![Adaptive Cards in SharePoint](assets/preview.png)
## Used SharePoint Framework Version
![1.11.0](https://img.shields.io/badge/version-1.11.0-green.svg)
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Local | Hosted](https://img.shields.io/badge/Workbench-Local%20%7C%20Hosted-green.svg)
## Applies to
@ -29,12 +34,6 @@ Version|Date|Comments
1.0|April 27, 2020|Initial release
2.0|August 25, 2020|Upgraded to SPFx 1.11 and added support for May 2020 changes to Adaptive Cards
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
* Clone this repository
@ -55,5 +54,20 @@ Version|Date|Comments
| AdaptiveCardHost.tsx | React Function component | Renders placeholder if template/data are missing. Handles card actions. |
| AdaptiveCard.tsx | React Class component | Responsible for rendering adaptive card and expanding card with data |
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-adaptivecards-hooks&authors=@pschaeflein&title=react-adaptivecards-hooks%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-adaptivecards-hooks&authors=@pschaeflein&title=react-adaptivecards-hooks%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-adaptivecards-hooks&authors=@pschaeflein&title=react-adaptivecards-hooks%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-adaptivecards-hooks" />

View File

@ -16,11 +16,14 @@ Attempts to replicate the functionality of Page Properties with the following im
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires access to information about the hosting page")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-yellow.svg "Works better when placed on a modern site page.")
## Applies to

View File

@ -119,7 +119,7 @@ Calendar Web Part|[Eli H. Schei](https://github.com/Eli-Schei)
Calendar Web Part|[Hugo Bernier](https://github.com/hugoabernier) ([@bernier](https://twitter.com/bernierh), [Tahoe Ninjas](https://tahoeninjas.blog/))
Calendar Web Part|[João Mendes](https://github.com/joaojmendes)
Calendar Web Part|[Mohamed Derhalli](https://github.com/derhallim)
Calendar Web PArt|[Mohammed Amer](https://www.linkedin.com/in/mohammad3mer/) ([@Mohammad3mer](https://twitter.com/Mohammad3mer))
Calendar Web PArt|[Mohammed Amer](https://github.com/mohammadamer) ([@Mohammad3mer](https://twitter.com/Mohammad3mer), https://www.linkedin.com/in/mohammad3mer/)
Calendar Web Part|[Nanddeep Nachan](https://github.com/nanddeepn) ([@NanddeepNachan](https://twitter.com/NanddeepNachan))
## Version history
@ -139,7 +139,8 @@ Version|Date|Comments
1.0.10|March 27, 2021|Updated prompt message when deleting single v/s multi-event.
1.0.11|May 10, 2021|Optimized page refresh using local storage
1.0.12|June 21, 2021|Fixes overlap with Year-view and the comment section by adding a vertical scrollbar.
1.0.13|October 16, 2021|Resolve unhandled exception that happens clicking on recurrent events
1.0.13|October 2, 2021|Fix to make sure Today is always visible and highlighted.
1.0.14|October 16, 2021|Resolve unhandled exception that happens clicking on recurrent events
## Minimal Path to Awesome
@ -161,11 +162,11 @@ Version|Date|Comments
We do not support samples, but we do use GitHub to track issues and constantly want to improve these samples.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@hugoabernier,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@mohammadamer,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@hugoabernier,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@mohammadamer,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@hugoabernier,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-calendar&authors=@Abderahman88,%20@Eli-Schei,%20@mohammadamer,%20@joaojmendes,%20@derhallim,%20@nanddeepn,%20@mohammadamer&title=react-calendar%20-%20).

View File

@ -4,50 +4,52 @@
display: flex;
flex-wrap: wrap;
overflow-y: auto;
}
.month {
margin: 5px 10px 15px 10px;
}
.month {
margin: 5px 10px 15px 10px;
.monthName {
color: $ms-color-themeDark;
font-weight: bold;
margin-bottom: 10px;
}
.monthName {
color: $ms-color-themePrimary;
font-weight: bold;
margin-bottom: 10px;
}
.day {
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
border: dotted 1px;
border-radius: 50%;
transform: scale(0.9, 0.9);
}
.day {
display: inline-block;
width: 30px;
height: 30px;
text-align: center;
line-height: 30px;
border: dotted 1px;
border-radius: 50%;
transform: scale(0.9, 0.9);
}
.date {
width: 30px;
height: 30px;
background: white;
border-radius: 50px;
border: none;
outline: none;
}
.date {
width: 30px;
height: 30px;
border-radius: 50px;
border: none;
outline: none;
.date.inMonth:hover {
cursor: pointer;
background: $ms-color-themeDark;
color: white;
font-weight: bold;
}
&.inMonth {
&:hover {
cursor: pointer;
background: $ms-color-themePrimary;
color: white;
font-weight: bold;
}
}
.today {
background: $ms-color-themeDark;
}
&.today {
background: $ms-color-themePrimary;
color: white;
}
.date.prevMonth,
.date.nextMonth {
color: grey;
.date.prevMonth,
.date.nextMonth {
color: grey;
}
}
}
}

View File

@ -39,7 +39,7 @@ function CalendarDate(props) {
const { dateToRender, dateOfMonth } = props;
const today =
dateToRender.format('YYYY-MM-DD') === moment().format('YYYY-MM-DD')
? 'today'
? styles.today
: '';
if (dateToRender.month() < dateOfMonth.month()) {

View File

@ -170,7 +170,14 @@ This sample shows how to use X and Y coordinate data elements in a scatter chart
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11-green.svg) ![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg) ![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-red.svg) ![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg) ![Workbench Local | Hosted](https://img.shields.io/badge/Workbench-Local%20%7C%20Hosted-green.svg)
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "The solution requires access to SharePoint content")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to

View File

@ -2,8 +2,7 @@
## Summary
Search People from Organization Directory and show live persona card on hover.
Search People from Organization Directory and show live persona card on hover.
##
![directory](/samples/react-directory/assets/react-directory7.png)
@ -32,12 +31,14 @@
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "The solution requires access to your organization directory")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
@ -77,13 +78,6 @@ Version|Date|Comments
3.0.0|Oct 17 2020|Minor fixes and add the additional web part property.
3.0.1|March 4 2021|Bugfix 'Sort People by'
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
@ -92,6 +86,20 @@ Version|Date|Comments
- `gulp build`
- `gulp bundle --ship`
- `gulp package-solution --ship`
- `Add to AppCatalog and deploy`
- Add to AppCatalog and deploy
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-directory&authors=@joaojmendes%20@petkir%20@sudharsank%20@Abderahman88&title=react-directory%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-directory&authors=@joaojmendes%20@petkir%20@sudharsank%20@Abderahman88&title=react-directory%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-directory&authors=@joaojmendes%20@petkir%20@sudharsank%20@Abderahman88&title=react-directory%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-directory" />

View File

@ -29,9 +29,16 @@ Below NPM packages are used to develop this sample.
2. react-orgchart (https://www.npmjs.com/package/react-orgchart)
3. array-to-tree (https://www.npmjs.com/package/array-to-tree)
## Used SharePoint Framework Version
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/version-1.11.0-green.svg)
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "The solution requires access to SharePoint content")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
@ -52,12 +59,6 @@ Version|Date|Comments
2.0.0|November 21, 2020|Upgraded to SPFx v1.11.0 (Nanddeep Nachan)
1.0.0|October 15, 2018|Initial release
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Prerequisites
- SharePoint Online tenant
@ -93,4 +94,18 @@ This sample web part shows how data stored in SharePoint list can be transformed
[figure5]: ./assets/list-sample-data.png
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-display-hierarchy" />
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-display-hierarchy&authors=@nanddeepn%20@ravi16a87&title=react-display-hierarchy%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-display-hierarchy&authors=@nanddeepn%20@ravi16a87&title=react-display-hierarchy%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-display-hierarchy&authors=@nanddeepn%20@ravi16a87&title=react-display-hierarchy%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-display-hierarchy" />

View File

@ -0,0 +1,33 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
release
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

View File

@ -0,0 +1,12 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.12.1",
"libraryName": "react-menu-accordion",
"libraryId": "f7134ff1-6e97-430c-9a73-5dc4902c75e3",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,85 @@
# Documents Links Accordion
## Summary
This web part allows user create a accordion with documents links grouped by any column of document library.
When the user clicks on the header it dynamically load documents.
![documentsLinksAccordion](./assets/documentsLinksAccordion.gif)
## Screenshots
![documentsLinksAccordion](./assets/documentsLinksAccordion1.png)
## Compatibility
![SPFx 1.12.1](https://img.shields.io/badge/SPFx-1.12.1-green.svg)
![Node.js LTS v14 | LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%20v14%20%7C%20LTS%20v12%20%7C%20LTS%20v10-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg)
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
* [SharePoint Framework](https://docs.microsoft.com/sharepoint/dev/spfx/sharepoint-framework-overview)
* [Office 365 tenant](https://docs.microsoft.com/sharepoint/dev/spfx/set-up-your-development-environment)
## Web Part Properties
Property |Type|Required| comments
--------------------|----|--------|----------
Web part Title| Text| no|
Select Document Library| dropdown|yes
Select Field to Group By | dropdown|yes
## Solution
The web part Use PnPjs library, Fluent-Ui-react components
Solution|Author(s)
--------|---------
React Documents Links Accordion |[João Mendes](https://github.com/joaojmendes) ([@joaojmendes](https://twitter.com/joaojmendes))
## Version history
Version|Date|Comments
-------|----|--------
1.0.0|October 10, 2021|Initial release
## Minimal Path to Awesome
- Clone this repository
- Move to sample folder
- in the command line run:
- `npm install`
- `gulp build`
- `gulp bundle --ship`
- `gulp package-solution --ship`
- Add to AppCatalog and deploy
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-list-items-menu&authors=@joaojmendes%20@Ravikadri&title=react-list-items-menu%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-list-items-menu&authors=@joaojmendes%20@Ravikadri&title=react-list-items-menu%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-list-items-menu&authors=@joaojmendes%20@Ravikadri&title=react-list-items-menu%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-documents-links-accordion" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

View File

@ -0,0 +1,89 @@
[
{
"name": "pnp-sp-dev-spfx-web-parts-react-document-links-accordion",
"source": "pnp",
"title": "Documents Links Accordion",
"shortDescription": "This web part allows user create a accordion with documents links grouped by any column of document library.",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-document-links-accordion",
"longDescription": [
"This web part allows user create a accordion with documents links grouped by any column of document library.",
"When the user clicks on the header it dynamically load documents."
],
"creationDateTime": "2021-10-10",
"updateDateTime": "2021-10-10",
"products": [
"SharePoint",
"Office"
],
"metadata": [
{
"key": "CLIENT-SIDE-DEV",
"value": "React"
},
{
"key": "SPFX-VERSION",
"value": "1.12.1"
},
{
"key": "SPFX-FULLPAGEAPP",
"value": "true"
},
{
"key": "SPFX-TEAMSTAB",
"value": "true"
},
{
"key": "SPFX-TEAMSPERSONALAPP",
"value": "true"
},
{
"key": "REACT-HOOKS",
"value": "true"
},
{
"key": "PNPCONTROLS",
"value": "PropertyFieldListPicker, PropertyFieldMessage, PropertyFieldSpinner, Placeholder, AccessibleAccordion"
}
],
"thumbnails": [
{
"type": "image",
"order": 100,
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-document-links-accordion/assets/documentsLinksAccordion.gif",
"alt": "Web part in action"
},
{
"type": "image",
"order": 101,
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-document-links-accordion/assets/documentsLinksAccordion1.png",
"alt": "Screen shot of web part"
}
],
"authors": [
{
"gitHubAccount": "joaojmendes",
"company": "Storm Technology Ltd",
"pictureUrl": "https://github.com/joaojmendes.png",
"name": "Jo\u00E3o Mendes",
"twitter": "joaojmendes"
}
],
"references": [
{
"name": "Build your first SharePoint client-side web part",
"description": "Client-side web parts are client-side components that run in the context of a SharePoint page. Client-side web parts can be deployed to SharePoint environments that support the SharePoint Framework. You can also use modern JavaScript web frameworks, tools, and libraries to build them.",
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
},
{
"name": "Supporting section backgrounds",
"description": "Starting with SharePoint Framework v1.8, web parts can be made aware of any section backgrounds and use these colors to improve the appearance of a web part when hosted in a section with a different background.",
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/supporting-section-backgrounds"
},
{
"name": "Building Microsoft Teams Tabs using SharePoint Framework",
"description": "Starting with SharePoint Framework v1.8, you can build tabs for Microsoft Teams with the SharePoint Framework tooling and use SharePoint as a host for your solutions. As part of the SharePoint Framework v1.10 you can also publish your solution as Microsoft Teams personal app.",
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/integrate-with-teams-introduction"
}
]
}
]

View File

@ -0,0 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"documentslinksaccordion-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/DocumentsLinksAccordion/DocumentsLinksAccordionWebPart.js",
"manifest": "./src/webparts/DocumentsLinksAccordion/DocumentsLinksAccordionWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"DocumentsLinksAccordionWebPartStrings": "lib/webparts/DocumentsLinksAccordion/loc/{locale}.js",
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js",
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js"
}
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "./release/assets/"
}

View File

@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./release/assets/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "react-menu-accordion",
"accessKey": "<!-- ACCESS KEY -->"
}

View File

@ -0,0 +1,21 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "react-documentslinks-accordion",
"id": "f7134ff1-6e97-430c-9a73-5dc4902c75e3",
"version": "1.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,
"developer": {
"name": "",
"websiteUrl": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"mpnId": ""
}
},
"paths": {
"zippedPackage": "solution/react-documentslinks-accordion.sppkg"
}
}

View File

@ -0,0 +1,16 @@
'use strict';
const build = require('@microsoft/sp-build-web');
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);
result.set('serve', result.get('serve-deprecated'));
return result;
};
build.initialize(require('gulp'));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
{
"name": "react-documentslinks-accordion",
"version": "0.0.1",
"private": true,
"main": "lib/index.js",
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.12.1",
"@microsoft/sp-lodash-subset": "1.12.1",
"@microsoft/sp-office-ui-fabric-core": "1.12.1",
"@microsoft/sp-property-pane": "1.12.1",
"@microsoft/sp-webpart-base": "1.12.1",
"@pnp/spfx-controls-react": "^3.3.0",
"@pnp/spfx-property-controls": "^3.2.0",
"@uifabric/file-type-icons": "^7.8.1",
"date-fns": "^2.25.0",
"office-ui-fabric-react": "7.156.0",
"react": "16.9.0",
"react-dom": "16.9.0"
},
"devDependencies": {
"@types/react": "16.9.36",
"@types/react-dom": "16.9.8",
"@microsoft/sp-build-web": "1.12.1",
"@microsoft/sp-tslint-rules": "1.12.1",
"@microsoft/sp-module-interfaces": "1.12.1",
"@microsoft/sp-webpart-workbench": "1.12.1",
"@microsoft/rush-stack-compiler-3.7": "0.2.3",
"gulp": "~4.0.2",
"ajv": "~5.2.2",
"@types/webpack-env": "1.13.1"
}
}

View File

@ -0,0 +1,160 @@
import { SPComponentLoader } from "@microsoft/sp-loader";
import { sp } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/regional-settings/web";
import { IRegionalSettingsInfo } from "@pnp/sp/regional-settings";
// get all the web's regional settings
const DEFAULT_PERSONA_IMG_HASH: string = "7ad602295f8386b7615b582d87bcc294";
const DEFAULT_IMAGE_PLACEHOLDER_HASH: string = "4a48f26592f4e1498d7a478a4c48609c";
const MD5_MODULE_ID: string = "8494e7d7-6b99-47b2-a741-59873e42f16f";
const PROFILE_IMAGE_URL: string = "/_layouts/15/userphoto.aspx?size=M&accountname=";
/**
* Gets user photo
* @param userId
* @returns user photo
*/
export const getUserPhoto = async (userId): Promise<string> => {
const personaImgUrl = PROFILE_IMAGE_URL + userId;
console.log(personaImgUrl);
// tslint:disable-next-line: no-use-before-declare
const url: string = await getImageBase64(personaImgUrl);
// tslint:disable-next-line: no-use-before-declare
const newHash = await getMd5HashForUrl(url);
if (newHash !== DEFAULT_PERSONA_IMG_HASH && newHash !== DEFAULT_IMAGE_PLACEHOLDER_HASH) {
return "data:image/png;base64," + url;
} else {
return "undefined";
}
};
/**
* Get MD5Hash for the image url to verify whether user has default image or custom image
* @param url
*/
export const getMd5HashForUrl = async (url: string) => {
return new Promise(async (resolve, reject) => {
// tslint:disable-next-line: no-use-before-declare
const library: any = await loadSPComponentById(MD5_MODULE_ID);
try {
const md5Hash = library.Md5Hash;
if (md5Hash) {
const convertedHash = md5Hash(url);
resolve(convertedHash);
}
} catch (error) {
resolve(url);
}
});
};
/**
* Load SPFx component by id, SPComponentLoader is used to load the SPFx components
* @param componentId - componentId, guid of the component library
*/
export const loadSPComponentById = async (componentId: string) => {
return new Promise((resolve, reject) => {
SPComponentLoader.loadComponentById(componentId)
.then((component: any) => {
resolve(component);
})
.catch((error) => {});
});
};
/**
* Gets image base64
* @param pictureUrl
* @returns image base64
*/
export const getImageBase64 = async (pictureUrl: string): Promise<string> => {
console.log(pictureUrl);
return new Promise((resolve, reject) => {
let image = new Image();
image.addEventListener("load", () => {
let tempCanvas = document.createElement("canvas");
(tempCanvas.width = image.width),
(tempCanvas.height = image.height),
tempCanvas.getContext("2d").drawImage(image, 0, 0);
let base64Str;
try {
base64Str = tempCanvas.toDataURL("image/png");
} catch (e) {
return "";
}
base64Str = base64Str.replace(/^data:image\/png;base64,/, "");
resolve(base64Str);
});
image.src = pictureUrl;
});
};
export const zeroPad = (num, places) => {
var zero = places - num.toString().length + 1;
return Array(+(zero > 0 && zero)).join("0") + num;
};
export const getSiteRegionalSettings = async (): Promise<IRegionalSettingsInfo> => {
try {
const s = await sp.web.regionalSettings();
return s;
} catch (error) {
console.error(error);
Promise.reject(error);
}
};
export const convertTimeTo12H = (
_hour: number
): Promise<{ hourInTimeFormat: string; current12HTimeFormat: string }> => {
console.log("prm", _hour);
return new Promise((resolve, rejected) => {
let hourInTimeFormat: string = "";
let current12HTimeFormat: string = "AM";
if (_hour >= 0 && _hour <= 11) {
if (_hour === 0) {
hourInTimeFormat = "12";
} else {
hourInTimeFormat = _hour.toString();
}
current12HTimeFormat = "AM";
} else {
const _hour12h = _hour - 12;
hourInTimeFormat = _hour12h === 0 ? "12" : _hour12h.toString();
current12HTimeFormat = "PM";
}
resolve({ hourInTimeFormat, current12HTimeFormat });
});
};
export const convertTimeTo24h = (hour: number, current12HTimeFormat: string): Promise<string> => {
return new Promise((resolve, rejected) => {
let hourInTimeFormat: string = "";
if (current12HTimeFormat === "PM") {
if (hour >= 1 && hour <= 11) {
if (hour === 12) {
hourInTimeFormat = "12";
}
const _hour24h = hour + 12;
hourInTimeFormat = _hour24h.toString();
}
} else {
if (hour === 12) {
hourInTimeFormat = "00";
} else {
hourInTimeFormat = hour.toString();
}
}
resolve(hourInTimeFormat);
});
};
/* Check if string is valid date */
export const checkIfValidDate = (str:string):boolean => {
// Regular expression to check if string is valid date
const regexExp = /(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})/gi;
return regexExp.test(str);
};

View File

@ -0,0 +1,16 @@
import * as React from "react";
import { WebPartContext } from "@microsoft/sp-webpart-base";
import { MSGraphClient, AadTokenProvider } from "@microsoft/sp-http";
import { IReadonlyTheme } from '@microsoft/sp-component-base';
import { IRegionalSettingsInfo} from "@pnp/sp/regional-settings";
export interface IAppContextProps {
currentUser:string;
msGraphClient:MSGraphClient;
locale:string;
themeVariant: IReadonlyTheme | undefined;
}
export const AppContext = React.createContext<IAppContextProps>(undefined);

View File

@ -0,0 +1,28 @@
import { IDatePickerStrings } from 'office-ui-fabric-react/lib/DatePicker';
export const DayPickerStrings: IDatePickerStrings = {
months: [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
],
shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
shortDays: ['S', 'M', 'T', 'W', 'T', 'F', 'S'],
goToToday: 'Go to today',
prevMonthAriaLabel: 'Go to previous month',
nextMonthAriaLabel: 'Go to next month',
prevYearAriaLabel: 'Go to previous year',
nextYearAriaLabel: 'Go to next year',
closeButtonAriaLabel: 'Close date picker',
monthPickerHeaderAriaLabel: '{0}, select to change the year',
yearPickerHeaderAriaLabel: '{0}, select to change the month',
};

View File

@ -0,0 +1,16 @@
$default-background: #f3f2f1;
$default-color: #252423;
$default-button-background: #6264a7;
$default-Button-color: #f3f2f1;
// dark theme
$dark-background: #2d2c2c;
$dark-color: #ffffff;
$dark-button-background: #6264a7;
$dark-button-color: #2d2c2c;
// contrast theme
$contrast-background: #000000;
$contrast-color: #ffffff;
$contrast-button-background: #b5c01c;
$contrast-Button-color: #000000;

View File

@ -0,0 +1,74 @@
@import '~office-ui-fabric-react/dist/sass/References.scss';
.DocumentsLinksAccordion {
.container {
max-width: 700px;
margin: 0px auto;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.row {
@include ms-Grid-row;
@include ms-fontColor-white;
background-color: $ms-color-themeDark;
padding: 20px;
}
.column {
@include ms-Grid-col;
@include ms-lg10;
@include ms-xl8;
@include ms-xlPush2;
@include ms-lgPush1;
}
.title {
@include ms-font-xl;
@include ms-fontColor-white;
}
.subTitle {
@include ms-font-l;
@include ms-fontColor-white;
}
.description {
@include ms-font-l;
@include ms-fontColor-white;
}
.button {
// Our button
text-decoration: none;
height: 32px;
// Primary Button
min-width: 80px;
background-color: $ms-color-themePrimary;
border-color: $ms-color-themePrimary;
color: $ms-color-white;
// Basic Button
outline: transparent;
position: relative;
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
-webkit-font-smoothing: antialiased;
font-size: $ms-font-size-m;
font-weight: $ms-font-weight-regular;
border-width: 0;
text-align: center;
cursor: pointer;
display: inline-block;
padding: 0 16px;
.label {
font-weight: $ms-font-weight-semibold;
font-size: $ms-font-size-m;
height: 32px;
line-height: 32px;
margin: 0 4px;
vertical-align: top;
display: inline-block;
}
}
}

View File

@ -0,0 +1,356 @@
import * as React from "react";
import * as strings from "DocumentsLinksAccordionWebPartStrings";
import { filter, findIndex, uniqBy } from "lodash";
import {
Customizer,
INavLink,
INavLinkGroup,
Label,
Link,
mergeStyleSets,
MessageBar,
MessageBarType,
Spinner,
SpinnerSize,
Stack,
FontIcon,
Text,
DetailsList,
DetailsListLayoutMode,
IColumn,
SelectionMode,
IDetailsListProps,
IStackStyles,
IStyle,
IDetailsListStyles,
} from "office-ui-fabric-react";
import { getFileTypeIconProps } from "@uifabric/file-type-icons";
import { useList } from "../../hooks/useList";
import { IDocumentsLinksAccordionState } from "./IDocumentsLinksAccordionState";
import { IDocumentsLinksAccordionProps } from "./IDocumentsLinksAccordionProps";
import {
Accordion,
AccordionItem,
AccordionItemHeading,
AccordionItemButton,
AccordionItemPanel,
} from "@pnp/spfx-controls-react/lib/AccessibleAccordion";
import { Placeholder } from "@pnp/spfx-controls-react/lib/Placeholder";
const { getGroupItems, getGroupHeaders, getField } = useList();
export const DocumentsLinksAccordion: React.FunctionComponent<IDocumentsLinksAccordionProps> = (
props: IDocumentsLinksAccordionProps
) => {
const [state, setState] = React.useState<IDocumentsLinksAccordionState>({
navLinkGroups: [],
isLoading: false,
hasError: false,
errorMessage: "",
listName: "",
});
const stackItemStyles: Partial<IStackStyles> = React.useMemo(() => {
return {
root: {
padding: 7,
} as IStyle,
};
}, []);
const listViewStyles: Partial<IDetailsListStyles> = React.useMemo(() => {
return {
focusZone: {
width: "auto",
maxHeight: 450,
overflowY: "auto",
overflowX: "hidden",
"&::-webkit-scrollbar-thumb": {
backgroundColor: props.themeVariant?.palette?.neutralLighter,
},
"&::-webkit-scrollbar": {
width: "7.5px",
},
"scrollbar-color": props.themeVariant?.palette?.neutralLighter,
"scrollbar-width": "thin",
},
root: {
"&::-webkit-scrollbar-thumb": {
backgroundColor: props.themeVariant?.palette?.neutralLighter,
},
"&::-webkit-scrollbar": {
height: "7.5px",
},
"scrollbar-color": props.themeVariant?.palette?.neutralLighter,
"scrollbar-width": "thin",
},
};
}, []);
const classComponent = React.useMemo(() => {
return mergeStyleSets({
webPartTitle: {
fontWeight: 600,
overflowX: "hidden",
textOverflow: "Ellipsis",
fontSize: props.themeVariant.fonts.large.fontSize,
marginBottom: 10,
},
});
}, [props.themeVariant]);
const stateRef = React.useRef(state); // Use to access state on eventListenners
const columns: IColumn[] = React.useMemo(() => {
return [
{
key: "documentRenderLink",
name: "Document",
fieldName: "name",
minWidth: 400,
maxWidth: 800,
isResizable: false,
data: "string",
},
];
}, []);
const onRenderRow: IDetailsListProps["onRenderRow"] = (propsItem) => {
if (propsItem.item) {
const item = propsItem.item as INavLink;
return (
<Stack horizontal horizontalAlign="start" tokens={{ childrenGap: 10 }} styles={stackItemStyles}>
<FontIcon iconName={item.iconProps.iconName} />
<Link href={item.url} target="_blank">
<Text variant={"medium"}>{item.name}</Text>
</Link>
</Stack>
);
}
return null;
};
React.useEffect(() => {
(async () => {
if (!props.listId || !props.fieldName) {
return;
}
try {
let _navLinksGroups: INavLinkGroup[] = [];
stateRef.current = {
...stateRef.current,
isLoading: true,
navLinkGroups: _navLinksGroups,
};
setState(stateRef.current);
const _groupHeaders = await getGroupHeaders(props.listId, props.fieldName, props.listBaseTemplate);
const { fieldName } = props;
const _field: any = await getField(props.listId, props.fieldName);
for (const groupHeader of _groupHeaders) {
let _name: any;
switch (_field.fieldType) {
case "TaxonomyFieldType":
_name = groupHeader[fieldName]?.Label ?? "Unassigned";
break;
case "TaxonomyFieldTypeMulti":
_name = groupHeader[fieldName][0]?.Label ?? "Unassigned";
break;
case "User":
if (_name != "Unassigned") {
_name = groupHeader[fieldName][0]?.title;
}
break;
case "Lookup":
_name =
groupHeader[props.fieldName] !== "" &&
groupHeader[props.fieldName] !== undefined &&
groupHeader[props.fieldName][0].lookupValue !== ""
? groupHeader[props.fieldName][0]?.lookupValue
: "Unassigned";
break;
default:
_name =
groupHeader[props.fieldName] !== "" && groupHeader[props.fieldName] !== undefined
? groupHeader[props.fieldName]
: "Unassigned";
break;
}
_navLinksGroups.push({
name: _name,
groupData: _name,
collapseByDefault: true,
links: [],
});
// Ensure the groups name are unique!
_navLinksGroups = uniqBy(_navLinksGroups, "name");
}
stateRef.current = {
...stateRef.current,
hasError: false,
errorMessage: "",
isLoading: false,
listName: _field.fieldScope,
navLinkGroups: _navLinksGroups,
};
setState(stateRef.current);
} catch (error) {
stateRef.current = {
...stateRef.current,
hasError: true,
errorMessage: error.message,
};
setState(stateRef.current);
}
})();
}, [props.listId, props.fieldName]);
// On Header click get Items for the header
const onGroupHeaderClick = React.useCallback(
async (ev: React.MouseEvent<HTMLElement, MouseEvent>) => {
try {
const _groupName = ev.currentTarget.innerText;
const { navLinkGroups } = stateRef.current;
setState(stateRef.current);
const _navGroup = filter(navLinkGroups, { name: _groupName });
if (_navGroup?.length && _navGroup[0]?.links?.length === 0) {
const _navlinks: INavLink[] = [];
const _groupHeaderItems: any[] = await getGroupItems(
props.listId,
props.fieldName,
_groupName,
props.listBaseTemplate
);
if (_groupHeaderItems?.length) {
for (const _groupHeaderItem of _groupHeaderItems) {
if (props.listBaseTemplate === 0) {
// List
_navlinks.push({
name: _groupHeaderItem.Title,
url: `${_groupHeaderItem.FileDirRef}/dispform.aspx?ID=${_groupHeaderItem.Id}`,
iconProps: {
iconName: "TaskManager",
},
key: _groupHeaderItem.Id,
target: "_blank",
isExpanded: false,
});
}
if (props.listBaseTemplate === 1) {
// Document Library
_navlinks.push({
name: _groupHeaderItem.FileLeafRef,
url: _groupHeaderItem.FileRef,
iconProps: {
...getFileTypeIconProps({
extension: _groupHeaderItem.DocIcon,
size: 16,
imageFileType: "svg",
}),
},
key: _groupHeaderItem.title,
target: "_blank",
isExpanded: false,
});
}
}
}
// Update Navigation with Items of Group
_navGroup[0].links = _navlinks;
}
const _index = findIndex(navLinkGroups, { name: _groupName });
_navGroup[0].collapseByDefault = true;
navLinkGroups[_index] = _navGroup[0];
stateRef.current = { ...stateRef.current, navLinkGroups: navLinkGroups };
setState(stateRef.current);
} catch (error) {}
},
[props]
);
// Show Error if Exists
if (state.hasError) {
return (
<>
<MessageBar messageBarType={MessageBarType.error} isMultiline>
{state.errorMessage}
</MessageBar>
</>
);
}
// render component
if (!props.listId || !props.fieldName) {
return (
<Placeholder
iconName="Edit"
iconText={strings.PlaceHolderIconText}
description={strings.PlaceHolderDescription}
buttonLabel={strings.PlaceHolderButtonLable}
onConfigure={props.onConfigure}
/>
);
}
return (
<>
<Customizer settings={{ theme: props.themeVariant }}>
{state.isLoading ? (
<Stack horizontal horizontalAlign="center">
<Spinner size={SpinnerSize.medium}></Spinner>
</Stack>
) : (
<>
<Stack horizontalAlign="space-between" horizontal tokens={{ childrenGap: 10 }} style={{ width: "100%" }}>
<div className={classComponent.webPartTitle}>{props.title}</div>
<Link href={state.listName}>{strings.ViewAllLabel}</Link>
</Stack>
{state.navLinkGroups?.length === 0 ? (
<Label
style={{
fontWeight: 400,
fontSize: props.themeVariant.fonts.small.fontSize,
}}
>
{strings.NodocumentsLabel}
</Label>
) : (
<Accordion allowZeroExpanded allowMultipleExpanded>
{state.navLinkGroups.map((item, i) => {
return (
<AccordionItem>
<AccordionItemHeading
onClick={async (ev) => {
await onGroupHeaderClick(ev);
}}
>
<AccordionItemButton>{item.name}</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<Stack>
<DetailsList
items={item.links}
columns={columns}
styles={listViewStyles}
compact={true}
selectionMode={SelectionMode.none}
setKey="none"
layoutMode={DetailsListLayoutMode.justified}
isHeaderVisible={false}
onRenderRow={onRenderRow}
/>
</Stack>
</AccordionItemPanel>
</AccordionItem>
);
})}
</Accordion>
)}
</>
)}
</Customizer>
</>
);
};

View File

@ -0,0 +1,14 @@
import { IReadonlyTheme } from "@microsoft/sp-component-base";
import { DisplayMode } from "@microsoft/sp-core-library";
export interface IDocumentsLinksAccordionProps {
title: string;
listId:string;
listBaseTemplate:number;
fieldName:string;
locale:string;
themeVariant: IReadonlyTheme | undefined;
onConfigure: () => void;
}

View File

@ -0,0 +1,9 @@
import { Nav, INavStyles, INavLinkGroup } from 'office-ui-fabric-react/lib/Nav';
export interface IDocumentsLinksAccordionState {
navLinkGroups: INavLinkGroup[];
isLoading: boolean;
hasError:boolean;
errorMessage:string;
listName:string;
}

View File

@ -0,0 +1,6 @@
export interface IListItemsMenu {
groupBy:string;
id:string;
title:string;
url:string;
}

View File

@ -0,0 +1,137 @@
import "@pnp/sp/fields";
import "@pnp/sp/items";
import "@pnp/sp/lists";
import "@pnp/sp/webs";
import { sortBy, uniqBy } from "lodash";
import { sp } from "@pnp/sp";
import { IFieldInfo } from "@pnp/sp/fields";
import { IListInfo } from "@pnp/sp/lists";
import * as moment from "moment";
import { format, parse, parseISO } from "date-fns";
import { checkIfValidDate } from "../Utils/Utils";
export const useList = () => {
// Run on useList hook
(async () => {})();
// Get List Columns
const getListColumns = async (listId: string): Promise<IFieldInfo[]> => {
const _listColumnsResults: IFieldInfo[] = await sp.web.lists.getById(listId).fields.filter("Hidden eq false").get();
const _wColumns: IFieldInfo[] = uniqBy(sortBy(_listColumnsResults, "Title"), "Title");
return _wColumns;
};
const getField = async (listId: string, field: string): Promise<any> => {
const _field: IFieldInfo = await sp.web.lists.getById(listId).fields.getByInternalNameOrTitle(field).get();
const fieldType = _field.TypeAsString;
const fieldScope = _field.Scope;
return { fieldType, fieldScope };
};
const getGroupHeaders = async (listId: string, groupByField: string, baseTemplate: number): Promise<any[]> => {
let _viewXml = `<View Scope='Recursive'>
<Query>
<GroupBy Collapse="TRUE">
<FieldRef Name="${groupByField}"/>
</GroupBy>
</Query>
<RowLimit>1000</RowLimit>
</View>`;
const _groupHeadersResults = await sp.web.lists.getById(listId).renderListDataAsStream({ ViewXml: _viewXml });
return uniqBy(_groupHeadersResults.Row, groupByField);
};
const getGroupItems = async (
listId: string,
groupByField: string,
groupFieldValue: string,
baseTemplate: number
): Promise<any[]> => {
const _field: any = await getField(listId, groupByField);
if (checkIfValidDate(groupFieldValue)) {
groupFieldValue = format(new Date(groupFieldValue), "yyyy-MM-dd");
}
switch (_field.fieldType) {
case "DateTime":
groupFieldValue =
groupFieldValue != "Unassigned" ? format(parseISO(groupFieldValue), "yyyy-MM-dd") : "Unassigned";
break;
case "AllDayEvent":
groupFieldValue = groupFieldValue === "No" ? "0" : "1";
break;
default:
break;
}
let _viewXml = `<View Scope='Recursive'>
<Query>
<OrderBy>
<FieldRef Name="${groupByField}" Ascending="FALSE"></FieldRef>
</OrderBy>
</Query>
</View>`;
if (groupFieldValue != "Unassigned") {
_viewXml = `<View Scope='Recursive'>
<Query>
<OrderBy>
<FieldRef Name="${groupByField}" Ascending="FALSE"></FieldRef>
</OrderBy>
<Where>
<Eq>
<FieldRef Name="${groupByField}"></FieldRef>
<Value Type="${_field.fieldType}" IncludeTimeValue="FALSE">${groupFieldValue}</Value>
</Eq>
</Where>
</Query>
</View>`;
}
if (groupFieldValue === "Unassigned") {
_viewXml = `<View Scope='Recursive'>
<Query>
<OrderBy>
<FieldRef Name="${groupByField}" Ascending="FALSE"></FieldRef>
</OrderBy>
<Where>
<IsNull>
<FieldRef Name="${groupByField}"></FieldRef>
</IsNull>
</Where>
</Query>
</View>`;
}
const _groupItemsResults = await sp.web.lists.getById(listId).renderListDataAsStream({ ViewXml: _viewXml });
return _groupItemsResults.Row;
};
// Get Lists
const getLists = async (baseTemplate: number): Promise<IListInfo[]> => {
let _filter: string = "Hidden eq false and ";
if (baseTemplate === 0) {
_filter = _filter + " BaseType ne 1";
} else {
_filter = _filter + " BaseType eq 1";
}
const _lists: IListInfo[] = await sp.web.lists.filter(_filter).get();
return _lists;
};
// Return functions
return {
getListColumns,
getLists,
getGroupItems,
getGroupHeaders,
getField,
};
};

View File

@ -0,0 +1,31 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
"id": "a0215264-a8cd-4952-aecd-4e80719de202",
"alias": "DocumentsLinksAccordionWebPart",
"componentType": "WebPart",
"supportsFullBleed": true,
// The "*" signifies that the version should be taken from the package.json
"version": "*",
"manifestVersion": 2,
// If true, the component can only be installed on sites where Custom Script is allowed.
// Components that allow authors to embed arbitrary script code should set this to true.
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false,
"supportedHosts": ["SharePointWebPart", "SharePointFullPage", "TeamsPersonalApp","TeamsTab"],
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
"group": { "default": "SPFx Custom Web Parts" },
"title": { "default": "Documents Links Accordion" },
"description": { "default": "Documents" },
"officeFabricIconFontName": "GroupedList",
"properties": {
"title": "Documents",
"listId": "",
"fieldName": "",
"listBasetemplate": 1
}
}]
}

View File

@ -0,0 +1,302 @@
import * as React from "react";
import * as ReactDom from "react-dom";
import {
loadTheme,
MessageBarType,
SpinnerSize
} from "office-ui-fabric-react";
import {
IReadonlyTheme,
ThemeChangedEventArgs,
ThemeProvider
} from "@microsoft/sp-component-base";
import { MSGraphClient } from "@microsoft/sp-http";
import {
IPropertyPaneConfiguration,
IPropertyPaneDropdownOption,
IPropertyPaneField,
IPropertyPaneGroup,
IPropertyPanePage,
PropertyPaneDropdown,
PropertyPaneTextField
} from "@microsoft/sp-property-pane";
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
import { sp } from "@pnp/sp";
import {
PropertyFieldListPicker,
PropertyFieldListPickerOrderBy
} from "@pnp/spfx-property-controls/lib/PropertyFieldListPicker";
import {
PropertyFieldMessage
} from "@pnp/spfx-property-controls/lib/PropertyFieldMessage";
import {
PropertyFieldSpinner
} from "@pnp/spfx-property-controls/lib/PropertyFieldSpinner";
import { useList } from "../../hooks/useList";
export interface IListItemsMenuWebPartProps {
title: string;
listId: string;
fieldName: string;
listBasetemplate: number;
}
const teamsDefaultTheme = require("../../common/TeamsDefaultTheme.json");
const teamsDarkTheme = require("../../common/TeamsDarkTheme.json");
const teamsContrastTheme = require("../../common/TeamsContrastTheme.json");
const { getListColumns, getLists } = useList() ;
import * as strings from 'DocumentsLinksAccordionWebPartStrings';
import { IDocumentsLinksAccordionProps } from "../../components/DocumentsLinksAccordion/IDocumentsLinksAccordionProps";
import {DocumentsLinksAccordion} from "../../components/DocumentsLinksAccordion/DocumentsLinksAccordion";
import { Version } from "@microsoft/sp-core-library";
export interface IDocumentsLinksAccordionWebPartProps {
title: string;
listId: string;
fieldName: string;
listBasetemplate: number;
}
export default class DocumentsLinksAccordionWebPart extends BaseClientSideWebPart<IDocumentsLinksAccordionWebPartProps> {
private columns: IPropertyPaneDropdownOption[] = [];
private lists: IPropertyPaneDropdownOption[] = [];
private _themeProvider: ThemeProvider;
private _themeVariant: IReadonlyTheme | undefined;
private _msgGraphclient: MSGraphClient;
private _hasError: boolean = false;
private _messageError: string = undefined;
protected async onInit(): Promise<void> {
sp.setup({
spfxContext: this.context,
});
this._msgGraphclient = await this.context.msGraphClientFactory.getClient();
this._themeProvider = this.context.serviceScope.consume(
ThemeProvider.serviceKey
);
// If it exists, get the theme variant
this._themeVariant = this._themeProvider.tryGetTheme();
// Register a handler to be notified if the theme variant changes
this._themeProvider.themeChangedEvent.add(
this,
this._handleThemeChangedEvent
);
if (this.context.sdks.microsoftTeams) {
// in teams ?
const context = this.context.sdks.microsoftTeams!.context;
this._applyTheme(context.theme || "default");
this.context.sdks.microsoftTeams.teamsJs.registerOnThemeChangeHandler(
this._applyTheme
);
}
return Promise.resolve();
}
/**
* Update the current theme variant reference and re-render.
*
* @param args The new theme
*/
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
this._themeVariant = args.theme;
this.render();
}
// Apply theme id in Teams
private _applyTheme = (theme: string): void => {
this.context.domElement.setAttribute("data-theme", theme);
document.body.setAttribute("data-theme", theme);
if (theme == "dark") {
loadTheme({
palette: teamsDarkTheme,
});
}
if (theme == "default") {
loadTheme({
palette: teamsDefaultTheme,
});
}
if (theme == "contrast") {
loadTheme({
palette: teamsContrastTheme,
});
}
}
public render(): void {
const element: React.ReactElement<IDocumentsLinksAccordionProps> = React.createElement(
DocumentsLinksAccordion,
{
title: this.properties.title,
listId: this.properties.listId,
fieldName: this.properties.fieldName,
themeVariant: this._themeVariant,
locale: this.context.pageContext.cultureInfo.currentUICultureName,
listBaseTemplate: this.properties.listBasetemplate ?? 1,
onConfigure: () =>{ this.context.propertyPane.open(); },
}
);
ReactDom.render(element, this.domElement);
}
protected onDispose(): void {
ReactDom.unmountComponentAtNode(this.domElement);
}
protected get disableReactivePropertyChanges() {
return true;
}
protected async onPropertyPaneConfigurationStart() {
if (
this.properties.fieldName &&
this.properties.listId &&
this.columns.length === 0
) {
await this.addListColumns(this.properties.listId);
this.context.propertyPane.refresh();
}
if ( this.properties.listId && this.lists.length === 0){
await this.addLists('1');
this.context.propertyPane.refresh();
}
}
protected async onPropertyPaneFieldChanged(
propertyPath: string,
oldValue: any,
newValue: any
) {
if (propertyPath === "listId" && newValue != oldValue) {
this.columns = [];
this.context.propertyPane.refresh();
await this.addListColumns(newValue);
this.context.propertyPane.refresh();
}
}
private async addLists(newValue: any) {
try {
this.lists = [];
const _lists = await getLists(newValue);
for (const _list of _lists) {
this.lists.push({ key: _list.Id, text: _list.Title });
}
} catch (error) {
this._hasError = true;
this._messageError =error.message;
}
}
private async addListColumns(newValue: any) {
try {
this.columns = [];
const _listColumns = await getListColumns(newValue);
for (const _column of _listColumns) {
this.columns.push({ key: _column.InternalName, text: _column.Title });
}
} catch (error) {
this._hasError = true;
this._messageError = error.message;
}
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
const _pages: IPropertyPanePage[] = [
{
header: {
description: strings.PropertyPaneDescription,
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField("title", {
label: strings.DescriptionFieldLabel,
}),
],
},
],
},
];
let groups: IPropertyPaneGroup = _pages[0].groups[0] as IPropertyPaneGroup;
let groupFields: IPropertyPaneField<any>[] = groups.groupFields;
groupFields.push(
PropertyFieldListPicker("listId", {
label: "Select Document Library",
selectedList: this.properties.listId ,
includeHidden: false,
baseTemplate: 101,
orderBy: PropertyFieldListPickerOrderBy.Title,
disabled: false,
onPropertyChange: this.onPropertyPaneFieldChanged.bind(this),
properties: this.properties,
context: this.context,
onGetErrorMessage: null,
deferredValidationTime: 0,
key: "listPickerFieldId",
})
);
if (this.properties.listId) {
groupFields.push(
PropertyFieldSpinner("", {
key: "sp1",
size: SpinnerSize.medium,
isVisible: (this.columns.length || this._hasError) ? false : true,
label: "Loading ...",
})
);
}
// Show Columns
if (this.columns.length > 0) {
groupFields.push(
PropertyPaneDropdown("fieldName", {
label: "Select field to group by documents",
options: this.columns,
selectedKey: this.properties.fieldName,
})
);
}
// Show Error
if (this._hasError) {
groupFields.push(
PropertyFieldMessage("", {
key: "msgError",
messageType: MessageBarType.error,
multiline: true,
text: this._messageError,
isVisible: this._hasError,
})
);
}
const _panelConfiguration: IPropertyPaneConfiguration = { pages: _pages };
return _panelConfiguration;
}
}

View File

@ -0,0 +1,12 @@
define([], function() {
return {
PlaceHolderButtonLable: "Configure",
PlaceHolderDescription: "Please configure the web part.",
PlaceHolderIconText: "Configure Documents Links Accordion Web Part",
"PropertyPaneDescription": "Show documents grouped by field",
"BasicGroupName": "Properties",
"DescriptionFieldLabel": "Title",
"NodocumentsLabel":"No documents found in library",
"ViewAllLabel": "View All"
}
});

View File

@ -0,0 +1,15 @@
declare interface IDocumentsLinksAccordionWebPartStrings {
PropertyPaneDescription: string;
BasicGroupName: string;
DescriptionFieldLabel: string;
ViewAllLabel:string;
NodocumentsLabel:string;
PlaceHolderButtonLable: string;
PlaceHolderDescription: string;
PlaceHolderIconText: string;
}
declare module 'DocumentsLinksAccordionWebPartStrings' {
const strings: IDocumentsLinksAccordionWebPartStrings;
export = strings;
}

View File

@ -0,0 +1,35 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.7/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"strictNullChecks": false,
"noUnusedLocals": false,
"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx"
]
}

View File

@ -0,0 +1,30 @@
{
"extends": "./node_modules/@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
"forin": false,
"label-position": false,
"member-access": true,
"no-arg": false,
"no-console": false,
"no-construct": false,
"no-duplicate-variable": true,
"no-eval": false,
"no-function-expression": true,
"no-internal-module": true,
"no-shadowed-variable": true,
"no-switch-case-fall-through": true,
"no-unnecessary-semicolons": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-with-statement": true,
"semicolon": true,
"trailing-comma": false,
"typedef": false,
"typedef-whitespace": false,
"use-named-parameter": true,
"variable-name": false,
"whitespace": false
}
}

View File

@ -22,9 +22,18 @@ This web part will allow users to view/update application customizers properties
- Allows to update application customizer properties which makes it easy to make re-useable application customizers
## Used SharePoint Framework Version
![SPFx 1.11](https://img.shields.io/badge/version-1.11-green.svg)
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires access to list the application customizers on a hosted site collection")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
@ -45,12 +54,6 @@ Version|Date|Comments
-------|----|--------
1.0|October 16, 2020|Initial release
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
---
## Minimal Path to Awesome
- Clone this repository
@ -62,8 +65,6 @@ Version|Date|Comments
For any issue or help, Buzz us on twitter:([sanganikunj](https://twitter.com/sanganikunj)) or ([siddh_me](https://twitter.com/siddh_me/))
> Sharing is caring!
## References
- [Getting started with SharePoint Framework](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
@ -72,4 +73,21 @@ For any issue or help, Buzz us on twitter:([sanganikunj](https://twitter.com/san
- [Publish SharePoint Framework applications to the Marketplace](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-overview)
- [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - Guidance, tooling, samples and open-source controls for your Microsoft 365 development
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-edit-applicationcustomizers&authors=@kunj-sangani%20@siddharth-vaghasia&title=react-edit-applicationcustomizers%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-edit-applicationcustomizers&authors=@kunj-sangani%20@siddharth-vaghasia&title=react-edit-applicationcustomizers%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-edit-applicationcustomizers&authors=@kunj-sangani%20@siddharth-vaghasia&title=react-edit-applicationcustomizers%20-%20).
> Sharing is caring!
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-edit-applicationcustomizers" />

View File

@ -0,0 +1 @@
// A file is required to be in the root of the /src directory by the TypeScript compiler

33
samples/react-emoji-ratings/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
# Logs
logs
*.log
npm-debug.log*
# Dependency directories
node_modules
# Build generated files
dist
lib
release
solution
temp
*.sppkg
# Coverage directory used by tools like istanbul
coverage
# OSX
.DS_Store
# Visual Studio files
.ntvs_analysis.dat
.vs
bin
obj
# Resx Generated Code
*.resx.ts
# Styles Generated Code
*.scss.ts

View File

@ -0,0 +1,12 @@
{
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.12.1",
"libraryName": "react-emoji-reaction-rating",
"libraryId": "fe292bb9-a5c2-40b4-b90b-61e8510c3c09",
"packageManager": "npm",
"isDomainIsolated": false,
"componentType": "webpart"
}
}

View File

@ -0,0 +1,109 @@
# Emoji Ratings
## Summary
This is sample web part which can be used to take emoji based reaction or feedback for particular news/article/posts.
We all know every organizations would be using SharePoint news features for company's internal communications from HR to IT updates and some time annoucements. News created in SharePoint are created as Pages in library. Idea behind this web part is to take employee/user's feedback as emoji reactions on particular news. This web part can also be used on wiki articles or blog posts to take similar reactions. Web part uses concept of 1 to 5 star based rating system(configurable), you can decide low to high based on your preference.
Ideally, we can do some automation using PnP Powershell and PowerAutomate (trigger when item is created ) to add this web part to any every news that is published.
If you wish to directly use the package in your tenant here is [link](https://github.com/siddharth-vaghasia/public-docs/blob/master/react-emoji-reaction-rating.sppkg) to download.
![Web part in Action](./assets/EmojiWPinAction.gif)
## Features
* Configurable header text, rating text, and images
* We can choose to show from minimum one rating to max 5 rating images and text
* Option to show total count of particular rating count as badge
* Option to show and capture comments from user when submitting feedback
* Display current user's rating selection with highlighted background
* Allow user to change rating(update rating)
* Stores ratings in SharePoint List
* Option to create list on the fly and choose list to store the ratings
* Option for admin to choose background color
## Technical Notes
* User's rating data would be stored in SP List, below are list of columns and its relevance
1. `Title`: To store user's display name (not required though)
2. `Page Name`: To store page on which rating is given by particular user, this will have absolute url of page
3. `User`: To store user who has given feedback for particular page/news where web part is added
4. `Comment`: To store comment provided by user while submitting reaction.
5. Then there are 5 columns `Rating1`, `Rating2`, `Rating3`, `Rating4`, `Rating5` which will store the rating text configured by admin in web part... Only one of this 5 columns would be populated for single item in list, which is what user has selected as part of giving reaction
* Below is how you can configure emoji's text and its image url
![Web part in Action](./assets/EmojisConfigurations.png)
I have added default emoji's images which can be used and uploaded to SharePoint library in the assets folder of this solution.
## Compatibility
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
![Teams Incompatible](https://img.shields.io/badge/Teams-Incompatible-lightgrey.svg)
![Local Workbench Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires access to a SharePoint list")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
## Applies to
- [SharePoint Framework](https://aka.ms/spfx)
- [Microsoft 365 tenant](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
> Get your own free development tenant by subscribing to [Microsoft 365 developer program](http://aka.ms/o365devprogram)
## Prerequisites
* SharePoint Online tenant
* Permission to deploy package to Tenant or SharePoint Site collection app catalog
## Solution
Solution|Author(s)
--------|---------
react-emoji-ratings | [Siddharth Vaghasia](https://github.com/siddharth-vaghasia) ([@siddh_me](https://twitter.com/siddh_me))
## Version history
Version|Date|Comments
-------|----|--------
1.0|Sep 04, 2021|Initial release
## Minimal Path to Awesome
- Clone this repository
- Ensure that you are at the solution folder
- in the command-line run:
- `npm install`
- `gulp serve`
## References
- [Getting started with SharePoint Framework](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
- [Building for Microsoft teams](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/build-for-teams-overview)
- [Publish SharePoint Framework applications to the Marketplace](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-overview)
- [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - Guidance, tooling, samples and open-source controls for your Microsoft 365 development
## Disclaimer
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
## Help
We do not support samples, but we this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues.
If you encounter any issues while using this sample, [create a new issue](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
For questions regarding this sample, [create a new question](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/sp-dev-fx-webparts/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=react-emoji-ratings&authors=@siddharth-vaghasia&title=react-emoji-ratings%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-emoji-ratings" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,55 @@
[
{
"name": "pnp-sp-dev-spfx-web-parts-react-emoji-ratings",
"source": "pnp",
"title": "Emoji Ratings",
"shortDescription": "Take emoji-based reactions or feedback for a given news/article/post",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-emoji-ratings",
"longDescription": [
"This is sample web part which can be used to take emoji based reaction or feedback for particular news/article/posts.",
"We all know every organizations would be using SharePoint news features for company's internal communications from HR to IT updates and some time annoucements. News created in SharePoint are created as Pages in library. Idea behind this web part is to take employee/user's feedback as emoji reactions on particular news. This web part can also be used on wiki articles or blog posts to take similar reactions. Web part uses concept of 1 to 5 star based rating system(configurable), you can decide low to high based on your preference."
],
"creationDateTime": "2021-09-24",
"updateDateTime": "2021-09-24",
"products": [
"SharePoint",
"Office"
],
"metadata": [
{
"key": "CLIENT-SIDE-DEV",
"value": "React"
},
{
"key": "SPFX-VERSION",
"value": "1.12.1"
},
{
"key": "PNPCONTROLS",
"value": "PropertyFieldCollectionData, PropertyFieldColorPicker, Placeholder"
}
],
"thumbnails": [
{
"type": "image",
"order": 100,
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-emoji-ratings/assets/EmojiWPinAction.gif",
"alt": "Web part in action"
}
],
"authors": [
{
"gitHubAccount": "siddharth-vaghasia",
"pictureUrl": "https://github.com/siddharth-vaghasia.png",
"name": "Siddharth Vaghasia"
}
],
"references": [
{
"name": "Build your first SharePoint client-side web part",
"description": "Client-side web parts are client-side components that run in the context of a SharePoint page. Client-side web parts can be deployed to SharePoint environments that support the SharePoint Framework. You can also use modern JavaScript web frameworks, tools, and libraries to build them.",
"url": "https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
}
]
}
]

View File

@ -0,0 +1,20 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
"version": "2.0",
"bundles": {
"react-emoji-reaction-rating-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/reactEmojiReactionRating/ReactEmojiReactionRatingWebPart.js",
"manifest": "./src/webparts/reactEmojiReactionRating/ReactEmojiReactionRatingWebPart.manifest.json"
}
]
}
},
"externals": {},
"localizedResources": {
"ReactEmojiReactionRatingWebPartStrings": "lib/webparts/reactEmojiReactionRating/loc/{locale}.js",
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js",
"ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
}
}

View File

@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
"deployCdnPath": "./release/assets/"
}

View File

@ -0,0 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
"workingDir": "./release/assets/",
"account": "<!-- STORAGE ACCOUNT NAME -->",
"container": "react-emoji-reaction-rating",
"accessKey": "<!-- ACCESS KEY -->"
}

Some files were not shown because too many files have changed in this diff Show More