Added PnP JS Tester Webpart
Added new sample PnP JS Tester Webpart which allows to test PnP JS SharePoint method. Co-Authored-By: Kunj Balkrishna Sangani <sangani.kunj@gmail.com>
This commit is contained in:
parent
ece43214ca
commit
0d9630f8a0
|
@ -0,0 +1,24 @@
|
||||||
|
# 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
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
# Build generated files
|
||||||
|
dist
|
||||||
|
lib
|
||||||
|
solution
|
||||||
|
temp
|
||||||
|
*.sppkg
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# OSX
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Visual Studio files
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
.vs
|
||||||
|
bin
|
||||||
|
obj
|
||||||
|
|
||||||
|
# Resx Generated Code
|
||||||
|
*.resx.ts
|
||||||
|
|
||||||
|
# Styles Generated Code
|
||||||
|
*.scss.ts
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"@microsoft/generator-sharepoint": {
|
||||||
|
"isCreatingSolution": false,
|
||||||
|
"environment": "spo",
|
||||||
|
"version": "1.10.0",
|
||||||
|
"libraryName": "react-pnpjsexplorer",
|
||||||
|
"libraryId": "a41b7fa8-313e-40d1-ae85-1d85baddecf5",
|
||||||
|
"packageManager": "npm",
|
||||||
|
"isDomainIsolated": false,
|
||||||
|
"componentType": "webpart"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
## SPFx webpart to Test PnpJS SharePoint Methods
|
||||||
|
|
||||||
|
This webpart will allow SPFx developers to test PnPjs methods and it displays response in JSON viewer to identify properties/attributes returned by method/api. This webpart can be used as seperate component to test PnP Js methods and know the response returned by a particular method/api. To maximise productivity, we should package and deploy it to a test(developer) site collection which then can be used side by side when we are doing development of SPFx solutions.
|
||||||
|
|
||||||
|
Note - As of now it only supports to test Pnp JS method from sp(SharePoint) packages which contains the fluent api used to call the SharePoint rest services.
|
||||||
|
|
||||||
|
You can refer to this blog [link](https://siddharthvaghasia.com/2020/08/16/usage-guide-on-spfx-pnpjs-tester-web-part/) for usage guidance on How to use this webpart.
|
||||||
|
|
||||||
|
|
||||||
|
WebPart in Action
|
||||||
|
|
||||||
|
![Webpart in action](assets/pnpjstesterinaction.gif?raw=true "Webpart in action")
|
||||||
|
|
||||||
|
Idea behind this webpart
|
||||||
|
* Most of the SharePoint developers are using PnP JS to develop SPFx solutions.
|
||||||
|
* During the development, there are times when we wanted to know what properties/attributes will be returned in response
|
||||||
|
* To get these details, we either use console.log to log response or debug the javascript and check what properties/attributes are returned etc.
|
||||||
|
* This webpart can be used so that we can quickly test any SharePoint rest api methods using PnP JS.
|
||||||
|
|
||||||
|
Feel free to connect on twitter:@siddh_me or twitter:@sanganikunj for any details.
|
||||||
|
|
||||||
|
### Notes on Webpart
|
||||||
|
|
||||||
|
* WebPart to test PnP JS SharePoint package methods
|
||||||
|
* Response will be displayed in a code format.
|
||||||
|
* By default, it will run in context of current site collection.
|
||||||
|
* Optional option to enter diffrent site collection or sub site url to set PnP JS context to diffrent url(other than current context)
|
||||||
|
* Support for Get and Post methods.
|
||||||
|
* Option to see some examples which can be copied and tested just by changing list/libraries/column names.
|
||||||
|
|
||||||
|
## Used SharePoint Framework Version
|
||||||
|
|
||||||
|
![drop](https://img.shields.io/badge/version-1.10.0-green.svg)
|
||||||
|
|
||||||
|
## Applies to
|
||||||
|
|
||||||
|
* [SharePoint Framework](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||||
|
* [Office 365 tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||||
|
|
||||||
|
### Package and Deploy
|
||||||
|
|
||||||
|
Note - If you don't want to build and package on your own, you can directly download package at this [location](./sharepoint/solution/react-pnpjsexplorer.sppkg) and upload to app catalog and install app on required site collection. Skip below steps and directly go to How to use section.
|
||||||
|
Clone the solution and make sure there is no error before packaging. Try first on local work bench.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone the repo
|
||||||
|
npm i
|
||||||
|
gulp serve
|
||||||
|
```
|
||||||
|
- Execute the following gulp task to bundle your solution. This executes a release build of your project by using a dynamic label as the host URL for your assets. This URL is automatically updated based on your tenant CDN settings:
|
||||||
|
```bash
|
||||||
|
gulp bundle --ship
|
||||||
|
```
|
||||||
|
- Execute the following task to package your solution. This creates an updated webpart.sppkg package on the sharepoint/solution folder.
|
||||||
|
```bash
|
||||||
|
gulp package-solution --ship
|
||||||
|
```
|
||||||
|
- Upload or drag and drop the newly created client-side solution package to the app catalog in your tenant.
|
||||||
|
- Based on your tenant settings, if you would not have CDN enabled in your tenant, and the includeClientSideAssets setting would be true in the package-solution.json, the loading URL for the assets would be dynamically updated and pointing directly to the ClientSideAssets folder located in the app catalog site collection.
|
||||||
|
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Solution|Author(s)
|
||||||
|
--------|---------
|
||||||
|
react-PnPjsTester | [Siddharth Vaghasia](https://www.linkedin.com/in/siddharthvaghasia/) and [Kunj Sangani](https://www.linkedin.com/in/kunj-sangani/)
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
Version|Date|Comments
|
||||||
|
-------|----|--------
|
||||||
|
1.0.0|Aug 14, 2020|Initial Release
|
||||||
|
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||||
|
|
||||||
|
For any issue or help, Buzz us on twitter:([siddh_me](https://twitter.com/siddh_me/)) or ([sanganikunj](https://twitter.com/sanganikunj))
|
||||||
|
|
||||||
|
> Sharing is caring!
|
||||||
|
|
||||||
|
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-pnpjsexplorer" />
|
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/config.2.0.schema.json",
|
||||||
|
"version": "2.0",
|
||||||
|
"bundles": {
|
||||||
|
"react-pn-pjs-tester-web-part": {
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"entrypoint": "./lib/webparts/reactPnPjsTester/ReactPnPjsTesterWebPart.js",
|
||||||
|
"manifest": "./src/webparts/reactPnPjsTester/ReactPnPjsTesterWebPart.manifest.json"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"externals": {},
|
||||||
|
"localizedResources": {
|
||||||
|
"ReactPnPjsTesterWebPartStrings": "lib/webparts/reactPnPjsTester/loc/{locale}.js"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||||
|
"deployCdnPath": "temp/deploy"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||||
|
"workingDir": "./temp/deploy/",
|
||||||
|
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||||
|
"container": "react-pnpjsexplorer",
|
||||||
|
"accessKey": "<!-- ACCESS KEY -->"
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
|
||||||
|
"solution": {
|
||||||
|
"name": "react-pnpjsexplorer-client-side-solution",
|
||||||
|
"id": "a41b7fa8-313e-40d1-ae85-1d85baddecf5",
|
||||||
|
"version": "2.0.0.0",
|
||||||
|
"includeClientSideAssets": true,
|
||||||
|
"isDomainIsolated": false
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"zippedPackage": "solution/react-pnpjsexplorer.sppkg"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"$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/"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||||
|
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const build = require('@microsoft/sp-build-web');
|
||||||
|
|
||||||
|
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||||
|
|
||||||
|
build.initialize(require('gulp'));
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"name": "react-pnpjsexplorer",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"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/sp": "^2.0.5",
|
||||||
|
"@types/es6-promise": "0.0.33",
|
||||||
|
"@types/react": "16.8.8",
|
||||||
|
"@types/react-dom": "16.8.3",
|
||||||
|
"@types/webpack-env": "1.13.1",
|
||||||
|
"ace-builds": "^1.4.11",
|
||||||
|
"office-ui-fabric-react": "6.189.2",
|
||||||
|
"react": "16.8.5",
|
||||||
|
"react-ace": "^9.1.1",
|
||||||
|
"react-dom": "16.8.5",
|
||||||
|
"react-json-view": "^1.19.1"
|
||||||
|
},
|
||||||
|
"resolutions": {
|
||||||
|
"@types/react": "16.8.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@microsoft/sp-build-web": "1.10.0",
|
||||||
|
"@microsoft/sp-tslint-rules": "1.10.0",
|
||||||
|
"@microsoft/sp-module-interfaces": "1.10.0",
|
||||||
|
"@microsoft/sp-webpart-workbench": "1.10.0",
|
||||||
|
"@microsoft/rush-stack-compiler-3.3": "0.3.5",
|
||||||
|
"gulp": "~3.9.1",
|
||||||
|
"@types/chai": "3.4.34",
|
||||||
|
"@types/mocha": "2.2.38",
|
||||||
|
"ajv": "~5.2.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||||
|
"id": "9dbf4d65-e0cc-4462-801a-2b96ea28de5a",
|
||||||
|
"alias": "ReactPnPjsTesterWebPart",
|
||||||
|
"componentType": "WebPart",
|
||||||
|
|
||||||
|
// The "*" signifies that the version should be taken from the package.json
|
||||||
|
"version": "*",
|
||||||
|
"manifestVersion": 2,
|
||||||
|
|
||||||
|
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||||
|
// Components that allow authors to embed arbitrary script code should set this to true.
|
||||||
|
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
|
||||||
|
"requiresCustomScript": false,
|
||||||
|
"supportedHosts": ["SharePointWebPart"],
|
||||||
|
|
||||||
|
"preconfiguredEntries": [{
|
||||||
|
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||||
|
"group": { "default": "Other" },
|
||||||
|
"title": { "default": "react-PnPjsTester" },
|
||||||
|
"description": { "default": "This webpart will help in executing multiple rest api using PnPjs this would be helpful for developers" },
|
||||||
|
"officeFabricIconFontName": "Page",
|
||||||
|
"properties": {
|
||||||
|
"description": "react-PnPjsTester"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDom from 'react-dom';
|
||||||
|
import { Version } from '@microsoft/sp-core-library';
|
||||||
|
import {
|
||||||
|
IPropertyPaneConfiguration,
|
||||||
|
PropertyPaneTextField
|
||||||
|
} from '@microsoft/sp-property-pane';
|
||||||
|
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
|
||||||
|
|
||||||
|
import * as strings from 'ReactPnPjsTesterWebPartStrings';
|
||||||
|
import ReactPnPjsTester from './components/ReactPnPjsTester';
|
||||||
|
import { IReactPnPjsTesterProps } from './components/IReactPnPjsTesterProps';
|
||||||
|
|
||||||
|
export interface IReactPnPjsTesterWebPartProps {
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class ReactPnPjsTesterWebPart extends BaseClientSideWebPart <IReactPnPjsTesterWebPartProps> {
|
||||||
|
|
||||||
|
public render(): void {
|
||||||
|
const element: React.ReactElement<IReactPnPjsTesterProps> = React.createElement(
|
||||||
|
ReactPnPjsTester,
|
||||||
|
{
|
||||||
|
description: this.properties.description,
|
||||||
|
spcontext:this.context
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ReactDom.render(element, this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected onDispose(): void {
|
||||||
|
ReactDom.unmountComponentAtNode(this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected get dataVersion(): Version {
|
||||||
|
return Version.parse('1.0');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
|
return {
|
||||||
|
pages: [
|
||||||
|
{
|
||||||
|
header: {
|
||||||
|
description: strings.PropertyPaneDescription
|
||||||
|
},
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
groupName: strings.BasicGroupName,
|
||||||
|
groupFields: [
|
||||||
|
PropertyPaneTextField('description', {
|
||||||
|
label: strings.DescriptionFieldLabel
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||||
|
|
||||||
|
export interface IReactPnPjsTesterProps {
|
||||||
|
description: string;
|
||||||
|
spcontext:WebPartContext;
|
||||||
|
}
|
|
@ -0,0 +1,134 @@
|
||||||
|
@import "~office-ui-fabric-react/dist/sass/References.scss";
|
||||||
|
|
||||||
|
.reactPnPjsTester {
|
||||||
|
.container {
|
||||||
|
// max-width: 800px;
|
||||||
|
margin: 0px auto;
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.jsonviewcont{
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
@include ms-Grid-row;
|
||||||
|
// @include ms-fontColor-white;
|
||||||
|
// background-color: $ms-color-themeDark;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
@include ms-Grid-col;
|
||||||
|
@include ms-lg12;
|
||||||
|
@include ms-xl12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col1 {
|
||||||
|
@include ms-Grid-col;
|
||||||
|
@include ms-sm2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col11 {
|
||||||
|
@include ms-Grid-col;
|
||||||
|
@include ms-sm10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
@include ms-font-xl;
|
||||||
|
@include ms-fontColor-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subTitle {
|
||||||
|
@include ms-font-l;
|
||||||
|
@include ms-fontColor-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
@include ms-font-m;
|
||||||
|
}
|
||||||
|
|
||||||
|
.methodSelector {
|
||||||
|
:global {
|
||||||
|
.ms-Dropdown {
|
||||||
|
&:focus {
|
||||||
|
color: $ms-color-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-Dropdown-title {
|
||||||
|
background-color: $ms-color-themePrimary;
|
||||||
|
color: $ms-color-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ms-Dropdown-caretDownWrapper i {
|
||||||
|
color: $ms-color-white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.collapse {
|
||||||
|
float: right;
|
||||||
|
margin-top: -20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeZone {
|
||||||
|
border: 1px solid;
|
||||||
|
border-color: $ms-color-neutralLight;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
// Our button
|
||||||
|
text-decoration: none;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 10px;
|
||||||
|
|
||||||
|
// Primary Button
|
||||||
|
min-width: 80px;
|
||||||
|
background-color: $ms-color-themePrimary;
|
||||||
|
border-color: $ms-color-themePrimary;
|
||||||
|
color: $ms-color-white;
|
||||||
|
|
||||||
|
// Basic Button
|
||||||
|
outline: transparent;
|
||||||
|
position: relative;
|
||||||
|
font-family: "Segoe UI WestEuropean", "Segoe UI", -apple-system,
|
||||||
|
BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
font-size: $ms-font-size-m;
|
||||||
|
font-weight: $ms-font-weight-regular;
|
||||||
|
border-width: 0;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 16px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-weight: $ms-font-weight-semibold;
|
||||||
|
font-size: $ms-font-size-m;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
margin: 0 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:global {
|
||||||
|
.pageContent_ecefc8ba {
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
.ms-Button-label {
|
||||||
|
width: 440px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,333 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import styles from "./ReactPnPjsTester.module.scss";
|
||||||
|
import { IReactPnPjsTesterProps } from "./IReactPnPjsTesterProps";
|
||||||
|
import { sp } from "@pnp/sp/presets/all";
|
||||||
|
import {
|
||||||
|
TextField,
|
||||||
|
Panel,
|
||||||
|
PanelType,
|
||||||
|
Checkbox,
|
||||||
|
Icon,
|
||||||
|
Dropdown,
|
||||||
|
TooltipHost,
|
||||||
|
DirectionalHint,
|
||||||
|
Toggle,
|
||||||
|
Stack,
|
||||||
|
} from "office-ui-fabric-react";
|
||||||
|
// import AceEditor from "react-ace";
|
||||||
|
import { DefaultButton, ActionButton, IconButton } from "office-ui-fabric-react/lib/Button";
|
||||||
|
// import "ace-builds/src-noconflict/mode-json";
|
||||||
|
// import "ace-builds/src-noconflict/theme-github";
|
||||||
|
import ReactJson from "react-json-view";
|
||||||
|
|
||||||
|
const samples:ISamples = require("./Samples.json");
|
||||||
|
|
||||||
|
export interface ISamples{
|
||||||
|
samples:any[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IReactPnPjsTesterState {
|
||||||
|
jsonResponse: any;
|
||||||
|
pnpCommand: any;
|
||||||
|
displayDataTypes: boolean;
|
||||||
|
displayObjectSize: boolean;
|
||||||
|
enableClipboard: boolean;
|
||||||
|
openPanel: boolean;
|
||||||
|
isError: boolean;
|
||||||
|
errorMessage: any;
|
||||||
|
siteUrl: string;
|
||||||
|
isUpdate: boolean;
|
||||||
|
showAddUpdateInformation: boolean;
|
||||||
|
defaultCollapsed: boolean;
|
||||||
|
requestType: string;
|
||||||
|
isOtherSite: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
var spObj = null;
|
||||||
|
|
||||||
|
export default class ReactPnPjsTester extends React.Component<
|
||||||
|
IReactPnPjsTesterProps,
|
||||||
|
IReactPnPjsTesterState
|
||||||
|
> {
|
||||||
|
private addCommand =
|
||||||
|
'sp.web.lists.getByTitle("CustomList").items.add({Title: "PnpJS Explorer"})';
|
||||||
|
private exampleJson = samples.samples;
|
||||||
|
|
||||||
|
// constructor to intialize state and pnp sp object.
|
||||||
|
constructor(props: IReactPnPjsTesterProps, state: IReactPnPjsTesterState) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
requestType: "GET",
|
||||||
|
jsonResponse: null,
|
||||||
|
pnpCommand: null,
|
||||||
|
displayDataTypes: false,
|
||||||
|
displayObjectSize: false,
|
||||||
|
enableClipboard: false,
|
||||||
|
openPanel: false,
|
||||||
|
isError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
siteUrl: "",
|
||||||
|
isUpdate: false,
|
||||||
|
showAddUpdateInformation: false,
|
||||||
|
defaultCollapsed: false,
|
||||||
|
isOtherSite: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private _reqBodyChanged = (val: string) => {
|
||||||
|
// this.setState({
|
||||||
|
// jsonResponse: val,
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): React.ReactElement<IReactPnPjsTesterProps> {
|
||||||
|
return (
|
||||||
|
<div className={styles.reactPnPjsTester}>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<div className={styles.row}>
|
||||||
|
<div className={styles.column}>
|
||||||
|
<TooltipHost
|
||||||
|
content="This webpart will allow SPFx developers to test PnPjs Sharepoint methods and it displays response in JSON viewer to identify properties/attributes returned by method"
|
||||||
|
id="tooltip"
|
||||||
|
directionalHint={DirectionalHint.rightCenter}
|
||||||
|
calloutProps={{ gapSpace: 0 }}
|
||||||
|
styles={{ root: { display: "inline-block" } }}
|
||||||
|
>
|
||||||
|
<h2 style={{ cursor: "pointer" }}>PnPjs Tester
|
||||||
|
<IconButton iconProps={{ iconName: 'InfoSolid' }} title="InfoSolid" ariaLabel="InfoSolid" />
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
</TooltipHost>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.row}>
|
||||||
|
<div className={styles.col1}>
|
||||||
|
<Dropdown
|
||||||
|
selectedKey={this.state.requestType}
|
||||||
|
onChanged={(val) => {
|
||||||
|
let isUpdate = val.key === "POST" ? true : false;
|
||||||
|
this.setState({ isUpdate: isUpdate, requestType: val.text });
|
||||||
|
}}
|
||||||
|
className={styles.methodSelector}
|
||||||
|
options={[
|
||||||
|
{ key: "GET", text: "GET" },
|
||||||
|
{ key: "POST", text: "POST" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.col11}>
|
||||||
|
<TextField
|
||||||
|
value={this.state.pnpCommand}
|
||||||
|
placeholder="Enter your query here e.g. sp.web.select('Title')"
|
||||||
|
onChange={(e) => this.setCommand(e.target)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.row}>
|
||||||
|
<div className={styles.column}>
|
||||||
|
<Checkbox
|
||||||
|
label="Use for other Site collection or Subsite"
|
||||||
|
onChange={(event, checked) => {
|
||||||
|
this.setState({ isOtherSite: checked });
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={styles.column}
|
||||||
|
style={{
|
||||||
|
display: this.state.isOtherSite ? "block" : "none",
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
placeholder="Enter site collection or subsite url"
|
||||||
|
value={this.state.siteUrl}
|
||||||
|
onChange={(e) => this.setSiteUrl(e.target)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.row}>
|
||||||
|
<div className={styles.column}>
|
||||||
|
<Panel
|
||||||
|
isLightDismiss
|
||||||
|
isOpen={this.state.openPanel}
|
||||||
|
headerText="Samples"
|
||||||
|
closeButtonAriaLabel="Close"
|
||||||
|
type={PanelType.custom}
|
||||||
|
customWidth={"600px"}
|
||||||
|
>
|
||||||
|
<p>{this.getPanelCommands()}</p>
|
||||||
|
</Panel>
|
||||||
|
|
||||||
|
<DefaultButton
|
||||||
|
onClick={() => this.executeCommand()}
|
||||||
|
className={styles.button}
|
||||||
|
>
|
||||||
|
<Icon className={styles.icon} iconName="LightningBolt" /> Run
|
||||||
|
query
|
||||||
|
</DefaultButton>
|
||||||
|
<DefaultButton
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({ openPanel: true });
|
||||||
|
}}
|
||||||
|
className={styles.button}
|
||||||
|
>
|
||||||
|
<Icon className={styles.icon} iconName="ReadingMode"></Icon>
|
||||||
|
Samples
|
||||||
|
</DefaultButton>
|
||||||
|
<DefaultButton
|
||||||
|
onClick={() => {
|
||||||
|
window.open("https://pnp.github.io/pnpjs/sp/", "__blank");
|
||||||
|
}}
|
||||||
|
className={styles.button}
|
||||||
|
>
|
||||||
|
<Icon className={styles.icon} iconName="Info"></Icon>About PnPjs
|
||||||
|
</DefaultButton>
|
||||||
|
{this.state.jsonResponse && (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{/* <Checkbox
|
||||||
|
label="Wrap code"
|
||||||
|
className={styles.collapse}
|
||||||
|
onChange={() => this.onCollapseAll()}
|
||||||
|
checked={this.state.defaultCollapsed}
|
||||||
|
|
||||||
|
/> */}
|
||||||
|
<br></br>
|
||||||
|
{this.state.jsonResponse &&
|
||||||
|
<React.Fragment>
|
||||||
|
<Stack horizontal tokens={{ childrenGap: 25 }}>
|
||||||
|
<Toggle checked={this.state.displayDataTypes} label="Show Data Types" inlineLabel onChange={() => { this.setState({ displayDataTypes: !this.state.displayDataTypes }); }} />
|
||||||
|
<Toggle checked={this.state.displayObjectSize} label="Show Count" inlineLabel onChange={() => { this.setState({ displayObjectSize: !this.state.displayObjectSize }); }} />
|
||||||
|
<Toggle checked={this.state.enableClipboard} label="Enable Clipboard" inlineLabel onChange={() => { this.setState({ enableClipboard: !this.state.enableClipboard }); }}/>
|
||||||
|
<Toggle checked={this.state.defaultCollapsed} label="Collapse All" inlineLabel onChange={()=>this.onCollapseAll()}/>
|
||||||
|
{/* <Checkbox className={styles.collapse} label="Collapse All" /> */}
|
||||||
|
</Stack>
|
||||||
|
<div className={styles.jsonviewcont}>
|
||||||
|
<ReactJson src={this.state.jsonResponse} collapsed={this.state.defaultCollapsed} displayDataTypes={this.state.displayDataTypes} displayObjectSize={this.state.displayObjectSize} enableClipboard={this.state.enableClipboard} />
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
{this.state.errorMessage &&
|
||||||
|
<div>{JSON.stringify(this.state.errorMessage)} </div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{/* <AceEditor
|
||||||
|
mode="json"
|
||||||
|
theme="github"
|
||||||
|
className={styles.codeZone}
|
||||||
|
value={JSON.stringify(this.state.jsonResponse, null, 2)}
|
||||||
|
onChange={this._reqBodyChanged}
|
||||||
|
highlightActiveLine={true}
|
||||||
|
editorProps={{ $blockScrolling: true }}
|
||||||
|
setOptions={{
|
||||||
|
wrap: this.state.defaultCollapsed,
|
||||||
|
showPrintMargin: false,
|
||||||
|
}}
|
||||||
|
height="500px"
|
||||||
|
width="100%"
|
||||||
|
/> */}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{this.state.errorMessage && (
|
||||||
|
<div>{JSON.stringify(this.state.errorMessage)} </div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onCollapseAll = () => {
|
||||||
|
this.setState({ defaultCollapsed: !this.state.defaultCollapsed });
|
||||||
|
}
|
||||||
|
|
||||||
|
private setCommand = (element) => {
|
||||||
|
var val = (element as HTMLInputElement).value;
|
||||||
|
this.setState({ pnpCommand: val });
|
||||||
|
}
|
||||||
|
|
||||||
|
private setSiteUrl = (element) => {
|
||||||
|
var val = (element as HTMLInputElement).value;
|
||||||
|
this.setState({ siteUrl: val });
|
||||||
|
}
|
||||||
|
|
||||||
|
private setPnP = () => {
|
||||||
|
spObj = null;
|
||||||
|
if (this.state.siteUrl != "" && this.state.isOtherSite) {
|
||||||
|
sp.setup({
|
||||||
|
sp: {
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json;odata=minimalmetadata",
|
||||||
|
},
|
||||||
|
baseUrl: this.state.siteUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sp.setup({
|
||||||
|
spfxContext: this.props.spcontext
|
||||||
|
});
|
||||||
|
}
|
||||||
|
spObj = sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private executeCommand() {
|
||||||
|
this.setPnP();
|
||||||
|
this.setState({ jsonResponse: null, errorMessage: null,openPanel:false });
|
||||||
|
var command = this.state.pnpCommand;
|
||||||
|
command = command.replace("sp", "spObj");
|
||||||
|
command = command.replace(/"/g, "'");
|
||||||
|
command = command.replace(".get()", "");
|
||||||
|
command = command.replace(";", "");
|
||||||
|
command = command.replace("()", "");
|
||||||
|
|
||||||
|
var evalString = "try{" + command;
|
||||||
|
|
||||||
|
if (!this.state.isUpdate) {
|
||||||
|
evalString += "()";
|
||||||
|
}
|
||||||
|
|
||||||
|
evalString +=
|
||||||
|
".then(\
|
||||||
|
(result) => {\
|
||||||
|
debugger;\
|
||||||
|
console.log(result);\
|
||||||
|
this.setState({jsonResponse:result});\
|
||||||
|
}\
|
||||||
|
)\
|
||||||
|
.catch(\
|
||||||
|
(error) => {\
|
||||||
|
debugger;\
|
||||||
|
console.log(error);\
|
||||||
|
this.setState({jsonResponse:{error:error.message}});\
|
||||||
|
}\
|
||||||
|
);\
|
||||||
|
}\
|
||||||
|
catch(e){\
|
||||||
|
alert(e);\
|
||||||
|
}";
|
||||||
|
eval(evalString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPanelCommands = () => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{this.exampleJson.map((item: any, index: number) => (
|
||||||
|
<div>
|
||||||
|
<ActionButton
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({ pnpCommand: item.command, openPanel: false });
|
||||||
|
}}
|
||||||
|
iconProps={{ iconName: "Copy" }}
|
||||||
|
title="Copy"
|
||||||
|
ariaLabel="Copy"
|
||||||
|
>
|
||||||
|
{item.command}
|
||||||
|
</ActionButton>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"samples": [
|
||||||
|
{
|
||||||
|
"command": "sp.web.select('Title')"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.currentUser.get()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').items.select('Title','Description').top(5).orderBy('Modified', true).get()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').items.getById(1).get()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('BigList').items.getAll()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('LookupList').items.getById(1).select('Title','Lookup/Title','Lookup/ID').expand('Lookup').get()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('Pages').items.select('Title','FileRef','FieldValuesAsText/MetaInfo').expand('FieldValuesAsText').get()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('CustomList').items.add({Title: 'PnpJS Explorer'})"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').items.getById(1).delete()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.associatedVisitorGroup()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').views()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('My List').views.getByTitle('All Items')()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.userCustomActions()"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sp.web.lists.getByTitle('Documents').rootFolder.folders()"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
define([], function() {
|
||||||
|
return {
|
||||||
|
"PropertyPaneDescription": "Description",
|
||||||
|
"BasicGroupName": "Group Name",
|
||||||
|
"DescriptionFieldLabel": "Description Field"
|
||||||
|
}
|
||||||
|
});
|
10
samples/react-pnpjsexplorer/src/webparts/reactPnPjsTester/loc/mystrings.d.ts
vendored
Normal file
10
samples/react-pnpjsexplorer/src/webparts/reactPnPjsTester/loc/mystrings.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
declare interface IReactPnPjsTesterWebPartStrings {
|
||||||
|
PropertyPaneDescription: string;
|
||||||
|
BasicGroupName: string;
|
||||||
|
DescriptionFieldLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'ReactPnPjsTesterWebPartStrings' {
|
||||||
|
const strings: IReactPnPjsTesterWebPartStrings;
|
||||||
|
export = strings;
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.3/includes/tsconfig-web.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"jsx": "react",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"outDir": "lib",
|
||||||
|
"inlineSources": false,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noUnusedLocals": false,
|
||||||
|
"typeRoots": [
|
||||||
|
"./node_modules/@types",
|
||||||
|
"./node_modules/@microsoft"
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
"es6-promise",
|
||||||
|
"webpack-env"
|
||||||
|
],
|
||||||
|
"lib": [
|
||||||
|
"es5",
|
||||||
|
"dom",
|
||||||
|
"es2015.collection"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"lib"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"class-name": false,
|
||||||
|
"export-name": false,
|
||||||
|
"forin": false,
|
||||||
|
"label-position": false,
|
||||||
|
"member-access": true,
|
||||||
|
"no-arg": false,
|
||||||
|
"no-console": false,
|
||||||
|
"no-construct": false,
|
||||||
|
"no-duplicate-variable": true,
|
||||||
|
"no-eval": false,
|
||||||
|
"no-function-expression": true,
|
||||||
|
"no-internal-module": true,
|
||||||
|
"no-shadowed-variable": true,
|
||||||
|
"no-switch-case-fall-through": true,
|
||||||
|
"no-unnecessary-semicolons": true,
|
||||||
|
"no-unused-expression": true,
|
||||||
|
"no-use-before-declare": true,
|
||||||
|
"no-with-statement": true,
|
||||||
|
"semicolon": true,
|
||||||
|
"trailing-comma": false,
|
||||||
|
"typedef": false,
|
||||||
|
"typedef-whitespace": false,
|
||||||
|
"use-named-parameter": true,
|
||||||
|
"variable-name": false,
|
||||||
|
"whitespace": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue