Merge branch 'main' into React-List-Items-Menu-SPfx-Upgrade
This commit is contained in:
commit
5e32931fc9
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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": "",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "modern-calendar",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.3",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -8,10 +8,8 @@
|
|||
|
||||
.carouselItem {
|
||||
background-color: $ms-color-themeDark;
|
||||
// display: flex;
|
||||
min-height: 150px;
|
||||
height: 98%;
|
||||
// justify-content: center;
|
||||
}
|
||||
|
||||
.carouselDotList {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-graph-app-secret-expiration",
|
||||
"version": "0.0.1",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -10,6 +10,7 @@ node_modules
|
|||
dist
|
||||
lib
|
||||
solution
|
||||
release
|
||||
temp
|
||||
*.sppkg
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
1
samples/react-groups-teams/release/assets/microsoft-groups-web-part_da003a7fb7fd1f14fcb7.js
vendored
Normal file
1
samples/react-groups-teams/release/assets/microsoft-groups-web-part_da003a7fb7fd1f14fcb7.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -11,6 +11,7 @@ dist
|
|||
lib
|
||||
solution
|
||||
temp
|
||||
release
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
!dist
|
||||
config
|
||||
|
||||
gulpfile.js
|
||||
|
||||
release
|
||||
src
|
||||
temp
|
||||
|
||||
tsconfig.json
|
||||
tslint.json
|
||||
|
||||
*.log
|
||||
|
||||
.yo-rc.json
|
||||
.vscode
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -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 -->"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -67,10 +67,8 @@ export default class KanbanTaskManagedProp extends React.Component<IKanbanTaskMa
|
|||
size={PersonaSize.size32}
|
||||
hidePersonaDetails={false}
|
||||
/>))
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
};
|
||||
</span>);
|
||||
break;
|
||||
case KanbanTaskMamagedPropertyType.complex:
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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;
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -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": []
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -12,6 +12,7 @@ lib
|
|||
release
|
||||
solution
|
||||
temp
|
||||
release
|
||||
*.sppkg
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -34,6 +34,14 @@
|
|||
{
|
||||
"key": "SPFX-TEAMSPERSONALAPP",
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"key": "PNPCONTROLS",
|
||||
"value": "PropertyFieldListPicker, PropertyFieldMessage, PropertyFieldSpinner"
|
||||
},
|
||||
{
|
||||
"key": "REACT-HOOKS",
|
||||
"value": "true"
|
||||
}
|
||||
],
|
||||
"thumbnails": [
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-my-task",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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
|
|
@ -12,6 +12,7 @@ lib
|
|||
solution
|
||||
temp
|
||||
*.sppkg
|
||||
release
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
"deployCdnPath": "./release/assets/"
|
||||
}
|
||||
|
|
|
@ -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 -->"
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
|
@ -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
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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": []
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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://<tenant>.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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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": [
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tiles",
|
||||
"version": "0.0.1",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "tiles",
|
||||
"version": "0.0.1",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,6 +4,9 @@ export interface ITileInfo {
|
|||
url: string;
|
||||
icon: string;
|
||||
target: LinkTarget;
|
||||
sortOrder: string;
|
||||
foreground: string;
|
||||
background: string;
|
||||
}
|
||||
|
||||
export enum LinkTarget {
|
||||
|
|
|
@ -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} />)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export interface ISimpleColorPickerProps {
|
||||
onChange(iconName: any): void;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export interface ISimpleColorPickerState {
|
||||
val: string;
|
||||
}
|
|
@ -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
Loading…
Reference in New Issue