Merge branch 'main' into React-List-Items-Menu-SPfx-Upgrade

This commit is contained in:
Hugo Bernier 2021-10-31 17:44:27 -04:00 committed by GitHub
commit 5e32931fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
116 changed files with 69190 additions and 33842 deletions

View File

@ -128,6 +128,10 @@ This Web Part illustrates the following concepts on top of the SharePoint Framew
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.
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/labels/YOUR-SOLUTION-NAME) to see if anybody else is having the same issues.
You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=label%3AYOUR-SOLUTION-NAME) and see what the community is saying.
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=YOUR-SOLUTION-NAME&authors=@YOURGITHUBUSERNAME&title=YOUR-SOLUTION-NAME%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=YOUR-SOLUTION-NAME&authors=@YOURGITHUBUSERNAME&title=YOUR-SOLUTION-NAME%20-%20).

View File

@ -47,6 +47,7 @@ Solution|Author(s)
js-modern-calendar | Jeremy Coleman (MCP, PC Professional, Inc.)
js-modern-calendar | Nanddeep Nachan ([@NanddeepNachan](twitter.com/NanddeepNachan))
js-modern-calendar | Ravi Chandra ([Ravikadri](https://github.com/Ravikadri))
js-modern-calendar | Peter Paul Kirschner ([@petkir_at](https://twitter.com/petkir_at))
## Version history
@ -55,6 +56,7 @@ Version|Date|Comments
1.0.0.0|February 11, 2017|Initial release
1.0.0.1|June 05, 2020|Updated the external CDN references to public CDN references
1.0.2.0|February 9, 2021|Upgraded to SPFx 1.11 and fixed issues with missing dependencies
1.0.3.0|October 28, 2021|fixed issues with Timezones. The Browser Timezone Settings are now used
## Disclaimer

View File

@ -21,7 +21,7 @@
},
{
"key": "SPFX-VERSION",
"value": "1.6.0"
"value": "1.11.0"
}
],
"thumbnails": [
@ -45,6 +45,13 @@
"pictureUrl": "https://github.com/nanddeepn.png",
"name": "Nanddeep Nachan",
"twitter": "NanddeepNachan"
},
{
"gitHubAccount": "petkir",
"company": "Cubido Business Solutions GmbH",
"pictureUrl": "https://github.com/petkir.png",
"name": "Peter Paul Kirschner",
"twitter": "petkir_at"
}
],
"references": [

View File

@ -2,7 +2,7 @@
"solution": {
"name": "SPFx Modern Calendar",
"id": "3d593a2f-73f1-486f-9dae-555c6f6b584d",
"version": "1.0.2.0",
"version": "1.0.3.0",
"includeClientSideAssets": true,
"developer": {
"name": "",

View File

@ -1,6 +1,6 @@
{
"name": "modern-calendar",
"version": "1.0.2",
"version": "1.0.3",
"private": true,
"main": "lib/index.js",
"engines": {

View File

@ -390,10 +390,12 @@ export default class ModernCalendarWebPart extends BaseClientSideWebPart<IModern
private _renderList(items: any[]): void {
var calItems: EventObjectInput[] = items.map((list: any) => {
const start = list[this.properties.start];
const end = list[this.properties.end];
return {
title: list[this.properties.title],
start: list[this.properties.start],
end: list[this.properties.end],
start: moment.utc(start,'YYYY-MM-DD HH:mm:ss').toDate(),
end: moment.utc(end,'YYYY-MM-DD HH:mm:ss').toDate(),
id: list["Id"],
detail: list[this.properties.detail],
};
@ -405,9 +407,9 @@ export default class ModernCalendarWebPart extends BaseClientSideWebPart<IModern
events: calItems,
eventClick: (_event) => {
var eventDetail =
moment(_event["start"]).format("MM/DD/YYYY hh:mm") +
moment.utc(_event["start"]).local().format('YYYY-MM-DD hh:mm A') +
" - " +
moment(_event["end"]).format("MM/DD/YYYY hh:mm") +
moment.utc(_event["end"]).local().format('YYYY-MM-DD hh:mm A') +
"<br>" +
_event["detail"];
swal2.default(_event.title, eventDetail, "info");

View File

@ -1,4 +1,4 @@
# react-at-a-glance
# At a glance
## Summary
@ -7,7 +7,7 @@ This sample shows a web part to show the first few sentences of an article in a
The idea is based of the *At a glance* section of a news in the BBC news app (beta).
### Highlights
- Usage of `SPHttpClient` or `PnP JS`
- Usage of `SPHttpClient` or `PnPjs`
- Conditional property enabling
- Usage of regex to get the sentences from article content
- Usage of Carousel for mobile view
@ -31,14 +31,16 @@ The idea is based of the *At a glance* section of a news in the BBC news app (be
![article-content-desktop](./assets/article-content-desktop.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)
![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")
![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 "The solution requires access to a news page to work")
![Hosted Workbench Partially](https://img.shields.io/badge/Hosted%20Workbench-Partially-yellow.svg "The solution needs to run on a news page to work")
## Applies to
@ -62,17 +64,18 @@ react-at-a-glance | [Anoop Tatti](https://github.com/anoopt) ([https://linktr.ee
Version|Date|Comments
-------|----|--------
1.0|September 07, 2021|Initial release
1.1|October 20, 2021|Minor CSS changes
## Minimal Path to Awesome
- Clone this repository
- Ensure that you are at the solution folder
- in the command-line run:
- **npm install**
- **gulp serve**
- `npm install`
- `gulp serve`
- Open a news article
- Add `?loadSPFX=true&debugManifestsFile=https://localhost:4321/temp/manifests.js` to the URL
- Add the `At a glance` web part to the page
- Add the **At a glance** web part to the page
## Features

View File

@ -10,7 +10,7 @@
"The idea is based of the At a glance section of a news in the BBC news app."
],
"creationDateTime": "2021-09-07",
"updateDateTime": "2021-09-07",
"updateDateTime": "2021-10-20",
"products": [
"SharePoint",
"Office"

View File

@ -77,6 +77,10 @@ export default class NewsGlanceWebPart extends BaseClientSideWebPart<INewsGlance
let element: any;
if (this.width < 400) {
this.sentences = this.sentences.map(sentence => {
return sentence.length > 100 ? `${sentence.slice(0, 100)}...` : sentence;
});
element = React.createElement(
NewsGlanceSmall,
{

View File

@ -25,13 +25,12 @@
}
.leftItem {
max-width: 150px;
object-fit: contain;
align-self: flex-start;
max-width: 200px;
flex: 1;
}
.rightItem {
flex: 1 1 auto;
flex: 2;
}
.articleImage {

View File

@ -8,10 +8,8 @@
.carouselItem {
background-color: $ms-color-themeDark;
// display: flex;
min-height: 150px;
height: 98%;
// justify-content: center;
}
.carouselDotList {

View File

@ -140,6 +140,7 @@ Version|Date|Comments
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 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

View File

@ -8,8 +8,8 @@
"longDescription": [
"This Web Part allows you to manage events in a calendar. Uses a list of existing calendars on any website. The location and name of the list and the dates of the events to be displayed are defined in the properties of the web part."
],
"creationDateTime": "2020-12-04",
"updateDateTime": "2021-10-02",
"created": "2020-12-04",
"modified": "2021-10-16",
"products": [
"SharePoint",
"Office"

View File

@ -369,6 +369,8 @@ export default class parseRecurrentEvent {
}
}
if (e.fRecurrence === "1" && e.MasterSeriesItemID !== "") {
e.EventDate = new Date(this.parseDate(e.EventDate, e.fAllDayEvent));
e.EndDate = new Date(this.parseDate(e.EndDate, e.fAllDayEvent));
const ni = this.cloneObj(e);
er.push(ni);
}

View File

@ -10,7 +10,7 @@ I got the idea from this great article [Use Power Automate to Notify of Upcoming
## 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)
![Node.js LTS v12 | LTS v10](https://img.shields.io/badge/Node.js-LTS%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 Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
@ -32,6 +32,7 @@ react-graph-app-secret-expiration | [Aimery Thomas](https://github.com/a1mery) (
Version|Date|Comments
-------|----|--------
1.0|September 17, 2021|Initial release
1.1|October 10, 2021|Add pagination
## Minimal Path to Awesome
@ -39,14 +40,14 @@ Version|Date|Comments
- Clone this repository
- Ensure that you are at the solution folder
- In the command-line run:
- **npm install**
- **gulp bundle**
- **gulp package-solution**
- `npm install`
- `gulp bundle`
- `gulp package-solution`
- Deploy the package to your app catalog
- Approve the API permission request from the SharePoint admin
- Add the web part to a page
- In the command-line run:
- **gulp serve --nobrowser**
- `gulp serve --nobrowser`
## Features

View File

@ -9,7 +9,7 @@
"This sample web part shows the list of your applications registered in Azure AD along with their associated client secret/certificate expiration date."
],
"creationDateTime": "2021-09-17",
"updateDateTime": "2021-09-17",
"updateDateTime": "2021-10-10",
"products": [
"SharePoint",
"Office"
@ -22,6 +22,10 @@
{
"key": "SPFX-VERSION",
"value": "1.12.1"
},
{
"key": "PNPCONTROLS",
"value": "Pagination"
}
],
"thumbnails": [

View File

@ -3,7 +3,7 @@
"solution": {
"name": "react-graph-app-secret-expiration-client-side-solution",
"id": "b25d85a4-7310-408a-a263-25959b0a5b1b",
"version": "1.0.0.0",
"version": "1.1.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false,
"skipFeatureDeployment": true,

View File

@ -1,6 +1,6 @@
{
"name": "react-graph-app-secret-expiration",
"version": "0.0.1",
"version": "1.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "react-graph-app-secret-expiration",
"version": "0.0.1",
"version": "1.1.0",
"private": true,
"main": "lib/index.js",
"scripts": {

View File

@ -5,7 +5,9 @@ import { ListView, IViewField, SelectionMode, GroupOrder, IGrouping } from "@pnp
import { IApplications, IApplication, IFormattedApplication } from '../../../models/IApplication';
import { IGraphAppSecretExpirationState } from './GraphAppSecretExpirationState';
import * as moment from 'moment';
import { DefaultButton, Spinner, mergeStyles } from '@fluentui/react';
import { DefaultButton, Spinner, mergeStyles, SearchBox } from '@fluentui/react';
import { Pagination } from "@pnp/spfx-controls-react/lib/pagination";
import * as strings from 'GraphAppSecretExpirationWebPartStrings';
const stackItemHidden = mergeStyles({
display: 'none',
@ -57,9 +59,13 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
super(props);
this.state = {
applications: [],
filteredApplications: [],
filterValue: "",
searchFilter: "",
error: undefined,
loading: true,
groupByFields: []
groupByFields: [],
page: 1
};
}
@ -113,8 +119,6 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
var today = (moment(Date.now())).format('DD-MMM-YYYY');
try {
applications.forEach(app => {
if (app.passwordCredentials.length > 0) {
app.passwordCredentials.forEach(pswd => {
let daysBeforeExpiration = moment.duration((moment(pswd.endDateTime)).diff(today, 'days'), 'days').asDays();
let formatedApp: IFormattedApplication = {
@ -126,8 +130,6 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
};
displayedApplication.push(formatedApp);
});
}
if (app.keyCredentials.length > 0) {
app.keyCredentials.forEach(keyCred => {
let daysBeforeExpiration = moment.duration((moment(keyCred.endDateTime)).diff(today, 'days'), 'days').asDays();
let formatedApp: IFormattedApplication = {
@ -139,16 +141,58 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
};
displayedApplication.push(formatedApp);
});
}
});
this.setState({
applications: displayedApplication
applications: displayedApplication,
filteredApplications: displayedApplication
});
} catch (error) {
console.log(error);
}
}
private _getPage(selectedPage: number) {
this.setState({
page: selectedPage
});
}
private _filterApplication = (value, clear: boolean) => {
let searchResult: IFormattedApplication[] = [];
if (clear) {
this.state.applications.forEach(app => {
if (this._filterByProperties(app, value)) {
searchResult.push(app);
}
});
this.setState({
filteredApplications: searchResult,
filterValue: value
});
} else {
this.setState({
filteredApplications: this.state.applications,
filterValue: value,
page: 1
});
}
}
private _filterByProperties(application: IFormattedApplication, filterValue) {
if (application.applicationId.toLowerCase().indexOf(filterValue.toLowerCase()) >= 0) {
return true;
} else if (application.displayName.toLowerCase().indexOf(filterValue.toLowerCase()) >= 0) {
return true;
} else if (application.expirationDate.toLowerCase().indexOf(filterValue.toLowerCase()) >= 0) {
return true;
} else if (application.type.toLowerCase().indexOf(filterValue.toLowerCase()) >= 0) {
return true;
} else {
return false;
}
}
private _groupView = () => {
if (this.state.groupByFields.length === 0) {
let groupByFields: IGrouping[] = [
@ -181,17 +225,27 @@ export default class GraphAppSecretExpiration extends React.Component<IGraphAppS
</div>
<div className={this.state.loading ? stackItemHidden : ""}>
<DefaultButton text={this.state.groupByFields.length === 0 ? "Group by App ID" : "Ungroup"} onClick={this._groupView} />
<SearchBox placeholder="Search" onChange={(e, text) => this._filterApplication(text, false)} onClear={() => this._filterApplication("", true)} value={this.state.filterValue} />
<ListView
items={this.state.applications}
items={this.state.filteredApplications.slice(this.state.page === 1 || this.state.filterValue !== "" ? 0 : this.state.page * 10 - 10, this.state.page * 10)}
viewFields={_viewFields}
iconFieldName="ServerRelativeUrl"
compact={true}
selectionMode={SelectionMode.none}
selection={this._getSelection}
groupByFields={this.state.groupByFields}
showFilter={true}
showFilter={false}
filterPlaceHolder="Search..." />
</div>
<Pagination
currentPage={1}
totalPages={Math.floor(this.state.filteredApplications.length / 10) + 1}
onChange={(page) => this._getPage(page)}
limiter={3} // Optional - default value 3
hideFirstPageJump // Optional
hideLastPageJump // Optional
limiterIcon={"Emoji12"} // Optional
/>
</div>
</div>
);

View File

@ -3,7 +3,11 @@ import { IApplications, IApplication,IPasswordCredential,IKeyCredential,IFormatt
export interface IGraphAppSecretExpirationState {
applications: IFormattedApplication[];
filteredApplications: IFormattedApplication[];
filterValue: string;
searchFilter: string;
groupByFields: IGrouping[];
page: number;
error: string;
loading: boolean;
}

View File

@ -10,6 +10,7 @@ node_modules
dist
lib
solution
release
temp
*.sppkg

View File

@ -26,11 +26,13 @@ Web part pulls all Microsoft 365 Groups and Teams that the logged in user has ac
## Compatibility
![SPFx 1.10](https://img.shields.io/badge/SPFx-1.10.0-green.svg)
![Node.js LTS 8.x | LTS 10.x](https://img.shields.io/badge/Node.js-LTS%208.x%20%7C%20LTS%210.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: Only after API permissions granted](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Only after API permissions granted")
![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%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 Incompatible](https://img.shields.io/badge/Local%20Workbench-Incompatible-red.svg "This solution requires API permissions")
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-yellow.svg "Only after API permissions granted")
## Applies to
@ -41,7 +43,7 @@ Web part pulls all Microsoft 365 Groups and Teams that the logged in user has ac
Solution|Author(s)
--------|---------
React-Groups-Teams | [Alison Collins](https://github.com/ReactIntern) |
React-Groups-Teams | [Alison Collins](https://github.com/ReactIntern) ([Blog](https://graphgod.dev), [LinkedIn](https://www.linkedin.com/in/alison-collins-53192b219/)) |
## Version history
@ -49,7 +51,7 @@ React-Groups-Teams | [Alison Collins](https://github.com/ReactIntern) |
| ------- | ---------------- | --------------- |
| 1.0.0 | April 16, 2021 | Initial release |
| 1.0.1 | August 1, 2021 | Fixed references to Office.com |
| 1.1.0 | October 8, 2021 | Upgraded to SPFx 1.12.1 for higher compatibility and added Teams Tab deployment support. |
# Prerequisites

View File

@ -9,7 +9,7 @@
"Web part pulls all Microsoft 365 Groups and Teams that the logged in user has access to view."
],
"creationDateTime": "2021-05-06",
"updateDateTime": "2021-08-01",
"updateDateTime": "2021-10-08",
"products": [
"SharePoint",
"Office"
@ -21,7 +21,7 @@
},
{
"key": "SPFX-VERSION",
"value": "1.10.0"
"value": "1.12.1"
}
],
"thumbnails": [

View File

@ -1,7 +1,16 @@
'use strict';
const gulp = require('gulp');
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.`);
build.initialize(gulp);
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

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,10 @@
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.9.1",
"@microsoft/sp-lodash-subset": "1.9.1",
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
"@microsoft/sp-webpart-base": "1.9.1",
"@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-webpart-base": "1.12.1",
"@types/es6-promise": "0.0.33",
"@types/react": "16.8.8",
"@types/react-dom": "16.8.3",
@ -28,10 +28,10 @@
"@types/react": "16.8.8"
},
"devDependencies": {
"@microsoft/sp-build-web": "1.9.1",
"@microsoft/sp-tslint-rules": "1.9.1",
"@microsoft/sp-module-interfaces": "1.9.1",
"@microsoft/sp-webpart-workbench": "1.9.1",
"@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-2.9": "0.7.16",
"gulp": "~3.9.1",
"@types/chai": "3.4.34",

View File

@ -0,0 +1,66 @@
{
"id": "5ced32db-af85-469a-a3cb-39f3986e1f1a",
"alias": "MicrosoftGroupsWebPart",
"componentType": "WebPart",
"version": "1.0.1",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [
"SharePointWebPart",
"TeamsTab"
],
"preconfiguredEntries": [
{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": {
"default": "Other"
},
"title": {
"default": "Microsoft Groups"
},
"description": {
"default": "Microsoft Groups description"
},
"officeFabricIconFontName": "Page",
"properties": {
"description": "Microsoft Groups"
}
}
],
"loaderConfig": {
"internalModuleBaseUrls": [
"https://localhost:4321/dist/"
],
"entryModuleId": "microsoft-groups-web-part",
"scriptResources": {
"microsoft-groups-web-part": {
"type": "path",
"path": "microsoft-groups-web-part_da003a7fb7fd1f14fcb7.js"
},
"@microsoft/sp-core-library": {
"type": "component",
"id": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"version": "1.12.1"
},
"@microsoft/sp-webpart-base": {
"type": "component",
"id": "974a7777-0990-4136-8fa6-95d80114c2e0",
"version": "1.12.1"
},
"react": {
"type": "component",
"id": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"version": "16.8.5"
},
"react-dom": {
"type": "component",
"id": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"version": "16.8.5"
},
"MicrosoftGroupsWebPartStrings": {
"type": "path",
"path": "MicrosoftGroupsWebPartStrings_en-us_b41dd8b4c7f5f69692bd8f24e2b83745.js"
}
}
}
}

View File

@ -0,0 +1,7 @@
define([], function() {
return {
"PropertyPaneDescription": "Description",
"BasicGroupName": "Group Name",
"DescriptionFieldLabel": "Description Field"
}
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,98 @@
{
"bundles": {
"microsoft-groups-web-part": {
"dependencies": [
{
"componentId": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"componentName": "@microsoft/sp-core-library",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "01c4df03-e775-48cb-aa14-171ee5199a15",
"componentName": "tslib",
"componentVersion": "1.10.0",
"isDirectDependency": false
},
{
"componentId": "2e09fb9b-13bb-48f2-859f-97d6fff71176",
"componentName": "@ms/odsp-core-bundle",
"componentVersion": "1.1.13",
"isDirectDependency": false
},
{
"componentId": "73e1dc6c-8441-42cc-ad47-4bd3659f8a3a",
"componentName": "@microsoft/sp-lodash-subset",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "974a7777-0990-4136-8fa6-95d80114c2e0",
"componentName": "@microsoft/sp-webpart-base",
"componentVersion": "1.12.1",
"isDirectDependency": true
},
{
"componentId": "8217e442-8ed3-41fd-957d-b112e841286a",
"componentName": "@ms/sp-telemetry",
"componentVersion": "0.19.2",
"isDirectDependency": false
},
{
"componentId": "467dc675-7cc5-4709-8aac-78e3b71bd2f6",
"componentName": "@microsoft/sp-component-base",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "e40f8203-b39d-425a-a957-714852e33b79",
"componentName": "@microsoft/sp-dynamic-data",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "78359e4b-07c2-43c6-8d0b-d060b4d577e8",
"componentName": "@microsoft/sp-diagnostics",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "1c4541f7-5c31-41aa-9fa8-fbc9dc14c0a8",
"componentName": "@microsoft/sp-page-context",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "229b8d08-79f3-438b-8c21-4613fc877abd",
"componentName": "@microsoft/load-themed-styles",
"componentVersion": "0.1.2",
"isDirectDependency": false
},
{
"componentId": "c07208f0-ea3b-4c1a-9965-ac1b825211a6",
"componentName": "@microsoft/sp-http",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "1c6c9123-7aac-41f3-a376-3caea41ed83f",
"componentName": "@microsoft/sp-loader",
"componentVersion": "1.12.1",
"isDirectDependency": false
},
{
"componentId": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"componentName": "react",
"componentVersion": "16.8.5",
"isDirectDependency": true
},
{
"componentId": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"componentName": "react-dom",
"componentVersion": "16.8.5",
"isDirectDependency": true
}
]
}
}
}

View File

@ -0,0 +1,66 @@
{
"id": "5ced32db-af85-469a-a3cb-39f3986e1f1a",
"alias": "MicrosoftGroupsWebPart",
"componentType": "WebPart",
"version": "1.0.1",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [
"SharePointWebPart",
"TeamsTab"
],
"preconfiguredEntries": [
{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": {
"default": "Other"
},
"title": {
"default": "Microsoft Groups"
},
"description": {
"default": "Microsoft Groups description"
},
"officeFabricIconFontName": "Page",
"properties": {
"description": "Microsoft Groups"
}
}
],
"loaderConfig": {
"internalModuleBaseUrls": [
"<!-- PATH TO CDN -->"
],
"entryModuleId": "microsoft-groups-web-part",
"scriptResources": {
"microsoft-groups-web-part": {
"type": "path",
"path": "microsoft-groups-web-part_da003a7fb7fd1f14fcb7.js"
},
"@microsoft/sp-core-library": {
"type": "component",
"id": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"version": "1.12.1"
},
"@microsoft/sp-webpart-base": {
"type": "component",
"id": "974a7777-0990-4136-8fa6-95d80114c2e0",
"version": "1.12.1"
},
"react": {
"type": "component",
"id": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"version": "16.8.5"
},
"react-dom": {
"type": "component",
"id": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"version": "16.8.5"
},
"MicrosoftGroupsWebPartStrings": {
"type": "path",
"path": "MicrosoftGroupsWebPartStrings_en-us_b41dd8b4c7f5f69692bd8f24e2b83745.js"
}
}
}
}

View File

@ -0,0 +1,66 @@
{
"id": "5ced32db-af85-469a-a3cb-39f3986e1f1a",
"alias": "MicrosoftGroupsWebPart",
"componentType": "WebPart",
"version": "1.0.1",
"manifestVersion": 2,
"requiresCustomScript": false,
"supportedHosts": [
"SharePointWebPart",
"TeamsTab"
],
"preconfiguredEntries": [
{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70",
"group": {
"default": "Other"
},
"title": {
"default": "Microsoft Groups"
},
"description": {
"default": "Microsoft Groups description"
},
"officeFabricIconFontName": "Page",
"properties": {
"description": "Microsoft Groups"
}
}
],
"loaderConfig": {
"internalModuleBaseUrls": [
"<!-- PATH TO CDN -->"
],
"entryModuleId": "microsoft-groups-web-part",
"scriptResources": {
"microsoft-groups-web-part": {
"type": "path",
"path": "microsoft-groups-web-part_da003a7fb7fd1f14fcb7.js"
},
"@microsoft/sp-core-library": {
"type": "component",
"id": "7263c7d0-1d6a-45ec-8d85-d4d1d234171b",
"version": "1.12.1"
},
"@microsoft/sp-webpart-base": {
"type": "component",
"id": "974a7777-0990-4136-8fa6-95d80114c2e0",
"version": "1.12.1"
},
"react": {
"type": "component",
"id": "0d910c1c-13b9-4e1c-9aa4-b008c5e42d7d",
"version": "16.8.5"
},
"react-dom": {
"type": "component",
"id": "aa0a46ec-1505-43cd-a44a-93f3a5aa460a",
"version": "16.8.5"
},
"MicrosoftGroupsWebPartStrings": {
"type": "path",
"path": "MicrosoftGroupsWebPartStrings_en-us_b41dd8b4c7f5f69692bd8f24e2b83745.js"
}
}
}
}

View File

@ -12,7 +12,7 @@
// 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"],
"supportedHosts": ["SharePointWebPart", "TeamsTab"],
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other

View File

@ -1,25 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@ -11,6 +11,7 @@ dist
lib
solution
temp
release
*.sppkg
# Coverage directory used by tools like istanbul

View File

@ -0,0 +1,16 @@
!dist
config
gulpfile.js
release
src
temp
tsconfig.json
tslint.json
*.log
.yo-rc.json
.vscode

View File

@ -4,23 +4,7 @@
* Chrome browser: https://aka.ms/spfx-debugger-extensions
*/
"version": "0.2.0",
"configurations": [{
"name": "Local workbench",
"type": "chrome",
"request": "launch",
"url": "https://localhost:4321/temp/workbench.html",
"webRoot": "${workspaceRoot}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///.././src/*": "${webRoot}/src/*",
"webpack:///../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../src/*": "${webRoot}/src/*",
"webpack:///../../../../../src/*": "${webRoot}/src/*"
},
"runtimeArgs": [
"--remote-debugging-port=9222"
]
},
"configurations": [
{
"name": "Hosted workbench",
"type": "chrome",

View File

@ -2,7 +2,7 @@
"@microsoft/generator-sharepoint": {
"isCreatingSolution": true,
"environment": "spo",
"version": "1.10.0",
"version": "1.13.0",
"libraryName": "react-kanban-board",
"libraryId": "cccbd72b-7b89-4128-9348-0a4850ded8fd",
"packageManager": "npm",

View File

@ -24,9 +24,17 @@ The web part uses the default columns of the SharePoint Tasks list for showing t
![picture of the web part in action](assets/kanbanofficeUI.gif)
## Used SharePoint Framework Version
![1.10.0](https://img.shields.io/badge/version-1.10.0-green.svg)
## Compatibility
![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)
![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)
## Applies to
@ -49,9 +57,10 @@ The Task list can be chosen using the web part properties (BaseTemplate 171 or 1
Solution|Author(s)
--------|---------
react-kanban-board | [Ram](https://twitter.com/ram_meenavalli)
react-kanban-board | Daniel Westerdale ([Westerdale Solutions Ltd.](https://westerdale.blog), [@westerdaled](https://twitter.com/westerdaled?s=20))
react-kanban-board | Peter Paul Kirschner ([@petkir_at](https://twitter.com/petkir_at))
react-kanban-board | [Ram Prasad Meenavalli](https://github.com/RamPrasadMeenavalli) ([@ram_meenavalli](https://twitter.com/ram_meenavalli))
react-kanban-board | [Daniel Westerdale](https://github.com/westerdaled) ([Westerdale Solutions Ltd.](https://westerdale.blog), [@westerdaled](https://twitter.com/westerdaled?s=20))
react-kanban-board | [Peter Paul Kirschner](https://github.com/petkir) ([@petkir_at](https://twitter.com/petkir_at))
react-kanban-board | [Alex Terentiev](https://github.com/AJIXuMuK) ([@alexaterentiev](https://twitter.com/alexaterentiev))
## Version history
@ -60,6 +69,7 @@ Version|Date|Comments
1.0.0.0|July 17, 2019|Initial release
1.0.1.0|April 21, 2020|Added support for Teams hosts
2.0.0.0|July 10, 2020| jqwidgets replaced with a custom Kanban Board based on Office UI Component and IE11 Support
3.0.0.0|October 29, 2021| SPFx 1.13, PnPJS v2, PnP Controls v3
[Read More about the implementation of this Board](./src/kanban/README.md)
@ -80,13 +90,6 @@ Version|Date|Comments
<!---* [Jean-Philippe CIVADE](https://github.com/ewidance) for Bug Report IE11 (initiator of rewrite of this sample)-->
<!---* [RamPrasadMeenavalli](https://github.com/RamPrasadMeenavalli) for the initial Idea-->
## 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
@ -102,4 +105,26 @@ This sample highlights the following concepts
When a task is moved to different columns in the Kanban Board, the status of the respective SharePoint list item is updated using PnP JS
## 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.
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/labels/react-kanban-board) to see if anybody else is having the same issues.
You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=label%3Areact-kanban-board) and see what the community is saying
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-kanban-board&authors=@RamPrasadMeenavalli%20@westerdaled%20@petkir%20@AJIXuMuK&title=react-kanban-board%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-kanban-board&authors=@RamPrasadMeenavalli%20@westerdaled%20@petkir%20@AJIXuMuK&title=react-kanban-board%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-kanban-board&authors=@RamPrasadMeenavalli%20@westerdaled%20@petkir%20@AJIXuMuK&title=react-kanban-board%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-kanban-board" />

View File

@ -21,11 +21,15 @@
},
{
"key": "SPFX-VERSION",
"value": "1.10.0"
"value": "1.13.0"
},
{
"key": "SPFX-TEAMSTAB",
"value": "true"
},
{
"key": "PNPCONTROLS",
"value": "PropertyFieldListPicker, PropertyFieldOrder, WebPartTitle, Placeholder"
}
],
"thumbnails": [
@ -57,6 +61,13 @@
"pictureUrl": "https://github.com/petkir.png",
"name": "Peter Paul Kirschner",
"twitter": "petkir_at"
},
{
"gitHubAccount": "AJIXuMuK",
"company": "Sharepointalist",
"pictureUrl": "https://avatars.githubusercontent.com/u/17036219?s=460\u0026u=b8e83fb70a90eae0c0e0078c206990785e1a5b6f\u0026v=4",
"name": "Alex Terentiev",
"twitter": "alexaterentiev"
}
],
"references": [

View File

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

View File

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

View File

@ -3,10 +3,17 @@
"solution": {
"name": "react-kanban-board-client-side-solution",
"id": "cccbd72b-7b89-4128-9348-0a4850ded8fd",
"version": "2.0.0.0",
"version": "3.0.0.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false
"isDomainIsolated": false,
"developer": {
"name": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"websiteUrl": "",
"mpnId": ""
}
},
"paths": {
"zippedPackage": "solution/react-kanban-board.sppkg"

View File

@ -2,9 +2,5 @@
"$schema": "https://developer.microsoft.com/json-schemas/core-build/serve.schema.json",
"port": 4321,
"https": true,
"initialPage": "https://localhost:5432/workbench",
"api": {
"port": 5432,
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
}
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
}

View File

@ -6,50 +6,13 @@ const gulp = require('gulp');
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.`);
// This section is inspired by Stefan Bauer's article at https://n8d.at/how-to-version-new-sharepoint-framework-projects/
// Stefan rocks!
let syncVersionsSubtask = build.subTask('version-sync', function (gulp, buildOptions, done) {
this.log('Synching versions');
// import gulp utilits to write error messages
const gutil = require('gulp-util');
// import file system utilities form nodeJS
const fs = require('fs');
// read package.json
var pkgConfig = require('./package.json');
// read configuration of web part solution file
var pkgSolution = require('./config/package-solution.json');
// log old version
this.log('package-solution.json version:\t' + pkgSolution.solution.version);
// Generate new MS compliant version number
var newVersionNumber = pkgConfig.version.split('-')[0] + '.0';
if (pkgSolution.solution.version !== newVersionNumber) {
// assign newly generated version number to web part version
pkgSolution.solution.version = newVersionNumber;
// log new version
this.log('New package-solution.json version:\t' + pkgSolution.solution.version);
fs.writeFile('./config/package-solution.json', JSON.stringify(pkgSolution, null, 4), function (err, result) {
if (err) this.log('error', err);
});
}
else {
this.log('package-solution.json version is up-to-date');
}
done();
});
let syncVersionTask = build.task('version-sync', syncVersionsSubtask);
build.rig.addPreBuildTask(syncVersionTask);
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(gulp);

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,39 @@
{
"name": "react-kanban-board",
"main": "lib/index.js",
"version": "2.0.0",
"version": "3.0.0",
"private": true,
"engines": {
"node": ">=0.10.0"
},
"engines": "undefined",
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
"test": "gulp test"
},
"dependencies": {
"@microsoft/sp-core-library": "1.10.0",
"@microsoft/sp-lodash-subset": "1.10.0",
"@microsoft/sp-office-ui-fabric-core": "1.10.0",
"@microsoft/sp-property-pane": "1.10.0",
"@microsoft/sp-webpart-base": "1.10.0",
"@pnp/common": "^1.3.3",
"@pnp/logging": "^1.3.3",
"@pnp/odata": "^1.3.3",
"@pnp/polyfill-ie11": "^2.0.2",
"@pnp/sp": "^1.3.3",
"@pnp/spfx-controls-react": "1.19.0",
"@pnp/spfx-property-controls": "1.19.0",
"@types/es6-promise": "0.0.33",
"@types/react": "16.8.8",
"@types/react-dom": "16.8.3",
"@types/webpack-env": "1.13.1",
"classnames": "^2.2.6",
"office-ui-fabric-react": "6.214.0",
"react": "16.8.5",
"react-dom": "16.8.5"
},
"resolutions": {
"@types/react": "16.8.8"
"@microsoft/sp-core-library": "1.13.0",
"@microsoft/sp-lodash-subset": "1.13.0",
"@microsoft/sp-office-ui-fabric-core": "1.13.0",
"@microsoft/sp-property-pane": "1.13.0",
"@microsoft/sp-webpart-base": "1.13.0",
"@pnp/sp": "2.10.0",
"@pnp/spfx-controls-react": "^3.5.0-beta.2d993b2",
"@pnp/spfx-property-controls": "^3.3.0-beta.d48002e",
"office-ui-fabric-react": "7.174.1",
"react": "16.13.1",
"react-dom": "16.13.1"
},
"devDependencies": {
"@microsoft/rush-stack-compiler-2.9": "0.7.7",
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
"@microsoft/sp-build-web": "1.10.0",
"@microsoft/sp-module-interfaces": "1.10.0",
"@microsoft/sp-tslint-rules": "1.10.0",
"@microsoft/sp-webpart-workbench": "1.10.0",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"@microsoft/rush-stack-compiler-3.7": "0.2.3",
"@microsoft/rush-stack-compiler-3.9": "0.4.47",
"@microsoft/sp-build-web": "1.13.0",
"@microsoft/sp-module-interfaces": "1.13.0",
"@microsoft/sp-tslint-rules": "1.13.0",
"@types/react": "16.9.51",
"@types/react-dom": "16.9.8",
"@types/webpack-env": "1.13.1",
"ajv": "~5.2.2",
"autoprefixer": "^9.8.4",
"gulp": "~3.9.1",
"gulp": "4.0.2",
"react-html-parser": "^2.0.2"
}
}

View File

@ -331,6 +331,7 @@ const hasprocessIndicator = buckets.filter((b)=> b.showPercentageHeadline).lengt
}
private onDragStart(event, taskId: string, bucket: string): void {
console.log('onDragStart');
const taskitem = this.props.tasks.filter(p => p.taskId === taskId);
if (taskitem.length === 1) {
event.dataTransfer.setData("text", taskId);
@ -353,6 +354,7 @@ const hasprocessIndicator = buckets.filter((b)=> b.showPercentageHeadline).lengt
private onDragOver(event, targetbucket: string): void {
event.preventDefault();
console.log('onDragOver');
if (this.dragelement.bucket !== targetbucket) {
const index = findIndex(this.props.buckets, element => element.bucket == targetbucket);

View File

@ -67,10 +67,8 @@ export default class KanbanTaskManagedProp extends React.Component<IKanbanTaskMa
size={PersonaSize.size32}
hidePersonaDetails={false}
/>))
)
)
))
}
};
</span>);
break;
case KanbanTaskMamagedPropertyType.complex:

View File

@ -11,7 +11,6 @@ import { cloneDeep } from '@microsoft/sp-lodash-subset';
import { PropertyFieldListPicker, PropertyFieldListPickerOrderBy } from '@pnp/spfx-property-controls/lib/PropertyFieldListPicker';
import { PropertyFieldOrder } from '@pnp/spfx-property-controls/lib/PropertyFieldOrder';
import * as strings from 'KanbanBoardWebPartStrings';
import "@pnp/polyfill-ie11";
import { sp } from '@pnp/sp';
import PropertyPaneBucketConfigComponent from './components/PropertyPaneBucketConfig';
@ -113,7 +112,7 @@ export default class KanbanBoardWebPart extends BaseClientSideWebPart<IKanbanBoa
onListsRetrieved: (lists) => {
//TODO Check from TS Definition it should be a string but i get a number
// with Typesafe equal it fails
if (Environment.type == EnvironmentType.Local || Environment.type == EnvironmentType.Test) {
if (Environment.type == EnvironmentType.Test) {
return lists;
} else {
const alists = lists.filter((l: any) => {

View File

@ -1,6 +1,4 @@
import { ISPKanbanService } from "./ISPKanbanService";
import "@pnp/polyfill-ie11";
import { sp } from '@pnp/sp';
import { IKanbanTask, KanbanTaskMamagedPropertyType } from "../../../kanban";
import * as strings from 'KanbanBoardWebPartStrings';

View File

@ -1,8 +1,16 @@
import { ISPKanbanService } from "./ISPKanbanService";
import "@pnp/polyfill-ie11";
import { sp } from '@pnp/sp';
import '@pnp/sp/webs';
import '@pnp/sp/lists';
import '@pnp/sp/items';
import '@pnp/sp/fields';
import { IKanbanTask, KanbanTaskMamagedPropertyType } from "../../../kanban";
import * as strings from 'KanbanBoardWebPartStrings';
import { IFieldInfo } from "@pnp/sp/fields";
interface IFieldChoiceInfo extends IFieldInfo {
Choices: string[];
}
export default class SPKanbanService implements ISPKanbanService {
@ -50,7 +58,7 @@ export default class SPKanbanService implements ISPKanbanService {
}
public getBuckets(listId: string, ): Promise<string[]> {
return sp.web.lists.getById(listId).fields.getByInternalNameOrTitle("Status").get()
.then(status => status.Choices.map((val, index) => {
.then((status: IFieldChoiceInfo) => status.Choices.map((val, index) => {
return val;
}));
}

View File

@ -1,5 +1,5 @@
{
"extends": "node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.9/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
@ -19,20 +19,18 @@
"./node_modules/@microsoft"
],
"types": [
"es6-promise",
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection"
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts", "src/webparts/kanbanBoard/components/bucketOrder.tsx"
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",
"lib"
]
"exclude": []
}

View File

@ -1,5 +1,5 @@
{
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
"extends": "./node_modules/@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,
@ -17,7 +17,6 @@
"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,

View File

@ -12,6 +12,7 @@ lib
release
solution
temp
release
*.sppkg
# Coverage directory used by tools like istanbul

View File

@ -56,7 +56,8 @@ Version|Date|Comments
1.0.0|November 20, 2020|Initial release
1.0.1|February 18, 2021|Added support for metadata columns
1.0.2|February 21, 2021|Fixed `gulp build` issues
1.0.3|October 31🦇, 2021|Upgraded to SPFx 1.13
1.0.3|October 25, 2021|Fixed bug support for metadata columns and Lookup fields
1.0.4|October 31🦇, 2021|Upgraded to SPFx 1.13
## Minimal Path to Awesome

View File

@ -34,6 +34,14 @@
{
"key": "SPFX-TEAMSPERSONALAPP",
"value": "true"
},
{
"key": "PNPCONTROLS",
"value": "PropertyFieldListPicker, PropertyFieldMessage, PropertyFieldSpinner"
},
{
"key": "REACT-HOOKS",
"value": "true"
}
],
"thumbnails": [

View File

@ -3,7 +3,7 @@
"solution": {
"name": "react-list-items-menu-client-side-solution",
"id": "8b4a758d-a968-4e7c-a949-b42e7dd5ad14",
"version": "1.0.2.0",
"version": "1.0.3.0",
"includeClientSideAssets": true,
"skipFeatureDeployment": true,
"isDomainIsolated": false,

View File

@ -24269,6 +24269,11 @@
}
}
},
"date-fns": {
"version": "2.25.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
"integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w=="
},
"dateformat": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "react-list-items-menu",
"version": "1.0.2",
"version": "1.0.3",
"private": true,
"main": "lib/index.js",
"engines": {
@ -27,6 +27,7 @@
"@pnp/spfx-property-controls": "1.19.0",
"@types/jquery": "^3.5.0",
"@uifabric/file-type-icons": "^7.6.11",
"date-fns": "^2.25.0",
"jquery": "^3.5.1",
"jsstore": "^3.10.3",
"moment": "^2.29.1",

View File

@ -158,3 +158,11 @@ export const convertTimeTo24h = (
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

@ -69,7 +69,86 @@ export const ListItemsMenu: React.FunctionComponent<IListItemsMenuProps> = (
const stateRef = React.useRef(state); // Use to access state on eventListenners
// On component did mount only if listId or Field Change
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,
onHeaderClick: _onGroupHeaderClick,
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 component did mount only if listId or Field Change
React.useEffect(() => {
(async () => {
if (!props.listId || !props.fieldName) {
@ -142,7 +221,7 @@ export const ListItemsMenu: React.FunctionComponent<IListItemsMenuProps> = (
setState(stateRef.current);
}
})();
}, [props.listId, props.fieldName]);
}, [props.listId, props.fieldName]); */
// On Header click get Items for the header
const _onGroupHeaderClick = async (

View File

@ -9,7 +9,8 @@ import moment from "moment";
import { sp } from "@pnp/sp";
import { IFieldInfo } from "@pnp/sp/fields";
import { IListInfo } from "@pnp/sp/lists";
import { checkIfValidDate } from "../Utils/Utils";
import {format , parseISO} from 'date-fns';
export const useList = () => {
// Run on useList hook
(async () => {})();
@ -71,12 +72,14 @@ export const useList = () => {
): 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"
? moment(groupFieldValue).format("YYYY-MM-DD")
: "Unassigned";
groupFieldValue != "Unassigned" ? format(parseISO(groupFieldValue), "yyyy-MM-dd") : "Unassigned";
break;
case "AllDayEvent":
groupFieldValue = groupFieldValue === "No" ? "0" : "1";
@ -84,7 +87,6 @@ export const useList = () => {
default:
break;
}
let _viewXml = `<View Scope='Recursive'>
<Query>
<OrderBy>

View File

@ -47,9 +47,17 @@ Current Data Functions:
Built with SharePoint Framework GA, Office Graph, React and Chart.JS
## Used SharePoint Framework Version
![version](https://img.shields.io/badge/version-1.10.0-green.svg)
## Compatibility
![SPFx 1.10](https://img.shields.io/badge/SPFx-1.10.0-green.svg)
![Node.js LSTS 8 | LTS 10](https://img.shields.io/badge/Node.js-LTS%208%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 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
@ -60,24 +68,20 @@ Built with SharePoint Framework GA, Office Graph, React and Chart.JS
Solution|Author(s)
--------|---------
react-modern-charts|Jeremy Coleman (MCP, PC Professional, Inc.)
react-modern-charts|Peter Paul Kirschner ([@petkir_at](https://twitter.com/petkir_at))
react-modern-charts|[Jeremy Coleman](https://github.com/jcoleman-pcprofessional) (MCP, PC Professional, Inc.)
react-modern-charts|[Peter Paul Kirschner](https://github.com/petkir) ([@petkir_at](https://twitter.com/petkir_at))
react-modern-charts|[Abderahman Moujahid](https://github.com/Abderahman88)
## Version history
Version|Date|Comments
-------|----|--------
1.0.0.4|October 19, 2021| Fix values of managed metadata fields
1.0.0.3|July 30, 2020| Support for Managed Metadata Field(Single) as Label
1.0.0.2|February 09, 2020| Upgrade to SPFx 1.10.0
1.0.0.1|April 25, 2018|Update to SPFx 1.4.1
1.0.0.0|February 11, 2017|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 with Office Graph content-enabled
@ -99,4 +103,18 @@ Sample Web Parts in this solution illustrate the following concepts on top of th
- passing Web Part properties to React components
- building dynamic web part properties
## 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-modern-charts&authors=@jcoleman-pcprofessional%20@petkir%20@Abderahman88&title=react-modern-charts%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-modern-charts&authors=@jcoleman-pcprofessional%20@petkir%20@Abderahman88&title=react-modern-charts%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-modern-charts&authors=@jcoleman-pcprofessional%20@petkir%20@Abderahman88&title=react-modern-charts%20-%20).
![](https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-modern-charts)

View File

@ -9,7 +9,7 @@
"This web part uses the Chart.js library to visualize SharePoint list data."
],
"creationDateTime": "2020-07-30",
"updateDateTime": "2020-07-30",
"updateDateTime": "2021-10-19",
"products": [
"SharePoint",
"Office"

View File

@ -3,7 +3,7 @@
"solution": {
"name": "modern-charts-client-side-solution",
"id": "f8a78a9a-a93e-4843-89e5-7b871d9b9fa2",
"version": "1.0.0.3",
"version": "1.0.0.4",
"isDomainIsolated": false,
"includeClientSideAssets": true
},

View File

@ -208,8 +208,11 @@ export default class ModernChartsWebPart extends BaseClientSideWebPart<IModernCh
private getUnique(data: Array<Object>, config: ChartConfiguration): Object {
const chLabels: Object = { unique: [], labels: [] };
data.forEach((item) => {
if (chLabels['unique'].indexOf(item[config.unique]) == -1 && item[config.unique] != null && item[config.unique] != "") {
chLabels['unique'].push(item[config.unique]);
var uniqueItem = item[config.unique];
var isTaxonomyField = item[config.unique].hasOwnProperty('TermGuid');
if ((isTaxonomyField ? !chLabels['unique'].some(field => field['TermGuid'] === uniqueItem['TermGuid']) : chLabels['unique'].indexOf(uniqueItem) == -1) && uniqueItem != null && uniqueItem != "") {
chLabels['unique'].push(uniqueItem);
//if term use VAlue
chLabels['labels'].push(this.getLabel(item, config.col1));
}
@ -234,14 +237,13 @@ export default class ModernChartsWebPart extends BaseClientSideWebPart<IModernCh
}
private getValues(data: Array<Object>, unique: Array<string>, config: ChartConfiguration): Array<Array<any>> {
const values: Object = {};
const vals: Array<Array<any>> = [[]];
unique.forEach((col, i) => {
values[col] = [];
vals[i] = [];
data.forEach((item, _i) => {
if (item[config.unique] == col) {
if (item[config.unique].hasOwnProperty('TermGuid') ? item[config.unique]["TermGuid"] == col["TermGuid"] : item[config.unique] == col) {
vals[i].push(item[config.col2]);
}
});

View File

@ -1,72 +1,96 @@
import * as React from 'react';
import styles from './ModernCharts.module.scss';
import { IModernChartsProps } from '../IModernChartsWebPartProps';
import { MChart } from '../IModernChartsWebPartProps';
import 'chart.js';
import { Doughnut } from 'react-chartjs-2';
import { Line } from 'react-chartjs-2';
import { Pie } from 'react-chartjs-2';
import { Bar } from 'react-chartjs-2';
import { HorizontalBar } from 'react-chartjs-2';
import { Radar } from 'react-chartjs-2';
import { Polar } from 'react-chartjs-2';
import ChartOptions from '../ChartOptions';
import * as React from "react";
import styles from "./ModernCharts.module.scss";
import { IModernChartsProps } from "../IModernChartsWebPartProps";
import { MChart } from "../IModernChartsWebPartProps";
import "chart.js";
import { Doughnut } from "react-chartjs-2";
import { Line } from "react-chartjs-2";
import { Pie } from "react-chartjs-2";
import { Bar } from "react-chartjs-2";
import { HorizontalBar } from "react-chartjs-2";
import { Radar } from "react-chartjs-2";
import { Polar } from "react-chartjs-2";
import ChartOptions from "../ChartOptions";
import {
DocumentCard,
DocumentCardTitle,
DocumentCardLocation,
DocumentCardPreview,
IDocumentCardPreviewProps
} from 'office-ui-fabric-react/lib/DocumentCard';
export default class ModernCharts extends React.Component<IModernChartsProps, {}> {
IDocumentCardPreviewProps,
} from "office-ui-fabric-react/lib/DocumentCard";
export default class ModernCharts extends React.Component<
IModernChartsProps,
{}
> {
public render(): JSX.Element {
const charts: JSX.Element[] = this.props.charts.map((chart: MChart, i: number) => {
const charts: JSX.Element[] = this.props.charts.map(
(chart: MChart, i: number) => {
return (
<DocumentCard onClickHref='#' className={styles.docContainer + ' ms-Grid-col ms-u-sm12 ms-u-md12 ms-u-lg' + chart.config.size} key={chart.key}>
<DocumentCard
onClickHref="#"
className={
styles.docContainer +
" ms-Grid-col ms-u-sm12 ms-u-md12 ms-u-lg" +
chart.config.size
}
key={chart.key}
>
<div className={styles.chartCard}>
{this.chart(ChartOptions.Data(chart), ChartOptions.Options(), chart.config.type)}
{this.chart(
ChartOptions.Data(chart),
ChartOptions.Options(),
chart.config.type
)}
</div>
<DocumentCardLocation location={chart.config.description} />
<DocumentCardTitle title={chart.config.title} />
</DocumentCard>
);
});
return (
<div className={styles.chartjs + ' ms-Grid'}>
<div className={'ms-Grid-row'}>
{charts}
</div>
<div style={{ clear: 'both' }} />
</div>
}
);
return (
<div className={styles.chartjs + " ms-Grid"}>
<div className={"ms-Grid-row"}>{charts}</div>
<div style={{ clear: "both" }} />
</div>
);
}
public chart(data: Object, options: Object, type: string) {
var tChart: any;
switch (type) {
case 'doughnut':
case "doughnut":
tChart = <Doughnut data={data} options={options} />;
return tChart;
case 'line':
debugger;
return <Line data={data} options={options} legend={{ display: false }} />;
case 'pie':
case "line":
return (
<Line data={data} options={options} legend={{ display: false }} />
);
case "pie":
tChart = <Pie data={data} options={options} />;
return tChart;
case 'bar':
tChart = <Bar data={data} options={options} legend={{ display: false }} />;
case "bar":
tChart = (
<Bar data={data} options={options} legend={{ display: false }} />
);
return tChart;
case 'horizontalbar':
tChart = <HorizontalBar data={data} options={options} legend={{ display: false }} />;
case "horizontalbar":
tChart = (
<HorizontalBar
data={data}
options={options}
legend={{ display: false }}
/>
);
return tChart;
case 'radar':
tChart = <Radar data={data} options={options} legend={{ display: false }} />;
case "radar":
tChart = (
<Radar data={data} options={options} legend={{ display: false }} />
);
return tChart;
case 'polar':
case "polar":
tChart = <Polar data={data} options={options} />;
return tChart;
default:

View File

@ -1,6 +1,6 @@
{
"name": "react-my-task",
"version": "0.0.1",
"version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -60,6 +60,8 @@ This extension illustrates the following concepts:
We do not support samples, but we do use GitHub to track issues and constantly want to improve these samples.
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/labels/react-organization-chart)
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-organisation-chart&authors=@joaojmendes&title=react-organisation-chart%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-organisation-chart&authors=@joaojmendes&title=react-organisation-chart%20-%20).

View File

@ -1,25 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
# change these settings to your own preference
indent_style = space
indent_size = 2
# we recommend you to keep these unchanged
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[{package,bower}.json]
indent_style = space
indent_size = 2

View File

@ -12,6 +12,7 @@ lib
solution
temp
*.sppkg
release
# Coverage directory used by tools like istanbul
coverage

View File

@ -18,7 +18,7 @@
"environment": "spo",
"framework": "react",
"isCreatingSolution": true,
"version": "1.9.1",
"version": "1.12.1",
"libraryName": "navigator",
"libraryId": "065ee566-e00d-4058-bbfd-356c8d9a8005",
"packageManager": "npm",

View File

@ -8,22 +8,29 @@ When added to a Vertical Section it can be used as a Contents table for the page
![Page Navigator](./assets/PageNavigator.gif)
## Used SharePoint Framework Version
## Compatibility
![version](https://img.shields.io/badge/version-1.9.1-green.svg)
![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 "The solution requires access to the page structure")
![Hosted Workbench Partially](https://img.shields.io/badge/Hosted%20Workbench-Partially-yellow.svg "The solution needs to run on a hosted page to work as intended")
## Version history
Version|Date|Comments
-------|----|--------
1.0|September 5, 2019|Initial release
1.1|October 20, 2021|SPFx Upgraded to 1.12.1 and code refactored
## Minimal Path to Awesome
- git clone the repo
- npm i
- gulp bundle --ship
- gulp package-solution --ship
- `git clone` the repo
- `npm i`
- `gulp bundle --ship`
- `gulp package-solution --ship`
- Add the app package to Site Collection App Catalog and Install the App
- Add the web part to a page in the Site Collection
@ -31,10 +38,20 @@ Version|Date|Comments
Solution|Author(s)
--------|---------
react-page-navigator|Aakash Bhardwaj
react-page-navigator|[Aakash Bhardwaj](https://github.com/aakashbhardwaj619)
## 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-page-navigator&authors=@aakashbhardwaj619&title=react-page-navigator%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-page-navigator&authors=@aakashbhardwaj619&title=react-page-navigator%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-page-navigator&authors=@aakashbhardwaj619&title=react-page-navigator%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-page-navigator" />

View File

@ -9,7 +9,7 @@
"This web part fetches all the automatically added Header anchor tags in a SharePoint page and displays them in a Navigation component."
],
"creationDateTime": "2019-09-05",
"updateDateTime": "2019-09-05",
"updateDateTime": "2021-10-20",
"products": [
"SharePoint",
"Office"
@ -21,7 +21,7 @@
},
{
"key": "SPFX-VERSION",
"value": "1.9.1"
"value": "1.12.1"
}
],
"thumbnails": [

View File

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

View File

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

View File

@ -1,9 +1,16 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"developer": {
"name": "",
"privacyUrl": "",
"termsOfUseUrl": "",
"websiteUrl": "",
"mpnId": ""
},
"name": "react-page-navigator",
"id": "065ee566-e00d-4058-bbfd-356c8d9a8005",
"version": "1.0.0.0",
"version": "1.1.0.0",
"includeClientSideAssets": true,
"isDomainIsolated": false
},

View File

@ -25,5 +25,12 @@ gulp.task('dev', gulpSequence('clean', 'bundle', 'package-solution'));
* Custom Framework Specific gulp tasks
*/
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(gulp);

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,6 @@
"version": "0.0.1",
"private": true,
"main": "lib/index.js",
"engines": {
"node": ">=0.10.0"
},
"scripts": {
"build": "gulp bundle",
"clean": "gulp clean",
@ -15,36 +12,35 @@
"test:watch": "./node_modules/.bin/jest --config ./config/jest.config.json --watchAll"
},
"dependencies": {
"@microsoft/sp-core-library": "1.9.1",
"@microsoft/sp-lodash-subset": "1.9.1",
"@microsoft/sp-office-ui-fabric-core": "1.9.1",
"@microsoft/sp-webpart-base": "1.9.1",
"@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/pnpjs": "^1.3.5",
"@pnp/spfx-controls-react": "1.14.0",
"@pnp/spfx-property-controls": "1.16.0",
"@types/es6-promise": "0.0.33",
"@types/react": "16.8.8",
"@types/react-dom": "16.8.3",
"@types/webpack-env": "1.13.1",
"office-ui-fabric-react": "^6.182.0",
"react": "16.8.5",
"react-dom": "16.8.5"
"office-ui-fabric-react": "7.156.0",
"react": "16.9.0",
"react-dom": "16.9.0"
},
"resolutions": {
"@types/react": "16.8.8"
},
"devDependencies": {
"@microsoft/rush-stack-compiler-3.3": "0.1.7",
"@microsoft/sp-build-web": "1.9.1",
"@microsoft/sp-module-interfaces": "1.9.1",
"@microsoft/sp-tslint-rules": "1.9.1",
"@microsoft/sp-webpart-workbench": "1.9.1",
"@types/chai": "3.4.34",
"@types/mocha": "2.2.38",
"@types/react": "^16.7.22",
"@microsoft/rush-stack-compiler-3.7": "0.2.3",
"@microsoft/sp-build-web": "1.12.1",
"@microsoft/sp-module-interfaces": "1.12.1",
"@microsoft/sp-tslint-rules": "1.12.1",
"@microsoft/sp-webpart-workbench": "1.12.1",
"@types/es6-promise": "0.0.33",
"@types/react": "16.9.36",
"@types/react-dom": "16.9.8",
"@types/webpack-env": "1.13.1",
"@voitanos/jest-preset-spfx-react16": "^1.1.0",
"ajv": "~5.2.2",
"gulp": "~3.9.1",
"gulp": "4.0.2",
"gulp-sequence": "1.0.0",
"jest": "^23.6.0"
}

View File

@ -3,18 +3,49 @@ import { WebPartContext } from '@microsoft/sp-webpart-base';
import { SPHttpClient } from '@microsoft/sp-http';
export class SPService {
/* Array to store all unique anchor URLs */
private static allUrls: string[] = [];
/**
* Returns the unique Anchor URL for a heading
* @param headingValue The text value of the heading
* @returns anchorUrl
*/
private static GetAnchorUrl(headingValue: string): string {
let urlExists = true;
// .replace(/'|?|\|/| |&/g, "-") replaces any blanks and special characters (list is for sure not complete) with "-"
// .replace(/--+/g, "-") replaces any additional - with only one -; e.g. --- get replaced with -, -- get replaced with - etc.
let anchorUrl = `#${headingValue
.replace(/\'|\?|\\|\/| |\&/g, "-")
.replace(/--+/g, "-")}`.toLowerCase();
let urlSuffix = 1;
while (urlExists === true) {
urlExists = (this.allUrls.indexOf(anchorUrl) === -1) ? false : true;
if (urlExists) {
anchorUrl = anchorUrl + `-${urlSuffix}`;
urlSuffix++;
}
}
return anchorUrl;
}
/**
* Returns the Anchor Links for Nav element
* @param context Web part context
* @returns anchorLinks
*/
public static async GetAnchorLinks(context: WebPartContext) {
let anchorLinks: INavLink[] = [];
const anchorLinks: INavLink[] = [];
try {
/* Page ID on which the web part is added */
let pageId = context.pageContext.listItem.id;
const pageId = context.pageContext.listItem.id;
/* Get the canvasContent1 data for the page which consists of all the HTML */
let data = await context.spHttpClient.get(`${context.pageContext.web.absoluteUrl}/_api/sitepages/pages(${pageId})`, SPHttpClient.configurations.v1);
let jsonData = await data.json();
let canvasContent1 = jsonData.CanvasContent1;
let canvasContent1JSON: any[] = JSON.parse(canvasContent1);
const data = await context.spHttpClient.get(`${context.pageContext.web.absoluteUrl}/_api/sitepages/pages(${pageId})`, SPHttpClient.configurations.v1);
const jsonData = await data.json();
const canvasContent1 = jsonData.CanvasContent1;
const canvasContent1JSON: any[] = JSON.parse(canvasContent1);
/* Initialize variables to be used for sorting and adding the Navigation links */
let headingIndex = 0;
@ -22,9 +53,6 @@ export class SPService {
let headingOrder = 0;
let prevHeadingOrder = 0;
/* Array to store all unique anchor URLs */
let allUrls: string[] = [];
/* Traverse through all the Text web parts in the page */
canvasContent1JSON.map((webPart) => {
if (webPart.innerHTML) {
@ -34,28 +62,14 @@ export class SPService {
/* The Header Text value */
// .replace(/<.+?>/gi, "") replaces in the headingValue any html tags like <strong> </strong>
// .replace(/&.+;/gi, "") replaces in the headingValue any &****; tags like &nbsp;
let headingValue = HTMLString.substring(HTMLString.search(/<h[1-4]>/g) + 4, HTMLString.search(/<\/h[1-4]>/g))
const headingValue = HTMLString.substring(HTMLString.search(/<h[1-4]>/g) + 4, HTMLString.search(/<\/h[1-4]>/g))
.replace(/<.+?>/gi, "")
.replace(/\&.+\;/gi, "");
headingOrder = parseInt(HTMLString.charAt(HTMLString.search(/<h[1-4]>/g) + 2));
/* Check if same anchorUrl already exists */
let urlExists = true;
// .replace(/'|?|\|/| |&/g, "-") replaces any blanks and special characters (list is for sure not complete) with "-"
// .replace(/--+/g, "-") replaces any additional - with only one -; e.g. --- get replaced with -, -- get replaced with - etc.
let anchorUrl = `#${headingValue
.replace(/\'|\?|\\|\/| |\&/g, "-")
.replace(/--+/g, "-")}`.toLowerCase();
let urlSuffix = 1;
while (urlExists === true) {
urlExists = (allUrls.indexOf(anchorUrl) === -1) ? false : true;
if (urlExists) {
anchorUrl = anchorUrl + `-${urlSuffix}`;
urlSuffix++;
}
}
allUrls.push(anchorUrl);
const anchorUrl = this.GetAnchorUrl(headingValue);
this.allUrls.push(anchorUrl);
/* Add links to Nav element */
if (anchorLinks.length === 0) {
@ -63,33 +77,42 @@ export class SPService {
} else {
if (headingOrder <= prevHeadingOrder) {
/* Adding or Promoting links */
if (headingOrder === 2) {
switch (headingOrder) {
case 2:
anchorLinks.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
headingIndex++;
subHeadingIndex = -1;
} else {
if (headingOrder === 4) {
break;
case 4:
if (subHeadingIndex > -1) {
anchorLinks[headingIndex].links[subHeadingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
} else if (headingOrder === 3) {
} else {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
subHeadingIndex++;
}
break;
default:
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
subHeadingIndex = anchorLinks[headingIndex].links.length - 1;
break;
}
} else {
/* Making sub links */
if (headingOrder === 3) {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
subHeadingIndex++;
subHeadingIndex = anchorLinks[headingIndex].links.length - 1;
} else {
if (subHeadingIndex > -1) {
anchorLinks[headingIndex].links[subHeadingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
} else {
anchorLinks[headingIndex].links.push({ name: headingValue, key: anchorUrl, url: anchorUrl, links: [], isExpanded: true });
}
}
}
}
prevHeadingOrder = headingOrder;
/* Replace the added header links from the string so they don't get processed again */
HTMLString = HTMLString.replace(`<h${headingOrder}>`, '');
HTMLString = HTMLString.replace(`</h${headingOrder}>`, '');
HTMLString = HTMLString.replace(`<h${headingOrder}>`, '').replace(`</h${headingOrder}>`, '');
}
}
});
@ -97,7 +120,7 @@ export class SPService {
console.log(error);
}
console.log(anchorLinks);
console.log('anchorLinks', anchorLinks);
return anchorLinks;
}
}

View File

@ -1,12 +1,8 @@
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { Version } from '@microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneConfiguration,
PropertyPaneTextField
} from '@microsoft/sp-webpart-base';
import { BaseClientSideWebPart } from "@microsoft/sp-webpart-base";
import { IPropertyPaneConfiguration, PropertyPaneTextField } from "@microsoft/sp-property-pane";
import * as strings from 'PageNavigatorWebPartStrings';
import PageNavigator from './components/PageNavigator';
import { IPageNavigatorProps } from './components/IPageNavigatorProps';

View File

@ -1,5 +1,5 @@
{
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.7/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
@ -19,20 +19,18 @@
"./node_modules/@microsoft"
],
"types": [
"es6-promise",
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection"
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts"
"src/**/*.ts",
"src/**/*.tsx"
],
"exclude": [
"node_modules",
"lib"
]
"exclude": []
}

View File

@ -1,5 +1,5 @@
{
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
"extends": "./node_modules/@microsoft/sp-tslint-rules/base-tslint.json",
"rules": {
"class-name": false,
"export-name": false,

View File

@ -16,7 +16,8 @@ This SPFx Outlook Add-In lets users save any email attachments to a OneDrive fol
![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-yellow.svg "Designed to work in Outlook, but will display sample attachments while in workbench")
![Hosted Workbench Partially](https://img.shields.io/badge/Hosted%20Workbench-Partially-yellow.svg "Designed to work in Outlook, but will display sample attachments while in workbench")
![Outlook Compatible](https://img.shields.io/badge/Outlook-Compatible-green.svg)
## Features

View File

@ -165,7 +165,7 @@ In order to make it available to absolutely all sites you need apply the _Deploy
Solution|Author(s)
--------|---------
react-script-editor | Mikael Svenson ([@mikaelsvenson](http://www.twitter.com/mikaelsvenson), [techmikael.com](techmikael.com))
react-script-editor | [Mikael Svenson](https://github.com/wobba) ([@mikaelsvenson](http://www.twitter.com/mikaelsvenson), [techmikael.com](techmikael.com))
## Version history
@ -190,11 +190,6 @@ Version|Date|Comments
1.0.0.16|April 1st, 2020|Improved how script tags are handled and cleaned up on smart page navigation.
1.0.17.0|January 29th, 2021|Changed versioning to 3 parts. Updated npm packages, restructured documentation, minor change to webpack analyzer setup.
## 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
### Local testing
@ -204,10 +199,10 @@ Version|Date|Comments
- `gulp serve`
### Deploy
* gulp clean
* gulp bundle --ship
* gulp package-solution --ship
* Upload .sppkg file from sharepoint\solution to your tenant App Catalog
* `gulp clean`
* `gulp bundle --ship`
* `gulp package-solution --ship`
* Upload `.sppkg` file from `sharepoint\solution` to your tenant App Catalog
* E.g.: https://&lt;tenant&gt;.sharepoint.com/sites/AppCatalog/AppCatalog
* Add the web part to a site collection, and test it on a page
## Features
@ -217,4 +212,24 @@ This web part illustrates the following concepts on top of the SharePoint Framew
- Office UI Fabric
- React
## 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.
You can try looking at [issues related to this sample](https://github.com/pnp/sp-dev-fx-webparts/labels/react-script-editor) to see if anybody else is having the same issues.
You can also try looking at [discussions related to this sample](https://github.com/pnp/sp-dev-fx-webparts/discussions?discussions_q=label%3Areact-script-editor) and see what the community is saying.
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-script-editor&authors=@wobba&title=react-script-editor%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-script-editor&authors=@wobba&title=react-script-editor%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-script-editor&authors=@wobba&title=react-script-editor%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-script-editor" />

View File

@ -13,9 +13,11 @@ This is a rebuild of the awesome project created by @hugoabernier [https://githu
![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)
![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 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
@ -37,14 +39,15 @@ react-tiles-v2 | [Omar El-Anis](https://github.com/omarelanis) @ SP Bytes www.sp
Version|Date|Comments
-------|----|--------
1.0|July 14, 2021|Initial release
1.1|October 14, 2021|Added sorting, static tile width and unique tile colour - [fthorild](https://github.com/fthorild)
## Minimal Path to Awesome
- Clone this repository
- Ensure that you are at the solution folder
- in the command-line run:
- **npm install**
- **gulp serve**
- `npm install`
- `gulp serve`
## Features
@ -75,10 +78,10 @@ This extension illustrates the following concepts:
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-tiles-v2&authors=@omarelanis&title=react-tiles-v2%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-tiles-v2&authors=fthorild%20@fthorild&title=react-tiles-v2%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-tiles-v2&authors=@omarelanis&title=react-tiles-v2%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-tiles-v2&authors=fthorild%20@fthorild&title=react-tiles-v2%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-tiles-v2&authors=@omarelanis&title=react-tiles-v2%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-tiles-v2&authors=fthorild%20@fthorild&title=react-tiles-v2%20-%20).
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-tiles-v2" />

View File

@ -9,7 +9,7 @@
"This solution creates a customisable Tiles Web part, it uses a stored collection from the PnP `PropertyFieldCollectionData` control and allows the user to choose the colour scheme (theme or custom) and to set the size of the tiles. By default the tiles use a fluid flex layout to use the available screen area."
],
"creationDateTime": "2021-07-14",
"updateDateTime": "2021-07-14",
"updateDateTime": "2021-10-14",
"products": [
"SharePoint",
"Office"
@ -22,6 +22,10 @@
{
"key": "SPFX-VERSION",
"value": "1.11"
},
{
"key": "PNPCONTROLS",
"value": "IconPicker, WebPartTitle, Placeholder, PropertyFieldCollectionData"
}
],
"thumbnails": [
@ -37,6 +41,12 @@
"gitHubAccount": "omarelanis",
"pictureUrl": "https://github.com/omarelanis.png",
"name": "Omar El-Anis"
},
{
"gitHubAccount": "fthorild",
"name": "Fredrik Thorild",
"company": "Sogeti Sweden",
"pictureUrl": "https://github.com/fthorild.png"
}
],
"references": [

View File

@ -3,7 +3,7 @@
"solution": {
"name": "Tiles V2 Webpart - Modern",
"id": "d56958d6-9eaf-4500-934b-b421c22a7d1f",
"version": "1.0.0.0",
"version": "1.1.0.0",
"skipFeatureDeployment": true,
"includeClientSideAssets": true,
"isDomainIsolated": false,

View File

@ -1,6 +1,6 @@
{
"name": "tiles",
"version": "0.0.1",
"version": "1.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "tiles",
"version": "0.0.1",
"version": "1.1.0",
"private": true,
"main": "lib/index.js",
"engines": {

View File

@ -4,20 +4,23 @@ import * as strings from 'TilesWebPartStrings';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme } from '@microsoft/sp-component-base';
import { IPropertyPaneConfiguration } from "@microsoft/sp-property-pane";
import { PropertyPaneToggle,PropertyPaneSlider } from '@microsoft/sp-property-pane';
import { PropertyPaneToggle, PropertyPaneSlider, PropertyPaneDropdown } from '@microsoft/sp-property-pane';
import { Tiles, ITilesProps, ITileInfo, LinkTarget } from './components';
import { IconPicker } from '@pnp/spfx-controls-react/lib/IconPicker';
import { initializeIcons } from 'office-ui-fabric-react/lib';
import { ColorPicker, initializeIcons } from 'office-ui-fabric-react/lib';
import { SimpleColorPicker } from './components/colorpicker/SimpleColorPicker';
const ThemeColorsFromWindow: any = (window as any).__themeState__.theme;
export interface ITilesWebPartProps {
collectionData: ITileInfo[];
tileHeight: number;
tileWidth: number;
tileColour: string;
tileFont: string;
title: string;
customColour: boolean;
staticWidth: boolean;
colourMode: string;
themeVariant: IReadonlyTheme | undefined;
ThemeColorsFromWindow: IReadonlyTheme | undefined;
}
@ -64,13 +67,15 @@ export default class TilesWebPart extends BaseClientSideWebPart<ITilesWebPartPro
{
title: this.properties.title,
tileHeight: this.properties.tileHeight,
tileWidth: this.properties.tileWidth,
tileColour: this.properties.tileColour,
tileFont: this.properties.tileFont,
customColour: this.properties.customColour,
staticWidth: this.properties.staticWidth,
collectionData: this.properties.collectionData,
displayMode: this.displayMode,
themeVariant: this._themeVariant,
ThemeColorsFromWindow: ThemeColorsFromWindow,
colourMode: this.properties.colourMode,
fUpdateProperty: (value: string) => {
this.properties.title = value;
},
@ -107,7 +112,9 @@ export default class TilesWebPart extends BaseClientSideWebPart<ITilesWebPartPro
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
let tileColourplaceholder: any = [];
let tileFontplaceholder: any = [];
if (this.properties.customColour) {
let tileStaticWidthplaceholder: any = [];
if (this.properties.colourMode === '2') {
tileColourplaceholder = this.propertyFieldColorPicker('tileColour', {
key: "tileColour",
label: strings.tileColour,
@ -132,7 +139,20 @@ export default class TilesWebPart extends BaseClientSideWebPart<ITilesWebPartPro
style: this.propertyFieldColorPickerStyle.Full,
iconName: 'Precipitation'
});
}
if (this.properties.staticWidth) {
tileStaticWidthplaceholder = PropertyPaneSlider('tileWidth', {
label: strings.widthStaticSet,
max: 1000,
min: 10,
step: 1,
showValue: true,
value: this.properties.tileHeight
});
}
return {
pages: [
{
@ -169,15 +189,53 @@ export default class TilesWebPart extends BaseClientSideWebPart<ITilesWebPartPro
type: this.customCollectionFieldType.string,
required: true
},
{
id: "sortOrder",
title: strings.sortOrder,
type: this.customCollectionFieldType.number,
required: true
},
{
id: "background",
title: strings.colorSetUniqueBg,
type: this.customCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => {
return (
React.createElement(SimpleColorPicker, {
key: itemId,
onChange: (colour: string) => {
onUpdate(field.id, colour);
return Event;
}
})
);
}
},
{
id: "foreground",
title: strings.colorSetUniqueFg,
type: this.customCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => {
return (
React.createElement(SimpleColorPicker, {
key: itemId,
onChange: (colour: string) => {
onUpdate(field.id, colour);
return Event;
}
})
);
}
},
{
id: "icon",
title: "Select Icon",
title: strings.iconField,
type: this.customCollectionFieldType.custom,
onCustomRender: (field, value, onUpdate, item, itemId, onError) => {
return (
React.createElement(IconPicker, {
key: itemId,
buttonLabel:"Select File",
buttonLabel: strings.iconSelectFile,
onChange: (iconName: string) => {
onUpdate(field.id, iconName);
return Event;
@ -207,24 +265,35 @@ export default class TilesWebPart extends BaseClientSideWebPart<ITilesWebPartPro
}
]
})
]},
]
},
{
groupName: "Tile Settings",
groupFields: [
PropertyPaneSlider('tileHeight', {
label: 'Tile Height',
label: strings.tilesHeight,
max: 300,
min: 120,
step: 1,
showValue: true,
value: this.properties.tileHeight
}),
PropertyPaneToggle('customColour', {
key: 'customColourID',
label: 'Theme or Custom colours',
onText: 'Custom Colours',
offText: 'Theme Colours',
checked: this.properties.customColour
PropertyPaneToggle('staticWidth', {
key: 'staticWidthID',
label: strings.widthAutomaticOrStatic,
onText: strings.widthStatic,
offText: strings.widthAutomatic,
checked: this.properties.staticWidth
}),
tileStaticWidthplaceholder,
PropertyPaneDropdown('colourMode', {
label: strings.colourMode,
options: [
{ key: '1', text: strings.colourModeTheme },
{ key: '2', text: strings.colourModeUniform },
{ key: '3', text: strings.colourModeUnique }
],
selectedKey: '1',
}),
tileColourplaceholder,
tileFontplaceholder

View File

@ -4,6 +4,9 @@ export interface ITileInfo {
url: string;
icon: string;
target: LinkTarget;
sortOrder: string;
foreground: string;
background: string;
}
export enum LinkTarget {

View File

@ -1,7 +1,7 @@
import * as React from 'react';
import * as strings from 'TilesWebPartStrings';
import styles from './Tiles.module.scss';
import { ITilesProps } from '.';
import { ITileInfo, ITilesProps } from '.';
import { Tile } from './tile';
import { WebPartTitle } from '@pnp/spfx-controls-react/lib/WebPartTitle';
import { Placeholder } from '@pnp/spfx-controls-react/lib/Placeholder';
@ -15,23 +15,32 @@ export class Tiles extends React.Component<ITilesProps, {}> {
*/
public render(): React.ReactElement<ITilesProps> {
const CustomStyles = createstyles(this.props.themeVariant);
return (
<div className={css(styles.tiles, CustomStyles.root)}>
<div className={css(styles.tiles, CustomStyles.root)
}>
<WebPartTitle displayMode={this.props.displayMode}
title={this.props.title}
updateProperty={this.props.fUpdateProperty} />
{
this.props.collectionData && this.props.collectionData.length > 0 ? (
<div className={styles.tilesList}>
{
this.props.collectionData.map((tile, idx) =>
this.props.collectionData
.sort((a: ITileInfo, b: ITileInfo) =>
parseInt(a.sortOrder) > parseInt(b.sortOrder) ?
1 : ((parseInt(b.sortOrder) > parseInt(a.sortOrder) ? -1 : 0)))
.map((tile, idx) =>
<Tile key={idx}
item={tile}
tileHeight={this.props.tileHeight}
tileWidth={this.props.tileWidth}
tileColour={this.props.tileColour}
tileFont={this.props.tileFont}
customColour={this.props.customColour}
staticWidth={this.props.staticWidth}
colourMode={this.props.colourMode}
themeVariant={this.props.themeVariant}
ThemeColorsFromWindow={this.props.ThemeColorsFromWindow} />)
}

View File

@ -0,0 +1,3 @@
export interface ISimpleColorPickerProps {
onChange(iconName: any): void;
}

View File

@ -0,0 +1,3 @@
export interface ISimpleColorPickerState {
val: string;
}

View File

@ -0,0 +1,28 @@
import * as React from 'react';
import { ISimpleColorPickerProps } from './ISimpleColorPickerProps';
import { ISimpleColorPickerState } from './ISimpleColorPickerState';
export class SimpleColorPicker extends React.Component<ISimpleColorPickerProps, ISimpleColorPickerState> {
constructor(props) {
super(props);
this.state = { val: '#efefef' };
}
private handleChange = event => {
const value = event.target.value;
(async () => {
await this.setState({ val: value });
this.props.onChange(this.state.val);
})();
}
public render(): React.ReactElement<ISimpleColorPickerProps> {
return (
<div>
<input
onChange={this.handleChange}
type='color'
value={this.state.val}
/>
</div>
);
}
}

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